GraphQL Connector Guide

The GraphQL connector lets Tealfabric workflows execute GraphQL queries and mutations against external APIs. It is useful when you need a generic integration layer for read/write operations across services that expose GraphQL schemas.

Document information
FieldValue
Canonical URL/docs/04_connecting-systems/connectors/g/graphql
Version (published date)2026-05-08
Tagsconnectors, reference, graphql
Connector IDgraphql-1.0.0

GraphQL connector flow showing token-authenticated mutations, query-based retrieval, and workflow-driven API orchestration.

Configure authentication

Set token to a valid bearer token for the target GraphQL service. Set base_url to the API host or full GraphQL endpoint (for example https://api.example.com or https://api.example.com/graphql). When base_url does not include /graphql, the connector appends /graphql automatically.

Use timeout_seconds (default 30) for slow or complex operations and ensure the token has schema-level permissions required for the fields and mutations your workflow executes.

Execute mutations with send

Use send for GraphQL mutations that create, update, or delete records. Keep mutation text and variables separate so your workflow stays clear and secure.

const baseUrl = "https://api.example.com/api/v1";
const tenantId = "<TENANT_ID>";
const apiKey = "<API_KEY>";

async function createUser(integrationId: string) {
  const response = await fetch(`${baseUrl}/integrations/${encodeURIComponent(integrationId)}/execute`, {
    method: "POST",
    headers: {
      "X-API-Key": apiKey,
      "X-Tenant-ID": tenantId,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      operation: "send",
      mutation: `
        mutation CreateUser(name: String!, email: String!) {
          createUser(name: name, email: email) {
            id
            name
            email
          }
        }
      `,
      variables: {
        name: "Alex Taylor",
        email: "alex.taylor@example.com"
      }
    }),
  });
  if (!response.ok) throw new Error(`Request failed: ${response.status}`);
  return response.json();
}
curl -X POST "https://api.example.com/api/v1/integrations/<ENTITY_ID>/execute" \
  -H "X-API-Key: <API_KEY>" \
  -H "X-Tenant-ID: <TENANT_ID>" \
  -H "Content-Type: application/json" \
  -d '{
    "operation": "send",
    "mutation": "mutation CreateUser($name: String!, email: String!) { createUser(name: $name, email: email) { id name email } }",
    "variables": {
      "name": "Alex Taylor",
      "email": "alex.taylor@example.com"
    }
  }'
{
  "success": true,
  "data": {
    "message_count": 1,
    "data": {
      "createUser": {
        "id": "<ENTITY_ID>",
        "name": "Alex Taylor",
        "email": "alex.taylor@example.com"
      }
    },
    "response": {
      "data": {
        "createUser": {
          "id": "<ENTITY_ID>",
          "name": "Alex Taylor",
          "email": "alex.taylor@example.com"
        }
      }
    }
  }
}

Execute queries with receive

Use receive for GraphQL queries that fetch entities and related fields for workflow decisions. Variables help keep requests reusable and avoid unsafe string interpolation.

const baseUrl = "https://api.example.com/api/v1";
const tenantId = "<TENANT_ID>";
const apiKey = "<API_KEY>";

async function getUser(integrationId: string) {
  const response = await fetch(`${baseUrl}/integrations/${encodeURIComponent(integrationId)}/execute`, {
    method: "POST",
    headers: {
      "X-API-Key": apiKey,
      "X-Tenant-ID": tenantId,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      operation: "receive",
      query: `
        query GetUser(id: ID!) {
          user(id: id) {
            id
            name
            email
          }
        }
      `,
      variables: {
        id: "<ENTITY_ID>"
      }
    }),
  });
  if (!response.ok) throw new Error(`Request failed: ${response.status}`);
  return response.json();
}
curl -X POST "https://api.example.com/api/v1/integrations/<ENTITY_ID>/execute" \
  -H "X-API-Key: <API_KEY>" \
  -H "X-Tenant-ID: <TENANT_ID>" \
  -H "Content-Type: application/json" \
  -d '{
    "operation": "receive",
    "query": "query GetUser($id: ID!) { user(id: $id) { id name email } }",
    "variables": {
      "id": "<ENTITY_ID>"
    }
  }'
{
  "success": true,
  "data": {
    "message_count": 1,
    "data": [
      {
        "id": "<ENTITY_ID>",
        "name": "Alex Taylor",
        "email": "alex.taylor@example.com"
      }
    ],
    "total_size": 1
  }
}

Bidirectional sync

Use sync to run an optional outbound mutation and/or inbound query in one call. Empty outbound or inbound objects are skipped (PHP !empty semantics).

{
  "operation": "sync",
  "outbound": {
    "mutation": "mutation { updateUser(id: \"1\", name: \"Alex\") { id name } }"
  },
  "inbound": {
    "query": "query { user(id: \"1\") { id name email } }"
  }
}

Sequential batch

Use batch to run multiple send or receive sub-operations. Each entry supports operation or type (default receive) and optional nested data.

Connection test

test validates token configuration and runs the introspection query { __schema { queryType { name } } } against the configured endpoint. base_url must be set before any GraphQL request.

{
  "success": true,
  "data": {
    "message": "GraphQL connection test successful",
    "details": {
      "api_base_url": "https://api.example.com"
    }
  }
}

Reliability guidance

Most GraphQL failures come from token permission issues, schema mismatches, or variable type errors. Validate authentication first, then verify fields, arguments, and variable shapes against the API schema.

For stable production workflows, request only required fields, handle errors responses explicitly, and use pagination for large collections. This keeps GraphQL operations predictable and efficient.

Additional resources