Skip to main content

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
The GraphQL API supports queries only. All write operations (create, update, delete) use the REST action endpoints.

Making a Request

Request Body

FieldTypeRequiredDescription
querystringYesGraphQL query string
variablesobjectNoQuery variables
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" }]
// 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" }]
// 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"}]}}
# 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"}]
// 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"}]}}
// 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"}]}}
/* 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);
// 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"}]}}
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"
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"

Status Codes

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

Schema Introspection

Recommended: Use standard GraphQL introspection to discover the full schema. This ensures you always work with the latest types and fields.
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.

Discover All Available Queries

query {
  __schema {
    queryType {
      fields {
        name
        description
        args {
          name
          type { name kind }
        }
      }
    }
  }
}

Discover Type Fields

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:
TypeOperatorsExample
StringFiltereq, ne, in, contains{ storeId: { eq: "STO_xxx" } }
DateTimeFiltereq, gt, lt, gte, lte{ createdAt: { gte: "2026-01-01" } }
IntFiltereq, gt, lt, gte, lte{ amount: { gte: 1000 } }
BooleanFiltereq{ isActive: { eq: true } }
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.
query {
  onetimeProducts(
    filter: { storeId: { eq: "STO_3bVzrkD0FJjFdZNLk8Ualx" } }
    limit: 10
    offset: 0
  ) {
    id
    name
  }
  onetimeProductsCount(
    filter: { storeId: { eq: "STO_3bVzrkD0FJjFdZNLk8Ualx" } }
  )
}
ParameterTypeDescription
limitintegerMaximum number of results to return
offsetintegerNumber 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

Stores & Products

Query stores, one-time products, subscription products, and product versions

Orders & Payments

Query orders, subscription orders, payments, and refund tickets

Analytics

Revenue statistics, payment analytics, trend analysis, and customer insights