Skip to main content
Exact field names, parameters, and versioning schemes vary by product, so check each API’s reference docs.

Success and error responses

  • Success responses describe the resource; error responses describe what went wrong. Tell them apart by the HTTP status code, not by whether a particular field is present in the body.
  • Use the machine-readable error code in your logic, not the message text.
  • The error message is written for people reading logs; its wording can change, so don’t depend on it in code.
  • Some APIs add sub-issues for multi-field validation errors. Treat them as optional.
  • Keep pagination metadata separate from the resource it wraps.

Additive changes

New error codes, optional fields, and endpoint versions get added over time. Existing ones never change or disappear.
  • Give enum and error-code switches a default branch. A new value is expected, not an error.
  • Ignore unknown JSON fields instead of rejecting the payload.
  • Treat enums as open-ended sets, not closed ones.
Reject unknown fields, or switch on enums without a default branch. A later additive change can then break your integration, even though nothing you use changed.

Versioning

A new version in the path (e.g. ../v3/…) typically signals a breaking change.
  • Don’t assume a newer version is a superset or drop-in replacement. Check the version-specific docs.
  • Pin your client to one version per resource, rather than writing code that handles whichever version the API returns.
  • Older versions usually stay available, so you can migrate on your own schedule. Check deprecation notices before assuming indefinite support.

Pagination

Pagination fetches a large collection one slice at a time. The mechanism varies by API (page/size, offset/limit, or headers), so check its docs.
  • The item list holds only the requested page, not the full collection.
  • Don’t hardcode how a “total pages” field is computed; it derives from item count and page size.
  • Sort and filter metadata matters only if the endpoint documents it as supported.

Documented contract

Depend on documented status codes, error codes, and field names, not on details that only happen to be true today. That includes exact error text, field order, undocumented fields, and timing.
  • Don’t assume a status code by convention. A “created” status is returned only where documented; many POSTs return a generic “success” instead.
  • Undocumented fields may appear for forward compatibility; depend only on documented ones.
  • For the full current list of resources, parameters, and schemas, use the published OpenAPI/Swagger docs. That’s the contract to code against.

Error categories

Expect these categories, with API-specific codes: These are the usual codes. A specific endpoint may use a different one, so check its reference docs.

Retry safety

Whether a retry is safe depends on the HTTP method and whether the request actually reached the server.
Blindly retrying a resource-creating POST after a timeout can create duplicates, and treating an append-style PATCH as idempotent double-applies the change.

Rate limiting

A 429 means the request was rejected for rate limiting, whether at the load balancer or the API. Wait before retrying, whatever the method.
  • Bare 429s (load-balancer rejections) carry no further detail.
  • Retry with exponential backoff and jitter. On a 429, some Phrase APIs return rate-limit headers (naming varies) so you can see how close you are to the limit.
For a full worked example (bulkheads, jittered backoff, global vs. concurrent 429s), see the TMS API’s rate limit and concurrent limit guides.