Admin Tools API
Internal automation API for Lumail administrators - execute admin tools across all organizations with a single endpoint
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 can list every organization and, with
X-Lumail-Organization, run the public v2/CLI API as that organization. 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).
Quick Start
Both operations live on a single endpoint: /api/v1/admin/tools.
List all available tools:
curl https://lumail.io/api/v1/admin/tools \
-H "Authorization: Bearer luma_YOUR_ADMIN_KEY"Execute a tool:
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_hereAdmin 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 usedis 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:
{
"success": true,
"usage": {
"execute": "POST /api/v1/admin/tools",
"body": { "tool": "<tool name>", "input": "<object matching inputSchema>" },
"example": { "tool": "list_orgs", "input": { "search": "acme", "pageSize": 20 } }
},
"total": 2,
"tools": [
{
"name": "list_orgs",
"description": "List and search every organization...",
"inputSchema": { "type": "object" }
},
{
"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:
{
"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:
{ "message": "Unknown tool: get_orgs. Available tools: list_orgs, get_org" }Example — invalid input:
{ "message": "Invalid input: Provide only one of id or slug" }Available Tools (2)
| Tool | Description |
|---|---|
list_orgs | List and search organizations with the same filters as Admin → Organizations. |
get_org | Get an organization's general information (plan, stats, members) and its configured sending domains. |
Admin keys can also call the public org-scoped API (/api/v2/... and the main CLI) by sending X-Lumail-Organization: <id-or-slug>. The CLI flag is --organization.
List Organizations
Tool: list_orgs
Same query as the admin organizations home page.
Parameters:
| Parameter | Type | Description |
|---|---|---|
search | string | Name, slug, tracking hash, or URL |
plan | string | free, creator, pro, premium, business |
status | string | unverified, automated, verified, blocked |
activity | string | active or all |
clickDomain | string | enabled |
doubleOptIn | string | enabled or disabled |
limits | string | approaching |
sort | string | asc or desc (default desc) |
sortBy | string | createdAt, name, plan, members, emails |
page | number | Default 1 |
pageSize | number | Default 10, max 50 |
curl -X POST https://lumail.io/api/v1/admin/tools \
-H "Authorization: Bearer luma_YOUR_ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{"tool": "list_orgs", "input": {"search": "acme", "plan": "pro", "pageSize": 20}}'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:
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:
{
"success": true,
"tool": "get_org",
"data": {
"organization": {
"id": "aBcD1234...",
"name": "Acme",
"slug": "acme",
"logo": "https://...",
"email": "[email protected]",
"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"
}
]
}
}subscriptionisnullwhen the organization has no active, trialing, or past-due subscription (free plan).domainsincludes 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.