> ## 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 Batched Payment

> Deprecated legacy endpoint for verifying an x402 payment with organization-specific authentication

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.

<Note>
  Circle recommends calling [Settle Batched
  Payment](/api-reference/endpoint/batched-settle) directly for production
  batched flows rather than the legacy `verify()` + `settle()` two-step. Use
  this endpoint mainly for diagnostics.
</Note>

## Routing

Identical to [Settle Batched Payment](/api-reference/endpoint/batched-settle):

* `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:

```json theme={"system"}
{
  "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](/api-reference/payment-types/circle-gateway#extra-field-reference) 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 }`:

```json theme={"system"}
{
  "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 `arc-testnet`, `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

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

### 500: Facilitator-side failure forwarding to Circle

```json theme={"system"}
{
  "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:

```json theme={"system"}
{
  "isValid": false,
  "invalidReason": "invalid_payload",
  "payer": "<authorization.from if EVM, else \"\">"
}
```

```json theme={"system"}
{
  "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).


## OpenAPI

````yaml POST /v1/verify
openapi: 3.1.0
info:
  title: Meridian Protocol API
  description: API for x402 payments
  license:
    name: MIT
  version: 1.0.0
servers:
  - url: https://api.mrdn.finance
    description: Production server
security:
  - cookieAuth: []
  - apiKeyAuth: []
paths:
  /v1/verify:
    post:
      summary: Verify x402 payment (deprecated)
      description: >-
        Deprecated legacy endpoint for verifying an x402 payment with
        organization-specific authentication
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                paymentPayload:
                  $ref: '#/components/schemas/PaymentPayload'
                paymentRequirements:
                  $ref: '#/components/schemas/PaymentRequirements'
              required:
                - paymentPayload
                - paymentRequirements
      responses:
        '200':
          description: Legacy payment verification result
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VerifyResponse'
        '400':
          description: Invalid payment data
        '401':
          description: Invalid API key
      deprecated: true
      security:
        - apiKeyAuth: []
components:
  schemas:
    PaymentPayload:
      description: >-
        Legacy x402 payment payload used by `POST /v1/verify` and by standard
        EIP-3009 EVM settlement.
      oneOf:
        - $ref: '#/components/schemas/ExactEvmPaymentPayload'
    PaymentRequirements:
      type: object
      required:
        - scheme
        - network
        - maxAmountRequired
        - resource
        - description
        - mimeType
        - payTo
        - maxTimeoutSeconds
        - asset
      properties:
        scheme:
          type: string
          enum:
            - exact
        network:
          type: string
          description: Network identifier
        maxAmountRequired:
          type: string
          pattern: ^\d+$
          description: Maximum amount required in the token's smallest unit.
        resource:
          type: string
          format: uri
        description:
          type: string
          description: Payment description
        mimeType:
          type: string
          description: Content MIME type
        payTo:
          type: string
          description: >-
            Facilitator or recipient address required by the selected payment
            type.
        maxTimeoutSeconds:
          type: integer
          description: Maximum validity window in seconds.
        asset:
          type: string
          description: Payment asset contract address or chain-specific asset identifier.
        extra:
          type: object
          additionalProperties: true
    VerifyResponse:
      type: object
      properties:
        isValid:
          type: boolean
          description: Whether payment is valid
        invalidReason:
          type: string
          description: Reason if payment is invalid
        payer:
          type: string
          description: Payment sender address
        authContext:
          type: object
          properties:
            organizationId:
              type: string
            authMethod:
              type: string
            timestamp:
              type: string
    ExactEvmPaymentPayload:
      type: object
      required:
        - x402Version
        - scheme
        - network
        - payload
      properties:
        x402Version:
          type: integer
          enum:
            - 1
          example: 1
        scheme:
          type: string
          enum:
            - exact
          example: exact
        network:
          type: string
          example: base-sepolia
        payload:
          $ref: '#/components/schemas/ExactEvmPayload'
    ExactEvmPayload:
      type: object
      required:
        - signature
        - authorization
      properties:
        signature:
          type: string
          pattern: ^0x[a-fA-F0-9]+$
        authorization:
          $ref: '#/components/schemas/ExactEvmAuthorization'
    ExactEvmAuthorization:
      type: object
      required:
        - from
        - to
        - value
        - validAfter
        - validBefore
        - nonce
      properties:
        from:
          type: string
          pattern: ^0x[a-fA-F0-9]{40}$
        to:
          type: string
          pattern: ^0x[a-fA-F0-9]{40}$
        value:
          type: string
          pattern: ^\d+$
        validAfter:
          type: string
          pattern: ^\d+$
        validBefore:
          type: string
          pattern: ^\d+$
        nonce:
          type: string
          pattern: ^0x[a-fA-F0-9]{64}$
  securitySchemes:
    cookieAuth:
      type: apiKey
      in: cookie
      name: siwe-session
    apiKeyAuth:
      type: apiKey
      in: header
      name: Authorization

````