Authorize

#Entities & Data Model

Entities are the records your application works with — a vessel, a task, a customer. Every entity belongs to an entity type, which pins its shape to a JSON schema and declares which attributes are queryable. Entities connect to one another through relationship rules (e.g. Project → Task). See Core Concepts for the mental model.

Authenticate with a Personal Access Token (HTTP Basic auth) — enter it once in the Authorize bar at the top of this page and every Try it below uses it. Each example body is pre-filled; the console targets staging by default. Full schemas and field docs are in the linked API reference.

#Build a data model

The flow is always the same: schema → entity type → relationship rule → entities → links.

#1. Define a JSON schema

A schema describes an entity's attributes. Reuse one schema across many types.

POST/schema/schemasRegister a JSON schemaAPI docs ↗Try it

#2. Create an entity type

The type binds a name to a schema and declares config.identifier_key — the attribute path(s) that derive an entity's stable business key, computed server-side on every write — and config.indexed_attributes — only indexed attributes are filterable/sortable in queries (querying an un-indexed attribute returns 400 INVALID_FILTER). A type is draft until you activate it; only active types accept entities.

POST/entity/entity-typesCreate an entity typeAPI docs ↗Try it

#3. Add a relationship rule

A rule declares a directed connection between two types and its cardinality (max_from_cardinality / max_to_cardinality; null = unlimited). Cardinality is enforced when links are written.

POST/entity/relationship-rulesCreate a relationship ruleAPI docs ↗Try it

#4. Create entities

attributes are validated against the type's schema. identifier_key is never sent by the caller — it's computed server-side from config.identifier_key (here, the key attribute) and returned on every response. A create whose computed identifier_key collides with a live entity returns 409 — use the upsert path instead.

POST/entity/entitiesCreate an entityAPI docs ↗Try it

Link two existing entities via a rule. on_cardinality_violation chooses what happens when the link would exceed a rule's cap: raise (default, abort) or trim (soft-delete the oldest edge to fit).

POST/entity/relationshipsLink two entitiesAPI docs ↗Try it

#Read & query

POST /entity/query is the read surface for anything non-trivial. The body is a filter tree plus sort, pagination, and relationship includes. Cross-tenant rows you can see through a share come back tagged source_type: "shared".

POST/entity/queryQuery entitiesAPI docs ↗Try it
  • Filter operators: eq/neq, gt/gte/lt/lte, like/ilike, is, in, cs (array contains-all), ov (array overlaps), combined with and / or / not.
  • Path conventions: ["name"] (a system field); ["attributes", "x"] (an indexed attribute — un-indexed paths are rejected); ["relationships", ruleName, "attributes", "x"] (filter through a relationship).
  • Pagination is keyset by default (cursor); offset (page/limit) is the escape hatch. include loads one hop of related entities by rule name; POST /entity/query/distinct returns distinct values for a path.

#Deep relationship reads — /query-graph

/entity/query reads one hop deep. For a whole related subtree in a single call, use POST /entity/query-graph — the same type_name / filter / sort / pagination shape, plus a nested include tree (each entry can itself carry include, filter, sort, limit, to any depth up to a server cap). Instead of a row-per-parent shape, the response is one deduplicated graph: roots (matching entity ids), nodes (every reachable entity, keyed by id — a node shared by two branches is serialized once), and edges. This is the REST-native way to do a graph-shaped read without GraphQL, and it's the surface most integrations reach for by default.

POST/entity/query-graphQuery a graph of entities (deep hydration)API docs ↗Try it

If the node budget constrains a deeply-nested branch, page_info.truncated is true and page_info.truncations reports which branch and at what depth — narrow that branch's limit, prune it, or paginate the roots and re-issue.

For a GraphQL surface over the same access rules (selective fields, Relay Connections, codegen) see Querying & GraphQL. The GraphQL playground also has a converter that turns a query into a workflow QueryEntity step.

#Bulk upsert & import

POST /entity/entities/upsert writes a large batch in one transaction (capped per request — see the reference). Each row matches an existing entity on its computed identifier_key (derived from attributes.key per the type's config above) — never a caller-supplied identifier_key. Useful options: skip_unresolved_relationships (skip + log an inline relationship whose target_identifier doesn't resolve, instead of failing the batch), merge_on_conflict / merge_cardinality (fold a colliding identifier_key into the surviving entity), and suppress_events.

POST/entity/entities/upsertBulk upsert entitiesAPI docs ↗Try it

For files, POST /entity/entities/import streams a CSV (an X-Import-Config header carries the column mapping + on_conflict strategy); …/export streams the inverse.

#Update, patch & delete

PUT replaces an entity; PATCH …/attributes deep-merges a partial attribute update; DELETE soft-deletes the entity and cascades to its relationship instances. Updates accept the same merge_on_conflict / merge_cardinality options as upsert.

PATCH/entity/entities/{id}/attributesPatch entity attributes (deep-merge)API docs ↗Try it

#Attach files (artifacts)

Files attach to an entity via a two-step flow: request an upload URL, PUT the bytes to it, then confirm. Artifacts are encrypted at rest and access is gated by the same permissions as the entity.

POST/entity/entities/{id}/artifacts/upload-urlRequest an artifact upload URLAPI docs ↗Try it

#Sharing & access

Sharing your data model and rows with other tenants — definition shares, data shares, and grants — is its own topic. See Shares & Grants.

#API reference

Every entity and schema operation, with full request/response schemas and an interactive console, is in the API reference.