Skip to main content

Checkout Session

Author: Josh S. Sakweli, Backend Lead Team
Last Updated: 2025-10-022026-05-23
Version: v1.v2.0

Base URL: https://apinexgate.glueauth.com/api/v1/

Short Description: The Checkout Session API manages the complete checkout process for both e-commerce and event transactions. It handles creatingsession checkoutcreation sessions(with fromupfront cartwallet orbalance directvalidation), purchase,inventory managingholds, payment intents, processing paymentsvia through multiple payment methods (Wallet, Cash on Delivery, Cards, Mobile Money),Cash, and supportsFree advanced features likeflows, group purchasingpurchasing, and installment payments. Each session maintains state, inventory holds, and payment attempt tracking with automatic expiration handling.

Hints:

  • Wallet balance is validated at session creation time — if insufficient, no session is created and a rich balance response is returned so the frontend can guide the user to top up
  • All checkout sessions expire after 15 minutes by default
  • Inventory is automatically held during active sessions and released upon expiration or cancellation
  • Maximum 5 payment retry attempts allowed per session
  • Group purchase sessions require WALLET payment method only
  • Sessions in PAYMENT_PROCESSING status cannot be modified
  • Installment payment typeonly ischarges plannedthe fordown futurepayment releaseat (placeholdercheckout; only)monthly payments are handled by the scheduler
  • All monetary values are in TZS (Tanzanian Shillings)
  • Use ISO 8601 format for all datetime fields
  • Sessions can only be updated when in PENDING_PAYMENT or PAYMENT_FAILED status

Full Checkout Flow Diagram

CLIENT                          BACKEND                         SYSTEMS
  |                               |                               |
  |  POST /checkout-sessions      |                               |
  |------------------------------>|                               |
  |                               |-- Validate request            |
  |                               |-- Calculate pricing           |
  |                               |                               |
  |                               |-- assertSufficientBalance()   |
  |                               |        |                      |
  |                               |        |-- GET wallet balance -|-> Ledger
  |                               |        |                      |
  |                               |   .......................      |
  |                               |   . BALANCE INSUFFICIENT .    |
  |                               |   .......................      |
  |    422 + rich balance data    |        |                      |
  |<------------------------------|<-------'                      |
  |  {                            |                               |
  |    walletBalance: 5000,       |                               |
  |    sessionTotal: 12000,       |                               |
  |    shortfall: 7000,           |                               |
  |    recommendedTopUp: 7000     |                               |
  |  }                            |                               |
  |                               |                               |
  |                               |   .......................      |
  |                               |   .  BALANCE SUFFICIENT  .    |
  |                               |   .......................      |
  |                               |        |                      |
  |                               |-- Hold inventory ------------>|-> Inventory
  |                               |-- Save session                |
  |                               |-- Schedule expiry job ------->|-> JobRunr
  |                               |                               |
  |    201 + session data         |                               |
  |<------------------------------|                               |
  |  { sessionId, status:         |                               |
  |    PENDING_PAYMENT, ... }     |                               |
  |                               |                               |
  |  ...15 min window...          |                               |
  |                               |                               |
  |  POST /{sessionId}/payment    |                               |
  |------------------------------>|                               |
  |                               |-- Validate status             |
  |                               |-- Check expiry                |
  |                               |                               |
  |                               |   .......................      |
  |                               |   .    FREE checkout     .    |
  |                               |   .......................      |
  |                               |        |                      |
  |                               |-- Create booking/order        |
  |                               |-- Track free transaction      |
  |    200 SUCCESS                |                               |
  |<------------------------------|                               |
  |                               |                               |
  |                               |   .......................      |
  |                               |   .    CASH checkout     .    |
  |                               |   .......................      |
  |                               |        |                      |
  |                               |-- Create booking/order        |
  |                               |-- Track cash transaction      |
  |    200 SUCCESS                |                               |
  |<------------------------------|                               |
  |                               |                               |
  |                               |   .......................      |
  |                               |   .   WALLET checkout    .    |
  |                               |   .......................      |
  |                               |        |                      |
  |                               |-- Set PAYMENT_PROCESSING      |
  |                               |-- holdMoney() --------------->|-> Escrow
  |                               |                               |
  |                               |   .......................      |
  |                               |   .     SUCCESS          .    |
  |                               |   .......................      |
  |                               |        |                      |
  |                               |-- Set PAYMENT_COMPLETED       |
  |                               |-- Create order/booking        |
  |                               |-- Commit inventory hold ----->|-> Inventory
  |                               |-- Publish payment event ----->|-> Notifications
  |    200 SUCCESS                |                               |
  |<------------------------------|                               |
  |  { orderId, escrowId,         |                               |
  |    amountPaid, ... }          |                               |
  |                               |                               |
  |                               |   .......................      |
  |                               |   .     FAILED           .    |
  |                               |   .......................      |
  |                               |        |                      |
  |                               |-- recordFailedAttempt()       |
  |                               |-- Release reservation         |
  |                               |   (events only)               |
  |    200 FAILED                 |                               |
  |<------------------------------|                               |
  |  { success: false,            |                               |
  |    canRetry: true/false }     |                               |
  |                               |                               |
  |  POST /{sessionId}/retry      |                               |
  |------------------------------>|                               |
  |                               |-- Check status = FAILED       |
  |                               |-- Check attempts < 5          |
  |                               |-- Re-validate inventory       |
  |                               |-- Check wallet balance        |
  |                               |-- Re-hold inventory           |
  |                               |-- Reset to PENDING_PAYMENT    |
  |                               |-- processPayment() ...        |
  |                               |   (same wallet flow above)    |

Session Type Routing

POST /checkout-sessions
  sessionType?
  .
  ├─ REGULAR_DIRECTLY ──> validate 1 item ──> balance check ──> hold inventory ──> session
  |
  ├─ REGULAR_CART ──────> validate cart ───> balance check ──> hold inventory ──> session
  |
  ├─ GROUP_PURCHASE ────> validate group ──> balance check ──> session (no hold, group-level)
  |
  └─ INSTALLMENT ───────> calculate down payment ──> balance check ──> hold inventory ──> session


POST /e-events/checkout
  ticketPricingType?
  .
  ├─ PAID ──> balance check ──> create payment intent ──> reserve ticket ──> session
  |
  └─ FREE ──> (no balance check) ──> reserve ticket ──> session

Standard Response Format

All API responses follow a consistent structure using our Globe Response Builder pattern:

Success Response Structure

{
  "success": true,
  "httpStatus": "OK",
  "message": "Operation completed successfully",
  "action_time": "2025-10-02T10:30:45",
  "data": {
    // Actual response data goes here
  }
}

Error Response Structure

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Error description",
  "action_time": "2025-10-02T10:30:45",
  "data": "Error description"
}

Insufficient Balance Error Structure (422)

This is a special structured error returned when wallet balance is insufficient at session creation time. The data field contains rich balance details so the frontend can guide the user to top up.

{
  "success": false,
  "httpStatus": "UNPROCESSABLE_ENTITY",
  "message": "Insufficient wallet balance to complete checkout",
  "action_time": "2025-10-02T10:30:45",
  "data": {
    "walletBalance": 5000.00,
    "sessionTotal": 12000.00,
    "shortfall": 7000.00,
    "hasSufficientBalance": false,
    "recommendedTopUp": 7000.00,
    "pspMinimum": 500.00,
    "currency": "TZS"
  }
}
FieldDescription
walletBalanceCurrent wallet balance of the user
sessionTotalTotal amount required for this checkout
shortfallHow much is missing (sessionTotal - walletBalance)
hasSufficientBalanceAlways false when this error is returned
recommendedTopUpSuggested top-up amount (at least shortfall, rounded up to PSP minimum)
pspMinimumMinimum top-up amount accepted by the payment provider
currencyAlways TZS

Standard Response Fields

Field Type Description
success boolean Always true for successful operations, false for errors
httpStatus string HTTP status name (OK, CREATED, BAD_REQUEST, NOT_FOUND, etc.)
message string Human-readable message describing the operation result
action_time string ISO 8601 timestamp of when the response was generated
data object/string Response payload for success, error details for failures

HTTP Method Badge Standards

For better visual clarity, all endpoints use colored badges for HTTP methods with the following standard colors:

  • GET - GET - Green (Safe, read-only operations)
  • POST - POST - Blue (Create new resources)
  • PATCH - PATCH - Orange (Partial updates)
  • DELETE - DELETE - Red (Remove resources)

Endpoints

1. Create Checkout Session

Purpose: Creates a new checkout session for processing a purchase. Wallet balance is validated upfront — if insufficient, no session is created and the caller receives rich balance data to guide the user. Supports multiple checkout types: direct product purchase, cart checkout, group purchasing, and installment payments (future).payments.

Endpoint: POST {base_url}/checkout-sessions

Access Level: 🔒 Protected (Requires Authentication)

Authentication: Bearer Token required in Authorization header

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authenticated user
Content-Type string Yes Must be application/json

Request JSON Sample:

{
  "sessionType": "REGULAR_DIRECTLY",
  "items": [
    {
      "productId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "quantity": 2
    }
  ],
  "shippingAddressId": "f1e2d3c4-b5a6-7890-cdef-123456789abc",
  "shippingMethodId": "standard-shipping",
  "metadata": {
    "couponCode": "SAVE20",
    "referralCode": "REF123",
    "notes": "Please handle with care"
  },
  "installmentPlanId": null,
  "groupInstanceId": null,
  "downPaymentPercent": 20,20
}

Request Body Parameters:

-PLACEHOLDERFORFUTURE
Parameter Type Required Description Validation
sessionType string Yes Type of checkout session enum: REGULAR_DIRECTLY, REGULAR_CART, GROUP_PURCHASE, INSTALLMENT
items array Conditional Array of items to checkout. Required for REGULAR_DIRECTLY and GROUP_PURCHASE For REGULAR_DIRECTLY: exactly 1 item. For GROUP_PURCHASE: exactly 1 item. Not used for REGULAR_CART
items[].productId string (UUID) Yes (if items provided) Product identifier Valid UUID format
items[].quantity integer Yes (if items provided) Quantity to purchase Min: 1, must not exceed product constraints
shippingAddressId string (UUID) Yes User's shipping address identifier Valid UUID format, must belong to authenticated user
shippingMethodId string Yes Selected shipping method identifier Must be valid shipping method
metadata object No Additional metadata for the session Key-value pairs for coupons, referrals, notes, etc.
installmentPlanId string (UUID) NoConditional Installment plan identifier (for INSTALLMENT type only) Valid UUID format
downPaymentPercent integerConditionalDown payment percentage (INSTALLMENT type only)Must satisfy plan's min/max constraints
groupInstanceId string (UUID) No Group instance to join (for GROUP_PURCHASE type only) Valid UUID format, group must be joinablejoinable. Null = create new group
groupNamestringConditionalName for new group (GROUP_PURCHASE, groupInstanceId null)Must be unique per product

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK"CREATED",
  "message": "Checkout session created successfully",
  "action_time": "2025-10-02T14:30:45",
  "data": {
    "sessionId": "c1d2e3f4-a5b6-7890-cdef-123456789abc",
    "sessionType": "REGULAR_DIRECTLY",
    "status": "PENDING_PAYMENT",
    "customerId": "u1s2e3r4-i5d6-7890-abcd-ef1234567890",
    "customerUserName": "john_doe",
    "items": [
      {
        "productId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "productName": "Premium Wireless Headphones",
        "productSlug": "premium-wireless-headphones",
        "productImage": "https://cdn.nextgate.com/products/headphones-001.jpg",
        "quantity": 2,
        "unitPrice": 150000.00,
        "discountAmount": 20000.00,
        "subtotal": 300000.00,
        "tax": 0.00,
        "total": 280000.00,
        "shopId": "s1h2o3p4-i5d6-7890-abcd-ef1234567890",
        "shopName": "TechWorld Electronics",
        "shopLogo": "https://cdn.nextgate.com/shops/techworld-logo.jpg",
        "availableForCheckout": true,
        "availableQuantity": 50
      }
    ],
    "pricing": {
      "subtotal": 300000.00,
      "discount": 20000.00,
      "shippingCost": 5000.00,
      "tax": 0.00,
      "total": 285000.00,
      "currency": "TZS"
    },
    "shippingAddress": {
      "fullName": "John Doe",
      "addressLine1": "123 Main Street",
      "addressLine2": "Apartment 4B",
      "city": "Dar es Salaam",
      "state": "Dar es Salaam Region",
      "postalCode": "12345",
      "country": "Tanzania",
      "phone": "+255123456789"
    },
    "billingAddress": {
      "sameAsShipping": false,
      "fullName": "John Doe",
      "addressLine1": "456 Business Ave",
      "city": "Dar es Salaam",
      "state": "Dar es Salaam Region",
      "postalCode": "12346",
      "country": "Tanzania"
    },
    "shippingMethod": {
      "id": "standard-shipping",
      "name": "Standard Shipping",
      "carrier": "DHL",
      "cost": 5000.00,
      "estimatedDays": "3-5 business days",
      "estimatedDelivery": "2025-10-07T14:30:45"
    },
    "paymentIntent": {
      "provider": "WALLET",
      "clientSecret": null,
      "paymentMethods": ["WALLET"],
      "status": "READY"
    },
    "paymentAttempts": [],
    "inventoryHeld": true,
    "inventoryHoldExpiresAt": "2025-10-02T14:45:45",
    "metadata": {
      "couponCode": "SAVE20",
      "referralCode": "REF123",
      "notes": "Please handle with care"
    },
    "expiresAt": "2025-10-02T14:45:45",
    "createdAt": "2025-10-02T14:30:45",
    "updatedAt": "2025-10-02T14:30:45",
    "completedAt": null,
    "createdOrderId": null,
    "cartId": null
  }
}

Success Response Fields:

Field Description
sessionId Unique identifier for the checkout session
sessionType Type of checkout (REGULAR_DIRECTLY, REGULAR_CART, GROUP_PURCHASE, INSTALLMENT)
status Current status of the session (PENDING_PAYMENT,always PAYMENT_PROCESSING,PENDING_PAYMENT PAYMENT_COMPLETED,on PAYMENT_FAILED, EXPIRED, CANCELLED, COMPLETED)creation)
customerId User ID who created the session
customerUserName Username of the customer
items Array of checkout items with product details, pricing, and availability
items[].productIdProduct unique identifier
items[].productNameProduct display name
items[].productSlugURL-friendly product identifier
items[].productImagePrimary product image URL
items[].quantityQuantity being purchased
items[].unitPricePrice per unit in TZS
items[].discountAmountTotal discount applied to this item
items[].subtotalUnit price × quantity
items[].taxTax amount for this item
items[].totalFinal total for this item (subtotal + tax - discount)
items[].shopIdShop identifier selling this product
items[].shopNameShop display name
items[].shopLogoShop logo URL
items[].availableForCheckoutWhether product is currently available
items[].availableQuantityCurrent stock quantity available
pricing Summary of all pricing calculations
pricing.subtotalSum of all item subtotals
pricing.discountTotal discount applied
pricing.shippingCostShipping fee
pricing.taxTotal tax amount
pricing.total Final amount to be paidcharged (subtotalwhat +was shippingCostvalidated +against taxwallet - discount)balance)
pricing.currency CurrencyAlways code (TZS)TZS
shippingAddress Complete shipping address details
billingAddressBilling address (may differ from shipping)
billingAddress.sameAsShippingWhether billing address matches shipping address
shippingMethod Selected shipping method details
shippingMethod.idShipping method identifier
shippingMethod.nameDisplay name of shipping method
shippingMethod.carrierCarrier company name
shippingMethod.costShipping fee in TZS
shippingMethod.estimatedDaysEstimated delivery timeframe
shippingMethod.estimatedDeliveryEstimated delivery datetime
paymentIntent Payment processing details
paymentIntent.providerPayment provider (WALLET, CASH_ON_DELIVERY, CREDIT_CARD, etc.)
paymentIntent.clientSecretClient secret for payment processing (null for WALLET/COD)
paymentIntent.paymentMethodsList of available payment methods
paymentIntent.statusPayment intent status (READY, PENDING, etc.)
paymentAttempts ArrayEmpty of payment attempts madearray on this sessioncreation
inventoryHeld Whether inventory is currently held (false for this sessionGROUP_PURCHASE)
inventoryHoldExpiresAt When the inventory hold will be released
metadataCustom metadata provided during creation
expiresAt When this checkout session expires
createdAtSession creation timestamp
updatedAtLast update timestamp
completedAtCompletion timestamp (null15 untilminutes completed)from creation)
createdOrderId Order ID created after successful payment (null until completed)payment succeeds
cartId Cart ID if session was created from cartcart, (null for REGULAR_DIRECTLY)otherwise

Error Response JSON SampleResponses:

Insufficient Wallet Balance (422) — includes rich top-up data:

{
  "success": false,
  "httpStatus": "BAD_REQUEST"UNPROCESSABLE_ENTITY",
  "message": "ValidationInsufficient failed"wallet balance to complete checkout",
  "action_time": "2025-10-02T14:30:45",
  "data": {
    "sessionType"walletBalance": 150000.00,
    "sessionTotal": 285000.00,
    "shortfall": 135000.00,
    "hasSufficientBalance": false,
    "recommendedTopUp": 135000.00,
    "pspMinimum": 500.00,
    "currency": "must not be null",
    "items": "Items are required for checkout",
    "shippingAddressId": "must not be null"TZS"
  }
}

Standard Error Types:

Application-Level Exceptions (400-499)

  • 400 BAD_REQUEST: Invalid request data, validation errors, business rule violations
  • 401 UNAUTHORIZED: Missing, invalid, or expired authentication token
  • 403 FORBIDDEN: Insufficient permissions or verification required
  • 404 NOT_FOUND: Product, payment method, shipping address, or other resource not found
  • 422 UNPROCESSABLE_ENTITY: Validation errors with detailed field information

Server-Level Exceptions (500+)

  • 500 INTERNAL_SERVER_ERROR: Unexpected server errors

Error Response Examples:

Bad Request - Invalid Session Type (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "REGULAR_DIRECTLY checkout supports only 1 item. Use REGULAR_CART for multiple items.",
  "action_time": "2025-10-02T14:30:45",
  "data": "REGULAR_DIRECTLY checkout supports only 1 item. Use REGULAR_CART for multiple items."
}

Bad Request - Insufficient Inventory (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Insufficient stock. Available: 3, Requested: 5",
  "action_time": "2025-10-02T14:30:45",
  "data": "Insufficient stock. Available: 3, Requested: 5"
}

Bad Request - Insufficient Wallet Balance (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Insufficient wallet balance. Required: 285000 TZS, Available: 150000 TZS",
  "action_time": "2025-10-02T14:30:45",
  "data": "Insufficient wallet balance. Required: 285000 TZS, Available: 150000 TZS"
}

Unauthorized - Token Missing (401):

{
  "success": false,
  "httpStatus": "UNAUTHORIZED",
  "message": "Authentication token is required",
  "action_time": "2025-10-02T14:30:45",
  "data": "Authentication token is required"
}

Not Found - Product Not Found (404):

{
  "success": false,
  "httpStatus": "NOT_FOUND",
  "message": "Product not found",
  "action_time": "2025-10-02T14:30:45",
  "data": "Product not found"
}

Not Found - Payment Method Not Found (404):

{
  "success": false,
  "httpStatus": "NOT_FOUND",
  "message": "Payment method not found or does not belong to you",
  "action_time": "2025-10-02T14:30:45",
  "data": "Payment method not found or does not belong to you"
}

Validation Error (422):

{
  "success": false,
  "httpStatus": "UNPROCESSABLE_ENTITY",
  "message": "Validation failed",
  "action_time": "2025-10-02T14:30:45",
  "data": {
    "sessionType": "must not be null",
    "items[0].quantity": "must be greater than or equal to 1",
    "shippingAddressId": "must not be null"
  }
}

Not Found - Product Not Found (404):

{
  "success": false,
  "httpStatus": "NOT_FOUND",
  "message": "Product not found",
  "action_time": "2025-10-02T14:30:45",
  "data": "Product not found"
}

Unauthorized (401):

{
  "success": false,
  "httpStatus": "UNAUTHORIZED",
  "message": "Authentication token is required",
  "action_time": "2025-10-02T14:30:45",
  "data": "Authentication token is required"
}

2. Get Checkout Session by ID

Purpose: Retrieves detailed information about a specific checkout session by its ID. Only the session owner can access their session.

Endpoint: GET {base_url}/checkout-sessions/{sessionId}

Access Level: 🔒 Protected (Requires Authentication and Ownership)

Authentication: Bearer Token required in Authorization header

Request Headers:

HeaderTypeRequiredDescription
AuthorizationstringYesBearer token for authenticated user

Path Parameters:

Parameter Type Required Description Validation
sessionId string (UUID) Yes Unique identifier of the checkout session Valid UUID format

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Checkout session retrieved successfully",
  "action_time": "2025-10-02T14:35:45",
  "data": {
    "sessionId": "c1d2e3f4-a5b6-7890-cdef-123456789abc",
    "sessionType": "REGULAR_DIRECTLY",
    "status": "PENDING_PAYMENT",
    "customerId": "u1s2e3r4-i5d6-7890-abcd-ef1234567890",
    "customerUserName": "john_doe",
    "items": [
      {
        "productId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "productName": "Premium Wireless Headphones",
        "productSlug": "premium-wireless-headphones",
        "productImage": "https://cdn.nextgate.com/products/headphones-001.jpg",
        "quantity": 2,
        "unitPrice": 150000.00,
        "discountAmount": 20000.00,
        "subtotal": 300000.00,
        "tax": 0.00,
        "total": 280000.00,
        "shopId": "s1h2o3p4-i5d6-7890-abcd-ef1234567890",
        "shopName": "TechWorld Electronics",
        "shopLogo": "https://cdn.nextgate.com/shops/techworld-logo.jpg",
        "availableForCheckout": true,
        "availableQuantity": 50
      }
    ],
    "pricing": {
      "subtotal": 300000.00,
      "discount": 20000.00,
      "shippingCost": 5000.00,
      "tax": 0.00,
      "total": 285000.00,
      "currency": "TZS"
    },
    "shippingAddress": {
      "fullName": "John Doe",
      "addressLine1": "123 Main Street",
      "addressLine2": "Apartment 4B",
      "city": "Dar es Salaam",
      "state": "Dar es Salaam Region",
      "postalCode": "12345",
      "country": "Tanzania",
      "phone": "+255123456789"
    },
    "billingAddress": {
      "sameAsShipping": false,
      "fullName": "John Doe",
      "addressLine1": "456 Business Ave",
      "city": "Dar es Salaam",
      "state": "Dar es Salaam Region",
      "postalCode": "12346",
      "country": "Tanzania"
    },
    "shippingMethod": {
      "id": "standard-shipping",
      "name": "Standard Shipping",
      "carrier": "DHL",
      "cost": 5000.00,
      "estimatedDays": "3-5 business days",
      "estimatedDelivery": "2025-10-07T14:30:45"
    },
    "paymentIntent": {
      "provider": "WALLET",
      "clientSecret": null,
      "paymentMethods": ["WALLET"],
      "status": "READY"
    },
    "paymentAttempts": [],
    "inventoryHeld": true,
    "inventoryHoldExpiresAt": "2025-10-02T14:45:45",
    "metadata": { "couponCode": "SAVE20" },
    "expiresAt": "2025-10-02T14:45:45",
    "createdAt": "2025-10-02T14:30:45",
    "updatedAt": "2025-10-02T14:30:45",
    "completedAt": null,
    "createdOrderId": null,
    "cartId": null
  }
}

Success Response Fields:

FieldDescription
sessionIdUnique identifier for the checkout session
sessionTypeType of checkout session
statusCurrent status of the session
customerIdUser ID who owns the session
customerUserNameUsername of the customer
itemsArray of checkout items (see Create Checkout Session for details)
pricingPricing summary (see Create Checkout Session for details)
shippingAddressShipping address details
billingAddressBilling address details
shippingMethodShipping method information
paymentIntentPayment intent details
paymentAttemptsArray of all payment attempts made
inventoryHeldWhether inventory is currently held
inventoryHoldExpiresAtWhen inventory hold expires
metadataCustom metadata
expiresAtSession expiration datetime
createdAtSession creation timestamp
updatedAtLast update timestamp
completedAtCompletion timestamp (null if not completed)
createdOrderIdOrder ID after successful payment (null if not completed)
cartIdCart ID if created from cart

Error Response JSON Sample:

{
  "success": false,
  "httpStatus": "NOT_FOUND",
  "message": "Checkout session not found or you don't have permission to access it",
  "action_time": "2025-10-02T14:35:45",
  "data": "Checkout session not found or you don't have permission to access it"
}

Error Response ExamplesResponses:

Not Found - Session Not Found or No Permission (404):

{
  "success": false,
  "httpStatus": "NOT_FOUND",
  "message": "Checkout session not found or you don't have permission to access it",
  "action_time": "2025-10-02T14:35:45",
  "data": "Checkout session not found or you don't have permission to access it"
}

Unauthorized (401):

{
  "success": false,
  "httpStatus": "UNAUTHORIZED",
  "message": "Authentication token is required",
  "action_time": "2025-10-02T14:35:45",
  "data": "Authentication token is required"
}

3. Get My Checkout Sessions

Purpose: Retrieves all checkout sessions belonging to the authenticated user, ordered by creation date (newest first).

Endpoint: GET {base_url}/checkout-sessions

Access Level: 🔒 Protected (Requires Authentication)

Authentication: Bearer Token required in Authorization header

Request Headers:

HeaderTypeRequiredDescription
AuthorizationstringYesBearer token for authenticated user

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Checkout sessions retrieved successfully",
  "action_time": "2025-10-02T14:40:45",
  "data": [
    {
      "sessionId": "c1d2e3f4-a5b6-7890-cdef-123456789abc",
      "sessionType": "REGULAR_DIRECTLY",
      "status": "PENDING_PAYMENT",
      "itemCount": 1,
      "totalAmount": 285000.00,
      "currency": "TZS",
      "expiresAt": "2025-10-02T14:45:45",
      "createdAt": "2025-10-02T14:30:45",
      "isExpired": false,
      "canRetryPayment": false,
      "itemPreviews": [
        {
          "productId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
          "productName": "Premium Wireless Headphones",
          "productImage": "https://cdn.nextgate.com/products/headphones-001.jpg",
          "quantity": 2,
          "unitPrice": 150000.00,
          "total": 280000.00,
          "shopName": "TechWorld Electronics"
        }
      ]
    },
    {
      "sessionId": "d2e3f4a5-b6c7-8901-def0-234567890abc",
      "sessionType": "REGULAR_CART",
      "status": "COMPLETED",
      "itemCount": 3,
      "totalAmount": 500000.00,
      "currency": "TZS",
      "expiresAt": "2025-10-01T10:15:30",
      "createdAt": "2025-10-01T10:00:30",
      "isExpired": false,
      "canRetryPayment": false,
      "itemPreviews": [
        {
          "productId": "p1r2o3d4-u5c6-7890-abcd-ef1234567890",
          "productName": "Smart Watch Series 5",
          "productImage": "https://cdn.nextgate.com/products/watch-005.jpg",
          "quantity": 1,
          "unitPrice": 350000.00,
          "total": 350000.00,
          "shopName": "Gadget Hub"
        },
        {
          "productId": "p2r3o4d5-u6c7-8901-bcde-f12345678901",
          "productName": "Wireless Mouse",
          "productImage": "https://cdn.nextgate.com/products/mouse-003.jpg",
          "quantity": 2,
          "unitPrice": 45000.00,
          "total": 90000.00,
          "shopName": "TechWorld Electronics"
        }
      ]
    },
    {
      "sessionId": "e3f4a5b6-c7d8-9012-ef01-345678901bcd",
      "sessionType": "PAYMENT_FAILED",
      "status": "PAYMENT_FAILED",
      "itemCount": 1,
      "totalAmount": 120000.00,
      "currency": "TZS",
      "expiresAt": "2025-10-02T15:00:00",
      "createdAt": "2025-10-02T14:45:00",
      "isExpired": false,
      "canRetryPayment": true,
      "itemPreviews": [
        {
          "productId": "p3r4o5d6-u7c8-9012-cdef-234567890123",
          "productName": "USB-C Cable 2m",
          "productImage": "https://cdn.nextgate.com/products/cable-002.jpg",
          "quantity": 5,
          "unitPrice": 15000.00,
          "total": 75000.00,
          "shopName": "Accessories World"
        }
      ]
    }
  ]
}

Success Response Fields:

Field Description
sessionId Unique identifier for the checkout session
sessionType Type of checkout session
status Current status of the session
itemCount Number of items in the checkout
totalAmount Total amount to be paid in TZS
currency Currency code (TZS)
expiresAt When this session expires
createdAt When this session was created
isExpired Whether the session has expired
canRetryPayment Whether payment can be retried (true only if status is PAYMENT_FAILED and not expired)expired and attempts < 5
itemPreviews Array of preview information for items in checkout
itemPreviews[].productIdProduct unique identifier
itemPreviews[].productNameProduct name
itemPreviews[].productImageProduct image URL
itemPreviews[].quantityQuantity being purchased
itemPreviews[].unitPricePrice per unit
itemPreviews[].totalTotal for this item
itemPreviews[].shopNameShop selling this product

Error Response JSON Sample:

{
  "success": false,
  "httpStatus": "UNAUTHORIZED",
  "message": "Authentication token is required",
  "action_time": "2025-10-02T14:40:45",
  "data": "Authentication token is required"
}

Error Response Examples:

Unauthorized (401):

{
  "success": false,
  "httpStatus": "UNAUTHORIZED",
  "message": "Authentication token is required",
  "action_time": "2025-10-02T14:40:45",
  "data": "Authentication token is required"
}

4. Get My Active Checkout Sessions

Purpose: Retrieves only active checkout sessions (PENDING_PAYMENT or PAYMENT_FAILED status) that haven't expired yet, ordered by creation date (newest first).

Endpoint: GET {base_url}/checkout-sessions/active

Access Level: 🔒 Protected (Requires Authentication)

AuthenticationNotes: Bearer Token required in Authorization header

Request Headers:

HeaderTypeRequiredDescription
AuthorizationstringYesBearer token for authenticated user

Success Response JSONstructure Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Active checkout sessions retrieved successfully",
  "action_time": "2025-10-02T14:42:45",
  "data": [
    {
      "sessionId": "c1d2e3f4-a5b6-7890-cdef-123456789abc",
      "sessionType": "REGULAR_DIRECTLY",
      "status": "PENDING_PAYMENT",
      "itemCount": 1,
      "totalAmount": 285000.00,
      "currency": "TZS",
      "expiresAt": "2025-10-02T14:45:45",
      "createdAt": "2025-10-02T14:30:45",
      "isExpired": false,
      "canRetryPayment": false,
      "itemPreviews": [
        {
          "productId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
          "productName": "Premium Wireless Headphones",
          "productImage": "https://cdn.nextgate.com/products/headphones-001.jpg",
          "quantity": 2,
          "unitPrice": 150000.00,
          "total": 280000.00,
          "shopName": "TechWorld Electronics"
        }
      ]
    },
    {
      "sessionId": "e3f4a5b6-c7d8-9012-ef01-345678901bcd",
      "sessionType": "GROUP_PURCHASE",
      "status": "PAYMENT_FAILED",
      "itemCount": 1,
      "totalAmount": 120000.00,
      "currency": "TZS",
      "expiresAt": "2025-10-02T15:00:00",
      "createdAt": "2025-10-02T14:45:00",
      "isExpired": false,
      "canRetryPayment": true,
      "itemPreviews": [
        {
          "productId": "p3r4o5d6-u7c8-9012-cdef-234567890123",
          "productName": "USB-C Cable 2m",
          "productImage": "https://cdn.nextgate.com/products/cable-002.jpg",
          "quantity": 5,
          "unitPrice": 15000.00,
          "total": 75000.00,
          "shopName": "Accessories World"
        }
      ]
    }
  ]
}

Success Response Fields:

filteredtoactive
FieldDescription
sessionIdUnique identifier foris the checkoutsame session
sessionTypeType of checkout session
statusCurrent status (PENDING_PAYMENT or PAYMENT_FAILED only)
itemCountNumber of items in the checkout
totalAmountTotal amount to be paid in TZS
currencyCurrency code (TZS)
expiresAtWhen this session expires
createdAtWhen this session was created
isExpiredAlways false for active sessions
canRetryPaymentWhether payment can be retried
itemPreviewsArray of preview information for items (seeas Get My Checkout Sessions forbut details)
sessions

Erroronly. Response JSON Sample:

{
  "success": false,
  "httpStatus": "UNAUTHORIZED",
  "message": "Authentication tokenisExpired is required",always "action_time":false "2025-10-02T14:42:45",in "data":this "Authentication token is required"
}

Error Response Examples:response.

Unauthorized (401):

{
  "success": false,
  "httpStatus": "UNAUTHORIZED",
  "message": "Authentication token is required",
  "action_time": "2025-10-02T14:42:45",
  "data": "Authentication token is required"
}

5. Update Checkout Session

Purpose: Updates an existing checkout session. Can modify shipping address, shipping method, payment method, or metadata. Only sessions in PENDING_PAYMENT or PAYMENT_FAILED status can be updated.

Endpoint: PATCH {base_url}/checkout-sessions/{sessionId}

Access Level: 🔒 Protected (Requires Authentication and Ownership)

Authentication: Bearer Token required in Authorization header

Request Headers:

HeaderTypeRequiredDescription
AuthorizationstringYesBearer token for authenticated user
Content-TypestringYesMust be application/json

Path Parameters:

Parameter Type Required DescriptionValidation
sessionId string (UUID) Yes Unique identifier of the checkout session Valid UUID format

Request JSON Sample:

{
  "shippingAddressId": "f9e8d7c6-b5a4-3210-fedc-ba9876543210",
  "shippingMethodId": "express-shipping",
  "paymentMethodId": "p9a8y7m6-e5n4-3210-tdef-ba9876543210",
  "metadata": {
    "giftWrapping": true,
    "giftMessage": "Happy Birthday!"
  }
}

Request Body Parameters:

(triggers
Parameter Type Required DescriptionValidation
shippingAddressId string (UUID) No New shipping address identifier Valid UUID format, must belong to user
shippingMethodId string No New shipping method identifier Mustpricing be valid shipping method
paymentMethodIdstring (UUID)NoNew payment method identifierValid UUID format, must belong to userrecalculation)
metadata object NoAdditional or updated metadata Key-value pairs, merged with existing metadata

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Checkout session updated successfully",
  "action_time": "2025-10-02T14:50:45",
  "data": {
    "sessionId": "c1d2e3f4-a5b6-7890-cdef-123456789abc",
    "sessionType": "REGULAR_DIRECTLY",
    "status": "PENDING_PAYMENT",
    "customerId": "u1s2e3r4-i5d6-7890-abcd-ef1234567890",
    "customerUserName": "john_doe",
    "items": [
      {
        "productId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "productName": "Premium Wireless Headphones",
        "productSlug": "premium-wireless-headphones",
        "productImage": "https://cdn.nextgate.com/products/headphones-001.jpg",
        "quantity": 2,
        "unitPrice": 150000.00,
        "discountAmount": 20000.00,
        "subtotal": 300000.00,
        "tax": 0.00,
        "total": 280000.00,
        "shopId": "s1h2o3p4-i5d6-7890-abcd-ef1234567890",
        "shopName": "TechWorld Electronics",
        "shopLogo": "https://cdn.nextgate.com/shops/techworld-logo.jpg",
        "availableForCheckout": true,
        "availableQuantity": 50
      }
    ],
    "pricing": {
      "subtotal": 300000.00,
      "discount": 20000.00,
      "shippingCost": 8000.00,
      "tax": 0.00,
      "total": 288000.00,
      "currency": "TZS"
    },
    "shippingAddress": {
      "fullName": "John Doe",
      "addressLine1": "789 New Address Street",
      "addressLine2": null,
      "city": "Dar es Salaam",
      "state": "Dar es Salaam Region",
      "postalCode": "12347",
      "country": "Tanzania",
      "phone": "+255987654321"
    },
    "billingAddress": {
      "sameAsShipping": false,
      "fullName": "John Doe",
      "addressLine1": "321 Payment Ave",
      "city": "Dar es Salaam",
      "state": "Dar es Salaam Region",
      "postalCode": "12348",
      "country": "Tanzania"
    },
    "shippingMethod": {
      "id": "express-shipping",
      "name": "Express Shipping",
      "carrier": "DHL",
      "cost": 8000.00,
      "estimatedDays": "1-2 business days",
      "estimatedDelivery": "2025-10-04T14:50:45"
    },
    "paymentIntent": {
      "provider": "CREDIT_CARD",
      "clientSecret": "pi_1234567890abcdef",
      "paymentMethods": ["CREDIT_CARD", "DEBIT_CARD"],
      "status": "READY"
    },
    "paymentAttempts": [],
    "inventoryHeld": true,
    "inventoryHoldExpiresAt": "2025-10-02T15:05:45",
    "metadata": {
      "couponCode": "SAVE20",
      "giftWrapping": true,
      "giftMessage": "Happy Birthday!"
    },
    "expiresAt": "2025-10-02T15:05:45",
    "createdAt": "2025-10-02T14:30:45",
    "updatedAt": "2025-10-02T14:50:45",
    "completedAt": null,
    "createdOrderId": null,
    "cartId": null
  }
}

Success Response Fields:

FieldDescription
All fieldsSame as Create Checkout Session response, with updated values
updatedAtTimestamp showing when the session was last updated
pricing.shippingCostMay be recalculated if shipping method changed
pricing.totalMay be recalculated if shipping method changed

Error Response JSON Sample:

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Cannot update - payment has been completed",
  "action_time": "2025-10-02T14:50:45",
  "data": "Cannot update - payment has been completed"
}

Error Response ExamplesResponses:

Bad Request - Cannot Update Completed Session (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Cannot update a completed checkout session",
  "action_time": "2025-10-02T14:50:45",
  "data": "Cannot update a completed checkout session"
}

Bad Request - Cannot Update Cancelled Session (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Cannot update a cancelled checkout session",
  "action_time": "2025-10-02T14:50:45",
  "data": "Cannot update a cancelled checkout session"
}

Bad Request - Cannot Update Expired Session (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Cannot update an expired checkout session",
  "action_time": "2025-10-02T14:50:45",
  "data": "Cannot update an expired checkout session"
}

Not Found - Session Not Found (404):

{
  "success": false,
  "httpStatus": "NOT_FOUND",
  "message": "Checkout session not found or you don't have permission to access it",
  "action_time": "2025-10-02T14:50:45",
  "data": "Checkout session not found or you don't have permission to access it"
}

Not Found - Payment Method Not Found (404):

{
  "success": false,
  "httpStatus": "NOT_FOUND",
  "message": "Payment method not found or does not belong to you",
  "action_time": "2025-10-02T14:50:45",
  "data": "Payment method not found or does not belong to you"
}

6. Cancel Checkout Session

Purpose: Cancels an existing checkout session and releases held inventory. Cannot cancel sessions that are completed or have successful payment.

Endpoint: DELETE {base_url}/checkout-sessions/{sessionId}/cancel

Access Level: 🔒 Protected (Requires Authentication and Ownership)

Authentication: Bearer Token required in Authorization header

Request Headers:

HeaderTypeRequiredDescription
AuthorizationstringYesBearer token for authenticated user

Path Parameters:

ParameterTypeRequiredDescriptionValidation
sessionIdstring (UUID)YesUnique identifier of the checkout session to cancelValid UUID format

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Checkout session cancelled successfully",
  "action_time": "2025-10-02T14:55:45",
  "data": null
}

Success Response Fields:

FieldDescription
dataAlways null for cancel operations

Error Response JSON Sample:

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Cannot cancel a completed checkout session",
  "action_time": "2025-10-02T14:55:45",
  "data": "Cannot cancel a completed checkout session"
}

Error Response ExamplesResponses:

Bad Request - Cannot Cancel Completed Session (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Cannot cancel a completed checkout session",
  "action_time": "2025-10-02T14:55:45",
  "data": "Cannot cancel a completed checkout session"
}

Bad Request - Cannot Cancel with Successful Payment (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Cannot cancel - payment has been completed. Please contact support.",
  "action_time": "2025-10-02T14:55:45",
  "data": "Cannot cancel - payment has been completed. Please contact support."
}

Bad Request - Already Cancelled (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Checkout session is already cancelled",
  "action_time": "2025-10-02T14:55:45",
  "data": "Checkout session is already cancelled"
}

Not Found - Session Not Found (404):

{
  "success": false,
  "httpStatus": "NOT_FOUND",
  "message": "Checkout session not found or you don't have permission to access it",
  "action_time": "2025-10-02T14:55:45",
  "data": "Checkout session not found or you don't have permission to access it"
}

7. Process Payment

Purpose: Initiates payment processing for a checkout session. Validates session status,in inventoryPENDING_PAYMENT availability,status. and payment method before processing. DelegatesRoutes to the appropriate payment providerprocessor (WALLET, CASH, FREE) based on the session amount and payment method type.method.

Endpoint: POST {base_url}/checkout-sessions/{sessionId}/process-payment

Access Level: 🔒 Protected (Requires Authentication and Ownership)

Authentication: Bearer Token required in Authorization header

Request Headers:

HeaderTypeRequiredDescription
AuthorizationstringYesBearer token for authenticated user

Path Parameters:

Parameter Type Required DescriptionValidation
sessionId string (UUID) Yes Unique identifier of the checkout sessionValid UUID format

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Payment processedcompleted successfully"successfully. Your order is being processed.",
  "action_time": "2025-10-02T15:00:45",
  "data": {
    "success": true,
    "paymentProvider": "WALLET",
    "transactionId": "txn_1234567890abcdef",
    "amount": 285000.00,
    "currency": "TZS",
    "status": "COMPLETED"SUCCESS",
    "message": "Payment successful"completed successfully. Your order is being processed.",
    "checkoutSessionId": "c1d2e3f4-a5b6-7890-cdef-123456789abc",
    "escrowId": "esc-uuid",
    "escrowNumber": "ESC-20251002-001",
    "orderId": "ord-uuid",
    "paymentMethod": "WALLET",
    "processedAt"amountPaid": 285000.00,
    "platformFee": 5700.00,
    "sellerAmount": 279300.00,
    "currency": "2025-10-02T15:00:45",
    "orderId": "ord_9876543210fedcba",
    "receiptUrl": nullTZS"
  }
}

Success Response Fields:

(maybenullfor
Field Description
success Whether the payment was successful
paymentProviderstatus PaymentSUCCESS, providerPENDING, usedor (WALLET, CASH_ON_DELIVERY, CREDIT_CARD, etc.)FAILED
transactionIdcheckoutSessionId UniqueThe transactionsession identifierthat was paid
amountescrowId AmountEscrow processedaccount inholding TZSthe funds
currencyCurrency code (TZS)
statusPayment status (COMPLETED, PENDING, PROCESSING, FAILED)
messageescrowNumber Human-readable paymentescrow result message
paymentMethodPayment method type used
processedAtTimestamp of payment processingreference
orderId Order or booking ID created after successful payment
receiptUrlpaymentMethod URLWALLET, toCASH, paymentor receiptFREE
amountPaid Total someamount paymentcharged methods)in TZS
platformFeePlatform fee deducted
sellerAmountAmount the seller receives
currencyAlways TZS

Error Response JSON Sample:

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Cannot process payment - session status: PAYMENT_COMPLETED",
  "action_time": "2025-10-02T15:00:45",
  "data": "Cannot process payment - session status: PAYMENT_COMPLETED"
}

Error Response ExamplesResponses:

Bad Request - Invalid Session StatusNot in PENDING_PAYMENT status (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Cannot process payment - session status:is not pending: PAYMENT_COMPLETED",
  "action_time": "2025-10-02T15:00:45",
  "data": "Cannot process payment - session status:is not pending: PAYMENT_COMPLETED"
}

Bad Request - Session Expired (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Checkout session has expired",
  "action_time": "2025-10-02T15:00:45",
  "data": "Checkout session has expired"
}

Bad Request - Insufficient Wallet Balance (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Insufficient wallet balance. Required: 285000 TZS, Available: 150000 TZS",
  "action_time": "2025-10-02T15:00:45",
  "data": "Insufficient wallet balance. Required: 285000 TZS, Available: 150000 TZS"
}

Not Found - Session Not Found (404):

{
  "success": false,
  "httpStatus": "NOT_FOUND",
  "message": "Checkout session not found or you don't have permission to access it",
  "action_time": "2025-10-02T15:00:45",
  "data": "Checkout session not found or you don't have permission to access it"
}

8. Retry Payment

Purpose: Retries payment for a failed checkout session. Validates that the session is in PAYMENT_FAILED status, hasn't exceeded maximum retry attempts (5), and hasn't expired.status. Re-validates inventory availabilityavailability, checks wallet balance, re-holds inventory, and extends session expiration before retrying. Maximum 5 total attempts.

Endpoint: POST {base_url}/checkout-sessions/{sessionId}/retry-payment

Access Level: 🔒 Protected (Requires Authentication and Ownership)

Authentication: Bearer Token required in Authorization header

Request Headers:

HeaderTypeRequiredDescription
AuthorizationstringYesBearer token for authenticated user

Path Parameters:

ParameterTypeRequiredDescriptionValidation
sessionIdstring (UUID)YesUnique identifier of the checkout sessionValid UUID format

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Payment retry successful",
  "action_time": "2025-10-02T15:10:45",
  "data": {
    "success": true,
    "paymentProvider": "WALLET",
    "transactionId": "txn_retry_1234567890abcdef",
    "amount": 285000.00,
    "currency": "TZS",
    "status": "COMPLETED",
    "message": "Payment successful on retry",
    "paymentMethod": "WALLET",
    "processedAt": "2025-10-02T15:10:45",
    "orderId": "ord_retry_9876543210fedcba",
    "receiptUrl": null
  }
}

Success Response Fields:

FieldDescription
successWhether the payment retry was successful
paymentProviderPayment provider used
transactionIdUnique transaction identifier for this retry
amountAmount processed in TZS
currencyCurrency code (TZS)
statusPayment status (COMPLETED, PENDING, PROCESSING, FAILED)
messageHuman-readable payment result message
paymentMethodPayment method type used
processedAtTimestamp of payment processing
orderIdOrder ID created after successful payment
receiptUrlURL to payment receipt (may be null)

Error Response JSON Sample:

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Cannot retry payment - session status: PENDING_PAYMENT. Expected: PAYMENT_FAILED",
  "action_time": "2025-10-02T15:10:45",
  "data": "Cannot retry payment - session status: PENDING_PAYMENT. Expected: PAYMENT_FAILED"
}

Error Response ExamplesResponses:

Bad Request - Invalid Status (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Cannot retry payment - session status: PENDING_PAYMENT. Expected: PAYMENT_FAILED",
  "action_time": "2025-10-02T15:10:45",
  "data": "Cannot retry payment - session status: PENDING_PAYMENT. Expected: PAYMENT_FAILED"
}

Bad Request - Session Expired (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Checkout session has expired. Please create a new checkout session.",
  "action_time": "2025-10-02T15:10:45",
  "data": "Checkout session has expired. Please create a new checkout session."
}

Bad Request - Max Retry Attempts Exceeded (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Maximum payment attempts (5) exceeded. Please create a new checkout session.",
  "action_time": "2025-10-02T15:10:45",
  "data": "Maximum payment attempts (5) exceeded. Please create a new checkout session."
}

BadInsufficient RequestWallet -Balance on Retry (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Insufficient wallet balance. Required: 285000 TZS, Available: 150000 TZS. Please top up your wallet.",
  "action_time": "2025-10-02T15:10:45",
  "data": "Insufficient wallet balance. Required: 285000 TZS, Available: 150000 TZS. Please top up your wallet."
}

Product No Longer Available (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Product 'Premium Wireless Headphones' is no longer available in requested quantity. Please create a new checkout session.",
  "action_time": "2025-10-02T15:10:45",
  "data": "Product 'Premium Wireless Headphones' is no longer available in requested quantity. Please create a new checkout session."
}

Bad Request - Insufficient Wallet Balance (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Insufficient wallet balance. Required: 285000 TZS, Available: 150000 TZS. Please top up your wallet or update your payment method.",
  "action_time": "2025-10-02T15:10:45",
  "data": "Insufficient wallet balance. Required: 285000 TZS, Available: 150000 TZS. Please top up your wallet or update your payment method."
}

Not Found - Session Not Found (404):

{
  "success": false,
  "httpStatus": "NOT_FOUND",
  "message": "Checkout session not found or you don't have permission to access it",
  "action_time": "2025-10-02T15:10:45",
  "data": "Checkout session not found or you don't have permission to access it"
}

Checkout Session Types

REGULAR_DIRECTLY

Direct product purchase without using a cart. Must include exactly 1 item in the request.

Characteristics:item.

  • Single item purchase flow
  • Items array must contain exactly 1 product
  • Does not link to any cart
  • cartId field will be null in response
  • Best for "Buy Now" buttons
  • or
  • Balance quickis checkoutchecked flowsagainst pricing.total (includes shipping)
  • Inventory is held immediately on session creation

Example Use Case: User clicks "Buy Now" on a product detail page and proceeds directly to checkout.

REGULAR_CART

Checkout from existing shopping cart. Items are retrievedfetched automatically from the user's active cart.

Characteristics:

  • Multi-item purchase flow
  • Items array not required in request
  • Balance is checked against pricing.total (fetchedincludes fromshipping)
  • Inventory is held for all cart automatically)
  • Links to user's cart via cartId
  • Cart is validated before checkout creation
  • cartId field will be populated in responseitems

Example Use Case: User adds multiple products to cart, reviews cart, and clicks "Proceed to Checkout".

GROUP_PURCHASE

SpecialGroup buying checkout type for group buying where multiple users purchase the same product at a discounted group price.

Characteristics:

  • Single item purchase at group priceproduct.groupPrice
  • ItemsBalance arrayis mustchecked containagainst exactlygroupPrice 1× productquantity
  • PaymentWALLET payment method MUST be WALLET (other methods not supported)only
  • Can join existing group via(provide groupInstanceId) or create new group (provide groupName)
  • UsesNo product'ssession-level groupPriceinventory insteadhold of regularinventory price
  • is
  • Requiresheld productat tothe havegroup groupBuyingEnabledlevel =after true
  • Quantity cannot exceed product's groupMaxSize
  • Group has time limit defined by product's groupTimeLimitHourspayment

Example Use Case: User sees a product available for group buying at 80,000 TZS (regular price: 150,000 TZS). User can either start a new group or join an existing group with available seats.

Request Example (Create New Group):Group:

{
  "sessionType": "GROUP_PURCHASE",
  "items": [{ "productId": "prod-uuid", "quantity": 2 }],
  "shippingAddressId": "addr-uuid",
  "groupName":"This is my winning group",
  "shippingMethodId": "standard",
  "paymentMethodId"groupName": null,"My "groupInstanceId":Winning nullGroup"
}

Request Example (Join Existing Group):Group:

{
  "sessionType": "GROUP_PURCHASE",
  "items": [{ "productId": "prod-uuid", "quantity": 3 }],
  "shippingAddressId": "addr-uuid",
  "shippingMethodId": "standard",
  "paymentMethodId": null,
  "groupInstanceId": "group-uuid-to-join"
}

INSTALLMENT

Status: PLACEHOLDER - Not Yet Implemented

Future checkout type for installmentSplit payment plans.over Willmultiple allowmonths. usersOnly tothe splitdown payment is charged at checkout; remaining monthly payments intoare multipleprocessed installments.

automatically

Plannedby Characteristics:the scheduler.

  • WillBalance requireis checked against downPaymentAmount only (not the full product price)
  • installmentPlanId and downPaymentPercent are required
  • pricing.total in request
  • the
  • Paymentsession spreadresponse overreflects multiple periods
  • May requirethe down payment only
  • InterestInventory ratesis mayheld apply basedimmediately on plan
  • session
  • Credit check may be requiredcreation

Current Behavior: Returns error:

{
  "INSTALLMENTsessionType": checkout"INSTALLMENT",
  not"items": implemented[{ yet"

"productId": "prod-uuid", "quantity": 1 }], "shippingAddressId": "addr-uuid", "shippingMethodId": "standard", "installmentPlanId": "plan-uuid", "downPaymentPercent": 20 }

Checkout Session Status Flow

Status Definitions

Status Description Can Update? Can Cancel? Can Pay? Can Retry?
PENDING_PAYMENT Session created, awaiting payment Yes Yes Yes No
PAYMENT_PROCESSING Payment in progress No No No No
PAYMENT_FAILED Payment failed, can retry Yes Yes No Yes
PAYMENT_COMPLETED Payment successful No No No No
EXPIRED Session expired No No No No
CANCELLED User cancelled No No No No
COMPLETED OrderFree/cash createdorder successfullycompleted No No No No

Status Transition Flow

[Session Creation]
        |
        | balance check passes
        v
PENDING_PAYMENT
    |
    |-- user cancels ──────────────────> PAYMENT_PROCESSINGCANCELLED
    |                                    (wheninventory paymentreleased)
    initiated)|
    |-- 15 min timeout ────────────────> PAYMENT_COMPLETEDEXPIRED
    |                                    (oninventory success)released)
    |
    |-- processPayment()
        |
        |-- amount = 0 ────────────────> COMPLETED (afterfree)
        order|
        creation)|-- CASH ──────────────────────> COMPLETED (cash)
        |
        |-- WALLET ────────────────────> PAYMENT_PROCESSING
                                                |
                                                |-- success ──> PAYMENT_COMPLETED
                                                |                (order/booking created,
                                                |                 inventory committed)
                                                |
                                                |-- failure ──> PAYMENT_FAILED
                                                                (oninventory failure,released canfor retryevents,
                                                                 max 5 times)retries)
                                                                |
                                                                |-- retryPayment() ──> PENDING_PAYMENT
                                                                |                     (wheninventory retryre-held)
                                                                initiated)|
                                                                |-- 5 attempts ──────> EXPIRED
(after
max
retries

Wallet orBalance Check Endpoint

For cases where the frontend wants to proactively check balance against an existing session timeout)(e.g., ├─>before CANCELLEDshowing (userthe cancels)"Pay └─>Now" EXPIREDbutton), (15use:

minutes

Endpoint: timeout)GET {base_url}/wallet/checkout-balance-check?sessionId={id}&domain={PRODUCT|EVENT}

Success Response:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Checkout balance check completed",
  "data": {
    "walletBalance": 150000.00,
    "sessionTotal": 285000.00,
    "shortfall": 135000.00,
    "hasSufficientBalance": false,
    "recommendedTopUp": 135000.00,
    "pspMinimum": 500.00,
    "currency": "TZS"
  }
}

Note: This endpoint always returns 200 — it never throws. Use hasSufficientBalance to determine if the user can pay. This is the "soft check" for an existing session; the "hard check" (which blocks session creation) happens automatically inside POST /checkout-sessions.


Payment Methods Supported

WALLET (Default)

Internal wallet systemsystem. forDefault storingif andno usingpayment funds.

method

Requirements:is specified.

  • User must have active wallet
  • Sufficient balance required
  • Balance checkedvalidated beforeat session creation (hard block) and again at payment processingtime (safety net)
  • Instant paymentprocessing processingvia escrow
  • NoFunds additionalheld feesin escrow until order is confirmed/delivered

Payment Flow:

  1. Validate wallet is active
  2. Check sufficient balance
  3. Deduct amount from wallet
  4. Create transaction record
  5. Create order

Default Behavior: If no paymentMethodId provided in request, WALLET is used as default.

CASH_ON_DELIVERYCASH

Pay in cash whenon orderdelivery isor delivered.

at

Requirements:the point of event check-in.

  • No pre-payment required
  • Payment collected by delivery agent
  • OrderOrder/booking created immediately
  • MayApplicable haveto geographicboth restrictionsproduct and event checkouts

FREE

PaymentZero-amount Flow:checkout (free products or free event tickets).

    • CreateHandled automatically when pricing.total = 0
    • No payment intentmethod with status "PENDING"required
    • CreateOrder/booking ordercreated immediately
    • Payment marked as "COD"
    • Delivery agent collects payment on delivery

CREDIT_CARD / DEBIT_CARDMOBILE_MONEY

Status: Planned - Notnot Yetyet Implemented

Future support for credit and debit card payments.

Planned Features:

  • Card tokenization for security
  • PCI compliance
  • 3D Secure authentication
  • Saved cards support
  • International cards support

MNO_PAYMENT (Mobile Money)

Status: Planned - Not Yet Implemented

Future support for mobile money payments (M-Pesa, Tigo Pesa, Airtel Money, etc.).

Planned Features:

  • USSD push notifications
  • Callback confirmation
  • Transaction reconciliation
  • Multiple operators support

Other Payment Methods

Additional payment methods (PayPal, Bank Transfer, Cryptocurrency, Gift Card) are placeholders for future implementation.implemented.


Inventory Management

Inventory Hold Mechanism

Session TypeHold Created AtHold Released At
REGULAR_DIRECTLYSession creationExpiry, cancellation, or payment success (committed)
REGULAR_CARTSession creationExpiry, cancellation, or payment success (committed)
GROUP_PURCHASEAfter payment, at group levelGroup expiry or group failure
INSTALLMENTSession creationExpiry, cancellation, or payment success (committed)

WhenOn asuccessful checkoutpayment, sessionholds isare created,committed inventory(stock ispermanently automaticallydeducted). heldOn failure/expiry/cancellation, holds are released (stock returned to prevent overselling.

Hold Behavior:

  • Inventory held for 15 minutes (matches session expiration)
  • Held quantity deducted from available stock
  • Other users cannot purchase held inventory
  • Hold automatically released on:
    • Session expiration
    • Session cancellation
    • Payment failure (after 5 retry attempts)
  • Hold converted to permanent deduction on successful payment

Hold Fields:

  • inventoryHeld: Boolean indicating if inventory is currently held
  • inventoryHoldExpiresAt: Timestamp when hold will be released

Example:

{
  "inventoryHeld": true,
  "inventoryHoldExpiresAt": "2025-10-02T14:45:45"
}

Inventory Validation

Before processing payment or retry, system validates:

  1. Product still exists and is active
  2. Product still in stock
  3. Requested quantity still available
  4. Product hasn't been deleted

If validation fails, user must create new checkout session with current availability.available).


Session Expiration

Expiration Rules

Default Expiration:Default: 15 minutes from creationcreation.

Expiration Extended When:when:

  • Payment retry is initiated (adds 15 minutes)
  • Session updated successfully (adds 15 minutes)
.

WhatOn Happens on Expiration:expiry:

  1. SessionStatus status changes to EXPIRED
  2. Held inventory released back to available stock
  3. Session cannot be updatedupdated, paid, or paid
  4. Session cannot be cancelled (already effectively ended)
  5. User must create new checkout session

Checking Expiration:

  • expiresAt field shows expiration timestamp
  • isExpired field (in summary responses) shows if session expired

Preventing Expiration

To prevent session expiration:

  1. Complete payment before expiration
  2. Update session if needed (extends timer)
  3. If expired, createa new checkout session

Best Practice: Display countdown timer to users showing time remaining before expiration.


Payment Attempts Tracking

Attempt Limits

Maximum Attempts: 5 attempts per session

Attempt Tracking:session. Each payment attempt recorded with:records:

  • Attempt number (1-1–5)
  • Payment method used
  • StatusStatus: (SUCCESS, FAILED, RETRY_INITIATED)or RETRY_INITIATED
  • Error message (if failed)
  • Timestamp
  • Transactionand transaction ID (if available)

Example Payment Attempts:

{
  "paymentAttempts": [
    {
      "attemptNumber": 1,
      "paymentMethod": "WALLET",
      "status": "FAILED",
      "errorMessage": "Insufficient wallet balance",
      "attemptedAt": "2025-10-02T14:35:00",
      "transactionId": null
    },
    {
      "attemptNumber": 2,
      "paymentMethod": "WALLET",
      "status": "RETRY_INITIATED",
      "errorMessage": null,
      "attemptedAt": "2025-10-02T14:40:00",
      "transactionId": null
    },
    {
      "attemptNumber": 3,
      "paymentMethod": "WALLET",
      "status": "SUCCESS",
      "errorMessage": null,
      "attemptedAt": "2025-10-02T14:42:00",
      "transactionId": "txn_1234567890abcdef"
    }
  ]
}

After Max Attempts

When 5 attemptsfailed exceeded:

attempts,
  1. Sessionsession status setmoves to EXPIRED
  2. Inventoryand released
  3. inventory
  4. Cannotis retry payment
  5. User must create new checkout session

Metadata Usage

Purpose

Metadata allows storing custom key-value data with checkout sessions for business-specific needs.released.

Common Use Cases

Coupons & Discounts:

{
  "metadata": {
    "couponCode": "SAVE20",
    "couponDiscount": 20000,
    "couponAppliedAt": "2025-10-02T14:30:00"
  }
}

Referral Tracking:

{
  "metadata": {
    "referralCode": "REF123",
    "referredBy": "user-uuid",
    "referralBonus": 5000
  }
}

Gift Options:

{
  "metadata": {
    "isGift": true,
    "giftWrapping": true,
    "giftMessage": "Happy Birthday!",
    "giftRecipientName": "Jane Doe"
  }
}

Delivery Instructions:

{
  "metadata": {
    "deliveryInstructions": "Leave package at front desk",
    "deliveryTimePreference": "morning",
    "contactOnArrival": true
  }
}

Group Purchase:

{
  "metadata": {
    "groupInstanceId": "group-uuid",
    "isGroupLeader": true,
    "groupCreatedAt": "2025-10-02T14:30:00"
  }
}

Marketing Attribution:

{
  "metadata": {
    "source": "facebook_ad",
    "campaign": "summer_sale_2025",
    "medium": "social_media"
  }
}

Metadata Rules

  • Stored as JSON object
  • Key-value pairs with string keys
  • Values can be strings, numbers, booleans, or nested objects
  • No size limit enforced at API level (reasonable usage expected)
  • Merged with existing metadata on update (not replaced)
  • Persisted with session throughout lifecycle
  • Accessible in order after completion

Error Handling Best Practices

Client-SideFrontend HandlingChecklist

Before Creatingcalling Checkout:POST /checkout-sessions:

    • ValidateEnsure the user has a shipping address saved
    • CheckNo productneed availabilityto pre-check balance — the API returns rich balance data if insufficient

    On 422 Insufficient Balance response:

    • Read data.shortfall to show how much the user is short
    • VerifyRead paymentdata.recommendedTopUp methodto existspre-fill (ifa top-up amount
    • Navigate the user to the wallet top-up screen
    • Once topped up, retry POST /checkout-sessions — do not usingstore wallet)the failed session
    • Display clear pricing breakdown

During Checkout:active session (PENDING_PAYMENT):

    • Show expirationa countdown timer using expiresAt
    • HandleOn expiry, prompt user to create a new session expiration gracefully
    • Provide clear error messages
    • Suggest actions (e.g., "Top up wallet" if insufficient balance)

PaymentOn Failures:payment failure:

    • DisplayShow specificcanRetryPayment errorto reasondecide whether to show a retry button
    • Show remaining retryattempts attempts(5 - paymentAttemptCount)
    • OfferOn retry, call POST /{sessionId}/retry-payment — no need to update payment method
    • Suggest alternative payment methods

Common Error Scenarios

Insufficient Inventory:

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Insufficient stock. Available: 3, Requested: 5"
}

Action: Reduce quantity or create new session with available quantity.

Insufficient Wallet Balance:

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Insufficient wallet balance. Required: 285000 TZS, Available: 150000 TZS"
}

Action: Top up wallet or change payment method.

Session Expired:

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Checkout session has expired"
}

Action: Create new checkout session.

Product Unavailable:

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Product is not available for purchase"
}

Action: Remove product from cart or select alternative product.

Max Retries Exceeded:

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Maximum payment attempts (5) exceeded. Please create a new checkoutsession
session."
}

Action: Create new checkout session, possibly with different payment method.


Integration Examples

Example 1: Direct Product Purchase Flow

Step 1: Create Checkout Session

1. POST /api/v1/checkout-sessions
   Authorization: Bearer422 {token}if Content-Type:balance application/jsoninsufficient {(show "sessionType":top-up "REGULAR_DIRECTLY",screen "items":with [{data.recommendedTopUp)
   "productId": "prod-uuid",201 "quantity":with 1sessionId }],if "shippingAddressId":balance "addr-uuid",OK

"shippingMethodId":2. "standard",
  "paymentMethodId": null
}

Step 2: Process Payment

POST /api/v1/checkout-sessions/{sessionId}/process-payment
   Authorization: Bearer200 {token}with orderId on success

Step 3: Check Order Created Response will include orderId field after successful payment.

Example 2: Cart Checkout Flow

Step 1: Create Checkout from Cart

1. POST /api/v1/checkout-sessions  Authorization: Bearer {token}
Content-Type: application/json

{ "sessionType":sessionType: "REGULAR_CART",REGULAR_CART, "shippingAddressId": "addr-uuid",
  "shippingMethodId": "express",
  "metadata": {
    "couponCode": "SAVE20"... }
   } 
422

Stepor 2:201 Review2. Session

(optional)
GETPATCH /api/v1/checkout-sessions/{sessionId}  Authorization: Bearer {token}

Step 3: Update if Needed

PATCH /api/v1/checkout-sessions/{sessionId}
Authorization: Bearer {token}
Content-Type: application/json

{ "shippingMethodId":shippingMethodId: "standard",
  "metadata": {
    "giftWrapping": trueexpress" }

}3. 

Step 4: Process Payment

POST /api/v1/checkout-sessions/{sessionId}/process-payment
Authorization: Bearer {token}

Example 3: Group Purchase Flow

Step 1: Create Group Purchase Session

1. POST /api/v1/checkout-sessions  Authorization: Bearer {token}
Content-Type: application/json

{ "sessionType":sessionType: GROUP_PURCHASE, groupName: "GROUP_PURCHASE"...", "items": [{
    "productId": "prod-uuid",
    "quantity": 2
  }],
  "shippingAddressId": "addr-uuid",
  "shippingMethodId": "standard",
  "groupInstanceId": null... }
   

Step422 2:if Processbalance Payment< (WALLETgroupPrice only)

×
qty
   → 201 with sessionId

2. POST /api/v1/checkout-sessions/{sessionId}/process-payment
   Authorization:(WALLET Bearer {token}only)

Example 4: Installment

1. POST /checkout-sessions  { sessionType: INSTALLMENT, installmentPlanId: "...", downPaymentPercent: 20 }
   → 422 if balance < downPaymentAmount
   → 201 with sessionId (pricing.total = down payment only)

2. POST /checkout-sessions/{sessionId}/process-payment
   → charges down payment only; monthly payments handled by scheduler

Example 5: Payment Retry Flow

Step 1: Get Active Sessions

1. GET /api/v1/checkout-sessions/active
   Authorization: Bearer {token}

Step 2: Identify Failed Session Look forfind session with status: "PAYMENT_FAILED"PAYMENT_FAILED, and canRetryPayment: true

Step2. 3: Update Payment Method (Optional)

PATCH /api/v1/checkout-sessions/{sessionId}
Authorization: Bearer {token}
Content-Type: application/json

{
  "paymentMethodId": "new-payment-method-uuid"
}

Step 4: Retry Payment

POST /api/v1/checkout-sessions/{sessionId}/retry-payment
   Authorization: Bearerre-validates {token}inventory + balance
   → re-holds inventory
   → processes payment

Rate Limiting

Rate

Limits:

  • Process/
  • Update/Cancel:
  • Rate

    Limit Headers:

    X-RateLimit-Limit: 20
    X-RateLimit-Remaining: 15
    X-RateLimit-Reset: 1696258800
    

    Rate Limit Exceeded:

    {
      "success": false,
      "httpStatus": "TOO_MANY_REQUESTS",
      "message": "Rate limit exceeded. Please try again later.",
      "action_time": "2025-10-02T15:30:45",
      "data": "Rate limit exceeded. Please try again later."
    }
    
    EndpointLimit
    Create Checkout:Checkout 20 requests per minutereq/min per user
    Get Sessions:Sessions 60 requests per minutereq/min per user
    Process / Retry Payment:Payment 10 requests per minutereq/min per user
    Update / Cancel30 requests per minutereq/min per user