Authentication and API keys

Authenticate requests with an API key or account token, choose scopes, limit keys to accounts, and rotate or revoke them.

Every /v1 request carries a credential as a bearer token. This page covers the credential types, the scopes a key holds, and how to limit, expire, rotate and revoke keys.

Authenticate a request

Send the credential in the Authorization header:

curl "https://api.workwae.com/v1/accounts" \
  -H "Authorization: Bearer $WORKWAE_API_KEY"

A credential that is refused answers with one of these reasons:

ReasonStatusCause
unauthenticated401No credential, a malformed header, an unknown or revoked key, or an unknown or expired account token.
api_key_expired401The key is past its expiresAt, or past the grace of a rotation.
missing_scope403The key lacks the scope the operation checks.
account_scope_forbidden403A key bound to accounts called an organization-wide operation.
account_token_forbidden403An account token called an operation outside its account.
mcp_only_key403An MCP key called /v1.

Credential types

CredentialPrefixIssued byReaches
API keywk_The console, by an owner or admin/v1, for every account or only the accounts it is bound to
Account tokenwat_POST /v1/accounts/{accountId}/tokensOne account's routes, for at most 24 hours
MCP keywk_POST /v1/accounts/{accountId}/mcp-keysThe MCP server only, for one account

An API key's secret is shown once. The console keeps only its prefix, its scopes and a hash.

Keep API keys on your server

A key that is not bound to accounts can read and change every mailbox of the organization. Do not put one in a browser, a mobile app or a repository. Give browsers an account token.

Scopes

A key holds one or more scopes. Scopes do not imply each other: a key that sends mail needs send, and also read if it lists mail. Each operation in the API reference shows the scope it checks; calling it without that scope answers 403 missing_scope.

ScopeAllows
readRead accounts, mail, threads, calendars, availability, contacts, identities, meeting connections, scheduling links, templates, suppressions, webhooks and their delivery attempts, settings, usage and the change feed.
writeCreate, update, sync and delete accounts; create connect sessions and account tokens; change mail, calendar and contact data; manage scheduling links and bookings, templates, suppressions and webhook endpoints (including replays, test events and secret rotation); request AI drafts.
sendSend mail, send drafts, cancel or reschedule queued sends, and run mail merges.
adminChange settings; manage OAuth apps, organization connections, meeting apps and MCP keys; read the audit log; create and download exports.

Account-limited keys

Set accountIds when you create or edit a key to bind it to those accounts (at most 1000). Leave it unset, or set it back to null, and the key reaches every account, including accounts connected later.

An accountIds entry that names an account the organization does not have is refused with unknown_account.

A key bound to accounts:

  • Answers account_not_found for account operations on any other account.
  • Sees only its accounts in GET /v1/accounts and GET /v1/changes.
  • Answers account_scope_forbidden for organization-wide operations, such as settings, webhooks, templates and exports.
  • Cannot mint MCP keys.

Expiry

expiresAt is optional when you create a key. Omit it, or send null, and the key works until you revoke it. A key past its expiry answers 401 api_key_expired.

Editing a key changes its name, scopes or accounts. It does not move the expiry.

Rotate a key

Owners and admins rotate a key in the console. Rotation creates a new secret with the same name, scopes and account limit, and the same lifetime counted from the moment of rotation. The new secret is shown once.

You choose a grace of 0 seconds to 30 days. The old key keeps working until the grace ends, or until its own expiry if that comes first, and then answers api_key_expired.

A key is replaced once: to rotate again, rotate the replacement.

Revoke a key

Revoking a key refuses it from the next request on. There is no undo; create another key instead.

Account tokens

An account token (wat_...) lets your own frontend call one account directly without holding an API key. It acts with every scope, on that one account only, for:

  • GET /v1/accounts/{accountId}.
  • The account's mail, sending, calendar, contacts, identities and meeting-connection routes.

Any other operation answers 403 account_token_forbidden. Account tokens cannot use the MCP server.

Mint one from your backend with a key that has the write scope. ttlSeconds is 60 to 86400 (24 hours) and defaults to 900 (15 minutes).

curl -X POST "https://api.workwae.com/v1/accounts/$ACCOUNT_ID/tokens" \
  -H "Authorization: Bearer $WORKWAE_API_KEY" \
  -H "content-type: application/json" \
  -d '{ "ttlSeconds": 900 }'

The token is returned once and cannot be retrieved later. Account tokens are not listed, rotated or revoked; they expire. In the browser, the SDK can fetch a fresh one per request; see Client options.

MCP keys

An MCP key authenticates one account's end user at the MCP server. Every /v1 route answers it with mcp_only_key.

  • Minting one needs the admin scope, from a key that is not bound to accounts.
  • Its scopes are read, write and send, never admin.
  • Revoke it with DELETE /v1/accounts/{accountId}/mcp-keys/{keyId}.
curl -X POST "https://api.workwae.com/v1/accounts/$ACCOUNT_ID/mcp-keys" \
  -H "Authorization: Bearer $WORKWAE_API_KEY" \
  -H "content-type: application/json" \
  -d '{ "name": "MCP", "scopes": ["read", "send"] }'

How clients present the key is in the MCP server guide; the operations are in the MCP keys reference.

On this page