GraphQL endpoints

The Fauna GraphQL API provides two endpoints:

Endpoint Description

Accepts and executes GraphQL queries, and returns the results.

Accepts and imports a GraphQL schema.

These endpoints are hosted at

GraphQL queries are executed by sending HTTP requests to the endpoint. This documentation does not describe how to implement HTTP requests, as you can do so in many different languages. Common GraphQL HTTP request information is available here:

The endpoint access GraphQL queries, and returns results in JSON format. See Getting started with GraphQL, or the GraphQL tutorials to see how queries work.

The endpoint accepts a GraphQL schema definition, which is translated into the equivalent Fauna collections and indexes.

When a GraphQL schema is imported, the GraphQL API automatically creates the following Fauna schema documents:

  • One collection for each declared GraphQL type (using the type’s name), but not for @embedded types.

  • One index for each declared query (using the query’s name), but not for queries annotated with the @resolver directive. The collection name can be specified with @collection, and the index name can be specified with @index.

  • When an @relation directive is used and the relationship is many-to-many (instead of one-to-one, or one-to-many), an associative collection is created, as well as three indexes, one for each side of the relationship, and a third indexing the refs of both sides.

  • One user-defined function for each mutation declared with the @resolver directive (using the resolver name). Note that you have to provide the implementation for the mutation function via FQL yourself. See User-defined functions for details.

The endpoint is not for importing data, it is only for importing a GraphQL schema. Use GraphQL mutations to create or update data.

A basic GraphQL schema looks like:

type User {
  username: String!

type Query {
  allUsers: [User!]!

This query defines a User type, which would become a collection in Fauna called User:

{ ref: Collection("User"),
  ts: 1560204122930000,
  history_days: 30,
  name: 'User',
   { gql:
      { ts: Time("2019-06-10T22:02:02.816944Z"),
         { name: 'User',
            [ { name: 'username', type: { NotNull: { Named: 'String' } } } ],
           directives: [ { name: 'collection', args: { name: 'User' } } ] } } } }

It also defines an allUsers query that provides paginated User results. Fauna implements such a query as an index called allUsers:

{ ref: Index("allUsers"),
  ts: 1560204123110000,
  active: true,
  partitions: 8,
  name: 'allUsers',
  source: Collection("User"),
   { gql:
      { ts: Time("2019-06-10T22:02:03.010289Z"),
         { name: 'allUsers',
           directives: [ { name: 'index', args: { name: 'allUsers' } } ],
           type: { NotNull: { List: { NotNull: { Named: 'User' } } } } } } },
  values: [],
  terms: [],
  unique: false }

For end-to-end examples of importing a schema, creating records, and querying them, see Getting started with GraphQL.


There are two import modes:

Mode Description


The merge mode creates missing collections, indexes, and functions, and annotates existing Fauna schema documents with GraphQL metadata, if required. This is the default mode.


The override mode deletes all collections, indexes, and functions that are annotated with GraphQL metadata, pauses 60 seconds to allow all cluster nodes to process the deletions, then it imports the new schema with merge mode.

The purpose of override mode is to make it easy to experiment with varying schemas. During development of your schema, it is often easier to start with a fresh schema.

override mode causes data loss for any previous GraphQL schema. Any collections, indexes, or documents that are not involved in GraphQL are not affected.

Specify the mode using a query parameter. For example:

POST /import?mode=override

If you are using curl, the command would look like:

curl -H 'Authorization: Bearer <FAUNA_SECRET>' --data-binary "@path/to/schema.gql"

Where FAUNA_SECRET is a secret associated with the database where the schema should be imported, and path/to/schema.gql is the path to a file containing your GraphQL schema.


Both endpoints require authentication with a specific Fauna database. This is achieved with a standard Fauna secret, which determines the database and permissions to be used.

The secret can be provided through the HTTP Authentication request header, either as a Bearer token, or via HTTP Basic authentication.

Bearer token

To use the Fauna secret as a Bearer token, the Authorization header should look like:

Authorization: Bearer <secret>

For example, if your Fauna secret is fnADMxRzydATDKibGAciQlNQWBs-HJdpJS1vJaIM, then your Authorization header would look like:

Authorization: Bearer fnADMxRzydATDKibGAciQlNQWBs-HJdpJS1vJaIM

If you are using curl, you can specify the Authorization header like so:

curl -H 'Authorization: Bearer fnADMxRzydATDKibGAciQlNQWBs-HJdpJS1vJaIM' ...

HTTP Basic

To use the Fauna secret with HTTP Basic authentication, provide the secret as the username value. You do not need to provide a password. Make sure that you encode the credentials into a Base64 string. For example, if your Fauna secret is fnADMxRzydATDKibGAciQlNQWBs-HJdpJS1vJaIM, you can convert it to HTTP Basic credentials like so:

echo -n "fnADMxRzydATDKibGAciQlNQWBs-HJdpJS1vJaIM:" | base64
The trailing colon (:) is required as it separates the username and password values.

Then your Authorization header would look like:

Authorization: Basic Zm5BRE14Unp5ZEFUREtpYkdBY2lRbE5RV0JzLUhKZHBKUzF2SmFJTTo=

curl automatically performs the Base64 encoding. Use the -u flag and specify the secret with a trailing colon:

curl -u fnADMxRzydATDKibGAciQlNQWBs-HJdpJS1vJaIM: ...


Authentication errors result in HTTP 401 error responses, with one of the following messages:

Error message Description

Missing authorization header

The Authorization header was not included in the request.

Invalid authorization header

The value for the Authorization header has an invalid format.

Invalid database secret

The database secret decoded from the Authorization header is not valid.

For the /graphql endpoint, the error message is formatted as JSON:

Status: 200
Content-type: application/json

  "errors": [
    { "message": "Invalid database secret." }

For the /import endpoint, the error message is formatted as plain text:

Status: 401
Content-type: text/plain

Invalid database secret.

Is this article helpful? 

Tell Fauna how the article can be improved:
Visit Fauna's forums or email

Thank you for your feedback!