> ## Documentation Index
> Fetch the complete documentation index at: https://docs.trylath.com/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Every Lath operation is POST https://platform.trylath.com/<operation name with dots replaced by slashes>, with a JSON body and `Authorization: Bearer <key>`. `email.send` is POST /email/send.
> Branch on `error.code`, never on `error.message`. Every refusal also carries `error.fix`, which names the next step.
> Send an `Idempotency-Key` header on any operation that is not retry-safe, so a retry cannot run it twice.
> A `lath_test_` key emails only the account's own members and sends no SMS; a `lath_live_` key reaches real recipients and is billed.
> The OpenAPI document, generated from the same registry as the routes, is at https://platform.trylath.com/openapi.json.

# Authentication

> What a key is, what it names, and why only one operation can do without one.

## A key is an identity, not a password

Every operation resolves the caller into an environment and a project. That is whose contacts, whose consent records, whose suppression list and whose bill are involved.

So a key is not a gate placed in front of the features — it is the thing that makes a request belong to somebody. A send with no key would be a send with no sender, and there would be nothing to attribute a STOP to.

## Live and test are different environments

Every project has both from the moment it exists, each with its own secret and publishable key. Which environment you are acting in is decided by the key you call with — not by a flag that can be forgotten.

They hold separate data: the same person in live and test is two records.

## Secret and publishable

A secret key is for your server. A publishable key is for a browser or an app, and can only reach the operations meant to be called from one — the hosted sign-in pages use it.

`developers.key.create` issues more, with scoped permissions. Each operation's page names the permission it needs.

```bash theme={null}
# Every request, every surface
Authorization: Bearer <key>
```

## The one operation without a key

`account.signup` takes no key, because it is how the first one is obtained. It is rate-limited per IP address.

Everything else answers `401 unauthenticated` without a valid key, rather than pretending the route does not exist.
