Bulk Import Test Cases into QTest Using the REST API
Learn how to post a JSON array to QTest’s bulk import endpoint, handle partial successes, and work around size and validation limits.
29 May 2026, 09:45 UTC

Problem: Onboarding a large test suite manually
When you need to move hundreds of test cases from a spreadsheet or legacy tool into QTest, creating them one‑by‑one through the UI is slow and error‑prone. The goal is to upload a batch of test cases in a single API call while still being able to see which items succeeded and which failed.
Thesis: QTest’s bulk import endpoint lets you send a JSON array of test case objects and receive a 207 Multi‑Status response that reports created IDs and per‑item validation errors.
How the bulk import works
The endpoint is POST https://.qtest.com/api/v3/projects//test-cases/bulk. It expects an array where each element matches the fields you would set when creating a test case individually – title, description, step actions, expected results, and any custom fields. Authentication is an OAuth 2.0 bearer token with the Test Case Create scope for the target project.
If the request is well‑formed, the server returns HTTP 207. The response body is a JSON array; each entry corresponds to the input item and contains either an id field (the newly created test case) or an errors array describing validation problems for that item. This lets you handle partial success without aborting the whole batch.
Worked example: importing two test cases
curl -X POST 'https://acme.qtest.com/api/v3/projects/12345/test-cases/bulk' -H 'Authorization: Bearer YOUR_OAUTH_TOKEN' -H 'Content-Type: application/json' -d '[ { "title": "Login with valid credentials", "description": "Verify that a user can log in with correct username and password.", "steps": [{"action": "Enter username", "expected": "Username field accepts input"}], "customFields": { "Priority": "High" } }, { "title": "Login with invalid password", "description": "Verify that an error is shown when the password is wrong.", "steps": [{"action": "Enter wrong password", "expected": "Error message appears"}], "customFields": { "Priority": "Medium" } } ]'
Replace acme with your QTest domain, 12345 with your project ID, and YOUR_OAUTH_TOKEN with a valid bearer token. The command must be run from a machine that has network access to the QTest endpoint; no special privileges beyond the token are required.
Assuming both objects pass validation, you will see a response similar to:
[ {"id": 987654}, {"id": 987655} ]
If the second object omitted the required title field, the response would be:
[ {"id": 987654}, {"errors": [{"field": "title", "message": "may not be blank"}]} ]
Notice that the first test case was still created despite the error in the second item.
Trade‑offs and limitations
- Payload size: The API rejects requests larger than about 5 MB. For very large suites you must split the array into multiple chunks and send sequential requests.
- Rate limiting: Each user is limited to roughly 60 requests per minute. Bulk import counts as a single request, but if you need many chunks you can hit this limit; pause between batches or use a service account with a higher quota.
- Custom field validation: Values must match the predefined data type (picklist, text, number, etc.). A mismatch produces a 400 error for that specific item, which appears in the
errorsarray. - No automatic linking: The bulk import does not associate the new test cases with existing requirements, test runs, or defect tickets. Those relationships must be added later via separate API calls (e.g., POST to the test‑case‑requirements endpoint).
Verification steps
- After a successful bulk import, capture the IDs from the 207 response.
- For each ID, run a GET request:
GET https://.qtest.com/api/v3/test-cases/with the same bearer token. - Check that the returned JSON contains the fields you sent (title, description, steps, custom fields).
- To test error handling, deliberately omit a required field in one object and confirm the response includes an
errorsentry for that item while the other item still returns anid.
Actionable closing
Start small: build a JSON array of five test cases, run the curl command, and inspect the 207 response. Once you confirm the payload structure and error handling, scale up by chunking your full test suite into 5 MB blocks and respecting the 60‑request‑per‑minute limit. This approach cuts manual entry time dramatically while giving you granular visibility into any validation problems.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.