> **Can't find what you're looking for?** Use `search_docs` on the docs MCP server at `https://www.openfort.io/api/mcp` to find what you need.
>
> **Have feedback?** Use `submit_feedback` on the same MCP server.

# Transactions

Create, estimate, sign, and track transactions sent from a wallet, with optional fee sponsorship.

## List transactions

`GET /v2/transactions`

Returns a list of transactions, most recent first.

### Query parameters

- `limit` `integer <int32>`: Specifies the maximum number of records to return.
- `skip` `integer <int32>`: Specifies the offset for the first records to return.
- `order` `string`: Specifies the order in which to sort the results.
- `expand` `string[]`: Specifies the fields to expand in the response. `timeline` adds the lifecycle history (one monitor lookup per request); `userOperation` and `logs` add the heavyweight execution payload and receipt logs, which are otherwise omitted.
- `chainId` `integer <int32>`: The chain ID. Must be a [supported chain](https://www.openfort.io/docs/configuration/chains).
- `accountId` `string[]`: Filter by account ID (starts with acc_).
- `userId` `string[]`: Filter by user ID (starts with usr_).
- `walletId` `string[]`: Filter by wallet ID (starts with pla_).
- `feeSponsorshipId` `string[]`: Filter by fee sponsorship ID (starts with pol_).
- `status` `string`: Filter by transaction status.

### Responses

#### `200`: Successful response.

Body (`application/json`):

- `object` `string` _(required)_
- `url` `string` _(required)_
- `data` `object[]` _(required)_
  - `id` `string` _(required)_
  - `object` `string` _(required)_
  - `createdAt` `integer <int32>` _(required)_
  - `updatedAt` `integer <int32>` _(required)_
  - `chainId` `integer <int32>` _(required)_
  - `status` `string` _(required)_
  - `accountId` `string` _(required)_: ID of the account that executes the transaction (starts with `acc_`).
  - `walletId` `string`: ID of the wallet that owns the account (starts with `pla_`). Absent for backend wallets.
  - `feeSponsorshipId` `string`: ID of the fee sponsorship paying for gas (starts with `pol_`). Absent when the account pays its own gas.
  - `account` `object`: The executing account. Present only with `expand=account`.
    - `id` `string` _(required)_
    - `wallet` `string` _(required)_
    - `accountType` `string` _(required)_
    - `address` `string` _(required)_
    - `ownerAddress` `string`
    - `chainType` `string` _(required)_
    - `chainId` `number <double>`
    - `createdAt` `number <double>` _(required)_
    - `updatedAt` `number <double>` _(required)_
    - `smartAccount` `object`
      - `implementationType` `string` _(required)_
      - `factoryAddress` `string`
      - `implementationAddress` `string` _(required)_
      - `salt` `string`
      - `deployedTx` `string`
      - `deployedAt` `number <double>`
      - `active` `boolean` _(required)_
      - `ownerAddress` `string`
      - `chainId` `number <double>`
    - `recoveryMethod` `string`
    - `recoveryMethodDetails` `object`
      - `passkeyId` `string`
      - `passkeyEnv` `object`
        - `name` `string`
        - `os` `string`
        - `osVersion` `string`
        - `device` `string`
    - `custody` `string` _(required)_: Indicates key custody: "Developer" for TEE managed keys, "User" for user-managed keys.
  - `feeSponsorship` `object`: The fee sponsorship paying for gas. Present only with `expand=feeSponsorship`.
    - `id` `string` _(required)_
    - `object` `string` _(required)_
    - `createdAt` `integer <int32>` _(required)_
    - `name` `string | null` _(required)_: Name of the fee sponsorship policy.
    - `description` `string | null` _(required)_: Description or comment for the fee sponsorship.
    - `chainId` `integer | null` _(required)_: Chain ID for single-chain sponsorship.
    - `enabled` `boolean` _(required)_: Whether the policy is enabled.
    - `strategy` `object` _(required)_: Sponsorship strategy configuration.
      - `sponsorSchema` `string` _(required)_: The sponsorship schema type.
      - `tokenContract` `string`: Token contract ID for charge_custom_tokens or fixed_rate schemas (EVM).
      - `tokenContractAmount` `string`: Token amount for charge_custom_tokens or fixed_rate schemas (EVM).
      - `dynamicExchangeRate` `boolean`: Whether any accepted token is priced dynamically from cached prices. True when at least one token has no static amount. For per-token detail, read the amount on each tokenContracts entry.
      - `splTokens` `string[]`: SPL mint addresses accepted for fee payment on Solana charge_custom_tokens policies.
      - `tokenContracts` `object[]`: ERC-20 tokens accepted as user-pay fee for EVM charge_custom_tokens policies. Populated for both new (tokenContracts) and legacy (tokenContract) requests; legacy single-token policies appear as a 1-element array here.
        - `contract` `string` _(required)_: Token contract ID.
        - `amount` `string`: Static exchange rate, or undefined when the dynamic cached rate is used.
    - `paymasterId` `string | null` _(required)_: Paymaster ID (optional).
    - `forwarderContractId` `string | null` _(required)_: Forwarder contract ID (optional, for meta-transactions).
    - `policyId` `string | null` _(required)_: Linked policy ID for criteria-based transaction filtering.
  - `calls` `object[]`: The calls this transaction executes.
    - `to` `string`: The address that receives the call. Use *only* for raw calls and native token transfers; a `pla_...` or `acc_...` id is converted to the corresponding address.
    - `value` `string`: The value sent with the call, as a stringified number in WEI (factor 10^18).
    - `data` `string`: Raw calldata (hex) for the call. Use instead of `contractId`/`functionName`.
    - `dataSuffix` `string`: Hex data appended to the encoded function call.
    - `contractId` `string`: ID of the contract the call interacts with. Must have been added to Openfort first, starts with `con_`.
    - `functionName` `string`: The function name of the contract. Accepts a function signature as well (e.g. mint(address)).
    - `functionArgs` `unknown[]`: The function arguments of the contract, formatted as strings.
  - `execution` `object`: How the transaction is executed on-chain, discriminated by `type`: `userOperation` (ERC-4337 smart accounts, including EIP-7702 delegated accounts) or `transaction` (plain EOA transaction). Absent only when the transaction failed before it could be built (`status: "failed"`, see `receipt.error`).
  - `nextAction` `object`: Present while `status` is `awaiting_signature`.
    - `type` `string` _(required)_
    - `hash` `string` _(required)_: Chain-agnostic hash to sign with the account's signer, then submit via `POST /v2/transactions/{id}/signature`.
  - `receipt` `object`: Present once the transaction reached a terminal status.
    - `createdAt` `integer <int32>` _(required)_: Unix timestamp (seconds) when the receipt was recorded.
    - `transactionHash` `string`
    - `blockNumber` `integer <int32>`
    - `to` `string`: Address the transaction was sent to (the EntryPoint for user operations).
    - `gasUsed` `string`
    - `gasFee` `string`
    - `l1GasUsed` `string`
    - `l1GasFee` `string`
    - `logs` `object[]`: The transaction's event logs. Present only with `expand=logs`.
      - `blockNumber` `number <double>` _(required)_
      - `blockHash` `string` _(required)_
      - `transactionIndex` `number <double>` _(required)_
      - `removed` `boolean` _(required)_
      - `address` `string` _(required)_
      - `data` `string` _(required)_
      - `topics` `string[]` _(required)_
      - `transactionHash` `string` _(required)_
      - `logIndex` `number <double>` _(required)_
      - `orphaned` `boolean`
    - `error` `object`: Present when the transaction reverted or failed.
      - `reason` `string` _(required)_: The error reason string returned by the bundler or execution environment.
      - `name` `string`: The decoded error name from the contract revert, if available.
      - `explanation` `object`: Detailed explanation of the error cause and suggested solution. Present only for known Account Abstraction error codes (AA10–AA99).
        - `cause` `string` _(required)_: A human-readable description of what caused the error.
        - `solution` `string` _(required)_: A human-readable suggestion for how to resolve the error.
  - `timeline` `object[]`: Lifecycle history in order, present only with `expand=timeline`. Status-valued events come from this API's own records and always agree with `status`; monitoring-only events (`indexed`, `confirmed`, `dropped`, `replaced`, `expired`) come from the user-operation monitor, are best-effort, and are never present for plain EOA transactions.
    - `event` `string` _(required)_: Timeline events: every `TransactionStatusV2` value (a state change), plus monitoring-only events that refine a state without changing it. `status` always equals the last status-valued event.
    - `at` `integer <int32>`: Unix timestamp (seconds). Absent when the exact time is unknown (e.g. `submitted` for a transaction the monitor did not track).
  - `costUsd` `string`: The actual transaction cost in USD, available after on-chain confirmation.
- `start` `integer <int32>` _(required)_
- `end` `integer <int32>` _(required)_
- `total` `integer <int32>` _(required)_

#### `401`: Error response.

Body (`application/json`):

- `error` `object` _(required)_
  - `type` `string` _(required)_
  - `message` `string` _(required)_
  - `details` `object`
  - `code` `string`: Machine-readable cause, when the thrower disambiguates one (e.g. funding_key_required).
  - `param` `string`: Offending request field path, when the thrower points at one (e.g. target.chain).

### Example request

```bash
curl 'https://api.openfort.io/v2/transactions?limit=10&skip=0&order=desc&expand=account&chainId=80002&accountId=acc_dc981458-a653-4539-b120-a321915b2896&userId=usr_556166c9-77ad-4a39-aaf8-c432defa8a0f&walletId=pla_6f6c9067-89fa-4fc8-ac72-c242a268c584&feeSponsorshipId=pol_7e07ae30-2a4d-48fa-803f-361da94905dd&status=awaiting_signature'
```

```ts
fetch('https://api.openfort.io/v2/transactions?limit=10&skip=0&order=desc&expand=account&chainId=80002&accountId=acc_dc981458-a653-4539-b120-a321915b2896&userId=usr_556166c9-77ad-4a39-aaf8-c432defa8a0f&walletId=pla_6f6c9067-89fa-4fc8-ac72-c242a268c584&feeSponsorshipId=pol_7e07ae30-2a4d-48fa-803f-361da94905dd&status=awaiting_signature')
```

## Create a transaction

`POST /v2/transactions`

Creates a transaction for an account.

For accounts whose key is held by the user, the response has `status: "awaiting_signature"` and a
`nextAction` with the hash to sign; submit the signature with `POST /v2/transactions/{id}/signature`.
For custodial and backend-wallet accounts the transaction is signed and broadcast in the same call
and the response already carries a `receipt` (unless `waitForReceipt` is `false`).

### Header parameters

- `X-Behalf-Of-Project` `string`: Project ID to act on behalf of (for ecosystem operations).

### Request body (required) (`application/json`)

- `chainId` `integer <int32>` _(required)_: The chain ID. Must be a [supported chain](https://www.openfort.io/docs/configuration/chains).
- `accountId` `string` _(required)_: ID of the account that executes the transaction (starts with `acc_`).
- `feeSponsorshipId` `string`: ID of the fee sponsorship that pays for gas (starts with `pol_`). Omit to pay gas from the account's native token balance.
- `feeSponsorshipToken` `string`: For a fee sponsorship that accepts several user-pay ERC-20 tokens, the on-chain address of the token the user pays the fee in. Must be one of the sponsorship's configured tokens on this chain.
- `calls` `object[]` _(required)_
  - `to` `string`: The address that receives the call. Use *only* for raw calls and native token transfers; a `pla_...` or `acc_...` id is converted to the corresponding address.
  - `value` `string`: The value sent with the call, as a stringified number in WEI (factor 10^18).
  - `data` `string`: Raw calldata (hex) for the call. Use instead of `contractId`/`functionName`.
  - `dataSuffix` `string`: Hex data appended to the encoded function call.
  - `contractId` `string`: ID of the contract the call interacts with. Must have been added to Openfort first, starts with `con_`.
  - `functionName` `string`: The function name of the contract. Accepts a function signature as well (e.g. mint(address)).
  - `functionArgs` `unknown[]`: The function arguments of the contract, formatted as strings.
- `waitForReceipt` `boolean`: Whether to hold the request until the transaction is mined and the `receipt` is available (default `true`). Set to `false` to respond as soon as the transaction is broadcast (`status: "submitted"`) and poll `GET /v2/transactions/{id}` for the outcome.
- `authorization` `string`: EIP-7702 signed authorization (hex) for a delegated account that is not yet delegated on-chain.

### Responses

#### `200`: Successful response.

Body (`application/json`):

- `id` `string` _(required)_
- `object` `string` _(required)_
- `createdAt` `integer <int32>` _(required)_
- `updatedAt` `integer <int32>` _(required)_
- `chainId` `integer <int32>` _(required)_
- `status` `string` _(required)_
- `accountId` `string` _(required)_: ID of the account that executes the transaction (starts with `acc_`).
- `walletId` `string`: ID of the wallet that owns the account (starts with `pla_`). Absent for backend wallets.
- `feeSponsorshipId` `string`: ID of the fee sponsorship paying for gas (starts with `pol_`). Absent when the account pays its own gas.
- `account` `object`: The executing account. Present only with `expand=account`.
  - `id` `string` _(required)_
  - `wallet` `string` _(required)_
  - `accountType` `string` _(required)_
  - `address` `string` _(required)_
  - `ownerAddress` `string`
  - `chainType` `string` _(required)_
  - `chainId` `number <double>`
  - `createdAt` `number <double>` _(required)_
  - `updatedAt` `number <double>` _(required)_
  - `smartAccount` `object`
    - `implementationType` `string` _(required)_
    - `factoryAddress` `string`
    - `implementationAddress` `string` _(required)_
    - `salt` `string`
    - `deployedTx` `string`
    - `deployedAt` `number <double>`
    - `active` `boolean` _(required)_
    - `ownerAddress` `string`
    - `chainId` `number <double>`
  - `recoveryMethod` `string`
  - `recoveryMethodDetails` `object`
    - `passkeyId` `string`
    - `passkeyEnv` `object`
      - `name` `string`
      - `os` `string`
      - `osVersion` `string`
      - `device` `string`
  - `custody` `string` _(required)_: Indicates key custody: "Developer" for TEE managed keys, "User" for user-managed keys.
- `feeSponsorship` `object`: The fee sponsorship paying for gas. Present only with `expand=feeSponsorship`.
  - `id` `string` _(required)_
  - `object` `string` _(required)_
  - `createdAt` `integer <int32>` _(required)_
  - `name` `string | null` _(required)_: Name of the fee sponsorship policy.
  - `description` `string | null` _(required)_: Description or comment for the fee sponsorship.
  - `chainId` `integer | null` _(required)_: Chain ID for single-chain sponsorship.
  - `enabled` `boolean` _(required)_: Whether the policy is enabled.
  - `strategy` `object` _(required)_: Sponsorship strategy configuration.
    - `sponsorSchema` `string` _(required)_: The sponsorship schema type.
    - `tokenContract` `string`: Token contract ID for charge_custom_tokens or fixed_rate schemas (EVM).
    - `tokenContractAmount` `string`: Token amount for charge_custom_tokens or fixed_rate schemas (EVM).
    - `dynamicExchangeRate` `boolean`: Whether any accepted token is priced dynamically from cached prices. True when at least one token has no static amount. For per-token detail, read the amount on each tokenContracts entry.
    - `splTokens` `string[]`: SPL mint addresses accepted for fee payment on Solana charge_custom_tokens policies.
    - `tokenContracts` `object[]`: ERC-20 tokens accepted as user-pay fee for EVM charge_custom_tokens policies. Populated for both new (tokenContracts) and legacy (tokenContract) requests; legacy single-token policies appear as a 1-element array here.
      - `contract` `string` _(required)_: Token contract ID.
      - `amount` `string`: Static exchange rate, or undefined when the dynamic cached rate is used.
  - `paymasterId` `string | null` _(required)_: Paymaster ID (optional).
  - `forwarderContractId` `string | null` _(required)_: Forwarder contract ID (optional, for meta-transactions).
  - `policyId` `string | null` _(required)_: Linked policy ID for criteria-based transaction filtering.
- `calls` `object[]`: The calls this transaction executes.
  - `to` `string`: The address that receives the call. Use *only* for raw calls and native token transfers; a `pla_...` or `acc_...` id is converted to the corresponding address.
  - `value` `string`: The value sent with the call, as a stringified number in WEI (factor 10^18).
  - `data` `string`: Raw calldata (hex) for the call. Use instead of `contractId`/`functionName`.
  - `dataSuffix` `string`: Hex data appended to the encoded function call.
  - `contractId` `string`: ID of the contract the call interacts with. Must have been added to Openfort first, starts with `con_`.
  - `functionName` `string`: The function name of the contract. Accepts a function signature as well (e.g. mint(address)).
  - `functionArgs` `unknown[]`: The function arguments of the contract, formatted as strings.
- `execution` `object`: How the transaction is executed on-chain, discriminated by `type`: `userOperation` (ERC-4337 smart accounts, including EIP-7702 delegated accounts) or `transaction` (plain EOA transaction). Absent only when the transaction failed before it could be built (`status: "failed"`, see `receipt.error`).
- `nextAction` `object`: Present while `status` is `awaiting_signature`.
  - `type` `string` _(required)_
  - `hash` `string` _(required)_: Chain-agnostic hash to sign with the account's signer, then submit via `POST /v2/transactions/{id}/signature`.
- `receipt` `object`: Present once the transaction reached a terminal status.
  - `createdAt` `integer <int32>` _(required)_: Unix timestamp (seconds) when the receipt was recorded.
  - `transactionHash` `string`
  - `blockNumber` `integer <int32>`
  - `to` `string`: Address the transaction was sent to (the EntryPoint for user operations).
  - `gasUsed` `string`
  - `gasFee` `string`
  - `l1GasUsed` `string`
  - `l1GasFee` `string`
  - `logs` `object[]`: The transaction's event logs. Present only with `expand=logs`.
    - `blockNumber` `number <double>` _(required)_
    - `blockHash` `string` _(required)_
    - `transactionIndex` `number <double>` _(required)_
    - `removed` `boolean` _(required)_
    - `address` `string` _(required)_
    - `data` `string` _(required)_
    - `topics` `string[]` _(required)_
    - `transactionHash` `string` _(required)_
    - `logIndex` `number <double>` _(required)_
    - `orphaned` `boolean`
  - `error` `object`: Present when the transaction reverted or failed.
    - `reason` `string` _(required)_: The error reason string returned by the bundler or execution environment.
    - `name` `string`: The decoded error name from the contract revert, if available.
    - `explanation` `object`: Detailed explanation of the error cause and suggested solution. Present only for known Account Abstraction error codes (AA10–AA99).
      - `cause` `string` _(required)_: A human-readable description of what caused the error.
      - `solution` `string` _(required)_: A human-readable suggestion for how to resolve the error.
- `timeline` `object[]`: Lifecycle history in order, present only with `expand=timeline`. Status-valued events come from this API's own records and always agree with `status`; monitoring-only events (`indexed`, `confirmed`, `dropped`, `replaced`, `expired`) come from the user-operation monitor, are best-effort, and are never present for plain EOA transactions.
  - `event` `string` _(required)_: Timeline events: every `TransactionStatusV2` value (a state change), plus monitoring-only events that refine a state without changing it. `status` always equals the last status-valued event.
  - `at` `integer <int32>`: Unix timestamp (seconds). Absent when the exact time is unknown (e.g. `submitted` for a transaction the monitor did not track).
- `costUsd` `string`: The actual transaction cost in USD, available after on-chain confirmation.

#### `400`: Request has invalid parameters.

Body (`application/json`):

- `error` `object` _(required)_
  - `type` `string` _(required)_
  - `message` `string` _(required)_
  - `details` `object`
  - `code` `string`: Machine-readable cause, when the thrower disambiguates one (e.g. funding_key_required).
  - `param` `string`: Offending request field path, when the thrower points at one (e.g. target.chain).

#### `401`: Error response.

Body (`application/json`):

- `error` `object` _(required)_
  - `type` `string` _(required)_
  - `message` `string` _(required)_
  - `details` `object`
  - `code` `string`: Machine-readable cause, when the thrower disambiguates one (e.g. funding_key_required).
  - `param` `string`: Offending request field path, when the thrower points at one (e.g. target.chain).

#### `409`: Error response.

Body (`application/json`):

- `error` `object` _(required)_
  - `type` `string` _(required)_
  - `message` `string` _(required)_
  - `details` `object`
  - `code` `string`: Machine-readable cause, when the thrower disambiguates one (e.g. funding_key_required).
  - `param` `string`: Offending request field path, when the thrower points at one (e.g. target.chain).

### Example request

```bash
curl https://api.openfort.io/v2/transactions \
  --request POST \
  --header 'Content-Type: application/json' \
  --data '{
  "chainId": 80002,
  "accountId": "acc_e1b24353-1741-4a3d-9e91-2b0fd2942f60",
  "feeSponsorshipId": "pol_7e07ae30-2a4d-48fa-803f-361da94905dd",
  "feeSponsorshipToken": "0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb",
  "calls": [
    {
      "to": "0x3994801f2BF191D22aA60c2ce3728c4D0e856a7B",
      "value": "1000000000000000000",
      "data": "string",
      "dataSuffix": "string",
      "contractId": "con_0cddb398-1dc6-4e6f-8726-9ec7cea85f35",
      "functionName": "mint",
      "functionArgs": []
    }
  ],
  "waitForReceipt": false,
  "authorization": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1c"
}'
```

```ts
fetch('https://api.openfort.io/v2/transactions', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    chainId: 80002,
    accountId: 'acc_e1b24353-1741-4a3d-9e91-2b0fd2942f60',
    feeSponsorshipId: 'pol_7e07ae30-2a4d-48fa-803f-361da94905dd',
    feeSponsorshipToken: '0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb',
    calls: [
      {
        to: '0x3994801f2BF191D22aA60c2ce3728c4D0e856a7B',
        value: '1000000000000000000',
        data: 'string',
        dataSuffix: 'string',
        contractId: 'con_0cddb398-1dc6-4e6f-8726-9ec7cea85f35',
        functionName: 'mint',
        functionArgs: []
      }
    ],
    waitForReceipt: false,
    authorization: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1c'
  })
})
```

## Get a transaction

`GET /v2/transactions/{id}`

Retrieves a transaction. Poll this endpoint until `status` is terminal
(`succeeded`, `reverted` or `failed`).

### Path parameters

- `id` `string` _(required)_: The transaction ID (starts with tin_).

### Query parameters

- `expand` `string[]`: Specifies the expandable fields.

### Responses

#### `200`: Successful response.

Body (`application/json`):

- `id` `string` _(required)_
- `object` `string` _(required)_
- `createdAt` `integer <int32>` _(required)_
- `updatedAt` `integer <int32>` _(required)_
- `chainId` `integer <int32>` _(required)_
- `status` `string` _(required)_
- `accountId` `string` _(required)_: ID of the account that executes the transaction (starts with `acc_`).
- `walletId` `string`: ID of the wallet that owns the account (starts with `pla_`). Absent for backend wallets.
- `feeSponsorshipId` `string`: ID of the fee sponsorship paying for gas (starts with `pol_`). Absent when the account pays its own gas.
- `account` `object`: The executing account. Present only with `expand=account`.
  - `id` `string` _(required)_
  - `wallet` `string` _(required)_
  - `accountType` `string` _(required)_
  - `address` `string` _(required)_
  - `ownerAddress` `string`
  - `chainType` `string` _(required)_
  - `chainId` `number <double>`
  - `createdAt` `number <double>` _(required)_
  - `updatedAt` `number <double>` _(required)_
  - `smartAccount` `object`
    - `implementationType` `string` _(required)_
    - `factoryAddress` `string`
    - `implementationAddress` `string` _(required)_
    - `salt` `string`
    - `deployedTx` `string`
    - `deployedAt` `number <double>`
    - `active` `boolean` _(required)_
    - `ownerAddress` `string`
    - `chainId` `number <double>`
  - `recoveryMethod` `string`
  - `recoveryMethodDetails` `object`
    - `passkeyId` `string`
    - `passkeyEnv` `object`
      - `name` `string`
      - `os` `string`
      - `osVersion` `string`
      - `device` `string`
  - `custody` `string` _(required)_: Indicates key custody: "Developer" for TEE managed keys, "User" for user-managed keys.
- `feeSponsorship` `object`: The fee sponsorship paying for gas. Present only with `expand=feeSponsorship`.
  - `id` `string` _(required)_
  - `object` `string` _(required)_
  - `createdAt` `integer <int32>` _(required)_
  - `name` `string | null` _(required)_: Name of the fee sponsorship policy.
  - `description` `string | null` _(required)_: Description or comment for the fee sponsorship.
  - `chainId` `integer | null` _(required)_: Chain ID for single-chain sponsorship.
  - `enabled` `boolean` _(required)_: Whether the policy is enabled.
  - `strategy` `object` _(required)_: Sponsorship strategy configuration.
    - `sponsorSchema` `string` _(required)_: The sponsorship schema type.
    - `tokenContract` `string`: Token contract ID for charge_custom_tokens or fixed_rate schemas (EVM).
    - `tokenContractAmount` `string`: Token amount for charge_custom_tokens or fixed_rate schemas (EVM).
    - `dynamicExchangeRate` `boolean`: Whether any accepted token is priced dynamically from cached prices. True when at least one token has no static amount. For per-token detail, read the amount on each tokenContracts entry.
    - `splTokens` `string[]`: SPL mint addresses accepted for fee payment on Solana charge_custom_tokens policies.
    - `tokenContracts` `object[]`: ERC-20 tokens accepted as user-pay fee for EVM charge_custom_tokens policies. Populated for both new (tokenContracts) and legacy (tokenContract) requests; legacy single-token policies appear as a 1-element array here.
      - `contract` `string` _(required)_: Token contract ID.
      - `amount` `string`: Static exchange rate, or undefined when the dynamic cached rate is used.
  - `paymasterId` `string | null` _(required)_: Paymaster ID (optional).
  - `forwarderContractId` `string | null` _(required)_: Forwarder contract ID (optional, for meta-transactions).
  - `policyId` `string | null` _(required)_: Linked policy ID for criteria-based transaction filtering.
- `calls` `object[]`: The calls this transaction executes.
  - `to` `string`: The address that receives the call. Use *only* for raw calls and native token transfers; a `pla_...` or `acc_...` id is converted to the corresponding address.
  - `value` `string`: The value sent with the call, as a stringified number in WEI (factor 10^18).
  - `data` `string`: Raw calldata (hex) for the call. Use instead of `contractId`/`functionName`.
  - `dataSuffix` `string`: Hex data appended to the encoded function call.
  - `contractId` `string`: ID of the contract the call interacts with. Must have been added to Openfort first, starts with `con_`.
  - `functionName` `string`: The function name of the contract. Accepts a function signature as well (e.g. mint(address)).
  - `functionArgs` `unknown[]`: The function arguments of the contract, formatted as strings.
- `execution` `object`: How the transaction is executed on-chain, discriminated by `type`: `userOperation` (ERC-4337 smart accounts, including EIP-7702 delegated accounts) or `transaction` (plain EOA transaction). Absent only when the transaction failed before it could be built (`status: "failed"`, see `receipt.error`).
- `nextAction` `object`: Present while `status` is `awaiting_signature`.
  - `type` `string` _(required)_
  - `hash` `string` _(required)_: Chain-agnostic hash to sign with the account's signer, then submit via `POST /v2/transactions/{id}/signature`.
- `receipt` `object`: Present once the transaction reached a terminal status.
  - `createdAt` `integer <int32>` _(required)_: Unix timestamp (seconds) when the receipt was recorded.
  - `transactionHash` `string`
  - `blockNumber` `integer <int32>`
  - `to` `string`: Address the transaction was sent to (the EntryPoint for user operations).
  - `gasUsed` `string`
  - `gasFee` `string`
  - `l1GasUsed` `string`
  - `l1GasFee` `string`
  - `logs` `object[]`: The transaction's event logs. Present only with `expand=logs`.
    - `blockNumber` `number <double>` _(required)_
    - `blockHash` `string` _(required)_
    - `transactionIndex` `number <double>` _(required)_
    - `removed` `boolean` _(required)_
    - `address` `string` _(required)_
    - `data` `string` _(required)_
    - `topics` `string[]` _(required)_
    - `transactionHash` `string` _(required)_
    - `logIndex` `number <double>` _(required)_
    - `orphaned` `boolean`
  - `error` `object`: Present when the transaction reverted or failed.
    - `reason` `string` _(required)_: The error reason string returned by the bundler or execution environment.
    - `name` `string`: The decoded error name from the contract revert, if available.
    - `explanation` `object`: Detailed explanation of the error cause and suggested solution. Present only for known Account Abstraction error codes (AA10–AA99).
      - `cause` `string` _(required)_: A human-readable description of what caused the error.
      - `solution` `string` _(required)_: A human-readable suggestion for how to resolve the error.
- `timeline` `object[]`: Lifecycle history in order, present only with `expand=timeline`. Status-valued events come from this API's own records and always agree with `status`; monitoring-only events (`indexed`, `confirmed`, `dropped`, `replaced`, `expired`) come from the user-operation monitor, are best-effort, and are never present for plain EOA transactions.
  - `event` `string` _(required)_: Timeline events: every `TransactionStatusV2` value (a state change), plus monitoring-only events that refine a state without changing it. `status` always equals the last status-valued event.
  - `at` `integer <int32>`: Unix timestamp (seconds). Absent when the exact time is unknown (e.g. `submitted` for a transaction the monitor did not track).
- `costUsd` `string`: The actual transaction cost in USD, available after on-chain confirmation.

#### `401`: Error response.

Body (`application/json`):

- `error` `object` _(required)_
  - `type` `string` _(required)_
  - `message` `string` _(required)_
  - `details` `object`
  - `code` `string`: Machine-readable cause, when the thrower disambiguates one (e.g. funding_key_required).
  - `param` `string`: Offending request field path, when the thrower points at one (e.g. target.chain).

#### `404`: Transaction not found.

Body (`application/json`):

- `error` `object` _(required)_
  - `type` `string` _(required)_
  - `message` `string` _(required)_
  - `details` `object`
  - `code` `string`: Machine-readable cause, when the thrower disambiguates one (e.g. funding_key_required).
  - `param` `string`: Offending request field path, when the thrower points at one (e.g. target.chain).

### Example request

```bash
curl 'https://api.openfort.io/v2/transactions/tin_48eeba57-2cd5-4159-a2cb-057a23a35e65?expand=account,timeline'
```

```ts
fetch('https://api.openfort.io/v2/transactions/tin_48eeba57-2cd5-4159-a2cb-057a23a35e65?expand=account,timeline')
```

## Estimate a transaction's gas cost

`POST /v2/transactions/estimate`

Estimates the gas cost of a transaction without sending it.

With a fee sponsorship that charges the user in an ERC-20 token, `feeInToken` is the estimated
amount of that token.

### Request body (required) (`application/json`)

- `chainId` `integer <int32>` _(required)_: The chain ID. Must be a [supported chain](https://www.openfort.io/docs/configuration/chains).
- `accountId` `string` _(required)_: ID of the account that executes the transaction (starts with `acc_`).
- `feeSponsorshipId` `string`: ID of the fee sponsorship that pays for gas (starts with `pol_`). Omit to pay gas from the account's native token balance.
- `feeSponsorshipToken` `string`: For a fee sponsorship that accepts several user-pay ERC-20 tokens, the on-chain address of the token the user pays the fee in. Must be one of the sponsorship's configured tokens on this chain.
- `calls` `object[]` _(required)_
  - `to` `string`: The address that receives the call. Use *only* for raw calls and native token transfers; a `pla_...` or `acc_...` id is converted to the corresponding address.
  - `value` `string`: The value sent with the call, as a stringified number in WEI (factor 10^18).
  - `data` `string`: Raw calldata (hex) for the call. Use instead of `contractId`/`functionName`.
  - `dataSuffix` `string`: Hex data appended to the encoded function call.
  - `contractId` `string`: ID of the contract the call interacts with. Must have been added to Openfort first, starts with `con_`.
  - `functionName` `string`: The function name of the contract. Accepts a function signature as well (e.g. mint(address)).
  - `functionArgs` `unknown[]`: The function arguments of the contract, formatted as strings.
- `waitForReceipt` `boolean`: Whether to hold the request until the transaction is mined and the `receipt` is available (default `true`). Set to `false` to respond as soon as the transaction is broadcast (`status: "submitted"`) and poll `GET /v2/transactions/{id}` for the outcome.
- `authorization` `string`: EIP-7702 signed authorization (hex) for a delegated account that is not yet delegated on-chain.

### Responses

#### `200`: Successful response.

Body (`application/json`):

- `gas` `string` _(required)_: Estimated gas.
- `gasPrice` `string` _(required)_: Gas price used for the estimation (wei).
- `fee` `string` _(required)_: Estimated fee in the chain's native token (wei).
- `feeUsd` `string` _(required)_: Estimated fee in USD.
- `feeInToken` `string`: Estimated fee in the sponsorship's ERC-20 token (token base units). Present for token-paying sponsorships.

#### `400`: Request has invalid parameters.

Body (`application/json`):

- `error` `object` _(required)_
  - `type` `string` _(required)_
  - `message` `string` _(required)_
  - `details` `object`
  - `code` `string`: Machine-readable cause, when the thrower disambiguates one (e.g. funding_key_required).
  - `param` `string`: Offending request field path, when the thrower points at one (e.g. target.chain).

#### `401`: Error response.

Body (`application/json`):

- `error` `object` _(required)_
  - `type` `string` _(required)_
  - `message` `string` _(required)_
  - `details` `object`
  - `code` `string`: Machine-readable cause, when the thrower disambiguates one (e.g. funding_key_required).
  - `param` `string`: Offending request field path, when the thrower points at one (e.g. target.chain).

### Example request

```bash
curl https://api.openfort.io/v2/transactions/estimate \
  --request POST \
  --header 'Content-Type: application/json' \
  --data '{
  "chainId": 80002,
  "accountId": "acc_e1b24353-1741-4a3d-9e91-2b0fd2942f60",
  "feeSponsorshipId": "pol_7e07ae30-2a4d-48fa-803f-361da94905dd",
  "feeSponsorshipToken": "0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb",
  "calls": [
    {
      "to": "0x3994801f2BF191D22aA60c2ce3728c4D0e856a7B",
      "value": "1000000000000000000",
      "data": "string",
      "dataSuffix": "string",
      "contractId": "con_0cddb398-1dc6-4e6f-8726-9ec7cea85f35",
      "functionName": "mint",
      "functionArgs": []
    }
  ],
  "waitForReceipt": false,
  "authorization": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1c"
}'
```

```ts
fetch('https://api.openfort.io/v2/transactions/estimate', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    chainId: 80002,
    accountId: 'acc_e1b24353-1741-4a3d-9e91-2b0fd2942f60',
    feeSponsorshipId: 'pol_7e07ae30-2a4d-48fa-803f-361da94905dd',
    feeSponsorshipToken: '0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb',
    calls: [
      {
        to: '0x3994801f2BF191D22aA60c2ce3728c4D0e856a7B',
        value: '1000000000000000000',
        data: 'string',
        dataSuffix: 'string',
        contractId: 'con_0cddb398-1dc6-4e6f-8726-9ec7cea85f35',
        functionName: 'mint',
        functionArgs: []
      }
    ],
    waitForReceipt: false,
    authorization: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1c'
  })
})
```

## Submit a transaction signature

`POST /v2/transactions/{id}/signature`

Submits the signature of `nextAction.hash` and broadcasts the transaction.

### Path parameters

- `id` `string` _(required)_: The transaction ID (starts with tin_).

### Request body (required) (`application/json`)

- `signature` `string` _(required)_: Signature of `nextAction.hash` by the account owner or a valid session key.
- `waitForReceipt` `boolean`: Whether to hold the request until the transaction is mined and the `receipt` is available (default `true`). Set to `false` to respond as soon as the transaction is broadcast (`status: "submitted"`) and poll `GET /v2/transactions/{id}` for the outcome.

### Responses

#### `200`: Successful response.

Body (`application/json`):

- `id` `string` _(required)_
- `object` `string` _(required)_
- `createdAt` `integer <int32>` _(required)_
- `updatedAt` `integer <int32>` _(required)_
- `chainId` `integer <int32>` _(required)_
- `status` `string` _(required)_
- `accountId` `string` _(required)_: ID of the account that executes the transaction (starts with `acc_`).
- `walletId` `string`: ID of the wallet that owns the account (starts with `pla_`). Absent for backend wallets.
- `feeSponsorshipId` `string`: ID of the fee sponsorship paying for gas (starts with `pol_`). Absent when the account pays its own gas.
- `account` `object`: The executing account. Present only with `expand=account`.
  - `id` `string` _(required)_
  - `wallet` `string` _(required)_
  - `accountType` `string` _(required)_
  - `address` `string` _(required)_
  - `ownerAddress` `string`
  - `chainType` `string` _(required)_
  - `chainId` `number <double>`
  - `createdAt` `number <double>` _(required)_
  - `updatedAt` `number <double>` _(required)_
  - `smartAccount` `object`
    - `implementationType` `string` _(required)_
    - `factoryAddress` `string`
    - `implementationAddress` `string` _(required)_
    - `salt` `string`
    - `deployedTx` `string`
    - `deployedAt` `number <double>`
    - `active` `boolean` _(required)_
    - `ownerAddress` `string`
    - `chainId` `number <double>`
  - `recoveryMethod` `string`
  - `recoveryMethodDetails` `object`
    - `passkeyId` `string`
    - `passkeyEnv` `object`
      - `name` `string`
      - `os` `string`
      - `osVersion` `string`
      - `device` `string`
  - `custody` `string` _(required)_: Indicates key custody: "Developer" for TEE managed keys, "User" for user-managed keys.
- `feeSponsorship` `object`: The fee sponsorship paying for gas. Present only with `expand=feeSponsorship`.
  - `id` `string` _(required)_
  - `object` `string` _(required)_
  - `createdAt` `integer <int32>` _(required)_
  - `name` `string | null` _(required)_: Name of the fee sponsorship policy.
  - `description` `string | null` _(required)_: Description or comment for the fee sponsorship.
  - `chainId` `integer | null` _(required)_: Chain ID for single-chain sponsorship.
  - `enabled` `boolean` _(required)_: Whether the policy is enabled.
  - `strategy` `object` _(required)_: Sponsorship strategy configuration.
    - `sponsorSchema` `string` _(required)_: The sponsorship schema type.
    - `tokenContract` `string`: Token contract ID for charge_custom_tokens or fixed_rate schemas (EVM).
    - `tokenContractAmount` `string`: Token amount for charge_custom_tokens or fixed_rate schemas (EVM).
    - `dynamicExchangeRate` `boolean`: Whether any accepted token is priced dynamically from cached prices. True when at least one token has no static amount. For per-token detail, read the amount on each tokenContracts entry.
    - `splTokens` `string[]`: SPL mint addresses accepted for fee payment on Solana charge_custom_tokens policies.
    - `tokenContracts` `object[]`: ERC-20 tokens accepted as user-pay fee for EVM charge_custom_tokens policies. Populated for both new (tokenContracts) and legacy (tokenContract) requests; legacy single-token policies appear as a 1-element array here.
      - `contract` `string` _(required)_: Token contract ID.
      - `amount` `string`: Static exchange rate, or undefined when the dynamic cached rate is used.
  - `paymasterId` `string | null` _(required)_: Paymaster ID (optional).
  - `forwarderContractId` `string | null` _(required)_: Forwarder contract ID (optional, for meta-transactions).
  - `policyId` `string | null` _(required)_: Linked policy ID for criteria-based transaction filtering.
- `calls` `object[]`: The calls this transaction executes.
  - `to` `string`: The address that receives the call. Use *only* for raw calls and native token transfers; a `pla_...` or `acc_...` id is converted to the corresponding address.
  - `value` `string`: The value sent with the call, as a stringified number in WEI (factor 10^18).
  - `data` `string`: Raw calldata (hex) for the call. Use instead of `contractId`/`functionName`.
  - `dataSuffix` `string`: Hex data appended to the encoded function call.
  - `contractId` `string`: ID of the contract the call interacts with. Must have been added to Openfort first, starts with `con_`.
  - `functionName` `string`: The function name of the contract. Accepts a function signature as well (e.g. mint(address)).
  - `functionArgs` `unknown[]`: The function arguments of the contract, formatted as strings.
- `execution` `object`: How the transaction is executed on-chain, discriminated by `type`: `userOperation` (ERC-4337 smart accounts, including EIP-7702 delegated accounts) or `transaction` (plain EOA transaction). Absent only when the transaction failed before it could be built (`status: "failed"`, see `receipt.error`).
- `nextAction` `object`: Present while `status` is `awaiting_signature`.
  - `type` `string` _(required)_
  - `hash` `string` _(required)_: Chain-agnostic hash to sign with the account's signer, then submit via `POST /v2/transactions/{id}/signature`.
- `receipt` `object`: Present once the transaction reached a terminal status.
  - `createdAt` `integer <int32>` _(required)_: Unix timestamp (seconds) when the receipt was recorded.
  - `transactionHash` `string`
  - `blockNumber` `integer <int32>`
  - `to` `string`: Address the transaction was sent to (the EntryPoint for user operations).
  - `gasUsed` `string`
  - `gasFee` `string`
  - `l1GasUsed` `string`
  - `l1GasFee` `string`
  - `logs` `object[]`: The transaction's event logs. Present only with `expand=logs`.
    - `blockNumber` `number <double>` _(required)_
    - `blockHash` `string` _(required)_
    - `transactionIndex` `number <double>` _(required)_
    - `removed` `boolean` _(required)_
    - `address` `string` _(required)_
    - `data` `string` _(required)_
    - `topics` `string[]` _(required)_
    - `transactionHash` `string` _(required)_
    - `logIndex` `number <double>` _(required)_
    - `orphaned` `boolean`
  - `error` `object`: Present when the transaction reverted or failed.
    - `reason` `string` _(required)_: The error reason string returned by the bundler or execution environment.
    - `name` `string`: The decoded error name from the contract revert, if available.
    - `explanation` `object`: Detailed explanation of the error cause and suggested solution. Present only for known Account Abstraction error codes (AA10–AA99).
      - `cause` `string` _(required)_: A human-readable description of what caused the error.
      - `solution` `string` _(required)_: A human-readable suggestion for how to resolve the error.
- `timeline` `object[]`: Lifecycle history in order, present only with `expand=timeline`. Status-valued events come from this API's own records and always agree with `status`; monitoring-only events (`indexed`, `confirmed`, `dropped`, `replaced`, `expired`) come from the user-operation monitor, are best-effort, and are never present for plain EOA transactions.
  - `event` `string` _(required)_: Timeline events: every `TransactionStatusV2` value (a state change), plus monitoring-only events that refine a state without changing it. `status` always equals the last status-valued event.
  - `at` `integer <int32>`: Unix timestamp (seconds). Absent when the exact time is unknown (e.g. `submitted` for a transaction the monitor did not track).
- `costUsd` `string`: The actual transaction cost in USD, available after on-chain confirmation.

#### `401`: Error response.

Body (`application/json`):

- `error` `object` _(required)_
  - `type` `string` _(required)_
  - `message` `string` _(required)_
  - `details` `object`
  - `code` `string`: Machine-readable cause, when the thrower disambiguates one (e.g. funding_key_required).
  - `param` `string`: Offending request field path, when the thrower points at one (e.g. target.chain).

#### `404`: Transaction not found.

Body (`application/json`):

- `error` `object` _(required)_
  - `type` `string` _(required)_
  - `message` `string` _(required)_
  - `details` `object`
  - `code` `string`: Machine-readable cause, when the thrower disambiguates one (e.g. funding_key_required).
  - `param` `string`: Offending request field path, when the thrower points at one (e.g. target.chain).

#### `409`: Error response.

Body (`application/json`):

- `error` `object` _(required)_
  - `type` `string` _(required)_
  - `message` `string` _(required)_
  - `details` `object`
  - `code` `string`: Machine-readable cause, when the thrower disambiguates one (e.g. funding_key_required).
  - `param` `string`: Offending request field path, when the thrower points at one (e.g. target.chain).

### Example request

```bash
curl https://api.openfort.io/v2/transactions/tin_48eeba57-2cd5-4159-a2cb-057a23a35e65/signature \
  --request POST \
  --header 'Content-Type: application/json' \
  --data '{
  "signature": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
  "waitForReceipt": false
}'
```

```ts
fetch('https://api.openfort.io/v2/transactions/tin_48eeba57-2cd5-4159-a2cb-057a23a35e65/signature', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    signature: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
    waitForReceipt: false
  })
})
```
