GraphQL endpoints

Overview

The Fauna GraphQL API provides three endpoints:

  • /graphql, for query execution.

  • /import, for schema management.

  • /ping, for testing connectivity to the GraphQL API.

The full endpoint URL depends on the Region Group you selected for your database. Fauna currently supports three Region Groups for decreased latency and improved data locality:

  • United States (US)

  • Europe (EU)

  • Classic (Europe and United States)

The full endpoint URL for each Region Group is listed in the following table:

Region Group Endpoint Description

United States (US)

https://graphql.us.fauna.com/graphql
https://graphql.us.fauna.com/import
https://graphql.us.fauna.com/ping

Executes GraphQL queries.
Imports a GraphQL schema.
For connectivity testing.

Europe (EU)

https://graphql.eu.fauna.com/graphql
https://graphql.eu.fauna.com/import
https://graphql.eu.fauna.com/ping

Executes GraphQL queries.
Imports a GraphQL schema.
For connectivity testing.

Classic

https://graphql.fauna.com/graphql
https://graphql.fauna.com/import
https://graphql.fauna.com/ping

Executes GraphQL queries.
Imports a GraphQL schema.
For connectivity testing.

Preview

https://graphql.fauna-preview.com/graphql
https://graphql.fauna-preview.com/import
https://graphql.fauna-preview.com/ping

Executes GraphQL queries.
Imports a GraphQL schema.
For connectivity testing.

GraphQL queries are executed by sending HTTP requests to the https://<environment>/graphql 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: https://graphql.org/learn/serving-over-http/

The Preview environment is where Fauna provides early access new to features. It is accessible by invitation only. Contact product@fauna.com for an invitation.

https://<environment>/graphql

The https://<environment>/graphql endpoint access GraphQL queries, and returns results in JSON format. See Getting started with GraphQL, or the GraphQL tutorials to see how queries work.

https://<environment>/import

The https://<environment>/import 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 creates the following schema objects in your Fauna database:

  • One collection for each declared GraphQL type (using the type name), with the exception of @embedded types.

  • One index for each declared query (using the query name), with the exception of queries annotated with the @resolver directive. You can use an existing collection with @collection, and an existing index with @index.

  • When a @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 plus three indexes, one for each side of the relationship, and a third covering the full relationship. For more information about many-to-many relationships and associative collections, see GraphQL Relationships.

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

The https://<environment>/import endpoint is not for importing data, it is only for importing a GraphQL schema. Use GraphQL mutations to create or update data.

When a GraphQL schema is imported, the GraphQL API enforces that schema for all subsequent GraphQL queries and mutations, until the schema is modified or replaced.

Schema enforcement happens in the GraphQL API only: the schema is not enforced at the database level.

FQL queries or UDFs can create or mutate documents, in the collections created for the schema, that do not comply with the schema. Such documents could cause queries and mutations to fail.

Care must be taken to ensure schema compatibility when using FQL or UDFs to create/mutate documents in GraphQL collections.

A basic GraphQL schema looks like:

type User {
  username: String!
}

type Query {
  allUsers: [User!]!
}

After importing a GraphQL schema, you can use the Fauna Dashboard to see all the newly created collections, indexes, and user-defined functions.

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

Get(Collection("User"))
{
  ref: Collection("User"),
  ts: 1618959271660000,
  history_days: 30,
  name: "User",
  data: {
    gql: {
      ts: Time("2021-04-20T22:54:31.557442Z"),
      meta: {
        name: "User",
        fields: [
          {
            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:

Get(Index("allUsers"))
{
  ref: Index("allUsers"),
  ts: 1618959271800000,
  active: true,
  serialized: true,
  name: "allUsers",
  source: Collection("User"),
  data: {
    gql: {
      ts: Time("2021-04-20T22:54:31.700473Z"),
      meta: {
        name: "allUsers",
        directives: [
          {
            name: "index",
            args: {
              name: "allUsers"
            }
          }
        ],
        type: {
          NotNull: {
            List: {
              NotNull: {
                Named: "User"
              }
            }
          }
        }
      }
    }
  },
  unique: false,
  partitions: 8
}

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

Modes

There are three import modes:

Mode Description

merge

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.

Since index definitions cannot be edited after creation, merge mode reports an error when an index definition would need to be modified to support the new schema.

Since merge incorporates a new schema with an existing schema, it is not possible to remove schema elements using merge. If removal is required, use replace instead.

replace

The replace mode replaces the current GraphQL metadata stored in collections, indexes, functions, and databases. replace is especially useful if you need to remove schema elements (types, inputs, and others). It does not change the underlying user-created documents Like merge mode, replace mode also creates missing collections, indexes, and functions.

Since index definitions cannot be edited after creation, replace mode reports an error when an index definition would need to be modified to support the new schema.

After replacing the schema, the underlying data may no longer work with existing queries. Fields that exist in documents that are not declared in the schema are not accessible using GraphQL queries. Fields that have new types may cause existing queries to fail. If you encounter such problems, update the schema accordingly or update the data using fauna-shell, Dashboard, or write a transformation script using one of the available drivers.

override

The override mode deletes all collections, indexes, and functions that are annotated with GraphQL metadata, pauses 60 seconds to allow for processing, then imports the new schema with merge mode. override lets you start over with a fresh schema that has no documents.

The purpose of override mode is to make it easy to experiment with varying schemas without worrying about how to migrate existing documents from the old schema to the new schema.

override mode causes data loss for the existing GraphQL schema. Collections, indexes, or documents that are not involved in the new GraphQL schema are not affected.

Specify the mode using a query parameter. For example:

POST /import?mode=replace

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

curl -H 'Authorization: Bearer <FAUNA_SECRET>' https://<environment>/import?mode=replace --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 with your GraphQL schema.

Handling import errors

When errors are encountered during schema import, they most often involve index definitions. Once an index exists, its definition cannot be modified. There are two strategies that you can use to resolve the errors:

  1. Create replacement indexes that define the appropriate terms and values definitions. There are two ways to use the replacement indexes:

    1. Renaming the existing index, and then create a new index using the correct definition and the original index name.

    2. Create the new index with a new name and correct definition, then update your schema using the @index directive directive.

    Once you know that the new index works correctly for your queries and mutations, and that the original index is no longer needed, you can delete the original index.

  2. Use override mode. This deletes all collections, indexes, and functions defined by the current schema, then the new schema is imported creating the required collections, indexes, and functions. The drawback is that all documents are deleted.

    Note that it is possible for override mode to end with an error. GraphQL schemas often require indexes with precise definitions to model relationships between types. When a new schema requires an index, and an index exists with the desired name but an incompatible definition, the GraphQL API aborts override mode to avoid interfering with FQL queries. You should assess whether adjusting your schema, or renaming existing indexes and updating FQL queries, is the better approach.

Authentication

Endpoints require authentication for a 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 as a Bearer token or using 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, include the secret as the username value. You do not need to include 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
Zm5BRE14Unp5ZEFUREtpYkdBY2lRbE5RV0JzLUhKZHBKUzF2SmFJTTo=
The trailing colon (:) is required as it separates the username and password values.

Then your Authorization header would look like:

Authorization: Basic Zm5BRE14Unp5ZEFUREtpYkdBY2lRbE5RV0JzLUhKZHBKUzF2SmFJTTo=

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

curl -u fnADMxRzydATDKibGAciQlNQWBs-HJdpJS1vJaIM: ...

Errors

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

Error message Description

Missing authorization header

The Authorization header is 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 docs@fauna.com

Thank you for your feedback!