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

# Authentication

> How to obtain and use API access tokens

## Overview

ZAFA PAY API uses Bearer Token authentication. All API requests must include an access token in the `Authorization` header.

## Obtaining Access Token

You can obtain an access token from the merchant dashboard.

<Steps>
  <Step title="Log in to Dashboard">
    Log in to the merchant dashboard ([https://app.zafapay.com](https://app.zafapay.com))
  </Step>

  <Step title="Open Merchant Settings">
    Select "Merchant Settings" from the side menu
  </Step>

  <Step title="Get Access Token">
    Use the access token displayed in the "API Settings" section
  </Step>
</Steps>

## API Endpoints

| Environment | Base URL                          | Purpose               |
| ----------- | --------------------------------- | --------------------- |
| Sandbox     | `https://api.sandbox.zafapay.com` | Testing & Development |
| Production  | `https://api.zafapay.com`         | Production            |

<Note>
  Different access tokens are required for Sandbox and Production environments.
</Note>

## Authentication Method

Set the `Authorization` header in all API requests.

```bash cURL theme={null}
curl https://api.sandbox.zafapay.com/v1/payments \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json"
```

```javascript Node.js theme={null}
const response = await fetch('https://api.sandbox.zafapay.com/v1/payments', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(data)
});
```

## Authentication Errors

| Error Code     | HTTP Status | Cause                    |
| -------------- | ----------- | ------------------------ |
| `unauthorized` | 401         | Invalid or expired token |
| `forbidden`    | 403         | Account is deactivated   |

### Error Response Examples

```json 401 Unauthorized theme={null}
{
  "error": {
    "code": "unauthorized",
    "message": "Missing or invalid authorization header"
  }
}
```

```json 403 Forbidden theme={null}
{
  "error": {
    "code": "forbidden",
    "message": "Merchant account is inactive"
  }
}
```

## Publishable Key (for S2S Payments)

For [server-to-server payments](/en/guide/s2s-payments), a separate **publishable key** is used to tokenize card details from the browser.

| Key Type        | Prefix                    | Usage                            | Exposure                         |
| --------------- | ------------------------- | -------------------------------- | -------------------------------- |
| Access Token    | —                         | All API operations (server-side) | **Never** expose to client       |
| Publishable Key | `pk_test_*` / `pk_live_*` | Token creation only (browser)    | **Safe** to use in frontend code |

You can obtain your publishable key from the merchant dashboard under **Merchant Settings > API Settings**.

```javascript Browser theme={null}
// Publishable key — safe for client-side use
const zafapay = Zafapay('pk_test_xxxxx');
const { token } = await zafapay.createToken({ ... });
```

<Warning>
  Publishable keys can only create tokens. They cannot access payments, customers, or any other API resources.
</Warning>

## Security Best Practices

🔒 **Store Tokens Securely**<br />
Store access tokens in environment variables or secret management services. Never hardcode them in your code.

🛡️ **Use HTTPS**<br />
Always make API requests over HTTPS.

🖥️ **Server-Side Calls**<br />
Never expose access tokens in client-side (browser) code.

🔄 **Regular Rotation**<br />
Regularly regenerate access tokens for security.
