Reference
Errors
Muny uses conventional HTTP status codes and returns a consistent JSON error body you can branch on.
Error body#
422 Unprocessable Entity
{
"error": {
"type": "invalid_request_error",
"code": "invalid_address",
"message": "recipient: Must be a valid Solana address",
"request_id": "req_8f2c1a9b4d7e",
"details": [{ "path": ["recipient"], "message": "Must be a valid Solana address" }]
}
}Branch on type and code; message is for humans and may change. Always log request_id — it is also returned in the x-request-id header.
Error types#
| Type | Status | Meaning |
|---|---|---|
invalid_request_error | 400 / 422 | The request is malformed or failed validation. |
authentication_error | 401 | Missing, invalid, expired or revoked credentials. |
permission_error | 403 | Authenticated, but the role or key scope doesn't allow this. |
not_found_error | 404 | The resource doesn't exist or belongs to another organization. |
idempotency_error | 409 | The idempotency key was reused with a different body, or is still in progress. |
conflict_error | 409 | The resource is in a state that doesn't allow this action. |
rate_limit_error | 429 | Too many requests. Back off and retry. |
risk_error | 422 | Blocked by limits or risk checks. |
api_error | 500 | Something went wrong on our side. Safe to retry with the same idempotency key. |
Common codes#
| Code | Type | What to do |
|---|---|---|
invalid_address | invalid_request_error | Check the recipient is a base58 Solana address. |
insufficient_funds | invalid_request_error | Fund the wallet, or wait for queued payouts to settle. |
amount_exceeds_limit | risk_error | The amount is above your per-payout limit. |
daily_limit_exceeded | risk_error | Your organization's daily payout limit would be exceeded. |
idempotency_key_reused | idempotency_error | Use a new key for a different payout. |
idempotency_key_in_progress | idempotency_error | Retry after a short delay. |
invalid_transition | conflict_error | E.g. cancelling a payout that is already processing. |
wallet_cannot_sign | invalid_request_error | The funding wallet is an external, watch-only wallet. |
Handling errors with the SDK#
ts
import { MunyError } from "@muny/sdk";
try {
await muny.payouts.create({ recipient, amount: "500" });
} catch (err) {
if (err instanceof MunyError && err.code === "insufficient_funds") {
await alertFinanceTeam(err.requestId);
} else {
throw err;
}
}