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

# API Reference

> Base URL, headers, and every endpoint available today.

Every endpoint documented here is callable with a merchant API key. Provisioning
and compliance operations are internal and deliberately excluded — if it is not
listed in this reference, it is not part of the merchant API.

## Base URL

```
https://api.spendin.app
```

All routes are versioned under `/v1/`. The version changes only on a breaking
change to a published contract.

## Required headers

| Header            | When                         | Notes                                                       |
| ----------------- | ---------------------------- | ----------------------------------------------------------- |
| `X-API-Key`       | Every request                | See [Authentication](/guides/authentication)                |
| `Idempotency-Key` | Every `POST`, `PUT`, `PATCH` | UUID v4. See [Idempotency](/guides/idempotency)             |
| `X-Request-Id`    | Optional, recommended        | Echoed back and into our logs. See [Errors](/guides/errors) |
| `Content-Type`    | Requests with a body         | `application/json`                                          |

<Note>
  `POST /v1/banks/resolve` is the one exception to the idempotency rule. It is a
  `POST` only to keep an account number out of a query string; it writes nothing, so
  it needs no `Idempotency-Key`.
</Note>

## Conventions

All field names are `snake_case`, in both directions, with no casing
transformation. Timestamps are ISO-8601 UTC. Every monetary amount is paired with a
currency field sharing its prefix.

Status values (`PENDING_PAYMENT`, `SUCCESSFUL`) are **uppercase**. Webhook event
types (`payout.pending_payment`) are lowercase and dotted. They are easy to confuse.

## What's available

<CardGroup cols={2}>
  <Card title="Payouts" icon="paper-plane">
    Create a payout, read one with its status timeline, and list them.
  </Card>

  <Card title="Payment instructions" icon="receipt">
    Fetch the active settlement instruction for a payout.
  </Card>

  <Card title="Rates" icon="chart-line">
    Indicative rates, and executable quotes with a fixed TTL.
  </Card>

  <Card title="Banks" icon="building-columns">
    Institution directory and name enquiry on a destination account.
  </Card>

  <Card title="Inflows" icon="arrow-down-to-arc">
    Your settlements, matched and unmatched.
  </Card>

  <Card title="Outflows" icon="arrow-up-from-arc">
    Every dispatch attempt made against a payout.
  </Card>

  <Card title="Refunds" icon="rotate-left">
    Refund destinations, and the history of money returned to you.
  </Card>

  <Card title="Webhooks" icon="webhook">
    Configure your endpoint, rotate the secret, inspect deliveries.
  </Card>
</CardGroup>

## Endpoint summary

| Method | Path                                          | Scope                       |
| ------ | --------------------------------------------- | --------------------------- |
| `POST` | `/v1/payouts`                                 | `payouts:write`             |
| `GET`  | `/v1/payouts`                                 | `payouts:read`              |
| `GET`  | `/v1/payouts/{id}`                            | `payouts:read`              |
| `GET`  | `/v1/payouts/{payout_id}/payment-instruction` | `payment_instructions:read` |
| `GET`  | `/v1/payouts/{payout_id}/outflows`            | `outflows:read`             |
| `GET`  | `/v1/payouts/{payout_id}/refunds`             | `refunds:read`              |
| `GET`  | `/v1/rates`                                   | `rates:read`                |
| `POST` | `/v1/rates/quotes`                            | `rates:read`                |
| `GET`  | `/v1/rates/quotes/{id}`                       | `rates:read`                |
| `POST` | `/v1/rates/quotes/{id}/accept`                | `rates:read`                |
| `GET`  | `/v1/banks`                                   | `identity:enquiry`          |
| `POST` | `/v1/banks/resolve`                           | `identity:enquiry`          |
| `GET`  | `/v1/inflows`                                 | `inflows:read`              |
| `GET`  | `/v1/inflows/{id}`                            | `inflows:read`              |
| `GET`  | `/v1/outflows/{id}`                           | `outflows:read`             |
| `PUT`  | `/v1/refund-destinations`                     | `refunds:manage`            |
| `GET`  | `/v1/refund-destinations`                     | `refunds:read`              |
| `GET`  | `/v1/refunds`                                 | `refunds:read`              |
| `GET`  | `/v1/refunds/{id}`                            | `refunds:read`              |
| `PUT`  | `/v1/webhooks/config`                         | `webhooks:manage`           |
| `GET`  | `/v1/webhooks/config`                         | `webhooks:manage`           |
| `POST` | `/v1/webhooks/config/rotate-secret`           | `webhooks:manage`           |
| `GET`  | `/v1/webhooks/deliveries`                     | `webhooks:manage`           |

Every operation declares its requirement as `x-required-scopes`. A key missing it
gets `403 INSUFFICIENT_SCOPES`, and the response names the scope it wanted.

## Pagination

`GET /v1/payouts`, `/v1/inflows`, `/v1/refunds`, and `/v1/webhooks/deliveries` are
cursor-paginated and return a `{ data, meta }` envelope. Every other list endpoint
returns a bare array. See [Pagination](/guides/pagination).

## No write endpoints for pipeline records

Inflows, outflows, payment instructions, and refunds are all system-generated.
There is no way to create, mutate, or cancel one through the API — they are the
record of what happened, and the only write you make is `POST /v1/payouts`.
