Organization connections

Register Google Workspace delegation or Microsoft 365 app-only access, then list the directory and add mailboxes as accounts.

Guides: Organization connections.

MethodPathOperationScope
GET/v1/org-connectionsList organization connectionsadmin
POST/v1/org-connectionsRegister an organization connectionadmin
GET/v1/org-connections/{connectionId}Get an organization connectionadmin
PATCH/v1/org-connections/{connectionId}Update an organization connectionadmin
DELETE/v1/org-connections/{connectionId}Delete an organization connectionadmin
POST/v1/org-connections/{connectionId}/consentStart Microsoft admin consentadmin
POST/v1/org-connections/{connectionId}/testTest an organization connectionadmin
GET/v1/org-connections/{connectionId}/directory-entriesList the directory's mailboxesadmin
POST/v1/org-connections/{connectionId}/accountsAdd mailboxes as accountswrite
GET
/v1/org-connections

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: admin.

Response Body

OK

application/json
  1. response
items*array<>
Example Request
curl -X GET 'https://api.workwae.com/v1/org-connections'
Example Response
{  "items": [    {      "id": "c4e6a8b0-1d3f-4a5c-8e7b-9d1f3a5c7e9b",      "kind": "google_delegation",      "name": "string",      "clientId": "string",      "status": "pending_consent",      "statusDetail": "string",      "checkedAt": "2026-05-04T09:30:00.000Z",      "google": {        "domain": "string",        "serviceAccountEmail": "string",        "directoryAdmin": "string",        "scopes": [          "string"        ]      },      "microsoft": {        "cloud": "global",        "credentialType": "platform",        "directoryId": "string",        "permissions": [          {            "name": "string",            "isRequired": true          }        ]      },      "accounts": 0,      "createdAt": "2026-05-04T09:30:00.000Z",      "updatedAt": "2026-05-04T09:30:00.000Z"    }  ]}
POST
/v1/org-connections

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

Google: the service account key is checked and sealed; authorize the returned clientId for the returned scopes in the Admin console, then test. Microsoft: a platform connection starts in pending_consent (POST .../consent); a tenant app with a directoryId starts unverified.

Required scope: admin.

Request Body

application/json
  1. body
kind*unknown
name*string
Length1 <= length <= 100
serviceAccountKey*string
Length2 <= length <= 20000
domain*string
Length3 <= length <= 253
calendarEnabled?boolean
Defaulttrue
contactsEnabled?boolean
Defaultfalse
directoryAdmin?string
Formatemail
Lengthlength <= 320

Response Body

OK

application/json
  1. response
id*string
Formatuuid
kind*OrgConnectionKind
Value in"google_delegation""microsoft_app"
name*string
clientId*string
status*OrgConnectionStatus
Value in"pending_consent""unverified""active""failing"
statusDetail*string|null
checkedAt*|null
google*|null
microsoft*|null
accounts*integer
createdAt*string
Formatdate-time
updatedAt*string
Formatdate-time
Example Request
curl -X POST 'https://api.workwae.com/v1/org-connections' \  -H 'Content-Type: application/json' \  -d '{  "kind": "google_delegation",  "name": "string",  "serviceAccountKey": "string",  "domain": "string"}'
Example Response
{  "id": "c4e6a8b0-1d3f-4a5c-8e7b-9d1f3a5c7e9b",  "kind": "google_delegation",  "name": "string",  "clientId": "string",  "status": "pending_consent",  "statusDetail": "string",  "checkedAt": "2026-05-04T09:30:00.000Z",  "google": {    "domain": "string",    "serviceAccountEmail": "string",    "directoryAdmin": "string",    "scopes": [      "string"    ]  },  "microsoft": {    "cloud": "global",    "credentialType": "platform",    "directoryId": "string",    "permissions": [      {        "name": "string",        "isRequired": true      }    ]  },  "accounts": 0,  "createdAt": "2026-05-04T09:30:00.000Z",  "updatedAt": "2026-05-04T09:30:00.000Z"}
GET
/v1/org-connections/{connectionId}

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: admin.

Path Parameters

connectionId*string
Formatuuid

Response Body

OK

application/json
  1. response
id*string
Formatuuid
kind*OrgConnectionKind
Value in"google_delegation""microsoft_app"
name*string
clientId*string
status*OrgConnectionStatus
Value in"pending_consent""unverified""active""failing"
statusDetail*string|null
checkedAt*|null
google*|null
microsoft*|null
accounts*integer
createdAt*string
Formatdate-time
updatedAt*string
Formatdate-time
Example Request
curl -X GET 'https://api.workwae.com/v1/org-connections/d2c1cc43-b491-4d08-8b29-11a5f88293ab'
Example Response
{  "id": "c4e6a8b0-1d3f-4a5c-8e7b-9d1f3a5c7e9b",  "kind": "google_delegation",  "name": "string",  "clientId": "string",  "status": "pending_consent",  "statusDetail": "string",  "checkedAt": "2026-05-04T09:30:00.000Z",  "google": {    "domain": "string",    "serviceAccountEmail": "string",    "directoryAdmin": "string",    "scopes": [      "string"    ]  },  "microsoft": {    "cloud": "global",    "credentialType": "platform",    "directoryId": "string",    "permissions": [      {        "name": "string",        "isRequired": true      }    ]  },  "accounts": 0,  "createdAt": "2026-05-04T09:30:00.000Z",  "updatedAt": "2026-05-04T09:30:00.000Z"}
PATCH
/v1/org-connections/{connectionId}

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

Replacing a credential or the authorized scopes makes the connection unverified until the next test.

Required scope: admin.

Path Parameters

connectionId*string
Formatuuid

Request Body

application/json
  1. body
name?string
Length1 <= length <= 100
serviceAccountKey?string
Length2 <= length <= 20000
calendarEnabled?boolean
contactsEnabled?boolean
directoryAdmin?|null
clientSecret?string
Length1 <= length <= 1024
certificate?string
Length1 <= length <= 20000
privateKey?string
Length1 <= length <= 20000
directoryId?string
Length1 <= length <= 100

Response Body

OK

application/json
  1. response
id*string
Formatuuid
kind*OrgConnectionKind
Value in"google_delegation""microsoft_app"
name*string
clientId*string
status*OrgConnectionStatus
Value in"pending_consent""unverified""active""failing"
statusDetail*string|null
checkedAt*|null
google*|null
microsoft*|null
accounts*integer
createdAt*string
Formatdate-time
updatedAt*string
Formatdate-time
Example Request
curl -X PATCH 'https://api.workwae.com/v1/org-connections/d2c1cc43-b491-4d08-8b29-11a5f88293ab' \  -H 'Content-Type: application/json' \  -d '{}'
Example Response
{  "id": "c4e6a8b0-1d3f-4a5c-8e7b-9d1f3a5c7e9b",  "kind": "google_delegation",  "name": "string",  "clientId": "string",  "status": "pending_consent",  "statusDetail": "string",  "checkedAt": "2026-05-04T09:30:00.000Z",  "google": {    "domain": "string",    "serviceAccountEmail": "string",    "directoryAdmin": "string",    "scopes": [      "string"    ]  },  "microsoft": {    "cloud": "global",    "credentialType": "platform",    "directoryId": "string",    "permissions": [      {        "name": "string",        "isRequired": true      }    ]  },  "accounts": 0,  "createdAt": "2026-05-04T09:30:00.000Z",  "updatedAt": "2026-05-04T09:30:00.000Z"}
DELETE
/v1/org-connections/{connectionId}

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

Required scope: admin.

Path Parameters

connectionId*string
Formatuuid

Response Body

OK

application/json
  1. response
Example Request
curl -X DELETE 'https://api.workwae.com/v1/org-connections/d2c1cc43-b491-4d08-8b29-11a5f88293ab'
Example Response
null
POST
/v1/org-connections/{connectionId}/consent

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

Returns the URL an administrator of the directory grants consent at. Afterwards the browser returns to redirectUri with status=success|error, connection_id, error and state; the connection records the consenting directory and is tested. A tenant app uses /adminconsent. The platform app is consented through a sign-in (authorize with prompt=admin_consent) and records the directory named by the sign-in's ID token; it can only be started from the console, and the console user who started it has to be signed in, in the browser that returns, for the directory to be recorded. Errors on return include access_denied, consent_failed, consent_unverified, directory_mismatch and directory_already_connected (another platform connection holds the directory).

Required scope: admin.

Path Parameters

connectionId*string
Formatuuid

Request Body

application/json
  1. body
redirectUri*string
Formaturi
state?string
Lengthlength <= 1024

Response Body

OK

application/json
  1. response
consentUrl*string
Formaturi
Example Request
curl -X POST 'https://api.workwae.com/v1/org-connections/d2c1cc43-b491-4d08-8b29-11a5f88293ab/consent' \  -H 'Content-Type: application/json' \  -d '{  "redirectUri": "https://app.example.com/mail/connected"}'
Example Response
{  "consentUrl": "https://app.example.com/"}
POST
/v1/org-connections/{connectionId}/test

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

Requests a token the way accounts will and reports each check; the connection becomes active or failing. A passing test returns accounts that were moved to reauth_required to active. Google impersonates user (default: the directory admin).

Required scope: admin.

Path Parameters

connectionId*string
Formatuuid

Request Body

application/json
  1. body
user?string
Formatemail
Lengthlength <= 320

Response Body

OK

application/json
  1. response
connection*
checks*array<>
Example Request
curl -X POST 'https://api.workwae.com/v1/org-connections/d2c1cc43-b491-4d08-8b29-11a5f88293ab/test' \  -H 'Content-Type: application/json' \  -d '{}'
Example Response
{  "connection": {    "id": "c4e6a8b0-1d3f-4a5c-8e7b-9d1f3a5c7e9b",    "kind": "google_delegation",    "name": "string",    "clientId": "string",    "status": "pending_consent",    "statusDetail": "string",    "checkedAt": "2026-05-04T09:30:00.000Z",    "google": {      "domain": "string",      "serviceAccountEmail": "string",      "directoryAdmin": "string",      "scopes": [        "string"      ]    },    "microsoft": {      "cloud": "global",      "credentialType": "platform",      "directoryId": "string",      "permissions": [        {          "name": "string",          "isRequired": true        }      ]    },    "accounts": 0,    "createdAt": "2026-05-04T09:30:00.000Z",    "updatedAt": "2026-05-04T09:30:00.000Z"  },  "checks": [    {      "name": "string",      "isOk": true,      "isRequired": true,      "detail": "string"    }  ]}
GET
/v1/org-connections/{connectionId}/directory-entries

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.

Microsoft: Graph /users (needs User.Read.All). Google: the Admin SDK users.list as the directory admin (needs admin.directory.user.readonly). query matches the start of names and addresses. A nextCursor is good for an hour, on this connection only.

Required scope: admin.

Path Parameters

connectionId*string
Formatuuid

Query Parameters

cursor?string
Length1 <= length <= 512
limit?integer
Range1 <= value <= 200
Default100
query?string
Lengthlength <= 100

Response Body

OK

application/json
  1. response
items*array<>
nextCursor*|null
Example Request
curl -X GET 'https://api.workwae.com/v1/org-connections/d2c1cc43-b491-4d08-8b29-11a5f88293ab/directory-entries'
Example Response
{  "items": [    {      "id": "string",      "email": "string",      "displayName": "string",      "accountId": "6f1c2a4e-8b3d-4e5f-9a7b-1c2d3e4f5a6b"    }  ],  "nextCursor": "eyJ0eG5pZCI6IjQyIiwiaWQiOjEwMDF9"}
POST
/v1/org-connections/{connectionId}/accounts

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

Each mailbox is checked through the connection before its account is created (Google: a delegated token for it; Microsoft: its inbox). items holds one result per mailbox, in request order. Per-mailbox failures are reported there with the reason the API would answer with, e.g. invalid_grant (no such user), consent_revoked (the scopes or permissions are not granted), provider_forbidden or provider_not_found (no mailbox access), plan_limit_accounts (the plan's account limit was reached part way through; the mailboxes before it are created).

Required scope: write.

Path Parameters

connectionId*string
Formatuuid

Request Body

application/json
  1. body
mailboxes*array<>
Items1 <= items <= 100
settings?

Response Body

OK

application/json
  1. response
items*array<>
Example Request
curl -X POST 'https://api.workwae.com/v1/org-connections/d2c1cc43-b491-4d08-8b29-11a5f88293ab/accounts' \  -H 'Content-Type: application/json' \  -d '{  "mailboxes": [    {      "email": "ada@example.com"    }  ]}'
Example Response
{  "items": [    {      "email": "string",      "status": "created",      "accountId": "6f1c2a4e-8b3d-4e5f-9a7b-1c2d3e4f5a6b",      "error": {        "reason": "string",        "message": "string"      }    }  ]}