---
title: "API keys and scoped keys for AI agents"
url: "https://conecto.chat/docs/keys"
markdown: "https://conecto.chat/docs/keys.md"
description: "How Conecto's keys work: the header, a key for each job limited by area, tool, network and end date, budgets a line of keys shares, and revoking."
section: "Concepts"
published: 2026-10-19
updated: 2026-10-19
---

# Keys and scopes

A key says which account an agent acts for. Give each bot or job a key of its own, limited to what it needs.

## Sending the key

Send the key as a bearer token on every call that reads or changes the business's data:

Header:

```text
Authorization: Bearer conecto_sk_...
```

`X-Api-Key: conecto_sk_...` works too, for tools that put a key in a header of their own, like Power Platform connectors. Over MCP, set the same `Authorization` header when you add the server.

A key starts with `conecto_sk_`. It is shown once, when it is made. Conecto keeps only its SHA-256 hash and its last four characters.

> **Warning:** A key spends the balance. Keep it out of prompts, logs and code you share, and revoke it as soon as it leaks.

The routes that describe Conecto answer without a key: the index, the lists of areas and tools, SKILL.md, the OpenAPI files, and an MCP server's `initialize` and `tools/list`.

## Making a key

`POST /v1/keys` makes a key for another bot or job, from a key that works. The new key is never wider than the key that makes it.

curl:

```bash
curl -X POST https://api.conecto.chat/v1/keys \
  -H "Authorization: Bearer $CONECTO_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "bot_name": "Support bot",
    "areas": ["helpdesk"],
    "drafts_only": true,
    "expires_at": "2027-01-31T18:00:00Z",
    "networks": ["203.0.113.0/24"],
    "team": "Support",
    "accountable": "Lena Brandt"
  }'
```

Python:

```python
import os
import requests

reply = requests.post(
    "https://api.conecto.chat/v1/keys",
    headers={"Authorization": f"Bearer {os.environ['CONECTO_KEY']}"},
    json={
        "bot_name": "Support bot",
        "areas": ["helpdesk"],
        "drafts_only": True,
        "expires_at": "2027-01-31T18:00:00Z",
        "networks": ["203.0.113.0/24"],
        "team": "Support",
        "accountable": "Lena Brandt",
    },
)
print(reply.status_code, reply.json())
```

JavaScript:

```javascript
const reply = await fetch("https://api.conecto.chat/v1/keys", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.CONECTO_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    bot_name: "Support bot",
    areas: ["helpdesk"],
    drafts_only: true,
    expires_at: "2027-01-31T18:00:00Z",
    networks: ["203.0.113.0/24"],
    team: "Support",
    accountable: "Lena Brandt",
  }),
});
console.log(reply.status, await reply.json());
```

```json
{
  "key_id": 4128,
  "key": "conecto_sk_9d2e7b4a1c6f3e8b5a0d7c2f9e4b1a6d",
  "key_note": "Shown once.",
  "daily_budget_usd": "$20.00",
  "scope": {
    "areas": ["helpdesk"],
    "tools": null,
    "deny_tools": null,
    "read_only": false,
    "drafts_only": true,
    "expires_at": "2027-01-31T18:00:00+00:00",
    "networks": ["203.0.113.0/24"],
    "team": "Support",
    "accountable": "Lena Brandt"
  }
}
```

### Every field

| Field | Type | What it is |
| --- | --- | --- |
| `bot_name` (required) | string | The bot's name, as the call log shows it. 1 to 80 characters. |
| `runtime` | string | What the agent runs in, like n8n or Claude Code. It shows beside the key. |
| `daily_budget_usd` | number | Its daily budget. On an account with an owner email, at most this key's. |
| `areas` | array of strings | The areas it works in. |
| `tools` | array of strings | The only tools it may run. |
| `deny_tools` | array of strings | Tools it may not run. |
| `read_only` | boolean | It only reads. |
| `drafts_only` | boolean | Every change it makes waits for a person. |
| `expires_in_days` | integer | It stops working after this many days. |
| `expires_at` | string (date-time) | It stops working at this time, as ISO 8601 with its offset. |
| `networks` | array of strings | The addresses or ranges it may be used from. |
| `team` | string | Its team. Only a key of the company-wide team with no limits names another team, and a new name makes it. |
| `accountable` | string | The person who answers for the key. |

### The rules

- A key makes keys only within its own scope and team. A request for more answers `scope_too_wide`.
- Keys made from a key form a line, and the whole line shares the daily budget of its first key. [Limits](https://conecto.chat/docs/limits.md#daily-budget) explains the budgets.
- On an account with an owner email, a new key's daily budget is at most that of the key making it.
- Only a key of the company-wide team with no areas, tool list or read-only limit names another team. A new team name makes the team.
- An account has at most 25 keys that work. More answers `limit_reached`.

## Scoped keys

A key limited to areas, to a list of tools or to reading is a scoped key. It stays inside what it was given:

- Of the account tools, it keeps `account_balance`, `account_get_call`, `account_list_calls` and `account_dashboard_link`, since the others reach every area. Its maker can name others in `tools`.
- `GET /v1/calls` shows it its own calls only.
- Changing the limits or auto-reload answers `key_scope`.

`networks` keeps any key to some addresses or ranges, like `203.0.113.0/24`, up to 20 of them. A call from anywhere else answers `network_not_allowed`. An end date, `expires_in_days` or `expires_at`, at most 366 days ahead, ends a key on its own, and a call after that answers `key_expired`.

`drafts_only` makes every change the key asks for wait for a person, while its reads go through. [Approvals](https://conecto.chat/docs/approvals.md#holds-with-no-rule) has the details.

## Listing and revoking

`GET /v1/keys` lists the keys that work, with each one's scope and the last time it was used. `current: true` marks the key making the call.

`DELETE /v1/keys/{key_id}` revokes a key. A key revokes itself and the keys made from it, and the first key of a line revokes any key of its line. Any other key answers `not_yours`. The owner revokes any key on the account page. A revoked key stops working on every server within 30 seconds.

## Keys for people's assistants

A connector that a person signs in to runs on a key of its own, named like "Ben, through Claude". It acts as that person, within their teams and role, and removing them from the account revokes it at once. [Accounts and people](https://conecto.chat/docs/accounts.md#assistants) has more.

## More in the docs

- Previous: [Accounts and people](https://conecto.chat/docs/accounts.md)
- Next: [Teams and budgets](https://conecto.chat/docs/teams.md)
- Every page in one file: https://conecto.chat/docs/all.md
- Every page's title and address: https://conecto.chat/docs/index.json
