Exposing GraphQL APIs with Trusted Document IDs and GET Requests

Tom HouléTom Houlé

GraphQL typically requires clients to construct and send queries as part of POST requests. This works well for GraphQL-aware clients but can be challenging for systems that prefer simpler REST-like interfaces. This guide demonstrates how to expose specific GraphQL operations via GET requests using trusted document IDs, making your GraphQL API accessible to a wider range of clients.

Trusted Documents allow you to register an allow-list of GraphQL operations. Once registered, clients can execute these operations by referencing their document IDs rather than sending the full query text. This approach offers two significant benefits:

  1. Simplified client implementation: Clients can make simple GET requests without constructing GraphQL queries
  2. Enhanced security: Only pre-registered operations can be executed

While Trusted Documents are commonly used with POST requests, they also work with GET requests, following the GraphQL over HTTP specification. This allows clients to execute GraphQL operations using familiar REST-like patterns.

First, define the GraphQL operations you want to expose. For this example, we'll create two operations - a query and a mutation:

# get-product.graphql query GetProduct($id: ID!) { product(id: $id) { id name price description } } # create-order.graphql mutation CreateOrder($productId: ID!, $quantity: Int!) { createOrder(input: { productId: $productId, quantity: $quantity }) { id status total } }

The next step is to generate a manifest file for these operations. You can use various client tools for this purpose, as documented in the Trusted Documents page.

This creates a manifest.json file containing your operations and their document IDs.

You can also create a manifest.json file that is just one object where the keys are the document ids, and the values are the corresponding GraphQL queries.

Upload the manifest to your Grafbase project:

grafbase trust my-account/my-graph@main --manifest manifest.json --client-name api-gateway

Enable trusted documents in your grafbase.toml configuration:

[trusted_documents] enabled = true enforced = false # optional, only set this if you want to adopt trusted documents whole-sale

enabled will only cause the Gateway to accept trusted document queries, not to enforce their usage.

Now you can execute your GraphQL operations using simple GET requests with document IDs:

curl -X GET 'https://myapi.grafbase.app/graphql?document_id=<get-product-doc-id>&variables={"id":"prod-123"}' \ -H 'x-grafbase-client-name: api-gateway'

While mutations are typically performed with POST requests, they can also work with GET requests when using document IDs:

curl -X GET 'https://myapi.grafbase.app/graphql?document_id=<create-order-doc-id>&variables={"productId":"prod-123","quantity":2}' \ -H 'x-grafbase-client-name: api-gateway'

Common issues when working with trusted document IDs and GET requests:

  • 404 Not Found: Ensure the document ID exists in your trusted documents manifest
  • Client name mismatch: Verify the x-grafbase-client-name header matches the name used when uploading the manifest
  • Variable format errors: Ensure variables are properly JSON-encoded in the URL. Note that the usage of variables is optional, queries that are always the same do not need them.
  • URL length limitations: For operations with many variables, consider using POST requests instead of GET

Using trusted document IDs with GET requests provides a bridge between GraphQL and REST-like APIs. This approach allows you to leverage GraphQL's power while exposing a simple interface for clients that prefer traditional HTTP methods. By registering only the operations you want to expose, you maintain control over your API's surface area while providing an accessible interface for all your clients.

// Using fetch to call a trusted document const fetchProduct = async (productId) => { const response = await fetch( `https://myapi.grafbase.app/graphql?document_id=abcdef123456&variables={"id":"${productId}"}`, { method: 'GET', headers: { 'x-grafbase-client-name': 'api-gateway' } } ); return response.json(); };
import requests import json # Using requests to call a trusted document def fetch_product(product_id): variables = json.dumps({"id": product_id}) response = requests.get( f"https://myapi.grafbase.app/graphql?document_id=abcdef123456&variables={variables}", headers={"x-grafbase-client-name": "api-gateway"} ) return response.json()

For more complex variables, you might need to URL-encode the JSON:

# URL-encode the variables JSON VARIABLES=$(python -c "import urllib.parse; print(urllib.parse.quote('{\"id\":\"prod-123\"}'))") # Make the request with encoded variables curl -X GET "https://myapi.grafbase.app/graphql?document_id=abcdef123456&variables=$VARIABLES" \ -H 'x-grafbase-client-name: api-gateway'

Trusted document IDs are particularly useful for webhook integrations. When a third-party service needs to trigger an action in your system:

  1. Create a specific mutation for the webhook action
  2. Register it as a trusted document
  3. Provide the webhook URL with the document ID
https://gateway.myapp.dev/graphql?document_id=webhook123&variables={"payload":"..."}

For cron jobs or scheduled tasks that need to perform specific operations:

# Crontab entry that runs daily at midnight 0 0 * * * curl -X GET 'https://myapi.grafbase.app/graphql?document_id=dailyReport&variables={"date":"'$(date +'%Y-%m-%d')'"}' -H 'x-grafbase-client-name: api-gateway' > /var/log/daily-report.log

Using trusted document IDs with GET requests allows for effective HTTP caching:

# Request that leverages HTTP caching curl -X GET 'https://myapi.grafbase.app/graphql?document_id=getPopularProducts&variables={}' \ -H 'x-grafbase-client-name: api-gateway' \ -H 'Cache-Control: max-age=300'

Get Started

Learn how to simplify GraphQL API access for non-GraphQL clients with trusted document IDs.