REST, JSON and one webhook.
The minimum that is genuinely enough for production: create a payment, get confirmation, close the order.
- 01
Keys
Request access, connect an IBAN, take sk_test from the dashboard.
- 02
Payment
POST /v1/invoices with amount and order number. You get a pay_url.
- 03
Webhook
Receive invoice.paid, verify the signature, close the order.
Create a payment
Amount in minor units, reference is your order number. Repeating the request with the same reference returns the same payment.
curl -X POST https://api.kvitnyk.com/v1/invoices \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"amount": 124000,
"currency": "UAH",
"reference": "A-10427",
"description": "Order A-10427",
"callback_url": "https://shop.ua/hooks/kvitnyk"
}'
{
"id": "inv_8Qk2m",
"status": "pending",
"pay_url": "https://pay.kvitnyk.com/8Qk2m",
"qr_payload": "BCD002UCT...",
"expires_at": "2026-09-12T18:40:00Z"
}Payment confirmation
Fires once the incoming transfer matches the open payment. Verify the signature header before processing.
POST /hooks/kvitnyk
{
"event": "invoice.paid",
"invoice_id": "inv_8Qk2m",
"reference": "A-10427",
"amount": 124000,
"paid_amount": 124000,
"currency": "UAH",
"payer_bank": "monobank",
"payer_name": "I*** K***",
"matched_by": "reference",
"verified_at": "2026-09-12T18:12:41Z"
}
HTTP 200 → delivered
otherwise: 5 retries, 1m → 1hPayment statuses
| pending | Payment issued, nothing received yet. |
|---|---|
| paid | Amount matched — payment verified, webhook sent. |
| review | Money arrived but did not reconcile automatically: a different reference, a transfer from a third party, or several near-identical amounts. It waits for a decision in the dashboard — one click confirms it manually, and the webhook goes out after that. |
| underpaid | Less arrived than issued. The payload carries the actual sum. |
| overpaid | More arrived than issued. You return the difference yourself. |
| expired | The payment window closed with no transfer. |
| refunded | You refunded the customer — marked manually or via API. |
Sandbox
Separate keys and emulated transfers: you can walk every status without moving real money.
Idempotency
Reference is the uniqueness key. Repeat calls create no second payment and no duplicate webhook.
Ready-made modules
WooCommerce, Prom, Shopify, plus examples for Node, PHP, Python and Laravel.
API limits
100 requests/min per key. Webhooks retry 5 times with backoff up to one hour.
Keys and sandbox the same day.
A request with no calls and no contracts. Test keys go out the same day; production follows once your account is connected.