Swayzio Core API v1 — base path /api/swayzio/v1
Conventions

Conventions

Patterns that hold across the whole API.

Error envelope

Every error is a JSON object with a machine‑readable error code. Variants add fields:

SituationStatusBody
Validation failed400{ "error": "validation_error", "issues": [{ "path", "message" }] } (Fastify: "validation_failed")
Malformed JSON400{ "error": "invalid_json", "message": "…" }
Unauthorized401{ "error": "unauthorized" }
Entitlement required403{ "error": "entitlement_required", "code", "feature", "current", "limit", "planId", "status", "upgradeRequired": true }
Not found404{ "error": "<resource>_not_found" }
Method not allowed405{ "error": "method_not_allowed" }
Conflict409{ "error": "<reason>" } (e.g. library_name_conflict, track_set_mismatch)
Structural validation422{ "error": "<x>_structural_validation_failed" }
Rate limited429{ "error": "analytics_rate_limited" }
Native route not implemented501{ "error": "native_route_not_implemented", "message", "path" }
Dependency unavailable503{ "error": "<x>_database_unavailable" | "native_runtime_required", "message" }

The Fastify Core API never leaks thrown messages: unhandled errors collapse to { "error": "internal_error" } with a 5xx status, and typed service errors are mapped to specific codes in‑handler.

Response headers

Set by the runtime on every Core response:

HeaderMeaning
x-swayzio-core-runtimevercel (served natively) or proxy (forwarded to Fastify)
x-swayzio-native-routedotted route label, e.g. tracks.detail, packs.tracks.add
x-swayzio-proxy-fallback1 when a native route fell back to the proxy
Cache-Controlno-store (default on all responses)

Proxy passthrough also forwards accept-ranges, content-range, etag, location. The AI catalog route sets x-swayzio-ai-thread-id.

Pagination

Most list endpoints return a flat envelope:

{ "records": [ /* … */ ] }

Track listing (GET /v1/tracks) and the search/analytics surfaces support limit + cursor (or nextCursor) style paging where noted on each endpoint. Internal drain‑eligible listing is cursor‑paged (limit, cursornextCursor).

Idempotency & safety

  • Writes are owner‑scoped and validated against a Zod request schema; unknown fields are rejected on .strict() schemas (billing, agent‑tool inputs).
  • Uploads are a two‑step intent → finalize flow (a signed PUT, then a finalize call) so large media never transits the API.
  • Conversions / sales tracking dedupe upstream (Dub); webhook ingestion is idempotent on provider event id.

Runtime modes (native vs proxy)

The /v1 surface has two implementations behind one contract. As a caller you don’t choose — the platform routes natively on Vercel and proxies anything not yet ported to the Fastify Core API. The x-swayzio-core-runtime header tells you which path served a given response. A handful of surfaces are native‑only and never proxy: /v1/analytics*, /v1/catalog-analysis, /v1/webhooks/*, /v1/media-intelligence/callback, and /v1/internal/*. See Architecture.