Available since: v3.2.0
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
From 3.3.0, start a normal instance - ISO GQL is on by default:
surreal start --log info --user root --pass secret memoryOn 3.2.x, pass the experimental capability (storage path after the flag, or use memory):
surreal start --log info --user root --pass secret \
--allow-experimental gql memoryexport SURREAL_CAPS_ALLOW_EXPERIMENTAL=gql
surreal start --log info --user root --pass secret memory 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.
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 SurrealDB Studio over cURL, run GQL through eval::gql inside SurrealQL. You still need --allow-eval-query, as eval::* is denied by default even under --allow-all. From 3.3.0 you do not need --allow-experimental gql as well (required on 3.2.x only).
One process (embedded): pass --allow-eval-query 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-eval-queryTwo processes (remote): enable eval 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-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.