Skip to main content
POST
/
v1
/
verify
Verify x402 payment (deprecated)
curl --request POST \
  --url https://api.mrdn.finance/v1/verify \
  --header 'Authorization: <api-key>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "paymentPayload": {
    "x402Version": 1,
    "scheme": "exact",
    "network": "base-sepolia",
    "payload": {
      "signature": "<string>",
      "authorization": {
        "from": "<string>",
        "to": "<string>",
        "value": "<string>",
        "validAfter": "<string>",
        "validBefore": "<string>",
        "nonce": "<string>"
      }
    }
  },
  "paymentRequirements": {
    "amount": "<string>",
    "recipient": "<string>",
    "network": "<string>",
    "asset": "<string>",
    "resource": "<string>",
    "description": "<string>",
    "mimeType": "<string>"
  }
}
'
{
  "isValid": true,
  "invalidReason": "<string>",
  "payer": "<string>",
  "authContext": {
    "organizationId": "<string>",
    "authMethod": "<string>",
    "timestamp": "<string>"
  }
}

Documentation Index

Fetch the complete documentation index at: https://docs.mrdn.finance/llms.txt

Use this file to discover all available pages before exploring further.

Verify a Nanopayments Gateway (Circle Gateway batched) payment without settling it. Routing happens on the same POST /v1/verify endpoint as the default x402 path; when paymentRequirements.extra.name === "GatewayWalletBatched", the facilitator forwards the request to Circle’s Gateway API.
Circle recommends calling Settle Batched Payment directly for production batched flows rather than the legacy verify() + settle() two-step. Use this endpoint mainly for diagnostics.

Routing

Identical to Settle Batched Payment:
  • paymentRequirements.extra.name === "GatewayWalletBatched" and extra.version === "1"
  • The network must be Gateway-enabled (testnets always; mainnets gated by GATEWAY_MAINNET_ENABLED)
If the network is not Gateway-enabled, the facilitator returns HTTP 403 with errorReason: "gateway_not_enabled".

Request Body

Same shape as the default verify endpoint, with the batched extra block:
{
  "paymentPayload": {
    "x402Version": 1,
    "scheme": "exact",
    "network": "base",
    "payload": {
      "signature": "0x...",
      "authorization": {
        "from": "0x742d35Cc6634C0532925a3b8D0c4E5e6C2aE7A3e",
        "to": "0x77777777Dcc4d5A8B6E418Fd04D8997ef11000eE",
        "value": "10000",
        "validAfter": "1735689600",
        "validBefore": "1736035200",
        "nonce": "0x..."
      }
    }
  },
  "paymentRequirements": {
    "scheme": "exact",
    "network": "base",
    "maxAmountRequired": "10000",
    "amount": "10000",
    "resource": "https://example.com/api/sample",
    "description": "Batched payment for 0.01 USDC",
    "mimeType": "application/json",
    "payTo": "0xRecipient...",
    "maxTimeoutSeconds": 345600,
    "asset": "0x77777777Dcc4d5A8B6E418Fd04D8997ef11000eE",
    "extra": {
      "name": "GatewayWalletBatched",
      "version": "1",
      "verifyingContract": "0x77777777Dcc4d5A8B6E418Fd04D8997ef11000eE",
      "creditedRecipient": "0xRecipient...",
      "platform": "0x0000000000000000000000000000000000000000",
      "platformFeeBps": 0,
      "destinationChainId": 8453
    }
  }
}
See the Nanopayments Gateway Overview for a full description of the extra fields.

Response

200: Success

The facilitator spreads Circle’s response and adds Meridian-specific fields. The exact shape is { ...gatewayResponse, verificationMethod, testnet, authContext }:
{
  "isValid": true,
  "verificationMethod": "batched",
  "testnet": false,
  "authContext": {
    "organizationId": "org_123",
    "authMethod": "middleware_handled",
    "timestamp": "2026-04-30T18:24:11.502Z"
  }
}
  • isValid (and any other fields) come from Circle.
  • verificationMethod: "batched" confirms the Circle Gateway path was taken.
  • testnet is true when paymentRequirements.network is base-sepolia or optimism-sepolia. Note: the verify path does not mark fluent-testnet as testnet, which differs from the settle path.
  • authContext.authMethod is the literal string "middleware_handled". The verify path’s authContext includes organizationId (resolved by the apiSession middleware).

403: Network not enabled

{
  "isValid": false,
  "invalidReason": "gateway_not_enabled",
  "error": "Circle Gateway is not enabled for network \"<network>\".",
  "payer": ""
}

500: Facilitator-side failure forwarding to Circle

{
  "isValid": false,
  "invalidReason": "batched_verify_error",
  "error": "<error.message or 'Unknown batched verification error'>",
  "payer": ""
}

400: Schema validation failures (apply to all /v1/verify requests)

Verify validates paymentPayload and paymentRequirements against PaymentPayloadSchema and PaymentRequirementsSchema before the batched routing check. If either fails, the request never reaches the Circle path:
{
  "isValid": false,
  "invalidReason": "invalid_payload",
  "payer": "<authorization.from if EVM, else \"\">"
}
{
  "isValid": false,
  "invalidReason": "invalid_payment_requirements",
  "payer": "<authorization.from if EVM, else \"\">"
}

Error Codes

  • gateway_not_enabled: paymentRequirements.extra matched batched but isGatewayEnabledForNetwork(network) returned false.
  • batched_verify_error: forwarding to Circle threw before a response could be parsed.
  • invalid_payload: paymentPayload failed PaymentPayloadSchema.parse().
  • invalid_payment_requirements: paymentRequirements failed PaymentRequirementsSchema.parse().
  • unexpected_verify_error: unhandled exception inside the verify handler (HTTP 500).

Authorizations

Authorization
string
header
required

Body

application/json
paymentPayload
object
required
paymentRequirements
object
required

Response

Legacy payment verification result

isValid
boolean

Whether payment is valid

invalidReason
string

Reason if payment is invalid

payer
string

Payment sender address

authContext
object