RADOK

Payment links

A hosted page that collects a payment without any code.

Contents

What a payment link is

A payment link is a hosted page that collects a payment without you building a checkout. A link can take naira by bank transfer, dollars by USDT or USDC, or both. Bank transfer uses a dedicated virtual account. Crypto settles into a USD balance after the network confirms the transfer.

Use one for an invoice, a donation page, an event ticket, or anywhere you want to take money without shipping code.

Create them from your server, or from the dashboard

Every endpoint here takes either a secret key or a dashboard session. There is no payment_links scope — a payment link is a way of opening a collection, so collections:read and collections:write cover it.

Creating one per order from your server is what powers the checkout widget: your server sets the amount, hands the browser a slug, and the customer pays in a modal on your own page.

Customers always pay on the hosted page. There is no public checkout API for your server to call — if you want to collect without a hosted page at all, mint a virtual account instead.

Create a payment link

POST/v1/payment-links
Auth
Secret key or dashboard session
Scope
collections:write

Body

FieldTypeDescription
titlerequiredstring1–120 characters. The heading on the hosted page.
descriptionstringUp to 2000 characters, shown under the title.
customerobjectDetails you already hold: name, email, phone, any subset. Each one is shown on the checkout but not editable, and is what lands on the collection — the payer’s browser cannot substitute another. Use it so a signed-in customer is not asked for an email you just authenticated them with.
amountTyperequiredstringfixed — you set the amount. customer_chooses — the payer enters one, optionally bounded.
amountmoneyRequired when amountType is fixed. Minor units in pricingCurrency (kobo or cents).
methodsstring[]bank_transfer, crypto, or both. Defaults to bank transfer only.
pricingCurrencystringNGN or USD. The amount you set is in this currency. The other rail is derived from the platform rate and frozen onto the checkout when the payer starts it.
cryptoWindowMinutesnumberHow long a crypto checkout stays open. Defaults to 60. Maximum 1440. Bank transfer stays 30 minutes.
minimumAmountmoneyOptional floor for customer_chooses.
maximumAmountmoneyOptional ceiling for customer_chooses.
linkTyperequiredstringone_time closes after the first successful payment. reusable keeps accepting payments until disabled.
customerFieldsrequiredobjectname, email, phone, each { collect: boolean, required: boolean }.
customFieldsarrayUp to 20 extra inputs, each { label, placeholder?, required }. Answers arrive on the collection.
expiresAtstring | nullISO 8601. After this the page stops accepting payment.
successRedirectUrlstring | nullOptional absolute http:// or https:// URL. After a successful payment, the checkout page redirects here after a few seconds.
appearancerequiredobjecttheme, brandColor, logoDataUrl (or null), showAttribution.
curl
curl -X POST https://api.radokpay.com/v1/payment-links \
  -H "Authorization: Bearer $RADOK_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Invoice #1042",
    "description": "Design retainer, August 2026",
    "customer": { "name": "Ada Lovelace", "email": "ada@example.com" },
    "amountType": "fixed",
    "amount": { "value": 25000000, "currency": "NGN" },
    "linkType": "one_time",
    "customerFields": {
      "name":  { "collect": true,  "required": true  },
      "email": { "collect": true,  "required": true  },
      "phone": { "collect": false, "required": false }
    },
    "customFields": [
      { "label": "Purchase order number", "required": false }
    ],
    "expiresAt": "2026-09-23T00:00:00.000Z",
    "successRedirectUrl": "https://example.com/thank-you",
    "appearance": {
      "theme": "neutral",
      "brandColor": "#1a2a80",
      "logoDataUrl": null,
      "showAttribution": true
    }
  }'
201 Created
{
  "data": {
    "id": "652f1a9c4d7b3e0812345678",
    "slug": "invoice-1042-9f4c1b",
    "url": "https://pay.radokpay.com/pl/invoice-1042-9f4c1b",
    "title": "Invoice #1042",
    "amountType": "fixed",
    "amount": { "value": 25000000, "currency": "NGN" },
    "linkType": "one_time",
    "status": "active",
    "disabled": false,
    "vaStatus": "ready",
    "bankName": "Providus Bank",
    "accountNumber": "9901234567",
    "accountName": "RADOK/INVOICE 1042",
    "successRedirectUrl": "https://example.com/thank-you",
    "expiresAt": "2026-09-23T00:00:00.000Z",
    "createdAt": "2026-08-23T11:30:00.000Z"
  }
}

Share only when vaStatus is ready

Create mints the dedicated virtual account before responding. On success you usually get vaStatus: "ready" with bank details in the same response. If minting fails, vaStatus is failed (with vaError) and a background retry may still bring it to ready — re-read the link before sharing it.

List payment links

GET/v1/payment-links
Auth
Secret key or dashboard session
Scope
collections:read

Page-based, unlike the cursor pagination used elsewhere in the API.

Query

FieldTypeDescription
environmentrequiredstringtest or live.
pageinteger1-based. Defaults to 1.
pageSizeinteger1–100. Defaults to 20.
200 OK
{
  "data": [ { "id": "652f1a9c...", "slug": "invoice-1042-9f4c1b", "status": "active" } ],
  "meta": { "total": 37, "page": 1, "pageSize": 20 }
}

Retrieve and disable

GET/v1/payment-links/{id}
Auth
Secret key or dashboard session
Scope
collections:read
POST/v1/payment-links/{id}/disable
Auth
Secret key or dashboard session
Scope
collections:write

Stops the page accepting payment and cancels its virtual account. Payments already settled are unaffected.

curl
curl -X POST https://api.radokpay.com/v1/payment-links/652f1a9c4d7b3e0812345678/disable \
  -H "Authorization: Bearer $RADOK_SECRET_KEY"

Payments against a link

GET/v1/payment-links/{id}/payments
Auth
Secret key or dashboard session
Scope
collections:read

Returns the collections created by this link, newest first, with the same page-based meta as the list endpoint. Every row is a normal collection, so it carries the same amount, platformFee, and netAmount.

Events

  • A paid link emits collection.success for both bank transfer and crypto. Crypto payloads also include method, received, overpaid, and fxRate. The payload carries paymentLinkId so you can attribute it.
  • A bank checkout lasts 30 minutes. A crypto checkout lasts cryptoWindowMinutes (default 60). If nothing arrives, a bank session emits collection.failed with reason: "expired". A crypto session emits collection.expired. A shortfall that did arrive emits collection.underpaid and is still credited.
  • While a crypto transfer is on-chain but under the confirmation threshold, the collection is confirming and you receive crypto.payment.confirming, then crypto.payment.confirmed once it finalizes. A transfer after expiry emits collection.late_payment. A transfer after the collection already settled emits crypto.unsolicited. Both are credited.
  • There is no separate payment_link.* event. Subscribe to collection events and branch on the presence of paymentLinkId.
  • A one_time link is marked paid and its account cancelled after the first success, so a second payment against it cannot happen.