Scalars
The schema builds on the standard GraphQL scalars and adds two custom ones. Both are declared at the top of the platform schema:ID
The ID scalar is the type used for every identifiable object: clients, tasks,
workspace users, uploads, and so on. Treat it as an opaque string. Always
send it back exactly as you received it; never parse it, slice it, or assume a
specific length. The two concrete scalar declarations in the live schema are
ID (the built-in) and the custom Date and JSON below.
Filed
ID values are UUIDv7 strings, for example
019f0fb6-37b1-7800-b7bc-0d11288504b1. You can confirm this from any example
response in these docs: the first three segments encode a Unix timestamp
(milliseconds) so IDs are roughly time-ordered, followed by random bits. This is
an implementation detail you can rely on for ordering and debugging, but you
should still round-trip the value as an opaque string and not construct IDs
yourself.Date
The Date scalar is an ISO 8601 timestamp string (RFC 3339), for example
2025-07-04T17:21:43.123Z. Every timestamp field in the schema (createdAt,
startedAt, completedAt, etc.) uses this scalar, even when the field name
does not contain the word Date. startedAt and completedAt on Task are
non-null String rather than the Date scalar, but they carry the same
ISO 8601 string format.
JSON
The JSON scalar holds an arbitrary JSON value: an object, array, string,
number, boolean, or null. It is used wherever a field’s value is structured
but not fixed by the schema, for example AI task results. The
TaskTaxAdvisorResult.byDomain field is a non-null JSON scalar that returns
a structured object whose shape is defined by the tax advisor task, not by the
GraphQL type system.
Pagination
List fields use offset-based pagination with two optional integer arguments,offset and limit. Both are plain Int scalars (nullable, so
you can omit either).
offsetis the number of items to skip before the first returned item. It is zero-based, sooffset: 0(or omitting it) returns from the start.limitis the maximum number of items to return in a single response.- The list is always a non-null list of non-null items, for example
[Client!]!or[Task!]!. An empty page is an empty array, nevernull.
The Filed API does not currently expose a cursor-based
Connection type or a
totalCount field. Page through a list by walking offset forward in steps of
limit until the returned list is shorter than limit (or empty). The
Workspace.tasks and Workspace.clients fields both follow this shape.Example: page through clients
"offset": 25 and the same limit to fetch the
next page. Stop when fewer than limit items come back. See
Clients for the full Client type and the filters/sortBy
arguments.
Sorting
List fields that acceptsortBy use the shared SortBy input type. It is a
single optional argument applied to the list before pagination.
field is the name of the field to sort by, as a string (for example
"createdAt", "name", "startedAt"). order is ASC for ascending or
DESC for descending. Both field and order are non-null inside SortBy,
so if you pass a sortBy value at all you must supply both. Omit the whole
sortBy argument to use the API’s default order.
SortBy input is reused by every list field that supports sorting:
Workspace.clients, Workspace.tasks, and Workspace.workspaceUsers.
Filtering
List fields take a typed filter input named after the entity:ClientFilters
for clients, TaskFilters for tasks. Each input is a nullable argument, so
you can omit it entirely or pass only the keys you care about. Every key inside
the input is itself optional, and combining keys applies them as a logical AND.
ClientFilters
ids to fetch a known set of clients by ID (passing a single-element list
is how you fetch one client). Use
status to filter by lifecycle state, search for free-text search over
client name and external ID, and assigneeIds or assignedToMe to filter by
assignee. Full field detail is on the Clients page.
TaskFilters
type (for example BINDER to follow a binder job), by
status (RUNNING, COMPLETED, FAILED), by the user who started the task
with triggeredBy, or with free-text search. Full field detail is on the
Tasks page.
Client.tasks(type:, status:, triggeredBy:, limit:) takes the same filtering
concepts as inline scalar arguments (not a TaskFilters input) and does not
take offset or sortBy. Use it when you want the tasks for one client; use
Workspace.tasks(filters:, sortBy:, limit:, offset:) when you want tasks
across the whole workspace.Next steps
- Making requests for the request anatomy and error model.
- Clients and Tasks for the full type detail of each list field.
- Authentication to mint the
workspaceTokenthese conventions assume.