> For the complete documentation index, see [llms.txt](https://docs.bugbug.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.bugbug.io/public-api-reference/import-export.md).

# Import / Export

Importing and exporting YAML and ZIP files

## Export project as ZIP

> Exports the entire project including all tests, components, suites and profiles as a ZIP archive.

```json
{"openapi":"3.1.0","info":{"title":"BugBug.io Public API","version":"v2"},"tags":[{"name":"Import / Export","description":"Importing and exporting YAML and ZIP files"}],"security":[{"tokenAuth":[]},{"Bearer":[]}],"components":{"securitySchemes":{"tokenAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"Token-based authentication with required prefix \"Token\""}}},"paths":{"/api/v2/project/export/":{"get":{"operationId":"v2_project_export_retrieve","description":"Exports the entire project including all tests, components, suites and profiles as a ZIP archive.","summary":"Export project as ZIP","tags":["Import / Export"],"responses":{"200":{"description":"ZIP archive download. Content-Type is `application/zip`."},"401":{"description":"Authentication credentials were missing or invalid."}}}}}}
```

## Check whether a project ZIP is importable (stateless)

> \*\*Stateless, read-only\*\* check: confirms the ZIP is a well-formed project export (has \`project.yaml\`, no folder/slug collisions). No DB writes, no draft or upload artifact created unlike \`import/validate\` - safe to call repeatedly. Does not check against this organization's existing data, so a \`200\` here doesn't guarantee \`import/validate\` + \`import/run\` will succeed. Use for pre-flight checks, including by LLM/agent callers, before committing to \`import/validate\`.

```json
{"openapi":"3.1.0","info":{"title":"BugBug.io Public API","version":"v2"},"tags":[{"name":"Import / Export","description":"Importing and exporting YAML and ZIP files"}],"security":[{"tokenAuth":[]},{"Bearer":[]}],"components":{"securitySchemes":{"tokenAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"Token-based authentication with required prefix \"Token\""}},"schemas":{"ProjectImportCheckRequest":{"type":"object","properties":{"file":{"type":"string","format":"uri","description":"Project ZIP file to check."}},"required":["file"]},"ProjectImportCheckResult":{"type":"object","properties":{"valid":{"type":"boolean","description":"Always `true` when the response is 200."},"summary":{"$ref":"#/components/schemas/ProjectImportCheckSummary"}},"required":["summary","valid"]},"ProjectImportCheckSummary":{"type":"object","properties":{"tests":{"type":"integer"},"components":{"type":"integer"},"suites":{"type":"integer"},"profiles":{"type":"integer"}},"required":["components","profiles","suites","tests"]}}},"paths":{"/api/v2/project/import/check/":{"post":{"operationId":"v2_project_import_check_create","description":"**Stateless, read-only** check: confirms the ZIP is a well-formed project export (has `project.yaml`, no folder/slug collisions). No DB writes, no draft or upload artifact created unlike `import/validate` - safe to call repeatedly. Does not check against this organization's existing data, so a `200` here doesn't guarantee `import/validate` + `import/run` will succeed. Use for pre-flight checks, including by LLM/agent callers, before committing to `import/validate`.","summary":"Check whether a project ZIP is importable (stateless)","tags":["Import / Export"],"requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/ProjectImportCheckRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectImportCheckResult"}}},"description":""},"400":{"description":"File missing, too large, or structurally invalid ZIP. See `message` for the reason."},"401":{"description":"Authentication credentials were missing or invalid."}}}}}}
```

## Run project import from a previously validated upload

> Starts the async import process for a previously validated upload. Returns immediately — the import runs in the background. The upload slot expires 30 minutes after \`import/validate\` was called.

```json
{"openapi":"3.1.0","info":{"title":"BugBug.io Public API","version":"v2"},"tags":[{"name":"Import / Export","description":"Importing and exporting YAML and ZIP files"}],"security":[{"tokenAuth":[]},{"Bearer":[]}],"components":{"securitySchemes":{"tokenAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"Token-based authentication with required prefix \"Token\""}},"schemas":{"ProjectImportRunRequest":{"type":"object","properties":{"uploadId":{"type":"string","format":"uuid","description":"Upload ID returned by `import/validate`."}},"required":["uploadId"]},"ProjectImportRunResult":{"type":"object","properties":{"projectId":{"type":"string","format":"uuid"},"status":{"enum":["pending"],"type":"string","description":"* `pending` - pending"}},"required":["projectId","status"]}}},"paths":{"/api/v2/project/import/run/":{"post":{"operationId":"v2_project_import_run_create","description":"Starts the async import process for a previously validated upload. Returns immediately — the import runs in the background. The upload slot expires 30 minutes after `import/validate` was called.","summary":"Run project import from a previously validated upload","tags":["Import / Export"],"requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/ProjectImportRunRequest"}},"application/json":{"schema":{"$ref":"#/components/schemas/ProjectImportRunRequest"}}},"required":true},"responses":{"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectImportRunResult"}}},"description":""},"400":{"description":"Missing `uploadId`, upload not found, expired, or artifact missing."},"401":{"description":"Authentication credentials were missing or invalid."}}}}}}
```

## Validate project ZIP and prepare upload

> Validates a ZIP file and creates a temporary upload slot (valid for 30 minutes). Returns an \`uploadId\` to be passed to the \`import/run\` endpoint.

```json
{"openapi":"3.1.0","info":{"title":"BugBug.io Public API","version":"v2"},"tags":[{"name":"Import / Export","description":"Importing and exporting YAML and ZIP files"}],"security":[{"tokenAuth":[]},{"Bearer":[]}],"components":{"securitySchemes":{"tokenAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"Token-based authentication with required prefix \"Token\""}},"schemas":{"ProjectImportValidateRequest":{"type":"object","properties":{"file":{"type":"string","format":"uri","description":"Project ZIP file to import."}},"required":["file"]},"ProjectImportValidateResult":{"type":"object","properties":{"uploadId":{"type":"string","format":"uuid","description":"Pass this to `import/run` to start the import."},"summary":{"$ref":"#/components/schemas/ProjectImportSummary"}},"required":["summary","uploadId"]},"ProjectImportSummary":{"type":"object","properties":{"tests":{"type":"integer"},"components":{"type":"integer"},"suites":{"type":"integer"},"profiles":{"type":"integer"}},"required":["components","profiles","suites","tests"]}}},"paths":{"/api/v2/project/import/validate/":{"post":{"operationId":"v2_project_import_validate_create","description":"Validates a ZIP file and creates a temporary upload slot (valid for 30 minutes). Returns an `uploadId` to be passed to the `import/run` endpoint.","summary":"Validate project ZIP and prepare upload","tags":["Import / Export"],"requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/ProjectImportValidateRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectImportValidateResult"}}},"description":""},"400":{"description":"File missing, too large, or invalid ZIP."},"401":{"description":"Authentication credentials were missing or invalid."}}}}}}
```

## List project backups

> Returns the backup schedule and unexpired backup archives for the selected project.

```json
{"openapi":"3.1.0","info":{"title":"BugBug.io Public API","version":"v2"},"tags":[{"name":"Import / Export","description":"Importing and exporting YAML and ZIP files"}],"security":[{"tokenAuth":[]},{"Bearer":[]}],"components":{"securitySchemes":{"tokenAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"Token-based authentication with required prefix \"Token\""}},"schemas":{"ProjectBackupList":{"type":"object","properties":{"isActive":{"type":"boolean"},"frequencyDays":{"type":"integer"},"retentionDays":{"type":["integer","null"]},"nextBackupAt":{"type":["string","null"],"format":"date-time"},"backups":{"type":"array","items":{"$ref":"#/components/schemas/ProjectBackup"}}},"required":["backups","frequencyDays","isActive","nextBackupAt","retentionDays"]},"ProjectBackup":{"type":"object","properties":{"id":{"type":"string","format":"uuid","readOnly":true},"created":{"type":"string","format":"date-time","readOnly":true},"expiresAt":{"type":"string","format":"date-time"},"testsCount":{"type":"integer","readOnly":true},"suitesCount":{"type":"integer","readOnly":true},"retentionDays":{"type":"integer","readOnly":true},"triggeredBy":{"enum":["automatic"],"type":"string","description":"* `automatic` - Automatic","readOnly":true}},"required":["created","expiresAt","id","retentionDays","suitesCount","testsCount","triggeredBy"]}}},"paths":{"/api/v2/projects/{project_pk}/backups/":{"get":{"operationId":"v2_projects_backups_list","description":"Returns the backup schedule and unexpired backup archives for the selected project.","summary":"List project backups","parameters":[{"in":"path","name":"project_pk","schema":{"type":"string","format":"uuid"},"required":true}],"tags":["Import / Export"],"responses":{"200":{"content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProjectBackupList"}}}},"description":""},"401":{"description":"Authentication credentials were not provided."},"404":{"description":"Project not found."}}}}}}
```

## Download project backup

> Downloads an unexpired project backup as a ZIP archive.

```json
{"openapi":"3.1.0","info":{"title":"BugBug.io Public API","version":"v2"},"tags":[{"name":"Import / Export","description":"Importing and exporting YAML and ZIP files"}],"security":[{"tokenAuth":[]},{"Bearer":[]}],"components":{"securitySchemes":{"tokenAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"Token-based authentication with required prefix \"Token\""}}},"paths":{"/api/v2/projects/{project_pk}/backups/{id}/download/":{"get":{"operationId":"v2_projects_backups_download_retrieve","description":"Downloads an unexpired project backup as a ZIP archive.","summary":"Download project backup","parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid"},"description":"A UUID string identifying this project backup.","required":true},{"in":"path","name":"project_pk","schema":{"type":"string","format":"uuid"},"required":true}],"tags":["Import / Export"],"responses":{"200":{"content":{"application/json":{"schema":{"type":"string","format":"binary"}}},"description":"ZIP archive download. Content-Type is `application/zip`."},"401":{"description":"Authentication credentials were not provided."},"404":{"description":"Project or backup not found."}}}}}}
```

## Get YAML JSON Schema

> Returns the JSON Schema for YAML import and export files.

```json
{"openapi":"3.1.0","info":{"title":"BugBug.io Public API","version":"v2"},"tags":[{"name":"Import / Export","description":"Importing and exporting YAML and ZIP files"}],"security":[{"Bearer":[]},{}],"components":{"securitySchemes":{}},"paths":{"/api/v2/schema/yaml/v1/":{"get":{"operationId":"v2_schema_yaml_v1_retrieve","description":"Returns the JSON Schema for YAML import and export files.","summary":"Get YAML JSON Schema","tags":["Import / Export"],"responses":{"200":{"description":"JSON Schema document for YAML import/export files."},"401":{"description":"Authentication credentials were missing or invalid."}}}}}}
```

## Export test as YAML or ZIP

> Exports a single test. \`yaml\` returns a standalone YAML file. \`zip\` returns a ZIP archive that includes the test and all reusable components it depends on.

```json
{"openapi":"3.1.0","info":{"title":"BugBug.io Public API","version":"v2"},"tags":[{"name":"Import / Export","description":"Importing and exporting YAML and ZIP files"}],"security":[{"tokenAuth":[]},{"Bearer":[]}],"components":{"securitySchemes":{"tokenAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"Token-based authentication with required prefix \"Token\""}}},"paths":{"/api/v2/tests/{id}/export/{fmt}/":{"get":{"operationId":"v2_tests_export_retrieve","description":"Exports a single test. `yaml` returns a standalone YAML file. `zip` returns a ZIP archive that includes the test and all reusable components it depends on.","summary":"Export test as YAML or ZIP","parameters":[{"in":"path","name":"fmt","schema":{"type":"string","enum":["yaml","zip"]},"description":"Export format.","required":true},{"in":"path","name":"id","schema":{"type":"string","format":"uuid"},"description":"A UUID string identifying this test.","required":true}],"tags":["Import / Export"],"responses":{"200":{"description":"File download. Content-Type is `text/yaml` for yaml, `application/zip` for zip."},"401":{"description":"Authentication credentials were missing or invalid."},"404":{"description":"Resource not found."}}}}}}
```

## Import test from YAML or ZIP

> Imports a test from a YAML or ZIP file. When a test with the same slug already exists, the behaviour depends on \`conflictMode\`. If \`conflictMode\` is omitted, conflicts are returned in the response body for manual resolution.

```json
{"openapi":"3.1.0","info":{"title":"BugBug.io Public API","version":"v2"},"tags":[{"name":"Import / Export","description":"Importing and exporting YAML and ZIP files"}],"security":[{"tokenAuth":[]},{"Bearer":[]}],"components":{"securitySchemes":{"tokenAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"Token-based authentication with required prefix \"Token\""}},"schemas":{"TestImportRequest":{"type":"object","properties":{"file":{"type":"string","format":"uri","description":"YAML or ZIP file to import."}},"required":["file"]},"TestImportConflict":{"type":"object","properties":{"status":{"enum":["conflict"],"type":"string","description":"* `conflict` - conflict"},"entityIds":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string","format":"uuid"}}},"conflicts":{"type":"array","items":{"$ref":"#/components/schemas/TestImportConflictItem"}}},"required":["conflicts","entityIds","status"]},"TestImportConflictItem":{"type":"object","properties":{"entityType":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"existingId":{"type":"string","format":"uuid"},"yamlDiff":{"oneOf":[{"$ref":"#/components/schemas/TestImportYamlDiff"},{"type":"null"}]}},"required":["entityType","existingId","name","slug","yamlDiff"]},"TestImportYamlDiff":{"type":"object","properties":{"currentYaml":{"type":"string"},"incomingYaml":{"type":"string"}},"required":["currentYaml","incomingYaml"]},"TestImportCreated":{"type":"object","properties":{"status":{"enum":["created","updated","skipped","conflict"],"type":"string","description":"* `created` - created\n* `updated` - updated\n* `skipped` - skipped\n* `conflict` - conflict"},"entityIds":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string","format":"uuid"}},"description":"Map of entity type to list of created/updated IDs."}},"required":["entityIds","status"]}}},"paths":{"/api/v2/tests/import/":{"post":{"operationId":"v2_tests_import_create","description":"Imports a test from a YAML or ZIP file. When a test with the same slug already exists, the behaviour depends on `conflictMode`. If `conflictMode` is omitted, conflicts are returned in the response body for manual resolution.","summary":"Import test from YAML or ZIP","parameters":[{"in":"query","name":"conflictMode","schema":{"type":"string","enum":["overwrite","skip"]},"description":"How to handle a slug conflict with an existing test. `overwrite` replaces the existing test. `skip` leaves the existing test unchanged. Omit to receive conflict details in the response and resolve manually."},{"in":"query","name":"onMissingComponent","schema":{"type":"string","enum":["error","skip"],"default":"error"},"description":"How to handle component references that are missing in the project. `error` (default) aborts the import. `skip` imports the test without the missing component steps."}],"tags":["Import / Export"],"requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/TestImportRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestImportConflict"}}},"description":""},"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestImportCreated"}}},"description":""},"400":{"description":"Validation error or missing component."},"401":{"description":"Authentication credentials were missing or invalid."}}}}}}
```

## Check whether a test YAML or ZIP is importable (stateless)

> \*\*Stateless, read-only\*\* check: confirms the YAML/ZIP is a well-formed test export (right schema, no folder/slug collisions). No DB writes, unlike \`import\` which writes immediately whenever there's no slug conflict - safe to call repeatedly. Does not check against this project's existing tests/components, so a \`200\` here doesn't guarantee \`import\` will succeed. Use for pre-flight checks, including by LLM/agent callers, before committing to \`import\`.

```json
{"openapi":"3.1.0","info":{"title":"BugBug.io Public API","version":"v2"},"tags":[{"name":"Import / Export","description":"Importing and exporting YAML and ZIP files"}],"security":[{"tokenAuth":[]},{"Bearer":[]}],"components":{"securitySchemes":{"tokenAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"Token-based authentication with required prefix \"Token\""}},"schemas":{"TestImportCheckRequest":{"type":"object","properties":{"file":{"type":"string","format":"uri","description":"YAML or ZIP file to check."}},"required":["file"]},"TestImportCheckResult":{"type":"object","properties":{"valid":{"type":"boolean","description":"Always `true` when the response is 200."},"summary":{"$ref":"#/components/schemas/TestImportCheckSummary"}},"required":["summary","valid"]},"TestImportCheckSummary":{"type":"object","properties":{"tests":{"type":"integer"},"components":{"type":"integer"}},"required":["components","tests"]}}},"paths":{"/api/v2/tests/import/check/":{"post":{"operationId":"v2_tests_import_check_create","description":"**Stateless, read-only** check: confirms the YAML/ZIP is a well-formed test export (right schema, no folder/slug collisions). No DB writes, unlike `import` which writes immediately whenever there's no slug conflict - safe to call repeatedly. Does not check against this project's existing tests/components, so a `200` here doesn't guarantee `import` will succeed. Use for pre-flight checks, including by LLM/agent callers, before committing to `import`.","summary":"Check whether a test YAML or ZIP is importable (stateless)","tags":["Import / Export"],"requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/TestImportCheckRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestImportCheckResult"}}},"description":""},"400":{"description":"File missing, too large, or structurally invalid. See `message` for the reason."},"401":{"description":"Authentication credentials were missing or invalid."}}}}}}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.bugbug.io/public-api-reference/import-export.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
