> ## 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.

# Execute ERC-20 Permit

> Submit a signed EIP-2612 permit and have the facilitator's signer execute `transferWithPermit` on the Meridian Proxy Facilitator contract. The user signs the permit off-chain; the facilitator pays the gas to apply the permit and transfer `value` tokens from `owner` to `recipient`.

Execute a gasless ERC-20 token transfer using a signed [EIP-2612](https://eips.ethereum.org/EIPS/eip-2612) permit. The user signs off-chain; the facilitator pays the gas and settles on-chain.

<Note>
  This endpoint is for ERC-2612 `permit()` transfers. Permit2 payments use
  [`POST /v1/settle`](/api-reference/endpoint/settle-payment) with the Permit2
  payment payload.
</Note>

## Authentication

Requires an API key passed as `Authorization: Bearer <api-key>`.

## Request Body

```json theme={"system"}
{
  "network": "base-sepolia",
  "tokenAddress": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
  "owner": "0x742d35Cc6634C0532925a3b8D0c4E5e6C2aE7A3e",
  "spender": "0x8e633dBf31adCc7D41BE3e95B7c8DD3526B5235A",
  "value": "1000000",
  "deadline": "1893456000",
  "v": 27,
  "r": "0x...",
  "s": "0x...",
  "recipient": "0x742d35Cc6634C0532925a3b8D0c4E5e6C2aE7A3e"
}
```

| Field          | Required | Notes                                                                                                                                                                                                                 |
| -------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `network`      | yes      | EVM network identifier (e.g. `base`, `avalanche`, `arbitrum`, `bsc`, `bot-chain`, `base-sepolia`, `arc-testnet`, `bot-chain-testnet`, `optimism`, `polygon`, `unichain`, `ink`, `sei`, `tempo`, `monad`, `robinhood`) |
| `tokenAddress` | yes      | ERC-20 token contract address                                                                                                                                                                                         |
| `owner`        | yes      | Token owner address; must have signed the EIP-2612 permit                                                                                                                                                             |
| `spender`      | yes      | Spender address authorized in the permit signature                                                                                                                                                                    |
| `value`        | yes      | Amount in the token's smallest unit as a decimal string (`1000000` = 1 USDC)                                                                                                                                          |
| `deadline`     | yes      | Unix timestamp after which the permit expires, as a decimal string                                                                                                                                                    |
| `v`            | yes\*    | Signature recovery byte (27 or 28). Provide `v/r/s` OR `signature`, not both.                                                                                                                                         |
| `r`            | yes\*    | 32-byte hex signature component                                                                                                                                                                                       |
| `s`            | yes\*    | 32-byte hex signature component                                                                                                                                                                                       |
| `recipient`    | yes      | Address that receives the transferred tokens                                                                                                                                                                          |

## Facilitator contract addresses

| Network             | Contract                                     |
| ------------------- | -------------------------------------------- |
| `arc-testnet`       | `0x8e633dBf31adCc7D41BE3e95B7c8DD3526B5235A` |
| `bot-chain-testnet` | `0x8e633dBf31adCc7D41BE3e95B7c8DD3526B5235A` |
| `bot-chain`         | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `base`              | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `bsc`               | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `base-sepolia`      | `0x8e633dBf31adCc7D41BE3e95B7c8DD3526B5235A` |
| `ethereum`          | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `avalanche`         | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `optimism`          | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `optimism-sepolia`  | `0x8e633dBf31adCc7D41BE3e95B7c8DD3526B5235A` |
| `arbitrum`          | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `polygon`           | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `unichain`          | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `ink`               | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `sonic`             | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `worldchain`        | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `sei`               | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `hyperevm`          | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `megaeth`           | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `tempo`             | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `monad`             | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `robinhood`         | `0x8E7769D440b3460b92159Dd9C6D17302b036e2d6` |
| `fluent-testnet`    | `0xB3Ac1B7871942bCdCD0bD6C65765272bBE70B8Da` |

## Response

### Success

```json theme={"system"}
{
  "success": true,
  "transaction": "0x1234567890abcdef...",
  "network": "base-sepolia"
}
```

### Error

```json theme={"system"}
{
  "success": false,
  "transaction": "",
  "network": "base-sepolia",
  "errorReason": "invalid_request"
}
```

## Error Codes

| `errorReason`             | HTTP | Description                                                       |
| ------------------------- | ---- | ----------------------------------------------------------------- |
| `invalid_request`         | 400  | Missing or malformed fields in the request body                   |
| `unsupported_network`     | 400  | `network` is not a supported EVM network                          |
| `network_not_configured`  | 400  | The facilitator has no private key configured for this network    |
| `invalid_signature`       | 400  | Could not resolve a valid `v`, `r`, `s` from the provided inputs  |
| `permit_execution_failed` | 500  | On-chain transaction failed (RPC error, revert, bad permit, etc.) |


## OpenAPI

````yaml POST /v1/permit
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/permit:
    post:
      summary: Execute ERC-20 Permit
      description: >-
        Submit a signed EIP-2612 permit and have the facilitator's signer
        execute `transferWithPermit` on the Meridian Proxy Facilitator contract.
        The user signs the permit off-chain; the facilitator pays the gas to
        apply the permit and transfer `value` tokens from `owner` to
        `recipient`.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PermitRequest'
      responses:
        '200':
          description: Permit transaction submitted
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PermitResponse'
        '400':
          description: >-
            Invalid request, unsupported network, network not configured, or
            invalid signature
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PermitResponse'
        '500':
          description: Permit execution failed (on-chain submission threw)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PermitResponse'
      security:
        - apiKeyAuth: []
components:
  schemas:
    PermitRequest:
      type: object
      required:
        - network
        - owner
        - spender
        - value
        - deadline
        - recipient
      properties:
        network:
          type: string
          description: >-
            EVM network identifier. Must be one of the facilitator's configured
            EVM networks (e.g. `base`, `arbitrum`, `bsc`, `bot-chain`,
            `base-sepolia`, `bot-chain-testnet`, `optimism`, `optimism-sepolia`,
            `polygon`, `unichain`, `ink`, `tempo`, `monad`, `robinhood`,
            `worldchain`, `hyperevm`, `megaeth`, `fluent-testnet`, etc.).
          example: base-sepolia
        tokenAddress:
          type: string
          pattern: ^0x[a-fA-F0-9]{40}$
          description: >-
            ERC-20 token address. Documented as optional with a fallback to the
            network's USDC, but the actual `transferWithPermit` call uses this
            value directly. Provide it explicitly to avoid
            `permit_execution_failed`.
          example: '0x036CbD53842c5426634e7929541eC2318f3dCF7e'
        owner:
          type: string
          pattern: ^0x[a-fA-F0-9]{40}$
          description: >-
            Token owner address (the signer of the EIP-2612 permit). Tokens are
            pulled from this address.
          example: '0x742d35Cc6634C0532925a3b8D0c4E5e6C2aE7A3e'
        spender:
          type: string
          pattern: ^0x[a-fA-F0-9]{40}$
          description: >-
            Spender address authorized by the permit signature. Required by the
            request schema. The on-chain `transferWithPermit` call uses the
            facilitator contract as the spender; this field is forwarded for
            signing-side compatibility.
          example: '0x8e633dBf31adCc7D41BE3e95B7c8DD3526B5235A'
        value:
          type: string
          pattern: ^\d+$
          description: >-
            uint256 token amount as a decimal string in the token's smallest
            unit (e.g. `1000000` = 1 USDC at 6 decimals). Numbers and bigints
            are accepted and coerced to a decimal string.
          example: '1000000'
        deadline:
          type: string
          pattern: ^\d+$
          description: >-
            uint256 permit deadline as a decimal Unix timestamp string. Numbers
            and bigints are accepted and coerced to a decimal string.
          example: '1893456000'
        signature:
          type: string
          pattern: ^0x[a-fA-F0-9]+$
          description: >-
            Optional 65-byte EIP-2612 permit signature, hex-encoded. Schema
            accepts `^0x[a-fA-F0-9]+$`. WARNING: this field is broken at runtime
            in the current handler (viem returns `r`/`s` as `0x`-prefixed and
            the assembler re-wraps them, producing malformed bytes); use the
            split `(v, r, s)` form instead. Provide this OR (`v`, `r`, `s`), but
            not both.
          example: 0x...
        v:
          type: integer
          minimum: 0
          maximum: 255
          description: >-
            Optional `v` byte of the signature. The exclusivity check uses
            `Boolean(data.v)`, so `v = 0` is treated as missing; use 27 or 28.
        r:
          type: string
          description: >-
            Optional `r` component. The schema accepts any string (no regex). In
            practice, send a 32-byte hex value (with or without leading `0x`);
            only the first occurrence of `0x` is stripped when assembling the
            final signature.
        s:
          type: string
          description: >-
            Optional `s` component. The schema accepts any string (no regex). In
            practice, send a 32-byte hex value (with or without leading `0x`);
            only the first occurrence of `0x` is stripped when assembling the
            final signature.
        recipient:
          type: string
          pattern: ^0x[a-fA-F0-9]{40}$
          description: >-
            Address that receives the transferred tokens after the permit is
            applied.
          example: '0x742d35Cc6634C0532925a3b8D0c4E5e6C2aE7A3e'
    PermitResponse:
      type: object
      required:
        - success
        - transaction
        - network
      properties:
        success:
          type: boolean
          description: >-
            `true` only when the on-chain transaction was submitted
            successfully.
        transaction:
          type: string
          description: >-
            Transaction hash on success. Empty string (`""`) on every error
            response.
        network:
          type: string
          description: >-
            Echoes the network from the request (or `""` if the request body
            could not be parsed).
        errorReason:
          type: string
          description: Present on error responses only.
          enum:
            - invalid_request
            - unsupported_network
            - network_not_configured
            - invalid_signature
            - permit_execution_failed
  securitySchemes:
    cookieAuth:
      type: apiKey
      in: cookie
      name: siwe-session
    apiKeyAuth:
      type: apiKey
      in: header
      name: Authorization

````