> ## Documentation Index
> Fetch the complete documentation index at: https://docs.waffo.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# GraphQL API

> Query all your data with GraphQL read-only queries

## Overview

The Waffo Pancake GraphQL API provides **read-only** access to all your data. Use REST action endpoints for writes, and GraphQL for queries.

```
POST /v1/graphql
```

**Authentication:** API Key

<Note>
  The GraphQL API supports **queries only**. All write operations (create, update, delete) use the [REST action endpoints](/api-reference/introduction#endpoint-groups).
</Note>

## Making a Request

### Request Body

| Field       | Type   | Required | Description          |
| ----------- | ------ | -------- | -------------------- |
| `query`     | string | Yes      | GraphQL query string |
| `variables` | object | No       | Query variables      |

<CodeGroup>
  ```typescript SDK theme={"system"}
  import { WaffoPancake } from "@waffo/pancake-ts";

  const client = new WaffoPancake({
    merchantId: process.env.WAFFO_MERCHANT_ID!,
    privateKey: process.env.WAFFO_PRIVATE_KEY!,
  });

  interface StoresQuery {
    stores: Array<{ id: string; name: string; status: string }>;
  }

  const result = await client.graphql.query<StoresQuery>({
    query: `{ stores { id name status } }`,
  });
  console.log(result.stores);
  // => [{ id: "STO_2aUyqjCzEIiEcYMKj7TZtw", name: "My Store", status: "active" }]
  ```

  ```typescript TypeScript (fetch) theme={"system"}
  // Uses callApi() helper from authentication.mdx
  const result = await callApi("POST", "/v1/graphql", {
    query: "query { stores { id name status } }",
    variables: {},
  });
  console.log(result.data.stores);
  // => [{ id: "STO_2aUyqjCzEIiEcYMKj7TZtw", name: "My Store", status: "active" }]
  ```

  ```java Java theme={"system"}
  // Uses callApi() helper from authentication.mdx
  String body = """
      {"query":"query { stores { id name status } }","variables":{}}""";

  String response = callApi("POST", "/v1/graphql", body);
  System.out.println(response);
  // => {"data":{"stores":[{"id":"STO_2aUyqjCzEIiEcYMKj7TZtw","name":"My Store","status":"active"}]}}
  ```

  ```python Python theme={"system"}
  # Uses call_api() helper from authentication.mdx
  result = call_api("POST", "/v1/graphql", {
      "query": "query { stores { id name status } }",
      "variables": {},
  })
  stores = result["data"]["stores"]
  print(stores)
  # => [{"id": "STO_2aUyqjCzEIiEcYMKj7TZtw", "name": "My Store", "status": "active"}]
  ```

  ```go Go theme={"system"}
  // Uses callAPI() helper from authentication.mdx
  body := map[string]interface{}{
      "query":     "query { stores { id name status } }",
      "variables": map[string]interface{}{},
  }
  result, err := callAPI("POST", "/v1/graphql", body)
  if err != nil {
      log.Fatal(err)
  }
  fmt.Println(string(result))
  // => {"data":{"stores":[{"id":"STO_2aUyqjCzEIiEcYMKj7TZtw","name":"My Store","status":"active"}]}}
  ```

  ```rust Rust theme={"system"}
  // Uses call_api() helper from authentication.mdx
  let body = serde_json::json!({
      "query": "query { stores { id name status } }",
      "variables": {}
  });
  let result = call_api("POST", "/v1/graphql", &body).await?;
  println!("{}", result);
  // => {"data":{"stores":[{"id":"STO_2aUyqjCzEIiEcYMKj7TZtw","name":"My Store","status":"active"}]}}
  ```

  ```c C theme={"system"}
  /* Uses call_api() helper from authentication.mdx */
  const char *body = "{\"query\":\"query { stores { id name status } }\",\"variables\":{}}";
  char *response = call_api("POST", "/v1/graphql", body);
  printf("%s\n", response);
  free(response);
  ```

  ```cpp C++ theme={"system"}
  // Uses callApi() helper from authentication.mdx
  std::string body = R"({"query":"query { stores { id name status } }","variables":{}})";
  std::string response = callApi("POST", "/v1/graphql", body);
  std::cout << response << std::endl;
  // => {"data":{"stores":[{"id":"STO_2aUyqjCzEIiEcYMKj7TZtw","name":"My Store","status":"active"}]}}
  ```

  ```bash cURL theme={"system"}
  MERCHANT_ID="MER_2aUyqjCzEIiEcYMKj7TZtw"
  TIMESTAMP=$(date +%s)
  BODY='{"query":"query { stores { id name status } }","variables":{}}'
  BODY_HASH=$(echo -n "$BODY" | openssl dgst -sha256 -binary | base64 -w 0)
  CANONICAL_REQUEST="POST
  /v1/graphql
  $TIMESTAMP
  $BODY_HASH"

  SIGNATURE=$(echo -n "$CANONICAL_REQUEST" | openssl dgst -sha256 -sign private_key.pem | base64 -w 0)

  curl -X POST "https://api.waffo.ai/v1/graphql" \
    -H "Content-Type: application/json" \
    -H "X-Merchant-Id: $MERCHANT_ID" \
    -H "X-Timestamp: $TIMESTAMP" \
    -H "X-Signature: $SIGNATURE" \
    -d "$BODY"
  ```

  ```bash wget theme={"system"}
  MERCHANT_ID="MER_2aUyqjCzEIiEcYMKj7TZtw"
  TIMESTAMP=$(date +%s)
  BODY='{"query":"query { stores { id name status } }","variables":{}}'
  BODY_HASH=$(echo -n "$BODY" | openssl dgst -sha256 -binary | base64 -w 0)
  CANONICAL_REQUEST="POST
  /v1/graphql
  $TIMESTAMP
  $BODY_HASH"

  SIGNATURE=$(echo -n "$CANONICAL_REQUEST" | openssl dgst -sha256 -sign private_key.pem | base64 -w 0)

  wget -qO- "https://api.waffo.ai/v1/graphql" \
    --header="Content-Type: application/json" \
    --header="X-Merchant-Id: $MERCHANT_ID" \
    --header="X-Timestamp: $TIMESTAMP" \
    --header="X-Signature: $SIGNATURE" \
    --post-data="$BODY"
  ```
</CodeGroup>

### Status Codes

| Status | Description                                                                    |
| ------ | ------------------------------------------------------------------------------ |
| 200    | Query succeeded (GraphQL errors in response body `errors` field)               |
| 400    | Missing query / depth exceeded / invalid environment / missing or invalid role |
| 401    | Authentication failed                                                          |
| 403    | Operation type not allowed (only Query supported)                              |
| 500    | Internal server error                                                          |

***

## Schema Introspection

<Tip>
  **Recommended:** Use standard GraphQL introspection to discover the full schema. This ensures you always work with the latest types and fields.
</Tip>

<Warning>
  **GraphQL types differ from REST/SDK types.** For example, `prices` is a `Record<string, PriceInfo>` in REST but `[CurrencyPrice!]!` (array of `{currency, priceInfo}`) in GraphQL, and `metadata` is a parsed object in REST but a JSON string in GraphQL. Do not use SDK TypeScript type definitions to construct GraphQL queries — always use introspection or the examples below.
</Warning>

### Discover All Available Queries

```graphql theme={"system"}
query {
  __schema {
    queryType {
      fields {
        name
        description
        args {
          name
          type { name kind }
        }
      }
    }
  }
}
```

### Discover Type Fields

```graphql theme={"system"}
query {
  __type(name: "Store") {
    name
    fields {
      name
      type { name kind ofType { name } }
    }
  }
}
```

API Key authentication gives you access to **18 query types** including single-entity queries, list queries with filters, count queries, and analytics queries.

***

## Filtering

GraphQL queries support filters using typed filter objects:

| Type             | Operators                            | Example                                                |
| ---------------- | ------------------------------------ | ------------------------------------------------------ |
| `StringFilter`   | `eq`, `ne`, `in`, `contains`         | `{ storeId: { eq: "STO_xxx" } }`                       |
| `DateTimeFilter` | `eq`, `gt`, `lt`, `gte`, `lte`       | `{ createdAt: { gte: "2026-01-01" } }`                 |
| `IntFilter`      | `eq`, `gt`, `lt`, `gte`, `lte`       | `{ attemptCount: { gte: 3 } }`                         |
| `AmountFilter`   | `eq`, `ne`, `gt`, `gte`, `lt`, `lte` | `{ amount: { gte: "9.99" }, currency: { eq: "USD" } }` |
| `BooleanFilter`  | `eq`                                 | `{ isActive: { eq: true } }`                           |

<Note>
  `AmountFilter` values are decimal strings in the currency's major unit (e.g. `"9.99"`). An amount filter **must** be accompanied by a sibling `currency: { eq: "..." }` in the same `filter` object — a single currency per query. Cross-currency amount comparison is not supported.
</Note>

```graphql theme={"system"}
query {
  onetimeProducts(
    filter: {
      storeId: { eq: "STO_3bVzrkD0FJjFdZNLk8Ualx" }
      status: { eq: "active" }
    }
  ) {
    id
    name
    prices
  }
}
```

***

## Pagination

Use `limit` and `offset` for pagination. Use `*Count` queries to get total counts.

```graphql theme={"system"}
query {
  onetimeProducts(
    filter: { storeId: { eq: "STO_3bVzrkD0FJjFdZNLk8Ualx" } }
    limit: 10
    offset: 0
  ) {
    id
    name
  }
  onetimeProductsCount(
    filter: { storeId: { eq: "STO_3bVzrkD0FJjFdZNLk8Ualx" } }
  )
}
```

| Parameter | Type    | Description                         |
| --------- | ------- | ----------------------------------- |
| `limit`   | integer | Maximum number of results to return |
| `offset`  | integer | Number of results to skip           |

***

## Environment-Specific Fields

The API Key environment affects which product data is returned:

* `version` -- Returns the version for the specified environment
* `status` -- Returns the status in the specified environment

A product may be `active` in test but `inactive` in production if it hasn't been published yet.

***

## Query Examples

<CardGroup cols={2}>
  <Card title="Stores & Products" icon="store" href="/api-reference/endpoints/graphql/stores-and-products">
    Query stores, one-time products, subscription products, and product versions
  </Card>

  <Card title="Orders & Payments" icon="cart-shopping" href="/api-reference/endpoints/graphql/orders-and-payments">
    Query orders, subscription orders, payments, and refund tickets
  </Card>

  <Card title="Analytics" icon="chart-line" href="/api-reference/endpoints/graphql/analytics">
    Revenue statistics, payment analytics, trend analysis, and customer insights
  </Card>
</CardGroup>
