Accounts

List, update, sync and delete connected accounts, connect IMAP mailboxes and token imports, and mint account tokens.

Guides: Connect flows, IMAP and SMTP, Authentication.

MethodPathOperationScope
GET/v1/accountsList accountsread
POST/v1/accountsConnect an account from an existing refresh tokenwrite
GET/v1/accounts/{accountId}Get an accountread
PATCH/v1/accounts/{accountId}Update an accountwrite
DELETE/v1/accounts/{accountId}Delete an accountwrite
POST/v1/accounts/{accountId}/syncSync an account nowwrite
POST/v1/accounts/{accountId}/tokensMint an account-scoped tokenwrite
POST/v1/imap-accountsConnect an IMAP/SMTP account with a passwordwrite
PATCH/v1/accounts/{accountId}/imap-settingsChange an IMAP account's servers or passwordwrite
GET/v1/autoconfigFind IMAP, SMTP and DAV settings for an addressread

List accounts

GET
/v1/accounts

Runs in your browser against api.workwae.com with the key you enter. Use a read-only key, limited to a test account if you can.

Newest first. q matches part of the email address or the external reference, case-insensitively; externalRef matches it exactly. An API key bound to accounts lists only those.

Required scope: read.

Query Parameters

limit?integer
Range1 <= value <= 200
Default50
cursor?string
Length1 <= length <= 512
externalRef?string
q?string
Length1 <= length <= 200
status?string
Value in"active""paused""reauth_required""disabled"
orgConnectionId?string
Formatuuid
delegateAccountId?string
Formatuuid

Response Body

OK

application/json
  1. response
items*array<>
nextCursor*|null
Example Request
curl -X GET 'https://api.workwae.com/v1/accounts'
Example Response
{  "items": [    {      "id": "c4e6a8b0-1d3f-4a5c-8e7b-9d1f3a5c7e9b",      "externalRef": "user_42",      "provider": "gmail",      "email": "string",      "displayName": "string",      "oauthAppId": "c6e11c75-050f-4212-9cff-bddb4fb07e36",      "cloud": "global",      "status": "active",      "statusReason": "string",      "settings": {        "bodyStorage": "none",        "syncWindowDays": 1,        "calendarEnabled": true,        "contactsEnabled": true,        "undoSendSeconds": 0,        "trackOpens": true,        "trackClicks": true,        "trackingHoneypot": true      },      "settingsOverride": {        "bodyStorage": "none",        "syncWindowDays": 1,        "calendarEnabled": true,        "contactsEnabled": true,        "undoSendSeconds": 0,        "trackOpens": true,        "trackClicks": true,        "trackingHoneypot": true      },      "runtime": {        "state": "pending",        "detail": "string",        "ownerInstanceId": "b31a377d-3f38-46d6-b670-15babc0f5625",        "updatedAt": "2026-05-04T09:30:00.000Z"      },      "imap": {        "imap": {          "host": "string",          "port": 0,          "security": "tls",          "user": "string"        },        "smtp": {          "host": "string",          "port": 0,          "security": "tls",          "user": "string"        },        "auth": "password",        "appendSent": true,        "dav": {          "calendarUrl": "string",          "contactsUrl": "string",          "user": "string",          "auth": "imap_password"        }      },      "auth": {        "method": "oauth",        "orgConnectionId": "17f753c8-b2ec-494b-9468-6e20a9a2f99c",        "delegateAccountId": "016ade53-f197-47ea-bd0e-48fda92e431f"      },      "initializedAt": "2026-05-04T09:30:00.000Z",      "calendarInitializedAt": "2026-05-04T09:30:00.000Z",      "contactsInitializedAt": "2026-05-04T09:30:00.000Z",      "createdAt": "2026-05-04T09:30:00.000Z",      "updatedAt": "2026-05-04T09:30:00.000Z"    }  ],  "nextCursor": "eyJ0eG5pZCI6IjQyIiwiaWQiOjEwMDF9"}
POST
/v1/accounts

Runs against the live API with the key you enter: this change really happens. Use a key limited to a test account.

The address is the provider's (Google's userinfo, Graph's /me).

Required scope: write.

Request Body

application/json
  1. body
provider*OAuthProvider
Value in"google""microsoft"
microsoftCloud?MicrosoftCloud
Default"global"
Value in"global""gcc-high""dod""china"
refreshToken*string
Length1 <= length
oauthAppId?string
Formatuuid
externalRef?string
Lengthlength <= 255
settings?
sharedMailboxesEnabled?boolean

Response Body

OK

application/json
  1. response
id*string
Formatuuid
externalRef*string|null
provider*AccountProvider
Value in"gmail""graph""imap"
email*string
displayName*string|null
oauthAppId*|null
cloud*|null
status*AccountStatus
Value in"active""paused""reauth_required""disabled"
statusReason*string|null
settings*
settingsOverride*
runtime*|null
imap*|null
auth*
initializedAt*|null
calendarInitializedAt*|null
contactsInitializedAt*|null
createdAt*string
Formatdate-time
updatedAt*string
Formatdate-time
Example Request
curl -X POST 'https://api.workwae.com/v1/accounts' \  -H 'Content-Type: application/json' \  -d '{  "provider": "google",  "refreshToken": "string"}'
Example Response
{  "id": "c4e6a8b0-1d3f-4a5c-8e7b-9d1f3a5c7e9b",  "externalRef": "user_42",  "provider": "gmail",  "email": "string",  "displayName": "string",  "oauthAppId": "c6e11c75-050f-4212-9cff-bddb4fb07e36",  "cloud": "global",  "status": "active",  "statusReason": "string",  "settings": {    "bodyStorage": "none",    "syncWindowDays": 1,    "calendarEnabled": true,    "contactsEnabled": true,    "undoSendSeconds": 0,    "trackOpens": true,    "trackClicks": true,    "trackingHoneypot": true  },  "settingsOverride": {    "bodyStorage": "none",    "syncWindowDays": 1,    "calendarEnabled": true,    "contactsEnabled": true,    "undoSendSeconds": 0,    "trackOpens": true,    "trackClicks": true,    "trackingHoneypot": true  },  "runtime": {    "state": "pending",    "detail": "string",    "ownerInstanceId": "b31a377d-3f38-46d6-b670-15babc0f5625",    "updatedAt": "2026-05-04T09:30:00.000Z"  },  "imap": {    "imap": {      "host": "string",      "port": 0,      "security": "tls",      "user": "string"    },    "smtp": {      "host": "string",      "port": 0,      "security": "tls",      "user": "string"    },    "auth": "password",    "appendSent": true,    "dav": {      "calendarUrl": "string",      "contactsUrl": "string",      "user": "string",      "auth": "imap_password"    }  },  "auth": {    "method": "oauth",    "orgConnectionId": "17f753c8-b2ec-494b-9468-6e20a9a2f99c",    "delegateAccountId": "016ade53-f197-47ea-bd0e-48fda92e431f"  },  "initializedAt": "2026-05-04T09:30:00.000Z",  "calendarInitializedAt": "2026-05-04T09:30:00.000Z",  "contactsInitializedAt": "2026-05-04T09:30:00.000Z",  "createdAt": "2026-05-04T09:30:00.000Z",  "updatedAt": "2026-05-04T09:30:00.000Z"}

Get an account

GET
/v1/accounts/{accountId}

Runs in your browser against api.workwae.com with the key you enter. Use a read-only key, limited to a test account if you can.

Required scope: read.

Path Parameters

accountId*string
Formatuuid

Response Body

OK

application/json
  1. response
id*string
Formatuuid
externalRef*string|null
provider*AccountProvider
Value in"gmail""graph""imap"
email*string
displayName*string|null
oauthAppId*|null
cloud*|null
status*AccountStatus
Value in"active""paused""reauth_required""disabled"
statusReason*string|null
settings*
settingsOverride*
runtime*|null
imap*|null
auth*
initializedAt*|null
calendarInitializedAt*|null
contactsInitializedAt*|null
createdAt*string
Formatdate-time
updatedAt*string
Formatdate-time
Example Request
curl -X GET 'https://api.workwae.com/v1/accounts/6f1c2a4e-8b3d-4e5f-9a7b-1c2d3e4f5a6b'
Example Response
{  "id": "c4e6a8b0-1d3f-4a5c-8e7b-9d1f3a5c7e9b",  "externalRef": "user_42",  "provider": "gmail",  "email": "string",  "displayName": "string",  "oauthAppId": "c6e11c75-050f-4212-9cff-bddb4fb07e36",  "cloud": "global",  "status": "active",  "statusReason": "string",  "settings": {    "bodyStorage": "none",    "syncWindowDays": 1,    "calendarEnabled": true,    "contactsEnabled": true,    "undoSendSeconds": 0,    "trackOpens": true,    "trackClicks": true,    "trackingHoneypot": true  },  "settingsOverride": {    "bodyStorage": "none",    "syncWindowDays": 1,    "calendarEnabled": true,    "contactsEnabled": true,    "undoSendSeconds": 0,    "trackOpens": true,    "trackClicks": true,    "trackingHoneypot": true  },  "runtime": {    "state": "pending",    "detail": "string",    "ownerInstanceId": "b31a377d-3f38-46d6-b670-15babc0f5625",    "updatedAt": "2026-05-04T09:30:00.000Z"  },  "imap": {    "imap": {      "host": "string",      "port": 0,      "security": "tls",      "user": "string"    },    "smtp": {      "host": "string",      "port": 0,      "security": "tls",      "user": "string"    },    "auth": "password",    "appendSent": true,    "dav": {      "calendarUrl": "string",      "contactsUrl": "string",      "user": "string",      "auth": "imap_password"    }  },  "auth": {    "method": "oauth",    "orgConnectionId": "17f753c8-b2ec-494b-9468-6e20a9a2f99c",    "delegateAccountId": "016ade53-f197-47ea-bd0e-48fda92e431f"  },  "initializedAt": "2026-05-04T09:30:00.000Z",  "calendarInitializedAt": "2026-05-04T09:30:00.000Z",  "contactsInitializedAt": "2026-05-04T09:30:00.000Z",  "createdAt": "2026-05-04T09:30:00.000Z",  "updatedAt": "2026-05-04T09:30:00.000Z"}

Update an account

PATCH
/v1/accounts/{accountId}

Runs against the live API with the key you enter: this change really happens. Use a key limited to a test account.

Changing settings.bodyStorage, calendarEnabled or syncWindowDays restarts the account's syncs: full stores every indexed message and backfills, none deletes stored content. status only moves between active and paused; only a new grant clears reauth_required and disabled.

Required scope: write.

Path Parameters

accountId*string
Formatuuid

Request Body

application/json
  1. body
externalRef?|null
status?SettableAccountStatus
Value in"active""paused"
settings?

Response Body

OK

application/json
  1. response
id*string
Formatuuid
externalRef*string|null
provider*AccountProvider
Value in"gmail""graph""imap"
email*string
displayName*string|null
oauthAppId*|null
cloud*|null
status*AccountStatus
Value in"active""paused""reauth_required""disabled"
statusReason*string|null
settings*
settingsOverride*
runtime*|null
imap*|null
auth*
initializedAt*|null
calendarInitializedAt*|null
contactsInitializedAt*|null
createdAt*string
Formatdate-time
updatedAt*string
Formatdate-time
Example Request
curl -X PATCH 'https://api.workwae.com/v1/accounts/6f1c2a4e-8b3d-4e5f-9a7b-1c2d3e4f5a6b' \  -H 'Content-Type: application/json' \  -d '{}'
Example Response
{  "id": "c4e6a8b0-1d3f-4a5c-8e7b-9d1f3a5c7e9b",  "externalRef": "user_42",  "provider": "gmail",  "email": "string",  "displayName": "string",  "oauthAppId": "c6e11c75-050f-4212-9cff-bddb4fb07e36",  "cloud": "global",  "status": "active",  "statusReason": "string",  "settings": {    "bodyStorage": "none",    "syncWindowDays": 1,    "calendarEnabled": true,    "contactsEnabled": true,    "undoSendSeconds": 0,    "trackOpens": true,    "trackClicks": true,    "trackingHoneypot": true  },  "settingsOverride": {    "bodyStorage": "none",    "syncWindowDays": 1,    "calendarEnabled": true,    "contactsEnabled": true,    "undoSendSeconds": 0,    "trackOpens": true,    "trackClicks": true,    "trackingHoneypot": true  },  "runtime": {    "state": "pending",    "detail": "string",    "ownerInstanceId": "b31a377d-3f38-46d6-b670-15babc0f5625",    "updatedAt": "2026-05-04T09:30:00.000Z"  },  "imap": {    "imap": {      "host": "string",      "port": 0,      "security": "tls",      "user": "string"    },    "smtp": {      "host": "string",      "port": 0,      "security": "tls",      "user": "string"    },    "auth": "password",    "appendSent": true,    "dav": {      "calendarUrl": "string",      "contactsUrl": "string",      "user": "string",      "auth": "imap_password"    }  },  "auth": {    "method": "oauth",    "orgConnectionId": "17f753c8-b2ec-494b-9468-6e20a9a2f99c",    "delegateAccountId": "016ade53-f197-47ea-bd0e-48fda92e431f"  },  "initializedAt": "2026-05-04T09:30:00.000Z",  "calendarInitializedAt": "2026-05-04T09:30:00.000Z",  "contactsInitializedAt": "2026-05-04T09:30:00.000Z",  "createdAt": "2026-05-04T09:30:00.000Z",  "updatedAt": "2026-05-04T09:30:00.000Z"}

Delete an account

DELETE
/v1/accounts/{accountId}

Runs against the live API with the key you enter: this change really happens. Use a key limited to a test account.

Stops syncing and removes the credential at once. The account's data is purged for good after the retention period (default 30 days), or shortly after the call with ?purge=true; account.purged announces it. Its events are left to age out of the event log (within 31 days). purge=true also purges an account that is already deleted.

Required scope: write.

Path Parameters

accountId*string
Formatuuid

Query Parameters

purge?|
Defaultfalse

Response Body

OK

application/json
  1. response
Example Request
curl -X DELETE 'https://api.workwae.com/v1/accounts/6f1c2a4e-8b3d-4e5f-9a7b-1c2d3e4f5a6b'
Example Response
null

Sync an account now

POST
/v1/accounts/{accountId}/sync

Runs against the live API with the key you enter: this change really happens. Use a key limited to a test account.

Wakes the account's sync the way a provider push does: one nudge per kind to the instance that owns it. The owner keeps at most one pending pass per kind, so a repeat while a pass is running becomes a single extra pass. At most 30 of these requests per account per minute (429 rate_limited). kinds defaults to every kind the account has enabled (mail always; calendar and contacts when its settings turn them on). With no live owner the answer is still 202: the next owner starts with a full pass, and the backstop poll covers a wake nobody was listening for.

Required scope: write.

Path Parameters

accountId*string
Formatuuid

Request Body

application/json
  1. body
kinds?array<>
Items1 <= items

Response Body

OK

application/json
  1. response
kinds*array<>
Example Request
curl -X POST 'https://api.workwae.com/v1/accounts/6f1c2a4e-8b3d-4e5f-9a7b-1c2d3e4f5a6b/sync' \  -H 'Content-Type: application/json' \  -d '{}'
Example Response
{  "kinds": [    "mail"  ]}
POST
/v1/accounts/{accountId}/tokens

Runs against the live API with the key you enter: this change really happens. Use a key limited to a test account.

The token is returned once; it is not retrievable later.

Required scope: write.

Path Parameters

accountId*string
Formatuuid

Request Body

application/json
  1. body
ttlSeconds?integer
Range60 <= value <= 86400
Default900

Response Body

OK

application/json
  1. response
token*string
expiresAt*string
Formatdate-time
Example Request
curl -X POST 'https://api.workwae.com/v1/accounts/6f1c2a4e-8b3d-4e5f-9a7b-1c2d3e4f5a6b/tokens' \  -H 'Content-Type: application/json' \  -d '{}'
Example Response
{  "token": "string",  "expiresAt": "2026-05-04T09:30:00.000Z"}
POST
/v1/imap-accounts

Runs against the live API with the key you enter: this change really happens. Use a key limited to a test account.

The login is checked before anything is stored, for DAV too. Giving dav switches settings.calendarEnabled and contactsEnabled on for the halves found unless settings names them.

Required scope: write.

Request Body

application/json
  1. body
email*string
Formatemail
Lengthlength <= 320
displayName?string
Lengthlength <= 255
password*string
Length1 <= length <= 1024
smtpPassword?string
Length1 <= length <= 1024
imap?
smtp?|null
appendSent?boolean
dav?
externalRef?string
Lengthlength <= 255
settings?

Response Body

OK

application/json
  1. response
id*string
Formatuuid
externalRef*string|null
provider*AccountProvider
Value in"gmail""graph""imap"
email*string
displayName*string|null
oauthAppId*|null
cloud*|null
status*AccountStatus
Value in"active""paused""reauth_required""disabled"
statusReason*string|null
settings*
settingsOverride*
runtime*|null
imap*|null
auth*
initializedAt*|null
calendarInitializedAt*|null
contactsInitializedAt*|null
createdAt*string
Formatdate-time
updatedAt*string
Formatdate-time
Example Request
curl -X POST 'https://api.workwae.com/v1/imap-accounts' \  -H 'Content-Type: application/json' \  -d '{  "email": "ada@example.com",  "password": "string"}'
Example Response
{  "id": "c4e6a8b0-1d3f-4a5c-8e7b-9d1f3a5c7e9b",  "externalRef": "user_42",  "provider": "gmail",  "email": "string",  "displayName": "string",  "oauthAppId": "c6e11c75-050f-4212-9cff-bddb4fb07e36",  "cloud": "global",  "status": "active",  "statusReason": "string",  "settings": {    "bodyStorage": "none",    "syncWindowDays": 1,    "calendarEnabled": true,    "contactsEnabled": true,    "undoSendSeconds": 0,    "trackOpens": true,    "trackClicks": true,    "trackingHoneypot": true  },  "settingsOverride": {    "bodyStorage": "none",    "syncWindowDays": 1,    "calendarEnabled": true,    "contactsEnabled": true,    "undoSendSeconds": 0,    "trackOpens": true,    "trackClicks": true,    "trackingHoneypot": true  },  "runtime": {    "state": "pending",    "detail": "string",    "ownerInstanceId": "b31a377d-3f38-46d6-b670-15babc0f5625",    "updatedAt": "2026-05-04T09:30:00.000Z"  },  "imap": {    "imap": {      "host": "string",      "port": 0,      "security": "tls",      "user": "string"    },    "smtp": {      "host": "string",      "port": 0,      "security": "tls",      "user": "string"    },    "auth": "password",    "appendSent": true,    "dav": {      "calendarUrl": "string",      "contactsUrl": "string",      "user": "string",      "auth": "imap_password"    }  },  "auth": {    "method": "oauth",    "orgConnectionId": "17f753c8-b2ec-494b-9468-6e20a9a2f99c",    "delegateAccountId": "016ade53-f197-47ea-bd0e-48fda92e431f"  },  "initializedAt": "2026-05-04T09:30:00.000Z",  "calendarInitializedAt": "2026-05-04T09:30:00.000Z",  "contactsInitializedAt": "2026-05-04T09:30:00.000Z",  "createdAt": "2026-05-04T09:30:00.000Z",  "updatedAt": "2026-05-04T09:30:00.000Z"}
PATCH
/v1/accounts/{accountId}/imap-settings

Runs against the live API with the key you enter: this change really happens. Use a key limited to a test account.

Present fields replace the stored ones and the result is checked like a new account. An account in reauth_required becomes active again. A stored password is never sent to a new server or tried for another login: changing the IMAP server (host, port, security or user) needs password in the same request, changing the SMTP server (host, port, security or user) needs smtpPassword (or password when SMTP uses the IMAP password), switching SMTP from its own password to the IMAP one (smtpPassword: null) needs password, and adding DAV settings or changing their URLs, user or password source needs the password DAV logs in with (dav.password, or password when DAV uses the IMAP password). Sending dav: null removes the calendar and contacts; a CalDAV or CardDAV half the account did not have before switches settings.calendarEnabled or contactsEnabled on, unless the account's settings already name that key (an earlier opt-out stays); dav fields left out keep their stored values, or are discovered for an account without DAV settings. An account that signs in with OAuth always uses its provider's servers.

Required scope: write.

Path Parameters

accountId*string
Formatuuid

Request Body

application/json
  1. body
password?string
Length1 <= length <= 1024
smtpPassword?|null
imap?
smtp?|null
appendSent?boolean
dav?|null

Response Body

OK

application/json
  1. response
id*string
Formatuuid
externalRef*string|null
provider*AccountProvider
Value in"gmail""graph""imap"
email*string
displayName*string|null
oauthAppId*|null
cloud*|null
status*AccountStatus
Value in"active""paused""reauth_required""disabled"
statusReason*string|null
settings*
settingsOverride*
runtime*|null
imap*|null
auth*
initializedAt*|null
calendarInitializedAt*|null
contactsInitializedAt*|null
createdAt*string
Formatdate-time
updatedAt*string
Formatdate-time
Example Request
curl -X PATCH 'https://api.workwae.com/v1/accounts/6f1c2a4e-8b3d-4e5f-9a7b-1c2d3e4f5a6b/imap-settings' \  -H 'Content-Type: application/json' \  -d '{}'
Example Response
{  "id": "c4e6a8b0-1d3f-4a5c-8e7b-9d1f3a5c7e9b",  "externalRef": "user_42",  "provider": "gmail",  "email": "string",  "displayName": "string",  "oauthAppId": "c6e11c75-050f-4212-9cff-bddb4fb07e36",  "cloud": "global",  "status": "active",  "statusReason": "string",  "settings": {    "bodyStorage": "none",    "syncWindowDays": 1,    "calendarEnabled": true,    "contactsEnabled": true,    "undoSendSeconds": 0,    "trackOpens": true,    "trackClicks": true,    "trackingHoneypot": true  },  "settingsOverride": {    "bodyStorage": "none",    "syncWindowDays": 1,    "calendarEnabled": true,    "contactsEnabled": true,    "undoSendSeconds": 0,    "trackOpens": true,    "trackClicks": true,    "trackingHoneypot": true  },  "runtime": {    "state": "pending",    "detail": "string",    "ownerInstanceId": "b31a377d-3f38-46d6-b670-15babc0f5625",    "updatedAt": "2026-05-04T09:30:00.000Z"  },  "imap": {    "imap": {      "host": "string",      "port": 0,      "security": "tls",      "user": "string"    },    "smtp": {      "host": "string",      "port": 0,      "security": "tls",      "user": "string"    },    "auth": "password",    "appendSent": true,    "dav": {      "calendarUrl": "string",      "contactsUrl": "string",      "user": "string",      "auth": "imap_password"    }  },  "auth": {    "method": "oauth",    "orgConnectionId": "17f753c8-b2ec-494b-9468-6e20a9a2f99c",    "delegateAccountId": "016ade53-f197-47ea-bd0e-48fda92e431f"  },  "initializedAt": "2026-05-04T09:30:00.000Z",  "calendarInitializedAt": "2026-05-04T09:30:00.000Z",  "contactsInitializedAt": "2026-05-04T09:30:00.000Z",  "createdAt": "2026-05-04T09:30:00.000Z",  "updatedAt": "2026-05-04T09:30:00.000Z"}
GET
/v1/autoconfig

Runs in your browser against api.workwae.com with the key you enter. Use a read-only key, limited to a test account if you can.

dav carries CalDAV and CardDAV context URLs when a source names them; they need the login to resolve to the account's home sets, which creating the account does.

Required scope: read.

Query Parameters

email*string
Formatemail
Lengthlength <= 320

Response Body

OK

application/json
  1. response
source*AutoconfigSource
Value in"provider""autoconfig""ispdb""srv""mx"
imap*
smtp*|null
oauth*|null
dav*|null
Example Request
curl -X GET 'https://api.workwae.com/v1/autoconfig?email=ada%40example.com'
Example Response
{  "source": "provider",  "imap": {    "host": "string",    "port": 0,    "security": "tls",    "user": "string"  },  "smtp": {    "host": "string",    "port": 0,    "security": "tls",    "user": "string"  },  "oauth": "google",  "dav": {    "source": "provider",    "calendarUrl": "string",    "contactsUrl": "string"  }}