Skip to main content
Version: 2019-05-29 (Current)

Chains API (Marketplace)

The Chains API enables marketplace and platform businesses to split payments between platform and merchants. Build multi-party payment flows with automated commission handling.

Available Endpoints

Overview

Chains (also called Omise Link) enable:

  • Split payments - Automatically split between platform and merchants
  • Commission handling - Deduct platform fees before merchant payout
  • Multi-merchant charges - Charge customer and distribute to multiple recipients
  • Marketplace flows - Build Uber, Airbnb, Shopify-style payment flows
  • Transparent tracking - Track entire payment chain from charge to transfer

How Chains Work

  1. Customer pays - Charge created with destination (recipient)
  2. Platform receives - Full amount goes to platform account
  3. Commission deducted - Platform fee is automatically calculated
  4. Merchant receives - Remaining amount transferred to recipient
  5. Chain tracked - Entire flow linked via chain ID

Prerequisites

  • Chain-enabled account - Contact Omise to enable marketplace features
  • Verified recipients - Recipients must be verified before receiving transfers
  • KYC compliance - Recipients complete identity verification

Authentication

All Chains API endpoints require authentication using your secret key.

Commission Calculation

Platform fees can be specified as fixed amounts and/or percentages:

Fixed Commission

{
"platform_fee": {
"fixed": 50000
}
}

Deducts ฿500.00 (50,000 satang) from merchant payout.

Percentage Commission

{
"platform_fee": {
"percentage": 10.5
}
}

Deducts 10.5% from merchant payout.

Combined Commission

{
"platform_fee": {
"fixed": 10000,
"percentage": 5
}
}

Deducts ฿100 + 5% from merchant payout.

Calculation Example

Charge Amount: ฿10,000 (1,000,000 satang) Platform Fee: ฿100 fixed + 5% = ฿100 + ฿500 = ฿600 Merchant Receives: ฿10,000 - ฿600 = ฿9,400

Implementation Example

Creating a Chain Charge

// Node.js example
const charge = await omise.charges.create({
amount: 1000000, // ฿10,000
currency: 'thb',
card: 'tokn_test_123',
description: 'Order #1234 - Platform Marketplace',

// Destination merchant
destination: {
amount: 950000, // ฿9,500 (after ฿500 platform fee)
recipient: 'recp_test_merchant_456'
},

// Platform fee
platform_fee: {
fixed: 50000 // ฿500
},

metadata: {
order_id: '1234',
merchant_id: 'merchant_456',
customer_email: 'customer@example.com'
}
});

console.log('Chain ID:', charge.id);
console.log('Status:', charge.status);

Important Notes

  • destination.amount must be less than or equal to charge amount minus platform fee
  • Total of destination amounts cannot exceed charge amount
  • Platform fee is deducted from the destination amount
  • Funds are held in platform account until transfer is initiated

Chain Status Lifecycle

Chains progress through these stages:

  1. Charge Created - Customer payment processed
  2. Charge Successful - Payment confirmed
  3. Transfer Pending - Waiting for transfer schedule
  4. Transfer Created - Transfer to merchant initiated
  5. Transfer Sent - Funds sent to recipient's bank
  6. Transfer Paid - Merchant received funds

Multiple Recipients

You can split payments to multiple merchants:

{
amount: 1000000, // ฿10,000
destinations: [
{
amount: 400000, // ฿4,000 to merchant A
recipient: 'recp_test_merchant_a'
},
{
amount: 350000, // ฿3,500 to merchant B
recipient: 'recp_test_merchant_b'
}
],
platform_fee: {
fixed: 250000 // ฿2,500 platform keeps
}
}

Webhook Events

Monitor chain progress with webhooks:

  • charge.complete - Customer payment successful
  • transfer.create - Merchant transfer initiated
  • transfer.sent - Funds sent to merchant
  • transfer.paid - Merchant received funds

Error Handling

ErrorDescriptionSolution
chain_not_enabledAccount not enabled for chainsContact support to enable
invalid_destinationRecipient not found or inactiveVerify recipient exists and is active
destination_amount_exceeds_chargeDestination sum > charge amountReduce destination amounts
insufficient_balanceNot enough balance for transferCharge must complete before transfer

Best Practices

1. Verify Recipients First

Ensure all recipients are verified before creating chain charges:

const recipient = await omise.recipients.retrieve('recp_test_123');
if (recipient.verified === false) {
throw new Error('Recipient not verified');
}

2. Use Metadata for Tracking

Store order and merchant details:

{
"metadata": {
"order_id": "ord_123",
"merchant_id": "merch_456",
"commission_rate": "5%"
}
}

3. Handle Failed Transfers

Not all transfers will succeed. Monitor webhooks and retry if needed:

if (transfer.status === 'failed') {
// Log failure reason
console.error('Transfer failed:', transfer.failure_code);

// Notify merchant
await notifyMerchant(transfer.recipient, transfer.failure_message);
}

4. Reconcile Daily

Match charges to transfers daily for accurate accounting:

  • List all chains for a date range
  • Verify each charge has corresponding transfer
  • Track commission totals

Limitations

  • Minimum transfer amount: ฿20 (2,000 satang)
  • Maximum recipients per charge: 10
  • Platform fee cannot exceed charge amount
  • Recipients must have verified bank accounts
  • Transfers follow standard settlement schedule (7 days Thailand, 21 days Japan)