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

# Authentication

> Authenticate Dojah API requests with your AppId and secret key — key types, headers, the Bearer gotcha, and keeping secrets safe.

Every Dojah API request is authenticated with two headers — your `AppId` and your secret key. Keys are created per app in your dashboard.

## Your keys

Each app has two keys for two different jobs:

| Key        | Where it’s used                            | Notes                                   |
| ---------- | ------------------------------------------ | --------------------------------------- |
| Public key | Client-side — Widget SDKs and hosted flows | Safe to ship in frontend code.          |
| Secret key | Server-side — REST API requests            | Never expose. Treat it like a password. |

Find both under **Developers → Configuration** in the dashboard, where you can also regenerate them.

## Authorizing a request

Send your secret key in the `Authorization` header **raw** — not as `Bearer` — alongside your `AppId`.

| Header          | Required | Value                        |
| --------------- | -------- | ---------------------------- |
| `Authorization` | Yes      | Your secret key, sent as-is. |
| `AppId`         | Yes      | Your app’s App ID.           |

`POST /api/v1/messaging/otp`

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://sandbox.dojah.io/api/v1/messaging/otp" \
    -H "Authorization: {{secret_key}}" \
    -H "AppId: {{app_id}}" \
    -H "Content-Type: application/json" \
    -d '{ "sender_id": "Dojah", "destination": "2348012345678", "channel": "sms" }'
  ```

  ```js Node.js theme={null}
  const res = await fetch("https://sandbox.dojah.io/api/v1/messaging/otp", {
    method: "POST",
    headers: {
      Authorization: process.env.DOJAH_SECRET_KEY,
      AppId: process.env.DOJAH_APP_ID,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ sender_id: "Dojah", destination: "2348012345678", channel: "sms" }),
  });
  const data = await res.json();
  ```

  ```python Python theme={null}
  import os, requests

  res = requests.post(
      "https://sandbox.dojah.io/api/v1/messaging/otp",
      headers={
          "Authorization": os.environ["DOJAH_SECRET_KEY"],
          "AppId": os.environ["DOJAH_APP_ID"],
      },
      json={"sender_id": "Dojah", "destination": "2348012345678", "channel": "sms"},
  )
  data = res.json()
  ```
</CodeGroup>

<Warning>
  **Common mistake.** Prefixing the key with `Bearer` causes a `401`. Send the key on its own.
</Warning>

## Keep your secret key safe

* Call the API only from your **backend** — never from browser or mobile code.
* Store keys in environment variables or a secrets manager, not in source control.
* Use **sandbox** keys while developing; swap to live keys only in production.
* If a key leaks, **regenerate** it from the dashboard immediately.

## Authentication errors

| Code  | Meaning                                                     |
| ----- | ----------------------------------------------------------- |
| `401` | Missing/invalid key or App ID — or a stray `Bearer` prefix. |
| `403` | The key is valid but not permitted for this resource.       |
