Conventions
Four things behave consistently across the whole API. Knowing them removes most of the guesswork from reading the schema reference.
Identifiersâ
Ids are Long. Most top-level entities also carry an opaque publicId â a UUID
string that is safe to put in URLs and to hand to third parties.
By-id getters dual-accept: pass exactly one of the two.
query { tasks { getTask(taskId: 42) { name } } }
query { tasks { getTask(publicId: "0b7fâŚ") { name } } }
Passing both, or neither, is an error rather than a silent preference.
Dates and timesâ
| Scalar | Format | Example |
|---|---|---|
LocalDate | YYYY-MM-DD | "2026-07-31" |
ZonedDateTime | ISO-8601 | "2026-07-31T12:00:00Z" |
Entity timestamps come back as ISO-8601 strings.
JsonString fieldsâ
Some fields â task metadata, integration configurations, form definitions â hold
arbitrary JSON. They are typed JsonString and are transported as a string
containing JSON, not as a JSON object.
That means you escape twice on the way in:
{"query": "mutation($m: JsonString!) { tasks { updateTask(taskId: 42, metadata: $m) { taskId } } }",
"variables": {"m": "{\"source\":\"crm\",\"externalId\":\"A-119\"}"}}
and parse on the way out â the value you receive is a string, and
JSON.parse (or your language's equivalent) turns it into the object you expected.
Permissions are in the schemaâ
Every operation's description ends with what it requires:
Requires canManageTasks.
Requires Owner or Admin role.
Read it before you call. A PERMISSION_DENIED is a statement about the key, not a
transient failure â retrying will not help. See Errors.