Skip to content

Create Order API

Lock in a quote and create a payment order. This API converts a quote into an executable payment order with guaranteed pricing.

Endpoint

POST /v1/order/create

Authentication

This endpoint requires API key authentication:

Authorization: Bearer YOUR_API_KEY

Request Parameters

ParameterTypeRequiredDescription
checkoutIdstringCheckout session identifier
quoteIdstringQuote identifier from Get Quote API
userAddressstringUser's wallet address
recipientAddressstringCustom recipient address (defaults to merchant address)
metadataobjectAdditional order metadata

Example Request

{
  "checkoutId": "checkout_1759231185333_abc123",
  "quoteId": "quote_1759231185333_def456",
  "userAddress": "0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8e8",
  "recipientAddress": "0x8ba1f109551bD432803012645Hac136c22C501e5",
  "metadata": {
    "customerNote": "Express delivery requested",
    "referralCode": "FRIEND20"
  }
}

Response Format

Success Response

{
  "success": true,
  "data": {
    "orderId": "order_1759231185333_ghi789",
    "checkoutId": "checkout_1759231185333_abc123",
    "quoteId": "quote_1759231185333_def456",
    "status": "pending_payment",
    "paymentAmount": "100.50",
    "settlementAmount": "100.00",
    "paymentToken": {
      "address": "0x7F5c764cBc14f9669B88837ca1490cCa17c31607",
      "decimals": 6,
      "symbol": "USDC.e",
      "chainId": 10
    },
    "settlementToken": {
      "address": "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
      "decimals": 6,
      "symbol": "USDC",
      "chainId": 137
    },
    "userAddress": "0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8e8",
    "recipientAddress": "0x8ba1f109551bD432803012645Hac136c22C501e5",
    "constraints": {
      "maxSlippage": "0.5%",
      "minOutputAmount": "99.50",
      "deadline": 1759234785
    },
    "fees": {
      "total": {
        "amount": "0.50",
        "amountUsd": "0.50",
        "percentage": "0.5%"
      },
      "breakdown": {
        "networkFee": "0.20",
        "bridgeFee": "0.15",
        "platformFee": "0.15"
      }
    },
    "estimatedTime": 420,
    "createdAt": 1759231185,
    "expiresAt": 1759234785,
    "metadata": {
      "customerNote": "Express delivery requested",
      "referralCode": "FRIEND20"
    }
  },
  "timestamp": "2024-01-01T00:00:00Z"
}

Response Fields

FieldTypeDescription
orderIdstringUnique order identifier
statusstringOrder status (pending_payment, expired, completed, failed)
paymentAmountstringAmount user needs to pay
settlementAmountstringAmount merchant will receive
constraintsobjectPayment constraints and limits
feesobjectDetailed fee breakdown
estimatedTimenumberEstimated completion time in seconds
expiresAtnumberOrder expiration timestamp

Order Status Values

StatusDescription
pending_paymentWaiting for user to initiate payment
processingPayment is being processed
bridgingCross-chain transfer in progress
settlingFinal settlement in progress
completedOrder successfully completed
failedOrder failed (may be retryable)
expiredOrder expired without payment
cancelledOrder cancelled by user or merchant

Error Responses

Quote Expired

{
  "success": false,
  "error": {
    "code": "QUOTE_EXPIRED",
    "message": "Quote has expired, please request a new quote",
    "details": {
      "quoteId": "quote_1759231185333_def456",
      "expiredAt": 1759231485,
      "currentTime": 1759231500
    }
  },
  "timestamp": "2024-01-01T00:00:00Z"
}

Invalid Checkout

{
  "success": false,
  "error": {
    "code": "INVALID_CHECKOUT",
    "message": "Checkout session not found or expired",
    "details": {
      "checkoutId": "checkout_1759231185333_abc123"
    }
  },
  "timestamp": "2024-01-01T00:00:00Z"
}

Insufficient Balance

{
  "success": false,
  "error": {
    "code": "INSUFFICIENT_BALANCE",
    "message": "User has insufficient balance for this payment",
    "details": {
      "required": "100.50",
      "available": "50.25",
      "token": "USDC.e",
      "chainId": 10
    }
  },
  "timestamp": "2024-01-01T00:00:00Z"
}

Code Examples

JavaScript/TypeScript

import { CyberPaySDK } from '@cyberpay/sdk';
 
const sdk = new CyberPaySDK({
  apiKey: 'YOUR_API_KEY',
  environment: 'production'
});
 
async function createOrder() {
  try {
    const order = await sdk.order.create({
      checkoutId: 'checkout_1759231185333_abc123',
      quoteId: 'quote_1759231185333_def456',
      userAddress: '0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8e8',
      metadata: {
        customerNote: 'Express delivery requested'
      }
    });
    
    console.log('Order created:', order);
    return order;
  } catch (error) {
    console.error('Error creating order:', error);
    
    if (error.code === 'QUOTE_EXPIRED') {
      // Get a new quote and retry
      const newQuote = await sdk.quote.get({...});
      return createOrder(newQuote.quoteId);
    }
    
    throw error;
  }
}

cURL

curl -X POST https://api.cyberpay.org/v1/order/create \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "checkoutId": "checkout_1759231185333_abc123",
    "quoteId": "quote_1759231185333_def456",
    "userAddress": "0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8e8",
    "metadata": {
      "customerNote": "Express delivery requested"
    }
  }'

Python

import requests
 
def create_order(checkout_id, quote_id, user_address):
    url = "https://api.cyberpay.org/v1/order/create"
    headers = {
        "Authorization": "Bearer YOUR_API_KEY",
        "Content-Type": "application/json"
    }
    data = {
        "checkoutId": checkout_id,
        "quoteId": quote_id,
        "userAddress": user_address,
        "metadata": {
            "customerNote": "Express delivery requested"
        }
    }
    
    response = requests.post(url, headers=headers, json=data)
    
    if response.status_code == 200:
        return response.json()
    else:
        error = response.json()
        if error.get('error', {}).get('code') == 'QUOTE_EXPIRED':
            # Handle expired quote
            print("Quote expired, need to get new quote")
        raise Exception(f"API Error: {error}")

Integration Patterns

Basic Order Creation

// 1. Create checkout
const checkout = await sdk.checkout.create({...});
 
// 2. Get quote
const quote = await sdk.quote.get({
  checkoutId: checkout.checkoutId,
  paymentToken: selectedToken,
  amount: checkout.amount
});
 
// 3. Create order
const order = await sdk.order.create({
  checkoutId: checkout.checkoutId,
  quoteId: quote.quoteId,
  userAddress: userWalletAddress
});
 
// 4. Proceed to payment
console.log('Order ready for payment:', order.orderId);

Error Handling with Retry Logic

async function createOrderWithRetry(checkoutId, quoteId, userAddress, maxRetries = 3) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await sdk.order.create({
        checkoutId,
        quoteId,
        userAddress
      });
    } catch (error) {
      if (error.code === 'QUOTE_EXPIRED' && attempt < maxRetries) {
        console.log(`Quote expired, getting new quote (attempt ${attempt})`);
        
        // Get fresh quote
        const newQuote = await sdk.quote.get({
          checkoutId,
          paymentToken: originalPaymentToken,
          amount: originalAmount
        });
        
        quoteId = newQuote.quoteId;
        continue;
      }
      
      throw error;
    }
  }
}

Order Status Monitoring

async function monitorOrder(orderId) {
  const maxAttempts = 60; // 5 minutes with 5-second intervals
  let attempts = 0;
  
  while (attempts < maxAttempts) {
    const status = await sdk.order.getStatus(orderId);
    
    console.log(`Order ${orderId} status: ${status.status}`);
    
    if (['completed', 'failed', 'expired', 'cancelled'].includes(status.status)) {
      return status;
    }
    
    // Wait 5 seconds before next check
    await new Promise(resolve => setTimeout(resolve, 5000));
    attempts++;
  }
  
  throw new Error('Order monitoring timeout');
}

Webhook Integration

Set up webhooks to receive order status updates:

// Webhook handler
app.post('/webhooks/cyberpay/orders', (req, res) => {
  const signature = req.headers['x-cyberpay-signature'];
  const payload = req.body;
  
  // Verify webhook signature
  if (!sdk.webhooks.verify(payload, signature)) {
    return res.status(401).send('Invalid signature');
  }
  
  const { event, data } = payload;
  
  switch (event) {
    case 'order.created':
      console.log('Order created:', data.orderId);
      break;
      
    case 'order.payment_received':
      console.log('Payment received for order:', data.orderId);
      // Update order status in your database
      break;
      
    case 'order.completed':
      console.log('Order completed:', data.orderId);
      // Fulfill the order, send confirmation email
      break;
      
    case 'order.failed':
      console.log('Order failed:', data.orderId, data.failureReason);
      // Handle failed order, possibly retry or refund
      break;
  }
  
  res.status(200).send('OK');
});

Best Practices

Quote Management

  • Always check quote expiration before creating orders
  • Implement automatic quote refresh for better UX
  • Cache quotes temporarily to reduce API calls
  • Handle quote expiration gracefully with retry logic

Order Validation

  • Validate user balance before creating orders
  • Check token allowances for ERC-20 payments
  • Verify user address format and network compatibility
  • Implement proper error handling for all failure scenarios

Security

  • Validate all webhook signatures
  • Store sensitive metadata securely
  • Use HTTPS for all API communications
  • Implement proper API key management

Performance

  • Use appropriate timeout values for order creation
  • Implement exponential backoff for retries
  • Cache frequently accessed data
  • Monitor API response times

Rate Limits

  • Standard: 100 requests per minute
  • Premium: 1000 requests per minute
  • Enterprise: Custom limits available

Next Steps

After creating an order:

  1. Execute Payment - Process the cross-chain transaction
  2. Query Status - Monitor payment progress
  3. Webhook Setup - Configure real-time notifications

Support