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

# Authentication

> How to authenticate your requests with TokenAccount and TokenInstance

RyzeAPI uses two types of token to authenticate each request. Both are sent in the `token` header. Understand when to use each one and how to handle the most common errors.

## Two types of token

<CardGroup cols={2}>
  <Card title="TokenAccount" icon="users">
    This is your **main token**. With it you create and administer your WhatsApp instances.

    **Scope:** your entire account, all of the instances it owns.

    **When to use:** create an instance, list all of your instances, delete an instance, or any operation in which you need to act as the "account owner".
  </Card>

  <Card title="TokenInstance" icon="key">
    Generated automatically when you create a new instance. Each instance has its own.

    **Scope:** **only that specific instance**.

    **When to use:** day-to-day operations, send a message, create a group, configure a webhook, read contacts, etc. It is the token you will use in **99% of calls**.
  </Card>
</CardGroup>

<Tip>
  As a rule of thumb: **use the TokenInstance whenever the endpoint has `:instance` in the path**. Use the TokenAccount only to create/list/delete instances.
</Tip>

## Token lifecycle

<Steps>
  <Step title="You receive your TokenAccount">
    Delivered when your account is created. Store it in a safe place, it cannot be recovered later.
  </Step>

  <Step title="Create an instance">
    Call [`POST /api/instance/new`](/en/api/instance/create) sending your TokenAccount. The response includes the `data.token` field, which is the **TokenInstance** for that instance.
  </Step>

  <Step title="Use the TokenInstance day to day">
    From there on, every operation on that instance (sending a message, reading contacts, configuring a webhook) uses the TokenInstance.
  </Step>

  <Step title="Need to create another instance?">
    Go back to using your TokenAccount to provision one more.
  </Step>
</Steps>

## Three ways to send the token

We recommend **always** using the `token` header. The other forms exist only for specific cases.

### `token` header (recommended default)

```http theme={null}
POST /api/message/text/$Instance_Name HTTP/1.1
Host: ryzeapi.cloud
Content-Type: application/json
token: your-token-here

{"number": "5511999999999", "message": "Hello!"}
```

### `Authorization: Bearer` header (compatibility)

In case your tool only supports the Bearer standard.

```http theme={null}
Authorization: Bearer your-token-here
```

### `?token=` query string (browser WebSocket only)

Used when it is not possible to send headers, the typical case being WebSocket in browser JavaScript, since `new WebSocket(...)` does not accept custom headers.

```javascript theme={null}
const ws = new WebSocket(
  `wss://ryzeapi.cloud/ws/$Instance_Name?token=${instanceToken}`
);
```

<Warning>
  Query strings appear in proxy and CDN logs. **Do not use in production outside the WebSocket/browser case.**
</Warning>

## Who can do what

<AccordionGroup>
  <Accordion title="With TokenAccount" icon="users">
    * Create new instances ([`POST /api/instance/new`](/en/api/instance/create))
    * List all of your instances ([`GET /api/instance/list`](/en/api/instance/list))
    * Operate any `:instance` endpoint of your own instances (send a message, manage groups, etc.)
    * Delete one of your instances ([`DELETE /api/instance/delete/:instance`](/en/api/instance/delete))
  </Accordion>

  <Accordion title="With TokenInstance" icon="key">
    * Any `:instance` endpoint of the **instance itself**: send a message, read contacts, configure a webhook, create a group, etc.
    * Inspect the current state of the instance itself ([`GET /api/instance/list`](/en/api/instance/list))
    * Open a WebSocket connection to receive events in real time
  </Accordion>

  <Accordion title="Not allowed" icon="ban">
    * TokenInstance **does not create new instances**, use TokenAccount for that
    * The TokenInstance of one instance **does not operate another instance**, each token is only valid for its own
    * The TokenAccount/TokenInstance of one account **does not operate instances of another account**
  </Accordion>
</AccordionGroup>

## Access protection (ownership)

RyzeAPI automatically checks, before each operation, whether the token sent has permission for that specific resource. This prevents a token from leaking access to third-party instances.

Examples of what is automatically blocked:

* Trying to send a message on instance `B` using the token of instance `A` → `403`
* Trying to delete an instance that belongs to another account → `403`
* TokenAccount trying to create more instances than its quota allows → `403`

## Authentication errors

All auth error responses come with HTTP `401` (invalid token) or `403` (no permission) and follow the format:

```json theme={null}
{
  "success": false,
  "error": {
    "message": "human-readable description of the problem"
  }
}
```

### Messages you may encounter

| HTTP | Message                                                             | Most likely cause                                              |
| :--: | ------------------------------------------------------------------- | -------------------------------------------------------------- |
|  401 | `Missing token in header`                                           | You did not send the `token` header                            |
|  401 | `Missing token in header, Authorization header, or query parameter` | None of the 3 token forms were used                            |
|  401 | `Invalid token`                                                     | Token does not exist, is wrong, or has been revoked            |
|  401 | `Invalid instance token`                                            | The token does not match the instance in the path              |
|  403 | `Instance token does not match requested instance`                  | You are using the TokenInstance of A on the path `:instance=B` |
|  403 | `Instance does not belong to your account`                          | TokenAccount trying to operate an instance of another account  |
|  403 | `Account instance quota exceeded`                                   | You hit the instance limit for your account                    |

<Tip>
  If you receive `Invalid token` without knowing why, check: (1) that the token is complete and has no spaces; (2) that you are using the right type of token for that endpoint; (3) that the instance exists and is active.
</Tip>

## Security: best practices

<Check>Treat **every token** as a credential, store it in environment variables or a secrets vault, never in the frontend or in public repositories.</Check>
<Check>Use one TokenInstance per instance, if one leaks, you only revoke that one.</Check>
<Check>Use HTTPS in production, RyzeAPI accepts only secure connections.</Check>
<Check>Use the `token` header (not the query string) in most cases, headers do not end up in proxy logs.</Check>
<Check>Monitor the `X-RateLimit-Remaining` header to avoid being blocked for excess requests.</Check>

## Next

<CardGroup cols={2}>
  <Card title="Error types" icon="triangle-exclamation" href="/en/guide/errors">
    The response formats and how to interpret each HTTP code.
  </Card>

  <Card title="Rate limit" icon="gauge" href="/en/guide/rate-limit-cors">
    How much you can call per minute and how to react to `429`.
  </Card>
</CardGroup>
