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

Architecture

How the Swayzio API is actually served. You don’t need this to call the API — but it explains the x-swayzio-core-runtime header, the native→proxy notes, and where the asynchronous work happens.

Two implementations, one contract

The /api/swayzio/v1 surface has two implementations behind a single contract:

  1. Native (Next.js route handlers on Vercel) — the forward path. Reads/writes Neon Postgres and signs GCS URLs directly. This is what serves production today.
  2. Fastify Core API (services/api) — the compatibility/fallback service. Any /v1 path not yet ported natively is transparently proxied here.

A generic catch‑all (/api/swayzio/[...path]) forwards anything without a more‑specific native handler, so every Fastify route is reachable. The decision is made per request:

  • SWAYZIO_CORE_API_RUNTIME === "vercel" → serve natively.
  • A native handler that returns “no match” → proxy fallback (when SWAYZIO_PROXY_FALLBACK_ENABLED, default on) → else 501.
  • A *_database_unavailable error → proxy fallback → else 503.

The response header x-swayzio-core-runtime (vercel | proxy) tells you which path served a given call, and x-swayzio-proxy-fallback: 1 flags a fallback.

Native‑only surfaces never proxy: /v1/analytics*, /v1/catalog-analysis, /v1/webhooks/*, /v1/media-intelligence/callback, and all /v1/internal/*. The Stripe webhook returns 503 native_runtime_required if not running on Vercel.

Both implementations share the same auth model (requireSwayzioActor / requireActor), the same @swayzio/domain Zod schemas, and the same owner‑scoping discipline. Parity is intentionally incomplete — the proxy covers the remainder.

The platform around the API

SystemRole
Vercel / Next.jsHosts the web app + native Core API route handlers
Fastify Core API (services/api)Compatibility/fallback implementation of /v1
ClerkAuthentication; issues the session JWTs the API verifies
Neon (Postgres)Primary datastore (owner‑scoped rows, pgvector search)
Google Cloud StorageAudio + media objects (served via short‑lived signed URLs)
ModalGPU media intelligence — embeddings, tags, stems, lyrics
Worker (services/worker, Cloud Run)Upload finalize → readiness → drains; dispatches to Modal
Trigger.devAsync workflows (upload processing, catalog drains)
StripeBilling & subscriptions
DubLink shortening + click/conversion analytics
ResendTransactional email (pack invites)
SentryErrors + tracing

Request lifecycle (an authenticated read)

Client ──Bearer JWT──▶ Vercel route handler
                         │  requireSwayzioActor → { ownerId, … }
                         │  validate query (Zod)
                         ├─ native: repository (WHERE owner_id = $ownerId) → Neon
                         │          → redact DTO (strip ownerId / storageUri)
                         └─ proxy:  forward to Fastify Core API (same auth/headers)
                         ◀── JSON + x-swayzio-core-runtime header

Media processing (asynchronous)

Uploads don’t block on analysis. The flow:

POST /v1/uploads ─▶ signed PUT ─▶ POST /finalize
        │                              │
        ▼                              ▼
   GCS object                   worker: probe + waveform (fast readiness)
        │                              │
        └─ GCS finalize push ─▶ worker ─▶ Modal (tags / stems / lyrics, GPU)

                          POST /v1/media-intelligence/callback (signed)

                              persist lanes; queue embedding refresh

Embeddings (MuQ / MuLan) power audio search; they’re computed by a separate Modal app and drained by the worker. See Internal & Services.