Quickstart
Create an API key, make a first call, connect a mailbox, read its mail and follow its events.
This path takes you from a new organization to reading a connected mailbox and following its changes. Each step links to the guide that covers it in full.
1. Create an API key
In the console, open API keys and create a key with the read and write scopes. The key (wk_...) is shown once: store it in your secret manager.
The examples read it from the WORKWAE_API_KEY environment variable. Scopes, account-limited keys and rotation are in Authentication and API keys.
2. Make a first call
Call the API with any HTTP client, or install the TypeScript SDK. It runs on Node.js 20 or later, Bun, Deno, Cloudflare Workers and browsers.
bun add @workwae/sdkList the accounts of your organization. A new organization has none yet, so items is empty.
curl "https://api.workwae.com/v1/accounts" \
-H "Authorization: Bearer $WORKWAE_API_KEY"A refused request answers with a stable reason in code, such as missing_scope. See Errors.
3. Connect a mailbox
A connect session is a page Workwae hosts. You create the session, send the user to its url, and they sign in with Google or Microsoft or enter IMAP settings. The browser then returns to your redirectUri.
Allow your redirect URI
A session returns only to an address in settings.redirectUris; without a redirectUri it ends on a Workwae confirmation page. Add yours on the console's Settings page, or with a key that has the admin scope:
curl -X PATCH "https://api.workwae.com/v1/settings" \
-H "Authorization: Bearer $WORKWAE_API_KEY" \
-H "content-type: application/json" \
-d '{ "redirectUris": ["https://app.example.com/mail/connected"] }'Create the session
curl -X POST "https://api.workwae.com/v1/connect-sessions" \
-H "Authorization: Bearer $WORKWAE_API_KEY" \
-H "content-type: application/json" \
-d '{
"redirectUri": "https://app.example.com/mail/connected",
"providers": ["google", "microsoft", "imap"],
"externalRef": "user_42",
"state": "opaque-value-you-check-on-return"
}'externalRef is your own identifier for the user. It is stored on the account, and GET /v1/accounts?externalRef=... filters by it.
When the user is done, the browser lands on your redirect URI with the outcome in the query string. Check that state matches the value you sent.
https://app.example.com/mail/connected?status=success&account_id=6f1c2a4e-...&state=opaque-value-you-check-on-return
https://app.example.com/mail/connected?status=error&error=access_denied&state=opaque-value-you-check-on-returnConnect flows covers headless OAuth, your own OAuth apps and reauthorization.
4. Read mail
A new account syncs in the background. Its initializedAt is null until the first mail sync finishes; the account.initialized event announces the end of it. Mail from before that point is not announced message by message.
# Mailboxes (folders and labels)
curl "https://api.workwae.com/v1/accounts/$ACCOUNT_ID/mailboxes" \
-H "Authorization: Bearer $WORKWAE_API_KEY"
# Unread messages in one mailbox
curl "https://api.workwae.com/v1/accounts/$ACCOUNT_ID/messages?mailboxId=$MAILBOX_ID&unread=true" \
-H "Authorization: Bearer $WORKWAE_API_KEY"
# One message
curl "https://api.workwae.com/v1/accounts/$ACCOUNT_ID/messages/$MESSAGE_ID" \
-H "Authorization: Bearer $WORKWAE_API_KEY"The message list covers the account's sync window; without mailboxId it lists every mailbox. Filters, search, threads and attachments are in Reading mail.
5. Follow events
Everything that happens in your organization is an event: accounts connecting, messages arriving, sends completing, calendar changes. The same events reach your webhooks and the change feed, GET /v1/changes, which you can poll instead of or alongside webhooks.
- Omit
cursorto start from the oldest retained event, then pass each page'snextCursorback. - An empty page means you are caught up: keep the cursor and ask again later.
- Events are kept for the organization's
eventRetentionDays(7 to 30).
curl "https://api.workwae.com/v1/changes?limit=100&cursor=$CURSOR" \
-H "Authorization: Bearer $WORKWAE_API_KEY"Filtering by type and resuming after a crash are in Change feed. For low latency, receive the same events as signed webhooks; the event catalog lists every type.