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

# BillStack API Overview

> Learn how the BillStack API works : base URL, authentication, response shapes, pagination, and idempotency.

The BillStack API gives you programmatic access to virtual accounts, transactions, and webhooks so you can collect payments and receive real-time notifications from your own systems. Every interaction follows a consistent set of conventions : once you understand them here, they apply uniformly across every endpoint in this reference.

## Base URL

All API requests are made over HTTPS to the following base URL:

```text theme={null}
https://api.billstack.co/v2
```

There is no trailing slash. Every endpoint path in this reference is appended directly to this base URL (e.g., `https://api.billstack.co/v2/reserved-accounts`).

## Request & Response Format

All request bodies must be JSON, and all responses are returned as JSON. Set the `Content-Type` header on every request that includes a body:

```http theme={null}
Content-Type: application/json
```

You do not need to set an `Accept` header : the API always responds with `application/json`.

## Authentication

Authenticate your requests by passing your **secret key** as a Bearer token in the `Authorization` header:

```http theme={null}
Authorization: Bearer Bill_Stack-SEC-KEY-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```

Requests made without a valid, active key receive a `401 Unauthorized` response. See the [Authentication](/api-reference/authentication) page for full details on public vs. secret keys and how to rotate them.

## Response Envelope

Every API response : success or error : is wrapped in the same envelope. It always contains a boolean `status`, a human-readable `message`, and a `data` field. List responses additionally include a `meta` object with pagination details:

```json theme={null}
{
  "status": true,
  "message": "OK",
  "data": { ... },
  "meta": {
    "total": 50,
    "page": 1,
    "pageSize": 20,
    "totalPages": 3
  }
}
```

On failure, `status` is `false`, `message` describes what went wrong, and `data` is `null`:

```json theme={null}
{
  "status": false,
  "message": "Invalid or inactive secret key",
  "data": null
}
```

Check the boolean `status` field to determine success or failure, and read `message` for context. See the [Errors](/api-reference/errors) reference for HTTP status codes and how to handle them.

## Pagination

All list endpoints support page-based pagination via two query parameters:

<ParamField query="page" default="1" type="integer">
  The page number to retrieve. Starts at `1`.
</ParamField>

<ParamField query="pageSize" default="20" type="integer">
  The number of results to return per page.
</ParamField>

The response `meta` object tells you where you are in the full result set:

<ResponseField name="meta" type="object">
  Pagination metadata included on all list responses.

  <Expandable title="meta fields">
    <ResponseField name="meta.total" type="integer">
      Total number of records matching the query across all pages.
    </ResponseField>

    <ResponseField name="meta.page" type="integer">
      The current page number.
    </ResponseField>

    <ResponseField name="meta.pageSize" type="integer">
      The number of records returned per page.
    </ResponseField>

    <ResponseField name="meta.totalPages" type="integer">
      The total number of pages available for this query.
    </ResponseField>
  </Expandable>
</ResponseField>

To page through a full result set, request `page=1`, then keep incrementing `page` until it reaches `meta.totalPages`.

## Idempotency

When you initiate a transfer, you can include an `idempotency_key` in the request body to safely retry without risking a duplicate payout. If a transfer with the same key has already been accepted for your account, BillStack returns the existing transfer instead of creating a second one.

```json theme={null}
{
  "idempotency_key": "a8098c1a-f86e-11da-bd1a-00112444be1e",
  "amount": 5000,
  "...": "..."
}
```

Use a UUID or another sufficiently random string as your key, and generate a fresh one per distinct transfer.

<Warning>
  Always include an `idempotency_key` when initiating a transfer. Without it, a network timeout that prompts a retry could send the same payout twice.
</Warning>

***

## Explore the API

<CardGroup cols={2}>
  <Card title="Authentication" icon="key" href="/authentication">
    Learn how to obtain, use, and rotate your public and secret keys.
  </Card>

  <Card title="Errors" icon="circle-exclamation" href="/errors">
    Browse the HTTP status codes BillStack returns and how to handle them gracefully.
  </Card>

  <Card title="Create Virtual Account" icon="building-columns" href="/create-account">
    Provision a virtual bank account to start collecting payments for a customer.
  </Card>

  <Card title="Webhooks" icon="bolt" href="/webhooks">
    Receive and verify real-time payment and transaction events on your server.
  </Card>
</CardGroup>
