Graphdocs

Features

Environments

Serving production and staging content from the same API.

Content types and entries live in an environment. Production is your live content, and what the API serves by default. Staging is a separate copy where your team can prepare changes, preview them, and push them to production when they are ready.

Media, languages, roles, API keys and settings are shared by both environments; only content types and entries are separate.

Choosing an environment

Every REST and GraphQL request takes the environment as a query parameter or a header:

# Query parameter
curl "https://api.graphcms.io/v1/content/blog-posts?environment=staging" \
-H "Authorization: Bearer $GRAPH_API_KEY"
# Header
curl https://api.graphcms.io/v1/content/blog-posts \
-H "Authorization: Bearer $GRAPH_API_KEY" \
-H "X-Environment: staging"
curl "https://api.graphcms.io/graphql?environment=staging" \
-H "Authorization: Bearer $GRAPH_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query":"{ contentTypes { slug } }"}'
  • With neither, the request uses production.
  • The value is production or staging, case-insensitive. If both are sent, the query parameter wins.
  • It applies to writes as well as reads: a GraphQL mutation sent with environment=staging changes staging only.
  • The same API key works in both environments. There is no separate staging key.

Errors

SituationRESTGraphQL
Any other value, such as environment=prod400: Unknown environment "prod". Use "production" or "staging".Error with code BAD_USER_INPUT
staging before your workspace has set it up404: This team has no staging environment yet. Set it up from the dashboard.Error with code BAD_USER_INPUT
staging when your plan doesn't include it402: The staging environment isn’t included in this team’s plan.Error with code BAD_USER_INPUT

Setting up staging

Staging is created from the dashboard. The environment dropdown next to the logo switches the dashboard between production and staging; choosing staging the first time sets it up as a copy of production. Setting up and resetting staging needs the environments.manage permission (owners and admins by default).

Moving changes to production

The Changes screen (linked from the environment dropdown) lists what differs between the two environments:

  • Staging changes can be pushed to production, or discarded.
  • Production changes, edits made directly in production, can be copied into staging.
  • An item changed in both since they last matched is a conflict; copying it overwrites the other side.

Selecting a change brings along what it depends on: an entry brings its content type when that type is new or changed, and deleting a type brings the deletion of its entries. Every push runs in one transaction, so it either applies completely or not at all, and each push is recorded under History. Pushing to production needs the environments.push permission.

Pushing is done in the dashboard; there is no API for it.

Preview deployments

The usual setup is one codebase, deployed twice, with the environment as configuration:

.env (preview deployment)
GRAPH_API_KEY=graph_YOUR_API_KEY
GRAPH_ENVIRONMENT=staging
lib/graphcms.js
1const API_URL = 'https://api.graphcms.io/v1';
2const ENVIRONMENT = process.env.GRAPH_ENVIRONMENT ?? 'production';
3
4export async function getEntries(type) {
5 const response = await fetch(`${API_URL}/content/${type}`, {
6 headers: {
7 Authorization: `Bearer ${process.env.GRAPH_API_KEY}`,
8 'X-Environment': ENVIRONMENT,
9 },
10 });
11 const { data } = await response.json();
12 return data;
13}

With the SDK, pass environment:

1import { GraphCMS } from '@graphcms/sdk';
2
3const graph = new GraphCMS({
4 apiKey: process.env.GRAPH_API_KEY,
5 environment: process.env.GRAPH_ENVIRONMENT ?? 'production',
6});
7
8// Or derive a staging client from an existing one:
9const staging = graph.withConfig({ environment: 'staging' });

Your production site reads production, and the preview site shows exactly what production will look like after the next push.