---
title: "Authentication, permissions, errors and limits"
description: "How TalaLevel API keys work: the Bearer header, a permission level for each area, the error codes, rate limits and cursor paging."
url: https://talalevel.com/docs/authentication/
date: 2026-11-12
updated: 2026-11-12
---

# Authentication, permissions, errors and limits

Send the key as Authorization: Bearer tl_live_… on every call. A key holds a level (none, read, write or send) for each area such as leads, texts and pipeline. Errors are JSON with an error sentence; the limit is 600 calls a minute for each key.

## The key

Every call carries a workspace key:

```
Authorization: Bearer tl_live_…
```

- An **owner** makes a key in **Settings → Connections → API and webhooks**, names it and picks what it may do.
- The key is shown once. We keep a hash of it and its last four characters, so two keys can be told apart.
- A key belongs to one workspace and acts as the owner who made it. If that person leaves the workspace or is put on hold, the key stops working.
- A revoked key stops at once.
- The base address is `https://app.talalevel.com/api/v1`. Requests and answers are JSON.

The same key also works on the [MCP server](https://talalevel.com/docs/mcp/) and the [command line](https://talalevel.com/docs/cli/).

## Permissions

A key holds one level for each area. **Write** includes read, and **send** includes both.

| Area | Levels | What it covers |
| --- | --- | --- |
| `leads` | none, read, write | Leads, their contacts, fields and status |
| `lists` | none, read, write | Saved lists and who is on them |
| `notes` | none, read, write | Notes on a lead |
| `tasks` | none, read, write | A lead's task and callbacks |
| `pipeline` | none, read, write | Pipelines, stages and deals |
| `calls` | none, read, send | Calls and transcripts; send starts and stops AI caller runs |
| `texts` | none, read, write, send | Text threads; write drafts, send sends |
| `emails` | none, read, write, send | Emails on a lead; write drafts, send sends |
| `calendar` | none, read | Booked calls and calendar events |
| `reports` | none, read | Activity figures |
| `team` | none, read | The people in the workspace |

The presets set every area at once:

| Preset | Every area at |
| --- | --- |
| Read only | read |
| Read and write | its highest level short of send |
| Read, write and send | its highest level |
| Custom | whatever you pick; a key that allows nothing is refused |

A call the key's level does not cover is a `403` that names what is missing:

```json
{ "error": "This key may not send texts.", "area": "texts", "needs": "send" }
```

## Errors

An error is a status code and a sentence. Some carry more, such as the lead a duplicate phone belongs to.

```json
{ "error": "That phone is on a lead here already. Update it, or upsert by phone.", "lead_id": 123 }
```

| Code | Meaning | What to do |
| --- | --- | --- |
| 400 | The body could not be read, has a field we do not know, or a bad value | Fix the request. Nothing was written. |
| 401 | No valid key | Check the `Authorization` header. |
| 403 | The key's permissions do not cover this call | The answer names the `area` and the level it `needs`. |
| 404 | No such record, or it is another workspace's | The two are never told apart. |
| 409 | A duplicate, an ambiguous match, or a change the record cannot take | The answer says which; a duplicate carries `lead_id` or `lead_ids`. |
| 422 | A send or a tool was refused: an opt-out, quiet hours, the day cap, a stale preview | Read the sentence. Nothing was sent. |
| 429 | Too many calls | Wait for the time in the `retry-after` header. |
| 500 | Our fault | Try again. |

A body is checked whole before anything is written. One bad field is a `400` and no part of the request is applied.

## Rate limits

| Limit | Value |
| --- | --- |
| Calls for each key | 600 a minute |
| Calls with no valid key, for each address | 60 a minute |
| Texts and emails a key may send | 20 in 24 hours unless the owner changes it; at most 500 |
| Rows a key may read through tools | 5,000 in 24 hours |
| Leads in one batch or run preview | 5,000 |

The owner sets the daily send limit in **Settings → AI apps**. Batches, waves and AI caller runs keep their own limits and do not count against it.

## Paging

List calls take `cursor` and `limit` and answer with `next_cursor` and `has_more`.

- `/leads` and `/deals` list the **oldest change first**. Call again at once while `has_more` is true. When it is false, keep `next_cursor` and use it on your next poll to get only what changed since.
- A change is listed 30 seconds after it happens, so a record that is still being saved is never skipped.
- Notes, texts, calls and emails on a lead list the **newest first**, and the cursor is the last row's id.

```sh
curl "https://app.talalevel.com/api/v1/leads?cursor=$CURSOR&limit=50" \
  -H "Authorization: Bearer $TALALEVEL_KEY"
```

## Questions

### How do I authenticate to the TalaLevel API?

With a workspace key in the Authorization header: Authorization: Bearer tl_live_…. An owner makes the key in Settings → Connections → API and webhooks.

### What is the TalaLevel API rate limit?

600 calls a minute for each key. Over it the answer is 429 with a retry-after header that says when to try again.

### Can I limit what an API key may do?

Yes. Each key holds a level for each area: none, read, write, or send. A key that only reads leads cannot text anyone.
