Skip to content
WealthMgr Docs

Rate Limits & Errors

Error response format

All API errors return a JSON body with an error field describing the problem:

{
  "error": "name is required"
}

For validation errors with multiple fields, the message may list all issues in a single string.

HTTP status codes

StatusMeaningCommon causes
200 OKRequest succeededGET requests
201 CreatedResource createdClean transaction or account insert
202 AcceptedSaved, flagged for reviewTransaction matched a soft duplicate — inserted but marked for review
204 No ContentDeletion succeededDELETE /api/transactions/:id, DELETE /api/accounts/:id
400 Bad RequestInvalid requestMissing or malformed body fields; PATCH with no editable fields, or account balance in the body (balances are app-side anchors, not API-editable)
401 UnauthorizedNot authenticatedMissing or invalid API key
403 ForbiddenNot authorizedFree-tier key (API requires Starter+), or the method/path is outside the API-key allowlist (PUT is never allowed — partial updates are PATCH)
404 Not FoundResource not foundWrong ID, or resource belongs to another user
409 ConflictDuplicate or guarded mutationTransaction matches an existing one on all fields — not inserted. Also returned by corrections (WEA-368): editing/deleting an initial_balance anchor or price_revaluation row, a pocket-allocated money edit/delete, an account type flip with ledger history, or deleting an account still referenced by transactions/pockets/rules/alerts. (POST /api/accounts has no duplicate detection: a retried account create returns 201 and makes a second account — keep returned ids.)
422 Unprocessable EntityCloud sync requiredThe account has no per-user cloud database yet — the API reads/writes it
429 Too Many RequestsRate limit exceededSee rate limits below
500 Internal Server ErrorServer errorRetry with backoff; if persistent, contact support

Rate limits

Rate limits are applied per user: a monthly call quota and a token-bucket rate limit.

PlanMonthly API callsRate limit (requests/second)
Freenone (403)—
Starter1,0002
Growth3,00010
Enterprise50,00050

Exceeding the per-second bucket returns 429 Too Many Requests with a Retry-After header; exceeding the monthly quota returns 402 Payment Required { error, tier, limit, used }.

HTTP/1.1 429 Too Many Requests
Retry-After: 15
Content-Type: application/json

{
  "error": "Rate limit exceeded. Retry after 15 seconds."
}

Tip

Implement exponential backoff in your integration: start with the `Retry-After` value and double the wait on each subsequent 429 response, capped at 60 seconds.

Handling 401 errors

A 401 Unauthorized response means your key is missing or invalid. Check:

  1. The Authorization header is present: Authorization: Bearer <your-api-key>.
  2. The key has not been revoked (check Settings → API Keys).
  3. The key belongs to the correct user account.

Handling 500 errors

Transient 500 errors can occur during deploys or brief outages. Retry up to 3 times with exponential backoff (1s, 2s, 4s). If the error persists, the issue is likely in your request — check the request body and headers.

Pagination

Pagination is available on GET /api/transactions (limit up to 200, offset). Other list endpoints (e.g. GET /api/accounts) return all rows in one response.

CORS

The API allows cross-origin requests from trusted origins. For direct browser-to-API calls from your own domain, contact support to add your domain to the CORS allowlist. Server-side requests (from your backend) work without CORS configuration.

API versioning

The API is currently unversioned (all paths are /api/...). A versioned prefix (/api/v1/...) will be introduced with the stable release. Migration guides will be published when versioning is introduced.