---
title: "Create a key for an agent"
description: "Create a narrow MachineMail API key for one agent from the dashboard or the API: pick its scope and permissions, copy it once, hand it over, revoke it later."
canonical: "https://machinemail.dev/docs/guides/api-key-for-an-agent"
---

# Create a key for an agent

> Create a narrow MachineMail API key for one agent from the dashboard or the API: pick its scope and permissions, copy it once, hand it over, revoke it later.

Source: https://machinemail.dev/docs/guides/api-key-for-an-agent

Give each agent its own key, scoped to what it needs. A leaked inbox key exposes one mailbox, not your whole organization. Each step shows the dashboard first and the API second.

## Pick the scope

The scope decides what the key can reach. It is fixed when you create the key.

**Dashboard**

Open [machinemail.dev/app/api-keys?create=1](https://machinemail.dev/app/api-keys?create=1). You can also go to **API keys** and choose **Create key**, or choose **New API key** in the command menu (⌘K).

Give the key a **Name** that says which agent uses it, such as `Support agent (prod)`. Then pick the **Scope**:

- **Organization (can mint keys)**: everything in the organization. Only organization keys can create other keys.
- **Inbox ·** followed by an address: that one inbox, its messages, threads and drafts. This is the best choice for a single agent.

**API**

The route you create the key on sets its scope. Creating keys needs an organization key with `api_key_create`.

| Scope        | Route                                  |
| ------------ | -------------------------------------- |
| Organization | `POST /v0/api-keys`                    |
| Pod          | `POST /v0/pods/{pod_id}/api-keys`      |
| Inbox        | `POST /v0/inboxes/{inbox_id}/api-keys` |

## Pick the permissions

Without a permission list, a key can do everything its scope allows. A list narrows it further.

**Dashboard**

Pick one of the **Permissions** presets:

| Preset                        | The key can                                                                                     |
| ----------------------------- | ----------------------------------------------------------------------------------------------- |
| **Full access for the scope** | Do everything its scope allows.                                                                 |
| **Read only**                 | Read inboxes and messages (`inbox_read`, `message_read`).                                       |
| **Agent: read, send, label**  | Read, send, and change labels (`inbox_read`, `message_read`, `message_send`, `message_update`). |

Leave the **inbound\_raw** box unticked for agents. It lets the key inject raw test mail, which is never authenticated.

**API**

Pass `permissions`, an object of booleans or an array of names. Leave it out for full access within the scope.

```json title="Permissions for an agent that drafts but never sends"
{ "inbox_read": true, "message_read": true, "thread_read": true, "draft_create": true }
```

[API keys](https://machinemail.dev/docs/concepts/api-keys#permissions) lists every permission.

`inbound_raw` is never part of full access. Only the dashboard, or a key that already has `inbound_raw`, can grant it.

## Create the key and copy it

The full key is shown once. MachineMail stores only a hash of it.

**Dashboard**

1. Choose **Create key**.
2. The **Save your key** dialog shows the key. Choose **Copy**.
3. Store it somewhere safe, then choose **I've saved it**.

**API**

```bash title="Terminal"
curl https://api.machinemail.dev/v0/inboxes/support-agent@machinemail.dev/api-keys \
  -H "Authorization: Bearer $MACHINEMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Support agent (prod)",
    "permissions": { "inbox_read": true, "message_read": true, "message_send": true, "message_update": true },
    "expires_at": "2027-01-01T00:00:00Z"
  }'
```

The response's `api_key` is the full key. It is never returned again.

If you lose the key, revoke it and create another.

## Give it to the agent

Put the key in the agent's secret store, never in a prompt or a file you share. The agent sends it as `Authorization: Bearer` followed by the key. An MCP client sends it the same way, as a header: see [Client setup](https://machinemail.dev/docs/agents/clients).

## Revoke it when you're done

A revoked key stops working at once. Requests that use it get 401.

**Dashboard**

On [API keys](https://machinemail.dev/app/api-keys), find the key by its **Name**, the start of the **Key**, its **Scope** and when it was **Last used**. Choose **Revoke**, type `DELETE` and choose **Revoke key**.

**API**

```bash title="Terminal"
curl -X DELETE https://api.machinemail.dev/v0/api-keys/key_01m4fy8hmg0000dgevarwczcf7 \
  -H "Authorization: Bearer $MACHINEMAIL_API_KEY"
```

> **Not in the dashboard:** Pod scope, a custom permission list, and renaming or changing a key's permissions are API only. The dashboard can set an expiry (Expires, in the create dialog). The dashboard can't rotate a key:
> create a new one, switch the agent over, then revoke the old one.

## Troubleshooting

| Symptom                                              | Fix                                                                                 |
| ---------------------------------------------------- | ----------------------------------------------------------------------------------- |
| The agent gets `403` with "lacks the ... permission" | The key's permission list is too narrow. Create a key with the permission it needs. |
| The agent gets `404` for an inbox                    | The inbox is outside the key's scope.                                               |
| The agent gets `401`                                 | The key was revoked, expired or mistyped.                                           |
| An inbox is missing from **Scope**                   | The list shows your organization's inboxes. Create the inbox first.                 |

## Related

- [API keys](https://machinemail.dev/docs/concepts/api-keys)
- [Connect an agent without code](https://machinemail.dev/docs/guides/connect-an-agent)
- [Approve drafts before they send](https://machinemail.dev/docs/guides/approve-drafts)
