connected apps.md


title: "Connected Apps" description: "List the apps and MCP clients people in your organization connected to MachineMail with OAuth, and disconnect one to revoke its tokens immediately." canonical: "https://machinemail.dev/docs/reference/api/connected-apps"

Connected Apps

List the apps and MCP clients people in your organization connected to MachineMail with OAuth, and disconnect one to revoke its tokens immediately.

Source: https://machinemail.dev/docs/reference/api/connected-apps

Method Path Summary
GET /v0/oauth-grants List Connected Apps
DELETE /v0/oauth-grants/{grant_id} Disconnect App

List Connected Apps

GET /v0/oauth-grants

Apps and MCP clients people in the organization connected with OAuth. Requires an organization-scoped credential with api_key_read; pod, inbox and sandbox credentials get 403.

Authentication: Authorization: Bearer <api key> or the dashboard mm_session cookie. Permission: none beyond a valid key.

Query parameters

Field Type Description
limit integer Maximum number of items to return. Default 50, maximum 500; larger values are capped.
page_token string next_page_token from the previous page.
ascending boolean Sort oldest first.

Response

200 A page of grants (application/json)

Field Type Description
count integer required Number of items returned.
limit integer Maximum number of items per page. Default 50, maximum 500; larger values are capped.
next_page_token string Page token for pagination. Absent on the last page.
oauth_grants OAuthGrant[] required Newest first unless ascending is set.

Each item of oauth_grants is a OAuthGrant:

Field Type Description
grant_id string required ID of the grant (oag_...).
client_id string required
client_name string | null required Self-reported by the client at registration.
client_uri string | null required
logo_uri string | null required
registration "dynamic" | "metadata_document" required
user_id string required Who approved it.
user_email string | null required
scopes ("inboxes.read" | "inboxes.write" | "messages.read" | "messages.send" | "messages.write" | "webhooks.read" | "webhooks.write" | "domains.read" | "domains.write" | "lists.read" | "lists.write" | "metrics.read" | "pods.read" | "pods.write" | "api_keys.read" | "api_keys.write")[] required
resource string required Audience of its access tokens.
pod_id string | null required Set when the grant is limited to one pod.
inbox_id string | null required Set when the grant is limited to one inbox.
created_at string (date-time) required
last_used_at string (date-time) | null required Last token refresh or API call (updated at most once a minute).
expires_at string (date-time) required When the current refresh token expires unless it is used (30 days after the last refresh).

Errors

Status Meaning
400 Invalid request: error.type is validation and error.param names the field.
401 Missing, invalid, expired or revoked credential.
403 The credential lacks the permission or scope for this request (error.type forbidden), or MachineMail suspended the organization or its sending (account_suspended: error.message says what still works; do not retry or re-register).
500 Unexpected server error.

Error bodies use the error envelope.

Example

curl "https://api.machinemail.dev/v0/oauth-grants" \
  -H "Authorization: Bearer $MACHINEMAIL_API_KEY"
{
  "count": 1,
  "limit": 50,
  "next_page_token": "eyJvIjo1MH0",
  "oauth_grants": [
    {
      "grant_id": "string",
      "client_id": "my-client-id",
      "client_name": "string",
      "client_uri": "https://example.com",
      "logo_uri": "https://example.com",
      "registration": "dynamic",
      "user_id": "usr_01k6x3j0rw0000n8w4yc0g3q5s",
      "user_email": "agent@machinemail.dev",
      "scopes": ["inboxes.read"],
      "resource": "string",
      "pod_id": "pod_01k6x2m9qd0001b8j4mr0w3d5f",
      "inbox_id": "agent@machinemail.dev",
      "created_at": "2026-10-01T12:00:00.000Z",
      "last_used_at": "2026-10-01T12:00:00.000Z",
      "expires_at": "2026-10-01T12:00:00.000Z"
    }
  ]
}

Disconnect App

DELETE /v0/oauth-grants/{grant_id}

Revokes the grant: its refresh token and every access token issued from it stop working immediately (401 on /mcp and /v0). Returns the grant as it was. Requires an organization-scoped credential with api_key_delete.

Authentication: Authorization: Bearer <api key> or the dashboard mm_session cookie. Permission: none beyond a valid key.

Path parameters

Field Type Description
grant_id string required ID of the grant (oag_...).

Response

200 The revoked grant (application/json)

Errors

Status Meaning
401 Missing, invalid, expired or revoked credential.
403 The credential lacks the permission or scope for this request (error.type forbidden), or MachineMail suspended the organization or its sending (account_suspended: error.message says what still works; do not retry or re-register).
404 Not found. Also returned for resources outside the credential scope.
500 Unexpected server error.

Error bodies use the error envelope.

Example

curl -X DELETE "https://api.machinemail.dev/v0/oauth-grants/string" \
  -H "Authorization: Bearer $MACHINEMAIL_API_KEY"
{
  "grant_id": "string",
  "client_id": "my-client-id",
  "client_name": "string",
  "client_uri": "https://example.com",
  "logo_uri": "https://example.com",
  "registration": "dynamic",
  "user_id": "usr_01k6x3j0rw0000n8w4yc0g3q5s",
  "user_email": "agent@machinemail.dev",
  "scopes": ["inboxes.read"],
  "resource": "string",
  "pod_id": "pod_01k6x2m9qd0001b8j4mr0w3d5f",
  "inbox_id": "agent@machinemail.dev",
  "created_at": "2026-10-01T12:00:00.000Z",
  "last_used_at": "2026-10-01T12:00:00.000Z",
  "expires_at": "2026-10-01T12:00:00.000Z"
}