# API keys

Make a key in Settings, send it with each request, and learn what it opens, how many you can hold, and what stops it.

An API key lets a program of yours call the Little Worker API as you. This page shows how to make a key, how to send it, what the **Can allow actions** switch opens, and what stops a key.

## What a key is

A key is a secret that starts with `lw_key_`. It acts as the person who made it, in that person's workspace, so a program that holds it can give your workers tasks and read their work. It opens only the API at `https://core.thelittleworker.com/api/v1`. It never opens the app's own routes.

Anyone who holds a key can use your workers. Keep it in your program's secrets, never in code, and never save it as a password a worker can read.

## 1. Make a key

Sign in at [app.thelittleworker.com](https://app.thelittleworker.com), open **Settings**, then **API Keys**, and choose **Create Key**.

1. In **New API Key**, give the key a **Name**, up to 80 characters. Name it after the program that will use it.
2. Choose whether to turn on **Can allow actions**. It is off to begin with. The next section says what it opens.
3. Choose **Create**. **Copy Your Key** shows the key. Copy it, then choose **Done**.

The key is shown once. Little Worker keeps only a fingerprint of it and its last four characters, so it cannot show the key again. If you lose a key, remove it and make a new one.

Settings lists the keys you made, each with its name, the last four characters, the day it was made and the day it was last used. Remove a key there when a program no longer needs it.

## 2. Send it with every request

Send the key in the `x-api-key` header. Every request also needs the `Little-Worker-Version` header. This call lists your workers:

```bash title="curl"
curl https://core.thelittleworker.com/api/v1/workers \
  -H "x-api-key: $LITTLE_WORKER_API_KEY" \
  -H "Little-Worker-Version: 2026-10-19"
```

```ts title="TypeScript"
const response = await fetch("https://core.thelittleworker.com/api/v1/workers", {
  headers: {
    "x-api-key": process.env.LITTLE_WORKER_API_KEY ?? "",
    "Little-Worker-Version": "2026-10-19",
  },
})
console.log(response.status, await response.json())
```

```python title="Python"
import os

import requests

response = requests.get(
    "https://core.thelittleworker.com/api/v1/workers",
    headers={
        "x-api-key": os.environ["LITTLE_WORKER_API_KEY"],
        "Little-Worker-Version": "2026-10-19",
    },
)
print(response.status_code, response.json())
```

The answer is `200`. `data` lists your workers, newest first, and `next_page` is `null` when there are no more:

```json
{
  "data": [
    {
      "type": "worker",
      "id": "worker_bf5ff997fca044b38dc1cc9ea5b60100",
      "version": 1,
      "name": "Copywriter",
      "status": "active"
    }
  ],
  "next_page": null
}
```

A client that cannot set `x-api-key` may send `Authorization: Bearer lw_key_...` instead. If a request carries both, `x-api-key` is the one used.

If the request is refused, `error.type` and `details.error_code` say why:

| Status | `error.type` and `error_code` | When it happens | What to do |
| --- | --- | --- | --- |
| 401 | `authentication_error`, `unauthenticated` | No key was sent, or the key is not valid because it was removed, or never existed, or its owner left the workspace. | Send the key in `x-api-key`, or make a new key. |
| 400 | `invalid_request_error`, `validation_error` | `Little-Worker-Version` is missing or is not `2026-10-19`. | Send `Little-Worker-Version: 2026-10-19`. |
| 403 | `permission_error`, `workspace_mismatch` | `Little-Worker-Workspace-Id` names a workspace other than the key's. | Leave the header out. A key belongs to one workspace and needs no other. |
| 403 | `permission_error`, `person_required` | The call needs a permission the key was made without, or only a person may do it. | See **Can allow actions** below. |

A bad key is answered before the version is checked, so a request with both problems gets `401`. Here is the `401` body for a key that is not valid:

```json
{
  "type": "error",
  "error": {
    "type": "authentication_error",
    "message": "This API key is not valid. Make a new one.",
    "retryable": false,
    "details": { "error_code": "unauthenticated" }
  },
  "request_id": "request_3f2a9c1d7e5b4a8f9d0c2e4b6a8d1f3c"
}
```

A `401` also carries a `WWW-Authenticate` header that names a document about how to get a key. An agent that cannot make a key itself can read [how to ask a person for one](https://thelittleworker.com/auth.md).

## What Can allow actions opens

Some calls decide for a person: they let a worker act without asking, or they answer a worker that asked. A key made with **Can allow actions** off cannot make them. With it on, a key can:

- Answer a worker's approvals with `user.approval` events, to allow or deny an action. [Approvals](/concepts/approvals) says who may answer, and [Answer approvals from your program](/guides/answer-approvals) shows how.
- Make a worker's `networking` `unrestricted`, so the worker can reach any website. Without the switch the answer is `403` with `person_required`.
- Set a password's `permission` to `always`, so a worker uses the password without asking. Without the switch the answer is `403` with `person_required`.

Turn it on for a program that applies a rule you wrote, and leave it off for the rest.

Even with the switch on, a key never answers these. Only a person can, in the app, and a key that tries gets `403` with `person_required`:

- A worker's first use of a saved password.
- An email a worker sends.
- A press on a risky control in the worker's browser.
- A public post, such as publishing on X.
- A payment, and any other step that is a card in the app.
- A refund.

A key can also be made to delete tasks, with **Can delete tasks**. Settings does not offer that switch yet, so a key made there cannot delete a task. [Archive a task](/api/tasks#archive-a-task) instead.

## How many keys

A workspace holds up to 20 keys. When you have 20, Settings says to remove one before it makes another.

The limits on requests are not per key. All of a workspace's keys share one count of 1,200 reads and 300 writes a minute, and 10 open event streams. Past a limit the answer is `429`, with `Retry-After` in seconds.

## What stops a key

A key works until one of these happens:

- **You remove it.** Choose **Remove** next to the key in Settings. Programs that use it stop working right away. A task the program already started goes on, so stop it too if it should not.
- **Its owner leaves the workspace.** The key stops at once.
- **The owner's account is deleted, or the workspace is deleted.** The key stops at once.

After any of these, a request with the key is answered `401`. A key does not expire by itself.

## Next steps

- [Quickstart](/get-started/quickstart): make a worker, give it a task, and read the result.
- [Answer approvals from your program](/guides/answer-approvals): use a key made with **Can allow actions**.
- [Overview](/get-started/overview): the headers, errors and limits every request meets.
- [Stop work and keep history](/guides/stop-and-retention): stop what a program started before you remove its key.
