All APIs use Basic Authentication:
curl -u "USERNAME:ACCESS_KEY"
Base URL: https://test-management.browserstack.com/api/v2
The import sequence should be:
- Create Project
- Create Custom Fields
- Create Configurations
- Create Folder Hierarchy
- Create Test Cases
- Upload Test Case Attachments
- Create Test Plans
- Create Test Runs
- Push Test Results
- Upload Result Attachments
This order is important because:
- test cases require folder IDs
- test runs require test case IDs
- results require test run + test case IDs
- attachments require entity IDs
Supported system values:
- Low
- Medium
- High
- Critical
Supported values:
- Active
- Draft
- In Review
- Rejected
- Outdated
Supported values:
- Acceptance
- Accessibility
- Compatibility
- Destructive
- Functional
- Other
- Performance
- Regression
- Security
- Smoke & Sanity
- Usability
Important: Custom enum values are also supported for some fields.
POST /api/v2/projects
Payload:
{ "project": { "name": "Project Name", "description": "Project Description" } }
Returns:
- project identifier (PR-xxx)
Store mapping:
{ "testlink_project_id": 10, "browserstack_project_id": "PR-123" }
Folders organize test cases.
POST /api/v2/projects/{project-id}/folders
Payload:
{ "folder": { "name": "Login", "description": "Login test cases", "parent_id": 1200 } }
Important:
- parent_id = null creates root folder
- preserve hierarchy during migration
Store mapping:
{ "testlink_suite_id": 55, "browserstack_folder_id": 1310 }
POST /api/v2/projects/{project_id}/folders/{folder_id}/test-cases
Payload structure:
{ "test_case": { "name": "Verify Login", "description": "
HTML supported
", "owner": "user@email.com", "preconditions": "Preconditions
", "test_case_steps": [ { "step": "Open app", "result": "App launches" } ], "issues": ["TM-123"], "tags": ["Regression"], "case_type": "Functional", "priority": "Medium", "custom_fields": { "estimate": "10" } } }Important mappings:
TestLink → BrowserStack
- tc name → name
- summary → description
- preconditions → preconditions
- steps → test_case_steps
- expected results → result
- importance → priority
- keywords → tags
- custom fields → custom_fields
Returns:
- test case identifier (TC-xxxx)
Store mapping:
{ "testlink_tcversion_id": 456, "browserstack_testcase_id": "TC-6655" }
BrowserStack supports:
- test_case_steps
- test_case_text
- test_case_bdd
BDD requires:
- feature
- scenario
and must NOT contain steps.
POST /api/v2/projects/{project_id}/test-cases/{test_case_id}/attachments
Multipart upload:
-F "file=@path/to/file"
Optional: inline=true
Limits:
- max file size = 50 MB
Important:
- BrowserStack stores attachments in S3-style URLs
- preserve attachment metadata separately
Migration strategy:
- upload files AFTER testcase creation
- upload sequentially or controlled concurrency
POST /api/v2/custom-fields
Supported field types:
- string
- dropdown
- text
- user
- boolean
- url
- date
- int
Important: Create custom fields BEFORE importing test cases.
Store mapping:
{ "testlink_custom_field": "estimate", "browserstack_custom_field": "CF-1234" }
Configurations represent:
- OS
- Browser
- Device combinations
POST /api/v2/configurations
Payload:
{ "name": "iPhone 13 Safari" }
Returns:
- configuration ID
Used later in:
- test runs
- test results
POST /api/v2/projects/{project_id}/test-plans
Payload:
{ "test_plan": { "name": "Regression Cycle", "plan_status": "completed", "description": "Regression Plan" } }
Returns:
- TP-xxx
POST /api/v2/projects/{project_id}/test-runs
Payload supports:
- linked test cases
- linked folders
- linked configurations
- linked test plan
- tags
- assignees
Important:
- include_all=true imports entire project
- test_plan_id and sub_test_plan_id are mutually exclusive
Store mapping:
{ "testlink_testplan_id": 123, "browserstack_testrun_id": "TR-321" }
POST /api/v2/projects/{project_id}/test-runs/{test_run_id}/results
Important constraints:
- testcase MUST already exist in test run
- max 300 testcase IDs per request
Result contains:
- status
- issues
- configuration_id
- step results
- custom fields
Recommended migration:
- batch results in chunks
- validate testcase mappings first
Most list APIs are paginated.
Response contains:
{ "info": { "page": 1, "page_size": 30, "count": 100, "next": ... } }
Migration importer should:
- support pagination
- support retries
- checkpoint progress
migration_bundle/ ├── manifest.json ├── projects.ndjson.gz ├── folders.ndjson.gz ├── testcases.ndjson.gz ├── testplans.ndjson.gz ├── testruns.ndjson.gz ├── results.ndjson.gz ├── configurations.ndjson.gz ├── custom_fields.ndjson.gz ├── mappings/ └── attachments/
- Never call BrowserStack APIs during DB extraction
- Use snapshot-based migration
- Use streaming NDJSON exports
- Batch API imports
- Maintain ID mapping tables
- Handle retries/checkpoints
- Separate extraction from import
- Upload attachments after entities exist
- Preserve folder hierarchy order
- Create custom fields before test cases
Safe parallelism:
- Projects: sequential
- Folders: low concurrency
- Test cases: medium concurrency
- Attachments: low concurrency
- Results: batched concurrency
Avoid aggressive parallel uploads because:
- rate limits
- attachment overhead
- dependency ordering
-
Attachment limit: 50 MB
-
Results request max: 300 testcase IDs
-
IDs are string-based:
- PR-xxx
- TC-xxx
- TR-xxx
- TP-xxx
-
APIs are RBAC protected
-
Pagination enabled almost everywhere
Phase 1: TestLink DB → Canonical Export Bundle
Phase 2: Bundle → BrowserStack APIs
Do NOT: TestLink DB → BrowserStack directly
The snapshot approach gives:
- retries
- resumability
- offline debugging
- deterministic imports
- reduced DB load