Skip to main content
POST
Create Product Payment Intent

Create Product Payment Intent

Creates a payment intent for products in your Khaime catalog. Supports physical products (with shipping), digital products, and gift cards.
Show the final total before you create the intent. Send this same body to Preview Payment on your review step: it returns the exact subtotal, fee and total without creating anything. Prices, Fees and Totals shows how the pricing calls fit together.
This endpoint is for Khaime catalog products. If your products live on your own platform (e.g., WooCommerce), use Create Payment Intent instead.
Requirements vary by product type:
  • Physical products: Requires cart_unique_id from /cart/validate and delivery_details
  • Digital/Gift Card/Others: No cart validation needed - cart_unique_id is auto-generated

Request

string
required
Your API key

Body Parameters

string
required
Type of product being purchased. Determines required fields and checkout flow.Values: physical_product, digital, gift_card
array
required
Array of cart items.
string
required
Customer’s email address
string
required
Customer’s first name
string
required
Customer’s last name
string
required
Currency code (e.g., USD, NGN, GBP)
string
required
Payment type. Use one for one-time payments.Values: one, multiple_time
string
Cart ID from /cart/validate. Required for physical products. Auto-generated for digital products if not provided.
object
Shipping address and delivery preferences. Required for physical products. Not needed for digital products.
string
Customer’s country code (e.g., US, NG). Auto-detected from IP if not provided.
string
Preferred payment gateway. Auto-selected based on currency if not provided.Values: stripe, paystack, paypal, square
boolean
default:"false"
Whether a coupon code is being applied
string
Coupon code to apply (if is_coupon_used is true)
string
required
Who is paying. Values: customer, business, educator
Required, and it must be customer for a normal purchase. Omitting it is rejected with a validation error. Sending any other value is accepted, but the payment then settles down a different path and no merchant wallet is credited — the charge succeeds and the money is not attributed. If a payment completes at the gateway but no wallet balance moves, check this field first.
number
required
Order total in the smallest currency unit. For an installment, send the plan total.

Installments

The product must be sold in installments, alone in the cart.
boolean
default:"false"
true to pay in installments.
integer
Installment to pay. Required with is_split. 1 opens a new plan.
integer
Plan to pay. Required for position 2 and later.
Each installment must be above the gateway minimum (e.g. $0.50 on Stripe, ₦50 on Paystack).

Selling a sub-merchant’s product

A marketplace operator can sell a product from a sub-merchant’s catalogue through this endpoint. There is nothing extra to send: call it with your own API key and put the sub-merchant’s product_id in the cart. Ownership, authorisation and commission are all resolved server-side from the product itself.
Never send the seller’s id in the body. Ownership comes from the product record, so a caller cannot name a merchant they are not entitled to sell for. A cart containing a product you have no active marketplace relationship with is rejected with 403 AUTH_PERMISSION_DENIED.
Rules that apply to a marketplace cart:
  • Every product in one cart must belong to the same merchant. A mixed-owner cart is rejected with 400 MARKETPLACE_MIXED_OWNER_CART — an order settles to a single merchant, so there is no correct split for a mixed one.
  • Prices come from the catalogue, not from the request. The price you send on each cart line is used for display reconciliation only; the server re-derives the total from the stored product price, any active deal, and the buyer’s market. If they disagree, the catalogue wins.
  • Commission is a percentage of the sale, set per sub-merchant by the operator. There is no fixed-fee or markup option — to leave a sub-merchant exactly 10.00ofa10.00 of a 15.00 sale, set the rate to 33.33%.
How the money divides. The sub-merchant’s share is fixed by the commission the operator agreed, and the Khaime transaction fee is carried by the operator out of their commission:
On a $15.00 sale at 33.33%, with the customer absorbing the fee: If the operator absorbs the fee instead, the sub-merchant still receives exactly 10.00andtheoperatorreceives10.00 and the operator receives 3.80. The sub-merchant’s number does not move.
The commission must cover the Khaime fee. If it does not, the intent is rejected with 400 MARKETPLACE_COMMISSION_BELOW_FEES, naming both amounts — raise the commission rate for that merchant, or have the customer pay the transaction fee.
The split is recorded when the intent is created, so the rate in force at purchase is the rate that settles, whatever the operator changes afterwards. Wallets are credited when the payment succeeds, not when the intent is created.

Product Type Requirements


Response

Response Fields

Showing the fee to the customer

When breakdown.customer_pays_fees is true, the transaction fee is included in amount and returned as breakdown.transaction_fee. Show it as its own line in your order summary, before the customer pays — it’s best practice for transparency, and a total higher than the catalog price with no explanation erodes trust and invites disputes. See Fees. Who pays is the business’s customer_pays_transaction_fee setting. When an operator sells a sub-merchant’s product, it’s the operator’s decision. The total you display must equal amount, because that’s what the customer is charged. To show the breakdown while the customer is still reviewing their cart, call Preview Payment first — it returns the same numbers without creating an intent.
transaction_fee is returned even when the merchant absorbs the fee. Decide whether to show the line from customer_pays_fees, not from whether transaction_fee is present — otherwise you’ll show customers a fee they aren’t paying.
Token Expiration: Tokens expire after 15 minutes. If a customer takes too long to complete payment, you’ll need to create a new payment intent.

Examples

Physical Product Checkout

Requires cart validation first to calculate shipping.

Digital Product Checkout

No cart validation or address required. Supports multi-item carts. Uses simplified cart schema.
Simplified schema for digital products: Do NOT include product_title, product_thumbnail, main_variant, least_sub_variant_id, or shipping_rate in cart items. These are only for physical products. You can still include additional_information for custom fields.

Digital Product with Custom Fields

Example showing a digital product (e.g., personalized certificate) with custom fields.

Physical Product with Custom Fields

Example showing a product where the business has configured custom fields for personalization. Product’s custom fields (configured by business): Checkout request with customer-provided values:
Accessing custom field values: The additional_information data is included in order webhooks and the Order API response. Use this to fulfill personalized orders correctly.

Gift Card Checkout

Same flow as digital products. Each gift card item creates a separate gift card code.

Pay in Installments

First installment:
Next installment: same body with the position and plan.
Send the cart line again, with its additional_information if the product has custom fields.

Accepting Payments

Once you receive the response, collect payment from your customer using one of these options: Embed the checkout directly in your app using @khaime/react.
1

Install @khaime/react

2

Render the Checkout

React SDK Documentation

See the full React SDK documentation for all available options

Option 2: Redirect Checkout

Redirect the customer to Khaime’s hosted checkout page:

Errors

Every error carries a stable string error_code alongside a human-readable message. Switch on error_code — the message wording changes, the code does not. VALIDATION_ERROR was never a real code; use VALIDATION_FAILED.

Confirming Payment

Always verify payments via webhooks before fulfilling orders. Frontend callbacks are for UI purposes only.

Digital Cart Checkout

Complete guide for digital product multi-item carts

Physical Checkout Guide

Complete guide for physical products with shipping

Cart Validation

Validate cart and calculate shipping (physical products)

Webhooks

Listen for payment completion events