## @replace: Methods

| Method                                                           | Description                                                |
| ---------------------------------------------------------------- | ---------------------------------------------------------- |
| `query<T>(query, schema, variables?, metadata?, headers?)`       | Execute a GraphQL query with required schema validation    |
| `mutation<T>(mutation, schema, variables?, metadata?, headers?)` | Execute a GraphQL mutation with required schema validation |

## @replace: Trace Metadata

All methods accept an optional `metadata` parameter for diagnostics labeling. See the [root SDK README](../../../README.md#trace-metadata) for details.

## Dynamic Headers

Static headers (e.g. a fixed `X-API-Version`) and auth headers (e.g. Bearer tokens, API keys) should be configured on the GraphQL integration in the Superblocks UI so they apply to every call automatically.

For values that change per request — for example a bearer token derived from the API's input or from `ctx.env` — pass an optional `headers` map as the final argument to `query()` or `mutation()`:

```typescript
const MeResponseSchema = z.object({
  data: z.object({
    me: z.object({ id: z.string(), email: z.string() }),
  }),
});

const result = await ctx.integrations.graphql.query(
  `query { me { id email } }`,
  { response: MeResponseSchema },
  undefined, // no variables
  undefined, // no trace metadata
  { Authorization: `Bearer ${ctx.env.UPSTREAM_TOKEN}` },
);
```

Since both `variables` and `metadata` accept plain objects, pass `undefined` for any of them that you do not need.
