# UTERLAB Merchant API v1

Public documentation for **Merchant → UTERLAB** integration.

## Base URL

`https://YOUR-UTERLAB-DOMAIN/api/v1`

## Authentication

Every protected request uses:

- `X-API-Key`
- `X-Timestamp` — Unix timestamp, allowed window ±60 seconds
- `X-Nonce` — unique value for every request
- `X-Signature` — HMAC-SHA256

Signature source:

```text
timestamp\nnonce\nMETHOD\n/path\nraw_body
```

`X-Signature = HMAC-SHA256(signature_string, secret)`

Never expose the API secret in browser/client-side code.

## Endpoints

| Method | Endpoint | Scope |
|---|---|---|
| GET | `/api/v1/balance` | `balance:read` |
| GET | `/api/v1/methods` | `methods:read` |
| GET | `/api/v1/banks` | `banks:read` |
| POST | `/api/v1/orders` | `orders:create` |
| GET | `/api/v1/orders/{external_id}` | `orders:read` |
| POST | `/api/v1/orders/{external_id}/cancel` | `orders:cancel` |
| POST | `/api/v1/orders/{external_id}/payment-received` | `orders:dispute` |
| POST | `/api/v1/orders/{external_id}/check-payment` | `orders:dispute` |
| GET | `/api/v1/payout-methods` | `payout-methods:read` |
| POST | `/api/v1/payouts` | `payouts:create` |
| GET | `/api/v1/payouts/{external_id}` | `payouts:read` |
| POST | `/api/v1/payouts/{external_id}/cancel` | `payouts:cancel` |

## Create order

`POST /api/v1/orders`

```json
{
  "external_id": "ORDER-10001",
  "amount": "15000.00",
  "currency": "RUB",
  "method": "c2c",
  "bank_code": "sber"
}
```

Successful response:

```json
{
  "success": true,
  "data": {
    "external_id": "ORDER-10001",
    "status": "active",
    "amount": "15000.0000",
    "rate": "95.42000000",
    "amount_usdt": "157.1997",
    "expires_at": "2026-10-14 21:30:00",
    "payment": {
      "bank_code": "sber",
      "bank_name": "СберБанк",
      "requisite": "2202201234567890",
      "holder_name": "Иван И."
    }
  }
}
```

No requisites:

```json
{
  "success": false,
  "message": "No available requisites",
  "data": {
    "external_id": "ORDER-10001",
    "status": "failed",
    "amount": "15000.0000",
    "currency": "RUB"
  }
}
```

## Payment received

`POST /api/v1/orders/{external_id}/payment-received`

Requires `multipart/form-data` with exactly one receipt:

- `comment`
- `receipt` — required

Limit: 1 file, up to 2 MB, JPG/JPEG/PNG/WEBP/PDF.

## Payouts

`POST /api/v1/payouts`

```json
{
  "external_id": "PAYOUT-10001",
  "amount": "10000.00",
  "currency": "RUB",
  "method": "card_rub",
  "bank_code": "sber",
  "requisite": "2202201234567890",
  "recipient_name": "Иван Иванов"
}
```

For SBP, bank is required. Pass `bank_code` or `bank_name`.

## Order statuses

`new`, `active`, `completed`, `cancelled`, `expired`, `dispute`, `failed`.

## Common HTTP errors

- `401` — API key/signature/timestamp error
- `403` — scope/IP/access error
- `409` — replayed nonce or state conflict
- `422` — invalid data or no available requisites
- `429` — rate limit exceeded

Error format:

```json
{"success":false,"message":"Invalid signature"}
```

Only Merchant → UTERLAB integration is public. Reverse UTERLAB → Merchant integrations are configured by UTERLAB administrators and are not part of this public document.


## Изменения 1.1.10

См. [UPDATE-1.1.10.md](UPDATE-1.1.10.md): callback-токен и идентификаторы исходящего каскада, сверка неизвестных результатов, безопасная отмена и повторная доставка webhook.
