Explore the public API surface
This reference follows the current public Swagger scope. Every section below maps to the endpoints that are actually exposed to partner integrations today.
Authentication
Public Otto requests are authenticated with workspace-issued credentials. The API key identifies the workspace and the signature proves the payload integrity.
All public endpoints| Name | Type | Required | Description |
|---|---|---|---|
| X-API-Key | string | Yes | Workspace-issued public key. |
| X-Signature | string | Yes | Base64 HMAC-SHA256 of the serialized payload or query object. |
| Content-Type | application/json | POST/PATCH | Required for JSON bodies. |
Signing rules
- Sign the exact JSON body for POST and PATCH operations.
- Sign the exact query object for GET requests with parameters.
- Keep the private secret on trusted backends only.
Vaults
Vaults are the treasury boundary for wallet creation and downstream policy execution. The current public contract exposes creation and paginated listing.
/api/v1/vault/createBody
| Name | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Human-readable vault name. |
Response
{
"id": "2b2a7902-f7f1-4b0e-a00d-e8d8df2fa1a0",
"name": "Operating Treasury",
"createdAt": "2026-05-02T15:18:07.640Z",
"updatedAt": "2026-05-02T15:18:07.640Z",
"status": null,
"totalWallets": 0,
"totalBalance": "0",
"type": null,
"environment": "PRODUCTION",
"workspaceId": "6de239cb-cb42-4f01-9a8a-3d6ccff23858"
}/api/v1/dash/vaults/listQuery parameters
| Name | Type | Required | Description |
|---|---|---|---|
| page | number | No | Pagination index. Defaults to 1. |
| pageSize | number | No | Page size. Defaults to 10. |
Response
{
"vaults_list": [
{
"id": "2b2a7902-f7f1-4b0e-a00d-e8d8df2fa1a0",
"name": "Operating Treasury",
"createdAt": "2026-05-02T15:18:07.640Z",
"updatedAt": "2026-05-02T15:18:07.640Z",
"status": null,
"totalWallets": 3,
"totalBalance": 1245.22,
"totalBalanceDisplay": "$1,245.22",
"type": null,
"environment": "PRODUCTION",
"workspaceId": "6de239cb-cb42-4f01-9a8a-3d6ccff23858"
}
],
"pagination": {
"currentPage": 1,
"pageSize": 10,
"totalItems": 1,
"totalPages": 1
}
}Wallets
Wallet endpoints generate managed addresses, return balances, list inventories, and drive transfer preview and submission flows.
/api/v1/wallet/generate-address-hdBody
| Name | Type | Required | Description |
|---|---|---|---|
| network | string | Yes | Network slug such as ethereum. |
| vault_id | string | Yes | Parent vault identifier. |
| name | string | No | Optional wallet display label. |
Response
{
"id": "wallet_01H...",
"address": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F",
"network": "ethereum",
"vaultId": "vault_01H..."
}/api/v1/dash/wallets/listQuery parameters
| Name | Type | Required | Description |
|---|---|---|---|
| page | number | No | Pagination index. Defaults to 1. |
| pageSize | number | No | Page size. Defaults to 10. |
| vaultName | string | No | Filter by vault display name. |
| chainName | string | No | Filter by network or chain label. |
| address | string | No | Filter by wallet address. |
/api/v1/wallet/get-balanceBody
{
"network": "ethereum",
"address": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F"
}Response
{
"address": "0x71C7...",
"network": "ethereum",
"nativeBalance": "0.4821",
"tokens": []
}/api/v1/wallet/transfer-previewBody
{
"from": "0xSender",
"to": "0xReceiver",
"amount": "0.50",
"tokenAddress": null
}Response
{
"ready": true,
"network": "ethereum",
"asset": "ETH",
"estimatedFee": "0.00042"
}/api/v1/wallet/send-transactionBody
| Name | Type | Required | Description |
|---|---|---|---|
| network | string | Yes | Target network slug. |
| from | string | Yes | Managed source wallet address. |
| to | string | Yes | Destination address. |
| amount | number | Yes | Transfer amount in user-facing units. |
| tokenAddress | string | No | ERC-20 token address when sending tokens instead of native gas asset. |
Transactions
The public transaction surface is retrieval-heavy and complements execution with metrics, volume history, and paginated activity.
/api/v1/transaction/listQuery parameters
| Name | Type | Required | Description |
|---|---|---|---|
| page | number | No | Pagination index. Defaults to 1. |
| limit | number | No | Page size. Defaults to 20. |
Response
{
"items": [
{
"id": "8041d6ec-b5d3-4a07-859f-b1b77c2fd280",
"hash": "0x4ba2...",
"category": "transfer",
"status": "confirmed",
"amount": "0.5",
"rawAmount": "500000000000000000",
"amountUsd": 1240.33,
"assetSymbol": "ETH",
"networkId": "ethereum-mainnet",
"fromAddress": "0xSender",
"toAddress": "0xReceiver",
"timestamp": "2026-05-02T15:18:07.640Z"
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 1,
"totalPages": 1
}
}/api/v1/transaction/metricsQuery parameters
?from=2026-05-01T00:00:00.000Z
Response
{
"total_transactions": 14,
"daily_volume": 1240.33,
"weekly_volume": 8124.89,
"monthly_volume": 21522.14
}/api/v1/transaction/volume-historyQuery parameters
?from=2026-01-01T00:00:00.000Z
Response
{
"items": [
{
"key": "2026-01",
"label": "Jan",
"date": "2026-01-01T00:00:00.000Z",
"volumeUsd": 4200.22
},
{
"key": "2026-02",
"label": "Feb",
"date": "2026-02-01T00:00:00.000Z",
"volumeUsd": 5301.48
}
]
}Gas Station
Gas Station handles refill automation, target selection, and sponsor-oriented balance maintenance. The public surface includes both resource lifecycle and execution helpers.
/api/v1/gas-station/createBody
{
"name": "Mainnet sponsor",
"networkId": "ethereum-mainnet",
"threshold": 0.002,
"refillAmount": 0.01
}/available-networks · /list · /:id · /low-balance| Endpoint | Use | Notes |
|---|---|---|
| /gas-station/available-networks | List supported sponsor networks. | Environment-aware. |
| /gas-station/list | List configured gas stations. | Workspace-scoped. |
| /gas-station/:id | Fetch one configuration. | Use for detail views. |
| /gas-station/low-balance | Return wallets below threshold. | Accepts optional threshold. |
/refill · /processRefill body
| Name | Type | Required | Description |
|---|---|---|---|
| walletAddress | string | Yes | Wallet that should receive sponsored gas. |
| amount | number | No | Optional refill amount. |
| purpose | GAS | APPROVE | No | Explicit sponsor purpose. |
Response
{
"queued": true,
"walletAddress": "0xReceiver",
"purpose": "GAS"
}/vault/add · /vault/remove · /include-wallet · /exclude-wallet| Endpoint | Body | Use |
|---|---|---|
| /gas-station/:id/vault/add | { vaultId } | Include all wallets from a vault. |
| /gas-station/:id/vault/remove | { vaultId } | Detach a vault scope. |
| /gas-station/:id/include-wallet | { walletId } | Force-include one wallet. |
| /gas-station/:id/exclude-wallet | { walletId } | Force-exclude one wallet. |
| /gas-station/:id/add-target | { walletId } | Add a direct sponsor target. |
| /gas-station/:id/remove-target | { walletId } | Remove a direct sponsor target. |
MPC Wallets
MPC resources support wallet creation, session orchestration, signer participation, and coordinated approvals.
/wallets · /wallets/:walletId · /sessions · /participants| Endpoint | Use | Notes |
|---|---|---|
| /mpc-security/wallets | List MPC wallets. | Workspace + environment scoped. |
| /mpc-security/wallets/:walletId | Fetch one MPC wallet. | Use for signer and threshold inspection. |
| /mpc-security/sessions | List signing sessions. | Operational history. |
| /mpc-security/participants | List available participants. | Useful before wallet creation. |
/api/v1/mpc-security/walletsBody
{
"networkId": "ethereum-mainnet",
"name": "Treasury MPC",
"threshold": 2,
"participants": [
{ "type": "USER", "workspaceMemberId": "member_01H..." },
{ "type": "SERVER", "publicKey": "server-public-key" }
]
}Response
{
"id": "mpc_wallet_01H...",
"threshold": 2,
"participants": 2,
"networkId": "ethereum-mainnet"
}/sessions · /sessions/:sessionId/start · /sessions/:sessionId/signCreate session body
{
"walletId": "mpc_wallet_01H...",
"networkId": "ethereum-mainnet",
"to": "0xReceiver",
"amount": "0.5",
"assetSymbol": "ETH",
"assetAddress": null
}Sign body
{
"participantId": "participant_01H..."
}Webhooks
Webhooks let integrators react to wallet and transaction state changes without relying on polling loops everywhere.
/metrics · /list · /find/:id| Endpoint | Use | Notes |
|---|---|---|
| /webhook/metrics | Read delivery metrics. | Workspace scoped. |
| /webhook/list | List configured webhooks. | Operational inventory. |
| /webhook/find/:id | Fetch one webhook. | Use for edit and audit flows. |
/create · /updateBody
{
"url": "https://example.com/webhooks/otto",
"eventTypes": ["transaction.completed", "wallet.low_balance"],
"secret": "optional-shared-secret"
}Delete
DELETE /api/v1/webhook/delete/:id
Response
{
"id": "e48cb1cc-c6a7-42c3-b0bc-b517cb7727f8",
"url": "https://example.com/webhooks/otto",
"eventTypes": ["transaction.completed", "wallet.low_balance"],
"isActive": true,
"secret": "optional-shared-secret",
"name": null,
"createdAt": "2026-05-02T15:18:07.640Z",
"updatedAt": "2026-05-02T15:18:07.640Z",
"environment": "PRODUCTION",
"workspaceId": "6de239cb-cb42-4f01-9a8a-3d6ccff23858"
}Delivery payload
{
"eventType": "transaction.completed",
"payload": {
"transactionId": "8041d6ec-b5d3-4a07-859f-b1b77c2fd280",
"hash": "0x4ba2...",
"status": "confirmed",
"workspaceId": "6de239cb-cb42-4f01-9a8a-3d6ccff23858"
}
}Delivery headers
Content-Type: application/json X-Webhook-Id: b56b7d87-5ecf-4ec3-aed8-bd5ae8ab902e X-Webhook-Secret: optional-shared-secret
Errors
Public API consumers should separate authentication, permission, validation, and transient failures in both retry logic and monitoring.
HTTP status families| Status | Meaning | Typical cause |
|---|---|---|
| 400 / 422 | Invalid request or business validation failure. | Malformed payload, missing fields, bad address, unsupported asset, or rule violation. |
| 401 | Authentication failure. | Wrong API key or invalid signature. |
| 403 | Permission failure. | Role, policy, assignment, environment gate, or signer restriction. |
| 404 | Resource not found. | Unknown gas station, webhook, wallet, or MPC resource ID. |
| 5xx | Server-side failure. | Transient backend or infrastructure problem. |
403 is usually not something you should blindly retry. It is a policy signal: the integration is outside the allowed execution scope.Policy controls
Otto Wallets keeps policy authoring inside the dashboard and admin surfaces, not in the public API. Integrators consume the result of that governance through runtime behavior: approvals, limits, signer thresholds, vault restrictions, and assignment checks.
- Use the API and SDK assuming permissions may differ per workspace, vault, or signer.
- Treat
403as a policy signal, not only an auth failure. - Configure policies, roles, and assignments in the Otto Wallets dashboard before enabling production automation.
Supported chains
Otto Wallets already supports multiple execution environments, but chain activation is gated per workspace. Production-grade access should be requested before you plan a live rollout.
- EVM networks
- Solana
- Bitcoin
- TRON