Subway API endpoint
Returns one Subway store's complete menu: every category, every product, and for each purchasable size (Footlong, 6-inch, etc.) its price, full nutrition panel (calories, fat, sodium, protein and more) and allergen disclosures. Store IDs come from a GET /subway/store result's store_id field. This endpoint currently covers US stores only: the menu is not available for non-US stores, which return 404 -- see GET /subway/combos for the bundle/combo categories that are available in other markets. Categories carry is_main_category: true for human-browsable menu sections (Sandwiches, Drinks, Salads, ...) and false for Subway's own internal build/customization groupings, which are included for completeness but are not meant to be shown as menu sections on their own.
/subway/menuCoverage: US stores only. The upstream menu route backing this endpoint is not served for non-US stores, which return 404. Confirmed 2026-09-05 against stores in GB, DE and FR, under every locale variant. Non-US markets do expose bundle/combo categories with price ranges — see /api/v1/subway/combos — but those carry no individual products, and no nutrition or allergen data.
Query parameters:
store_id (required) — the store's ordering-platform ID, from a /api/v1/subway/store result's store_id field, e.g. 75376-0.Response includes store_id, currency, category_count, product_count, categories[], source_url, and fetched_at.
Each categories[] entry has id, name, description, slug, is_main_category, and items[]. Subway models both human-browsable menu sections (Sandwiches, Drinks, Salads, ...) and its own internal build/customization groupings as categories in the same flat list — is_main_category is true for the former and false for the latter; filter on it for a human-facing menu.
Each items[] entry is one product family (e.g. "Steak Philly") with id, name, slug, and variants[] — one or more purchasable builds of that item (e.g. its Footlong and 6-inch sizes), each priced and nutritioned independently.
Each variants[] entry has id, name, size (the build label, e.g. Footlong, 6''), price, available, nutrition[], allergens[], and image_asset_urn. image_asset_urn is Subway's own Adobe AEM asset identifier, not a directly fetchable URL.
Each nutrition[] entry has name (already carrying its unit, e.g. TOTAL FAT (g), SODIUM (mg)) and value.
Each allergens[] entry has name, contains, and may_contain.
| Field | Filled in, of 94 checked | Values in the sample |
|---|---|---|
| id | 94 | |
| name | 94 | “Snacks, Sides & Desserts” and 39 other values |
| slug | 94 | |
| is_main_category | 94 | true in 21 of 94 |
| items | 81 | median 1 entry |
| description | 16 | “Sweet. Spicy. So Swicy. Don’t miss the limited-time subs an…” and 15 other values |
| Parameter | Type | Required | Default | Description | Example |
|---|---|---|---|---|---|
| store_id | string | Yes | Store ID from a /subway/store result's store_id | 75376-0 | |
| x-api-key (header) | string | Yes | API key required |
curl -X GET "https://api.crawlora.net/api/v1/subway/menu?store_id=75376-0" \ -H "x-api-key: $CRAWLORA_API_KEY"
{
"code": 200,
"msg": "OK",
"data": {
"store_id": "75376-0",
"currency": "USD",
"category_count": 1,
"product_count": 1,
"categories": [
{
"id": "1187",
"name": "Steak",
"is_main_category": true,
"items": [
{
"id": "50080",
"name": "Steak Philly",
"slug": "steak-philly",
"variants": [
{
"id": "50081",
"name": "Steak Philly Sandwich (1DM)",
"size": "Footlong",
"price": 13.99,
"available": true,
"nutrition": [
{
"name": "CALORIES",
"value": 1010
},
{
"name": "TOTAL FAT (g)",
"value": 50
}
],
"allergens": [
{
"name": "Milk/Lactose",
"contains": true,
"may_contain": false
}
],
"image_asset_urn": "urn:aaid:aem:steak-philly-footlong"
}
]
}
]
}
],
"source_url": "https://www.subway.com/api/store-menu/75376-0?locale=en-us",
"fetched_at": "2026-09-02T12:00:00Z"
}
}Request schema
No body schema
Response schema
#/definitions/subway.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 | subway.MenuResponse | No | ||||
| data.categories | array | No | ||||
| data.categories[].description | string | No | ||||
| data.categories[].id | string | No | ||||
| data.categories[].is_main_category | boolean | No | ||||
| data.categories[].items | array | No | ||||
| data.categories[].items[].id | string | No | ||||
| data.categories[].items[].name | string | No | ||||
| data.categories[].items[].slug | string | No | ||||
| data.categories[].items[].variants | array | No | ||||
| data.categories[].items[].variants[].allergens | array | No | ||||
| data.categories[].items[].variants[].allergens[].contains | boolean | No | ||||
| data.categories[].items[].variants[].allergens[].may_contain | boolean | No | ||||
| data.categories[].items[].variants[].allergens[].name | string | No | ||||
| data.categories[].items[].variants[].available | boolean | No | ||||
| data.categories[].items[].variants[].id | string | No | ||||
| data.categories[].items[].variants[].image_asset_urn | string | No | ImageAssetURN is Subway's own Adobe AEM asset identifier, not a directly fetchable URL -- confirmed live 2026-09-02 that the upstream's own imageUrl field is always empty; this is what is actually populated. Kept as-is rather than inventing an unverified delivery-URL scheme. | |||
| data.categories[].items[].variants[].name | string | No | Name is the upstream product name, which sometimes carries an internal build code in parentheses (e.g. "(1DM)") -- passed through verbatim rather than stripped, since the meaning of that code is not documented anywhere this family could confirm. | |||
| data.categories[].items[].variants[].nutrition | array | No | ||||
| data.categories[].items[].variants[].nutrition[].name | string | No | ||||
| data.categories[].items[].variants[].nutrition[].value | number | No | ||||
| data.categories[].items[].variants[].price | number | No | ||||
| data.categories[].items[].variants[].size | string | No | Size is the build label ("Footlong", "6''", "Kids") distinguishing this variant from siblings of the same MenuItem. | |||
| data.categories[].name | string | No | ||||
| data.categories[].slug | string | No | ||||
| data.category_count | integer | No | ||||
| data.currency | string | No | USD | |||
| data.fetched_at | string | No | ||||
| data.product_count | integer | No | ||||
| data.source_url | string | No | ||||
| data.store_id | string | No | ||||
| 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/subway/menu?store_id=75376-0" \
-H "x-api-key: $CRAWLORA_API_KEY"