Integrating Voucher Payments via API

With the Voucher Payments API, you can initiate and manage voucher charges directly via API, while maintaining full control over the customer experience.

Endpoint

POST {{baseurl}}/api/v1/charge/voucher

Voucher Charge

Request Body

{
    "amount": 100,
    "currency": "ZAR",
    "merchant_bears_cost": true,
    "notification_url": "https://secure.example.com/api/v1/callback/deposit",
    "description": "This is a voucher payment",
    "reference": "example-unique-reference",
    "voucher": {
        "pin": "1168648096792943",
        "phone_number": "+270576847568",
        "provider_code": "0001"
    },
    "customer": {
        "email": "[email protected]",
        "name": "John Doe"
    },
    "metadata": {
        "key": "Value 1"
    }
}

Request Parameters

Kora dispatches asynchronous notifications for all status changes. For voucher transactions, the webhook payload includes the payment method and details for any newly issued vouchers.

PARAMETERTYPEREQUIREDDESCRIPTION
amountnumbertrueThe transaction amount to be charged.
currencystringtrueThe currency code for the transaction (e.g., ZAR).
merchant_bears_costbooleantrueA boolean indicating whether the merchant covers the transaction cost.
notification_urlstringfalseThe URL where transaction notifications (webhooks) should be sent.
descriptionstringfalseA brief description of the payment.
referencestringtrueA unique identifier for the transaction.
voucher.pinnumbertrueThe voucher PIN or code entered by the customer.
voucher.phone_numberstringtrueThe customer's phone number.
voucher.provider_codestringtrueThe identifier for the voucher provider.
customer.namestringfalseThe name of the customer.
customer.emailstringtrueThe email address of the customer.
metadataobjectfalseThis is a key value object for additional information

Charge Response

{
    "status": true,
    "message": "Charge Successful",
    "data": {
        "currency": "ZAR",
        "amount": 10,
        "fee": 0,
        "vat": 0,
        "transaction_reference": "KPY-CA-qFNr4bXheKr6",
        "payment_reference": "unique-payment-reference",
        "status": "success",
        "voucher": {
            "serial_number": "20251024103152983020",
            "balance": 10,
            "pin": "1234252526252525",
            "expiry_date": "2028-10-24 10:31:26"
        },
        "customer": {
            "name": "John Doe",
            "email": "[email protected]"
        }
    }
}

Partial Payments and Remaining Balances

If a voucher provider supports partial redemptions, the transaction may be processed for an amount less than the total voucher value.

  • Success Logic: Kora marks the transaction as success if the redemption is partially fulfilled.
  • Residual Value: Any remaining balance is managed by the voucher provider to the customer.
📘

Note: There is no "Check Balance" API; verify remaining value via the transaction response returned after the charge.


Failed Payments

When a voucher payment request is declined or fails, Kora automatically transitions the transaction status to failed.

  • Checkout Experience: If the failure occurs during a Hosted Checkout flow, Kora automatically presents the user with a user-friendly error message (e.g., "Invalid Voucher," "Insufficient Balance").
  • API Requests: Server-to-server API calls return the corresponding error status.
  • Webhooks: Kora dispatches a charge.failed event to your registered notification URL.
  • Reconciliation: All failed transactions and the specific failure reason are logged in your Kora Dashboard for audit.

Voucher-Specific Error Codes

HTTP StatusDescription
400The voucher pin you have entered is invalid.
400The voucher has already been used.
402Voucher funds are lower than the transaction amount.
400The amount provided exceeds the required amount.
403The voucher provider is not active for this merchant.
400The selected provider code is not supported.
500An unexpected system error occurred.

Error Response Format

All error responses are returned in the following standard JSON format:

{
  "status": false,
  "message": "Error description here",
  "data": null
}