API Reference

Complete REST API for managing migrations, connections, webhooks, and team.

Authentication

All endpoints (except /api/contact) require authentication. Two options:

  • Session cookie: Sign in via the web app — cookies are sent automatically
  • API key: Generate from Settings → API Keys. Format: nss_ + 64 hex chars. Include as Authorization: Bearer YOUR_KEY

API keys are shown once at creation. Stored as SHA-256 hashes — they cannot be retrieved after creation. Revoke and regenerate at any time.

Workspaces

If you've accepted a team invite, requests can act on that team's data instead of your own. A session normally operates on your own account; sending a nss_workspace cookie set to another account's id switches every endpoint below to read and write that account's migrations, connections, and webhooks instead. It only ever grants access you already have — a cookie pointing at a workspace you're not an accepted member of is ignored, not rejected. API keys always act as their own owner's account and don't follow this cookie.

GET/api/workspaces

Every workspace you can act in — your own, plus any team you've been accepted into — with your role in each.

POST/api/workspaces/active

Body { accountId }. Switches the workspace cookie after checking real membership.

member can view everything and create/run/stop/pause/resume/validate migrations. admin can also manage connections and webhooks, delete or cut over a migration, and share or revoke a report link. Billing and team invites always belong to the real account owner, whichever workspace is active.

Migrations API

GET/api/migrations

List all migrations. Optional query: ?search=&status=&mode=. Returns enriched with source/target connection names.

POST/api/migrations

Create a migration. Required body:

{
  "name": "users-prod-to-pg",
  "sourceConnectionId": "<UUID>",
  "targetConnectionId": "<UUID>",
  "sourceDatabase": "production",
  "sourceCollection": "users",
  "targetTable": "users",
  "mode": "one-time",
  "groupId": "optional-batch-id",
  "groupName": "optional-batch-name"
}

Returns 201 with { id, name, status: "created" }.

GET/api/migrations/:id

Full migration detail — progress, record counts, timestamps, error messages.

DELETE/api/migrations/:id

Delete a migration. Cannot delete running/queued (returns 409).

POST/api/migrations/:id/start

Start migration. Requires existing schema mapping. Enqueues BullMQ job. Response: { status: "queued" }.

POST/api/migrations/:id/stop

Stop a running migration. Removes BullMQ job, sets status to stopped.

POST/api/migrations/:id/pause

Pause a running CDC migration. Status → paused.

POST/api/migrations/:id/resume

Resume a paused CDC migration. Uses saved resume token.

GET/api/migrations/:id/logs

Server-Sent Events stream of real-time logs. Connect via EventSource. Sends { done: true } on terminal status.

PATCH/api/migrations/:id

Update settings. Body (either field): { driftPolicy?: "ignore" | "add_column" | "alert_and_pause", lagAlertThresholdMs?: number | null }. The threshold is 1,000–86,400,000 ms; null turns lag alerts off.

GET/api/migrations/:id/metrics?minutes=60

Throughput, lag, error rate and freshness. Returns summary (events/sec over the last 5 minutes, error rate and worst lag over the window), a per-minute series, and the current lagMs and lastEventAt. minutes is 1–1440; metrics are kept for 7 days.

POST/api/migrations/:id/validate

Run validation: row-count parity plus checksum sampling of up to 100 rows. Returns the report and a runId. Each run is stored as a fixed snapshot.

GET/api/migrations/:id/validation-runs

The last 20 validation runs, newest first: { id, createdAt, verdict, label, sharePath }. verdict is passed, failed or incomplete. label is the display text; it reads Counts match for an incomplete run whose row counts matched where row checksums aren't available for that source/target pair.

GET/api/validation-runs/:runId/export?format=md

Download one run as Markdown (format=md, the default) or JSON (format=json).

POST/api/validation-runs/:runId/share

Create a public read-only link for one run, or return the existing one: { sharePath: "/reports/<token>" }. Anyone with the link can view it without logging in. It shows counts, verdict and mismatched primary keys, never connection details or row values.

DELETE/api/validation-runs/:runId/share

Revoke the link. The old URL stops working immediately and is never reissued.

GET/api/migrations/:id/schema

Get saved schema mapping for a migration.

POST/api/migrations/:id/schema

Save/update schema mapping. Body:

{
  "mappings": [
    { "sourceField": "_id", "targetColumn": "id",
      "sqlType": "UUID", "nullable": false, "isPrimaryKey": true },
    { "sourceField": "email", "targetColumn": "email",
      "sqlType": "TEXT", "nullable": true, "isPrimaryKey": false }
  ]
}
POST/api/migrations/:id/schema/introspect

Trigger auto schema introspection. Samples 500 docs, returns detected fields + generated DDL.

Connections API

GET/api/connections

List all connections. Credentials never returned.

POST/api/connections

Create connection. Body: { name, type, dbType, credentials }. Credentials encrypted with AES-256-GCM.

PATCH/api/connections/:id

Update name or credentials. Only provided fields updated.

DELETE/api/connections/:id

Delete a connection permanently.

POST/api/connections/:id/test

Test connectivity. Returns { ok: true } or { ok: false, message }.

GET/api/connections/:id/databases

List available databases on the source connection.

GET/api/connections/:id/collections?database=X

List collections/tables in the specified database.

Audit log API

GET/api/audit-logs

Business and Enterprise plans. Every sign-in, sign-up and change to migrations, connections, API keys, webhooks, team, billing and shared reports, newest first. Each event has the actor, action, target, IP address, user agent, and whether it came from the app or an API key (with the key's prefix). Query: action (prefix, e.g. migration.), from / to (ISO dates), limit (1–100), cursor (from nextCursor). Add format=csv to download up to 50,000 matching rows. Events are append-only, with no edit or delete endpoint, and credential values are never recorded.

Webhooks API

GET/api/webhooks

List configured webhooks, with the last 4 characters of each signing secret and the last delivery's time and HTTP status.

POST/api/webhooks

Create webhook. URL must be HTTPS. Events: migration.completed, migration.failed, migration.started, cdc.error, cdc.lag_exceeded, cdc.lag_recovered, schema.drift. Returns the endpoint's signing secret once — see Integrations for verifying signatures.

DELETE/api/webhooks/:id

Delete a webhook.

POST/api/webhooks/:id/test

Send test payload to verify endpoint.

Other endpoints

GET/api/stats

Dashboard stats: active migrations, total records, CDC channels, total migrations.

GET/api/user

Get profile (id, name, email).

PATCH/api/user

Update name and/or email.

GET/api/api-keys

List API keys (prefix, scope, environment label and last-used time — never raw keys).

POST/api/api-keys

Generate new key. Body: name, optional scope (read | write | admin, default admin) and env label. Returns the raw key once. See Integrations for what each scope allows.

DELETE/api/api-keys/:id

Revoke an API key.

GET/api/team

List team members.

POST/api/team

Invite member by email with role (admin/member).

DELETE/api/team/:id

Remove a team member.

POST/api/contact

Public (no auth). Submit contact/sales inquiry.

Rate limits

Redis-backed sliding-window rate limiting on all authenticated endpoints:

  • Auth endpoints: 10 req / 60s window
  • Migrations API: 30 req / 60s
  • Connections API: 30 req / 60s
  • Webhooks API: 20 req / 60s

Exceeding returns HTTP 429 with Retry-After header.