Skip to main content
The restaurant you want is booked solid, and the tables that come back from cancellations go within minutes to whoever happens to be refreshing. This program watches the Resy page every minute. When it changes, your server sends an agent, signed in as you, to book the earliest time in your window for your party, with your card for the hold if Resy asks for one. You get a Slack message with the confirmation, and the watching stops. Book tables you will sit at. The program books one table and deletes its monitor; it is not a way to hold tables for resale.

What you need

  • An Outcrawl API key in OUTCRAWL_API_KEY.
  • A profile signed in to your Resy account, labelled resy-personal.
  • Your card stored as a secret named card_dining with kind: 'card'. The agent types it by name when Resy asks for a card; the model never sees the number.
  • A server reachable from the internet, with a long random string in HOOK_TOKEN. The monitor and the run both post to it.
  • Optional: a Slack incoming webhook URL in SLACK_WEBHOOK_URL. Python also needs fastapi and uvicorn.

How it works

1

A monitor watches the page

monitors.create checks the Resy page for your date and party size every minute. Each check is 1 credit, whether or not the page changed; a real change posts to your endpoint. A monitor cannot start an agent itself, so your endpoint does.
2

Your endpoint sends an agent to book

It submits one agent run on your profile, with your card secret, your window and party size in the task, and a schema for the booking. The rule Only use resy.com. is enforced. One run at a time: a change that arrives while a run is booking is ignored.
3

The run reports back

The run’s webhook posts to your second endpoint when it ends, and retries if your server is down. The endpoint reads the run by id rather than trusting the body, and checks the booked time against your window.
4

You get the message, and the watching stops

A booking goes to Slack and monitors.delete removes the monitor. A change with nothing that fits is logged, and the monitor keeps watching.
Your window, party size and deposit ceiling are instructions in the task. What is enforced is the site (Only use resy.com.), the card (the run can type only the one secret it is given), and your code’s check of the booked time. A spend-limit rule is left out on purpose: it has to read a total on the page before a booking button and blocks the booking when it cannot, and most reservations that need no deposit show no total.

The program

Run it as a server. It creates the monitor when it starts.

What you get back

In Slack:
The run’s answer, as your endpoint reads it with oc.agent.get:
When the page changed but nothing fit, the answer is { "booked": false, "reason": "The only new time is 22:15, outside 19:00 to 21:00." } and the monitor keeps going.

What it costs

  • Watching is 1 credit per check, whether or not the page changed, plus the model’s usage when a changed page is judged (judge: true), per pricing. A check every minute is 1,440 checks a day, so 1,440 credits a day.
  • A change with nothing that fits starts a short run. An agent run is billed for the model’s usage, browser time and proxy usage, and a typical run costs about 15 credits a minute all in; the real figure depends on the task and how heavy the pages are. About 30 s is about 8 credits.
  • The booking is about 2 minutes: about 30 credits, once.
A popular page also changes when other people take times. A week of watching with 30 changes before a table fits is 10,080 × 1 + 29 × 8 + 30 = about 10,340 credits, plus model usage for the 30 judged changes. Each run’s caps.budget is 75. Checking every 5 minutes instead cuts the watching to 2,016 credits a week.

Make it yours

  • Check the deposit in code before anything is booked: split the run into one that lists open times with their deposits and one that books the time your code picks, as Book the first appointment slot that fits your week does. It costs about a minute more, and tables go fast.
  • Skip changes that only remove times: judge: true puts a model’s summary of the change in the monitor’s post, and your endpoint can start a run only when it mentions a new time.
  • Watch several dates: one monitor per date’s page, all posting to the same endpoint, and delete them all once one books.
  • Text yourself instead of Slack: tell is one HTTP call.

Monitors

Schedules and notify targets.

Monitoring a run

Run webhooks and their retries.

Secrets

A card the agent types but never reads.

Profiles

Stay signed in to Resy.