Concepts

Key ideas you need before integrating: base URL, item codes, price vs face value (charged vs denomination), the response envelope, and the difference between checking stock and checking order status.

Base URL and versioning

All API requests go to:

https://api.cardpluspay.com/v1

The path /v1 is the API version. Append the endpoint path to this base (e.g. https://api.cardpluspay.com/v1/balance, https://api.cardpluspay.com/v1/catalog). Future versions may use /v2; the current production version is v1.

Item codes

Products in the catalog are identified by an item code (sometimes referred to as item_id in query parameters). For example: GOOGLE-5USD-KOXx.

  • Use the same identifier when calling the catalog, checking stock, and creating orders.
  • Get item codes from GET /catalog or GET /catalog?item_id=...; store the code in your database or config when you link your products to CardPlusPay.

Price vs face value (list, charged, denomination)

Three kinds of amounts appear in catalog and order responses. Use them correctly:

  • Face value (denomination) — What the customer receives (e.g. “$5 Google Play card” or “60 UC”). In the catalog use face_value (preferred) or value (alias). In order responses use denomination per code. For display only — not for billing.
  • List price — Pre-offer wholesale/list price per unit. In the catalog this is price.
  • Charged amount — What is debited per unit after an active offer. In the catalog this is charged_price (equals price when no offer). In stock check and orders use price / charged_amount / amount for financial logic.

Always re-check at checkout: cache charged_price from the catalog for display, but call POST /orders/check for the authoritative per-unit charge and stock before purchase.

Charged amount can be less than face value (e.g. promotional pricing). Never use face value for balance or checkout totals.

Product type vs category

category is a merchandising shelf (e.g. “Google Play SA”). Path GET /catalog/{category} filters by category.

product_type is the product vertical (e.g. app_store, game_card, direct_top_up). Filter with ?product_type= on GET /catalog. See the display products guide for the full slug list.

Response envelope

Every API response uses a common structure:

{
  "success": true | false,
  "message": "Human-readable message",
  "data": { ... }
}
  • success — Whether the request succeeded. Always check this before trusting data.
  • message — Short description (e.g. "Balance retrieved successfully" or an error message).
  • data — The payload. Structure depends on the endpoint (e.g. balance, products, order_id, codes).

On failure, success is false and message (and optionally data) describes the error.

Purchase and delivery

Gift card and digital product purchases are fulfilled through the CardPlusPay API. Your integration uses CardPlusPay endpoints only.

  • Code delivery — Products such as game_card, gift_card, and app_store return redeemable codes in the POST /orders response when fulfillment completes in the same request.
  • Direct top-up — Products with product_type = direct_top_up credit a buyer account. They require a fields object (from catalog required_fields), return empty codes, and include a delivery object. See direct top-up orders.
  • Async fulfillment — Some orders return HTTP 200 with status: pending (and empty codes for code products). This means CardPlusPay is still processing — not a failure. Poll GET /orders/{id} until completed or failed. Your API wallet stays debited while an order is pending.
  • Availabilityavailable_quantity on POST /orders/check reflects how many units CardPlusPay can fulfill right now. It may change between check and purchase; always re-validate at checkout.
  • Order lookup — Use GET /orders/{id} after create when status is pending, after a connection timeout, or for support — see order status & polling.

Stock check vs order status

Do not confuse these two operations:

Goal Endpoint Use when
Check if a product is available (stock) POST /orders/check Before add-to-cart or checkout. Send item_id (item code) and quantity. Response tells you if that quantity is in stock.
Get status of an existing order GET /orders/{id} After creating an order. Send the order_id from the create response. Use this to show status and retrieve gift card codes.

Use POST /orders/check for “Is this product in stock?” and GET /orders/{id} for “What’s the status of order #123?”

Quantity limits

CardPlusPay exposes per-SKU quantity limits so you can cap cart and checkout without guessing:

  • Catalog (GET /catalog) — Each product includes min_quantity and max_quantity for listings and sync. These are not live stock counts.
  • Stock check (POST /orders/check) — Success data adds available_quantity (units purchasable now, or null if unknown), plus quantity_contract_version (currently 1).
  • Purchase (POST /orders) — Quantity must be within the SKU min/max and current stock. Failures use data.state of invalid_quantity or out_of_stock.

Purchasable cap (client-side):

purchasable_now = min(max_quantity, available_quantity ?? max_quantity, 100)

Also apply your wallet: floor(balance / price) from GET /balance. See the check availability guide for a full example response.

Typical purchase flow

A common end-to-end flow for buying a gift card looks like this:

  1. Check balance — Optional but recommended. Call GET /balance to ensure you have enough funds for the planned purchase.
  2. Get product info — Use GET /catalog (or GET /catalog?item_id=...) for item_code, charged_price, face value, quantity bounds, and product_type. Paginate with sort_by=item_code for full sync.
  3. Check stock and price — Before checkout, call POST /orders/check with item_id and quantity. Use data.price (authoritative charge), min_quantity, max_quantity, and available_quantity; confirm state is "in_stock".
  4. Create the order — After payment is authorized, call POST /orders with item_code and quantity (and a stable Idempotency-Key in production). For direct_top_up SKUs, include fields — see direct top-up orders. On success, use order_id, amount, and either codes (code products) or delivery.status (top-up).
  5. Poll if pending — When status is pending, call GET /orders/{id} on an interval until completed or failed. Do not treat a client timeout as failure — retry POST /orders with the same idempotency key first.
  6. Confirm if needed (optional) — Call GET /orders/{id} if you did not receive a response and are reconciling with the same idempotency key, or for support.

← Integration Guide · Authentication →