The Admin Tools API is an **internal, admin-only** REST interface for platform automation. It exposes a registry of tools behind a single endpoint, secured by dedicated admin API keys.

> **Warning:** Admin API keys grant **read access across every organization** on the platform. They are reserved for Lumail administrators — this API is not part of the public API and is not available to regular accounts. If you are looking for the customer-facing API, see [Tools API (v2)](/docs/api-reference/v2-tools).

## Quick Start

Both operations live on a single endpoint: `/api/v1/admin/tools`.

**List all available tools:**

```bash
curl https://lumail.io/api/v1/admin/tools \
  -H "Authorization: Bearer luma_YOUR_ADMIN_KEY"
```

**Execute a tool:**

```bash
curl -X POST https://lumail.io/api/v1/admin/tools \
  -H "Authorization: Bearer luma_YOUR_ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -d '{"tool": "get_org", "input": {"slug": "acme"}}'
```

## Authentication

All requests require an admin API key as a Bearer token:

```
Authorization: Bearer luma_your_admin_key_here
```

Admin keys are managed from **Admin → API Keys** (`/admin/api-keys`) by platform administrators:

- Keys use the `luma_` prefix followed by 64 hex characters.
- The plaintext key is shown **once** at creation — only a sha256 hash is stored.
- Revoking a key from the admin panel cuts off access immediately.
- `Last used` is tracked automatically (background write, throttled to once per minute).

## Listing Tools

`GET /api/v1/admin/tools` is self-describing: it returns every registered tool with its JSON input schema, plus a `usage` block that shows how to execute them.

**Response:**

```json
{
  "success": true,
  "usage": {
    "execute": "POST /api/v1/admin/tools",
    "body": { "tool": "<tool name>", "input": "<object matching inputSchema>" },
    "example": { "tool": "get_org", "input": { "slug": "acme" } }
  },
  "total": 1,
  "tools": [
    {
      "name": "get_org",
      "description": "Get an organization's general information...",
      "inputSchema": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "description": "Organization ID" },
          "slug": { "type": "string", "description": "Organization slug" }
        }
      }
    }
  ]
}
```

## Executing Tools

`POST /api/v1/admin/tools` with a JSON body:

| Field   | Type   | Required | Description                                  |
| ------- | ------ | -------- | -------------------------------------------- |
| `tool`  | string | Yes      | Name of the tool to execute (e.g. `get_org`) |
| `input` | object | No       | Input matching the tool's `inputSchema`      |

The input is validated against the tool's schema before execution — invalid input returns a `400` with the exact validation issues.

**Success response:**

```json
{
  "success": true,
  "tool": "get_org",
  "data": {
    /* tool-specific response */
  }
}
```

## Errors

| Status | Meaning                                                      |
| ------ | ------------------------------------------------------------ |
| `400`  | Invalid input — the message lists each failing field and why |
| `401`  | Missing, malformed, or revoked admin API key                 |
| `404`  | Unknown tool — the message lists the available tool names    |
| `429`  | IP rate limit exceeded — check the `Retry-After` header      |

**Example — unknown tool:**

```json
{ "message": "Unknown tool: get_orgs. Available tools: get_org" }
```

**Example — invalid input:**

```json
{ "message": "Invalid input: Provide only one of id or slug" }
```

## Available Tools (1)

| Tool      | Description                                                                                          |
| --------- | ---------------------------------------------------------------------------------------------------- |
| `get_org` | Get an organization's general information (plan, stats, members) and its configured sending domains. |

---

### Get Organization

**Tool:** `get_org`

Get an organization's general information (plan, stats, members) and its configured sending domains with DNS verification status. Provide either `id` or `slug` — never both.

**Parameters:**

| Parameter | Type   | Required | Description       |
| --------- | ------ | -------- | ----------------- |
| `id`      | string | No\*     | Organization ID   |
| `slug`    | string | No\*     | Organization slug |

\* Exactly one of `id` or `slug` is required.

**Example:**

```bash
curl -X POST https://lumail.io/api/v1/admin/tools \
  -H "Authorization: Bearer luma_YOUR_ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -d '{"tool": "get_org", "input": {"slug": "acme"}}'
```

**Response:**

```json
{
  "success": true,
  "tool": "get_org",
  "data": {
    "organization": {
      "id": "aBcD1234...",
      "name": "Acme",
      "slug": "acme",
      "logo": "https://...",
      "email": "team@acme.com",
      "timezone": "Europe/Paris",
      "verified": true,
      "createdAt": "2026-01-01T00:00:00.000Z"
    },
    "subscription": {
      "plan": "PREMIUM",
      "status": "active",
      "periodStart": "2026-07-01T00:00:00.000Z",
      "periodEnd": "2026-08-01T00:00:00.000Z",
      "cancelAtPeriodEnd": false,
      "customLimits": null
    },
    "stats": {
      "members": 3,
      "subscribers": 1200,
      "campaigns": 42
    },
    "domains": [
      {
        "id": "dom_...",
        "domain": "mail.acme.com",
        "status": "VERIFIED",
        "region": "EU_WEST_1",
        "sesRecords": [
          {
            "name": "_amazonses.mail.acme.com",
            "type": "TXT",
            "value": "...",
            "status": "verified"
          }
        ],
        "fallbackPriority": null,
        "verificationRequestedAt": null,
        "createdAt": "2026-02-01T00:00:00.000Z"
      }
    ]
  }
}
```

- `subscription` is `null` when the organization has no active, trialing, or past-due subscription (free plan).
- `domains` includes the full SES DNS records with per-record verification status — useful to debug deliverability without impersonating the account.

## Adding New Tools

Tools live in an extensible registry in `src/lib/admin-tools/`. See `src/lib/admin-tools/README.md` in the repository for the step-by-step guide — new tools automatically appear in the `GET` listing, the execution endpoint, and the `/admin/api-keys` usage panel.
