Send Pay Links
API Reference

Checkout API

Initialize and complete checkout sessions

Checkout API

The Checkout API handles the core checkout flow: initializing sessions with payment providers, completing purchases, and retrieving payment tokens for upsells.

Initialize Checkout

Initialize a checkout session with a payment provider.

POST /api/checkout/initialize
Content-Type: application/json

Request Body

interface InitializeRequest {
  token: string;                    // JWT checkout token
  provider: PaymentProviderType;    // Payment provider to use

  // Optional: Override/update customer info (for global links)
  customer?: {
    email: string;
    firstName: string;
    lastName: string;
    phone?: string;
  };

  // Optional: Override/update addresses
  shippingAddress?: {
    line1: string;
    line2?: string;
    city: string;
    state: string;
    postalCode: string;
    country: string;
  };

  billingAddress?: {
    line1: string;
    line2?: string;
    city: string;
    state: string;
    postalCode: string;
    country: string;
  };
}

type PaymentProviderType =
  | 'stripe'
  | 'nmi'
  | 'sticky'
  | 'konnektive'
  | 'shopify'
  | 'ultracart'
  | 'epd';

Example Request

{
  "token": "eyJhbGciOiJIUzI1NiIs...",
  "provider": "stripe",
  "customer": {
    "email": "customer@example.com",
    "firstName": "John",
    "lastName": "Doe",
    "phone": "+1234567890"
  },
  "shippingAddress": {
    "line1": "123 Main St",
    "city": "New York",
    "state": "NY",
    "postalCode": "10001",
    "country": "US"
  }
}

Success Response

{
  "success": true,
  "provider": "stripe",
  "providerOrderId": "pi_3ABC123DEF456",
  "clientSecret": "pi_3ABC123DEF456_secret_xyz789"
}

Response fields vary by provider:

ProviderResponse Fields
StripeclientSecret for Stripe.js
ShopifycheckoutUrl for redirect
NMIproviderOrderId
Sticky.ioproviderOrderId

Error Responses

// Missing token or provider
{
  "error": "Missing token or provider"
}
// Status: 400

// Invalid or expired token
{
  "error": "Invalid token"
}
// Status: 401

// Provider not allowed for this checkout
{
  "error": "Payment provider not allowed for this checkout"
}
// Status: 400

Complete Checkout

Complete checkout after successful payment. Creates order records, retrieves payment tokens for upsells, and optionally records in CRM.

POST /api/checkout/complete
Content-Type: application/json

Request Body

interface CompleteCheckoutRequest {
  // Required fields
  orderId: string;
  transactionId: string;
  provider: PaymentProviderType;
  customerEmail: string;
  customerName: string;
  amount: number;               // In cents (9999 = $99.99)
  currency: string;

  // Optional: Provider-specific order ID
  providerOrderId?: string;

  // Optional: Customer and address info for CRM
  customer?: {
    firstName: string;
    lastName: string;
    phone?: string;
    ipAddress?: string;
  };

  billingAddress?: {
    line1: string;
    line2?: string;
    city: string;
    state: string;
    postalCode: string;
    country: string;
  };

  shippingAddress?: {
    line1: string;
    line2?: string;
    city: string;
    state: string;
    postalCode: string;
    country: string;
  };

  lineItems?: Array<{
    id: string;
    name?: string;
    quantity: number;
    unitPrice: number;
    sku?: string;
  }>;

  // CRM options
  recordInCrm?: boolean;
  crmProvider?: 'konnektive' | 'sticky' | 'ultracart' | 'none';
  crmCampaignId?: string;
  affId?: string;
  subId?: string;

  // Sales attribution for commissions
  salesAttribution?: {
    salespersonId: string;
    salespersonName?: string;
    salespersonEmail?: string;
    teamId?: string;
    teamName?: string;
    commissionRate?: number;      // 0.10 = 10%
    commissionType?: 'percentage' | 'fixed';
    source?: string;
    campaignCode?: string;
    generatedAt?: number;
  };
}

Example Request

{
  "orderId": "order_abc123",
  "transactionId": "pi_3ABC123DEF456",
  "provider": "stripe",
  "providerOrderId": "pi_3ABC123DEF456",
  "customerEmail": "customer@example.com",
  "customerName": "John Doe",
  "amount": 9999,
  "currency": "USD",
  "customer": {
    "firstName": "John",
    "lastName": "Doe",
    "phone": "+1234567890",
    "ipAddress": "192.168.1.1"
  },
  "billingAddress": {
    "line1": "123 Main St",
    "city": "New York",
    "state": "NY",
    "postalCode": "10001",
    "country": "US"
  },
  "lineItems": [
    {
      "id": "prod_123",
      "name": "Premium Plan",
      "quantity": 1,
      "unitPrice": 9999,
      "sku": "PREM-001"
    }
  ],
  "recordInCrm": false,
  "salesAttribution": {
    "salespersonId": "sp_123",
    "salespersonName": "Jane Smith",
    "commissionRate": 0.10,
    "commissionType": "percentage"
  }
}

Success Response

{
  "success": true,
  "orderId": "order_abc123",
  "transactionId": "pi_3ABC123DEF456",
  "paymentMethodToken": "pm_1ABC|cus_XYZ",
  "provider": "stripe",
  "crmOrderId": "12345678",
  "crmProvider": "konnektive",
  "commissionId": "comm_xyz789"
}

Payment Method Token Formats

The paymentMethodToken enables 1-click upsell charges:

ProviderFormatUsage
StripepaymentMethodId|customerIdPaymentIntent with saved method
NMIcustomerVaultId|transactionIdCustomer vault charge
Sticky.iostickyOrderIdAdd-to-order
KonnektiveorderIdAdd-to-order

Get Payment Token

Retrieve payment method token for processing upsell charges.

POST /api/checkout/get-payment-token
Content-Type: application/json

Request Body

{
  "provider": "stripe",
  "transactionId": "pi_3ABC123DEF456",
  "providerOrderId": "pi_3ABC123DEF456"
}

Response

{
  "success": true,
  "paymentMethodToken": "pm_1ABC|cus_XYZ",
  "provider": "stripe"
}

Generate Token (Development)

Generate checkout tokens and short URLs for development and testing.

POST /api/token/generate
Content-Type: application/json

Request Body

interface GenerateTokenRequest {
  orderInfo?: {
    orderId?: string;
    total?: number;
    currency?: string;
    productName?: string;
    productDescription?: string;
  };

  lineItems?: Array<{
    id: string;
    name: string;
    description?: string;
    quantity: number;
    unitPrice: number;
  }>;

  customer?: {
    email?: string;
    firstName?: string;
    lastName?: string;
    phone?: string;
  };

  salesAttribution?: {
    salespersonId: string;
    salespersonName?: string;
    commissionRate?: number;
  };
}

Response

{
  "success": true,
  "code": "abc123",
  "checkoutUrl": "https://checkout.example.com/c/abc123",
  "token": "eyJhbGciOiJIUzI1NiIs...",
  "payload": {
    "orderId": "order_test_123",
    "total": 4999,
    "currency": "USD"
  }
}

This endpoint auto-generates demo data if fields are not provided. Use it for testing checkout flows and sales attribution.


Checkout Flow Diagram

┌─────────────────────────────────────────────────────────────────┐
│                        Your Server                               │
├─────────────────────────────────────────────────────────────────┤
│  1. Generate JWT token with order details                       │
│     └─> Sign with CHECKOUT_TOKEN_SECRET                         │
└───────────────────────────┬─────────────────────────────────────┘

                            v
┌─────────────────────────────────────────────────────────────────┐
│                     Checkout Frontend                            │
├─────────────────────────────────────────────────────────────────┤
│  2. Customer enters info, selects payment method                │
│                                                                  │
│  3. POST /api/checkout/initialize                               │
│     └─> Returns clientSecret (Stripe) or checkoutUrl            │
│                                                                  │
│  4. Collect payment via provider SDK                            │
│     └─> Stripe.js, hosted form, etc.                            │
│                                                                  │
│  5. POST /api/checkout/complete                                 │
│     └─> Creates order, returns paymentMethodToken               │
│                                                                  │
│  6. (Optional) Create upsell session                            │
│     └─> POST /api/upsell/create-session                         │
└───────────────────────────┬─────────────────────────────────────┘

                            v
┌─────────────────────────────────────────────────────────────────┐
│                    Webhook Delivery                              │
├─────────────────────────────────────────────────────────────────┤
│  7. Events sent to configured webhooks                          │
│     - checkout.completed                                         │
│     - payment.succeeded                                          │
│     - order.confirmed                                            │
└─────────────────────────────────────────────────────────────────┘

Error Codes

CodeDescription
INVALID_TOKENThe checkout token is invalid or expired
CHECKOUT_NOT_FOUNDNo checkout found for the given token
CHECKOUT_EXPIREDThe checkout session has expired
PAYMENT_FAILEDPayment processing failed
VALIDATION_ERRORRequest validation failed
PROVIDER_NOT_ALLOWEDPayment provider not allowed for this checkout

Error Response Format

{
  "error": "Payment failed: Card declined",
  "details": "insufficient_funds"
}

Code Examples

Node.js / TypeScript

// Initialize checkout
const initResponse = await fetch('/api/checkout/initialize', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    token: checkoutToken,
    provider: 'stripe',
    customer: {
      email: 'customer@example.com',
      firstName: 'John',
      lastName: 'Doe',
    },
  }),
});

const { clientSecret } = await initResponse.json();

// Use Stripe.js to confirm payment
const { error, paymentIntent } = await stripe.confirmPayment({
  elements,
  clientSecret,
  confirmParams: {
    return_url: `${window.location.origin}/success`,
  },
});

if (!error && paymentIntent.status === 'succeeded') {
  // Complete checkout
  const completeResponse = await fetch('/api/checkout/complete', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      orderId: 'order_123',
      transactionId: paymentIntent.id,
      provider: 'stripe',
      customerEmail: 'customer@example.com',
      customerName: 'John Doe',
      amount: 9999,
      currency: 'USD',
    }),
  });

  const { paymentMethodToken } = await completeResponse.json();
  // Use token for upsells if needed
}

Python

import requests

# Initialize checkout
init_response = requests.post(
    'https://checkout.example.com/api/checkout/initialize',
    json={
        'token': checkout_token,
        'provider': 'stripe',
        'customer': {
            'email': 'customer@example.com',
            'firstName': 'John',
            'lastName': 'Doe',
        },
    }
)

data = init_response.json()
client_secret = data['clientSecret']

# Complete checkout after payment
complete_response = requests.post(
    'https://checkout.example.com/api/checkout/complete',
    json={
        'orderId': 'order_123',
        'transactionId': 'pi_abc123',
        'provider': 'stripe',
        'customerEmail': 'customer@example.com',
        'customerName': 'John Doe',
        'amount': 9999,
        'currency': 'USD',
    }
)

result = complete_response.json()
print(f"Order completed: {result['orderId']}")
print(f"Payment token: {result['paymentMethodToken']}")

CRM Integration

When recordInCrm is true, the order is recorded in the configured CRM after payment:

{
  "orderId": "order_123",
  "transactionId": "pi_abc",
  "provider": "stripe",
  "recordInCrm": true,
  "crmProvider": "konnektive",
  "crmCampaignId": "camp_123",
  "customer": { ... },
  "billingAddress": { ... },
  "lineItems": [ ... ]
}

Note: CRM recording requires customer and billingAddress fields. If these are missing, CRM recording is skipped (unless failOnCrmError is configured).

The response includes CRM order ID:

{
  "success": true,
  "orderId": "order_123",
  "crmOrderId": "12345678",
  "crmProvider": "konnektive"
}

On this page