---
name: scout-reservations
description: Find Resy restaurants and request reservations through Scout on behalf of a signed-in user, with the user approving any automatic booking.
homepage: https://dinewithscout.com/developers
version: 1.0.0
---

# Scout reservations

Scout watches Resy for a table that matches a user's request and either alerts them or, with their explicit approval, books it. This file tells an AI agent how to use Scout correctly. Read the whole file before making a request.

Origin: `https://dinewithscout.com`
REST base: `https://dinewithscout.com/api/v1`
OpenAPI: `https://dinewithscout.com/api/v1/openapi.json`
MCP endpoint (Streamable HTTP): `https://dinewithscout.com/mcp`

## Three ways to connect, easiest first

1. REST with a personal access token. Works from any HTTP client. No OAuth dance. Start here.
2. MCP over Streamable HTTP with OAuth 2.1. For MCP hosts with native OAuth support (Claude, ChatGPT connectors, Cursor, and similar).
3. This skill file, served at `https://dinewithscout.com/developers/skill.md`, for agents that read instructions and call REST themselves.

## What to ask your user to do first

You cannot create a Scout account or a token for the user. Ask them to:

1. Sign in at `https://dinewithscout.com`.
2. Connect their Resy account under Settings. Without it, Scout cannot check availability or book.
3. Open `https://dinewithscout.com/assistants` and create a personal access token under "Personal access tokens", choosing the scopes you need (see Scopes below). The token starts with `spt_`, is shown once, lasts 90 days, and can be revoked on the same page.
4. Store the token in your secure vault or environment. Ask the user not to paste it into the chat transcript. If they already did, ask them to revoke it and create a new one.

If your host supports MCP with OAuth, skip step 3 and 4 and add `https://dinewithscout.com/mcp` as a remote MCP server instead. The host discovers Scout's OAuth server, registers itself, and opens Scout sign-in and consent in the user's browser.

## Authentication

Send the token as a bearer token on every call:

```
Authorization: Bearer spt_...
```

Personal access tokens work on every `/api/v1/*` route and on `/mcp`.

OAuth details for MCP hosts: authorization code with PKCE (S256), dynamic client registration at `POST https://dinewithscout.com/oauth/register`, token endpoint `POST https://dinewithscout.com/oauth/token`, resource `https://dinewithscout.com/mcp`. Discovery at `https://dinewithscout.com/.well-known/oauth-authorization-server` and `https://dinewithscout.com/.well-known/oauth-protected-resource/mcp`. Grants last 30 days. Access tokens last 15 minutes and come with refresh tokens.

## Scopes

| Scope | Allows |
| --- | --- |
| `restaurants:read` | Search the restaurant catalog for venue IDs |
| `requests:read` | Capabilities, preview, list and read requests. Required for any MCP connection |
| `requests:write` | Create, update and stop requests |
| `reservations:read` | See reservation details on requests and `GET /reservations/{id}` |

A token only sees the requests and reservations created through that token or connection.

## Step by step

All examples use `$SCOUT_TOKEN` for the token and `https://dinewithscout.com` for the origin.

### 1. Confirm access and readiness

```
curl -H "Authorization: Bearer $SCOUT_TOKEN" https://dinewithscout.com/api/v1/capabilities
```

A 200 confirms the token works. Read `executor.ready`. If it is false, `executor.reason` says why (usually `resy_not_connected`). Tell the user to fix that in Scout before you create an auto_book request. `executor.execution` says where Scout would book: `cloud` is the default once Resy is connected, and `user_device` appears only if the user chose to book from their own paired device in Settings. Do not tell the user a device is involved unless it says `user_device`. A 401 means the token is missing, expired or revoked.

### 2. Find venue IDs

```
curl -H "Authorization: Bearer $SCOUT_TOKEN" "https://dinewithscout.com/api/v1/restaurants?q=carbone"
```

Returns up to 8 matches with `venue_id`, `name`, `city`, `neighborhood`, `time_zone` and any known reservation release rule. Scout searches its own catalog and, for a restaurant it has not stored yet, Resy; a restaurant found on Resy is added and can be watched. It does not check live availability. If nothing matches, the restaurant is most likely not on Resy (Scout supports Resy only); tell the user that rather than guessing an ID. `time_zone` is an IANA name such as `America/New_York`; send it as the request's `timezone`.

### 3. Build the request spec

```json
{
  "title": "Anniversary dinner",
  "venue_ids": [4123],
  "dates": ["2026-10-02", "2026-10-03"],
  "party_size": 2,
  "earliest_time": "19:00",
  "latest_time": "21:00",
  "timezone": "America/New_York",
  "seating": "any",
  "mode": "alert_only",
  "max_cancellation_fee_per_person": 0,
  "fee_review_hours": 3,
  "expires_at": "2026-10-03T23:59:00-04:00",
  "max_bookings": 1
}
```

Field rules. Unknown fields are rejected.

| Field | Rule |
| --- | --- |
| `title` | Optional, up to 120 characters |
| `venue_ids` | 1 to 8 positive integers from step 2 |
| `dates` | 1 to 42 explicit ISO dates (`YYYY-MM-DD`) from today through the next 90 days. No ranges, no weekday rules |
| `party_size` | Integer 1 to 20. Default 2 |
| `earliest_time`, `latest_time` | `HH:MM`, 24 hour. `latest_time` must not be before `earliest_time`; split overnight windows into two requests |
| `timezone` | IANA name, normally the venue's `time_zone`. Default `America/New_York` |
| `seating` | `any`, `indoor` or `outdoor` |
| `mode` | `alert_only` (notify the user) or `auto_book` (book after the user approves) |
| `max_cancellation_fee_per_person` | 0 to 1000 USD. Scout will not auto-book a table whose cancellation or no-show fee exceeds this |
| `fee_review_hours` | 0 to 168. Scout only auto-books when the free cancellation deadline is at least this many hours away, so the user can review and cancel without a fee. Default 3 |
| `expires_at` | ISO datetime with a UTC offset. Monitoring stops here. Must be in the future, no later than the last requested service time, and before the token or grant expires |
| `max_bookings` | Must be the integer 1 |

### 4. Preview before creating

```
curl -X POST -H "Authorization: Bearer $SCOUT_TOKEN" -H "Content-Type: application/json" \
  -d @spec.json https://dinewithscout.com/api/v1/requests/preview
```

Preview validates the spec, resolves restaurant names and timezones, and reports `executor` readiness. It creates nothing. Show the user the resolved restaurants, dates, time window and party size and confirm before continuing. Preview returns 422 for invalid specs and 409 if an active automatic request or existing reservation already overlaps this dinner.

### 5. Create the request

```
curl -X POST -H "Authorization: Bearer $SCOUT_TOKEN" -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" -d @spec.json https://dinewithscout.com/api/v1/requests
```

`Idempotency-Key` is required: 8 to 128 characters of letters, digits, `.`, `:`, `_` or `-`. Reuse the same key when retrying the same spec. Reusing a key with a different spec returns 409.

The response is the full request view. Two cases:

- `mode: alert_only`. `status` is `active`. Scout is monitoring. Nothing else is needed.
- `mode: auto_book`. `status` is `needs_approval`. Nothing is being watched or booked yet. The response's `action_url` is the approval link. Give it to the user and ask them to open it in Scout, where they review the exact dates, times, party and fee limits and approve. You cannot approve on their behalf. Do not say anything is booked or being watched until `status` becomes `active`.

### 6. Poll for status

```
curl -H "Authorization: Bearer $SCOUT_TOKEN" https://dinewithscout.com/api/v1/requests/sr_...
```

There are no webhooks. Poll when the user asks, or on a slow schedule (every few minutes at most). `GET /api/v1/requests` lists this token's recent requests, including ones from earlier conversations.

| `status` | Meaning | What to tell the user |
| --- | --- | --- |
| `needs_approval` | Auto-book request waiting for the user | Open `action_url` in Scout to approve |
| `active` | Scout is monitoring | Watching. No table yet |
| `awaiting_verification` | A booking may have been submitted; Scout is confirming with Resy | Do not claim success or failure yet. Check again shortly |
| `confirmed` | A reservation exists and Resy's account confirmed it | Report the reservation from `reservations[]` |
| `expired` | `expires_at` passed without a booking | Nothing was booked. Offer a new request |
| `stopped` | Stopped by the user or an agent | Monitoring ended. Any existing reservation still stands |
| `revoked` | The token or connection was revoked | Ask the user to reconnect and create a new request |

A reservation is real only when an entry in `reservations[]` has `verified: true`. Until then, say "Scout is watching" or "a booking is being verified", never "booked". `reservations[]` is empty unless the token has `reservations:read`.

### 7. Update or stop

Update replaces the spec with optimistic locking. Send the current `revision` from the latest view. Changing an auto_book request puts it back into `needs_approval` with a new `action_url`.

```
curl -X PUT -H "Authorization: Bearer $SCOUT_TOKEN" -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"revision": 1, "spec": { ...full spec... }}' https://dinewithscout.com/api/v1/requests/sr_...
```

Stop ends monitoring. It never cancels a reservation that already exists, and it cannot undo a submission already in flight.

```
curl -X POST -H "Authorization: Bearer $SCOUT_TOKEN" https://dinewithscout.com/api/v1/requests/sr_.../stop
```

To cancel or change an actual reservation, send the user to resy.com/account/reservations. Scout has no cancellation tool.

## Rules that protect the user

- Never claim a table is booked until `reservations[].verified` is `true`.
- Always hand the user the `action_url` for an auto_book request. Never imply approval happened.
- Never ask the user to paste their `spt_` token into chat. Never echo it back.
- Confirm the spec with the user after preview and before create. Booking mistakes cost fees.
- Do not create a second request for the same dinner while one is open. Update or stop the first.
- Report Scout's limits honestly when the user asks for something outside them.

## Limits

- Resy only. No other reservation platforms.
- 20 open requests per user. 8 restaurants and 42 dates per request. One booking per request.
- Scout's service charge is $0. Restaurant cancellation or no-show fees are separate and capped by the approved `max_cancellation_fee_per_person`. Scout never authorizes deposits or prepaid meals.
- No cancellation tool. No webhooks. Poll for status.
- Resy's terms prohibit automated access and Resy may deactivate accounts that use tools like Scout. The user accepts that risk when they connect Resy; make sure they know it.

## MCP tools

When connected over MCP, the same operations appear as tools: `scout_find_restaurants`, `scout_preview_request`, `scout_create_request`, `scout_update_request`, `scout_get_request`, `scout_list_requests`, `scout_stop_request` and `scout_get_reservation`. `scout_create_request` and `scout_update_request` take `spec` plus an `idempotency_key` argument. Everything above about approval, statuses and verification applies to the tools too.

## Errors

Errors return JSON with `code` and `message`. Common codes: `idempotency_key_required`, `venue_not_found`, `venue_timezone_mismatch` (all venues in one request must share the timezone you send), `dates_out_of_range`, `invalid_expiry` and other validation errors (422), `revision_conflict`, `idempotency_conflict`, `overlapping_booking_request`, `existing_reservation` and `outcome_unknown` (409), `request_limit` (429), `authorization_revoked` (401), `request_not_found` and `reservation_not_found` (404), `grant_expires_first` when `expires_at` is later than the token or grant expiry (422). Read the message; it is written to be shown to the user.
