---
title: "List connected apps"
method: GET
path: "/v1/oauth/grants"
tags: ["Connected Apps"]
---

# List connected apps

`GET /v1/oauth/grants`

## Request

- Base URL: `https://api.mails.ai`
- URL: `https://api.mails.ai/v1/oauth/grants`
- Auth: HTTP bearer

**Requires scope:** `manage`. The apps connected to this workspace by signing in, whoever in it connected them: the mails CLI and apps such as Claude, ChatGPT or Cursor. Only those that can still act are listed, newest first: one revoked, or whose tokens have all expired or been signed out, is not. Settings › Connected apps in the dashboard shows the same apps to everyone in the workspace. There, a member can revoke the apps they connected, and an owner or admin can revoke any of them. Closed to apps connected by sign-in (403 `connected_app_not_allowed`), and to a key tied to one agent (403): use an API key with `manage` that is not tied to an agent, or the mails CLI.

## Query parameters

- `limit` integer
- `cursor` string

## Response `200`

A page of connected apps.

- object
  - `data` ConnectedApp[], required: The items on this page, at most `limit` of them.
    - `id` string, required: The sign-in's id (`oag_…`). Approving the same app again in the same workspace keeps it.
    - `client_id` string, required: The app's OAuth client id: the id it registered with, or the address of its client-ID document. The mails CLI's is `https://api.mails.ai/oauth/clients/cli`.
    - `client_name` string, nullable, required: The name the app gave itself; `mails CLI` for the mails CLI.
    - `first_party` boolean, required: `true` for the mails CLI, `false` for an app somebody connected by signing in (Claude, ChatGPT, Cursor …).
    - `scope` string, required: What the person approved: `full_access`, `send` or `read`.
    - `scopes` string[], required: What its tokens may do, in the API key scopes: `full_access` = `send` + `read` + `manage`, `send` = `send` + `read`, `read` = `read`. Never more than the role of the person who approved it gives an app now: a Member's apps never hold `manage`, and a Billing member's hold `read` only.
    - `created_at` string, date-time, required: When it was first approved.
    - `approved_at` string, date-time, required: When it was last approved.
    - `last_used_at` string, date-time, nullable, required: When one of its tokens was last used.
    - `created_api_keys` integer, required: API keys it created that still work (only the mails CLI, and keys it made, can create any). Revoking the app leaves them working: revoke them under API keys.
    - `created_webhooks` integer, required: Webhook endpoints it created (only the mails CLI, and keys it made, can create any). Revoking the app leaves them in place.
    - `signing_secrets_known` integer, required: Other webhook endpoints still signing with a secret it was shown. Revoking the app leaves those secrets in use: rotate them (`POST /v1/webhooks/{id}/rotate-secret`).
  - `has_more` boolean, required: True when more items follow this page: pass `next_cursor` as `cursor` to get them.
  - `next_cursor` string: Pass as `cursor` to fetch the next page. Absent on the last page.

## Other responses

- `400`: Invalid request — malformed JSON or a field failed validation. Also `feature_not_enabled` when this server has a feature switched off (custom domains before they are available).
- `401`: Missing or invalid API key.
- `403`: The API key lacks the required scope (`insufficient_scope`), or the token belongs to an app connected by sign-in and this operation is closed to connected apps (`connected_app_not_allowed`).
- `500`: Internal server error.

---

[API](https://skmtc.dev/mails/apis/mails-ai-api.md) · [All operations](https://skmtc.dev/mails/apis/mails-ai-api/llms.txt) · [OpenAPI document](https://skmtc.dev/mails/apis/mails-ai-api/revisions/4d4930a8c33b?raw)
