Skip to content
Settings

Working with entities

This page shows the patterns for interacting with entities through the platform API. Examples assume a local cyoda-go instance running on the default port with SQLite persistence; the same requests work against Cyoda Cloud with the cloud endpoint and an issued token.

The complete endpoint catalogue — parameters, response shapes, error codes — lives in the API reference. Keep that open as you work.

Cyoda speaks REST for CRUD, search, and workflow invocation, gRPC for external processors, and Trino SQL for analytics. This page covers REST; see Build → client compute nodes for gRPC and the APIs and surfaces overview for the decision framework.

Every request is authenticated with a bearer token. Every response includes the entity’s current revision, state, and timestamps.

Post an entity to its model. The first time you post, Cyoda discovers the schema from what you send:

Terminal window
curl -X POST http://localhost:8080/api/entity/JSON/orders/1 \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $TOKEN" \
-d '{
"orderId": "ORD-42",
"customerId": "CUST-7",
"amount": 120.00,
"currency": "EUR",
"lines": [
{ "sku": "AX-1", "qty": 2, "price": 60.00 }
]
}'

The path is /api/entity/{format}/{entityName}/{modelVersion} — here JSON, orders, and version 1. The response carries an array whose first element contains entityIds[0], the system-assigned UUID of the new entity, plus its current state and revision number. Capture the UUID — downstream reads, updates, and transitions address the entity by that UUID, not by the business key orderId.

Fetch the current revision by id. The {entityId} in these URLs is the UUID returned in entityIds[0] from the create response, not a business key like orderId:

Terminal window
curl http://localhost:8080/api/entity/${ENTITY_ID} \
-H "Authorization: Bearer $TOKEN"

List every entity in a model with GET /api/entity/{entityName}/{modelVersion}:

GET /api/entity/orders/1

For filtered reads — predicates, pagination, result caps, historical reads — see searching entities. The list endpoint does not accept ad-hoc field filters; those belong to search.

Direct updates use PUT /api/entity/{format}/{entityId} (loopback update — stores a new revision without a named transition) or PUT /api/entity/{format}/{entityId}/{transition} (update with a named transition). There is no PATCH endpoint — all writes are full-payload PUTs.

Mutations that move the entity between lifecycle states should go through a named transition, not a bare loopback update. Invoking the submit transition records it in the audit trail and runs any attached processors. The transition carries the new entity JSON in the request body (the platform stores the updated entity and records the named transition in one call):

Terminal window
curl -X PUT http://localhost:8080/api/entity/JSON/${ENTITY_ID}/submit \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $TOKEN" \
-d '{ "orderId": "ORD-42", "status": "submitted" }'

See Build → workflows and processors for how to declare transitions.

Cyoda supports two query modes:

  • Direct (synchronous, capped result size) — API term direct. Returns right away. Good for UI lookups and short operations. Result size is capped, so direct is best for queries that produce a bounded, small result set.
  • Async (background, unbounded, paged) — API term async. Queued as a job, returns a handle you can poll. Result size is unbounded; results are paged. Good for large result sets, periodic reports, and exports. On the Cassandra-backed tier (Cyoda Cloud, or a licensed Enterprise install), async search runs distributed across the cluster and scales horizontally: query throughput for a fixed shape grows roughly linearly with the number of nodes.

Both accept the same filter grammar over entity fields, metadata, and workflow state. Pick direct by default; switch to async when a query would hit the direct result cap, would time out, or would hold resources you need elsewhere. For predicates, pagination, and worked examples, see searching entities.

Every entity’s history is queryable. Add a pointInTime parameter to any read or search request to retrieve the world as of that timestamp:

GET /api/entity/{entityId}?pointInTime=2026-03-01T00:00:00Z

This is the primary way to answer regulatory and audit questions: what did this customer’s balance look like at quarter close? For the same parameter applied to searches, see searching entities → historical reads; for analytical reads expressed as SQL, see analytics with SQL.

When your code is reacting to a transition — running a processor or evaluating a criterion — talk to the platform over gRPC, not REST. The gRPC path preserves the audit association between the transition and the compute call, brokers identity, and supports streaming. See Build → client compute nodes for the implementation pattern.