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

# Authentication

> Create, scope, store, rotate, and revoke Onlyform API keys.

The Onlyform Public API authenticates requests with scoped API keys. Keys start with `of_live_` and belong to the user who created them.

## Send an API key

Send the key in the `X-API-Key` request header:

```bash theme={null}
curl https://api.onlyform.com/v1/me \
  --header "X-API-Key: $ONLYFORM_API_KEY"
```

The API also accepts a bearer token for compatibility, but `X-API-Key` is the documented and recommended method.

<Warning>
  Never put an API key in a URL, client-side bundle, mobile application, public repository, log message, or support ticket.
</Warning>

## Create a key

1. Open [**Profile → API keys**](https://app.onlyform.com/profile/api-keys).
2. Select **Create API key**.
3. Enter a name that identifies the integration.
4. Select the minimum scopes the integration needs.
5. Choose an expiration date when appropriate.
6. Copy and securely store the secret.

Onlyform shows the complete secret once. The dashboard later displays only its prefix and metadata. You can have up to 20 active, unexpired keys.

## Scopes

Scopes use the `resource:action` format.

| Scope               | Allows                                           |
| ------------------- | ------------------------------------------------ |
| `analytics:read`    | Read aggregate form funnel metrics.              |
| `forms:read`        | List forms and read form definitions and blocks. |
| `forms:write`       | Create, update, and move forms to trash.         |
| `submissions:read`  | List and read completed submissions.             |
| `submissions:write` | Permanently delete submissions.                  |
| `webhooks:read`     | List webhooks and inspect recent deliveries.     |
| `webhooks:write`    | Create, update, and delete webhooks.             |
| `workspaces:read`   | List and read accessible workspaces.             |
| `workspaces:write`  | Create, update, and delete workspaces.           |

Calling an endpoint without its required scope returns `403 INSUFFICIENT_SCOPE`.

<Tip>
  Use separate keys for development and production. This limits the impact of a leak and makes rotation easier.
</Tip>

## Rotate a key

<Steps>
  <Step title="Create a replacement">
    Create a new key with the same minimum scopes as the existing integration.
  </Step>

  <Step title="Update your secret store">
    Deploy the replacement key without revoking the old key yet.
  </Step>

  <Step title="Verify traffic">
    Call `GET /v1/me` with the replacement key and confirm the integration is using it.
  </Step>

  <Step title="Revoke the old key">
    Revoke the previous key from **Profile → API keys**. Revocation takes effect immediately.
  </Step>
</Steps>

Expired or revoked keys return `401 INVALID_API_KEY`.

## Key security

* Store keys in a managed secrets service or encrypted environment configuration.
* Grant only the scopes an integration needs.
* Set an expiration for temporary integrations.
* Rotate keys on a schedule and immediately after suspected exposure.
* Use the key's **Last used** value to identify inactive credentials.

<Card title="Make your first request" icon="rocket" href="/quickstart">
  Verify a new key and list your workspaces.
</Card>
