> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mobula.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Bridge Execute (Gasless)

> [Alpha Preview] Submit a user-signed EIP-7702 batch and let Mobula broadcast it and pay the origin gas — bridge from an EVM wallet holding zero native token.

<Warning>
  **Alpha Preview** — Endpoints, response shape, contract addresses, and supported
  routes may change without notice. Don't depend on it for production-critical
  flows until it leaves alpha.
</Warning>

`POST /api/2/bridge/execute` broadcasts an **EVM origin deposit on the user's
behalf and pays its gas**. The user signs the batch off-chain; Mobula's solver
sends it. A wallet with `0` ETH/BNB/POL can approve and bridge in a single
signature.

The origin gas is not free — it's **priced into the quote** and deducted from
the amount delivered, which is why `/execute` only accepts intents quoted with
[`gasless=true`](/rest-api-reference/endpoint/bridge-quote).

## How it works

Under the hood this is an [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702)
sponsored batch:

1. The user's EOA is **delegated** to `MobulaBatchExecutor`. The delegation
   rides along as an authorization tuple on the first sponsored transaction —
   the wallet never sends a delegation transaction of its own.
2. The user signs an **EIP-712 `Batch`** — the quote's `approve` +
   `bridgeToken`/`swapAndBridge` steps, exactly the transactions they would
   otherwise broadcast themselves.
3. Mobula submits a type-4 transaction carrying that batch and pays the gas.
   The calls execute **from the user's own EOA**, so `msg.sender` at the bridge
   is still the user, and the deposit is indistinguishable from a self-sent one
   (same refund path, same `/status` lifecycle).

Because the calls run from the user's account, Mobula never takes custody and
never needs an allowance to itself — the approve in the batch is the user's own
approve.

### Authentication

Same as every bridge endpoint, and **required** — the call is refused with `401`
without it. Pass your API key as a query parameter on the POST URL
(`POST /api/2/bridge/execute?apiKey=YOUR_API_KEY`) or send it as
`Authorization: Bearer <apiKey-or-short-lived-JWT>`, exactly like `/quote`.
The request costs one credit on the resolved key.

### Availability

| Requirement  | Rule                                                                                                                                                                                                                                                                                                               |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Origin chain | EVM only, and only chains with a deployed executor (table below). Solana origins have their own gasless mechanism — pass `feePayerAddress` on `/quote` instead.                                                                                                                                                    |
| Route        | Cross-chain only. Same-chain swaps have no bridge deposit to sponsor and are refused at the quote.                                                                                                                                                                                                                 |
| Origin token | **ERC-20 only.** A native (or wrapped-native) origin deposit carries native value, and a sponsored batch may not move value.                                                                                                                                                                                       |
| Quote        | Must have been requested with `gasless=true`. A normally-quoted intent is refused — its output never paid for the gas.                                                                                                                                                                                             |
| Wallet       | Signing the 7702 authorization requires a signer that can produce an authorization tuple (embedded/local accounts, e.g. viem's `signAuthorization`, or Privy's `useSign7702Authorization`). Most injected browser wallets cannot. Once the account is delegated, later deposits need only a plain `signTypedData`. |

**Don't hardcode the executor address.** Every gasless quote returns it as
`sponsorGate.batchExecutor`, and the authorization tuple must name whatever that
says. A client holding its own copy is a second source of truth for the address
its batch is signed against: when the executor is redeployed, the batch is built
for one delegate and submitted against an account still delegated to another,
which does not necessarily fail loudly. Since no intent can reach `/execute`
without a `gasless=true` quote first, reading it from the quote costs nothing.

It is currently the same address on every supported chain, but that is a fact
about today's deployment, not a guarantee:

| Chain                        | MobulaBatchExecutor                          |
| ---------------------------- | -------------------------------------------- |
| `evm:8453` (Base)            | `0x29440460fbdda286fe259b0b1cbfbc018d47dfda` |
| `evm:56` (BSC)               | `0x29440460fbdda286fe259b0b1cbfbc018d47dfda` |
| `evm:42161` (Arbitrum)       | `0x29440460fbdda286fe259b0b1cbfbc018d47dfda` |
| `evm:137` (Polygon)          | `0x29440460fbdda286fe259b0b1cbfbc018d47dfda` |
| `evm:4663` (Robinhood Chain) | `0x29440460fbdda286fe259b0b1cbfbc018d47dfda` |

## The flow

```
GET  /2/bridge/quote?...&gasless=true      → intentId, typedData, steps
sign  typedData                            (EIP-712 BridgeIntent — the bridge intent)
sign  authorization                        (EIP-7702 — first gasless deposit only)
sign  Batch                                (EIP-712 — the approve + deposit calls)
POST /2/bridge/execute                     → depositTxHash
GET  /2/bridge/status/{intentId}/wait      → filled
```

Two of those signatures are the normal bridge flow (the intent) and the batch;
the authorization only appears once per account per chain. You can send the
bridge-intent `signature` in the `/execute` body to **skip the signed-quote
confirm call** — `/execute` persists the intent from the quote's own stash, so
the whole trade is two HTTP calls.

## Request body

| Field               | Required    | Notes                                                                                                                                                                                                                      |
| ------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `originChainId`     | yes         | The quote's origin chain (`evm:8453`, …).                                                                                                                                                                                  |
| `intentId`          | yes         | From the `gasless=true` quote. It is also the idempotency key.                                                                                                                                                             |
| `authority`         | yes         | The user's EOA: batch signer, authorization signer, and the account the calls run from. Must be the address the intent was quoted for.                                                                                     |
| `calls`             | yes         | The quote's `steps` mapped 1:1 to `{ to, value, data }` — `approve` then `bridgeToken`/`swapAndBridge`. Max 4 calls. Every `value` must be `"0"`. Don't drop the approve: the batch must do exactly what the quote priced. |
| `batchNonce`        | yes         | Decimal string. `(keccak256(utf8Bytes(intentId)) & (2**192 - 1)) << 64` — this intent's dedicated nonce lane (see [Nonce lanes](#nonce-lanes)).                                                                            |
| `deadline`          | yes         | Unix seconds (string). After it, the batch signature is refused on-chain and by the API. \~5 minutes is a sensible TTL.                                                                                                    |
| `gasToken`          | yes         | The origin token being bridged. Must equal the token the intent was quoted for.                                                                                                                                            |
| `minBalance`        | yes         | Raw units the account must hold for the batch to run. Must be at least the quoted deposit amount.                                                                                                                          |
| `batchSignature`    | yes         | EIP-712 signature over the `Batch` payload below, by `authority`.                                                                                                                                                          |
| `authorizationList` | conditional | One EIP-7702 tuple on the account's **first** sponsored deposit on that chain; `[]` once it's already delegated to `MobulaBatchExecutor`.                                                                                  |
| `shape`             | yes         | `bridgeToken` or `swapAndBridge` — the type of the quote's last step.                                                                                                                                                      |
| `signature`         | no          | The bridge-intent EIP-712 signature. Include it to skip the `/quote` confirm call; omit it if you already committed the signature there.                                                                                   |
| `executionKind`     | no          | Reserved; only `sponsored7702` exists today.                                                                                                                                                                               |

### Batch EIP-712 schema

```
Domain:
  name:              "MobulaBatchExecutor"
  version:           "1"
  chainId:           <numeric origin chain id>     // 8453, 56, 42161, 137, 4663
  verifyingContract: <the user's EOA>              // the ACCOUNT, not the executor

Call:
  to      address
  value   uint256      // always 0
  data    bytes

Batch:
  calls       Call[]     // the quote's steps, in order
  nonce       uint256    // batchNonce (the intent's lane)
  deadline    uint256    // unix seconds
  gasToken    address    // the origin token you are bridging
  minBalance  uint256    // the deposit amount, in that token's raw units
```

`gasToken` and `minBalance` are a balance gate the executor checks **before any
call runs**: if the account does not hold `minBalance` of `gasToken`, the batch
reverts immediately. It exists because Mobula pays the gas whether a batch
succeeds or fails, so a deposit that was never going to move any tokens has to
fail in \~35k gas rather than burning the whole limit.

Set them to the origin token and the exact amount the quote priced —
`/execute` refuses a batch whose `gasToken` is not the quoted origin token, or
whose `minBalance` is below the quoted deposit.

`verifyingContract` is the **user's own account** — that's what stops a batch
signed for one delegated EOA from being replayed against another.

### Authorization tuple

```json theme={null}
{ "chainId": 8453, "address": "0x7025…d736", "nonce": 42, "yParity": 0, "r": "0x…", "s": "0x…" }
```

* `address` must be the chain's `MobulaBatchExecutor`; anything else is refused.
* `chainId` must be the origin chain — the `0` "any chain" wildcard is refused.
* `nonce` is the **authority's current account nonce**, not `nonce + 1`: the
  solver submits the transaction, not the user. With viem's
  `signAuthorization`, that means *not* passing `executor: 'self'`. Get this
  wrong and the chain silently drops the authorization, leaving the batch to
  call `execute` on an account with no code.

Read the current delegation with `eth_getCode(authority)`: an empty result is a
plain EOA, and a delegated one is exactly `0xef0100 || <20-byte delegate>`. Send
a tuple when that delegate isn't `MobulaBatchExecutor`.

### Nonce lanes

`MobulaBatchExecutor` uses a two-dimensional nonce — `key << 64 | seq`,
sequential within a lane, independent across lanes — and every intent gets its
own lane derived from its `intentId`. Two deposits signed before either mines
can't collide, and a fresh lane always starts at sequence `0`, so no client ever
reads the chain to pick a nonce. Re-signing the *same* intent reuses its lane,
which is what makes a retry mutually exclusive with the attempt it replaces.

## Response

```json theme={null}
{
  "data": {
    "intentId": "a3b4ba1-e34523c-324",
    "status": "pending",
    "depositTxHash": "0x…",
    "sponsoredGasLimit": "1150000",
    "message": "Deposit broadcast; poll /bridge/status/:id for the fill"
  }
}
```

* `depositTxHash` is the sponsored transaction carrying the batch.
* `sponsoredGasLimit` is the gas units the send was capped at — exactly the
  units the quote charged for.
* `status` is always `pending`: the deposit has been broadcast, not yet filled.
  Poll [`/status/{intentId}/wait`](/rest-api-reference/endpoint/bridge-status)
  as with any other deposit.

## What the server checks

A sponsored batch spends Mobula's gas, so `/execute` validates rather than
rebuilds it (rebuilding would change the calldata and void the user's
signature):

* The intent's prediction must say it was quoted **gasless**, and quoted for
  **this `authority`**.
* Every `calls[].to` must be one of three addresses: the **origin token the
  quote priced** (to approve), the chain's `SwapBridgeHelper`, or
  `MobulaBridge`. Anything else is out of scope.
* No call may carry native `value`.
* `batchNonce` must be this intent's lane; `deadline` must be in the future;
  at most 4 calls.
* `batchSignature` must recover to `authority`, and every authorization tuple
  must be **signed by `authority`** and delegate to `MobulaBatchExecutor` on
  this chain.
* The gas limit of the broadcast is the quote's own units — never a client- or
  solver-supplied number.

## Idempotency and retries

`intentId` is the idempotency key: the first `/execute` for an intent claims it
for 15 minutes, and a second returns **409**. On a **504** the claim is
deliberately *retained* — the broadcast may still land, so poll
`/status/{intentId}` before doing anything else. Every other failure releases
the claim, so you can fix the request and retry the same intent.

## When the batch reverts on-chain

A `200` means the transaction was **broadcast**, not that it succeeded. A batch
can still revert once mined — a stale approval, a swap that moves past its own
limit, an out-of-gas. When it does, no tokens moved, so no deposit exists and no
bridge intent is ever created.

`/status/{intentId}` reports that case as `failed` rather than leaving it
`pending`:

```json theme={null}
{
  "data": {
    "id": "…",
    "status": "failed",
    "depositTxHash": "0x…",
    "failureReason": "CallFailed(index=1)",
    "message": "The sponsored deposit reverted on-chain — nothing left your wallet. Request a new quote."
  }
}
```

Nothing left the user's wallet, so there is nothing to refund. Re-quote and sign
again — re-submitting the same batch is refused with a **409**, because it would
revert identically.

## Errors

| Status | Meaning                                                                                                                                                              | What to do                                                                         |
| ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
| `400`  | Batch or intent refused: not quoted as gasless, wrong authority, out-of-scope call, non-zero value, wrong nonce lane, expired deadline, bad bridge-intent signature. | Fix and re-quote; nothing was sent.                                                |
| `401`  | `batchSignature` doesn't recover to `authority`.                                                                                                                     | Check the EIP-712 domain (`verifyingContract` = the user's EOA) and the signer.    |
| `409`  | This intent was already submitted, or its batch already reverted on-chain.                                                                                           | Poll `/status/{intentId}`. If it reads `failed`, re-quote — do **not** re-execute. |
| `502`  | The solver refused or failed to broadcast (bad authorization, send failure).                                                                                         | Nothing was sent; retry the same intent or re-quote.                               |
| `503`  | Single-execution or quote verification couldn't be guaranteed.                                                                                                       | Retry shortly.                                                                     |
| `504`  | The solver didn't answer within 30 s.                                                                                                                                | The deposit **may still land** — poll `/status/{intentId}` before retrying.        |

Error bodies are `{ "error": "...", "intentId": "..." }`.

## Example

Base → BSC, 100 USDC → USDT, from a wallet with no ETH. Two HTTP calls, three
signatures (one of which disappears after the first ever gasless deposit).

```typescript theme={null}
import { createPublicClient, createWalletClient, http, keccak256, toHex } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { base } from "viem/chains";

const API = "https://api.mobula.io/api/2/bridge";
const KEY = "YOUR_API_KEY";
const EXECUTOR = "0x29440460fbdda286fe259b0b1cbfbc018d47dfda";

const account = privateKeyToAccount("0xYourPrivKey");
const client = createWalletClient({ account, chain: base, transport: http() });
const publicClient = createPublicClient({ chain: base, transport: http() });

// 1. Quote it as gasless. The origin gas is already deducted from estimatedAmountOut.
const params = new URLSearchParams({
  originChainId: "evm:8453",
  destinationChainId: "evm:56",
  originToken: "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913", // USDC on Base
  destinationToken: "0x55d398326f99059fF775485246999027B3197955", // USDT on BSC
  amount: "100",
  walletAddress: account.address,
  senderAddress: account.address,
  gasless: "true",
  apiKey: KEY,
});
const { data: quote, error } = await fetch(`${API}/quote?${params}`).then((r) => r.json());
if (error) throw new Error(error);

// 2. Sign the bridge intent (sent in the /execute body — no confirm call needed).
const signature = await client.signTypedData({
  account,
  domain: quote.typedData.domain,
  types: quote.typedData.types,
  primaryType: quote.typedData.primaryType,
  message: quote.typedData.message,
});

// 3. Delegate the EOA, unless it already points at MobulaBatchExecutor.
const code = await publicClient.getCode({ address: account.address });
const delegate = code?.startsWith("0xef0100") ? `0x${code.slice(8, 48)}` : null;
const authorizationList =
  delegate?.toLowerCase() === EXECUTOR.toLowerCase()
    ? []
    : [
        // No `executor: 'self'` — Mobula submits, so the tuple takes the account's CURRENT nonce.
        await client.signAuthorization({ account, contractAddress: EXECUTOR }),
      ];

// 4. Sign the batch: the quote's steps, verbatim, in this intent's nonce lane.
const calls = quote.steps.map((s) => ({ to: s.tx.to, value: s.tx.value ?? "0", data: s.tx.data }));
const batchNonce = (BigInt(keccak256(toHex(quote.intentId))) & ((1n << 192n) - 1n)) << 64n;
const deadline = BigInt(Math.floor(Date.now() / 1000) + 300);

const batchSignature = await client.signTypedData({
  account,
  domain: {
    name: "MobulaBatchExecutor",
    version: "1",
    chainId: base.id,
    verifyingContract: account.address, // the ACCOUNT, not the executor
  },
  types: {
    Call: [
      { name: "to", type: "address" },
      { name: "value", type: "uint256" },
      { name: "data", type: "bytes" },
    ],
    Batch: [
      { name: "calls", type: "Call[]" },
      { name: "nonce", type: "uint256" },
      { name: "deadline", type: "uint256" },
      { name: "gasToken", type: "address" },
      { name: "minBalance", type: "uint256" },
    ],
  },
  primaryType: "Batch",
  message: { calls, nonce: batchNonce, deadline, gasToken, minBalance },
});

// 5. Hand it to Mobula, which broadcasts and pays the gas.
const res = await fetch(`${API}/execute?apiKey=${KEY}`, {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({
    executionKind: "sponsored7702",
    originChainId: "evm:8453",
    intentId: quote.intentId,
    authority: account.address,
    calls,
    batchNonce: batchNonce.toString(),
    deadline: deadline.toString(),
    batchSignature,
    authorizationList,
    shape: quote.steps.at(-1).type, // "swapAndBridge" | "bridgeToken"
    signature, // skips the /quote confirm call
  }),
});
const executed = await res.json();
if (!res.ok) throw new Error(executed.error);

console.log("Sponsored deposit:", executed.data.depositTxHash);

// 6. Same status flow as any other deposit.
const status = await fetch(`${API}/status/${quote.intentId}/wait?apiKey=${KEY}`).then((r) => r.json());
console.log(status.data.status); // "filled"
```

## Cost model

The user pays no origin gas, but the trade does. On a `gasless=true` quote:

* `fees.originSponsorGasUsd` is what the sponsored send costs, and it's already
  deducted from `estimatedAmountOut` and included in `totalFeeUsd`.
* The signed `minAmountOut` is derived from that same netted amount, so the
  floor the solver enforces matches the number the user was shown.
* The units charged are the exact gas limit the broadcast gets — the batch can
  never burn more than the quote reserved.

If the amount is too small to cover the origin gas, the quote fails with
`"Amount does not cover the sponsored origin gas ($…)"` rather than quoting a
payout it can't honour.

## See also

* [Bridge Quote](/rest-api-reference/endpoint/bridge-quote) — `gasless=true`, the
  typed data, and the deposit steps this endpoint batches.
* [Bridge Status](/rest-api-reference/endpoint/bridge-status) — the lifecycle
  after the deposit is broadcast.
* [Bridge Implementation guide](/guides/bridge-implementation) — the full
  non-gasless flow across EVM, Solana, and HyperLiquid.


## OpenAPI

````yaml post /2/bridge/execute
openapi: 3.0.0
info:
  version: 1.0.0
  title: Mobula API
  description: >-
    Documentation of the Mobula API


    **Demo API**: The default server (demo-api.mobula.io) is a demo API with
    rate limits.

    For production use, please use api.mobula.io with an API key from
    https://admin.mobula.io
servers:
  - url: https://demo-api.mobula.io/api/
    description: Demo API (rate limited, for testing only)
  - url: https://api.mobula.io/api/
    description: Production API (requires API key)
security: []
tags:
  - name: V2 - Token
    description: Token details, price, security, ATH, and holder data
  - name: V2 - Market Data
    description: Market details, OHLCV history, and lighthouse metrics
  - name: V2 - Trades
    description: Token trades, enriched trades, and trade filters
  - name: V2 - Wallet
    description: Wallet positions, activity, trades, analysis, and labels
  - name: V2 - Assets
    description: Cross-chain asset details and price history
  - name: V2 - Swap
    description: Swap quoting and execution
  - name: V2 - Perps
    description: Perpetual futures quoting, execution, and positions
  - name: V2 - Bridge
    description: Cross-chain bridge quoting and intent status (Alpha Preview)
  - name: V2 - DeFi
    description: Bonding pools and pulse data
  - name: V2 - Search
    description: Universal fast search
  - name: V2 - Usage
    description: Per-key API and WebSocket usage history
  - name: V2 - Blockchains
    description: System metadata and chain listings
  - name: V2 - Prediction Markets
    description: >-
      Polymarket markets/events, wallet positions, and the full execution stack
      (auth, order build/submit/cancel, approvals, pUSD wrap/unwrap, deploy,
      deposit/withdraw, redeem). Alpha — see /api/2/pm/*.
  - name: V1 - Market Data
    description: Market prices, history, sparklines, pairs, and multi-data
  - name: V1 - Wallet
    description: Wallet portfolio, transactions, history, and NFTs
  - name: V1 - Token
    description: First buyers
  - name: V1 - Trades
    description: Market trades by pair
  - name: V1 - Metadata
    description: Token metadata, categories, and news
  - name: V1 - Assets
    description: List all assets
  - name: V1 - Search
    description: Search for assets, tokens, and pairs
  - name: V1 - DeFi
    description: Bonding pool pulse data
  - name: V1 - Blockchains
    description: Blockchain listings, pairs, and stats
  - name: V1 - Webhooks
    description: Webhook management
  - name: V1 - Feed
    description: Custom feed creation
paths:
  /2/bridge/execute:
    post:
      tags:
        - V2 - Bridge
      summary: Execute a gasless (sponsored) EVM deposit
      description: >-
        [Alpha Preview] Submit a user-signed EIP-7702 batch (approve + deposit)
        that Mobula broadcasts and pays the origin gas for, so a wallet holding
        no native token can bridge. Requires an intent quoted with
        `gasless=true`; the origin gas was already deducted from that quote's
        output. EVM origins only. Returns the deposit transaction hash — poll
        `/2/bridge/status/{id}` for the fill.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                executionKind:
                  type: string
                  enum:
                    - sponsored7702
                  description: >-
                    Execution mechanism. Only `sponsored7702` exists today; the
                    field is optional and reserved.
                originChainId:
                  type: string
                  description: >-
                    Origin chain ID of the quote (e.g., "evm:8453"). Must be an
                    EVM chain with a MobulaBatchExecutor.
                intentId:
                  type: string
                  description: The `intentId` returned by the `gasless=true` quote.
                authority:
                  type: string
                  description: >-
                    The user's EOA — signer of the batch, and the account the
                    batched calls execute from. Must match the address the
                    intent was quoted for.
                calls:
                  type: array
                  description: >-
                    The quote's `steps`, in order, as batch calls (approve →
                    bridgeToken/swapAndBridge). Max 4, each with `value` "0".
                  items:
                    type: object
                    properties:
                      to:
                        type: string
                        description: >-
                          Target contract. Only the quoted origin token, the
                          chain's SwapBridgeHelper, and MobulaBridge are
                          accepted.
                      value:
                        type: string
                        description: >-
                          Must be "0" — a sponsored batch may not carry native
                          value.
                      data:
                        type: string
                        description: Calldata, taken verbatim from the quote step.
                    required:
                      - to
                      - value
                      - data
                batchNonce:
                  type: string
                  description: >-
                    MobulaBatchExecutor nonce, decimal string. Must equal this
                    intent's lane: `(keccak256(utf8Bytes(intentId)) & (2**192 -
                    1)) << 64`.
                deadline:
                  type: string
                  description: >-
                    Unix seconds after which the batch signature is refused.
                    Must be in the future.
                gasToken:
                  type: string
                  description: >-
                    Token whose balance gates the batch on-chain, taken verbatim
                    from the quote's `sponsorGate.gasToken`. Must be the token
                    this intent was quoted for; anything else is refused.
                minBalance:
                  type: string
                  description: >-
                    Minimum `gasToken` balance the account must hold for the
                    batch to run, from the quote's `sponsorGate.minBalance`.
                    Must be at least the quoted deposit amount. The executor
                    checks it before any call runs, so a batch that was never
                    going to move tokens fails in ~35k gas instead of burning
                    its whole limit.
                batchSignature:
                  type: string
                  description: >-
                    65-byte EIP-712 signature by `authority` over the
                    `Batch(calls, nonce, deadline, gasToken, minBalance)`
                    payload (domain `MobulaBatchExecutor` v1,
                    `verifyingContract` = `authority`).
                authorizationList:
                  type: array
                  description: >-
                    EIP-7702 authorization tuples. Exactly one on the account's
                    first sponsored send (it delegates the EOA to
                    MobulaBatchExecutor in the same transaction); empty
                    afterwards.
                  items:
                    type: object
                    properties:
                      chainId:
                        type: number
                      address:
                        type: string
                        description: >-
                          The delegate, from the quote's
                          `sponsorGate.batchExecutor`. Do not hardcode it — it
                          changes whenever the executor is redeployed.
                      nonce:
                        type: number
                        description: The authority's own account nonce.
                      yParity:
                        type: number
                      r:
                        type: string
                      s:
                        type: string
                    required:
                      - chainId
                      - address
                      - nonce
                      - yParity
                      - r
                      - s
                shape:
                  type: string
                  enum:
                    - bridgeToken
                    - swapAndBridge
                  description: >-
                    Which bridge entrypoint the batch ends on, matching the
                    quote's last step type.
                signature:
                  type: string
                  description: >-
                    Optional EIP-712 bridge-intent signature over the quote's
                    `typedData`. Send it here to skip the signed-quote confirm
                    call — `/execute` persists the intent from the quote's
                    stash. Omit if you already committed the signature via `GET
                    /2/bridge/quote`.
              required:
                - originChainId
                - intentId
                - authority
                - calls
                - batchNonce
                - deadline
                - gasToken
                - minBalance
                - batchSignature
                - shape
      responses:
        '200':
          description: The sponsored deposit was broadcast.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      intentId:
                        type: string
                      status:
                        type: string
                        enum:
                          - pending
                      depositTxHash:
                        type: string
                        description: Hash of the sponsored transaction carrying the batch.
                      sponsoredGasLimit:
                        type: string
                        description: >-
                          Gas units the send was capped at — exactly the units
                          the quote charged for.
                      message:
                        type: string
                    required:
                      - intentId
                      - status
                      - depositTxHash
                required:
                  - data
        '400':
          description: >-
            The batch or the intent was refused (bad signature, out-of-scope
            call, wrong nonce lane, expired deadline, intent not quoted as
            gasless).
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  intentId:
                    type: string
        '401':
          description: '`batchSignature` does not recover to `authority`.'
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  intentId:
                    type: string
        '409':
          description: >-
            This intent was already submitted. Poll `/2/bridge/status/{id}`
            instead of retrying.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  intentId:
                    type: string
        '502':
          description: >-
            The solver refused or failed to broadcast the batch. Nothing was
            sent; the intent can be retried.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  intentId:
                    type: string
        '503':
          description: >-
            Single-execution or quote verification could not be guaranteed right
            now. Retry shortly.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  intentId:
                    type: string
        '504':
          description: >-
            The solver did not answer in time. The deposit may still land — poll
            `/2/bridge/status/{id}` before retrying.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  intentId:
                    type: string

````