CtrlK
BlogDocsLog inGet started
Tessl Logo

restaurant-booking

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.

63

Quality

75%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Low

Low-risk findings worth noting

Fix and improve this skill with Tessl

tessl review fix ./skills/research-tools/capabilities/restaurant-booking/SKILL.md
SKILL.md
Quality
Evals
Security

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":"john@example.com"}'

# 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)

FieldSelector
First nameinput#firstName
Last nameinput#lastName
Emailinput#email
Phoneinput#phoneNumber
Terms checkboxtext=I agree to the restaurant
Submitbutton:has-text('Complete reservation')
Time slotsbutton:has-text('7:00 PM')
Seating selectbutton: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
Repository
gooseworks-ai/goose-skills
Last updated
First committed

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.