The POST /gql endpoint accepts a raw GQL query in the request body (not JSON-wrapped). Authentication and namespace selection use the same headers as POST /sql. For the full HTTP reference (headers, response envelope, limits), see POST /gql.
Start SurrealDB with GQL
ISO GQL is gated behind the experimental capability gql. Pass the storage path after the flag (or use memory):
surreal start --log info --user root --pass secret \
--allow-experimental gql memoryEnvironment variable equivalent:
export SURREAL_CAPS_ALLOW_EXPERIMENTAL=gql
surreal start --log info --user root --pass secret memory --allow-all does not enable experimental capabilities. You must allow gql explicitly. This is not GraphQL — use POST /graphql for GraphQL queries.
Load sample data
Use POST /sql with namespace main and database main (set via headers below):
curl -sS -X POST -u "root:secret" \
-H "Surreal-NS: main" -H "Surreal-DB: main" \
-H "Accept: application/json" -H "Content-Type: text/plain" \
-d "CREATE person:1 SET name = 'A', age = 30, active = true, city = 'London';
CREATE person:2 SET name = 'B', age = 20, active = false, city = 'Paris';
CREATE person:3 SET name = 'C', city = 'London';
CREATE city:1 SET name = 'London';
INSERT RELATION INTO knows [
{ id: knows:k12, in: person:1, out: person:2, since: 2021 },
{ id: knows:k21, in: person:2, out: person:1, since: 2018 },
{ id: knows:k23, in: person:2, out: person:3, since: 2020 },
{ id: knows:k1c, in: person:1, out: city:1, since: 2019 },
{ id: knows:k31, in: person:3, out: person:1 }
];" \
http://localhost:8000/sql POST /gql
Send the GQL query as the raw body with Content-Type: text/plain (or omit; UTF-8 text is expected).
curl -sS -X POST -u "root:secret" \
-H "Surreal-NS: main" -H "Surreal-DB: main" \
-H "Accept: application/json" -H "Content-Type: text/plain" \
-d 'MATCH (n:person) RETURN n.name AS name ORDER BY name' \
http://localhost:8000/gqlExample response (same envelope as /sql):
[
{
"status": "OK",
"result": [
{ "name": "A" },
{ "name": "B" },
{ "name": "C" }
],
"time": "1.5ms"
}
]Response formats
Set Accept to:
application/json(default)application/cborfor CBOR-encoded results
Parse errors return HTTP 400 with an error payload. If GQL is not enabled on the server, expect a capability or route error (403).
Mutations
The same endpoint accepts data-modifying GQL — INSERT, SET, REMOVE, and DELETE — interleaved with MATCH / OPTIONAL in one query. Mutation-bearing requests run in a write transaction and enforce the same permissions as SurrealQL writes.
Example — update a property and return the new value:
curl -sS -X POST -u "root:secret" \
-H "Surreal-NS: main" -H "Surreal-DB: main" \
-H "Accept: application/json" -H "Content-Type: text/plain" \
-d "MATCH (n:person WHERE n.name = 'A') SET n.age = 99 RETURN n.age AS age" \
http://localhost:8000/gqlSee GQL mutations for INSERT, REMOVE, DELETE, read-after-write interleaving, and rejected forms.
WebSocket RPC
On an authenticated WebSocket session, send the query as the first parameter. Pass typed variables as an optional second object:
{
"id": 1,
"method": "gql",
"params": [
"MATCH (n:person) RETURN n.name AS name ORDER BY name"
]
}With parameters:
{
"id": 2,
"method": "gql",
"params": [
"MATCH (n:person) WHERE n.age > $min RETURN n.name AS name",
{ "min": 18 }
]
} Try without HTTP — eval::gql
If you prefer the CLI or Surrealist over cURL, run GQL through eval::gql inside SurrealQL. You still need the gql experimental capability and --allow-eval-query, as eval::* is denied by default even under --allow-all.
One process (embedded): pass both flags on surreal sql, load the seed data with ordinary SurrealQL, then:
eval::gql("MATCH (n:person) RETURN n.name AS name ORDER BY name");surreal sql --user root --pass secret \
--allow-experimental gql --allow-eval-queryTwo processes (remote): enable both on surreal start, then connect with surreal sql as usual — capability flags on the client do not turn on eval for a remote engine.
surreal start --user root --pass secret \
--allow-experimental gql --allow-eval-queryMutations work the same way: eval::gql("MATCH (n:person WHERE n.name = 'A') SET n.age = 99 RETURN n.age AS age") runs in the open SurrealQL transaction. See GQL mutations and Eval functions.