Most queries and mutations on the GraphQL API share a common shape — the same filter operators, the same Connection wrapper around lists, the same nested-mutation conventions. This page is the reference for those shared patterns.Documentation Index
Fetch the complete documentation index at: https://archie.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
The Connection wrapper
Every list field in the schema (root-level lists and nested relationship lists) returns a Connection wrapper:| Field | Type | Description |
|---|---|---|
items | [T!]! | The records on the current page. |
count | Int! | Total matching records — useful for pagination UIs. |
pageInfo.hasNextPage | Boolean! | Whether more records exist after this page. |
pageInfo.hasPreviousPage | Boolean! | Whether records exist before this page. |
aggregates | JSON | Computed aggregate values when aggregateBy is used. |
filter, first, skip, and orderBy to a nested list the same way you pass them at the root.
Filter operators
Comparison and text
Most fields support a standard set of operators. The exact set depends on the field type — text fields get string operators, numeric fields get range operators, and so on.| Operator | Description | Example |
|---|---|---|
equals | Exact match | { status: { equals: "active" } } |
not_equals | Negated match | { status: { not_equals: "archived" } } |
gt | Greater than | { age: { gt: 18 } } |
gte | Greater than or equal | { age: { gte: 18 } } |
lt | Less than | { price: { lt: 100 } } |
lte | Less than or equal | { price: { lte: 100 } } |
contains | Substring match | { name: { contains: "phone" } } |
starts_with | Prefix match | { sku: { starts_with: "PROD-" } } |
is_empty | NULL or empty | { phoneNumber: { is_empty: true } } |
is_not_empty | Has any value | { bio: { is_not_empty: true } } |
Logical composition
AND, OR, and NOT compose any number of clauses. They can nest.
Date helpers
Relative date filters save you from computing exact timestamps.| Operator | Example |
|---|---|
today | { createdAt: { today: true } } |
this_week | { createdAt: { this_week: true } } |
this_month | { createdAt: { this_month: true } } |
last_days | { createdAt: { last_days: 30 } } |
Relational quantifiers
To filter parent records by the state of their related children, usesome, every, and none:
| Quantifier | Matches when… |
|---|---|
some | At least one child matches the inner filter. |
every | All children match the inner filter (also matches parents with no children). |
none | No children match the inner filter. |
Nested mutations
Every relationship field on a mutation input accepts exactly one of three operations:| Operation | What it does |
|---|---|
create | Insert a new related record inline. |
connect | Link to an existing record by a unique field. |
connectOrCreate | Find by a unique field; create if missing. |
Atomic upserts
Tables with at least one unique column expose anupsert<TableName> mutation. It atomically checks the unique field and runs create or update:
Modifying relationships
TheupdateRelationship mutation changes how a foreign key behaves — cascade behavior, nullability, descriptive metadata. Names map to the underlying database constraint name.
| Property | Accepts | What it does |
|---|---|---|
onDelete | CASCADE, SET NULL, RESTRICT, NO ACTION | What happens to child rows when the parent is deleted. |
onUpdate | Same set | What happens to child rows when the parent’s key changes. |
isNullable | true / false | Whether the relationship column can be null. Required true for SET NULL. |
description | String | Documentation for the relationship. |
Permissions and authentication
Filters, nested mutations, and upserts all run through the same authorization checks. Read access is required for filter clauses that touch a related table; write access is required for every step of a nested mutation. See Role-Based Access. Authentication tokens come from App Services → Authentication Providers.FAQ
When should I use `every` vs `some`?
When should I use `every` vs `some`?
some is “at least one child matches” — finds parents that have any matching child. every is stricter — all children must match. Note that every also matches parents with zero children, which is sometimes surprising.What's the difference between `connect` and passing a foreign key id directly?
What's the difference between `connect` and passing a foreign key id directly?
connect is the schema-level way to link by a unique field — including non-id columns like an email. Passing a raw foreign key id is shorter, but only works when you already have the id and the column is the primary key.Are nested mutations slower than separate operations?
Are nested mutations slower than separate operations?
Faster, in practice. They run in one round-trip and one database transaction, where separate operations require a round-trip per step and don’t share a transaction. They also avoid orphaned records when a later step fails.
Can I combine `having` with `filter`?
Can I combine `having` with `filter`?
Yes.
filter runs before grouping (SQL WHERE); having runs after (SQL HAVING). Use filter to scope the rows that participate in the aggregation, and having to drop groups whose aggregate doesn’t meet a threshold. See Queries → Grouping and aggregation.What's the maximum nesting depth on filters?
What's the maximum nesting depth on filters?
Deep nesting works for typical use cases. For very deep filter trees, consider the
_query POST endpoint on the REST API — it accepts a JSON body that’s easier to compose in code than a deeply nested GraphQL filter literal.