---
title: "Agent access"
description: "Give a script or automation its own token to create rooms and schedules on your behalf."
---

# Agent access

Agent access tokens let something other than a person with a browser create rooms
and build schedules in your account — a script, a no-code automation tool (Zapier,
n8n, Make), or a custom integration you have written yourself. It authenticates
over a small REST API instead of a login session.

Find it at **Agent access** in account settings, or `/settings/agent-access`.

## What this is, and is not, for

This is a credential for software you control — a script, a no-code automation tool, or
Claude connected via [MCP](mcp-setup.md), which uses this same token through its
connector's own authentication field rather than a chat message. There is no ChatGPT
connector yet: ChatGPT's custom connectors only support no-auth or OAuth, not a pasted
token, so that integration is a deliberate, not-yet-built follow-up rather than an oversight.

> **Do not paste a raw token into a chat message.** Doing so
> puts your credential in that provider's conversation history and logs, which is
> exactly the exposure this feature's token hashing is designed to prevent on our
> side. Give the token to a script's environment variables, an automation
> platform's own credential store, or a custom integration's secrets manager —
> never to a chat message.

## Creating a token

In the **Create a token** form, set:

- **Name** — anything that reminds you what will use it, for example "Zapier
  automation" or "Nightly schedule importer".
- **Scopes** — which actions the token may perform (see the table below). At
  least one is required.
- **Expires** — 30 days, 90 days, 1 year, or no expiry.

Click **Create token**.

### Scopes

Four scopes exist, but only two currently do anything, because only two REST
endpoints exist to authorize:

| Scope              | Label in the form | What it allows                                                          |
| ------------------ | ----------------- | ----------------------------------------------------------------------- |
| `rooms:create`     | Create rooms      | Create a new room — works today                                         |
| `schedules:create` | Create schedules  | Add timers to a room the token can access — works today                 |
| `rooms:read`       | Read rooms        | Reserved for a future rooms-lookup endpoint — nothing calls this yet    |
| `schedules:read`   | Read schedules    | Reserved for a future schedule-lookup endpoint — nothing calls this yet |

Selecting a read scope does no harm, but it does not unlock anything either —
there is no endpoint yet for it to authorize. Stick to `rooms:create` and
`schedules:create` unless you are deliberately preparing for a later release.

### Expiry

Choose the shortest expiry that is still practical for whatever holds the token.
An expired token stops working the same way a revoked one does; the only
difference is that expiry happens on its own, without anyone clicking anything.

## The token is shown once

When you create a token, a panel shows its full raw value — the only time it is
ever displayed. Copy it now. Tamora stores only a cryptographic hash of the
value, so if you close the panel or reload the page without copying it, nobody —
including us — can recover it. Your only options at that point are to rotate the
token or create a new one.

Rotating works the same way: the new value is shown exactly once, at the moment
you rotate.

The panel's **Done** button stays disabled until you tick **I've saved this
token**, and pressing Escape or clicking outside the panel does nothing. This is
deliberate, so the panel cannot be dismissed by accident before you have copied
the value.

## Revoking and rotating

Every active token in the list has **Rotate** and **Revoke** controls.

- **Revoke** stops the token working immediately. A confirmation dialog names the
  token first, because this cannot be undone — anything already using it starts
  failing right away. A revoked token stays in the list, shown as revoked, rather
  than disappearing, so its history stays visible in Agent activity below.
- **Rotate** replaces a token's value while keeping its name, scopes, and expiry.
  The old value stops working the moment you rotate, and the new value is
  revealed once, exactly as at creation. Use this instead of revoking and
  recreating when you only need to swap the secret a script uses, without
  reconfiguring anything else about it.

## What the two endpoints do

Both endpoints are called with an `Authorization: Bearer` header carrying the raw
token — for example, `Authorization: Bearer et_pat_2f6a9c…` — plus a JSON request
body, and both return the created resource on success, as an HTTP 201. This
section describes them at the level someone deciding whether to use this feature
needs; it is not a full API reference.

### Creating a room — POST /api/v1/rooms

Requires the `rooms:create` scope. Has the same effect as clicking **+ New room**
on the dashboard.

| You send   | Type                               |
| ---------- | ---------------------------------- |
| `title`    | text                               |
| `timezone` | an IANA name, e.g. `Europe/London` |

The response carries the new room's `id`, `title`, `timezone`, and `created_at`.

If your account is on the free tier and already has a room, this fails with an
upgrade-required error instead of creating a second one — the same limit the
dashboard itself enforces.

### Adding a schedule — POST /api/v1/rooms/:roomId/schedule

Requires the `schedules:create` scope. Put the room's `id` from the step above
where `:roomId` appears in the URL.

| You send                        | Type                       |
| ------------------------------- | -------------------------- |
| `items`                         | a list of timers to create |
| each item's `title`             | text                       |
| each item's `duration_sec`      | whole number of seconds    |
| each item's `speaker` / `notes` | text, optional             |

The response carries the timers that were created. The same limits as
[CSV import](csv-import.md) apply: up to 500 items per request, and each
duration is clamped to between 1 second and 24 hours.

A token can never be pointed at a room it does not own by supplying a different
id anywhere in the request — access is always resolved from the token itself,
never from anything in the request body.

### Retrying safely

If your automation might retry a request after a timeout or a dropped response,
send an `Idempotency-Key` header with a value unique to that one logical request.
A retried request carrying the same key returns the original result instead of
creating a second room or schedule.

## Agent activity

The **Agent activity** list on the same settings page shows recent actions taken
through a token — a created room, a created schedule, or a failed or unauthorized
attempt — each with a timestamp and a result. It only shows activity for your own
tokens, is limited to the most recent entries, and has no filter or export
control. Check it whenever a token has done something you did not expect.

## Treat the token like a password

A raw token grants whatever its scopes allow, to whoever holds it, with no login
step in between. If you suspect one has leaked — committed to a public
repository, pasted somewhere it should not have been, sent to the wrong person —
revoke it immediately rather than waiting to investigate first. Agent activity
keeps a record of what the token did before you revoked it, so you can review
that afterwards without leaving the exposure open in the meantime.

## Related

- [Team management](team-management.md) — the team a token's rooms and schedules
  belong to
- [CSV import](csv-import.md) — the row cap and duration clamp the schedule
  endpoint shares with CSV import
- [Controller](controller.md) — where a room or schedule created by a token
  appears, exactly like one created by hand
