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

# Smart Accounts API

> Gasless deposits, redemptions, and withdrawals over a managed smart account

## Overview

The Smart Accounts API lets you give your users a **gasless** deposit and
redemption experience without ever handling a private key or paying gas on their
behalf. Each user gets a deterministic smart account (Kernel v3.1) derived from
their EOA; once the user signs a one-time, per-chain authorization, you submit
buy / sell / withdraw actions through 1tx and a relayer executes and sponsors the
gas.

This is the **white-label / relay** integration: your server authenticates with
an `x-api-key` and names the `ownerEoa` it is acting for. The same routes also
back the first-party 1tx app (Privy bearer token); this page documents the
API-key path.

<Note>
  All Smart Accounts endpoints require an `x-api-key` header. No bearer token is
  needed. An action can only target an `ownerEoa` your key has authorized — the
  session grant created at authorize time is bound to your API key.
</Note>

### How it works

1. **Derive the account.** `GET /account` returns the user's counterfactual
   smart-account address (the same on every chain).
2. **Authorize, once per chain.** `POST /authorize/prepare` returns an EIP-712
   message; your user signs it with their EOA wallet; `POST /authorize/confirm`
   stores the scoped session grant. The user signs **once per chain**, not per
   action.
3. **Fund the smart account.** The user sends USDC to the smart-account address.
   Deposits draw from this balance.
4. **Act, gasless.** `POST /buy` and `POST /sell` are relayer-signed — no
   per-action signature, no gas. Poll `GET /actions/:id` for status.
5. **Withdraw.** `POST /withdraw/prepare` + `confirm` return idle USDC to the
   user's EOA. The recipient is always pinned to the owner EOA.

<Note>
  The owner signs only at **authorize** and **withdraw** time. Buy and sell never
  require a user signature once a chain is authorized.
</Note>

### Base URL

```
https://api.1tx.fi/api/v1
```

***

## Look Up Account

<span style={{color: '#10B981', fontWeight: 'bold'}}>GET</span> `/account`

Resolve a user's smart-account address and authorization state.

### Query Parameters

| Param      | Type   | Required | Description            |
| ---------- | ------ | -------- | ---------------------- |
| `ownerEoa` | string | Yes      | The user's EOA address |

```bash theme={null}
curl "https://api.1tx.fi/api/v1/account?ownerEoa=0x59F84Af036712AFe2fD0Ec77f4D9a6F0a612f1fE" \
  -H "x-api-key: <your_api_key>"
```

### Response

```json theme={null}
{
  "accountAddress": "0x8a3...c21",
  "deployedChains": [8453],
  "authorizedChainIds": [8453, 42161],
  "grant": {
    "status": "active",
    "scope": { "policyVersion": 3 },
    "expiresAt": "2026-09-01T00:00:00.000Z"
  }
}
```

| Field                | Type           | Description                                                        |
| -------------------- | -------------- | ------------------------------------------------------------------ |
| `accountAddress`     | string         | Counterfactual smart-account address (same on all chains)          |
| `deployedChains`     | number\[]      | Chains where the account is already deployed on-chain              |
| `authorizedChainIds` | number\[]      | Chains with an active session grant on the current policy          |
| `grant`              | object \| null | The active grant summary, or `null` if the user must (re)authorize |

***

## Authorize a Chain

Establish a scoped session grant so the relayer can submit gasless actions for
the user on a given chain. **One signature per chain.**

### Prepare

<span style={{color: '#EAB308', fontWeight: 'bold'}}>POST</span> `/authorize/prepare`

Returns an EIP-712 message for the user to sign with their EOA wallet.

| Field       | Type   | Required | Description                                                                |
| ----------- | ------ | -------- | -------------------------------------------------------------------------- |
| `ownerEoa`  | string | Yes      | The user's EOA address                                                     |
| `chainId`   | number | No       | Chain to authorize. Defaults to Base (8453)                                |
| `spendCap`  | string | No       | Per-period spend cap in USDC subunits (6dp) baked into the on-chain policy |
| `expiresAt` | number | No       | Unix timestamp when the grant expires                                      |
| `scope`     | object | No       | Advanced: override the default call-policy scope                           |

```bash theme={null}
curl -X POST "https://api.1tx.fi/api/v1/authorize/prepare" \
  -H "x-api-key: <your_api_key>" \
  -H "Content-Type: application/json" \
  -d '{ "ownerEoa": "0x59F8...f1fE", "chainId": 8453 }'
```

```json theme={null}
{
  "accountAddress": "0x8a3...c21",
  "chainId": 8453,
  "enableTypedData": {
    "domain": { "name": "Kernel", "version": "0.3.1", "chainId": 8453, "verifyingContract": "0x..." },
    "types": { "Enable": [ /* ... */ ] },
    "primaryType": "Enable",
    "message": { /* ... */ }
  }
}
```

Have the user sign `enableTypedData` with `eth_signTypedData_v4` on the EOA
wallet. The wallet must be connected to `chainId` when signing.

### Confirm

<span style={{color: '#EAB308', fontWeight: 'bold'}}>POST</span> `/authorize/confirm`

Submit the signature to activate the grant.

| Field       | Type   | Required | Description                                               |
| ----------- | ------ | -------- | --------------------------------------------------------- |
| `ownerEoa`  | string | Yes      | The user's EOA address                                    |
| `signature` | string | Yes      | The `eth_signTypedData_v4` signature of `enableTypedData` |
| `chainId`   | number | No       | The chain that was authorized (matches `prepare`)         |

```bash theme={null}
curl -X POST "https://api.1tx.fi/api/v1/authorize/confirm" \
  -H "x-api-key: <your_api_key>" \
  -H "Content-Type: application/json" \
  -d '{ "ownerEoa": "0x59F8...f1fE", "chainId": 8453, "signature": "0x..." }'
```

```json theme={null}
{ "accountAddress": "0x8a3...c21" }
```

### Revoke

<span style={{color: '#EF4444', fontWeight: 'bold'}}>DELETE</span> `/authorize/:ownerEoa`

Off-chain revoke: the relayer stops replaying the session approval. Optionally
scope to one chain with `?chainId=`.

```bash theme={null}
curl -X DELETE "https://api.1tx.fi/api/v1/authorize/0x59F8...f1fE?chainId=8453" \
  -H "x-api-key: <your_api_key>"
```

```json theme={null}
{ "accountAddress": "0x8a3...c21" }
```

***

## Buy (Gasless Deposit)

<span style={{color: '#EAB308', fontWeight: 'bold'}}>POST</span> `/buy`

Submit a relayer-signed, gas-sponsored deposit into an instrument. Requires an
active grant on the source chain and sufficient USDC in the smart account. For a
cross-chain buy the relayer bridges via CCTP automatically.

### Request Body

| Field            | Type    | Required | Description                                                                                                       |
| ---------------- | ------- | -------- | ----------------------------------------------------------------------------------------------------------------- |
| `ownerEoa`       | string  | Yes      | The user's EOA address                                                                                            |
| `instrumentId`   | string  | Yes      | Target instrument ID                                                                                              |
| `amountUsdc`     | string  | Yes      | Deposit amount in human-readable USDC, e.g. `"100.50"`                                                            |
| `sourceChainId`  | number  | No       | Force a source chain instead of auto-selecting from the account's balances                                        |
| `slippageBps`    | number  | No       | Slippage tolerance in basis points. Defaults to `50`                                                              |
| `fastTransfer`   | boolean | No       | Cross-chain only: CCTP fast transfer (\~seconds, higher fee) vs standard (free, \~10–30 min). Defaults to `false` |
| `maxFee`         | string  | No       | Cross-chain fast-transfer max fee in USDC subunits (6dp). Required when `fastTransfer` is `true`                  |
| `referralFeeBps` | number  | No       | Referral fee in basis points (0–500). Requires `referralWallet`                                                   |
| `referralWallet` | string  | No       | Address that receives the referral fee                                                                            |
| `idempotencyKey` | string  | No       | A retry with the same key returns the original action instead of submitting a second userOp                       |

```bash theme={null}
curl -X POST "https://api.1tx.fi/api/v1/buy" \
  -H "x-api-key: <your_api_key>" \
  -H "Content-Type: application/json" \
  -d '{
    "ownerEoa": "0x59F84Af036712AFe2fD0Ec77f4D9a6F0a612f1fE",
    "instrumentId": "0x0000a4b194d4938ed6aab5bdbac7ca4b622f3639b1bca1b8b9c3271403d3b1b5",
    "amountUsdc": "100.50",
    "idempotencyKey": "user-123-deposit-7f3a"
  }'
```

### Response

```json theme={null}
{
  "accountAddress": "0x8a3...c21",
  "actionId": "op_7f3a9c2e",
  "userOpHash": "0x..."
}
```

| Field            | Type    | Description                                                           |
| ---------------- | ------- | --------------------------------------------------------------------- |
| `accountAddress` | string  | The smart account the action ran on                                   |
| `actionId`       | string  | Pass to `GET /actions/:id` to track status                            |
| `userOpHash`     | string  | The submitted ERC-4337 userOp hash                                    |
| `idempotent`     | boolean | Present and `true` when a prior action with the same key was returned |

***

## Sell (Gasless Redeem)

<span style={{color: '#EAB308', fontWeight: 'bold'}}>POST</span> `/sell`

Submit a relayer-signed redemption of a position. Same-chain only; USDC proceeds
land in the smart account (use `/withdraw` to send them to the EOA).

### Request Body

| Field              | Type   | Required | Description                                                     |
| ------------------ | ------ | -------- | --------------------------------------------------------------- |
| `ownerEoa`         | string | Yes      | The user's EOA address                                          |
| `instrumentId`     | string | Yes      | Instrument ID to redeem from                                    |
| `yieldTokenAmount` | string | Yes      | Human-readable yield-token amount, e.g. `"95.5"`                |
| `slippageBps`      | number | No       | Slippage tolerance in basis points. Defaults to `50`            |
| `referralFeeBps`   | number | No       | Referral fee in basis points (0–500). Requires `referralWallet` |
| `referralWallet`   | string | No       | Address that receives the referral fee                          |
| `idempotencyKey`   | string | No       | Retry-safe key, as in `/buy`                                    |

```bash theme={null}
curl -X POST "https://api.1tx.fi/api/v1/sell" \
  -H "x-api-key: <your_api_key>" \
  -H "Content-Type: application/json" \
  -d '{
    "ownerEoa": "0x59F84Af036712AFe2fD0Ec77f4D9a6F0a612f1fE",
    "instrumentId": "0x00002105c053a3e1290845e12a3eea14926472ce7f15da324cdf0700056fc04b",
    "yieldTokenAmount": "95.5"
  }'
```

```json theme={null}
{
  "accountAddress": "0x8a3...c21",
  "actionId": "op_be21d4f0",
  "userOpHash": "0x..."
}
```

***

## Get Action Status

<span style={{color: '#10B981', fontWeight: 'bold'}}>GET</span> `/actions/:id`

Track a submitted buy, sell, or withdraw by its `actionId`.

```bash theme={null}
curl "https://api.1tx.fi/api/v1/actions/op_7f3a9c2e" \
  -H "x-api-key: <your_api_key>"
```

### Response

```json theme={null}
{
  "operationId": "op_7f3a9c2e",
  "type": "buy",
  "status": "success",
  "createdAt": 1775747400,
  "updatedAt": 1775747460,
  "sourceChainId": 8453,
  "destinationChainId": 8453,
  "isCrossChain": false,
  "userOpHash": "0x...",
  "sourceTxHash": "0x...",
  "destinationTxHash": null,
  "error": null,
  "result": {
    "amountIn": "100500000",
    "amountOut": "100500000",
    "instrumentId": "0x0000a4b1...",
    "finalTxHash": "0x..."
  }
}
```

| `status`            | Meaning                                                                                 |
| ------------------- | --------------------------------------------------------------------------------------- |
| `success`           | Completed (same-chain, or cross-chain fully settled)                                    |
| `confirming_source` | Cross-chain userOp landed; awaiting CCTP bridge settlement                              |
| `failed`            | The userOp reverted. `error` carries the reason; the idempotency key is freed for retry |

<Tip>
  For cross-chain buys, after `confirming_source` you can also follow the bridge
  via the [CCTP API](/api-reference/endpoints/cctp) using `sourceTxHash`.
</Tip>

***

## Withdraw to Owner EOA

Return idle USDC from the smart account to the user's own EOA. The recipient is
**always** the owner EOA — it is never caller-supplied — so the user signs a
userOp digest that commits to that calldata.

### Prepare

<span style={{color: '#EAB308', fontWeight: 'bold'}}>POST</span> `/withdraw/prepare`

| Field        | Type   | Required | Description                                   |
| ------------ | ------ | -------- | --------------------------------------------- |
| `ownerEoa`   | string | Yes      | The user's EOA address (also the recipient)   |
| `amountUsdc` | string | Yes      | Amount in human-readable USDC                 |
| `chainId`    | number | No       | Chain to withdraw on. Defaults to Base (8453) |

```bash theme={null}
curl -X POST "https://api.1tx.fi/api/v1/withdraw/prepare" \
  -H "x-api-key: <your_api_key>" \
  -H "Content-Type: application/json" \
  -d '{ "ownerEoa": "0x59F8...f1fE", "amountUsdc": "50.00", "chainId": 8453 }'
```

```json theme={null}
{
  "accountAddress": "0x8a3...c21",
  "chainId": 8453,
  "digest": "0x...",
  "signingMethod": "personal_sign"
}
```

Have the user sign the raw `digest` with an EIP-191 `personal_sign`
(e.g. `signMessage({ message: { raw: digest } })`) and return the 65-byte
signature unchanged.

### Confirm

<span style={{color: '#EAB308', fontWeight: 'bold'}}>POST</span> `/withdraw/confirm`

| Field       | Type   | Required | Description                               |
| ----------- | ------ | -------- | ----------------------------------------- |
| `ownerEoa`  | string | Yes      | The user's EOA address                    |
| `signature` | string | Yes      | The `personal_sign` signature of `digest` |

```bash theme={null}
curl -X POST "https://api.1tx.fi/api/v1/withdraw/confirm" \
  -H "x-api-key: <your_api_key>" \
  -H "Content-Type: application/json" \
  -d '{ "ownerEoa": "0x59F8...f1fE", "signature": "0x..." }'
```

```json theme={null}
{ "actionId": "op_c93b71a2", "userOpHash": "0x..." }
```

Track completion with `GET /actions/:id`.

***

## End-to-End Flow

1. `GET /account` → show the user their smart-account address and which chains
   are authorized.
2. For each chain the user wants to use: `POST /authorize/prepare` → user signs
   EIP-712 → `POST /authorize/confirm`.
3. User funds the smart-account address with USDC.
4. `POST /buy` → poll `GET /actions/:id` until `success` (or `confirming_source`
   then settled, for cross-chain).
5. `POST /sell` to redeem; `POST /withdraw/prepare` + `confirm` to move USDC back
   to the EOA.

<Note>
  Cross-chain **sell** is not supported. To move a position across chains, redeem
  on its chain and withdraw, or buy fresh on the target chain.
</Note>
