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

# Authentication

> Bearer API tokens, scopes, expiry and rotation.

Notealy uses Bearer tokens for the public API. Tokens are issued per organization, carry one or more scopes, and are passed in the `Authorization` header of every request.

```bash theme={null}
curl https://thanos.notealy.com/v1/people \
  -H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
```

With the SDK the token is configured once on the client:

```ts theme={null}
import { Notealy } from '@notealy/sdk'

const notealy = new Notealy({ apiToken: process.env.NOTEALY_TOKEN! })
```

## Verify your token

Once you have a token, the simplest way to confirm it works is `GET /v1/me`. It requires no specific scope and returns the token's identity card and the organization it's attached to.

```bash theme={null}
curl https://thanos.notealy.com/v1/me \
  -H "Authorization: Bearer sk_live_..."
```

```json theme={null}
{
  "token": {
    "id": "tok_...",
    "prefix": "sk_live_xxxx",
    "name": "Production server",
    "scopes": ["people:read", "people:write"],
    "expiresAt": null,
    "lastUsedAt": "2026-05-04T18:21:00.000Z"
  },
  "organization": {
    "id": "org_...",
    "name": "Acme Inc",
    "slug": "acme"
  }
}
```

A `200` here means your token is valid and you know which organization and scopes the rest of the API will operate against. A `401` means the token is missing, malformed, revoked or expired.

## Creating a token

1. Sign in to your Notealy dashboard.
2. Open **Settings → API Tokens** (Owner or Admin role required).
3. Click **New token**, pick a name, select the scopes you need, and optionally set an expiry date.
4. Copy the token — it is shown **only once**.

If you lose a token, revoke it and create a new one — there is no recovery flow.

## Scopes

A token can only call endpoints that match its scopes. Pick the narrowest scope that fits your integration; you can always issue a second token with broader scopes for a different use case.

| Scope                  | Grants                                                         |
| ---------------------- | -------------------------------------------------------------- |
| `people:read`          | List and fetch people                                          |
| `people:write`         | Create, update, delete people; attach/detach tags              |
| `people:*`             | All `people:*` actions                                         |
| `companies:read`       | List and fetch companies                                       |
| `companies:write`      | Create, update, delete companies                               |
| `companies:*`          | All `companies:*` actions                                      |
| `tags:read`            | List tags (needed to discover ids when attaching tags via API) |
| `tags:write`           | Create new tags                                                |
| `tags:*`               | All `tags:*` actions                                           |
| `email:send`           | Send a templated email to a known contact                      |
| `email:send:to`        | Send a templated email to an arbitrary address                 |
| `email:*`              | All `email:*` actions                                          |
| `email_templates:read` | List email templates (to discover template ids)                |
| `email_templates:*`    | All `email_templates:*` actions                                |
| `email_campaigns:read` | List and fetch email campaigns                                 |
| `email_campaigns:send` | Trigger campaign sends                                         |
| `email_campaigns:*`    | All `email_campaigns:*` actions                                |
| `*`                    | Wildcard — all current and future scopes                       |

`GET /v1/me` requires no scope at all — any active token can call it.

Wildcards match within a resource: `people:*` covers any `people:<action>`; the bare `*` matches everything.

## Expiry and revocation

* **Expiry** — Set an `expiresAt` date when creating the token. After that timestamp the token is rejected with `401 Unauthorized`.
* **Revocation** — Delete the token in the dashboard at any time. Revoked tokens are rejected immediately.
* **Rotation** — Best practice is to issue a new token first, switch your integration over to it, then revoke the old one. Tokens carry no shared state; you can run two in parallel during the cutover.

The dashboard shows the last time each token was used and the IP that used it, so you can spot stale or compromised tokens.

## Errors

| Status                  | Meaning                                                     |
| ----------------------- | ----------------------------------------------------------- |
| `401 Unauthorized`      | Header missing, malformed, or token invalid/revoked/expired |
| `403 Forbidden`         | Token is valid but lacks the required scope                 |
| `429 Too Many Requests` | You hit the rate limit — see [Rate limits](/rate-limits)    |
