GraphQL ​
AYB exposes a GraphQL API backed by live database schema metadata.
Endpoint ​
- HTTP query/mutation:
POST /api/graphql - WebSocket subscriptions (
graphql-transport-ws):GET /api/graphqlwith WebSocket upgrade
GET /api/graphql without WebSocket upgrade is rejected with 405 Method Not Allowed (websocket upgrade required for GET /graphql).
Authentication ​
When auth is enabled:
POST /api/graphqlis mounted with the same admin-or-user auth middleware used by REST API routes.- WebSocket auth is enforced in the
graphql-transport-wsprotocol init step (connection_init) via bearer token or API key validation. - Invalid/missing auth during init closes the socket with close code
4401.
bash
curl -X POST http://localhost:8090/api/graphql \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"query":"{ posts(limit: 5) { id title } }"}'Query example ​
Table names become root fields.
graphql
query Posts {
posts(
where: { published: { _eq: true } }
order_by: { created_at: DESC }
limit: 20
offset: 0
) {
id
title
published
}
}Mutation examples ​
For table posts, AYB generates:
insert_postsupdate_postsdelete_posts
graphql
mutation CreatePost {
insert_posts(objects: [{ title: "Hello", published: true }]) {
affected_rows
returning {
id
title
}
}
}graphql
mutation UpdatePost {
update_posts(
where: { id: { _eq: 42 } }
_set: { title: "Updated" }
) {
affected_rows
returning {
id
title
}
}
}graphql
mutation DeletePost {
delete_posts(where: { id: { _eq: 42 } }) {
affected_rows
}
}Subscriptions ​
Subscriptions are table-based and stream row changes.
graphql
subscription WatchPosts {
posts(where: { published: { _eq: true } }) {
id
title
published
}
}Use graphql-transport-ws protocol on ws://localhost:8090/api/graphql.
Transport behavior:
- Subprotocol
graphql-transport-wsis required. connection_initmust be sent beforesubscribe.- Sending
subscribebeforeconnection_initcloses with4401.
Schema introspection ​
graphql
query Introspect {
__schema {
queryType { name }
mutationType { name }
subscriptionType { name }
}
}Introspection behavior is controlled by graphql.introspection config:
""(default): admin-gated"open": no introspection gate"disabled": blocked
Error envelope differences vs REST ​
- GraphQL request/validation/execution errors are returned as GraphQL errors (
{ "errors": [...] }), commonly with HTTP200. - Malformed JSON body returns HTTP
400with GraphQL-style error envelope. - Introspection blocked by policy returns HTTP
403with GraphQL-style error envelope. - REST endpoints use
{ code, message, data?, doc_url? }via sharedhttputilhelpers.
Practical notes ​
- Tables prefixed with
_ayb_are excluded. - Views/materialized views are queryable but not mutation targets.
limitis capped server-side (default max 1000 rows).- Filters support
_eq,_neq,_gt,_gte,_lt,_lte,_in,_like,_ilike,_is_null.