Every business application has to integrate with something else. A public website that needs to display the latest product catalog. A mobile app that is really a thin client for the same data. An accounting system that expects an end-of-month feed. A data warehouse that wants yesterday's transactions by morning. A partner portal that reads records through an API gateway. Whether those integrations take hours, weeks, or get abandoned almost always comes down to the quality of the API they're built against. Ours is meant to be the kind that turns the platform from a silo into a hub.
The starting point is coverage. Every type — system types and tenant-defined types — is addressable over HTTP, and the same is true for users, files, queries, and automation triggers. If it exists in the platform and a user could interact with it through the UI, an integration can reach it through the API. That's the promise: no special-cased entities, no "you can do X in the UI but not through the API." If the feature is there, the endpoint is there.
Identifier flexibility is a small but important convenience. A record can be referenced by its UUID, by its numeric identifier, or by its system name. That matters because integrations often carry their own identifiers — a partner's order number, an external customer ID — that map to system names on the tenant's side. A PATCH against /api/v1/customers/acme-industries is valid if acme-industries is the system name of a record, which eliminates the usual integration pain of maintaining a parallel ID-mapping table.
Filters use the same expression vocabulary the UI's query builder produces, serialized into the query string. That means sophistication isn't sacrificed at the integration boundary: nested conditions, OR branches, subquery references, relationship walks, and date-aware expressions are all available from the URL. Advanced filtering is not a UI-only feature, which in practice means an external client can ask the same nuanced questions the platform's power users can ask, without a reporting layer in between.
Ordering, pagination, and field selection round out the reading experience. Multi-field sort is supported with the same semantics the UI uses. Pagination comes with sensible maximums to prevent accidental full-table scans. Field selection is a three-mode affair — showFields for a minimal response, hideFields for dropping a few expensive properties, and wrapFields for nesting related data — so API consumers get exactly the payload they want, without receiving two megabytes when they only wanted a name and a status.
The automatic object-ordering default is a small feature that saves callers a parameter. Types with a defined canonical ordering — a task's priority position, an entry's sort order — return their records in that order by default, so clients that want the "natural" view don't have to specify a sort. For calls that want something different, an explicit sort overrides the default.
Writing is where the API earns its second round of careful thinking. Create, update, patch, and delete all behave as you'd expect. Two modifiers extend the standard patterns usefully. += appends values to a collection property without replacing the existing ones — attaching a file, adding a participant, extending a list — which is the operation most integrations actually want on an update but rarely get without complicated read-modify-write patterns. +== is its slightly-stricter cousin, which enforces uniqueness: add this if it isn't already there. That combination is the difference between an integration that respects concurrent edits and one that clobbers them.
Patch-by-reference is the other writing feature worth highlighting. An integration that receives updates keyed by an external identifier — the partner's order number, the upstream system's record ID — can patch the target record by that identifier directly, without first looking up the internal identifier. The platform resolves the reference, applies the patch, and returns the updated record. That turns a two-call flow into one and removes a class of race conditions in the process.
Files are treated as first-class citizens. Uploads use a promise pattern: the client announces an upload, receives an upload URL, pushes the bytes, and then references the completed upload in a subsequent call. That decouples the heavy I/O from the record write, plays nicely with cloud storage backends, and keeps API endpoints fast. Downloads are by record reference and respect the same permission model as any other read.
Nested filter notation deserves a specific callout because it's what closes the expressivity gap between the UI and the API. The same nested AND/OR/subquery structure that the query builder produces can be serialized into the query string, decoded on the server, and applied without flattening or approximation. Integrations that need "European customers with an overdue invoice who haven't been contacted in thirty days" can express exactly that without having to compromise down to a simpler filter.
Get-by endpoints find a single record by a unique property value — useful when you know the email address but not the identifier, or when your integration keys on a business identifier rather than a platform one. A quick GET /api/v1/customers/get-by?email=... returns the record without a list-then-filter pattern.
Integrations need concurrency to behave predictably. The API exposes the usual patterns — optimistic updates where appropriate, clear error codes on conflicts, idempotent semantics for patches — and pagination is cursor-friendly where it matters. The platform isn't trying to be a database; it's trying to be the record-of-truth for specific data domains, and the API reflects that.
Authentication is covered in detail in the API protection article. Webhooks, which complete the picture by letting the platform push updates to integrations rather than forcing them to poll, have their own article. Taken together, the three — REST API, protection, webhooks — are what let external systems use the platform as a real hub. Many of our customers build entire companion applications — public sites, mobile apps, partner portals — on top of this API, with the platform itself providing the admin interface, the data model, and the workflows. That's exactly the use case we built it for.