Skip to main content

Overview

The ReelMirror API supports two authentication methods:
  1. API keys — For programmatic/server-side access
  2. JWT tokens — For browser-based access via Supabase Auth
Every request must include an Authorization header:
Authorization: Bearer <token>

API Keys

API keys are the recommended way to authenticate programmatic access.

Creating a key

Create an API key from the dashboard or via the API using your JWT token:
curl -X POST https://reelmirror.com/api/v1/api-keys \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "Production Key", "scopes": ["personas:read", "content:read"]}'
Response:
{
  "id": "uuid",
  "name": "Production Key",
  "key": "rm_abc123...",
  "scopes": ["personas:read", "content:read"],
  "created_at": "2025-01-01T00:00:00Z"
}
The key field is only returned once at creation time. Store it securely — you cannot retrieve it later.

Key format

API keys follow the format rm_ followed by 32 random characters. Keys are stored as SHA-256 hashes in the database.

Listing keys

curl https://reelmirror.com/api/v1/api-keys \
  -H "Authorization: Bearer YOUR_TOKEN"

Revoking a key

curl -X DELETE https://reelmirror.com/api/v1/api-keys/KEY_ID \
  -H "Authorization: Bearer YOUR_TOKEN"

JWT Tokens

JWT tokens are Supabase session tokens issued when a user signs in via the dashboard. They are primarily used for frontend/browser access. JWT users automatically have all scopes — no scope restrictions apply.

Scopes

API keys can be restricted to specific scopes. If no scopes are specified when creating a key, all scopes except billing:read, billing:write, feedback:read, and feedback:write are granted by default. Billing and feedback scopes must be explicitly requested.
ScopeDescription
personas:readRead personas
personas:writeCreate, update, delete personas
sources:readList sources
sources:writeAdd, remove sources
content:readRead content, poll generation status
content:writeGenerate content, clone URLs, toggle public, approve/reject posts
sync:writeTrigger content sync
billing:readView balance and transactions
billing:writeTop up balance and configure auto-reload
publishing:readList connected accounts, view outgoing posts and slots
publishing:writeConnect accounts, create/update/publish outgoing posts
profile:readRead your profile
profile:writeUpdate your profile
uploads:writeUpload avatar images and voice samples
feedback:readRead your feedback tickets and responses
feedback:writeSubmit feedback and post replies

Scope requirements by endpoint

EndpointMethodRequired scope
/v1/api-keysPOST, GET, DELETENone (always allowed)
/v1/personasGETpersonas:read
/v1/personasPOST, PATCH, DELETEpersonas:write
/v1/personas/:id/sourcesGETsources:read
/v1/personas/:id/sourcesPOST, DELETEsources:write
/v1/personas/:id/syncPOSTsync:write
/v1/personas/:id/source-postsGETcontent:read
/v1/personas/:id/generated-postsGETcontent:read
/v1/generatePOSTcontent:write
/v1/generate/media-itemPOSTcontent:write
/v1/generate/voice-convertPOSTcontent:write
/v1/generate/regenerate-postPOSTcontent:write
/v1/clone-urlPOSTcontent:write
/v1/generate/toggle-publicPOSTcontent:write
/v1/generated-posts/:idDELETEcontent:write
/v1/generated-media-items/:idDELETEcontent:write
/v1/sync-jobs/:idGETcontent:read
/v1/generated-posts/:idGETcontent:read
/v1/generated-media-items/:idGETcontent:read
/v1/billing/balanceGETbilling:read
/v1/billing/balancePATCHbilling:write
/v1/billing/topupPOSTbilling:write
/v1/billing/setup-intentPOSTbilling:write
/v1/billing/transactionsGETbilling:read
/v1/publishing/accountsGETpublishing:read
/v1/publishing/accounts/connectGETpublishing:write
/v1/publishing/accounts/slotsGETpublishing:read
/v1/publishing/accounts/slotsPOSTpublishing:write
/v1/publishing/accounts/{id}GETpublishing:read
/v1/publishing/accounts/{id}DELETEpublishing:write
/v1/publishing/postsGETpublishing:read
/v1/publishing/postsPOSTpublishing:write
/v1/publishing/posts/{id}GETpublishing:read
/v1/publishing/posts/{id}PATCH, DELETEpublishing:write
/v1/publishing/posts/{id}/publishPOSTpublishing:write
/v1/publishing/posts/{id}/schedulePOSTpublishing:write
/v1/publishing/posts/{id}/retryPOSTpublishing:write
/v1/publishing/posts/{id}/cancelPOSTpublishing:write
/v1/publishing/captionPOSTpublishing:write
/v1/generated-posts/{id}/approvePOSTcontent:write
/v1/generated-posts/{id}/rejectPOSTcontent:write
/v1/generated-posts/{id}/send-to-composePOSTcontent:write
/v1/generated-media-items/{id}/rejectPOSTcontent:write
/v1/profileGETprofile:read
/v1/profilePATCHprofile:write
/v1/uploadsPOSTuploads:write
/v1/feedbackGETfeedback:read
/v1/feedbackPOSTfeedback:write
/v1/feedback/{id}GETfeedback:read
/v1/feedback/{id}/responsesPOSTfeedback:write
/v1/auth/signupPOSTNone (public)
/v1/publishing/accounts/connect requires a browser. The authUrl returned must be opened in a browser to complete the OAuth flow. The provider redirects to /api/internal/publishing/accounts/callback — this is an HTML redirect, not a JSON callback. API clients (curl, scripts) cannot complete this flow. Connect accounts once via the dashboard; all publishing operations are fully automatable thereafter.

Rate Limiting

Rate limits are applied per authentication identity:
Auth typeLimit
API key60 requests/minute
JWT120 requests/minute
Rate limit information is included in every response:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 58
X-RateLimit-Reset: 1704067260
When the limit is exceeded, the API returns a 429 status with the RATE_LIMITED error code.

Monthly Spending Limits

Each API key can have an optional monthly spending limit. When set, the API will reject requests that would cause the key’s total spending for the current calendar month (UTC) to exceed the limit.

Setting a limit

Set monthly_limit_cents when creating or updating a key:
# Create a key with a $50/month limit
curl -X POST https://reelmirror.com/api/v1/api-keys \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "Limited Key", "monthly_limit_cents": 5000}'

# Update an existing key's limit
curl -X PATCH https://reelmirror.com/api/v1/api-keys/KEY_ID \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"monthly_limit_cents": 10000}'

# Remove the limit (unlimited)
curl -X PATCH https://reelmirror.com/api/v1/api-keys/KEY_ID \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"monthly_limit_cents": null}'

How it works

  • Limits are checked before every billable operation (sync, generate, clone-url, voice conversion)
  • The limit resets on the 1st of each month (UTC)
  • When exceeded, the API returns a 429 status with the KEY_SPENDING_LIMIT_EXCEEDED error code
  • The monthly_spent_cents field on the list endpoint shows current-month spending per key
  • JWT/cookie auth (dashboard usage) is never subject to key spending limits
  • Valid range: 1.00(100cents)to1.00 (100 cents) to 10,000.00 (1,000,000 cents)

Checking current spending

The list API keys endpoint includes monthly_spent_cents for keys that have a limit configured:
{
  "data": [
    {
      "id": "uuid",
      "name": "Limited Key",
      "monthly_limit_cents": 5000,
      "monthly_spent_cents": 1250,
      ...
    }
  ]
}

Security Best Practices

  • Never expose API keys in client-side code. Use them only in server-side applications.
  • Use the minimum scopes necessary. Create separate keys for different services with only the scopes they need.
  • Set spending limits on API keys. Protect against abuse or key theft by capping monthly spend per key.
  • Rotate keys regularly. Delete old keys and create new ones periodically.
  • Monitor usage. Check last_used_at on your API keys via the list endpoint.