Skip to main content

Authentication (REST API)

Every request. Always pair with Moda-Version: 2026-05-01.

Creating a key

  1. Open the Moda app → Settings → Developer → REST API → Create Key.
  2. Name the key for the integration it belongs to (“CI Pipeline”, “Slack bot”).
  3. Copy the key immediately — it’s shown once.
  4. Copy the webhook signing secret shown in the same banner. This is used to verify webhook payloads. You cannot retrieve it later.
There is no scope picker on that screen. A key created there carries the default grant — every recognized scope except admin. Treat it as broadly privileged: one key per integration, stored as a production secret, revoked the moment it is no longer needed. Keys start with moda_live_. They are hashed at rest; only the prefix is safe to log. Lost a key? Revoke it and create a new one.

Scopes (22)

Twenty-two scopes are recognized; twenty-one of them are in the default grant. admin is opt-in only and never granted by default. Drive reads (folder list / tree / file list / file metadata) ride canvases:read; only file bytes need files:read.

Scope recipes by integration type

What each integration actually exercises — useful for auditing an integration’s blast radius, not something the Settings key creator lets you enforce.

Security best practices

  • Keep keys server-side. Never expose them in frontend code, mobile apps, or client bundles.
  • One key per integration. Revocation affects one system; rotation doesn’t cascade.
  • Narrow scopes. A read-only dashboard shouldn’t have tasks:write.
  • Rotate on a schedule or after any suspected leak. Revoke in the app; issue a fresh key; update config.
  • Store in a secret manager. .env works for local dev; production should use Vault / AWS Secrets Manager / GCP Secret Manager / Doppler.
  • Log the request_id from error envelopes — it’s how support finds your request in logs. Don’t log the key itself.

Revoking

Settings → Developer → REST API → Delete. Takes effect immediately. All requests using that key return 401 Unauthorized instantly.

Errors

Both come with a WWW-Authenticate: Bearer header. Errors carry the standard typed envelope; see errors.md.

Common wrong guesses

  • Committing a moda_live_… key to a repo. Even private repos leak eventually. Use env vars + a secret manager.
  • Assuming a key is narrow because the integration is. Keys minted in Settings carry the default grant regardless of what the integration calls. Isolate by key, not by scope.
  • Logging the full key for debugging. Only log the prefix (moda_live_) — the suffix is a secret.
  • Using the same key across production and staging. Keys should be environment-specific so you can revoke independently.
  • Forgetting the webhook signing secret. It’s shown once alongside the key. Store it adjacent to the key in your secret manager — you’ll need it to verify webhook payloads.

Upstream