Popeyes API endpoint
Returns one restaurant's menu grouped into categories (e.g. "Big Box", "Chicken Wraps"). Every entry is an item, a combo, a picker (a variant-choice product such as "choose your side") or a bundle, and carries a price reflecting this specific restaurant when Popeyes reports one for that exact entry -- a missing price does not mean the item is free, it means this restaurant's pricing call did not cover that entry. Some menu entries are published directly at the top level outside any named section; these are grouped into a synthetic "Featured" category (featured true). Entries of type ITEM also carry published nutrition facts and allergen data when Popeyes reports them for that item; COMBO/PICKER/BUNDLE entries do not carry their own nutrition/allergen data.
/popeyes/menuReturns one restaurant's menu grouped into categories (e.g. "Big Box", "Chicken Wraps"), with real per-store pricing merged in.
Query parameters:
store_id (required) — Popeyes' numeric store id, from /popeyes/locations, e.g. 14156.market (optional, default US) — restaurant market: US or CA.Response includes store_id, currency, categories[], item_count, source_url, and fetched_at. Each category has id, name, featured, and items[]. Each item has id, type, name, image_url, price, nutrition, and allergens.
price carries default_cents/default (the item's base price) plus min_cents/min and max_cents/max bounding items whose price varies with the options chosen — for a fixed-price item all three are equal.
nutrition and allergens are populated only for entries of type ITEM — Sanity's schema does not carry nutrition/allergen fields directly on COMBO, PICKER, or BUNDLE entries. A missing field within nutrition/allergens means Popeyes did not publish that value for this item, not that the value is zero or the allergen is absent. nutrition carries calories, fat_g, saturated_fat_g, trans_fat_g, cholesterol_mg, sodium_mg, carbohydrates_g, fiber_g, sugar_g, proteins_g, and serving_weight_g. allergens carries a raw upstream indicator (values observed: 0, 1, 3) for each of milk, eggs, fish, shellfish, peanuts, tree_nuts, soy, wheat, mustard, sesame, celery, lupin, gluten, and sulphur_dioxide — Popeyes does not publicly document what the non-zero scale means beyond "present in some form".
market: CA returns Canadian restaurants' menus from Popeyes' own separate Canadian Sanity dataset, with currency: "CAD".
| Field | Filled in, of 16 checked | Values in the sample |
|---|---|---|
| id | 15 | |
| name | 16 | “Limited Time Items” and 15 other values |
| items | 16 | median 3 entries |
| featured | 1 | true in 1 of 1 |
| Parameter | Type | Required | Default | Description | Example |
|---|---|---|---|---|---|
| store_id | string | Yes | Popeyes' numeric store id, from /popeyes/locations | 14156 | |
| market | string | No | Restaurant market: `US` (default) or `CA` | US | |
| x-api-key (header) | string | Yes | API key required |
curl -X GET "https://api.crawlora.net/api/v1/popeyes/menu?store_id=14156" \ -H "x-api-key: $CRAWLORA_API_KEY"
{
"code": 200,
"msg": "OK",
"data": {
"store_id": "14156",
"currency": "USD",
"categories": [
{
"id": "c17aefeb-aabe-4c21-ae57-137eb724f565",
"name": "Limited Time Items",
"items": [
{
"id": "item_103182",
"type": "ITEM",
"name": "Cheese Bites",
"image_url": "https://cdn.sanity.io/images/czqk28jt/prod_plk_us/5030d73a5159ee07173fd5de0495fe9d089513c3-888x570.png",
"price": {
"default_cents": 399,
"default": 3.99,
"min_cents": 199,
"min": 1.99,
"max_cents": 399,
"max": 3.99
},
"nutrition": {
"calories": 560,
"fat_g": 44,
"trans_fat_g": 1,
"cholesterol_mg": 75,
"sodium_mg": 1470,
"carbohydrates_g": 23,
"fiber_g": 2,
"sugar_g": 2,
"proteins_g": 17
}
}
]
}
],
"item_count": 98,
"source_url": "https://czqk28jt.apicdn.sanity.io/v1/graphql/prod_plk_us/default",
"fetched_at": "2026-09-02T00:00:00Z"
}
}Request schema
No body schema
Response schema
#/definitions/popeyes.menuResponseDoc
| Field | Type | Required | Enum | Bounds | Example | Description |
|---|---|---|---|---|---|---|
| code | integer | No | Code is the HTTP status code or a custom code used to indicate the result of the request @example 200 | |||
| data | popeyes.MenuResponse | No | ||||
| data.categories | array | No | ||||
| data.categories[].featured | boolean | No | ||||
| data.categories[].id | string | No | ||||
| data.categories[].items | array | No | ||||
| data.categories[].items[].allergens | popeyes.Allergens | No | ||||
| data.categories[].items[].allergens.celery | number | No | ||||
| data.categories[].items[].allergens.eggs | number | No | ||||
| data.categories[].items[].allergens.fish | number | No | ||||
| data.categories[].items[].allergens.gluten | number | No | ||||
| data.categories[].items[].allergens.lupin | number | No | ||||
| data.categories[].items[].allergens.milk | number | No | ||||
| data.categories[].items[].allergens.mustard | number | No | ||||
| data.categories[].items[].allergens.peanuts | number | No | ||||
| data.categories[].items[].allergens.sesame | number | No | ||||
| data.categories[].items[].allergens.shellfish | number | No | ||||
| data.categories[].items[].allergens.soy | number | No | ||||
| data.categories[].items[].allergens.sulphur_dioxide | number | No | ||||
| data.categories[].items[].allergens.tree_nuts | number | No | ||||
| data.categories[].items[].allergens.wheat | number | No | ||||
| data.categories[].items[].id | string | No | item_103182 | |||
| data.categories[].items[].image_url | string | No | ||||
| data.categories[].items[].name | string | No | Cheese Bites | |||
| data.categories[].items[].nutrition | popeyes.Nutrition | No | ||||
| data.categories[].items[].nutrition.calories | number | No | 560 | |||
| data.categories[].items[].nutrition.carbohydrates_g | number | No | 23 | |||
| data.categories[].items[].nutrition.cholesterol_mg | number | No | 75 | |||
| data.categories[].items[].nutrition.fat_g | number | No | 44 | |||
| data.categories[].items[].nutrition.fiber_g | number | No | 2 | |||
| data.categories[].items[].nutrition.proteins_g | number | No | 17 | |||
| data.categories[].items[].nutrition.saturated_fat_g | number | No | ||||
| data.categories[].items[].nutrition.serving_weight_g | number | No | ||||
| data.categories[].items[].nutrition.sodium_mg | number | No | 1470 | |||
| data.categories[].items[].nutrition.sugar_g | number | No | 2 | |||
| data.categories[].items[].nutrition.trans_fat_g | number | No | 1 | |||
| data.categories[].items[].price | popeyes.Price | No | ||||
| data.categories[].items[].price.default | number | No | 3.99 | |||
| data.categories[].items[].price.default_cents | integer | No | 399 | |||
| data.categories[].items[].price.max | number | No | ||||
| data.categories[].items[].price.max_cents | integer | No | ||||
| data.categories[].items[].price.min | number | No | ||||
| data.categories[].items[].price.min_cents | integer | No | ||||
| data.categories[].items[].type | string | No | ITEM | |||
| data.categories[].name | string | No | Chicken Wraps | |||
| data.currency | string | No | USD | |||
| data.fetched_at | string | No | ||||
| data.item_count | integer | No | 120 | |||
| data.source_url | string | No | ||||
| data.store_id | string | No | 14156 | |||
| msg | unknown | No | Msg is the message that describes the result of the request @example "Request successful" |
| Status | Description | Schema |
|---|---|---|
| 400 | Bad Request | #/definitions/app.Response |
| 404 | Not Found | #/definitions/app.Response |
| 429 | Too Many Requests | #/definitions/app.Response |
| 503 | Service Unavailable | #/definitions/app.Response |
Use environment variables for secrets and keep Crawlora API keys server-side.
curl -X GET "https://api.crawlora.net/api/v1/popeyes/menu?store_id=14156" \
-H "x-api-key: $CRAWLORA_API_KEY"