API Reference
Full endpoint documentation
Base URL: https://business.madhousewallet.com
Authentication: Authorization: Bearer mw_live_<keyId>_<secret>
Content-Type: application/json
Interactive API docs are available at https://developer.madhousewallet.com.
All successful responses are returned as JSON. Rate limits are per API key.
MCP Server
Endpoint: https://mcp.madhousewallet.com/
Madhouse Wallet offers a hosted Model Context Protocol (MCP) server that exposes the payouts API as a set of tools your AI agents can call directly. Instead of hand-wiring HTTP requests, an MCP-compatible client (Claude, Cursor, or any agent framework) can discover and invoke wallet actions — fetching quotes, managing recipients, and initiating transfers — through a single connection.
Use it to let AI agents:
Look up account requirements and create recipients
Request locked FX quotes
Initiate and track USDC off-ramp transfers
Programmatically orchestrate payouts as part of an agentic workflow
Authentication uses the same mw_live_<keyId>_<secret> API keys described above.
For setup instructions, the full tool catalog, and client configuration, see https://mcp.madhousewallet.com/.
Recipients
GET /api/payouts/recipients
List all recipients for the authenticated account.
Rate limit: 30 req/min
Response:
POST /api/payouts/recipients
Create a new payout recipient.
Rate limit: 30 req/min
Request body:
Use GET /api/payouts/account-requirements first to determine the correct type and required details fields for each currency.
Response:
GET /api/payouts/recipients/:id
Fetch a single recipient by ID.
Rate limit: 30 req/min
DELETE /api/payouts/recipients/:id
Delete a recipient. Returns 409 Conflict if a transfer for this recipient is in a non-terminal status.
Rate limit: 30 req/min
Account Requirements
GET /api/payouts/account-requirements
Fetch required fields for creating a recipient in a target currency.
Rate limit: 60 req/min
Query parameters:
source
string
Source currency (e.g. USD)
target
string
Target fiat currency (e.g. KES)
sourceAmount
number
Amount in source currency
Response (array of requirement types):
Fields with refreshRequirementsOnChange: true (e.g. legalType) require a follow-up POST to this endpoint with the current form state to receive updated field lists.
POST /api/payouts/account-requirements
Refresh requirements after a refreshRequirementsOnChange field changes.
Rate limit: 60 req/min
Request body:
Quotes
GET /api/payouts/quote
Get a locked FX quote. Valid for 5 minutes.
Rate limit: 20 req/min
Query parameters:
targetCurrency
string
Target fiat currency (e.g. KES)
sourceAmount
number
USD amount to send
Response:
Pass quoteId to POST /api/payouts/transfer within the 5-minute window.
Transfers
POST /api/payouts/transfer
Initiate a USDC off-ramp transfer.
Rate limit: 5 req/min
Request body:
quote_id
string
Yes
From GET /api/payouts/quote
source_wallet
string
Yes
Ethereum address (0x...) sending the USDC
amount
number
Yes
USD amount (must match quote ±$0.01)
recipientId
number
Yes
From POST /api/payouts/recipients
customer_uuid
string
No
Your own idempotency key (prevents duplicates on retry)
Response:
Send exactly amount USDC from source_wallet to escrow_wallet before expires_at.
Error codes:
400
Invalid input or stale/mismatched quote
403
Recipient not owned by this account
409
Duplicate customer_uuid
429
Rate limit exceeded
POST /api/payouts/transfer/cancel
Cancel a transfer before USDC has been sent.
Rate limit: 20 req/min
Request body:
Returns 409 if the transfer has already received a deposit.
GET /api/payouts/transfer/:id
Get transfer status from the database snapshot.
Rate limit: 30 req/min
GET /api/payouts/transfer-status/:id
Get transfer status with live quote data and recipient details fetched in real time.
Rate limit: 30 req/min
Response:
Rate Limits
Rate limits are per API key. Headers are included on every response:
When exceeded, the API returns 429 Too Many Requests. Back off and retry after X-RateLimit-Reset.
Errors
All errors follow the format:
400
Bad request — check input parameters
401
Invalid or missing API key
403
Forbidden — resource not owned by this account
404
Resource not found
409
Conflict — duplicate or in-flight transfer
429
Rate limit exceeded
500
Internal server error — contact support
Last updated
Was this helpful?