# Payment API

> Maak en beheer crypto-betalingssessies met de Payment API van 2328.io.

Met de Payment API kun je betalingssessies aanmaken, klanten doorverwijzen naar een gehoste checkout en de status van betalingen volgen.

## Betaling aanmaken

Maakt een betalingssessie aan en geeft een URL terug waarmee de klant kan betalen.

### Verzoekparameters

| Veld | Type | Vereist | Beschrijving | Waarden |
|------|------|---------|--------------|---------|
| `amount` | decimal | ja | Betalingsbedrag in de valuta, bijv. `100.00` |  |
| `currency` | string | ja | Fiatvaluta (USD, EUR, RUB, …) of cryptovaluta (USDT, TRX, BTC, …) | `USD`, `EUR`, `RUB`, `KZT`, `UAH`, `UZS`, `USDT`, `USDC`, `BTC`, `ETH`, `GRAM`, `SOL`, `TRX`, `BNB`, `POL`, `LTC`, `DASH`, `DOGE`, `ZEC`, `XRP`, `XMR` |
| `order_id` | string | ja | Je order-ID, bijv. `ORDER-12345` (max. 128 tekens) |  |
| `to_currency` | string | nee | Vooraf geselecteerde cryptovaluta | `USDT`, `USDC`, `BTC`, `ETH`, `GRAM`, `SOL`, `TRX`, `BNB`, `POL`, `LTC`, `DASH`, `DOGE`, `ZEC`, `XRP`, `XMR` |
| `network` | string | nee\* | Netwerkcode (verplicht als `to_currency` is ingesteld of als `currency` een cryptovaluta is) | `TRX-TRC20`, `ETH-ERC20`, `BASE`, `BSC-BEP20`, `AVAX-C`, `POL-MATIC`, `TON`, `SOL`, `BTC`, `LTC`, `DASH`, `DOGE`, `ZEC`, `XRP`, `XMR` |
| `url_return` | string | nee | Redirect-URL na betaling, bijv. `https://your-site.com/return` |  |
| `url_success` | string | nee | Alternatief voor `url_return` |  |
| `url_callback` | string | ja | URL voor webhook-meldingen, bijv. `https://your-site.com/webhook` |  |
| `invite_code` | string | nee | Verwijzerscode |  |
| `fee_split` | decimal | nee | Aandeel van de merchantfee dat aan de betaler wordt doorberekend, 0–100 (%). 0 = merchant betaalt volledig, 100 = betaler betaalt volledig. Overschrijft de project-instelling. **Voorbeeld: `30`** (betaler dekt 30% van de fee). |  |
| `price_markup` | decimal | nee | Toeslag of korting op het factuurbedrag, −99 tot 100 (%). Overschrijft de project-instelling. **Voorbeeld: `5`** (+5%) of `-10` (10% korting). |  |
| `description` | string | nee | Optionele factuurbeschrijving (max. 200 tekens). Wordt op de betaalpagina aan de betaler getoond. **Voorbeeld: `Premium plan — Order #12345`**. |  |
| `ttl_seconds` | int | nee | Levensduur van de factuur in seconden, van `300` (5 minuten) tot `86400` (24 uur). Daarna vervalt de factuur en kan deze niet meer worden betaald. Standaard: `3600` (1 uur). **Voorbeeld: `3600`**. |  |

### Response

```json
{
  "state": 0,
  "result": {
    "uuid": "abc123-def456-...",
    "order_id": "ORDER-12345",
    "amount": "100.00",
    "currency": "USD",
    "amount_usd": "100.00",
    "exchange_rate": null,
    "url": "https://2328.io/pay/abc123-def456-...",
    "tg_deeplink": "https://t.me/my2328bot?start=pay_abc123-def456-...",
    "expires_at": "2026-01-11T21:00:00Z",
    "created_at": "2026-01-11T20:00:00Z",
    "payer_currency": "USDT",
    "payer_amount": "100.50",
    "network": "TRX-TRC20",
    "address": "TXYZabc123...",
    "payment_status": "check",
    "txid": null,
    "payment_amount": null,
    "qr": "data:image/png;base64,iVBORw0..."
  }
}
```

- Verwijs de klant door naar `result.url` om de betaling te voltooien.
- `tg_deeplink` — Telegram-bot-deeplink voor betaling via de Telegram MiniApp.
- `qr` — base64-gecodeerde QR-code (data URI) van het stortingsadres. Aanwezig wanneer er al een adres is toegewezen (wanneer `network` samen met `to_currency` is ingesteld, of wanneer `currency` een cryptovaluta is); anders `null`.
- `txid`, `payment_amount` — `null` totdat de klant betaalt. Worden ingevuld zodra de transactie on-chain is gedetecteerd. Luister naar de `payment_status: paid`-webhook om te weten wanneer.
- `exchange_rate` — `null` als conversie nog niet van toepassing is (bijv. wisselkoers fiat → crypto is nog niet vastgelegd). Wordt ingevuld zodra een betalersvaluta is gekozen.

> Use your project UUID and the endpoint-appropriate API key from the merchant dashboard.

#### Interactive request: `POST /v1/payment`
  - `amount` (decimal, required)
  - `currency` (enum, required): USD,EUR,RUB,KZT,UAH,UZS,USDT,USDC,BTC,ETH,GRAM,SOL,TRX,BNB,POL,LTC,DASH,DOGE,ZEC,XRP,XMR
  - `order_id` (string, required)
  - `to_currency` (enum): USDT,USDC,BTC,ETH,GRAM,SOL,TRX,BNB,POL,LTC,DASH,DOGE,ZEC,XRP,XMR
  - `network` (enum): TRX-TRC20,ETH-ERC20,BASE,BSC-BEP20,AVAX-C,POL-MATIC,TON,SOL,BTC,LTC,DASH,DOGE,ZEC,XRP,XMR
  - `url_return` (string)
  - `url_success` (string)
  - `url_callback` (string, required)
  - `invite_code` (string)
  - `fee_split` (decimal)
  - `price_markup` (decimal)
  - `description` (string)
  - `ttl_seconds` (integer)

## Gehoste checkout, H2H en exacte crypto-bedragen

Dezelfde endpoint ondersteunt drie verschillende factuurvormen. Kies er bewust één; mix hun bedragsemantiek niet.

### Gehoste checkout met keuze voor betaler

Verzend `amount`, `currency`, `order_id` en `url_callback`, maar laat `to_currency` en `network` weg. De respons bevat `result.url`; `address`, `qr` en soms betaler-velden blijven `null` totdat de betaler een richting kiest op de gehoste pagina.

```json
{
  "amount": "125.00",
  "currency": "EUR",
  "order_id": "ORDER-2026-1042",
  "url_callback": "https://merchant.example/webhooks/2328",
  "url_return": "https://merchant.example/orders/ORDER-2026-1042"
}
```

### Direct-adres H2H factuur

Stuur zowel `to_currency` als `network`. 2328.io maakt de blockchainfactuur aan tijdens het API-verzoek, zodat een succesvolle respons kan worden weergegeven binnen uw checkout zonder de klant door te verwijzen.

```json
{
  "amount": "100.00",
  "currency": "USD",
  "to_currency": "USDT",
  "network": "TRX-TRC20",
  "order_id": "ORDER-2026-1043",
  "url_callback": "https://merchant.example/webhooks/2328"
}
```

Geef deze waarden exact weer zoals teruggestuurd:

- `payer_amount` en `payer_currency` — de betalingsinstructie;
- `network` en `address` — de enige bestemming voor deze factuur;
- `qr` — een data-URI voor hetzelfde adres;
- `expires_at` — de factuurdeadline;
- `url` — een nuttige gehoste fallback wanneer de aangepaste checkout niet kan worden voltooid.

> **DANGER:** Genereer of vervang nooit een adres, hergebruik geen adres van een andere factuur, of bereken `payer_amount` uit een publieke spotprijs. De API-respons is gezaghebbend.

### Factuur voor een exact cryptobedrag

Plaats de cryptocurrency in `currency` wanneer de factuur zelf in crypto is genoteerd:

```json
{
  "amount": "25.000000",
  "currency": "USDT",
  "network": "TRX-TRC20",
  "order_id": "ORDER-2026-1044",
  "url_callback": "https://merchant.example/webhooks/2328"
}
```

De gevraagde crypto-waarde wordt behouden in `payer_currency` / `payer_amount`. De dienst kan ook intern een USD-waardering bijhouden voor boekhoudkundige en tariefvelden; vervang de exacte crypto-instructie niet door die waardering. Behoud geretourneerde decimale strings, inclusief de achtervoegende precisie.

Voor een cryptocurrency met slechts één ondersteund netwerk, kan het netwerk automatisch worden geselecteerd. Het expliciet opgeven van `network` wordt nog steeds aanbevolen voor een deterministische integratie. Voor activa met meerdere netwerken, zoals stablecoins, stuur het altijd.

## Idempotentie en herhaalde pogingen

`order_id` is gekoppeld aan het geauthenticeerde handelsproject en fungeert als de idempotentiesleutel voor het aanmaken. Als er al een betaling bestaat, retourneert de API die sessie met `state: 0`.

> **WARNING:** Een herhaalde poging met hetzelfde `order_id` betekent **not** “werk deze factuur bij.” Gewijzigd bedrag, valuta, callback, markup, TTL of richtingvelden kunnen worden genegeerd omdat de bestaande sessie wordt geretourneerd. Sla het eerste verzoek op en wijs tegenstrijdige herhaalde pogingen af in uw eigen applicatie.

Aanbevolen creatie-algoritme:

1. Voeg uw lokale betalingspoging en unieke `order_id` in één database-transactie in.
2. Stuur het ondertekende API-verzoek.
3. Sla de geretourneerde `uuid` en volledige respons op.
4. Als het HTTP-resultaat verloren gaat, probeer dan hetzelfde verzoek opnieuw of vraag `/v1/payment/info` op via `order_id`.
5. Maak nooit een tweede lokale bestelling alleen omdat het upstream-verzoek is verlopen.

## Betalings randgevallen

| Situatie | Juiste afhandeling |
|-----------|------------------|
| `address` / `qr` is `null` | De betaler richting is niet geïnitialiseerd. Omleiden naar `url`, of maak een nieuwe correct gespecificeerde H2H-factuur met een nieuwe `order_id`. |
| HTTP `400` validatiefout | Lees het veldniveau `errors`; probeer geen ongewenste invoer opnieuw. |
| HTTP `429` | Probeer opnieuw met een jittered exponentiële backoff en behoud hetzelfde `order_id`. |
| HTTP `503` / `direction_disabled` | Vernieuw `/v1/directions`; verberg de richting tijdelijk of probeer later opnieuw. |
| Client verzoek timeout | Behandel het resultaat als onbekend. Vraag op via `order_id` voordat u iets anders aanmaakt. |
| `underpaid_check` | Sla het gedeeltelijke evenement op en wacht op een bijbetaling of latere status. Crediteer niet twee keer wanneer er meer txids binnenkomen. |
| `underpaid` | Definitieve staat van onderbetaling. Pas uw geconfigureerde fulfilment-/handmatige beoordelingsbeleid toe op het daadwerkelijk gecrediteerde bedrag. |
| `overpaid` | Succesvolle betaling met teveel ontvangen middelen. Voer idempotent uit en bewaar de werkelijke bedragen voor reconciliatie-/terugbetalingsbeleid. |
| `aml_lock` | Voer niet automatisch uit of geef middelen vrij; routeer naar compliance-/support-workflow. |
| `cancel` | Factuur is verlopen of geannuleerd. Leid hieruit niet af dat een late on-chain overdracht onmogelijk is; reconcilieer elk later evenement met support. |

De browserreturn-URL is alleen voor navigatie. Een klant kan deze openen zonder te betalen, sluiten na betaling, of later opnieuw afspelen. Alleen een geverifieerde API/webhook-status kan de bestelling van de handelaar afhandelen.

## Betalingsinformatie

Haal de huidige betalingsstatus op met `uuid` of `order_id`.

### Verzoekparameters

| Veld | Type | Vereist | Beschrijving | Waarden |
|------|------|---------|--------------|---------|
| `uuid` | string | ja\* | Payment UUID (uit `result.uuid` bij aanmaken) |  |
| `order_id` | string | ja\* | Je order-ID |  |

> **INFO:** Ten minste één van `uuid` of `order_id` is vereist.

#### Interactive request: `POST /v1/payment/info`
  - `uuid` (string)
  - `order_id` (string)

## Betalingenlijst

Haal een lijst van alle betalingen op met filtering en paginering.

### Verzoekparameters

| Veld | Type | Vereist | Beschrijving | Waarden |
|------|------|---------|--------------|---------|
| `status` | string | nee | Filteren op betalingsstatus (zie [References](/docs/references)) | `pending`, `check`, `paid`, `underpaid_check`, `underpaid`, `overpaid`, `cancel` |
| `date_from` | date | nee | Begindatum (YYYY-MM-DD), bijv. `2026-01-01` |  |
| `date_to` | date | nee | Einddatum (YYYY-MM-DD), bijv. `2026-01-31` |  |
| `page` | int | nee | Paginanummer, standaard `1` |  |
| `per_page` | int | nee | Items per pagina, standaard `15`, max `5000` |  |

#### Interactive request: `POST /v1/payment/list`
  - `status` (enum): pending,check,paid,underpaid_check,underpaid,overpaid,cancel
  - `date_from` (string)
  - `date_to` (string)
  - `page` (integer)
  - `per_page` (integer)