# Headers

Learn how to use headers as a global way to send more specific requests to our API

## Overview

HTTP headers are a set of key-value pairs included in HTTP requests. They are essential for communicating extra information between the client (you) and the server. 

When making GraphQL queries over HTTP, headers are typically used to send important details, like authentication info, content type information, or custom information needed by the server.

Think of HTTP headers as “metadata” for your request, as they carry information about the request itself rather than the actual query content. 

Each header has a name (like `"Authorization"`) and a value (like `"Bearer YOUR_TOKEN_HERE"`).

For example:

```
Authorization: Bearer YOUR_TOKEN_HERE
Content-Type: application/json
```

## HTTP headers in GraphQL

These are the most commonly used headers in GraphQL:

- **Authorization**: You need an authorization token for secure API access in Hygraph. You'll use **HTTP headers** to pass authentication tokens, specifically the `Authorization` header with a **Bearer token**. This process ensures that only authorized users or systems can access your data.
    - For example: `Authorization: Bearer YOUR_TOKEN_HERE`
- **Content-Type**: This header tells the server what format the request body is in. In GraphQL, it's usually JSON.
    - For example: `Content-Type: application/json`
- **Custom Headers**: If you need to send any specific info to the server, you can add your own headers. The [custom headers](https://hygraph.com/docs/api-reference/content-api/headers#custom-headers) shown in this document, are headers that Hygraph specifically uses to control aspects related to how the data should be fetched. While they follow the general structure of HTTP headers, they are unique to Hygraph's API and not standard HTTP headers like `Authorization` or `Content-Type`.
    - For example: `gcms-stage: DRAFT`

### Add headers to a GraphQL query

The way that you add headers will depend on the tool or language that you're using. Here's how you'd typically add headers in two common ways: using `cURL` (a command-line tool) and `JavaScript` (fetch API).

Example with `cURL`:

```bash
curl -X POST -H "Content-Type: application/json" \
     -H "Authorization: Bearer YOUR_TOKEN_HERE" \
     -d '{"query": "{ yourQueryHere }"}' \
     https://your-graphql-api.com/graphql
```

Example with `JavaScript`:

```jsx
fetch("https://your-graphql-api.com/graphql", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_TOKEN_HERE"
  },
  body: JSON.stringify({
    query: "{ yourQueryHere }"
  })
})
  .then(response => response.json())
  .then(data => console.log(data));
```

**Pro Tip:**

The `headers` object shown in of both examples above is where we specify the `HTTP` headers. Each header will let the server understand the context of your request.

## Custom headers

 You can use headers as a global way to send more specific requests to our API. While you could use parameters for this, it is generally easier to dynamically change headers than parameters in a query.

This is where you add headers in the API Playground:

![Headers in the API Playground](https://hygraph.com/images/docs/api-reference/content-api/headers-api-playground.png)

### gcms-locales

This header works in the same way as [using the query input for locales](https://hygraph.com/docs/api-reference/content-api/localization#fallback-locales).

You can pass the `gcms-locales` header for localized content with your required locales. It is just another way besides the query param to decide which locales a query should return. Basically, the placement is different - header vs. query - but the result is the same. Using one or the other mostly comes down to the developer's preference.

**Why use `gmcs-locales` instead of the query param then?**

To keep queries exactly the same across different environments - production, development, etc. - and then instead of passing the param to the query, you use the header.

In some specific cases passing headers could be easier than putting the params in the query itself.

Example usage `'gcms-locales': 'rb, de, en'`:

```js
const fetch = require('cross-fetch');

const headers = {
  'Content-Type': 'application/json',
  'gcms-locales': 'rb, de, en',
};

const body = JSON.stringify({ query: '{ products { name } }' });

const { products } = await fetch('<your-hygraph-endpoint>', {
  method: 'POST',
  headers,
  body,
});
```

You can also pass an array of locales to `gcms-locales` to define your fallback preference.

### gcms-stage

This header works in the same way as [using the stage input on a query](https://hygraph.com/docs/api-reference/content-api/queries#fetching-stages).

You can pass the `gcms-stage` header to specify the stage of your content. It is just another way besides the query param to decide which stage a query should return. Basically, the placement is different - header vs. query - but the result is the same. Using one or the other mostly comes down to the developer's preference.

**Why use `gcms-stage` instead of the query param then?**

To keep queries exactly the same across different environments - production, development, etc. - and then instead of passing the param to the query, you use the header.

In some specific cases passing headers could be easier than putting the params in the query itself.

Example usage `'gcms-stage': 'DRAFT'`:

```js
const fetch = require('cross-fetch');

const headers = {
  'Content-Type': 'application/json',
  'gcms-stage': 'DRAFT',
};

const body = JSON.stringify({ query: '{ products { name } }' });

const { products } = await fetch('<your-hygraph-endpoint>', {
  method: 'POST',
  headers,
  body,
});
```

### hyg-stale-if-error

This header for the [High performance endpoint](https://hygraph.com/docs/api-reference/basics/caching#stale-if-error) lets you set `stale-if-error` on a per query basis.

This cache header can be used to fine-tune our default caching behavior. For instance, we could use it to make sure we return stale data on errors for much longer.

The need to use this header highly depends on the use-case and whether it's important to always get fresh data or to always get data, no matter if stale or new.

Example usage `'hyg-stale-if-error': '21600'`:

```js
const fetch = require('cross-fetch');

const headers = {
  'Content-Type': 'application/json',
  'hyg-stale-if-error': '21600',
};

const body = JSON.stringify({ query: '{ products { name } }' });

const { products } = await fetch('<your-hygraph-endpoint>', {
  method: 'POST',
  headers,
  body,
});
```

The values are in seconds. The default value is `86400`, but this can be adjusted **on dedicated clusters** if needed.

**Pro Tip:**
This is only available on the <b>High performance</b> endpoint.

The default `Stale-if-error` for all **shared clusters** is 86400s (1 day). This value is customizable for **dedicated clusters**.

To check what your current default is, send a request to the [high-performance endpoint](https://hygraph.com/docs/api-reference/basics/caching#high-performance-endpoint) and check the response headers called `gcms-origin-cache-control`. On a shared cluster, the value of the response header would be similar to this `s-maxage=31536000, stale-if-error=86400, stale-while-revalidate=0`.

### hyg-stale-while-revalidate

This header for the [High performance endpoint](https://hygraph.com/docs/api-reference/basics/caching#stale-while-revalidate) lets you set `stale-while-revalidate` on a per query basis.

This cache header can be used to fine-tune our default caching behavior. For instance, we could use it to make sure we return stale data while the cache is revalidating.

The need to use this header highly depends on the use-case and whether it's important to always get fresh data or to always get data, no matter if stale or new.

Example usage `'hyg-stale-while-revalidate': '27'`:

```js
const fetch = require('cross-fetch');

const headers = {
  'Content-Type': 'application/json',
  'hyg-stale-while-revalidate': '27',
};

const body = JSON.stringify({ query: '{ products { name } }' });

const { products } = await fetch('<your-hygraph-endpoint>', {
  method: 'POST',
  headers,
  body,
});
```

The values are in seconds. The default value is `0`, but this can be adjusted **on dedicated clusters** if needed.

**Pro Tip:**
This is only available on the <b>High performance</b> endpoint.

The default `stale-while-revalidate` for our **shared clusters** is `0`. This value is customizable for **dedicated clusters**.

To check what your current default is, send a request to the [high-performance endpoint](https://hygraph.com/docs/api-reference/basics/caching#high-performance-endpoint) and check the response headers called `gcms-origin-cache-control`. On a shared cluster, the value of the response header would be similar to this `s-maxage=31536000, stale-if-error=86400, stale-while-revalidate=0`.

### x-debug-complexity

You can use this header to enable complexity debugging, so the [complexity tree](https://hygraph.com/docs/api-reference/basics/query-complexity#complexity-tree-json-output) is returned.

The possible values are `true` & `false`.

Example usage `'x-debug-complexity': 'true'`:

```js
const fetch = require('cross-fetch');

const headers = {
  'Content-Type': 'application/json',
  'x-debug-complexity': 'true',
};

const body = JSON.stringify({ query: '{ products { name } }' });

const { products } = await fetch('<your-hygraph-endpoint>', {
  method: 'POST',
  headers,
  body,
});
```
