Skip to main content
The Moda REST API uses a calendar-dated version string carried on the Moda-Version request header. Pinning a version guarantees the wire shape you built against stays stable even when we ship a newer version.

Supported versions

  • Canonical means routes emit this shape natively. Pin this to get the newest response fields.
  • Default means unpinned requests (no Moda-Version header) resolve to this version. The default advances to the next-newest supported version once the current default sunsets.
  • Sunset means the version stops being supported on the listed date. After that date, pinning the sunset version returns 400 unsupported_version, and the default advances to the next-newest.

The Moda-Version header

Sending the header

Pin explicitly on every request:

Omitting the header

If you omit Moda-Version, the server resolves your request to the current default (2026-04-12). Unpinned integrations keep working across version bumps until a sunset advances the default. For production, pin explicitly so future default advancement doesn’t silently change your response shapes.

Unknown versions

Any value other than a currently-supported version returns 400 unsupported_version:
The response’s Moda-Version header still carries the current default, so clients can detect the drift and upgrade.

Response header

Every response — success or error — carries the resolved Moda-Version back:
If you omit the header and want to record which version the server resolved you to, read it off the response.

What changes between versions

The 2026-05-01 canonical shape is a cleaner envelope for all task-shaped operations (POST /v1/tasks, GET /v1/tasks/{id}, GET /v1/tasks). The 2026-04-12 legacy shape is the original flat JobResponse form.

Task endpoints

2026-04-12 (legacy flat shape)
2026-05-01 (canonical Task envelope)

Quick migration map

Per-operation examples are on each endpoint’s reference page.

List endpoints: offset → cursor pagination

Every list endpoint moved from offset pagination to opaque cursor pagination. Iterate until next_cursor is null: Before (2026-04-12):
After (2026-05-01):
Migration pattern:
Sort order changed from updated_at DESC (canvases) / name ASC (orgs) to (created_at DESC, id DESC) across every list endpoint — immutable columns only, which avoids row skip / duplicate bugs when rows mutate mid-scan. GET /v1/brand-kits also dropped the team_id field from the canonical response — it’s implicit in the API key context.

Error responses

Every endpoint now explicitly declares ErrorEnvelope responses for 401 / 403 / 404 / 409 / 422 / 429 / 500 in the OpenAPI spec. The wire shape is unchanged — this is a spec-hardening change for SDK generators to emit typed error classes. No migration action required for direct HTTP callers.

Webhook event taxonomy

Webhook event.type values moved from the legacy job.* prefix to task.* / export.*. Legacy spelling task.cancelled (two Ls) is retired — canonical uses task.canceled (matching the PublicTaskStatus.CANCELED enum value). Non-terminal states (queued, running, expired) no longer fire webhooks — the v1 taxonomy is terminal-only. See Webhooks for the full event envelope.

What’s covered by a version bump

New versions only ship for breaking response-shape changes. Additive changes — new endpoints, new optional request parameters, new response fields, new error codes within an existing error type — land at the current canonical version without a bump. Your client should tolerate unknown fields in responses so these additions don’t surprise it.

Breaking changes (new version ships)

  • Removing or renaming a response field
  • Removing an endpoint, path, or parameter
  • Changing a field’s type or shape
  • Tightening validation (new 400s for inputs that used to succeed)
  • Changing status vocabulary (e.g. completedsucceeded)
  • Changing default behavior of an existing parameter

Additive changes (no version bump)

  • New endpoint, path, or optional parameter
  • New response field (existing fields unchanged)
  • New optional request header
  • New code within an existing type on error responses
  • Loosened validation (fewer 400s)

Version bump policy

We ship additive version bumps. When a new canonical version lands:
  1. The new version becomes the canonical (newest) — routes emit it natively.
  2. The previous default stays supported for a sunset window (typically 2–3 weeks for small shape changes; longer for substantial ones).
  3. On the sunset date, the older version retires (pinning it returns 400), and the default advances to whichever supported version is next-oldest.
Practical upshot: if you pin explicitly, you upgrade on your schedule. If you stay unpinned, you’ll track the current default and will see a shape change whenever the default advances — which we announce here with a calendar date well in advance.

Recommendations

  • Pin Moda-Version explicitly on every request in production. Don’t rely on the default — the default advances on sunset dates.
  • Log the response’s Moda-Version header so you can tell at a glance which version your traffic is actually hitting.
  • When you see 400 unsupported_version, read the supported list out of the error details — that’s the ground truth and updates automatically.
  • Subscribe to the changelog to hear about new versions and sunset dates as they’re announced.