Restaurant booking

Book restaurant reservations via browser automation.

How to use it

  1. Hit Copy the whole skill.
  2. Claude: ⋯ → Download .md, then Customize → Skills → Add → Upload skill.
    ChatGPT: make a Project and paste it into Instructions.
    Neither? Paste it at the top of a new chat — it works for that chat.
  3. Describe your job in plain words. The AI follows the skill from there.
Claude Code — installs the whole folder, not just SKILL.md
npx degit gooseworks-ai/goose-skills/skills/research-tools/capabilities/restaurant-booking#main ~/.claude/skills/restaurant-booking

For one project only, change the path to .claude/skills/restaurant-booking.

Not working?
  • Check which app you pasted it into — the steps above name the right one.
  • Some skills need the paid tier of Claude or ChatGPT.
Step-by-step guide with screenshots · Ask in the forum

Paste into Claude, ChatGPT or Cursor.

Show the full text221 lines
restaurant-booking/SKILL.md221 lines6.7 KBpushed 96d agoRawView on GitHub

Restaurant Booking

Setup

Read your credentials from ~/.gooseworks/credentials.json:

export GOOSEWORKS_API_KEY=$(python3 -c "import json;print(json.load(open('$HOME/.gooseworks/credentials.json'))['api_key'])")
export GOOSEWORKS_API_BASE=$(python3 -c "import json;print(json.load(open('$HOME/.gooseworks/credentials.json')).get('api_base','https://api.gooseworks.ai'))")

If ~/.gooseworks/credentials.json does not exist, tell the user to run: npx gooseworks login

All endpoints use Bearer auth: -H "Authorization: Bearer $GOOSEWORKS_API_KEY"

Book reservations using Notte browser automation via Orthogonal.

Requirements

  • Orthogonal CLI (npm install -g @orth/cli) or API key
  • Guest info: name, email, phone

Quick Flow

  1. Start Notte session
  2. Navigate to booking site (OpenTable preferred)
  3. Select date/time/party size
  4. Fill contact form
  5. Submit and confirm

CLI Method (Recommended)

1. Start a Notte Session

curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
  -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"api":"notte","path":"/sessions/start"}'
  --body '{"browser_type":"chromium","headless":true,"solve_captchas":true,"idle_timeout_minutes":10}'

Save the session_id from the response.

2. Navigate to OpenTable

curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
  -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}'
  --body '{"type":"goto","url":"https://www.opentable.com/r/{restaurant}?datetime=2026-02-17T19:00&covers=2"}'

3. Click Time Slot

curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
  -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}'
  --body '{"type":"click","selector":"button:has-text(\"7:00 PM\")"}'

4. Select Seating (if prompted)

curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
  -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}'
  --body '{"type":"click","selector":"button:has-text(\"Select\")"}'

5. Fill the Form

# First name
curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
  -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}'
  --body '{"type":"fill","selector":"input#firstName","value":"John"}'

# Last name
curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
  -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}'
  --body '{"type":"fill","selector":"input#lastName","value":"Doe"}'

# Email
curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
  -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}'
  --body '{"type":"fill","selector":"input#email","value":"[email protected]"}'

# Phone
curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
  -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}'
  --body '{"type":"fill","selector":"input#phoneNumber","value":"4155551234"}'

6. Accept Terms

curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
  -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}'
  --body '{"type":"click","selector":"text=I agree to the restaurant"}'

7. Submit Reservation

curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
  -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}'
  --body '{"type":"click","selector":"button:has-text(\"Complete reservation\")"}'

8. Verify Confirmation

curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
  -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"api":"notte","path":"/sessions/{session_id}/page/scrape"}'
  --body '{"only_main_content":true}'

Look for "confirmed" in the response.

API Method (curl)

# Start session
curl -X POST "https://api.orth.sh/v1/run" \

  -H "Content-Type: application/json" \
  -d '{
    "api": "notte",
    "path": "/sessions/start",
    "body": {
      "browser_type": "chromium",
      "headless": true,
      "solve_captchas": true,
      "idle_timeout_minutes": 10
    }
  }'

# Execute actions (same pattern)
curl -X POST "https://api.orth.sh/v1/run" \

  -H "Content-Type: application/json" \
  -d '{
    "api": "notte",
    "path": "/sessions/{session_id}/page/execute",
    "body": {"type":"goto","url":"https://www.opentable.com/..."}
  }'

Key Selectors (OpenTable)

Field Selector
First name input#firstName
Last name input#lastName
Email input#email
Phone input#phoneNumber
Terms checkbox text=I agree to the restaurant
Submit button:has-text('Complete reservation')
Time slots button:has-text('7:00 PM')
Seating select button:has-text('Select')

Finding Restaurant IDs

Search OpenTable and extract from URL:

  • restref=1906 → Foreign Cinema
  • Restaurant slug in URL path

Example URL format:

https://www.opentable.com/r/{restaurant-slug}?restref={id}&datetime={YYYY-MM-DDTHH:MM}&covers={n}

Tips

  • OpenTable holds table for 5 minutes - move fast
  • Use fill action with value param (not type with text)
  • Click terms via label text, not checkbox directly
  • No credit card needed - reservations are free
  • Confirmation email sent automatically

Resy Alternative

If restaurant uses Resy:

https://resy.com/cities/{city}/venues/{restaurant}?date={YYYY-MM-DD}&seats={n}

Similar flow but different selectors. Scrape page first to identify form fields.

After Booking

  1. Create calendar event with gog calendar create
  2. Add attendees and location
  3. Include confirmation number in description
1---
2name: restaurant-booking
3description: Book restaurant reservations via browser automation. Use when asked to make dinner reservations, book a table, or find availability at restaurants. Supports OpenTable, Resy, and direct restaurant booking sites.
4source: orthogonal
5---
6 
7 
8# Restaurant Booking
9 
10## Setup
11 
12Read your credentials from ~/.gooseworks/credentials.json:
13```bash
14export GOOSEWORKS_API_KEY=$(python3 -c "import json;print(json.load(open('$HOME/.gooseworks/credentials.json'))['api_key'])")
15export GOOSEWORKS_API_BASE=$(python3 -c "import json;print(json.load(open('$HOME/.gooseworks/credentials.json')).get('api_base','https://api.gooseworks.ai'))")
16```
17 
18If ~/.gooseworks/credentials.json does not exist, tell the user to run: `npx gooseworks login`
19 
20All endpoints use Bearer auth: `-H "Authorization: Bearer $GOOSEWORKS_API_KEY"`
21 
22 
23Book reservations using Notte browser automation via Orthogonal.
24 
25## Requirements
26 
27- Orthogonal CLI (`npm install -g @orth/cli`) or API key
28- Guest info: name, email, phone
29 
30## Quick Flow
31 
321. Start Notte session
332. Navigate to booking site (OpenTable preferred)
343. Select date/time/party size
354. Fill contact form
365. Submit and confirm
37 
38## CLI Method (Recommended)
39 
40### 1. Start a Notte Session
41 
42```bash
43curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
44 -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
45 -H "Content-Type: application/json" \
46 -d '{"api":"notte","path":"/sessions/start"}'
47 --body '{"browser_type":"chromium","headless":true,"solve_captchas":true,"idle_timeout_minutes":10}'
48```
49 
50Save the `session_id` from the response.
51 
52### 2. Navigate to OpenTable
53 
54```bash
55curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
56 -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
57 -H "Content-Type: application/json" \
58 -d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}'
59 --body '{"type":"goto","url":"https://www.opentable.com/r/{restaurant}?datetime=2026-02-17T19:00&covers=2"}'
60```
61 
62### 3. Click Time Slot
63 
64```bash
65curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
66 -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
67 -H "Content-Type: application/json" \
68 -d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}'
69 --body '{"type":"click","selector":"button:has-text(\"7:00 PM\")"}'
70```
71 
72### 4. Select Seating (if prompted)
73 
74```bash
75curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
76 -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
77 -H "Content-Type: application/json" \
78 -d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}'
79 --body '{"type":"click","selector":"button:has-text(\"Select\")"}'
80```
81 
82### 5. Fill the Form
83 
84```bash
85# First name
86curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
87 -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
88 -H "Content-Type: application/json" \
89 -d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}'
90 --body '{"type":"fill","selector":"input#firstName","value":"John"}'
91 
92# Last name
93curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
94 -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
95 -H "Content-Type: application/json" \
96 -d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}'
97 --body '{"type":"fill","selector":"input#lastName","value":"Doe"}'
98 
99# Email
100curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
101 -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
102 -H "Content-Type: application/json" \
103 -d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}'
104 --body '{"type":"fill","selector":"input#email","value":"[email protected]"}'
105 
106# Phone
107curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
108 -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
109 -H "Content-Type: application/json" \
110 -d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}'
111 --body '{"type":"fill","selector":"input#phoneNumber","value":"4155551234"}'
112```
113 
114### 6. Accept Terms
115 
116```bash
117curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
118 -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
119 -H "Content-Type: application/json" \
120 -d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}'
121 --body '{"type":"click","selector":"text=I agree to the restaurant"}'
122```
123 
124### 7. Submit Reservation
125 
126```bash
127curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
128 -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
129 -H "Content-Type: application/json" \
130 -d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}'
131 --body '{"type":"click","selector":"button:has-text(\"Complete reservation\")"}'
132```
133 
134### 8. Verify Confirmation
135 
136```bash
137curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
138 -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
139 -H "Content-Type: application/json" \
140 -d '{"api":"notte","path":"/sessions/{session_id}/page/scrape"}'
141 --body '{"only_main_content":true}'
142```
143 
144Look for "confirmed" in the response.
145 
146## API Method (curl)
147 
148```bash
149# Start session
150curl -X POST "https://api.orth.sh/v1/run" \
151 
152 -H "Content-Type: application/json" \
153 -d '{
154 "api": "notte",
155 "path": "/sessions/start",
156 "body": {
157 "browser_type": "chromium",
158 "headless": true,
159 "solve_captchas": true,
160 "idle_timeout_minutes": 10
161 }
162 }'
163 
164# Execute actions (same pattern)
165curl -X POST "https://api.orth.sh/v1/run" \
166 
167 -H "Content-Type: application/json" \
168 -d '{
169 "api": "notte",
170 "path": "/sessions/{session_id}/page/execute",
171 "body": {"type":"goto","url":"https://www.opentable.com/..."}
172 }'
173```
174 
175## Key Selectors (OpenTable)
176 
177| Field | Selector |
178|-------|----------|
179| First name | `input#firstName` |
180| Last name | `input#lastName` |
181| Email | `input#email` |
182| Phone | `input#phoneNumber` |
183| Terms checkbox | `text=I agree to the restaurant` |
184| Submit | `button:has-text('Complete reservation')` |
185| Time slots | `button:has-text('7:00 PM')` |
186| Seating select | `button:has-text('Select')` |
187 
188## Finding Restaurant IDs
189 
190Search OpenTable and extract from URL:
191- `restref=1906` → Foreign Cinema
192- Restaurant slug in URL path
193 
194Example URL format:
195```
196https://www.opentable.com/r/{restaurant-slug}?restref={id}&datetime={YYYY-MM-DDTHH:MM}&covers={n}
197```
198 
199## Tips
200 
201- OpenTable holds table for 5 minutes - move fast
202- Use `fill` action with `value` param (not `type` with `text`)
203- Click terms via label text, not checkbox directly
204- No credit card needed - reservations are free
205- Confirmation email sent automatically
206 
207## Resy Alternative
208 
209If restaurant uses Resy:
210```
211https://resy.com/cities/{city}/venues/{restaurant}?date={YYYY-MM-DD}&seats={n}
212```
213 
214Similar flow but different selectors. Scrape page first to identify form fields.
215 
216## After Booking
217 
2181. Create calendar event with `gog calendar create`
2192. Add attendees and location
2203. Include confirmation number in description
221 

Discussion

Alternatives

Also in Workflow automation