<div class="pp-hero" markdown>
<p class="pp-eyebrow">Payment API · v1</p>

# Accept SBP and card payments through one API

You create a payment. The API issues the transfer requisites, watches for the money
and sends you a signed callback when it arrives.

[Quickstart in 15 minutes](quickstart.md){ .md-button .md-button--primary }
[Request signing](signing.md){ .md-button }
</div>

## Integration in five steps { #five-steps }

<ol class="pp-steps">
<li><strong>Project and token</strong>Create a project in the cabinet and issue an API token.</li>
<li><strong>Signing key</strong>Generate an Ed25519 key and upload the public part to the cabinet.</li>
<li><strong>Callback</strong>Set a notification URL and issue a callback signing secret.</li>
<li><strong>Payment</strong>Send a signed <code>POST /api/v1/payments</code> and show the requisites to the payer.</li>
<li><strong>Result</strong>Receive the callback, verify its signature and mark the order as paid.</li>
</ol>

<div class="pp-seq" data-lanes="Your server|API|Payer" markdown>

1. **Your server → API.** `POST /api/v1/payments`, Ed25519 signature
2. **API ⇢ Your server.** `201`: `status=processing`, requisites, recipient and bank
3. **Your server → Payer.** You show the requisites, amount and deadline
4. **Payer.** Transfers via SBP or to the card in their bank app
5. **API → Your server.** Callback `status=completed`, HMAC-SHA256 signature
6. **Your server ⇢ API.** You reply `2xx`

</div>

## Where to go next { #next }

<div class="grid cards pp-bento" markdown>

-   :material-lightning-bolt:{ .lg } **[SBP payments](sbp.md)**

    ---

    Payment request, what to show the payer, statuses, polling and edge cases.

-   :material-credit-card-outline:{ .lg } **[Card payments](card.md)**

    ---

    Transfer to a card: how it differs from SBP and what to show the payer.

-   :material-signature-freehand:{ .lg } **[Request signing](signing.md)**

    ---

    RFC 9421 and Ed25519: ready-made functions and a shared test vector.

-   :material-bell-ring-outline:{ .lg } **[Callbacks](callbacks.md)**

    ---

    Result notifications and HMAC signature verification.

-   :material-alert-circle-outline:{ .lg } **[Statuses and errors](statuses.md)**

    ---

    Every status, error code and when to retry.

-   :material-robot-outline:{ .lg } **[For AI agents](ai-agents.md)**

    ---

    llms.txt, Markdown pages and the docs MCP server.

</div>

## Environments { #environments }

Addresses in these docs are written as placeholders; substitute your own values:

- `{{base_url}}` is the API address issued to you when you are connected. The sandbox and
  production each have their own. Request examples put `{{base_url}}` before the path:
  `POST {{base_url}}/api/v1/payments`.
- `{{cabinet_url}}` is the merchant cabinet address. You receive it together with your access.

| Environment | API address | Cabinet | Token prefix |
| --- | --- | --- | --- |
| Sandbox | sandbox `{{base_url}}` | sandbox `{{cabinet_url}}` | `nl_test_` |
| Production | production `{{base_url}}` | production `{{cabinet_url}}` | `nl_live_` |

Keep `{{base_url}}` in your app configuration, not in code: going live then changes one
setting.

The sandbox behaves like production: same signing, limits and errors. The only
difference is that no money moves. See [Sandbox](sandbox.md).

## General API conventions { #conventions }

- **Format.** Requests and responses are UTF-8 JSON. Parsing is strict: an unknown field
  or trailing data after the object returns `400 bad_request`.
- **Access.** Every request carries `Authorization: Bearer <project token>`.
- **Signature.** Every write request is signed with an Ed25519 key per
  [RFC 9421](signing.md). Payments cannot be created without a signature, neither in the
  sandbox nor in production.
- **Amounts.** `amount` is in major currency units: `3400` or `"3400.50"` roubles. USDT
  amounts in `merchant_information` are decimal strings: `"34.0000"`; the rate `course` and
  fee `rate` are numbers with two decimals: `100.00`.
- **Time.** All timestamps are RFC 3339 in UTC, for example `2026-09-28T12:00:00Z`.
- **Errors.** The error body is `{"error":"<code>"}`. See
  [Statuses and errors](statuses.md) for the list.
- **Tracing.** The `X-Request-ID` request header is echoed in the response. Log it:
  support finds your request by it.

## API methods { #endpoints }

| Method | What it does | Signature |
| --- | --- | --- |
| `POST /api/v1/payments` | Creates a pay-in | always |
| `GET /api/v1/payments/{id}` | Returns a payment by `id` | if the project policy requires it |
| `GET /api/v1/project` | Shows the project and token scopes | if the project policy requires it |

Field-level details are in the [API reference](api-reference.md).