API keys & auth

Bearer tokens with user-scope or app-scope, shown once at creation.

Token shape

Stripe-style prefixes you can spot in a log stream.

Rowly issues two kinds of bearer tokens. The scope is encoded right in the prefix:

  • rowly_live_u_<uid>_…user-scoped. Can call admin operations across every app the user owns (create_app, list_apps, invite_member).
  • rowly_live_a_<aid>_…app-scoped. Limited to the app in the prefix. This is what you hand to Claude Desktop for day-to-day CRUD.

The _live_ segment reserves room for _test_ tokens once a sandbox ships.

Scopes

Permission strings attached to each key.

Scopes are verb:resource pairs, granted per key at creation time. A key with records:read can call get_record and query_records but not create_record.

// Read-only automation
["records:read", "docs:read"]

// Standard integration
["records:read", "records:write", "docs:read"]

// Admin automation (user-scoped only)
["apps:write", "members:write", "records:*"]

Show-once discipline

Plaintext tokens never leave the creation dialog.

The only response that contains the full token is POST /api/api-keys. After that, the list view + audit log only see the public prefix (e.g. rowly_live_a_app123_ab12CDEF). If you lose the key, revoke it and create a new one — there is no recovery path by design.

Using the token

Standard Bearer header; same everywhere.

curl https://rowly.ai/api/records/Vehicle \
  -H "Authorization: Bearer rowly_live_a_app123_xxxxxxxx"
{
  "mcpServers": {
    "rowly": {
      "url": "https://rowly.ai/mcp",
      "headers": {
        "Authorization": "Bearer rowly_live_a_app123_xxxxxxxx"
      }
    }
  }
}

OAuth 2.1 (v0.2)

API keys stay forever; OAuth lands alongside them.

v0.1 ships only the OAuth 2.1 scaffolding — the resource metadata endpoint at /.well-known/oauth-protected-resource and the workers-oauth-provider wiring. The full authorization-code flow and consent screen go live in v0.2. API-key auth stays supported forever as the automation story.