Skip to main content
POST
/
v1
/
settle
curl -X POST https://facilitator.0xmeta.ai/v1/settle \
  -H "Content-Type: application/json" \
  -d '{
    "verification_id": "vrf_b183c9692fac4481",
    "destination_address": "0xa821f428ef8cc9f54a9915336a82220853059090"
  }'
{
  "settlement_id": "stl_a47920cbc2dc45c5",
  "verification_id": "vrf_b183c9692fac4481",
  "status": "pending",
  "settlement_tx_hash": null,
  "settled_amount": "10000",
  "settled_at": null,
  "destination_address": "0xa821f428ef8cc9f54a9915336a82220853059090",
  "upstream_settlement_id": "574e56cd-a679-41c9-8aa3-90a4dcf42a03",
  "fee_collection_status": "pending",
  "created_at": "2025-11-24T07:43:04Z"
}

Endpoint

Initiate settlement of a verified payment. This executes the transferWithAuthorization on-chain.
verification_id
string
required
The verification ID from a successful payment verification Example: vrf_b183c9692fac4481
destination_address
string
required
Merchant’s address to receive the funds (42 characters, must start with 0x) Example: 0xa821f428ef8cc9f54a9915336a82220853059090
curl -X POST https://facilitator.0xmeta.ai/v1/settle \
  -H "Content-Type: application/json" \
  -d '{
    "verification_id": "vrf_b183c9692fac4481",
    "destination_address": "0xa821f428ef8cc9f54a9915336a82220853059090"
  }'
{
  "settlement_id": "stl_a47920cbc2dc45c5",
  "verification_id": "vrf_b183c9692fac4481",
  "status": "pending",
  "settlement_tx_hash": null,
  "settled_amount": "10000",
  "settled_at": null,
  "destination_address": "0xa821f428ef8cc9f54a9915336a82220853059090",
  "upstream_settlement_id": "574e56cd-a679-41c9-8aa3-90a4dcf42a03",
  "fee_collection_status": "pending",
  "created_at": "2025-11-24T07:43:04Z"
}

Response Fields

settlement_id
string
required
Unique identifier for this settlement
verification_id
string
required
The associated verification ID
status
string
required
Settlement status: pending, settled, or failed
settlement_tx_hash
string
On-chain transaction hash (available when settled)
settled_amount
string
Amount settled in token’s smallest unit
settled_at
string
ISO 8601 timestamp when settlement completed
destination_address
string
Merchant’s receiving address
upstream_settlement_id
string
Provider transaction execution ID
fee_collection_status
string
Fee collection status: pending, success, failed_insufficient_allowance, failed_insufficient_balance, or failed
fee_tx_hash
string
Transaction hash of fee collection (if separate from settlement)

Settlement Process

Settlement States

Fee Collection

Before settlement can proceed, 0xmeta collects a $0.001 flat fee via USDC transferFrom:
1

One-Time Approval Required

Merchant must approve 0xmeta treasury to spend USDC:
const USDC = "0x036CbD53842c5426634e7929541eC2318f3dCF7e"; // Base Sepolia
const TREASURY = "0xa92560dcaf2fb556dfee4d2599f021a511b94aae";

await usdcContract.approve(
  TREASURY,
  ethers.parseUnits("10", 6) // $10 = 10,000 settlements
);
2

Fee Collection

When settlement is initiated: solidity USDC.transferFrom(merchant, treasury, 1000); // $0.001 (6 decimals)
3

Settlement Execution

After fee collection, the EIP-3009 authorization is executed via Provider
Without USDC approval, settlements will fail! You must approve the treasury address before your first settlement.

Handling Settlement Status

Polling for Status

async function waitForSettlement(settlementId) {
  const maxAttempts = 60; // 5 minutes

  for (let attempt = 0; attempt < maxAttempts; attempt++) {
    const response = await fetch(
      `https://facilitator.0xmeta.ai/v1/settlements/${settlementId}`
    );

    const settlement = await response.json();

    if (settlement.status === "settled") {
      console.log("✅ Settlement complete:", settlement.settlement_tx_hash);
      return settlement;
    }

    if (settlement.status === "failed") {
      console.error("❌ Settlement failed:", settlement.fee_collection_status);
      throw new Error("Settlement failed");
    }

    // Wait 5 seconds before next check
    await new Promise((resolve) => setTimeout(resolve, 5000));
  }

  throw new Error("Settlement timeout");
}

Fee Collection Status Values

StatusDescription
pendingFee collection not yet attempted
successFee successfully collected
failed_insufficient_allowanceMerchant hasn’t approved USDC spending
failed_insufficient_balanceMerchant has no USDC balance
failedOther error during fee collection

Common Issues

Error: fee_collection_status: failed_insufficient_allowanceSolution: Approve USDC spending:
# Run merchant approval setup
python -m app.merchant_approval --network base-sepolia --amount 1000
Error: FiatTokenV2: authorization is expired Solution: User needs to create a new authorization with longer validBefore: javascript validBefore: String(Math.floor(Date.now() / 1000) + 86400) // 24 hours
Error: FiatTokenV2: authorization is used or canceled Solution: Generate a new unique nonce for each payment: javascript const nonceBytes = new Uint8Array(32); window.crypto.getRandomValues(nonceBytes); const nonce = "0x" + Array.from(nonceBytes) .map(b => b.toString(16).padStart(2, "0")) .join("");
Settlements typically complete in 30-60 seconds. Delays can occur due to:
  • Network congestion
  • Provider API processing time
  • RPC endpoint issues
Solution: Implement proper polling with timeouts (max 5 minutes)

Settlement Timing

StageTypical Duration
Fee Collection< 5 seconds
Provider Submission5-15 seconds
On-chain Confirmation15-45 seconds
Total30-60 seconds
Settlement typically completes in 30-60 seconds on Base network. Use polling or webhooks to track status.
Save the settlement_id immediately and track it in your database. You’ll need it to check status and handle any issues.
Fee: $0.001 flat fee per successful settlement (collected before execution).