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

# Authentication

> Learn how to authenticate your API requests

All API requests to Zentra must be authenticated using API keys. This guide explains how to obtain and use your API keys securely.

## API Keys

Zentra uses API keys to authenticate requests. You can obtain your API keys from the [Developer Console](https://api.usezentra.com/developer/signin?callbackUrl=%2Fdeveloper%2Fapi-keys).

### Key Types

<CardGroup cols={2}>
  <Card title="Secret Key" icon="key">
    **Format**: `sk_sandbox_...` or `sk_live_...`

    Used for server-side API calls. **Never expose this in client-side code!**
  </Card>

  <Card title="Public Key" icon="eye">
    **Format**: `pk_sandbox_...` or `pk_live_...`

    Can be used in client-side code for specific operations like initializing payments.
  </Card>
</CardGroup>

### Environments

Zentra provides two environments:

| Environment | Purpose                 | Key Prefix                   |
| ----------- | ----------------------- | ---------------------------- |
| **Sandbox** | Testing and development | `sk_sandbox_`, `pk_sandbox_` |
| **Live**    | Production transactions | `sk_live_`, `pk_live_`       |

<Warning>
  Always use sandbox keys during development and testing. Only use live keys in production.
</Warning>

## Making Authenticated Requests

Include your API key in the `Authorization` header using Bearer authentication:

```bash theme={null}
Authorization: Bearer YOUR_SECRET_KEY
```

### Example Requests

<Note>
  The examples below intentionally use reviewed transfer endpoints rather than draft customer or wallet surfaces.
</Note>

<CodeGroup>
  ```javascript JavaScript theme={null}
  const { Zentra } = require('@zentra/sdk');

  const client = new Zentra({
    secretKey: 'sk_sandbox_your_key_here',
    environment: 'sandbox'
  });

  // Make API calls
  const banks = await client.transfers.getBanks();
  console.log(banks[0]);

  const transfer = await client.transfers.create({
    amountMinor: 50000,
    destinationBankCode: '058',
    destinationAccountNumber: '0123456789',
    destinationAccountName: 'Sandbox Beneficiary',
    narration: 'Auth example transfer',
    reference: 'AUTH_EXAMPLE_001'
  });

  console.log(transfer.reference);
  ```

  ```python Python theme={null}
  from zentra import Client

  client = Client(
      api_key='sk_sandbox_your_key_here',
      environment='sandbox'
  )

  # Make API calls
  banks = client.transfers.get_banks()
  print(banks[0])

  transfer = client.transfers.create(
      amount_minor=50000,
      destination_bank_code='058',
      destination_account_number='0123456789',
      destination_account_name='Sandbox Beneficiary',
      narration='Auth example transfer',
      reference='AUTH_EXAMPLE_001'
  )

  print(transfer['reference'])
  ```

  ```php PHP theme={null}
  use Zentra\Client;

  $client = new Client([
      'api_key' => 'sk_sandbox_your_key_here',
      'environment' => 'sandbox'
  ]);

  // Make API calls
  $banks = $client->transfers->getBanks();
  $transfer = $client->transfers->create([
      'amount_minor' => 50000,
      'destination_bank_code' => '058',
      'destination_account_number' => '0123456789',
      'destination_account_name' => 'Sandbox Beneficiary',
      'narration' => 'Auth example transfer',
      'reference' => 'AUTH_EXAMPLE_001'
  ]);
  ```

  ```bash cURL theme={null}
  curl -X POST https://api.usezentra.com/api/v1/transfers \
    -H "Authorization: Bearer sk_sandbox_your_key_here" \
    -H "Content-Type: application/json" \
    -d '{
      "amount_minor": 50000,
      "destination_bank_code": "058",
      "destination_account_number": "0123456789",
      "destination_account_name": "Sandbox Beneficiary",
      "narration": "Auth example transfer",
      "reference": "AUTH_EXAMPLE_001"
    }'
  ```
</CodeGroup>

## Keeping Your Keys Safe

<AccordionGroup>
  <Accordion title="Do's">
    * Store keys in environment variables
    * Use different keys for development and production
    * Rotate keys regularly
    * Use a secrets manager (AWS Secrets Manager, Azure Key Vault, etc.)
    * Restrict API key permissions to only what's needed
    * Monitor API usage for unusual activity
  </Accordion>

  <Accordion title="❌ Don'ts">
    * Never commit keys to version control
    * Don't hardcode keys in your application
    * Don't share keys via email or chat
    * Don't use production keys in development
    * Don't expose secret keys in client-side code
    * Don't share keys across multiple applications
  </Accordion>
</AccordionGroup>

## Environment Variables

Store your API keys in environment variables:

<CodeGroup>
  ```bash .env theme={null}
  ZENTRA_SECRET_KEY=sk_sandbox_your_key_here
  ZENTRA_PUBLIC_KEY=pk_sandbox_your_key_here
  ```

  ```javascript JavaScript (.env.local) theme={null}
  NEXT_PUBLIC_ZENTRA_PUBLIC_KEY=pk_sandbox_your_key_here
  ZENTRA_SECRET_KEY=sk_sandbox_your_key_here
  ```

  ```python Python (.env) theme={null}
  ZENTRA_SECRET_KEY=sk_sandbox_your_key_here
  ZENTRA_PUBLIC_KEY=pk_sandbox_your_key_here
  ```
</CodeGroup>

Then load them in your application:

<CodeGroup>
  ```javascript JavaScript theme={null}
  require('dotenv').config();

  const client = new Zentra.Client({
    apiKey: process.env.ZENTRA_SECRET_KEY,
    environment: 'sandbox'
  });
  ```

  ```python Python theme={null}
  import os
  from zentra import Client

  client = Client(
      api_key=os.getenv('ZENTRA_SECRET_KEY'),
      environment='sandbox'
  )
  ```

  ```php PHP theme={null}
  $client = new Client([
      'api_key' => getenv('ZENTRA_SECRET_KEY'),
      'environment' => 'sandbox'
  ]);
  ```
</CodeGroup>

## Error Responses

If authentication fails, you'll receive a `401 Unauthorized` response:

```json theme={null}
{
  "error": {
    "code": "unauthorized",
    "message": "Invalid API key",
    "status": 401
  }
}
```

Common authentication errors:

| Error Code          | Description                        | Solution                        |
| ------------------- | ---------------------------------- | ------------------------------- |
| `unauthorized`      | Invalid or missing API key         | Check your API key is correct   |
| `invalid_key`       | Malformed API key                  | Ensure key format is correct    |
| `expired_key`       | API key has been revoked           | Generate a new API key          |
| `wrong_environment` | Using sandbox key on live endpoint | Use the correct environment key |

## API Key Management

### Rotating Keys

To rotate your API keys:

1. Generate a new key in the Developer Console
2. Update your application with the new key
3. Test thoroughly
4. Revoke the old key

<Info>
  We recommend rotating keys every 90 days as a security best practice.
</Info>

### Revoking Keys

If you suspect a key has been compromised:

1. Go to **Dashboard → API Keys**
2. Click **Revoke** next to the compromised key
3. Generate and deploy a new key immediately

### Key Permissions

You can create API keys with limited permissions:

* **Read-only**: Only GET requests
* **Write**: POST, PUT, PATCH, DELETE requests
* **Admin**: Full access including sensitive operations

## IP Whitelisting (Optional)

For additional security, you can whitelist IP addresses:

1. Go to **Dashboard → Security**
2. Add your server IP addresses
3. Save changes

<Warning>
  Be careful with IP whitelisting if your application runs on dynamic infrastructure (like cloud functions).
</Warning>

## Rate Limiting

API keys are subject to rate limits:

| Environment  | Limit                  |
| ------------ | ---------------------- |
| Sandbox      | 100 requests/minute    |
| Live (Basic) | 1,000 requests/minute  |
| Live (Pro)   | 10,000 requests/minute |

See [Rate Limits](/api-reference/rate-limits) for more details.

## Next Steps

<CardGroup cols={2}>
  <Card title="Make Your First Request" icon="rocket" href="/quickstart">
    Follow our quickstart guide
  </Card>

  <Card title="API Reference" icon="book" href="/api-reference/overview">
    Explore all available endpoints
  </Card>

  <Card title="Error Handling" icon="triangle-exclamation" href="/api-reference/errors">
    Learn about error responses
  </Card>

  <Card title="Webhooks" icon="webhook" href="/api-reference/webhooks/overview">
    Set up webhook authentication
  </Card>
</CardGroup>
