Docs · GraphQL API
GraphQL API
Two kinds of thing exist in Closure. Everything else is a projection.
| DataSchema | DataObject | |
|---|---|---|
| Job | Declares a shape | Is a row of that shape |
| Identity | schema:… | urn:uuid:… |
| Example | schema:experience, schema:workflow, schema:page | CRM Lite Experience, a lead-capture workflow, a page |
JSON-LD is how objects carry meaning. GraphQL is how you query and mutate the store.
Same store the console, Experiences, Knowledge → Data, and your IDE all use. Auth: Closure session (POST /api/graphql). GET /api/graphql returns the SDL.
Browser apps should call your BFF, which proxies with org credentials — see SDK & client.
Mental model
DataSchema ──types──▶ DataObject store (G)
│
┌───────────────┼───────────────┐
▼ ▼ ▼
GraphQL Renderer Runtime
(query) (Experiences) (Workflows API)A page is a DataObject. A component is a DataObject. A workflow graph is a DataObject. A skill is a DataObject. One type in GraphQL (DataObject); schemaRef differentiates meaning.
Paradigm deep-dive: Everything is JSON-LD · why this model: Why a Product Graph?
Try it here
Don't read about it — query it. The playground below runs the real Platform GraphQL executor against an in-memory sample org (org_demo) — same SDL as production. No session required. Everything on the rest of this page can be pasted straight in.
For your live Organization: Closure → Knowledge → Data → GraphQL.
Live sample · org_demo
Real Platform GraphQL executor · 4 seeded DataObjects
// Result appears here
Sample DataObject (JSON-LD)
What lands in the store — and what GraphQL returns under data:
{
"@context": "https://closureapps.com/schema/context.jsonld",
"@id": "urn:uuid:16e43167-66ad-5e94-a0e8-60f9d482fcfe",
"schemaRef": "schema:experience",
"name": "Demo Experience",
"orgId": "org_demo",
"state": "active",
"data": {
"slug": "demo",
"homePath": "/",
"homePageId": "urn:uuid:720eedf1-10a6-5030-a53d-9f6b2e57fd82",
"pageIds": ["urn:uuid:720eedf1-10a6-5030-a53d-9f6b2e57fd82"],
"nav": [{ "label": "Home", "href": "/" }]
}
}A DataSchema row (schemaRef: "schema:data_schema") describes fields other objects must carry — meta-schema, same store.
Schema (SDL)
type DataObject {
id: ID!
orgId: String!
schemaRef: String!
name: String!
state: String!
data: JSON!
links: JSON
createdAt: String!
updatedAt: String!
}
type Query {
object(id: ID!): DataObject
objects(orgId: String!, schemaRef: String, where: ObjectWhere, limit: Int): [DataObject!]!
experience(orgId: String!, slug: String!): DataObject
resolveBind(orgId: String!, bind: JSON!): JSON!
}
type Mutation {
upsertObject(input: UpsertObjectInput!): DataObject!
deleteObject(id: ID!): Boolean!
}orgId can be omitted when the session already scopes the Organization.
Cookbook
List Experiences
query {
objects(orgId: "org_demo", schemaRef: "schema:experience", limit: 50) {
id
name
state
data
updatedAt
}
}Resolve by slug
query {
experience(orgId: "org_demo", slug: "demo") {
id
name
data
}
}Follow the graph (page → components)
query {
objects(orgId: "org_demo", schemaRef: "schema:page", limit: 20) {
id
name
data
}
}Then query schema:component and match data / links to the page’s rootComponentId.
Upsert
mutation ($input: UpsertObjectInput!) {
upsertObject(input: $input) {
id
updatedAt
}
}{
"input": {
"id": "urn:uuid:aaaaaaaa-aaaa-5aaa-8aaa-aaaaaaaaaaaa",
"orgId": "org_demo",
"schemaRef": "schema:artifact",
"name": "Signal",
"data": { "kind": "note", "title": "Hello graph" }
}
}Curl
curl -sS https://closureapps.com/console/api/graphql \
-H "Content-Type: application/json" \
-H "Cookie: <your-session>" \
-d '{"query":"query { objects(orgId: \"org_demo\", schemaRef: \"schema:experience\", limit: 5) { id name } }"}'Boundaries
| Do with GraphQL | Do with Workflows API |
|---|---|
| Read / write DataObjects | Start and advance runs |
Bind Experiences (resolveBind) | Collect → agent → HITL → seal |
Inspect schema:workflow rows | Execute the process graph |
Workflow execution: Workflows API.
What is not (yet)
- Public API-key multi-tenant GraphQL for anonymous internet clients — roadmap
- L1’s richer
executeFunction/executeWorkflowGraphQL surface — Platform keeps execution on the Workflows HTTP API on purpose