Documentation Index Fetch the complete documentation index at: https://docs.moneda.com/llms.txt
Use this file to discover all available pages before exploring further.
The Moneda REST API provides 43 endpoints organized by domain. All endpoints use JSON request/response bodies and require an OAuth 2.0 Bearer token unless noted otherwise.
Write endpoints that involve money — like initiating payments — always require your confirmation in the Moneda app before anything happens.
Base URL
https://api.moneda.com/v1
All endpoints are prefixed with /v1. Include your Bearer token in the Authorization header:
curl -H "Authorization: Bearer YOUR_TOKEN" https://api.moneda.com/v1/balances
Response shape: ?view=full vs ?view=lite
Every GET /v1/* endpoint accepts an optional view query parameter that selects the response shape. This lets LLM agents and terminals consume a compact version of each response without dropping existing integrations.
viewDefault Use case full✅ Back-compat — every field the service exposes. Existing integrations keep working unchanged. lite— Smaller response with optional metadata, coaching fields, derived counts, and empty/null optionals dropped. Designed for LLM agents and CLI rendering.
On a typical support-chatbot turn mix, ?view=lite reduces response payloads by ~20–80% per endpoint (see the per-endpoint notes below). The difference is most dramatic on /v1/wallet, /v1/virtual-accounts, and the balance snapshot-fallback path, where the full shape carries UI coaching text that an LLM reasoning about “how much do I have” doesn’t need.
lite is a strict subset of fields with two renames:
balances[].accountName → balances[].type (on /v1/balances, for semantic clarity)
points_activity[].createdAt → points_activity[].date
Empty arrays, empty objects, null, and "" are also dropped from the response body on every lite call — 0, false, and "0" are preserved (balance of zero is a real answer). This is a minor shape change on lite only; the full shape is unchanged.
Example:
# Full (default)
curl https://api.moneda.com/v1/wallet -H "Authorization: Bearer $TOKEN "
# → {"smartAccountAddress":"0x...","network":"Base","supportedTokens":[...],
# "username":"@alice","warning":"...","tip":"..."}
# Lite
curl 'https://api.moneda.com/v1/wallet?view=lite' -H "Authorization: Bearer $TOKEN "
# → {"smartAccountAddress":"0x...","username":"@alice"}
Routes whose response is already minimal (/v1/health, /v1/exchange-rates, /v1/points/balance, /v1/settings, knowledge search) ignore view because there’s nothing to trim.
Health
GET /v1/health
Server health check. No authentication required.
Response
{
"status" : "ok" ,
"uptime" : 12345 ,
"version" : "1.0.0"
}
Balances & Finances
GET /v1/balances
Returns your account balances. Scope: read:balances
Query parameters
Parameter Type Required Description currencyUSD | EUR | CHFNo Filter by currency viewfull | liteNo Response shape selector. Default full. See above .
Response (full)
{
"source" : "snapshot" ,
"balances" : [
{
"accountName" : "USD Account" ,
"currency" : "USD" ,
"type" : "LOCAL" ,
"balance" : "1250.50"
},
{
"accountName" : "EUR Account" ,
"currency" : "EUR" ,
"type" : "LOCAL" ,
"balance" : "890.25"
}
],
"snapshotTimestamp" : "2026-03-07T10:30:00.000Z" ,
"snapshotAge" : "2 minutes ago"
}
Response (?view=lite)
Drops source, snapshotTimestamp, and notice. On the snapshot-fallback path only, collapses all 4 metadata fields to one optional stale field. Renames accountName → type per row.
{
"balances" : [
{ "currency" : "USD" , "type" : "USD Account" , "balance" : "1250.50" },
{ "currency" : "EUR" , "type" : "EUR Account" , "balance" : "890.25" }
],
"stale" : "2 minutes ago"
}
GET /v1/transactions
Returns your transaction history with powerful filtering. Scope: read:transactions
Query parameters
Parameter Type Required Description currencyUSD | EUR | CHFNo Filter by currency typestring No Filter by exact transaction type (e.g. TRANSFER, SWAP) typeGroupstring No Filter by group: transfer, exchange, deposit, withdrawal, earnings, topup, offramp categorystring No Filter by spending category (e.g. GROCERIES, TRAVEL) statusCOMPLETED | PENDING | FAILED | allNo Default: COMPLETED + COMPLETED_DELAYED. all to include every status. directionincoming | outgoing | exchangeNo Filter by transaction direction relative to the user counterpartystring No Search by counterparty username, wallet name, address, or external provider transactionHashstring No Exact hash lookup (with or without 0x prefix, case-insensitive). Returns at most one row. searchstring No Free-text substring search over note + reference fields startDateISO 8601 No Filter from date endDateISO 8601 No Filter until date yearnumber No Filter by year (overrides startDate/endDate) minAmountnumber No Minimum amount filter maxAmountnumber No Maximum amount filter hasNotetrue | falseNo Filter by whether transactions have a note hasCategorytrue | falseNo Filter by whether transactions have a category sortnewest | oldest | amount_desc | amount_ascNo Default: newest limitnumber No Max 50, default 5 offsetnumber No Pagination offset viewfull | liteNo Response shape selector. Default full. See above .
Response (full)
{
"data" : [
{
"transactionHash" : "0xabc...123" ,
"typeGroup" : "Transfers" ,
"type" : "TRANSFER" ,
"category" : "Friends & Family" ,
"note" : "Dinner split" ,
"direction" : "outgoing" ,
"amount" : "25.00" ,
"currency" : "USD" ,
"status" : "COMPLETED" ,
"counterparty" : {
"type" : "user" ,
"username" : "@alice"
},
"date" : "2026-03-06T18:30:00.000Z"
}
],
"count" : 1 ,
"limit" : 5 ,
"offset" : 0
}
Exchange transactions include additional fields:
{
"direction" : "exchange" ,
"amount" : "0" ,
"exchanged" : "100.00" ,
"exchangedCurrency" : "USD" ,
"received" : "92.15" ,
"receivedCurrency" : "EUR"
}
Counterparty types
Type Fields Description self— Self-transfer (swap, deposit, withdrawal) userusernameMoneda user providernameService provider (Coinbase, etc.) bankname, iban, account, routingBank transfer walletname, addressExternal wallet unknownaddressUnknown source
Response (?view=lite)
Drops typeGroup, type, category, note, reference, exchanged*, received*, and counterparty raw address/iban/account/routing (already masked, still unused by LLM agents). Keeps hash, direction, amount, currency, status, date, and the trimmed counterparty. Per row ≈40–50 % smaller.
{
"data" : [
{
"hash" : "0xabc...123" ,
"direction" : "outgoing" ,
"amount" : "25.00" ,
"currency" : "USD" ,
"status" : "COMPLETED" ,
"date" : "2026-03-06T18:30:00.000Z" ,
"counterparty" : { "type" : "user" , "username" : "@alice" }
}
],
"count" : 1 ,
"limit" : 5 ,
"offset" : 0
}
GET /v1/transactions/{hash}
Single-resource lookup by transaction hash. Scope: read:transactions
Path parameters
Parameter Type Description hashstring Transaction hash (with or without 0x prefix, case-insensitive)
Query parameters
Parameter Type Required Description viewfull | liteNo Default full. Pass lite for the compact shape when you don’t need typeGroup/category/note/reference/raw routing.
Returns a single transaction (same shape as the list items above). 404 if not found or not owned by this user.
GET /v1/spending/by-type-group
Spending grouped by transaction type group (formerly /v1/spending/summary). Scope: read:spending
Query parameters
Parameter Type Required Description period7d | 30d | 90dNo Default: 30d currencyUSD | EURNo Filter by currency
Response
{
"period" : "30d" ,
"since" : "2026-02-05T00:00:00.000Z" ,
"typeGroups" : [
{
"typeGroup" : "transfer" ,
"name" : "Transfers" ,
"count" : 12 ,
"total" : "450.00"
}
],
"totalSpent" : "1250.00" ,
"transactionCount" : 28
}
GET /v1/exchange-rates
Current USD/EUR exchange rate. Scope: read:rates
Query parameters
Parameter Type Required Description fromUSD | EURNo Default: USD toUSD | EURNo Default: EUR
Response
{
"from" : "USD" ,
"to" : "EUR" ,
"rate" : "0.9215" ,
"updatedAt" : "2026-03-07T10:00:00.000Z"
}
GET /v1/apy-rates
Current earnings APY rates. Scope: read:earnings
Query parameters
Parameter Type Required Description currencyUSD | EURNo Filter by currency
Response
[
{
"product" : "Morpho USDC Vault" ,
"currency" : "USD" ,
"apyPercent" : "4.25" ,
"updatedAt" : "2026-03-07T00:00:00.000Z"
}
]
Account Info
GET /v1/wallet
Your smart wallet address on Base. Scope: read:account
Query parameters
Parameter Type Required Description viewfull | liteNo Default full. lite drops network, supportedTokens, warning, tip.
Response (full)
{
"smartAccountAddress" : "0x1234...abcd" ,
"network" : "Base" ,
"supportedTokens" : [ "USDC" , "EURC" , "CHFAU" ],
"username" : "@john" ,
"warning" : "Never send tokens on other networks to this address." ,
"tip" : "This is your Base smart account address. Only send USDC, EURC, or CHFAU on the Base network."
}
Response (?view=lite) — ~76% smaller
{ "smartAccountAddress" : "0x1234...abcd" , "username" : "@john" }
GET /v1/virtual-accounts
IBAN and ACH virtual account details for receiving transfers. Scope: read:virtual_accounts
Query parameters
Parameter Type Required Description viewfull | liteNo Default full. lite drops capabilityInfo, minimumTransfer, firstPartyPayments, thirdPartyPayments, and the per-account type discriminator.
Response (full)
{
"status" : "active" ,
"accounts" : {
"eur" : {
"type" : "IBAN" ,
"iban" : "DE89370400440532013000" ,
"minimumTransfer" : "1.00"
},
"usd" : {
"type" : "ACH" ,
"accountNumber" : "1234567890" ,
"routingNumber" : "021000021" ,
"minimumTransfer" : "1.00"
}
}
}
Status can be active, pending, or not_registered.
Response (?view=lite) — ~78% smaller
{
"status" : "active" ,
"accounts" : {
"eur" : { "iban" : "DE89370400440532013000" },
"usd" : { "accountNumber" : "1234567890" , "routingNumber" : "021000021" }
}
}
GET /v1/accounts
Your saved external wallets and bank accounts. Scope: read:external_accounts
Query parameters
Parameter Type Required Description viewfull | liteNo Default full. lite drops walletCount, bankCount, wallet address, wallet provider.
Response (full)
{
"wallets" : [
{
"accountId" : "acc_123" ,
"name" : "MetaMask" ,
"address" : "0xabcd...1234" ,
"provider" : "EXTERNAL"
}
],
"bankAccounts" : [
{
"id" : "bank_456" ,
"holderName" : "John Doe" ,
"bankName" : "Deutsche Bank" ,
"iban" : "DE89****3000" ,
"country" : "DE"
}
],
"walletCount" : 1 ,
"bankCount" : 1
}
Your saved contacts (Moneda users, external wallets, and bank accounts). Scope: read:contacts
Query parameters
Parameter Type Required Description searchstring No Search by name, username, or address limitnumber No Max results offsetnumber No Pagination offset
Response
{
"monedaContacts" : [
{
"type" : "user" ,
"username" : "@alice" ,
"displayName" : "Alice Smith" ,
"isExternal" : false ,
"lastInteraction" : "2026-03-06T12:00:00.000Z"
}
],
"walletContacts" : [
{
"type" : "wallet" ,
"contactAccountId" : "acc_789" ,
"name" : "Alice's MetaMask" ,
"address" : "0xdef...5678"
}
],
"bankContacts" : [
{
"type" : "bank" ,
"contactAccountId" : "acc_012" ,
"name" : "Alice's Bank" ,
"bankName" : "N26" ,
"iban" : "DE89****3000" ,
"country" : "DE"
}
],
"monedaUsers" : 1 ,
"wallets" : 1 ,
"bankAccounts" : 1
}
GET /v1/settings
Your app preferences. Scope: read:settings
Response
{
"language" : "en" ,
"currency" : "USD" ,
"country" : "US" ,
"phone" : "+1****7890" ,
"phoneCountryCode" : "+1" ,
"theme" : "LIGHT" ,
"notifications" : {
"email" : true ,
"inApp" : true
},
"biometrics" : true ,
"animations" : true ,
"decimalSeparator" : "DOT" ,
"hideBalances" : false
}
GET /v1/passkeys
Your authentication passkeys. Scope: read:passkeys
Response
{
"passkeys" : [
{
"provider" : "iCloud Keychain" ,
"status" : "active" ,
"address" : "0x12...ab" ,
"createdAt" : "2026-01-15T10:00:00.000Z"
}
],
"count" : 1
}
Your recovery guardians. Scope: read:recovery
Response
{
"myContacts" : [
{
"username" : "@alice" ,
"displayName" : "Alice Smith" ,
"imageUrl" : null ,
"status" : "accepted" ,
"addedAt" : "2026-02-01T10:00:00.000Z"
}
],
"myContactsCount" : 1 ,
"recoveryContactOf" : [
{
"username" : "@bob" ,
"displayName" : "Bob Jones" ,
"imageUrl" : null ,
"status" : "accepted" ,
"addedAt" : "2026-02-15T10:00:00.000Z"
}
],
"recoveryContactOfCount" : 1
}
Recovery emails (ZK email recovery)
The recovery-emails endpoints surface the email addresses set up for ZK email-based account recovery. Mutations (invite, accept, recover) require a passkey-signed UserOp from the mobile app and are not exposed over REST.
All four endpoints share the read:recovery scope and accept an optional accountId query parameter — when omitted, the call defaults to the authenticated user’s main LOCAL account.
GET /v1/recovery-emails
List recovery emails set up for the account.
Query parameters
Parameter Type Required Description accountIdUUID No Defaults to the user’s main LOCAL account. viewfull | liteNo Default full. lite drops notes and irrelevant timestamps.
Response
{
"recoveryEmails" : [
{
"id" : "g-abc123" ,
"email" : "alice@example.com" ,
"weight" : 100 ,
"status" : "accepted" ,
"invitedAt" : "2026-01-01T00:00:00.000Z" ,
"acceptedAt" : "2026-01-02T00:00:00.000Z" ,
"declinedAt" : null ,
"removedAt" : null ,
"notes" : null
}
],
"count" : 1
}
When no recovery emails are configured, the response includes a friendly message field instead of an empty array.
GET /v1/recovery-emails/{id}
Single recovery email lookup by id. 404 if not found or not owned by this user (unified to prevent existence leakage).
Path parameters
Parameter Type Description idUUID Recovery email id (zkRecoveryGuardian.id)
Query parameters
Parameter Type Required Description viewfull | liteNo Default full.
Returns the same shape as the list rows, plus the on-chain accountAddress the email protects.
GET /v1/recovery-config
Recovery configuration for an account: accepted recovery emails, total weight, and the threshold required to approve a recovery.
Query parameters
Parameter Type Required Description accountIdUUID No Defaults to the user’s main LOCAL account. viewfull | liteNo Default full. lite adds fullySet: boolean and drops accountAddress + per-row id / acceptedAt.
Response
{
"accountAddress" : "0x1234...abcd" ,
"recoveryEmails" : [
{
"id" : "g-abc123" ,
"email" : "alice@example.com" ,
"weight" : 100 ,
"acceptedAt" : "2026-01-02T00:00:00.000Z"
}
],
"totalWeight" : 100 ,
"threshold" : 100
}
The threshold is a fixed value (currently 100) that must match the on-chain Universal Email Recovery Module configuration. Recovery is approvable when totalWeight >= threshold.
GET /v1/recovery-status
Most recent recovery request snapshot for the account. Reads from the database only — agents tolerate the slight lag while the cron job syncs on-chain state. The mobile app additionally polls on-chain.
Query parameters
Parameter Type Required Description accountIdUUID No Defaults to the user’s main LOCAL account. viewfull | liteNo Default full.
Response (no recovery in flight)
{ "hasActiveRecovery" : false }
Response (recovery in flight)
{
"hasActiveRecovery" : true ,
"recovery" : {
"id" : "r-xyz789" ,
"status" : "threshold_met" ,
"createdAt" : "2026-04-01T00:00:00.000Z" ,
"executeAfter" : "2026-04-02T00:00:00.000Z" ,
"executeBefore" : "2026-04-09T00:00:00.000Z" ,
"threshold" : 100 ,
"totalRecoveryEmails" : 1 ,
"approvedCount" : 1 ,
"approvedWeight" : 100 ,
"approvedBy" : [
{ "email" : "a***@example.com" , "weight" : 100 , "approvedAt" : "2026-04-01T01:00:00.000Z" }
],
"pending" : [],
"isExecutable" : true ,
"timeUntilExecutable" : 0 ,
"cancelledAt" : null ,
"completedAt" : null ,
"expiredAt" : null
}
}
hasActiveRecovery is true only for the active states (initiated, threshold_met, executing); terminal states (cancelled, completed, expired, failed) flip it back to false while the latest recovery details are still returned for context. Recovery email addresses are anonymized to first-letter***@domain in the active payload.
Notifications
GET /v1/notifications
Paginated in-app notifications inbox, newest first. Scope: read:notifications
Query parameters
Parameter Type Required Description cursorUUID No Id of the last notification from the previous page. limitnumber No Page size, max 50, default 20. filterall | unreadNo Default all. Pass unread to scope to unread items.
Response
{
"notifications" : [
{
"id" : "n-abc123" ,
"type" : "TRANSFER_RECEIVED" ,
"deepLink" : "moneda://tx/0xabc" ,
"metadata" : { "amount" : "100" , "currency" : "USD" },
"isRead" : false ,
"createdAt" : "2026-04-01T00:00:00.000Z"
}
],
"nextCursor" : "n-abc123"
}
nextCursor is omitted on the last page. metadata shape varies by type — agents should treat it as opaque unless they recognise the type. Mark-as-read / dismiss / clear-all are tied to the active mobile push session and stay in tRPC; the REST surface is read-only.
GET /v1/notifications/unread-count
Unread notification count. Scope: read:notifications
Response
Sub-accounts (vaults)
Sub-accounts (a.k.a. vaults) are nested Safe smart accounts owned by your main account. The endpoints below are read-only — vault create / top-up / withdraw / freeze / close all require a passkey-signed UserOp from the mobile app.
All endpoints require the read:sub_accounts scope.
GET /v1/sub-accounts
List the user’s sub-accounts.
Query parameters
Parameter Type Required Description includeClosedboolean No Default false. Pass true to include archived vaults. viewfull | liteNo Default full.
Response
{
"subAccounts" : [
{
"id" : "sa-abc123" ,
"name" : "Travel fund" ,
"status" : "ACTIVE" ,
"type" : "VAULT" ,
"address" : "0xchild...safe" ,
"createdAt" : "2026-02-01T10:00:00.000Z"
}
]
}
GET /v1/sub-accounts/{id}
Single sub-account detail by id.
Path parameters
Parameter Type Description idUUID Sub-account id
Returns the full sub-account shape including parent + child Safe addresses, members, deployment index, and close timestamp.
GET /v1/sub-accounts/{id}/balance
On-chain balances for a sub-account’s child Safe.
Path parameters
Parameter Type Description idUUID Sub-account id
Query parameters
Parameter Type Required Description currencyUSDC | EURC | CHFAUNo Filter to a single token. Omit for every enabled currency. viewfull | liteNo Default full.
Balances are returned as raw bigint strings (6 decimals).
GET /v1/wealth
Aggregate wealth across the main account + every live vault. Scope: read:balances + read:sub_accounts.
Query parameters
Parameter Type Required Description viewfull | liteNo Default full.
Returns per-leg breakdown (wallet + Morpho + YO for the main account; wallet-only for vaults) plus per-currency totals. USDC and EURC are cross-converted using the on-chain Aerodrome rate.
Sessions
API key authentication produces sessions tracked in the database for audit trails. Bearer-token (OAuth) requests don’t create sessions.
POST /v1/sessions
Create a session record (typically called by clients that hold long-lived API keys). Scope: depends on the calling channel.
Request body
{
"deviceName" : "moneda-cli" ,
"platform" : "darwin"
}
Response
{
"sessionId" : "ses_abc123" ,
"createdAt" : "2026-04-01T00:00:00.000Z"
}
DELETE /v1/sessions/{sessionId}
End a session.
Path parameters
Parameter Type Description sessionIdUUID Session id from the create response
Returns 204 No Content on success.
Points & Referrals
GET /v1/points/balance
Your points balance. Scope: read:points
Response
GET /v1/points/activity
Points earning history. Scope: read:points
Query parameters
Parameter Type Required Description limitnumber No Max results offsetnumber No Pagination offset
Response
{
"data" : [
{
"actionType" : "REFERRAL_BONUS" ,
"points" : 500 ,
"description" : "Referred a friend" ,
"createdAt" : "2026-03-01T10:00:00.000Z"
}
],
"count" : 1 ,
"limit" : 10 ,
"offset" : 0
}
GET /v1/referrals/code
Your referral link and stats. Scope: read:referrals
First call for a new user lazily enrolls them into GrowSurf (get-or-create). Subsequent calls are pure reads.
Response
{
"code" : "abc123" ,
"link" : "https://moneda.com/ref?grsf=abc123" ,
"referralCount" : 5
}
GET /v1/referrals/referees
Friends you’ve referred. Scope: read:referrals
Response
{
"referees" : [
{
"name" : "Alice" ,
"email" : "" ,
"status" : "referred" ,
"referredAt" : "2026-02-20T10:00:00.000Z"
}
],
"count" : 1
}
Knowledge Base
These endpoints are public — no authentication required.
GET /v1/knowledge/search
Search the FAQ knowledge base.
Query parameters
Parameter Type Required Description querystring No Search query categorystring No Filter by category slug limitnumber No Max results
Response
{
"query" : "transfer fees" ,
"totalMatches" : 3 ,
"returned" : 3 ,
"results" : [
{
"id" : "faq_001" ,
"question" : "Are there fees for transfers?" ,
"answer" : "Moneda does not charge fees for transfers between Moneda users..." ,
"category" : "Transfers"
}
]
}
GET /v1/knowledge/categories/
Browse a FAQ category by slug.
Path parameters
Parameter Type Required Description slugstring Yes Category slug (e.g. transfers, security)
Response
{
"category" : "Transfers" ,
"slug" : "transfers" ,
"itemCount" : 8 ,
"items" : [
{
"id" : "faq_001" ,
"question" : "Are there fees for transfers?" ,
"answer" : "..." ,
"category" : "Transfers"
}
]
}
GET /v1/knowledge/items/
Get a specific FAQ item.
Path parameters
Parameter Type Required Description idstring Yes FAQ item ID
Response
{
"id" : "faq_001" ,
"question" : "Are there fees for transfers?" ,
"answer" : "Moneda does not charge fees for transfers between Moneda users..." ,
"category" : "Transfers" ,
"categorySlug" : "transfers" ,
"relatedItems" : [
{
"id" : "faq_002" ,
"question" : "How long do transfers take?" ,
"category" : "Transfers"
}
]
}
Users
GET /v1/users/search
Search Moneda users by username or display name. Scope: read:users
Query parameters
Parameter Type Required Description querystring Yes Search query
Response
{
"users" : [
{
"username" : "@alice" ,
"displayName" : "Alice Smith"
}
],
"count" : 1
}
Write Endpoints
PATCH /v1/profile
Update your display name. Scope: write:profile
Request body
{
"displayName" : "John Doe"
}
Response
PATCH /v1/transactions//category
Assign a spending category to a transaction. Scope: write:transactions
Path parameters
Parameter Type Required Description idstring Yes Transaction hash
Request body
{
"category" : "GROCERIES"
}
Valid categories: TOP_UP, INVESTMENT, FRIENDS_FAMILY, INTEREST_EARNINGS, SUBSCRIPTIONS, SERVICES, GROCERIES, SHOPPING, RESTAURANTS, TRANSPORT, TRAVEL, UTILITIES, CASH, SALARY, FUEL, EV_CHARGING, GAMBLING, CHARITY_DONATIONS, TAXES, INSURANCE, CARD, HEALTHCARE, GENERAL
Response
PATCH /v1/transactions//note
Add or update a note on a transaction. Scope: write:transactions
Path parameters
Parameter Type Required Description idstring Yes Transaction hash
Request body
{
"note" : "Dinner at Luigi's"
}
Response
POST /v1/transactions/batch/categories
Categorize up to 25 transactions at once. Scope: write:transactions
Request body
{
"updates" : [
{ "transactionHash" : "0xabc...123" , "category" : "GROCERIES" },
{ "transactionHash" : "0xdef...456" , "category" : "TRAVEL" }
]
}
Response
{
"succeeded" : 2 ,
"failed" : 0
}
POST /v1/transactions/batch/notes
Add notes to up to 25 transactions at once. Scope: write:transactions
Request body
{
"updates" : [
{ "transactionHash" : "0xabc...123" , "note" : "Weekly groceries" },
{ "transactionHash" : "0xdef...456" , "note" : "Flight to Paris" }
]
}
Response
{
"succeeded" : 2 ,
"failed" : 0
}
POST /v1/accounts/wallets
Save an external crypto wallet. Scope: write:external_accounts
Request body
{
"walletName" : "MetaMask" ,
"walletAddress" : "0x1234567890abcdef1234567890abcdef12345678" ,
"confirmed" : true
}
Set confirmed: false first to check for warnings (e.g. if the address belongs to another Moneda user). Then resend with confirmed: true to proceed.
Response
{
"success" : true ,
"wallet" : {
"id" : "acc_123" ,
"name" : "MetaMask" ,
"address" : "0x1234...5678" ,
"network" : "Base" ,
"supportedTokens" : [ "USDC" , "EURC" ]
}
}
Or if confirmation is needed:
{
"success" : false ,
"requiresConfirmation" : true ,
"message" : "This address belongs to a Moneda user. Are you sure you want to add it as an external wallet?"
}
POST /v1/accounts/banks
Save a bank account (EU IBAN or US ACH). Scope: write:external_accounts
Request body (EU)
{
"firstName" : "John" ,
"lastName" : "Doe" ,
"country" : "DE" ,
"iban" : "DE89370400440532013000" ,
"bic" : "COBADEFFXXX" ,
"confirmed" : true
}
Request body (US)
{
"firstName" : "John" ,
"lastName" : "Doe" ,
"country" : "US" ,
"accountNumber" : "1234567890" ,
"routingNumber" : "021000021" ,
"accountType" : "CHECKING" ,
"confirmed" : true
}
Response
{
"success" : true ,
"bankAccount" : {
"id" : "bank_456" ,
"holderName" : "John Doe" ,
"country" : "DE" ,
"iban" : "DE89****3000"
}
}
POST /v1/payments
Initiate a payment. Requires approval in the Moneda app. Scope: write:payments
Payments are not executed immediately. After calling this endpoint, the user must approve the payment in the Moneda mobile app within 5 minutes.
Request body
{
"paymentType" : "transfer_moneda" ,
"amount" : "50.00" ,
"currency" : "USD" ,
"recipientUsername" : "@alice" ,
"reference" : "Dinner split"
}
Payment types
Type Required fields Description transfer_monedarecipientUsernameSend to a Moneda user transfer_accountaccountIdSend to a saved external account transfer_contact_bankcontactUsername, contactAccountIdSend to a contact’s bank account transfer_contact_walletcontactUsername, contactAccountIdSend to a contact’s wallet
Response
{
"paymentRequestId" : "pr_abc123" ,
"status" : "PENDING_APPROVAL" ,
"amount" : "50.00" ,
"currency" : "USD" ,
"recipient" : "@alice" ,
"paymentType" : "transfer_moneda" ,
"expiresAt" : "2026-03-07T10:35:00.000Z" ,
"message" : "Payment request created. Please approve in your Moneda app within 5 minutes." ,
"nextStep" : "Open the Moneda app to approve this payment." ,
"pollAfterMs" : 3000
}
GET /v1/payments//status
Check the status of a payment request. Scope: write:payments
Path parameters
Parameter Type Required Description idstring Yes Payment request ID (UUID)
Response
{
"paymentRequestId" : "pr_abc123" ,
"status" : "COMPLETED" ,
"amount" : "50.00" ,
"currency" : "USD" ,
"recipient" : "@alice" ,
"paymentType" : "transfer_moneda" ,
"expiresAt" : "2026-03-07T10:35:00.000Z" ,
"message" : "Payment completed successfully." ,
"transactionHash" : "0xabc...123"
}
Payment statuses : PENDING_APPROVAL, APPROVED, COMPLETED, FAILED, EXPIRED, REJECTED
Error Responses
All errors follow a consistent format:
{
"code" : "UNAUTHORIZED" ,
"message" : "Invalid or missing Bearer token" ,
"retryable" : false
}
Error codes
Code HTTP Status Description UNAUTHORIZED401 Invalid or missing Bearer token INSUFFICIENT_SCOPE403 Token lacks the required scope NOT_FOUND404 Resource not found RESOURCE_NOT_OWNED403 Resource belongs to another user VALIDATION_ERROR422 Invalid request parameters RATE_LIMIT_EXCEEDED429 Too many requests (60/min per IP) INTERNAL_ERROR500 Unexpected server error SERVICE_UNAVAILABLE503 Downstream service temporarily unavailable
What’s next?
Authentication Learn how to authenticate your API requests.
OpenAPI Spec Explore the API interactively with Swagger UI.
Scopes See which scopes each endpoint requires.
CLI Tool Use these endpoints from the command line with the Moneda CLI.