Skip to main content
Validates an EIP-712 TransferWithAuthorization signature against on-chain state. Call this before /settle to confirm the payment is executable.
POST /verify

Request Body

FieldTypeDescription
paymentPayloadobjectSigned payment data
paymentPayload.tokenstringToken contract address
paymentPayload.payloadobjectAuthorization and signature
paymentPayload.payload.authorizationobjectEIP-712 authorization fields
paymentPayload.payload.authorization.fromstringPayer wallet address
paymentPayload.payload.authorization.tostringRecipient wallet address
paymentPayload.payload.authorization.valuestringAmount in wei (uint256)
paymentPayload.payload.authorization.validAfternumberUnix timestamp, signature valid after
paymentPayload.payload.authorization.validBeforenumberUnix timestamp, signature valid before
paymentPayload.payload.authorization.noncestringRandom bytes32 nonce
paymentPayload.payload.signaturestringEIP-712 signature
paymentRequirementsobjectNetwork and contract details
paymentRequirements.networkstringTarget network ("bsc" or "base")
paymentRequirements.relayerContractstringb402 Relayer contract address

Response

Valid Payment (200)

FieldTypeDescription
isValidbooleantrue if the payment can be settled
payerstringRecovered signer address

Invalid Payment (200)

FieldTypeDescription
isValidbooleanfalse
invalidReasonstringWhy the payment failed verification

Verification Checks

The facilitator runs these checks in order:
  1. Signature recovery - Recovers the signer from the EIP-712 signature and confirms it matches authorization.from
  2. Nonce uniqueness - Checks the nonce has not been used or canceled on-chain
  3. Time window - Confirms validAfter <= now <= validBefore
  4. Token whitelisting - Verifies the token is whitelisted on the Relayer contract
  5. Balance and allowance - Checks the payer has sufficient token balance and has approved the Relayer contract
A valid verification does not guarantee settlement will succeed. On-chain state can change between verify and settle calls. Always settle promptly after verification.

Examples

cURL

curl -X POST https://facilitatorv3.b402.ai/verify \
  -H "Content-Type: application/json" \
  -d '{
    "paymentPayload": {
      "token": "0x55d398326f99059fF775485246999027B3197955",
      "payload": {
        "authorization": {
          "from": "0xAbC1234567890aBcDeF1234567890AbCdEf123456",
          "to": "0x9876543210FeDcBa9876543210FeDcBa98765432",
          "value": "10000000000000000",
          "validAfter": 1709251200,
          "validBefore": 1709254800,
          "nonce": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
        },
        "signature": "0xabc123...eip712_signature"
      }
    },
    "paymentRequirements": {
      "network": "bsc",
      "relayerContract": "0xE91b564EB8DFF305Ff8efA332f84c487b9da5171"
    }
  }'

TypeScript

const response = await fetch("https://facilitatorv3.b402.ai/verify", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    paymentPayload: {
      token: "0x55d398326f99059fF775485246999027B3197955",
      payload: {
        authorization: {
          from: wallet.address,
          to: recipientAddress,
          value: "10000000000000000",
          validAfter: Math.floor(Date.now() / 1000),
          validBefore: Math.floor(Date.now() / 1000) + 3600,
          nonce: crypto.randomBytes(32).toString("hex"),
        },
        signature: eip712Signature,
      },
    },
    paymentRequirements: {
      network: "bsc", // or "base"
      relayerContract: "0xE91b564EB8DFF305Ff8efA332f84c487b9da5171",
    },
  }),
});

const result = await response.json();

if (result.isValid) {
  console.log("Payment verified. Payer:", result.payer);
  // Proceed to /settle
} else {
  console.error("Verification failed:", result.invalidReason);
}

Error Codes

CodeHTTP StatusDescription
signature_error400EIP-712 signature is malformed or recovery failed
nonce_error400Nonce has already been used or was canceled
payment_verification_error400Balance insufficient, allowance too low, or token not whitelisted
validation_error400Request body is missing required fields or has invalid types