Concepts
Errors
Errors come back as JSON with a status code that says what kind of problem it is. Every endpoint puts the reason in detail.
Error bodies#
Every endpoint puts the reason in detail: a sentence, or for a refused export request a list of problems with their place in the body.
{ "detail": "Data export not found." }{
"detail": [
{
"loc": ["body", "metrics", 2, "id"],
"msg": "Unknown metric id 'revenue'. GET /exports/metrics lists the valid ids.",
"type": "type_error.enum"
},
{
"loc": ["body", "time_granularity"],
"msg": "HOURLY is not available in exports: hourly performance is kept for the last few weeks and shown in the app. Use DAILY, WEEKLY or MONTHLY.",
"type": "value_error"
}
]
}POST /orders, POST /spend and POST /views also repeat the sentence in error, the field they used before detail, so older clients keep working. A body that is not valid adds issues: the first 50 problems, each with its path in the body and a message. Some answers add a field, such as order_ids on a 409 from POST /orders and retry on a 422.
{
"detail": "invalid input",
"error": "invalid input",
"issues": [
{ "path": "0.time_of_purchase", "message": "Invalid ISO datetime" }
]
}A download link answers its errors in plain text, such as This download link has expired. Fetch the export result again for a new one. A 500 from any other endpoint has a body too: {"detail": "Internal server error."}, with the same error on the endpoints that take data in.
Status codes#
| Status | Meaning | Returned by |
|---|---|---|
| 200 | Success. | Every GET, and POST /orders, /spend and /views. |
| 201 | The export was created. | POST /exports/data-export. |
| 400 | The body is not valid JSON, or not valid for the endpoint. issues says where. | POST /orders, /spend, /views. |
| 401 | No valid key for the Data-Client-ID brand: missing, unknown, revoked, or another brand's. | Every endpoint but downloads. |
| 403 | The key lacks the scope this endpoint needs. For a download: the link is not valid. | Every endpoint but GET /exports/account. |
| 404 | No such export for this brand, or no such file. | GET /exports/data-export/result/{id}, downloads. |
| 409 | A conflict with data MTA already gets elsewhere: an order id from the brand's Shopify store, or spend for a platform with a live connection. | POST /orders, POST /spend. |
| 410 | The download link has expired. | Downloads. |
| 413 | The body is over 20 MB. | POST /orders, POST /views. |
| 422 | For an export: a field is wrong (see below). For orders and spend: no exchange rate yet for a currency and date. | POST /exports/data-export, POST /orders, POST /spend. |
| 429 | Too many requests from this key. Wait Retry-After seconds. | The export endpoints. |
| 500 | Something failed on our side. | Any endpoint. |
The difference between 401 and 403 is explained on Authentication.
Export validation errors#
Each entry in a 422's detail has loc, the path to the field starting with "body"; msg, a sentence; and type:
| type | Meaning |
|---|---|
| value_error.missing | A required field is missing: msg is field required. |
| value_error.extra | A field the request does not take: msg is extra fields not permitted. |
| type_error.enum | A value outside the allowed list, such as an unknown model, metric or breakdown key. msg lists what is allowed or where to find it. |
| value_error.jsondecode | The body is not valid JSON. |
| value_error | A rule on the value, such as a period over two years or two metrics with the same header. msg says which. |
Other value_error.… types name the check that failed, such as a string that is too short. When the body's shape is wrong, only those problems are listed; the checks on values run once the shape is right.
When to retry#
| Answer | What to do |
|---|---|
| 429 | Wait the seconds in Retry-After, then send the same request. |
| 422 from orders or spend | MTA has asked for the missing exchange rate. Send the same request again later. |
| 500 | Send the same request again later. Orders, spend and views upsert, so a retry stores nothing twice. |
| 410 on a download | Fetch the export result again and use the fresh link. |
ERROR status on an export | Create the export again. |
| 400, 401, 403, 404, 409, 413, or 422 from an export | Retrying will not help. Fix the request, the key or the data first. |
Request ids#
When a request to POST /orders or POST /spend with a valid key fails, MTA keeps its status and error message for 30 days, and the brand's team can read them under Settings > Data Diagnostics. The error response carries that record's id in X-Request-Id. Quote it when you ask us about a failure.
Questions about the API: support@growthdept.ai.