Skip to main content

Overview

Validates payment proof from client and executes the blockchain transaction. Endpoint: POST https://facilitator.corbits.dev/settle

Purpose

This endpoint is called by resource server middleware after receiving a payment attempt from a client. The facilitator validates the payment proof, executes the on-chain settlement, and returns the transaction hash. The validation and settlement logic differs based on the blockchain:
  • Solana: Validates and co-signs partially-signed transactions, then submits them to the network
  • EVM: Validates EIP-3009 authorization signatures and calls transferWithAuthorization on the token contract

Request Body

x402Version
number
required
The x402 protocol version. Currently 1.
paymentHeader
string
required
Base64-encoded JSON string containing the payment payload from the client’s X-PAYMENT header.
paymentRequirements
object
required
The original payment requirements object (same structure as in /accepts endpoint).

Response

success
boolean
required
Whether the payment settlement succeeded. true if transaction was confirmed, false otherwise.
error
string | null
Error message if success is false. null on success.
txHash
string | null
required
Blockchain transaction hash on success. null on failure.
networkId
string | null
required
Network identifier where the transaction was settled. null on failure.Format:
  • Solana: x402 network identifier (e.g., "solana-devnet")
  • EVM: Numeric chain ID as string (e.g., "84532" for Base Sepolia)

Example Request (Solana)

{
  "x402Version": 1,
  "paymentHeader": "eyJzY2hlbWUiOiJleGFjdCIsIm5ldHdvcmsiOiJzb2xhbmEtZGV2bmV0IiwiYXNzZXQiOiI0ek1NQzlzcnQ1UmkXMTRHQWdYaGFIaWkzR25QQUVFUllQSmdaSkRuY0RVIiwicGF5bG9hZCI6eyJ0eCI6IkFRQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBIn19",
  "paymentRequirements": {
    "scheme": "exact",
    "network": "solana-devnet",
    "maxAmountRequired": "1000000",
    "resource": "https://api.example.com/data",
    "description": "API access fee",
    "mimeType": "application/json",
    "payTo": "9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM",
    "maxTimeoutSeconds": 300,
    "asset": "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU",
    "extra": {
      "feePayer": "FacilitatorPubKey...",
      "decimals": 6,
      "recentBlockhash": "4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ..."
    }
  }
}

Example Response (Success)

{
  "success": true,
  "error": null,
  "txHash": "5KxzZ9Nh7PjVkAqYqoxMjF8FcQjS9JfqNqXrKwYNJzQqBx1qKjYvNqXrKwYNJzQqBx1qKj",
  "networkId": "solana-devnet"
}

Example Response (Error)

{
  "success": false,
  "error": "Invalid transfer amount: expected 1000000, got 900000",
  "txHash": null,
  "networkId": null
}

Usage in Middleware

Resource servers typically call this endpoint through middleware:
import { handleMiddlewareRequest } from '@faremeter/middleware';

app.use('/protected', async (req, res) => {
  const result = await handleMiddlewareRequest({
    req,
    res,
    facilitatorUrl: 'https://facilitator.corbits.dev',
    paymentRequirements: {...}
  });

  if (result.paid) {
    // result.txHash contains the blockchain transaction hash
    // result.networkId contains the network identifier
    console.log(`Payment confirmed: ${result.txHash}`);

    res.json({ data: protectedData });
  }
});

Handler Behavior

When the facilitator receives a /settle request:
  1. Decodes payment header: Extracts payment payload from base64-encoded header
  2. Tries each handler: Calls handleSettle() on registered handlers
  3. First match wins: Uses the first handler that returns a non-null result
  4. Validates payment: Handler performs blockchain-specific validation
  5. Executes settlement: Handler submits transaction to blockchain
  6. Waits for confirmation: Handler waits for on-chain confirmation
  7. Returns result: Transaction hash and success status returned

Solana Validation

The facilitator performs the following checks on Solana transactions:
  1. Transaction Structure: Validates transaction has correct number of instructions (3 or 4)
  2. Fee Payer Verification: Ensures the facilitator’s public key is the fee payer
  3. Compute Budget: Validates compute unit limits and priority fees
  4. Transfer Instruction: Verifies correct token program, amount, recipient, and source account
  5. Security Checks: Prevents facilitator fund theft attempts
See Solana Payments for detailed validation logic.

EVM Validation

The facilitator performs the following checks on EVM authorizations:
  1. Payload Structure: Validates required fields are present
  2. Address Validation: Ensures from and to addresses are valid
  3. Signature Verification: Validates EIP-712 typed data signature
  4. Amount Check: Ensures value matches maxAmountRequired
  5. Recipient Check: Ensures to matches payTo address
  6. Time Validity: Checks current time is between validAfter and validBefore
  7. Nonce Check: Verifies nonce hasn’t been used on-chain
  8. Token Contract Call: Executes transferWithAuthorization with facilitator paying gas
See EVM Payments for detailed validation logic.

Transaction Confirmation

The facilitator waits for different confirmation levels based on the blockchain: Solana:
  • Simulates transaction before sending to detect potential failures
  • Sends transaction and polls getSignatureStatuses for confirmation status
  • Accepts either confirmed OR finalized commitment level
  • Polls up to 30 times with 1-second intervals between checks
  • Checks for both successful confirmation and transaction errors during polling
  • Typical confirmation time: 1-5 seconds on normal network conditions
  • Maximum wait time: 30 seconds before timing out
EVM:
  • Sends transaction and calls waitForTransactionReceipt to wait for block inclusion
  • Verifies transaction receipt status is “success” (not just included in block)
  • Typical confirmation time: 1-2 blocks (~12-30 seconds depending on chain)
  • No explicit timeout configured (uses RPC provider defaults)
This ensures transactions are successfully confirmed on-chain before returning success to the resource server.

HTTP Status Codes

The /settle endpoint uses the following HTTP status codes: 200 OK:
  • Request was processed successfully
  • Check the success field in the response body to determine if settlement succeeded
  • Both successful settlements (success: true) and validation failures (success: false) return 200 status
400 Bad Request:
  • Invalid request format
  • Missing required fields (paymentHeader or paymentRequirements)
  • Malformed JSON in request body
  • Failed to decode payment header
500 Internal Server Error:
  • Handler threw an exception during settlement processing
  • Blockchain RPC failure
  • Unexpected errors during validation or execution
Important: Most validation and settlement errors return HTTP 200 with success: false in the response body. Only malformed requests return 400, and only unexpected server errors return 500.

See Also