Skip to content

Using the REST API

The MoneyLights REST API lets your own systems read and maintain your organization’s data: transactions, vendors, clients, projects, categories and cashflow. You authenticate with an API key.

Send your key in the X-API-Key header:

GET /api/transactions HTTP/1.1
Host: api.moneylights.app
X-API-Key: ml_sk_<key-id>_<secret>

Authorization: ApiKey <key> also works. Authorization: Bearer <key> does not — Bearer belongs to the browser session. Never put the key in the URL: such requests are refused before they reach anything.

The complete, always-current list of what your key can reach is the public OpenAPI document:

GET https://api.moneylights.app/api/public/openapi.json

It is generated from the running application and lists exactly the published endpoints, each annotated with the scope it requires (x-required-scope). If this guide and that document ever disagree, the document is right. You can feed it to a client generator or import it into an API tool.

Only endpoints that were explicitly published are part of the public API. The guiding rule is enrich and maintain, never destroy:

  • You can list and filter transactions, assign them a category, vendor, client, project or person allocations, and create or update vendors, clients, projects and categories.
  • You cannot delete a vendor, client, project or category through the API. Removing a record other records point at is a decision a script should not make unattended — those actions live in the app.

Bank connections, billing, team management and API-key management are never reachable with a key, whatever scopes it holds.

Three limits apply, and a request must satisfy all of them:

PlanReads/min per keyWrites/min per keyRequests/min per organizationPer day, per organization
Team1203012010 000
Enterprise600150600100 000

The organization-wide per-minute limit is the one to design around. It is the same number as the per-key limit, so one key running flat out can consume the whole organization’s minute — adding keys does not buy throughput. If you run several integrations, pace them.

Every response carries X-RateLimit-Limit and X-RateLimit-Remaining. A 429 carries Retry-After in seconds — honour it; retrying immediately is how a rate limit becomes an outage.

Refusals carry a stable code you can switch on. The ones you will actually meet:

CodeMeaning
api_key_invalidMalformed, unknown, or wrong secret
api_key_expiredPast its expiry date — create a new key
api_key_revokedThe key was cut, or a rotated secret lapsed
api_key_scope_missingThe key lacks the scope this endpoint needs
api_key_endpoint_not_publishedThe endpoint is not part of the public API
api_key_rate_limitedOver a limit — honour Retry-After

A request with no key at all gets a plain 401 with no code — treat a bodyless 401 as “I forgot the header”.

  • Your key reaches exactly one organization — the one it was issued for. It cannot be pointed anywhere else.
  • Usage figures are indicative. “Last used” and the request count answer “is this still in use?”, not billing questions.
  • Prefer the API for data flows, and the MCP Server when the caller is an AI assistant — same credential, same scopes.