Platform · platform & data

The same permission model as the interface, not a side door

Most ERP APIs are a second surface with their own auth model, their own idea of what a valid transaction is, and their own gaps. Ours goes through the same data layer and the same policy engine as the interface — which means an API key cannot do something a person with the equivalent role could not.

QuickBooksQuickBooks190NetSuiteNetSuite190StripeStripe190RampRamp190GustoGusto190ShopifyShopify190SalesforceSalesforce190PlaidPlaid190Business graphone model, all systemsDepartment P&LEntity roll-upProject marginShadow ledgerAgent contextUniversal search
Same enforcement as the UIIdempotent writesFull export, always

What it does

Six things, specifically.

REST over the business graph

Parties, agreements, obligations, work, dimensions, and events as resources — the same objects the interface and the agents use rather than a flattened export shape.

Scoped keys as actors

An API key is an actor with its own permission set, subject to the same conflict matrix. A key that could create vendors and release payments is rejected at creation.

Idempotent writes

Every mutating call takes an idempotency key. A retried request cannot create a duplicate transaction, which matters more in accounting than almost anywhere else.

Same posting engine

A journal entry submitted via API passes the identical invariant checks — balance, period state, account validity, dimensions. There is no privileged path.

Webhooks for events

Signed, retried with backoff, and replayable from a cursor, so a consumer that was down for an hour can catch up rather than silently missing events.

Bulk export

Ledger, documents, and the complete audit trail in open formats, on demand or scheduled into your warehouse. Leaving has to be technically possible or the rest is talk.

Why the API is not a separate surface

The common architecture treats the API as a parallel entry point, which produces two problems that both show up in security review. The auth model diverges from the UI’s, so answering "what can this integration do" requires reasoning about two systems. And business rules that live in the interface layer get bypassed, which is how integrations quietly post things the UI would have refused.

Routing the API through the same data access layer and the same policy engine removes both. An API key is an actor in the permission model. A journal entry submitted by an integration faces the same invariant checks as one entered by a person or proposed by an agent.

If your integrations can post something the interface would have rejected, your business rules live in the wrong layer.

Idempotency is not optional in accounting

In most APIs a retried request creating a duplicate record is an annoyance. In a ledger it is a duplicate transaction, and duplicates in accounting are expensive and awkward to unwind because the correction is itself a new entry.

Every mutating endpoint requires an idempotency key and returns the original result on replay. Network timeouts, client retries, and queue redelivery are all normal and none of them should be able to double-post a bill.

The export commitment

We publish a bulk export path deliberately, and it lowers our own switching cost. A vendor whose export is undocumented or partial has a commercial reason for that, and it is worth noticing which of your systems fall into that category.

Ledger, documents, and the full audit trail come out in open formats. If you leave, the audit trail goes with you — an audit record that evaporates at contract end satisfies nobody’s retention policy.

What we have deliberately not exposed

There is no API for authoring policies or granting authority levels. Those are administrative actions performed in a surface that automation cannot reach, because an integration able to widen its own permissions makes the whole model decorative.

Limits

Where this does not help.

No GraphQL yet

REST and webhooks today. GraphQL is on the roadmap and we would rather say that than list it as available.

Rate limits are real

Published per tier. Bulk operations go through the export and import paths rather than by looping a transactional endpoint, and we will tell you when you are using the wrong one.

No policy or authority API

Deliberate. Authoring policy and granting authority happen in an administrative surface automation cannot reach, because a key that can widen its own scope has no scope.

Questions

What people ask.

Is there a sandbox?
Yes, a full sandbox tenant with seeded data and no production access. Every customer gets one and it is where integration work should happen.
Can an API key post journal entries?
If its permissions allow it, and it faces the identical invariant checks as any other actor — balance, period state, account validity, required dimensions. There is no privileged path.
How do you handle retries?
Idempotency keys on every mutating call, returning the original result on replay. A double-posted bill from a network timeout is not an acceptable failure mode in a ledger.
What about GraphQL?
Not yet. REST and webhooks today; GraphQL is on the roadmap and we would rather not list it as shipped.
Can we export everything?
Yes — ledger, documents, and the complete audit trail in open formats, on demand or scheduled. It lowers our switching cost deliberately.

Bring your engineers.

A technical walkthrough of the API, the permission model, and the export path — without a salesperson on the call.