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

# Authentication

> Secure your API requests with API keys

## Overview

All protected Daya API requests require authentication using API keys. Each key is tied to a specific merchant and environment (Sandbox or Production).

<Warning>
  API keys grant full access to your account. **Never** share them publicly or commit them to version control.
</Warning>

## API Keys

### Generating Keys

1. Sign up at [dashboard.daya.co](https://dashboard.daya.co)
2. Navigate to **API Keys**
3. Generate separate keys for Sandbox and Production

### Key Format

| Environment | Prefix        | Example                |
| ----------- | ------------- | ---------------------- |
| Sandbox     | `sk_sandbox_` | `sk_sandbox_abc123...` |
| Production  | `sk_live_`    | `sk_live_xyz789...`    |

### Environments

| Environment    | Purpose                           | Base URL                      |
| -------------- | --------------------------------- | ----------------------------- |
| **Sandbox**    | Testing with fake funds           | `https://api.sandbox.daya.co` |
| **Production** | Live transactions with real money | `https://api.daya.co`         |

<Info>
  Sandbox and Production environments are **completely isolated**. Data and keys do not cross environments.
</Info>

## Making Authenticated Requests

Include your API key in the `X-Api-Key` header on every protected request:

<CodeGroup>
  ```bash cURL theme={null}
  curl --request GET \
    --url https://api.daya.co/v1/rates \
    --header 'X-Api-Key: YOUR_API_KEY'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://api.daya.co/v1/rates', {
    headers: {
      'X-Api-Key': 'YOUR_API_KEY',
      'Content-Type': 'application/json'
    }
  });
  ```

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

  headers = {
      'X-Api-Key': 'YOUR_API_KEY',
      'Content-Type': 'application/json'
  }
  response = requests.get('https://api.daya.co/v1/rates', headers=headers)
  ```

  ```go Go theme={null}
  client := &http.Client{}
  req, _ := http.NewRequest("GET", "https://api.daya.co/v1/rates", nil)
  req.Header.Add("X-Api-Key", "YOUR_API_KEY")
  req.Header.Add("Content-Type", "application/json")
  resp, _ := client.Do(req)
  ```
</CodeGroup>

## Idempotent Write Requests

Endpoints that create resources, such as `POST /v1/funding-accounts`, `POST /v1/transfers`, and `POST /v1/merchant/withdrawals`, also require an `X-Idempotency-Key` header. Use a new value for each new write attempt, and reuse the same value only when retrying the exact same request.

```bash cURL theme={null}
curl --request POST \
  --url https://api.daya.co/v1/funding-accounts \
  --header 'X-Api-Key: YOUR_API_KEY' \
  --header 'X-Idempotency-Key: funding-account-20260320-0001' \
  --header 'Content-Type: application/json'
```

## Environment Isolation

<Tabs>
  <Tab title="Sandbox">
    **For:** Integration testing, development

    **Characteristics:**

    * Separate API keys from production
    * Simulated NGN deposits
    * Testnet USDC/USDT (no real value)
    * Same API surface as production
    * No KYB required

    **Use when:** Building and testing your integration
  </Tab>

  <Tab title="Production">
    **For:** Live transactions with real money

    **Characteristics:**

    * Unique production API keys
    * Real NGN bank transfers
    * Mainnet USDC/USDT (real value)
    * KYB verification required
    * Audit logs and compliance monitoring

    **Use when:** Serving real users and processing actual funds
  </Tab>
</Tabs>

<Warning>
  **Never** use production keys in sandbox or vice versa. The API will reject cross-environment requests.
</Warning>

## Security Best Practices

<AccordionGroup>
  <Accordion title="Store keys securely">
    * Use environment variables or secret management systems (AWS Secrets Manager, HashiCorp Vault)
    * Never hardcode keys in source code
    * Never commit keys to Git repositories

    ```bash .env theme={null}
    DAYA_SANDBOX_KEY=sk_sandbox_abc123...
    DAYA_PRODUCTION_KEY=sk_live_xyz789...
    ```
  </Accordion>

  <Accordion title="Rotate keys regularly">
    Rotate API keys every 90 days or immediately if compromised:

    1. Generate new key in dashboard
    2. Update your application configuration
    3. Verify new key works
    4. Delete old key
  </Accordion>

  <Accordion title="Implement rate limiting">
    Implement client-side rate limiting to avoid hitting API limits:

    * 100 requests per minute per key
    * 1,000 funding account creations per day (see [Limits](/limits/overview))
  </Accordion>
</AccordionGroup>

## Error Responses

### 401 Unauthorized

Missing or invalid API key:

```json theme={null}
{
  "error": {
    "code": "unauthorized",
    "message": "Invalid or missing API key",
    "details": "Ensure the X-Api-Key header is present and contains a valid API key"
  }
}
```

**Common causes:**

* Missing `X-Api-Key` header
* Empty or malformed API key value
* Invalid or revoked API key
* Using sandbox key with production URL (or vice versa)

### 403 Forbidden

Merchant account frozen or suspended:

```json theme={null}
{
  "error": {
    "code": "merchant_frozen",
    "message": "Merchant account is frozen",
    "details": "Contact support@daya.co for assistance"
  }
}
```

**Why merchants are frozen:**

* Exceeded funding account creation limit (1,000/day)
* Risk or compliance review triggered
* Manual suspension by operations

<Info>
  If your merchant account is frozen, new funding accounts, FX conversions, transfers, and withdrawals are blocked. Contact support for resolution.
</Info>

## Webhook Authentication

Webhooks use **HMAC-SHA256** signatures, not API keys. See [Webhook Verification](/api-reference/webhooks/verification).

## Testing Authentication

Verify your API key works:

<CodeGroup>
  ```bash cURL theme={null}
  curl --request GET \
    --url https://api.sandbox.daya.co/v1/rates?from=NGN \
    --header 'X-Api-Key: YOUR_SANDBOX_KEY'
  ```

  ```javascript JavaScript theme={null}
  // Test authentication
  async function testAuth() {
    const response = await fetch(
      'https://api.sandbox.daya.co/v1/rates?from=NGN',
      {
        headers: { 'X-Api-Key': 'YOUR_SANDBOX_KEY' }
      }
    );

    if (response.ok) {
      console.log('Authentication successful');
    } else {
      console.error('Authentication failed:', response.status);
    }
  }
  ```
</CodeGroup>

Expected response (if successful):

```json theme={null}
{
  "rate_id": "rate_abc123",
  "from": "NGN",
  "to": "USDC",
  "rate": 1545.50,
  ...
}
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Core Concepts" icon="book" href="/concepts/overview">
    Understand funding accounts, deposits, transfers, and rates
  </Card>

  <Card title="Quick Start" icon="rocket" href="/quickstart">
    Create your first funding account
  </Card>
</CardGroup>
