Core concepts
Errors and rate limits
Response envelopes, error codes, and the usage headers that ride on every call.
Response envelopes
Products share a small set of shapes. Read the envelope before the payload.
- TrackingMCP and the SchedulesMCP public surface wrap success in
{ "ok": true, "data": ... }. - AirCargoMCP and FreightRatesMCP return the payload under
{ "data": ... }. - LoadingMCP returns
{ "ok": true, "plan": { ... } }. - The TrackingMCP DCSA feed at
/v2/eventsis the one exception. It follows the standard rather than our envelope, so it answers a bare JSON array and puts pagination in the response headers.
The keyed TrackingMCP surface returns a coded error object, so you can branch on the code and show the message:
{
"ok": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "identifier_type is required",
"severity": "warning"
}
}
The open TrackingMCP endpoints answer a plain message instead, and they are explicit rather than silent:
{
"ok": false,
"message": "That number fails the ISO check digit, which almost always means one digit is off. Did you mean MEDU1234562?"
}
Codes you will meet on TrackingMCP
| Code | Status | What it means |
|---|---|---|
VALIDATION_ERROR | 400 | A required field is missing or out of range. Posting the wrong field names lands here. |
UNAUTHORIZED | 401 | The key is missing, malformed or revoked. |
UNIQUE_QUOTA_EXCEEDED | 402 | The add would pass the shipment quota on your plan. |
CONTAINER_QUOTA_EXCEEDED | 402 | No container slot is free on your plan. |
PAYG_SPEND_CAP_REACHED | 402 | Pay-as-you-go only: the add would cross the spend cap you set. |
NOT_FOUND | 404 | No record with that UUID on your account. |
REFERENCE_NOT_RESOLVABLE | 404 | No line recognises the reference. |
ALREADY_TRACKED | 409 | You are already tracking that identifier. |
CONTAINER_ADD_IN_PROGRESS | 409 | The same identifier is mid-add on another request. |
RATE_LIMITED | 429 | Too soon after the last recheck of that box. |
DB_ERROR, INTERNAL_ERROR | 500 | Our side. Retry. |
The one that is not a failure
TRACKING_IN_PROGRESS arrives on a 202 from GET /v1/containers/lookup/{identifier}. The reference is registered and the carrier has not answered yet, so it is neither a success nor a not-found. It carries retry_after_seconds. Poll again on that delay rather than adding the box a second time.
Note that ok is false on that 202. Branch on the status code, not on ok alone, or a healthy in-progress lookup will read as an error.
FreightRatesMCP uses a structured error object:
{ "error": { "code": "not_found", "message": "No rate for that lane yet." } }
Status codes
| Code | Meaning |
|---|---|
200 | Success. |
201 | Created. A TrackingMCP add answers this. |
202 | Accepted and still resolving. See the note above. |
400 | The request is malformed, or a required parameter is missing. |
401 | The key is missing or not recognised. |
402 | A quota or spend cap stands in the way. |
404 | The identifier resolved to nothing, or the lane has no data yet. |
405 | Wrong method. FreightRatesMCP is GET only. |
409 | The same record is already tracked, or an identical request is in flight. |
429 | You are over the rate limit. Back off and retry. |
Error codes you will see in the FreightRatesMCP envelope include missing_key, invalid_request, not_found, method_not_allowed and server_error.
Rate limits and usage
Responses carry usage headers so you can watch your budget without a second call. Read them, and when you see 429, back off with a short exponential delay before retrying. Public endpoints are limited per IP; keyed endpoints are limited per account and plan.
Handling it well
- Treat any non-
2xxas a typed outcome, not a crash. Branch on the code. - Log the
message. It is written to be read by a human on your side. - Do not hammer a
404. An identifier that fails the check digit will keep failing until it is corrected. - Do not retry a
409 ALREADY_TRACKEDas if it were an error. Read the record you already hold.