Payments
Create Charge
Create a product-agnostic payment charge.
POST
Documentation Index
Fetch the complete documentation index at: https://docs.khaime.com/llms.txt
Use this file to discover all available pages before exploring further.
Create Charge
Create a one-time payment charge without requiring a product in Khaime’s catalog. Ideal for WooCommerce or custom integrations where products live on the merchant’s platform.This is the recommended endpoint for plugin integrations. Use Create Session if you need Stripe Checkout hosted pages instead.
Request Body
Charge amount in smallest currency unit (cents, kobo) — the customer’s payment currency. Must be calculated using /pricing/calculate when currency conversion is involved — we validate it matches our calculation.
3-letter ISO currency code for what the customer pays. Example:
USD, NGN, GBPThe full amount the merchant is collecting, in smallest currency unit of
total_currency. This is inclusive of all fees (shipping, handling, etc.) — not just the base product price.Why required: This field is the source of truth for what gets credited to the merchant’s wallet, and anchors our server-side conversion when multicurrency is involved.- No conversion: Pass the same value as
amount - Multicurrency: Pass the total in the merchant’s baseline currency (e.g.
8500for $85.00 USD) - Marketplace: Pass the total in the sub-merchant’s baseline currency
total_amount: 9000, total_currency: "USD".original_product_amount is accepted as a deprecated alias and will continue to work.ISO 4217 currency code for
total_amount. This is the merchant’s (or sub-merchant’s) pricing currency.- No conversion: Pass the same value as
currency - Multicurrency / Marketplace: Pass the merchant’s baseline currency
original_product_currency is accepted as a deprecated alias and will continue to work.Your pre-computed conversion of
total_amount into currency (the customer’s payment currency). Optional — but strongly recommended when total_currency differs from currency.When provided, we cross-validate:converted_total_currencymust equalcurrencyconverted_total_amountmust equalamount(within 1% tolerance)
converted_total_currency.The currency of
converted_total_amount. Must match currency. Required when converted_total_amount is provided.Human-readable description of the charge. Shown on payment receipts.
Your unique reference for this charge. Used for idempotency and reconciliation.
Canonical redirect URL after payment.
- Paystack: customer returns here after hosted checkout
- StartButton: sent through as
redirectUrlduring payment initialization - Stripe: use
return_urlinconfirmPayment()on the client
Camel-case alias for
callback_url. Useful for StartButton-oriented integrations.Snake-case alias for
callback_url.Alias for
customer.country. Accepted as a top-level field for storefronts that already send user_country.Alias for
customer.country. Accepted as a top-level field and inside metadata.Alias for
customer.country. Accepted as a top-level field.Billing country fallback when
customer.country is absent. Accepted as a top-level field and inside metadata.Shipping country fallback when
customer.country is absent. Accepted as a top-level field and inside metadata.Send any country value you already have. Khaime normalizes common country names and ISO-2 codes, then stores the resolved value on the transaction for customer geography reports. If no country is provided, Stripe/Paystack card country may be used after payment; otherwise the transaction may appear as
Unknown in geography analytics.Custom key-value pairs attached to the charge. Values must be strings, numbers, or booleans — no nested objects.
When
true, returns a fee and conversion breakdown without creating any database records or calling any payment gateway. Use this to show the customer exactly what they’ll pay before initiating the real charge.All validation still runs — amount mismatch, currency conversion, sub-merchant, etc. — so a successful preview response means your actual charge will go through.See Preview Mode below for the response shape.Marketplace Fields
This field is only relevant if your account is set up as a marketplace operator. See Setup Marketplace to enable marketplace mode.
The Khaime educator ID of the sub-merchant this charge is being collected for. Must have
active status in your marketplace.When present, the webhook additionally credits the sub-merchant’s wallet for total_amount minus your marketplace commission, in total_currency. Your marketplace wallet is still credited as normal.How the split works
On webhook receipt after a successful payment:- Your marketplace wallet is credited for
amountminus the Khaime platform fee — same as a standard charge. - The sub-merchant wallet is additionally credited for
total_amountminus your commission, intotal_currency. No additional platform fee is deducted from the sub-merchant — it was already taken on the full charge.
- Per-merchant
commission_rateset via Update Commission - Your portfolio default
marketplace_commission_rate 0if neither is set
conversion_details:
Response
The response varies based on which gateway Khaime routes to:- Stripe
- Paystack
client_secret and publishable_key to mount Stripe Payment Element.Gateway Routing
Thecurrency field determines which gateway processes the payment:
| Currency | Gateway |
|---|---|
| NGN | Paystack |
| GHS, KES, ZAR, TZS, XAF, XOF | StartButton |
| USD, EUR, GBP, CAD, AUD | Stripe |
Preview Mode
Pass"preview": true in the request body to calculate fees and FX conversion without creating a charge. The response is identical in structure to a normal charge response except:
preview: trueis set at the top level- No
charge_id,client_secret,payment_url, ortransaction_id— no gateway was called - No database records are created
customer and business are always in different currencies when multicurrency is involved — do not compare customer.base_amount with business.priced_amount directly. Use the conversion.exchange_rate to relate them. conversion is only present when currency differs from total_currency.Amount Validation (Double Check)
Both you and Khaime calculate the charge amount independently — they must match. Your workflow:- Call /pricing/calculate with
total_amountandtarget_currency - Use the returned
local.amountas youramountin the charge request - Optionally, pass
converted_total_amountandconverted_total_currencyto make your pre-computed conversion explicit - We recalculate using the same conversion service and verify they match (1% tolerance for rounding)
Error Codes
| Status | Error | Fix |
|---|---|---|
400 | Amount mismatch | Your amount doesn’t match our calculation. Use /pricing/calculate to get the correct amount. |
400 | converted_total_amount does not match amount | Your pre-computed conversion differs from amount. Ensure both represent the charge total in the same currency. |
400 | converted_total_currency must match the charge currency | converted_total_currency must equal currency. |
400 | Both converted_total_amount and converted_total_currency must be provided together | Supply both fields or neither. |
422 | "amount" is required | Include amount — use /pricing/calculate to convert total_amount to the customer’s currency. |
422 | Missing total_amount / total_currency | Include total_amount and total_currency (or their aliases original_product_amount / original_product_currency). |
400 | Unable to convert from X to Y | Currency conversion failed — try again or use a supported currency. |
400 | Missing required fields | Include amount, currency, customer.email. |
401 | Invalid API key | Check your X-API-Key header. |
422 | Metadata validation failed | Ensure metadata values are scalar (no nested objects). |
