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

# Validate API Key

> Confirm a Bill Payment key works and which environment it belongs to

## Overview

Verifies your Bill Payment API key and echoes back who you are and which environment the key is bound to. It is the first call to make in a new integration and the safest way to prove, before you move any money, that you are pointed at sandbox rather than production.

<Note>
  Each key is bound to exactly one environment — `SANDBOX` or `PRODUCTION`. The environment is a property of the key we issue you. **Never derive it from the text or the prefix of the key**; read `key.type` from this endpoint.
</Note>

Bill Payment lives on `https://billapi.oneclickdz.com`, not on the base URL used by the rest of the platform. The header is the same one you already use: `X-Access-Token`.

## Response

<ResponseField name="success" type="boolean" required>
  `true` when the key was verified.
</ResponseField>

<ResponseField name="data" type="object" required>
  <Expandable title="properties">
    <ResponseField name="account" type="object" required>
      <Expandable title="properties">
        <ResponseField name="id" type="string" required>
          Your partner account identifier.
        </ResponseField>

        <ResponseField name="status" type="string" required>
          `ACTIVE` for a key that passed verification.
        </ResponseField>

        <ResponseField name="currency" type="string" required>
          Always `DZD`.
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="key" type="object" required>
      <Expandable title="properties">
        <ResponseField name="type" type="string" required>
          `SANDBOX` or `PRODUCTION`. The only reliable statement of which environment this key acts in.
        </ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="meta" type="object" required>
  <Expandable title="properties">
    <ResponseField name="timestamp" type="string" required>
      Response time, ISO 8601 UTC.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="requestId" type="string" required>
  Correlation identifier, also sent as the `X-Request-Id` response header.
</ResponseField>

## Examples

<CodeGroup>
  ```bash cURL theme={null}
  curl https://billapi.oneclickdz.com/v3/validate \
    -H "X-Access-Token: YOUR_API_KEY"
  ```

  ```javascript Node.js theme={null}
  const response = await fetch("https://billapi.oneclickdz.com/v3/validate", {
    headers: { "X-Access-Token": process.env.ONECLICKDZ_API_KEY },
  });

  const body = await response.json();

  if (!body.success) {
    throw new Error(`${body.error.code}: ${body.error.message}`);
  }

  console.log(`Account ${body.data.account.id} — ${body.data.key.type}`);
  ```

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

  response = requests.get(
      'https://billapi.oneclickdz.com/v3/validate',
      headers={'X-Access-Token': os.getenv('ONECLICKDZ_API_KEY')}
  )

  body = response.json()

  if not body['success']:
      raise RuntimeError(f"{body['error']['code']}: {body['error']['message']}")

  print(f"Account {body['data']['account']['id']} — {body['data']['key']['type']}")
  ```

  ```php PHP theme={null}
  <?php
  $ch = curl_init('https://billapi.oneclickdz.com/v3/validate');
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_HTTPHEADER, [
      'X-Access-Token: ' . getenv('ONECLICKDZ_API_KEY')
  ]);

  $body = json_decode(curl_exec($ch), true);
  curl_close($ch);

  if (!$body['success']) {
      throw new Exception($body['error']['code'] . ': ' . $body['error']['message']);
  }

  echo "Account {$body['data']['account']['id']} — {$body['data']['key']['type']}";
  ?>
  ```
</CodeGroup>

### Success Response

```json theme={null}
{
  "success": true,
  "data": {
    "account": {
      "id": "partner_7f21",
      "status": "ACTIVE",
      "currency": "DZD"
    },
    "key": {
      "type": "SANDBOX"
    }
  },
  "meta": {
    "timestamp": "2026-08-31T10:15:32.194Z"
  },
  "requestId": "req_9f3a1c72e0b84d51aB3xZq07"
}
```

## Error Responses

<AccordionGroup>
  <Accordion title="401 — Missing access token">
    **The `X-Access-Token` header was not sent.**

    ```json theme={null}
    {
      "success": false,
      "error": {
        "code": "MISSING_ACCESS_TOKEN",
        "message": "X-Access-Token header is required."
      },
      "requestId": "req_9f3a1c72e0b84d51aB3xZq07"
    }
    ```

    **What to do:** add the header. Bill Payment accepts the key in that header only — never in a query string or a request body.
  </Accordion>

  <Accordion title="401 — Invalid access token">
    **The key was rejected.**

    ```json theme={null}
    {
      "success": false,
      "error": {
        "code": "INVALID_ACCESS_TOKEN",
        "message": "The provided access token is invalid."
      },
      "requestId": "req_9f3a1c72e0b84d51aB3xZq07"
    }
    ```

    **What to do:** check for a copy-and-paste error, then contact support. Retrying the same key will not change the answer.
  </Accordion>

  <Accordion title="503 — Authentication unavailable">
    **We could not verify your key in time. Your key is not the problem.**

    ```json theme={null}
    {
      "success": false,
      "error": {
        "code": "AUTH_UNAVAILABLE",
        "message": "Authentication is temporarily unavailable. Please retry shortly."
      },
      "requestId": "req_9f3a1c72e0b84d51aB3xZq07"
    }
    ```

    **What to do:** wait for the `Retry-After` header (5 seconds) and retry. Never surface this to your customer as an invalid-credentials error, and never disable the key because of it.
  </Accordion>

  <Accordion title="503 — Service unavailable">
    **The Bill Payment API is in planned maintenance.**

    ```json theme={null}
    {
      "success": false,
      "error": {
        "code": "SERVICE_UNAVAILABLE",
        "message": "The service is temporarily unavailable. Please retry shortly."
      },
      "requestId": "req_9f3a1c72e0b84d51aB3xZq07"
    }
    ```

    **What to do:** honour `Retry-After` and retry.
  </Accordion>
</AccordionGroup>

## Confirming your environment before go-live

Run this check at start-up, and again in your deployment pipeline. A single line of output tells you whether the key in that environment's configuration is the one you meant to ship.

```javascript theme={null}
async function assertEnvironment(expected) {
  const response = await fetch("https://billapi.oneclickdz.com/v3/validate", {
    headers: { "X-Access-Token": process.env.ONECLICKDZ_API_KEY },
  });

  const body = await response.json();

  if (!body.success) {
    throw new Error(`Key check failed: ${body.error.code}`);
  }

  if (body.data.key.type !== expected) {
    throw new Error(
      `Wrong key: expected ${expected}, got ${body.data.key.type}`,
    );
  }

  return body.data.account.id;
}

// In your sandbox deployment
await assertEnvironment("SANDBOX");
```

<Warning>
  A sandbox key and a production key are interchangeable in shape but not in effect. A production key moves real money on the first successful payment. Verify `key.type` before you enable the payment path.
</Warning>

## What this endpoint does not return

Bill Payment keys have no scopes, no expiry field and no per-key balance, so none of those appear here. `account`, `key.type`, `meta` and `requestId` are the whole response.

## Best Practices

<CardGroup cols={2}>
  <Card title="Call it at start-up" icon="power-off">
    One call at boot proves the key works and names the environment, before any customer traffic reaches the payment path.
  </Card>

  <Card title="Never log the key" icon="key">
    Log `account.id` and `key.type` instead. The key itself belongs in a secret store, never in application logs.
  </Card>

  <Card title="Separate the two keys" icon="code-compare">
    Keep the sandbox and production keys in different configuration stores so neither can be reached from the other environment.
  </Card>

  <Card title="Treat 503 as transient" icon="clock-rotate-left">
    `AUTH_UNAVAILABLE` means we could not answer in time. Retry after `Retry-After`; do not roll the key.
  </Card>
</CardGroup>

## Related Endpoints

<CardGroup cols={2}>
  <Card title="List Partners" icon="building-columns" href="/en/api-reference/bill-payment/list-partners">
    Check which partners are available
  </Card>

  <Card title="Discover Bills" icon="magnifying-glass-dollar" href="/en/api-reference/bill-payment/discover-bills">
    Start a bill discovery
  </Card>

  <Card title="Bill Payment Overview" icon="file-invoice-dollar" href="/en/bill-payment-guides/overview">
    How the whole flow fits together
  </Card>

  <Card title="Sandbox Testing" icon="flask" href="/en/bill-payment-guides/6-sandbox-testing">
    Test every outcome before go-live
  </Card>
</CardGroup>
