Test Case Import API
The import endpoints stage an export file and then commit it directly into a project — there is no preview or dry-run step. A successful commit creates (or replaces) test cases and suites in one request; any row that could not be imported is reported back individually, and the rest of the file still imports.
Probara is the default re-import platform. Re-importing a file this API previously exported (see the export API) is the zero-configuration path: every format Probara can export — JSON, XML, CSV, and XLSX — can be re-imported, and the import preserves full fidelity. Qase and TestRail exports are also accepted, with a narrower field-mapping surface (see below).
All requests require an authenticated request (Bearer API token or session cookie) with at least member role in the project’s organization. Viewers receive 403 forbidden.
Stage the file
Section titled “Stage the file”/api/v1/projects/{projectId}/imports:stage{projectId} is the project code (for example ACME). The request body is multipart/form-data with a single file part carrying the export file.
Response
Section titled “Response”200 with:
{ "uploadUlid": "01J...", "byteSize": 4821, "filename": "acme-export.json" }uploadUlid identifies the staged upload for the commit call below. Staged uploads are not retained indefinitely — commit soon after staging.
Errors
Section titled “Errors”| Status | Code | Condition |
|---|---|---|
403 | forbidden | The caller’s role is viewer |
413 | file_too_large | The uploaded file exceeds IMPORT_MAX_FILE_BYTES (10 MB) |
422 | validation_failed | The request carries no file part |
429 | too_many_requests | The organization’s stage rate limit was exceeded |
Commit the import
Section titled “Commit the import”/api/v1/projects/{projectId}/imports/commit{ "uploadUlid": "01J...", "sourceFormat": "probara_json", "targetSuiteUlid": null, "replaceMatching": false}| Field | Notes |
|---|---|
uploadUlid | The value returned by the stage call above. |
sourceFormat | One of probara_json, probara_xml, probara_csv, probara_xlsx, qase_xml, qase_json, qase_csv, qase_xlsx, testrail_xml, testrail_csv. The web wizard resolves this automatically from the uploaded file’s extension/content — an integrator calling the API directly must set it explicitly. |
targetSuiteUlid | null imports beneath the project root; otherwise the suite hierarchy in the file is recreated beneath the given suite. |
replaceMatching | When true, a source case whose title exactly matches an existing case in the target suite overwrites that case’s content instead of creating a duplicate. |
Response
Section titled “Response”200 with the commit report:
{ "counts": { "suitesCreated": 2, "casesCreated": 8, "casesReplaced": 1, "rowsFailed": 0 }, "created": [{ "caseUlid": "01J...", "displayId": "ACME-42", "title": "Login succeeds" }], "replaced": [], "failures": [], "warnings": []}failures lists rows that did not import (the rest of the file still committed); warnings lists rows that did import but with a non-fatal notice — see below.
Probara re-import: full fidelity
Section titled “Probara re-import: full fidelity”Re-importing a Probara export (any of the four formats) maps back every system classification field — priority, severity, status, type, layer, behavior, automation status, is-flaky, preconditions, and postconditions — plus every existing user-defined custom field value, matched automatically by name (title for JSON/XML, slugified column header for CSV/XLSX). Steps, tags, description, and suite path always round-trip regardless of source platform.
No field or option is ever created on import. Every match is resolved against the organization’s existing custom fields and existing option values at commit time — there is no field-mapping payload in the request, and no interactive binding step. This makes re-import safe to run repeatedly (for example, restoring a backup or migrating cases between projects) without polluting the project’s schema.
Qase and TestRail exports map a narrower set — priority, type, and status only. User-defined custom fields are not mapped for those two platforms.
Unknown-field and unknown-option behavior
Section titled “Unknown-field and unknown-option behavior”An import never fails a row just because one field’s value could not be mapped — instead it commits the case and records a warning:
| Warning code | Meaning |
|---|---|
unmapped_value | A system or user-defined option value did not match any existing option, and the field has no configured default — the field is left unset. |
defaulted_value | Same as above, but the field has a configured default option — the field falls back to that default. |
unmapped_field | A user-defined field title (or CSV/XLSX column slug) did not match any field that exists on the project — the value is skipped, nothing is created. |
Every row failure and warning names the affected sourceRow and case title, so a partially-successful import is fully diagnosable from the response alone.
Row failures
Section titled “Row failures”A row fails (and its case is not imported) only for these reasons — every other value mismatch is the warning family above, never a failure:
| Code | Condition |
|---|---|
missing_title | The row has no title. |
ambiguous_match | replaceMatching is set and the title matches more than one existing case in the target suite. |
Size ceilings
Section titled “Size ceilings”An import is bounded to IMPORT_MAX_CASES (5000) parsed cases and IMPORT_MAX_FILE_BYTES (10 MB) staged bytes. A file exceeding either ceiling is rejected before any suite or case is written.
Rate limit
Section titled “Rate limit”Both stage and commit are rate-limited per organization (10 requests/hour each). Exceeding the limit returns 429 with { "error": { "code": "too_many_requests", ... } }.
Markdown is not a supported import format
Section titled “Markdown is not a supported import format”Markdown is not, and has never been, an importable source format. A .md upload is rejected client-side by the wizard with a translated inline error; an API caller that stages a .md file and attempts to commit it with any sourceFormat receives 422 parse_failed — the file will not parse as the declared format.
Errors
Section titled “Errors”| Status | Code | Condition |
|---|---|---|
403 | forbidden | The caller’s role is viewer |
404 | not_found | projectId, targetSuiteUlid, or the staged uploadUlid does not resolve in the active organization |
413 | file_too_large | The staged bytes exceed IMPORT_MAX_FILE_BYTES (defense-in-depth re-check at commit time) |
422 | parse_failed | The staged bytes did not parse as the declared sourceFormat, or the suite hierarchy nests too deeply |
422 | empty_import | The file parsed to zero cases |
422 | too_many_cases | The parsed case count exceeds IMPORT_MAX_CASES |
429 | too_many_requests | The organization’s import rate limit was exceeded |
Example
Section titled “Example”Stage a file, then commit it as a Probara JSON re-import:
curl -sS \ -H "Authorization: Bearer $PROBARA_API_TOKEN" \ -F "file=@acme-export.json" \ "https://probara.net/api/v1/projects/ACME/imports:stage"curl -sS \ -H "Authorization: Bearer $PROBARA_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{"uploadUlid":"01J...","sourceFormat":"probara_json","targetSuiteUlid":null,"replaceMatching":false}' \ "https://probara.net/api/v1/projects/ACME/imports/commit"Related pages
Section titled “Related pages”- Test case export API — produces the files this endpoint re-imports.