OpenTable needs a card unless Ophelia knows the venue does not. To find out before booking, call POST /v1/availability/search (example below). The response carries card_required: false means you can book without metadata.payment; true means send it. If card_required is absent, the policy is unknown and a card is still required.
A booking with no card at a venue that needs one, or whose policy is unknown, fails with error_code: "missing_card". The card is only entered if the venue's form asks for it, and Ophelia never charges it.
To have the card authorized through AgentCard instead of sending card details, see AgentCard.
curl
# Book (use a ven_ id from the search response). Send metadata.payment unless
# availability answered card_required: false. It is only entered if the venue asks,
# never charged by us. customer.name needs a first and last name.
curl -X POST "https://api.opheliaos.com/v1/bookings" \
# → "status": "requires_action", next_action.type "otp" (the diner gets an SMS code)
curl
# Submit the OTP the diner received — returns "status": "confirmed"
curl -X POST "https://api.opheliaos.com/v1/bookings/bkg_12345678/continue" \
-H "Authorization: Bearer YOUR_LIVE_KEY" \
-H "Content-Type: application/json" \
-d '{ "otp_code": "123456" }'
Remember when testing
If you're testing against a real OpenTable account, the customer fields you submit (email, phone number) must match the info tied to that account, or the booking will fail.
First and last name
OpenTable's form requires a last name. A one-word customer.name is refused up front with 400 and error_code: "missing_last_name", before any code is texted to the diner.
Availability
Each slot has kind: "time". datetime_utc is the slot in UTC, the universal standard across APIs, databases, and programming. Ophelia converts UTC to the venue's local time automatically. The datetime field in each slot carries the local offset, and display_time gives the human-readable local time ready to render in your UI.
OpenTable returns the slots it offers around the requested datetime. window_minutes is accepted but has no effect for OpenTable today.
Restaurant terms
Every slot carries terms, read from OpenTable on each request without holding a table: whether a card is held or charged, the late-cancellation fee and deadline, the restaurant's own policies, and the terms of any set menu or private room the slot books. card_required comes from the same read, so check_card_required is only a fallback: when OpenTable's card policy cannot be read directly, it lets Ophelia click a slot to learn it, which briefly holds a table.
A confirmed booking's confirmation.terms adds the restaurant's terms and conditions, which OpenTable shows only on its booking page. See Restaurant terms.
Request
json
{
"venue_id":"ven_755aa09d",
"party_size": 1,
"datetime":"2026-11-15T03:30:00Z"
}
Response
json
{
"venue_id":"ven_755aa09d",
"slots":[
{
"availability_id":"avail_8d6a0b078c6aefe7",
"kind":"time",
"venue_id":"ven_755aa09d",
"datetime":"2026-11-14T19:00:00-08:00",
"datetime_utc":"2026-11-15T03:00:00Z",
"display_time":"7:00 PM",
"party_size": 1,
"status":"available",
"price_required": false,
"deposit_required": false,
"terms":{
"source":"opentable_restref",
"card_required": false,
"card_policy":"none",
"policies":[
{"kind":"booking_policy","text":"We have a 15 minute grace period. Please call us if you are running later than 15 minutes after your reservation time."}
Only a confirmed booking can be modified, and OpenTable is the only provider that supports it. The booking stays confirmed at the original time until OpenTable accepts the change. If the new time needs a card, send it as payment in the modify body, the same shape as metadata.payment on a booking.
Change the date/time only:
curl
# Change date/time only — fields are independent, send only what you're changing
curl -X POST "https://api.opheliaos.com/v1/bookings/bkg_12345678/modify" \
-H "Authorization: Bearer YOUR_LIVE_KEY" \
-H "Content-Type: application/json" \
-d '{ "datetime": "2026-12-01T19:15:00" }'
Change the party size only:
curl
# Change party size only
curl -X POST "https://api.opheliaos.com/v1/bookings/bkg_12345678/modify" \
-H "Authorization: Bearer YOUR_LIVE_KEY" \
-H "Content-Type: application/json" \
-d '{ "party_size": 4 }'
Change date/time, party size, and seating preference together:
curl
# Change datetime, party_size, and seating_preference together
curl -X POST "https://api.opheliaos.com/v1/bookings/bkg_12345678/modify" \
-H "Authorization: Bearer YOUR_LIVE_KEY" \
-H "Content-Type: application/json" \
-d '{
"datetime":"2026-12-01T19:45:00",
"party_size": 4,
"seating_preference":"bar"
}'
OTP after a modify
OpenTable may require re-verification after certain modifications, the same OTP-by-SMS flow used on initial booking. There is no separate endpoint for this — reuse /continue to submit the code.
Confirm an OTP if OpenTable requires re-verification after a modify:
curl
# Confirm an OTP if OpenTable requires re-verification after a modify
curl -X POST "https://api.opheliaos.com/v1/bookings/bkg_12345678/continue" \
-H "Authorization: Bearer YOUR_LIVE_KEY" \
-H "Content-Type: application/json" \
-d '{ "otp_code": "123456" }'
Cancelling a Reservation
OpenTable bookings can be cancelled through Ophelia, including confirmed ones. The call takes no body. If OpenTable cannot cancel it, the booking stays confirmed and carries an error_code saying why.
curl
# Cancel a reservation
curl -X POST "https://api.opheliaos.com/v1/bookings/bkg_12345678/cancel" \