Conventions
Ids, timestamps, error shape, versioning and retries.
| Convention | Rule |
|---|---|
| Ids | UUIDs, opaque. Store them whole; never parse or shorten one |
| Timestamps | RFC 3339 in UTC, e.g. 2026-09-22T04:10:00Z |
| Unknown fields | ignore them. New response fields and new status values can arrive without a version bump |
| Versioning | the prefix carries the major version. A breaking change gets a new prefix and advance notice |
| Errors | {"description": "…", "error": {"error_code": "…", "error_attributes": {…}}} — branch on error.error_code, log description, never match on its text. See Errors & limits |
| Retries | honour Retry-After on 429. On 5xx, retry with exponential backoff and jitter |
Idempotency
Send an idempotency_key on every run you start. It is your own string — an episode number, a job id, anything stable for that unit of work.
- The same key with the same body returns the run that already exists, instead of starting a second one.
- The same key with a different body is refused with
idempotency_conflict. Use a new key for new work.
That makes a retry after a timeout safe, which is the difference between one run and a duplicate you are billed for.
Tracing
Every response carries x-morphic-trace-id. Log it. When you report a problem, that id is what lets us find the run in seconds rather than asking you for a time window.