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 parametercurl "https://api.graphcms.io/v1/content/blog-posts?environment=staging" \ -H "Authorization: Bearer $GRAPH_API_KEY"# Headercurl 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
productionorstaging, case-insensitive. If both are sent, the query parameter wins. - It applies to writes as well as reads: a GraphQL mutation sent with
environment=stagingchanges staging only. - The same API key works in both environments. There is no separate staging key.
Errors
| Situation | REST | GraphQL |
|---|---|---|
Any other value, such as environment=prod | 400: Unknown environment "prod". Use "production" or "staging". | Error with code BAD_USER_INPUT |
staging before your workspace has set it up | 404: 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 it | 402: 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:
GRAPH_API_KEY=graph_YOUR_API_KEYGRAPH_ENVIRONMENT=staging1const API_URL = 'https://api.graphcms.io/v1';2const ENVIRONMENT = process.env.GRAPH_ENVIRONMENT ?? 'production';34export 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';23const graph = new GraphCMS({4 apiKey: process.env.GRAPH_API_KEY,5 environment: process.env.GRAPH_ENVIRONMENT ?? 'production',6});78// 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.