Skip to main content
The Sintropix API is a JSON over HTTPS interface to the system that owns your ledger, your invoices, your bank movements, and your reports. Every business route is scoped to a single Entity (a legal company with its own books) and authenticated with an API key. Requests and responses are validated end to end, so field names, types, and enums are consistent across endpoints.

Base URL

All routes are mounted under the /api prefix:
The API is not versioned in the URL path.

Route Shape

Most business resources live under a single Entity:
For example:
A handful of routes are Entity-independent: /api/entities (list and create), /api/organizations, /api/fx-rates, /api/countries and /api/currencies, /api/onboarding/* (Superadmin only), /api/feedback, and /api/health. Data an Organization’s Entities share lives under the Organization instead, such as its Partners, Dimensions, and Integrations:
{entityId} is always a UUID. A request for an Entity the caller cannot access returns 404, never 403, so probing does not reveal whether an unknown Entity exists.

Access and roles

Access to an Entity comes from an Organization Membership. An Organization groups the Entities a client runs as one business, and every Entity belongs to exactly one Organization. A Membership gives a User one Role in an Organization. That Role applies to every Entity of the Organization, including Entities added later.
  • Read covers GET requests on Entity routes and on the data the Organization shares, including the Organization’s Audit Trail. Write covers POST, PUT, PATCH, and DELETE.
  • Sintropix work covers routes reserved for the accounting team: credentials (except Portal Logins, the bank, Getnet, SII, and Clay logins a client can store too), connecting or reconnecting a bank through Fintoc, automations, Agent Channels, and FX rate sync.
  • Tasks are open to staff and client, who read and work them the same way. A viewer can’t reach them.
  • Every Role, viewer included, reads and writes the Organization’s Chat and reads and marks their own Notifications.
  • Reading the email of the Organization’s Gmail, Outlook, and Mailbox accounts takes more than reading the books: staff and client can, viewer can’t.
  • An Entity outside your Organizations returns 404. An action your Role doesn’t allow returns 403 with PERMISSION_DENIED_ERROR.
  • No Role is global. A User with no Membership in an Organization can’t reach its Entities, whatever Role they hold elsewhere.
A Superadmin is a User Sintropix designates to manage access: Users, Organizations, Memberships, and Entities: creating them, setting their parent Entity, and moving them between Organizations. A Superadmin does this through the Onboarding API, the Organizations API, and the Entities API. These routes accept only a signed-in browser session. A request with an API key or an OAuth access token gets 403 with SUPERADMIN_SESSION_REQUIRED, even a Superadmin’s, and any other User gets 403 with SUPERADMIN_REQUIRED. Being a Superadmin opens no books: a Superadmin reaches an Entity only through a Membership, like everyone else.

Linking to the App

Every record has a page in the Sintropix web app at https://app.sintropix.com/{entityId}/<page>, where {entityId} is the same UUID as in the API route. A Ledger Entry is at /{entityId}/entries/{entryId}, a payable Invoice at /{entityId}/bills?open={invoiceId}, a Bank Movement at /{entityId}/banks/{bankAccountId}?open={movementId}. Include these links whenever you mention a record to a user. The full map is in Link to the App.

Authentication

Programmatic callers authenticate in one of two ways:
  • API key in the x-api-key header. Keys are created in the Sintropix app; see Get an API Key.
  • OAuth access token in the Authorization: Bearer <token> header. An app gets one when a User approves it for one Organization; see Connect an app with OAuth. A token acts as that User in that Organization only, with read or read and write access, and never beyond the User’s Role. Claude and ChatGPT use this to reach the Sintropix MCP server.
Every mutating request (POST, PUT, PATCH, DELETE) made with an API key must also send a Declared Actor and a Declared Reason:
x-audit-actor is a self-reported software label (for example claude-opus-4.8) that lands in the Audit Trail, with surrounding whitespace trimmed. Omitting it on a mutation, or sending it blank, returns 400 with code AUDIT_ACTOR_REQUIRED_ERROR. A value that starts with erwin: is reserved and returns 403 with code AUDIT_ACTOR_NOT_ALLOWED_ERROR. x-audit-reason is a one-line, plain-text explanation of why the change is being made (max 500 characters). The server trims surrounding whitespace and stores the value on the Audit Envelope. Missing or blank returns 400 with code AUDIT_REASON_REQUIRED_ERROR; longer than 500 characters returns 400 with code AUDIT_REASON_TOO_LONG_ERROR. A mutating request made with an OAuth access token must send x-audit-reason too. It doesn’t need x-audit-actor: the Audit Trail names the approved app instead. POST /api/feedback is the one exception: it writes nothing of an Organization, so it needs neither header, and a read-only key or Connected App can send it too. A mutating request can also send x-audit-trigger, the Declared Trigger: what started the agent turn behind the write. Send schedule when a schedule started it, or slack, app, chat, or terminal when a person’s message in that place started it. The header is optional, and a request without it stores no trigger. Any other value returns 400 with code AUDIT_TRIGGER_UNKNOWN_ERROR and writes nothing. Its params carry header and the accepted triggers.

Request Format

Requests are plain JSON. Include Content-Type: application/json on any request with a body.
Path parameters that are ids must be valid UUIDs; a malformed id returns 400. A malformed entityId returns 404, like any Entity you can’t reach. A string anywhere in the path, query, or body can’t hold a NUL character (\u0000). A request that holds one returns 400.

Search by amount

Many list endpoints take a search parameter. When the search reads as an amount, it also matches the amounts the endpoint’s reference page names for that search:
  • A search reads as an amount when it holds only digits, . and , separators, and spaces. It may start with one currency mark ($, US$, CLP, or USD) and one minus sign. 165, 165140, 165.140, $165.140, -165.140, and US$123,45 all read as amounts. A search with any other letter doesn’t.
  • Sintropix drops the separators and the sign, and matches the remaining digits anywhere in the amount written in minor units. 165.140 and 165140 both find an amount of 165140, and 165 finds it too. US$123,45 finds a USD amount of 12345 minor units.
  • The sign never matters: -165.140 and 165.140 find the same amounts.
The search still matches the endpoint’s text fields as usual, so a numeric search can also find a document number or a tax id that holds those digits.

Response Format

Responses are the resource itself as JSON. There is no top-level data wrapper, no meta envelope, and no pagination block on non-paginated endpoints. Each reference page lists the fields every endpoint returns. A single resource comes back as an object:
A list endpoint returns a bare JSON array:
A page endpoint (endpoints whose path ends in /pages, plus a handful of reports) returns a { rows, nextCursor } object. nextCursor is null on the last page.
Pagination is opt-in per endpoint, not sitewide. Endpoints without /pages in their path return every row and take no cursor argument. Check the individual reference page for the endpoint you are calling.

Errors

Non-2xx responses are JSON. Every response, success or failure, carries an x-request-id header; quote it when contacting support. An error body carries statusCode, timestamp (ISO datetime), path, and requestId (the same value as the header). A domain error also carries its code and params. Domain-level errors carry a stable string code in the body, for example API_KEY_READ_ONLY_ERROR. Match on code, not on the human-readable message. If an error looks wrong, a response confuses you, or the API can’t do something you need, tell the Sintropix developers with POST /api/feedback. Report papercuts, nits, and ideas for improvements too, and for something you couldn’t do, say what you did instead. Include the requestId of the call, and send ids rather than names or amounts. You don’t need to tell your user.

Provider refusals

When an outside system refuses a request, the API answers 424 Failed Dependency with a coded body. These codes answer 424:
  • BANK_FEED_PROVIDER_FAILURE_ERROR, BANK_FEED_PROVIDER_UNAUTHORIZED_ERROR, and BANK_FEED_PROVIDER_ROLE_REFUSED_ERROR
  • INTEGRATION_PROVIDER_FAILURE_ERROR and INTEGRATION_GRANT_FAILED_ERROR
  • SOURCE_FEED_SYNC_PROVIDER_FAULT_ERROR
  • AUTOMATION_PROVIDER_FAILURE_ERROR and AUTOMATION_PROVIDER_UNAUTHORIZED_ERROR
  • MAILBOX_LIMIT_REACHED_ERROR
A refusal answers the same until someone acts, for example by reconnecting the Integration, so don’t retry it in a loop. An outside system that doesn’t answer at all returns 503 with its own code, and that one is worth retrying later. The API doesn’t send 502 or 504 on purpose: if you see one, it comes from the network in front of the API, not from Sintropix.

Rate Limits

Each API key is rate-limited to 25,000 requests per hour on a sliding window. Exceeding the limit returns 429; there is no X-RateLimit-* header response contract.

Service Status

Sintropix publishes the live status of the ERP API and the Client app at status.sintropix.com. Check it when requests fail with 5xx errors or time out, before you contact support.

Browser Callers

The API is designed for server-to-server use with an API key. Calling it directly from a browser requires your origin to be allowlisted by Sintropix; contact support if you need that.

What Is Not Part of the API

There is no webhook system. Sintropix does not push event notifications to external URLs. Poll the endpoints you care about, or the Audit Trail for a change feed.
There is no cursor pagination on most endpoints. Only endpoints whose path ends in /pages (plus the general-ledger, open-item-lines, journal, ledger-entries, and customer-status pagers) return { rows, nextCursor }. Others return the full list.
API keys go in the x-api-key header, never in Authorization: Bearer. The Authorization: Bearer header carries only OAuth access tokens of connected apps.
There is no /v1 prefix. The base path is /api.