---
title: "Poll a menu read"
method: GET
path: "/menus/{menuId}"
tags: ["Menus"]
---

# Poll a menu read

`GET /menus/{menuId}`

## Request

- Base URL: `https://api.layout.link/v1`
- URL: `https://api.layout.link/v1/menus/{menuId}`
- Auth: HTTP bearer

Come back for a read POST /menus started. Free: it never starts a read and never draws on an allowance.

## Path parameters

- `menuId` string, required

## Headers

- `Layout-Version` '2026-10-01'

## Response `200`

The read finished.

- union
  - object
    - `status` 'menu', required
    - `restaurant` MenuRestaurant, required
      - `name` string, required
      - `address` string, nullable, required
    - `assumedNearest` boolean, required: True when the name matched several branches and Layout read the nearest one. Tell the person which.
    - `items` MenuItem[], required
      - `name` string, required
      - `image` ItemImage
        - `url` string, required: A JPEG, up to 1000px on its long side, served from Layout's CDN. Show this URL; do not copy the file.
        - `webpUrl` string, required: The same photo as WebP, smaller.
        - `width` integer, nullable, required
        - `height` integer, nullable, required
        - `source` 'menu' | 'product_page', required: `menu`: from the restaurant's own menu. `product_page`: from its own page for the item.
        - `checkedAt` string, nullable, required: When Layout last checked the photo against the restaurant's site (ISO 8601).
      - `priceMinor` integer: Minor units. 429 is $4.29. Absent when the site did not give one.
      - `description` string
      - `category` string
      - `optionGroups` MenuOptionGroup[]: Absent: not read. Empty: read, and the item needs no choices.
        - `name` string, required
        - `required` boolean, required
        - `options` string[], required
        - `moreOptions` integer: Options beyond the ones listed.
    - `confidence` 'high' | 'partial', required: `partial`: this may not be the whole menu.
    - `pricesUnavailable` boolean, required: The site gave no prices when it was read. Never fill one in.
    - `scope` 'chain': `chain`: this location's own menu could not be read, so these are the items at least half of the restaurant's read locations list. Never priced (`pricesUnavailable` is true, since prices vary by location), and this location may not carry every item. Absent: this location's own menu.
    - `readAt` string, date-time: When Layout read this whole menu from the site, for a menu served from that read rather than read just now. Absent: read just now.
  - object
    - `status` 'categories', required
    - `restaurant` MenuRestaurant, required
      - `name` string, required
      - `address` string, nullable, required
    - `assumedNearest` boolean, required: True when the name matched several branches and Layout read the nearest one. Tell the person which.
    - `categories` string[], required: Read one by sending it back as `category`.
  - object
    - `status` 'reading', required
    - `menuId` string, required
    - `restaurant` MenuRestaurant, required
      - `name` string, required
      - `address` string, nullable, required
    - `assumedNearest` boolean, required: True when the name matched several branches and Layout read the nearest one. Tell the person which.
    - `retryAfterSec` integer, required: When to poll GET /menus/{menuId}.
  - object
    - `status` 'knowledge', required
    - `restaurant` MenuRestaurant
      - `name` string, required
      - `address` string, nullable, required
    - `knowledge` string, required: General knowledge, not the live menu. Prices are not current.
    - `live` false, required
  - object
    - `status` 'unreadable', required
    - `restaurant` MenuRestaurant
      - `name` string, required
      - `address` string, nullable, required
  - object
    - `status` 'not_found', required
  - object
    - `status` 'needs_location', required
    - `candidates` object[], required: Send one back as `placeId`. Empty: send `near` or coordinates.
      - `placeId` string, required
      - `name` string, required
      - `address` string, required
      - `distanceMi` number, nullable, required

## Other responses

- `202`: Still reading.
- `400`: `unsupported_version`: the Layout-Version header names no version this API answers.
- `401`: The token is missing, expired, revoked, issued for another audience, or the person disconnected. Every 401 reads the same.
- `403`: The credential is real and may not do this: an application or account that is suspended, a live person on an unapproved application, a scope the token was not granted, or a person whose Layout account cannot order yet.
- `404`: No such read for this application and person, or it is no longer held. Start a new one with POST /menus.
- `429`: Polling faster than every few seconds, or the per-credential brake.
- `500`: Layout failed to answer. Retry with backoff.
- `503`: The read could not be checked right now. It is not lost: poll again after Retry-After.

---

[API](https://skmtc.dev/layout/apis/layout-partner-api.md) · [All operations](https://skmtc.dev/layout/apis/layout-partner-api/llms.txt) · [OpenAPI document](https://skmtc.dev/layout/apis/layout-partner-api/revisions/7ff4ba01bf56?raw)
