API conventions
Rules that hold across every endpoint, so you don't have to check them per resource.
Read, change, write back
The body a GET returns is accepted by the matching POST or PUT. Fetch a record, change one
field, send the whole thing back:
curl -s $API/api/mobile-tests/243 -H "Authorization: Bearer $TOKEN" > test.json
# edit test.json
curl -X PUT $API/api/mobile-tests/243 -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" --data @test.json
Fields that only make sense on the way out — id, createdAt, projectName — are ignored on the
way in. You don't have to strip them, and sending them is not an error. The id comes from the URL.
This matters more than it sounds: without it, the only way to change a record is to delete it and create a new one, which loses its id, its run history, and its place in any suite.
Lists can be arrays or comma-strings
Fields that hold several values — tags is the common one — accept either:
{"tags": "smoke,regression"}
{"tags": ["smoke", "regression"]}
They read back as the comma form. Blank entries are dropped and surrounding spaces trimmed.
Errors say what to fix
| Status | Means |
|---|---|
400 | The request is wrong. The message names the field and what was expected. |
401 / 403 | Not signed in, or signed in without the role this needs. |
404 | No such record — or no such path. |
405 | The path exists but not with that method. The Allow header lists the ones that work. |
409 | The change conflicts with something already there. |
500 | Our fault. Worth retrying, and worth telling us about. |
A 500 means the server is broken. If you can trigger one from a client, that's a bug in the
platform, not in your request — please report it.
Creating something inside a project
Endpoints that create a project-scoped record take projectId in the body, so the record is linked
as it's created:
POST /api/environments
{"name": "staging", "projectId": 590}
Applications are the exception. An application is shared across projects rather than owned by one,
so it's linked separately with POST /api/projects/{id}/applications.
Running a test
A run is a thing you create, so you create it on the collection of runs:
POST /api/mobile-tests/{id}/executions -> 201, Location: the new run
GET /api/mobile-tests/{id}/executions -> the runs so far
201 comes back with a Location header pointing at the run you just started, and the jobId in
the body.
POST /api/mobile-tests/{id}/execute still works and is deprecated. It answers with a Deprecation
header and a Link naming its replacement, so a client finds out from a response rather than from
an outage.
UI tests and suites still dispatch on /run and will move to the same shape.
Paging
List endpoints take ?page=, ?size= and ?sort=, and answer with the run of results plus the
totals:
{"content": [...], "totalElements": 143, "totalPages": 8, "size": 20, "number": 0}
size defaults to 20 and caps at 200. Filters are ordinary query parameters — ?nameContains=,
?projectId=, ?includeInactive=.