API reference Markdown

Workspaces

A workspace holds prospects, campaigns, mailboxes and settings. Every token belongs to exactly one workspace. An API token belongs to the workspace it was generated in. An OAuth token belongs to the workspace picked on the consent screen.

Method Path Action
GET /api/v1/workspaces The workspace of this token

List workspaces#

curl "https://app.anymail.watch/api/v1/workspaces" \
  -H "Authorization: Bearer $ANYMAIL_TOKEN"
const res = await fetch("https://app.anymail.watch/api/v1/workspaces", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.ANYMAIL_TOKEN}`,
  },
});
console.log(res.status, await res.text());
import os
import requests

response = requests.request(
    "GET",
    "https://app.anymail.watch/api/v1/workspaces",
    headers={
        "Authorization": f"Bearer {os.environ['ANYMAIL_TOKEN']}",
    },
)
print(response.status_code, response.text)

Response 200

{
  "data": [
    { "id": "00000000-0000-0000-0000-000000000001", "name": "Example Ltd", "created_at": "2026-08-01T00:00:00.000+00:00", "current": true }
  ],
  "next_cursor": null
}

The list has one row today, the workspace of the token, with current: true. It is a list so that a token for several workspaces can use the same shape later.

This call needs only the read scope, so it is a cheap way to check a token. The CLI uses it on anymail login.

The X-Workspace header#

Send X-Workspace: <workspace id> on any request to state which workspace you mean. When it names another workspace than the one of the token, the request fails before it does anything.

curl "https://app.anymail.watch/api/v1/campaigns" \
  -H "Authorization: Bearer $ANYMAIL_TOKEN" \
  -H "X-Workspace: 00000000-0000-0000-0000-000000000001"
const res = await fetch("https://app.anymail.watch/api/v1/campaigns", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.ANYMAIL_TOKEN}`,
    "X-Workspace": "00000000-0000-0000-0000-000000000001",
  },
});
console.log(res.status, await res.text());
import os
import requests

response = requests.request(
    "GET",
    "https://app.anymail.watch/api/v1/campaigns",
    headers={
        "Authorization": f"Bearer {os.environ['ANYMAIL_TOKEN']}",
        "X-Workspace": "00000000-0000-0000-0000-000000000001",
    },
)
print(response.status_code, response.text)

Response 403 when the id does not match

{ "error": "This token does not have access to the workspace named in X-Workspace.", "code": "workspace_forbidden" }

The header is optional. Without it, the request uses the workspace of the token. Use it in a script that holds tokens for several workspaces, so that a mixed-up token fails loudly and does not write to the wrong workspace.