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

# Authenticate requests to the Dubu Pay API

> Dubu Pay supports two authentication methods — JWT bearer tokens for session-based access and API keys for long-lived server-side integrations.

Every request to a protected Dubu Pay endpoint must carry valid credentials. Dubu Pay offers two authentication methods: a short-lived JWT bearer token issued on login, and a long-lived API key you create and manage from your account. Understanding when to use each method will help you build a secure integration.

## Authentication methods

### JWT bearer token

When you call `POST /auth/login`, the API returns an `access_token` and a `refresh_token`. Include the access token in the `Authorization` header for subsequent requests:

```
Authorization: Bearer <access_token>
```

| Property               | Value            |
| ---------------------- | ---------------- |
| Access token lifetime  | 15 minutes       |
| Refresh token lifetime | 7 days           |
| Header name            | `Authorization`  |
| Header value format    | `Bearer <token>` |

**When to use JWT tokens:** Use bearer tokens for dashboard-style applications where a user actively signs in, or for any short-lived session where you want automatic expiry. Because access tokens expire in 15 minutes, they limit the blast radius if a token is intercepted.

<CodeGroup>
  ```bash cURL theme={null}
  curl --request GET \
    --url https://api.dubupay.com/api/v1/auth/me \
    --header 'Authorization: Bearer eyJhbGci...'
  ```

  ```javascript Node.js theme={null}
  const response = await fetch('https://api.dubupay.com/api/v1/auth/me', {
    headers: {
      'Authorization': `Bearer ${access_token}`,
    },
  });
  const { data } = await response.json();
  ```
</CodeGroup>

***

### API key

API keys are long-lived credentials tied to your merchant account. Pass one in the `X-Api-Key` header:

```
X-Api-Key: dubu_sk_live_<32chars>
```

| Property    | Value                                                |
| ----------- | ---------------------------------------------------- |
| Key formats | `dubu_sk_live_<32chars>` or `dubu_sk_test_<32chars>` |
| Header name | `X-Api-Key`                                          |
| Expiry      | None (until revoked)                                 |

**When to use API keys:** Use API keys for server-side integrations — background jobs, webhooks, backend services — where there is no interactive login flow. The key must never be exposed in client-side JavaScript or mobile app bundles.

<CodeGroup>
  ```bash cURL theme={null}
  curl --request GET \
    --url https://api.dubupay.com/api/v1/payments/customers \
    --header 'X-Api-Key: dubu_sk_live_AbCdEfGhIjKlMnOpQrStUvWxYz012345'
  ```

  ```javascript Node.js theme={null}
  const response = await fetch('https://api.dubupay.com/api/v1/payments/customers', {
    headers: {
      'X-Api-Key': process.env.DUBU_API_KEY,
    },
  });
  const { data } = await response.json();
  ```
</CodeGroup>

***

## Refreshing an access token

When your access token expires, use the refresh token to obtain a new pair without requiring the user to log in again. Each refresh call issues a new access token and rotates the refresh token.

**Request body**

<ParamField body="refresh_token" type="string" required>
  The refresh token returned by `/auth/login` or a previous `/auth/refresh` call.
</ParamField>

<CodeGroup>
  ```bash cURL theme={null}
  curl --request POST \
    --url https://api.dubupay.com/api/v1/auth/refresh \
    --header 'Content-Type: application/json' \
    --data '{
      "refresh_token": "eyJhbGci..."
    }'
  ```

  ```javascript Node.js theme={null}
  const response = await fetch('https://api.dubupay.com/api/v1/auth/refresh', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ refresh_token: stored_refresh_token }),
  });
  const { data } = await response.json();
  const { access_token, refresh_token } = data;
  // Store the new refresh_token — the old one is now invalid
  ```
</CodeGroup>

**Example response**

```json theme={null}
{
  "success": true,
  "data": {
    "access_token": "eyJhbGci...",
    "refresh_token": "eyJhbGci..."
  }
}
```

<Warning>
  Refresh tokens rotate on every use. Store the new `refresh_token` returned from each `/auth/refresh` call and discard the previous one. Using an old refresh token will result in a `401` error.
</Warning>

***

## Authentication priority

When a request includes both an `X-Api-Key` header and an `Authorization: Bearer` header, Dubu Pay evaluates the API key first. If the API key is valid and active, the bearer token is ignored.

***

## Error responses

| HTTP status | Error code              | Cause                                                                         |
| ----------- | ----------------------- | ----------------------------------------------------------------------------- |
| `401`       | `UNAUTHORIZED`          | No credentials provided, token has expired, or token signature is invalid.    |
| `403`       | `IP_WHITELIST_REQUIRED` | Your account has no whitelisted IPs configured and IP enforcement is enabled. |
| `403`       | `IP_NOT_WHITELISTED`    | The request originated from an IP address not on your whitelist.              |

**Example 401 response**

```json theme={null}
{
  "success": false,
  "error": {
    "message": "Authentication required",
    "code": "UNAUTHORIZED"
  }
}
```

<Note>
  If you receive a `403 IP_NOT_WHITELISTED` error, add your server's outbound IP address to the IP whitelist in your account settings.
</Note>

***

## Logging out

To invalidate a session and revoke the active refresh token, call `POST /auth/logout` with a valid bearer token.

<CodeGroup>
  ```bash cURL theme={null}
  curl --request POST \
    --url https://api.dubupay.com/api/v1/auth/logout \
    --header 'Authorization: Bearer eyJhbGci...'
  ```

  ```javascript Node.js theme={null}
  await fetch('https://api.dubupay.com/api/v1/auth/logout', {
    method: 'POST',
    headers: { 'Authorization': `Bearer ${access_token}` },
  });
  ```
</CodeGroup>

**Example response**

```json theme={null}
{
  "success": true,
  "message": "Logged out successfully"
}
```

***

## Next steps

<CardGroup cols={2}>
  <Card title="API keys" icon="key" href="/authentication/api-keys">
    Create and manage long-lived API keys for server-side integrations.
  </Card>

  <Card title="Quickstart" icon="rocket" href="/quickstart">
    Follow the end-to-end guide to issue your first virtual bank account.
  </Card>
</CardGroup>
