# Technical reference documentation (/docs/server-to-server/technical-reference-documentation)

## About this reference [#about-this-reference]

The endpoint and field reference for the Precium card API. Interactive documentation and ready-to-run request collections are linked below; the tables on this page are the quick reference for the card surface.

| Resource | Link |
|---|---|
| **Interactive API reference** | [gate.reviopay.com/api/](https://gate.reviopay.com/api/) |
| **Postman collection** | Server-to-server merchant samples — request access from [support@precium.com](mailto:support@precium.com) |

<Callout type="info">
If you cannot open the Postman collection, contact support rather than assuming you lack permission — access is granted per workspace member.
</Callout>

## Base URL [#base-url]

```text
https://gate.reviopay.com/api/v1/
```

Every path below is relative to that base. Test and production share this URL; the API key you send selects the environment.

## Authentication [#authentication]

Bearer token on every request. Two credentials, from two different places.

| Key | Scope |
|---|---|
| **Bearer token** | All endpoints on this page. Developers section of your dashboard |
| **S2S token** | Card data submission to a purchase's `direct_post_url` only. Issued by Precium to qualifying merchants, **not on the dashboard** |

```text
Authorization: Bearer <api_key>
```

Creating a purchase also requires your `brand_id`.

## Purchases [#purchases]

| Method | Path | Purpose |
|---|---|---|
| POST | `/purchases/` | Create a purchase — the primary request for any integration |
| GET | `/purchases/{id}/` | Retrieve a purchase, including `transaction_data.attempts[]` |
| POST | `/purchases/{id}/charge/` | Charge or hold using a saved token |
| POST | `/purchases/{id}/capture/` | Capture a previously authorised payment |
| POST | `/purchases/{id}/release/` | Release funds on hold |
| POST | `/purchases/{id}/refund/` | Refund a paid purchase, fully or partially |
| POST | `/purchases/{id}/cancel/` | Cancel a pending purchase |
| POST | `/purchases/{id}/mark_as_paid/` | Mark a purchase paid — for payments settled outside Precium |
| POST | `/purchases/{id}/delete_recurring_token/` | Delete the token stored against this purchase |
| POST | `/purchases/{id}/resend_invoice/` | Re-send the invoice email |

### Creating a purchase — request fields [#creating-a-purchase--request-fields]

Three fields are required: a client (as `client_id` or an inline `client` object), `purchase`, and `brand_id`.

| Field | Type | Required | Notes |
|---|---|---|---|
| `brand_id` | string (uuid) | **Yes** | From your dashboard |
| `client_id` | string (uuid) | Either this… | An existing client |
| `client` | object | …or this | Inline client; found or created by `email` |
| `purchase` | object | **Yes** | Container for `currency`, `products`, `language` |
| `purchase.currency` | string | **Yes** | ISO 4217, e.g. `ZAR` |
| `purchase.products` | array | **Yes** | Each item needs `name` and `price` |
| `purchase.products[].price` | integer | **Yes** | **In cents.** 149900 = R1,499.00 |
| `reference` | string | No | Your own order identifier |
| `skip_capture` | boolean | No | Authorise only. With a zero total, becomes preauthorisation |
| `force_recurring` | boolean | No | Store the card; the purchase id becomes the token |
| `payment_method_whitelist` | array | No | Restrict accepted methods |
| `send_receipt` | boolean | No | Email a receipt on payment |
| `success_redirect` | string (url) | No* | *Required together with `failure_redirect` for direct post |
| `failure_redirect` | string (url) | No* | See above |
| `cancel_redirect` | string (url) | No | Where a cancelled payment returns |
| `success_callback` | string (url) | No | Per-purchase callback. Verify with `GET /public_key/` |
| `due` | integer | No | Due date, Unix timestamp |
| `purchase.due_strict` | boolean | No | Block payment after the due date |

<Callout type="warning">
**Booleans must be sent as booleans**, not strings — `true`, not `"true"`. The same applies to amounts: integers, not quoted numbers.
</Callout>

### Response fields worth keeping [#response-fields-worth-keeping]

| Field | Notes |
|---|---|
| `id` | The purchase id. Also the card token when `is_recurring_token` is true |
| `status` | See the lifecycle table in the *Integration guide* |
| `checkout_url` | Precium-hosted payment page |
| `direct_post_url` | Card submission endpoint. Null unless both redirects were supplied |
| `is_recurring_token` | True once a card has been stored against this purchase |
| `refund_availability` | `all`, `full_only`, `partial_only`, `pis_all`, `pis_partial` or `none` |
| `refundable_amount` | Amount still available to refund |
| `transaction_data.attempts[]` | Attempt history, newest first. `.error` carries the failure code |
| `marked_as_paid` | True if settled via `/mark_as_paid/` rather than through the gateway |

## Direct post fields [#direct-post-fields]

Posted to a purchase's `direct_post_url`. Add `?s2s=true` for server-side submission with the S2S key.

| Field | Format |
|---|---|
| `pm` | Payment method, e.g. `visa` |
| `cardholder_name` | Latin letters, space, apostrophe, dot, dash. Max 30 |
| `card_number` | Digits only, no whitespace. Max 19 |
| `expires` | `MM/YY` — two digits, slash, two digits |
| `cvc` | 3 or 4 digits |
| `remember_card` | `on` to store the card |

<Callout type="warning">
Validation failures are returned as payment failures, so validate client-side first.
</Callout>

## Clients [#clients]

| Method | Path | Purpose |
|---|---|---|
| POST | `/clients/` | Create a client. `email` required and unique |
| GET | `/clients/` | List clients. Filter with `q`, `email` or `phone` |
| GET | `/clients/{id}/` | Retrieve a client |
| PUT / PATCH | `/clients/{id}/` | Replace or partially update |
| DELETE | `/clients/{id}/` | Delete a client |
| GET | `/clients/{id}/feed/` | Purchases and refunds for this client |
| GET | `/clients/{id}/recurring_tokens/` | Stored cards |
| GET / DELETE | `/clients/{id}/recurring_tokens/{token_id}/` | Retrieve or remove a stored card |

Client fields include `email`, `full_name`, `phone`, `personal_code` (identity number, used for DebiCheck), billing and shipping address fields, `bank_account`, `bank_code`, and `cc` / `bcc` arrays for receipt copies.

## Payment methods [#payment-methods]

```bash
GET https://gate.reviopay.com/api/v1/payment_methods/?brand_id={brand_id}&currency=ZAR
```

Returns the methods actually enabled for that brand and currency. Send it with the same key you will create the purchase with — the key determines whether the lookup runs against test or live configuration. Prefer this over a hard-coded list.

## Webhooks [#webhooks]

| Method | Path | Purpose |
|---|---|---|
| POST | `/webhooks/` | Create a webhook. Requires `title`, `callback`, `events` |
| GET | `/webhooks/` | List webhooks |
| GET | `/webhooks/{id}/` | Retrieve a webhook, including its `public_key` |
| PUT / PATCH | `/webhooks/{id}/` | Replace or partially update |
| DELETE | `/webhooks/{id}/` | Delete a webhook |
| GET | `/webhooks/deliveries/` | Delivery history for one object |

`/webhooks/deliveries/` requires both `id` and `source_type` — the latter being `Purchase`, `Payment`, `Payout` or `BillingTemplateClient`. It returns every attempt, including failures and retries.

## Callback verification [#callback-verification]

```bash
GET https://gate.reviopay.com/api/v1/public_key/
```

Returns the PEM-encoded RSA public key for verifying per-purchase `success_callback` payloads. For webhook subscriptions, use `public_key` on the webhook object instead.

Every callback carries an `X-Signature` header: a base64-encoded RSA PKCS#1 v1.5 signature of the SHA-256 digest of the raw request body. Verify the raw bytes before parsing.

## Reporting [#reporting]

| Method | Path | Purpose |
|---|---|---|
| GET | `/balance/` | Balance data |
| GET | `/account/json/balance/` | Company balance |
| GET | `/account/json/turnover/` | Company turnover |
| POST | `/company_statements/` | Schedule statement generation |
| GET | `/company_statements/` | List generated statements |

Reconciliation file formats and settlement reporting are covered in *Reconciliation*.

## Conventions [#conventions]

| Topic | Behaviour |
|---|---|
| **Amounts** | Integers, in cents, always |
| **Identifiers** | UUIDs |
| **Timestamps** | Unix seconds on request fields; ISO 8601 on responses |
| **Pagination** | Cursor-based: `results` with `next` and `previous`. Follow `next` |
| **Rate limits** | 10 transactions per second, per IP address. `429` when exceeded |
| **Idempotency** | No idempotency key. A purchase may be paid only once; repeats return `409` |
| **Trailing slashes** | Required. Paths are case-sensitive — `/purchases/`, never `/Purchases/` |

## Status codes [#status-codes]

| Code | Meaning |
|---|---|
| `200` / `201` | Success / created |
| `204` | Deleted |
| `400` | Validation error, or a failed capture, release or refund — check the error code |
| `401` | Invalid or missing API key |
| `403` | Key valid but not permitted for this operation or brand |
| `404` | Not found — often a case-sensitivity or trailing-slash error |
| `409` | Conflict; typically an already-paid purchase |
| `429` | Rate limited |
| `500` | Server error. Safe to retry idempotent reads |

Full error codes with causes and retry guidance are in *Error mapping*; issuer decline codes are in *Issuer response codes*.
