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

# Keys and scopes

> Live and test keys, what a key may do, where it may be used from, and how to retire one.

Every request carries one key: `Authorization: Bearer ff_live_…`. The key is the account
— everything it reads and changes is that account's, and nothing else's.

## Making a key

<Steps>
  <Step title="Open Developer Tools → API keys">
    Owners and Admins can make keys. **Developer Tools** is the last entry in the side menu.
  </Step>

  <Step title="Name it, and choose what it may do">
    Give each system its own key ("Billing server", "Website") with only the scopes it
    needs.
  </Step>

  <Step title="Choose where it may be used from (optional)">
    Addresses or ranges such as `203.0.113.0/24`. A request from anywhere else is
    refused with `address_not_allowed`.
  </Step>

  <Step title="Copy it">
    The whole key is shown **once**. OMNI keeps only a fingerprint of it, so it can't be
    shown again — make a new one if it's lost.
  </Step>
</Steps>

<Frame caption="Developer Tools → API keys">
  <img src="https://mintcdn.com/fire-flo-omno/rCV-_otnmYljXMIQ/images/developers/api-keys.png?fit=max&auto=format&n=rCV-_otnmYljXMIQ&q=85&s=7834b9d3c1247eba8e4ce9492e6242ab" alt="The API keys screen, listing keys with what each may do and when it was last used" width="1440" height="900" data-path="images/developers/api-keys.png" />
</Frame>

## Live and test keys

| | Live `ff_live_…` | Test `ff_test_…` |
| :- | :- | :- |
| Messages and calls | Reach real people, and are charged | **Never reach a channel.** A message succeeds at once with the code `test` |
| Contacts, routes, templates, webhooks | Real | Real — a test key changes your account's data like a live one |
| Everything else | The same | The same |

Build against a test key, then switch the key, not the code.

## Scopes

A key may only do what its scopes allow. A request outside them is refused with
`scope_missing`, naming the scope it needed. The full list is on
[Scopes and events](/api-reference/scopes-and-events); the common ones:

| Scope | Lets the key |
| :- | :- |
| `messages:send`, `messages:read` | Send messages with failover; read them |
| `contacts:read`, `contacts:write` | Find, add and change contacts and their consent |
| `conversations:read`, `conversations:write` | Read the Inbox; reply, close, assign, label |
| `routes:*`, `templates:*` | Manage routes and unified templates |
| `calls:read`, `calls:write` | Read calls; ring people |
| `senders:read`, `usage:read` | See senders; see usage and balance |
| `webhooks:read`, `webhooks:write` | Manage webhook endpoints |
| `whatsapp.templates:*`, `sms.senders:*`, `sms.templates:*` | A channel's own features ([extensions](/developers/channel-extensions)) |

`GET /v1/me` needs no scope: any key may ask who it is.

## Retiring a key

**Revoke** it in Developer Tools → API keys. It stops working at once. A key can also be
given an expiry when it is made; after it, requests are refused with `invalid_key`.

Every request a key makes is in **Developer Tools → Requests** for 30 days — the time, the
key, the call, the answer and its request id.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.