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: the JSON, XML, CSV, and XLSX exports can each be re-imported, and the import preserves full fidelity. Qase and TestRail exports are also accepted, with a narrower field-mapping surface (see below). A Gherkin .feature file is accepted as gherkin_feature, one file per import (see Gherkin .feature files).
All requests require an authenticated request (Bearer API token or session cookie) carrying the import/export permission (held by owner/admin/member). 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, gherkin_feature. 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, "reviewRequestsCreated": 0 }, "created": [{ "caseUlid": "01J...", "displayId": "ACME-42", "title": "Login succeeds" }], "replaced": [], "reviewRequests": [], "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.
Projects that require review
Section titled “Projects that require review”When the project’s test case review is mandatory
(Pro or Enterprise plan), the commit writes no case. The suites are created; each case the import would create
becomes a create review request, and each case it would replace an update request, with the
caller as author and the project’s default reviewers. casesCreated and casesReplaced are 0,
reviewRequestsCreated counts the requests, and reviewRequests lists them:
{ "reviewRequests": [ { "reviewUlid": "01J...", "displayId": "RV-7", "kind": "update", "caseUlid": "01J...", "title": "Login succeeds" }, { "reviewUlid": "01J...", "displayId": "RV-8", "kind": "create", "caseUlid": null, "title": "Signup works" } ]}A case is written only when its request is merged, with the same validation as
POST .../test-cases (for example, required custom fields must have a value). Like the direct
import, the commit is not all-or-nothing: requests opened before a later failure stay open.
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, 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. So do a case’s step format and each Gherkin step’s keyword.
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.
The case’s automation key round-trips too. A replaced case keeps its current key when the file carries none, and an empty or whitespace-only key clears it. A key the import cannot apply — already held by another case of the project (archived included), repeated by an earlier row of the same file, or invalid — never fails the row: the case imports without it and the report carries an automation_key_skipped warning. Keys are checked against the project as it stood before the import, so a key the same file removes from one case cannot be given to another in that import.
The case’s parameters and excluded combinations round-trip too. CSV and XLSX carry them in two JSON columns, parameters and excluded_combinations, placed after the custom-field columns; JSON and XML carry them as parameters and excludedCombinations. The columns and keys appear only when a case has parameters or excluded combinations, so an export without them is unchanged. A shared parameter comes back as a local parameter with the values it held. The names parameters and excluded_combinations are reserved: a custom field with either title does not import its values. A Probara or .feature file that carries no parameters clears the parameters of a case it replaces, while a Qase or TestRail file, which carries none, keeps them.
Qase and TestRail exports map a narrower set — priority, type, and status only. User-defined custom fields are not mapped for those two platforms. A Gherkin .feature file maps no system or custom fields; its tags and suites are imported.
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. |
automation_key_skipped | The automation key is already used by another case of the project, repeated by an earlier row, or invalid — the case imports without it. |
shared_step_skipped | The case referenced a shared step whose text the file does not include — that reference is skipped and the case imports its other steps. |
step_format_folded | The case’s steps do not fit its stated format: a Gherkin step with no keyword or with an expected result, or a classic step with a keyword. The case imports as classic steps, each keyword kept at the start of its action. |
parameters_skipped | The file’s parameters break a parameter rule, such as a repeated name or row, or more than 100 values for a single parameter — the case imports without them. A replace keeps the case’s existing parameters, and a .feature file’s Examples are not kept. |
image_reference_dropped | A step, description or paragraph value names an image that is not stored in this organization, as in a file exported from another organization — that image is removed and the rest of the text is imported. |
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. |
review_already_open | Mandatory review only: the case the row would replace already has an open review request. |
review_proposal_invalid | Mandatory review only: the row’s content cannot be a review request (for example, a title over 400 characters or a step with no action). |
Gherkin .feature files
Section titled “Gherkin .feature files”Stage a .feature file as usual, then commit it with sourceFormat set to gherkin_feature. The file holds one Feature, written with English keywords. Each Scenario and each Scenario Outline becomes one Gherkin case under a suite named for the Feature, and a Rule adds a nested suite. The Background becomes the case’s preconditions. Tags become Probara tags, and the Feature’s and the Rule’s tags apply to every scenario under them. A Scenario Outline’s Examples become one parameter named Examples: the headers of its tables form the columns, in order of first appearance, and every row is kept, in order, with an empty cell where a table has no column. A table with a single column becomes a single parameter named after its header. Several Examples blocks merge into that one parameter, and their names and tags are not kept. When the Examples break a parameter rule, the case imports without them and the report carries a parameters_skipped warning. The .feature export writes a case’s parameters back as one Examples table, with a row for each combination the case runs. A Gherkin sync refuses such a scenario with 422, since a sync reports no warnings. A Feature or Rule description is not imported. A file the parser cannot read fails with 422 parse_failed, and its message names the line. The Gherkin test cases guide describes the same mapping for customers. A repository’s .feature files can instead be kept in sync with the Gherkin sync, so that their cases follow the files.
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; for gherkin_feature, the message names the line that failed |
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://app.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://app.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.