M 0

M 0 Permit API

The Permit API from M 0 — 2 operation(s) for permit.

OpenAPI Specification

m-0-permit-api-openapi.yml Raw ↑
openapi: 3.0.1
info:
  title: liquidity-api Order Permit API
  version: ''
  description: This API provides quotes for moving and converting between M extensions and other stablecoins
servers:
- url: https://gateway.m0.xyz/v1/orchestration
  description: mainnet
- url: https://gateway.stage.m0.xyz/v1/orchestration
  description: stage
- url: https://gateway.dev.m0.xyz/v1/orchestration
  description: devnet
- url: http://localhost:5600
  description: localnet
tags:
- name: Permit
paths:
  /permit/quote:
    post:
      description: 'Get quotes for the gasless-approval (EIP-2612 permit) flow.


        Like `/quote`, but every returned quote''s approvals are satisfied by

        signing an off-chain EIP-2612 permit instead of broadcasting a separate

        `approve` transaction — collapsing approve + action into a single

        on-chain transaction. **EVM only.**


        Each `PermitQuote` carries one `PermitRecipe` per leg (in execution

        order); sign each recipe''s `typedData`, then either POST the signed

        recipes to `/permit/build` to receive executable payloads, or encode

        the `*WithPermit` call locally from the recipe.


        Only routes whose every leg is permit-capable are returned.


        **Error responses**


        All errors return `commons.ErrorBody` (`{ code, message, requestId }`).

        Branch on `code`, not the HTTP status.


        | Status | `code`              | When                                                                    |

        | ------ | ------------------- | ----------------------------------------------------------------------- |

        | 400    | `BadPermitRequest`  | Missing/invalid fields, `source` == `destination`, or an unknown asset. |

        | 404    | `PermitNotSupported`| Structurally valid, but no permit-capable path exists for this route.   |

        | 500    | `PermitQuoteError`  | Unexpected internal failure while computing permit quotes.              |'
      operationId: permit_permitQuote
      tags:
      - Permit
      parameters: []
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PermitQuoteResponse'
        '400':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorBody'
        '404':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorBody'
        '500':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorBody'
      security:
      - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                route:
                  $ref: '#/components/schemas/Route'
                amountIn:
                  type: string
                sender:
                  type: string
                funder:
                  type: string
                  nullable: true
                  description: 'The account that holds the input tokens and signs the permit.

                    Defaults to `sender` when omitted.'
                recipient:
                  type: string
                  nullable: true
                maxNumQuotes:
                  type: integer
                  nullable: true
                providers:
                  $ref: '#/components/schemas/ProvidersParams'
                  nullable: true
              required:
              - route
              - amountIn
              - sender
  /permit/build:
    post:
      description: 'Exchange signed permit recipes for executable transaction payloads.


        Echo back the `PermitRecipe`s from `/permit/quote`, each paired with

        the user''s EIP-2612 signature over its `typedData`. Returns one

        `Payload` per recipe, in order — the encoded `*WithPermit` call.


        The server re-validates each recipe before encoding (permit `value`

        matches `amountIn`, `spender` matches the operation target, `deadline`

        not expired, and the recovered signer equals the permit `owner`).


        **Error responses**


        All errors return `commons.ErrorBody` (`{ code, message, requestId }`).

        Branch on `code`, not the HTTP status.


        | Status | `code`                   | When                                                          |

        | ------ | ------------------------ | ------------------------------------------------------------- |

        | 400    | `BadPermitRequest`       | Malformed body, or a recipe that fails internal consistency.  |

        | 410    | `PermitExpired`          | A recipe''s permit `deadline` has already passed.              |

        | 422    | `InvalidPermitSignature` | Signature does not recover to the permit `owner`.             |

        | 500    | `PermitBuildError`       | Unexpected internal failure while encoding the payloads.      |'
      operationId: permit_permitBuild
      tags:
      - Permit
      parameters: []
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PermitBuildResponse'
        '400':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorBody'
        '410':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorBody'
        '422':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorBody'
        '500':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorBody'
      security:
      - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                signedRecipes:
                  type: array
                  items:
                    $ref: '#/components/schemas/SignedPermitRecipe'
              required:
              - signedRecipes
components:
  schemas:
    AmmSwapPermitOp:
      title: AmmSwapPermitOp
      type: object
      description: Uniswap V3 `multicall([selfPermit, exactInputSingle])`. Signature split to v,r,s.
      properties:
        tokenIn:
          type: string
        tokenOut:
          type: string
        fee:
          type: integer
        recipient:
          type: string
        amountIn:
          type: string
        amountOutMinimum:
          type: string
        deadline:
          type: string
      required:
      - tokenIn
      - tokenOut
      - fee
      - recipient
      - amountIn
      - amountOutMinimum
      - deadline
    SvmPayload:
      title: SvmPayload
      type: object
      properties:
        chain:
          $ref: '#/components/schemas/Chain'
        transaction:
          type: string
          format: byte
      required:
      - chain
      - transaction
    Eip2612TypedData:
      title: Eip2612TypedData
      type: object
      description: 'Directly signable EIP-712 payload. `types`/`primaryType` are the standard

        EIP-2612 `Permit` definition and are omitted; clients use the canonical set.'
      properties:
        domain:
          $ref: '#/components/schemas/Eip712Domain'
        message:
          $ref: '#/components/schemas/Eip2612Message'
      required:
      - domain
      - message
    PermitOperation:
      title: PermitOperation
      oneOf:
      - type: object
        allOf:
        - type: object
          properties:
            type:
              type: string
              enum:
              - swap
        - $ref: '#/components/schemas/SwapPermitOp'
        required:
        - type
      - type: object
        allOf:
        - type: object
          properties:
            type:
              type: string
              enum:
              - limitOrder
        - $ref: '#/components/schemas/LimitOrderPermitOp'
        required:
        - type
      - type: object
        allOf:
        - type: object
          properties:
            type:
              type: string
              enum:
              - ammSwap
        - $ref: '#/components/schemas/AmmSwapPermitOp'
        required:
        - type
      description: 'Provider-specific static args for the `*WithPermit` call, discriminated

        so the build step (or a self-encoding client) knows exactly what to build.'
    TransactionPayload:
      title: TransactionPayload
      oneOf:
      - type: object
        allOf:
        - type: object
          properties:
            type:
              type: string
              enum:
              - evm
        - $ref: '#/components/schemas/EvmPayload'
        required:
        - type
      - type: object
        allOf:
        - type: object
          properties:
            type:
              type: string
              enum:
              - svm
        - $ref: '#/components/schemas/SvmPayload'
        required:
        - type
    Chain:
      title: Chain
      type: string
      enum:
      - Ethereum
      - Solana
      - Arbitrum
      - Base
      - Linea
      - Sepolia
      - BaseSepolia
      - ArbitrumSepolia
      - HyperEVM
      - BinanceSmartChain
      - Mantra
      - Plasma
      - SolanaDevnet
      - Soneium
      - Citrea
      - Fluent
      - Moca
      - Rise
    ErrorCode:
      title: ErrorCode
      type: string
      enum:
      - QuoteError
      - BadQuoteRequest
      - NoQuotesAvailable
      - BadOrderRequest
      - OrderNotFound
      - OrderNotCancellable
      - CancelOrderError
      - BadTopologyRequest
      - BadPermitRequest
      - PermitNotSupported
      - PermitExpired
      - InvalidPermitSignature
      - PermitQuoteError
      - PermitBuildError
      description: 'Stable machine-readable identifier for an API error. Each value

        corresponds 1:1 to an error type (and to one `responses` entry

        in the OpenAPI spec). Branch on this rather than on the HTTP status

        code — multiple errors may share a status as the API evolves.'
    Providers:
      title: Providers
      type: string
      enum:
      - m-swap-facility
      - m-wormhole-portal
      - m-hyperlane-portal
      - m-portal
      - wormhole-cctp
      - jupiter
      - raydium
      - mayan-swift
      - kyber-swap
      - limit-order
      - uniswap-v3
    SwapMethod:
      title: SwapMethod
      type: string
      enum:
      - swap
      - swapInM
      - swapOutM
    PermitBuildResponse:
      title: PermitBuildResponse
      type: object
      properties:
        requestId:
          type: string
        payloads:
          type: array
          items:
            $ref: '#/components/schemas/Payload'
        issues:
          $ref: '#/components/schemas/PermitIssues'
          nullable: true
      required:
      - requestId
      - payloads
    Payload:
      title: Payload
      type: object
      properties:
        provider:
          type: string
        annotation:
          type: string
          nullable: true
        data:
          $ref: '#/components/schemas/TransactionPayload'
        solver:
          $ref: '#/components/schemas/PayloadSolver'
          nullable: true
          description: 'Present only on limit-order legs. Identifies the solver that produced

            this leg, as reported to the server over gRPC.'
      required:
      - provider
      - data
    SignedPermitRecipe:
      title: SignedPermitRecipe
      type: object
      properties:
        recipe:
          $ref: '#/components/schemas/PermitRecipe'
          description: Echoed verbatim from `/permit/quote`.
        signature:
          type: string
          description: 65-byte hex EIP-2612 permit signature. Build splits to v,r,s where the contract needs it.
      required:
      - recipe
      - signature
    Eip2612Message:
      title: Eip2612Message
      type: object
      properties:
        owner:
          type: string
        spender:
          type: string
        value:
          type: string
        nonce:
          type: string
        deadline:
          type: string
      required:
      - owner
      - spender
      - value
      - nonce
      - deadline
    PermitRecipe:
      title: PermitRecipe
      type: object
      description: 'Everything needed to sign one leg''s permit and produce its executable

        transaction — either by POSTing to `/permit/build` or by encoding the

        `*WithPermit` call locally (self-encoding).'
      properties:
        provider:
          $ref: '#/components/schemas/Providers'
        annotation:
          type: string
          description: 'Human-readable label for this leg, e.g. `M0 Swap Facility wM → USD+`.

            For display in clients.'
        chain:
          $ref: '#/components/schemas/Chain'
        chainId:
          type: integer
        spender:
          type: string
          description: Contract granted the permit and called in `/permit/build` (the tx `to`).
        value:
          type: string
          description: Native value for the final transaction. "0" for the permit-capable providers.
        typedData:
          $ref: '#/components/schemas/Eip2612TypedData'
        solver:
          $ref: '#/components/schemas/PayloadSolver'
          nullable: true
          description: 'Present only on limit-order legs. Identifies the solver that produced

            this leg, mirroring `Payload.solver` on `/quote`. For display.'
        operation:
          $ref: '#/components/schemas/PermitOperation'
          description: Static args the build step encodes into the `*WithPermit` call.
        functionSignature:
          type: string
          description: 'Solidity signature of the `*WithPermit` call this recipe encodes to,

            e.g. `swapWithPermit(address,address,uint256,address,uint256,bytes)`.

            Lets a client encode the transaction locally — from `operation` plus

            the signature — instead of calling `/permit/build`.'
      required:
      - provider
      - annotation
      - chain
      - chainId
      - spender
      - value
      - typedData
      - operation
      - functionSignature
    AssetAddress:
      title: AssetAddress
      type: object
      properties:
        chain:
          $ref: '#/components/schemas/Chain'
        address:
          type: string
      required:
      - chain
      - address
    PermitQuoteResponse:
      title: PermitQuoteResponse
      type: object
      properties:
        requestId:
          type: string
          description: Per-request correlation id.
        quotes:
          type: array
          items:
            $ref: '#/components/schemas/PermitQuote'
        issues:
          $ref: '#/components/schemas/PermitIssues'
          nullable: true
          description: Non-fatal findings shared across all quotes (e.g. insufficient balance).
      required:
      - requestId
      - quotes
    Eip712Domain:
      title: Eip712Domain
      type: object
      properties:
        name:
          type: string
        version:
          type: string
        chainId:
          type: integer
        verifyingContract:
          type: string
          description: The input token's address.
      required:
      - name
      - version
      - chainId
      - verifyingContract
    Route:
      title: Route
      type: object
      properties:
        source:
          $ref: '#/components/schemas/AssetAddress'
        destination:
          $ref: '#/components/schemas/AssetAddress'
      required:
      - source
      - destination
    PermitQuote:
      title: PermitQuote
      type: object
      description: A quote whose approvals are satisfied by signing permits, not `approve`.
      properties:
        route:
          $ref: '#/components/schemas/Route'
        recipient:
          type: string
        amountIn:
          type: string
        amountOut:
          type: string
        minAmountOut:
          type: string
          description: 'Floor that must be met or the transaction reverts. Equals

            `amountOut` for exact-output providers; below it for AMM legs

            per `slippageBps`.'
        estFillTime:
          type: integer
        expiresAt:
          type: integer
          description: 'Unix seconds after which this quote is no longer buildable — the

            earliest permit `deadline` across its recipes. `/permit/build`

            rejects with `PermitExpired` past this.'
        recipes:
          type: array
          items:
            $ref: '#/components/schemas/PermitRecipe'
          description: One per leg, in execution order.
      required:
      - route
      - recipient
      - amountIn
      - amountOut
      - minAmountOut
      - estFillTime
      - expiresAt
      - recipes
    ErrorBody:
      title: ErrorBody
      type: object
      description: 'Standard error response body. Every error response from this API

        returns this shape.'
      properties:
        code:
          $ref: '#/components/schemas/ErrorCode'
          description: Stable machine-readable identifier for the failure mode.
        message:
          type: string
          description: Human-readable description of what went wrong. Safe to surface in UI.
        requestId:
          type: string
          nullable: true
          description: 'Per-request correlation id (matches the `requestId` field in

            server logs). Include this when filing support tickets.'
      required:
      - code
      - message
    EvmPayload:
      title: EvmPayload
      type: object
      properties:
        chain:
          $ref: '#/components/schemas/Chain'
        chainId:
          type: integer
        to:
          type: string
        data:
          type: string
        value:
          type: string
      required:
      - chain
      - chainId
      - to
      - data
      - value
    BalanceIssue:
      title: BalanceIssue
      type: object
      properties:
        token:
          type: string
        actual:
          type: string
        expected:
          type: string
      required:
      - token
      - actual
      - expected
    ProvidersParams:
      title: ProvidersParams
      type: object
      properties:
        include:
          type: array
          items:
            $ref: '#/components/schemas/Providers'
          nullable: true
        exclude:
          type: array
          items:
            $ref: '#/components/schemas/Providers'
          nullable: true
    PermitIssues:
      title: PermitIssues
      type: object
      description: Soft warnings; their presence does not fail the request.
      properties:
        balance:
          $ref: '#/components/schemas/BalanceIssue'
          nullable: true
          description: Present when `sender` does not hold `amountIn` of the input token.
    LimitOrderPermitOp:
      title: LimitOrderPermitOp
      type: object
      description: OrderBook `openOrderWithPermit`.
      properties:
        destChainId:
          type: integer
        fillDeadline:
          type: integer
        tokenIn:
          type: string
        tokenOut:
          type: string
          description: bytes32-encoded destination token.
        amountIn:
          type: string
        amountOut:
          type: string
        recipient:
          type: string
          description: bytes32-encoded recipient.
        solver:
          type: string
          description: bytes32-encoded designated solver (zero for an open fill).
        sender:
          type: string
        deadline:
          type: string
      required:
      - destChainId
      - fillDeadline
      - tokenIn
      - tokenOut
      - amountIn
      - amountOut
      - recipient
      - solver
      - sender
      - deadline
    SwapPermitOp:
      title: SwapPermitOp
      type: object
      description: M Swap Facility `swap*WithPermit`.
      properties:
        method:
          $ref: '#/components/schemas/SwapMethod'
        extensionIn:
          type: string
          nullable: true
        extensionOut:
          type: string
          nullable: true
        amount:
          type: string
        recipient:
          type: string
        deadline:
          type: string
      required:
      - method
      - amount
      - recipient
      - deadline
    PayloadSolver:
      title: PayloadSolver
      type: object
      description: 'The solver behind a limit-order leg. `exclusive` means the leg is bound to

        this solver on-chain (it becomes the order''s `designatedSolver`); when

        false, the quote reflects this solver''s price but any solver may fill.'
      properties:
        address:
          type: string
        name:
          type: string
          nullable: true
        exclusive:
          type: boolean
        feeBps:
          type: integer
          nullable: true
      required:
      - address
      - exclusive
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key