OpheliaDocs
Search docs⌘K
DashboardCreate an account
Verticals · Dining

OpenTable

Card unless the venue is known card-free · OTP required

curl
# Search (OpenTable). A dining search without "providers" searches
# OpenTable only; naming it keeps the request explicit.
curl -X POST https://api.opheliaos.com/v1/venues/search \
-H "Authorization: Bearer YOUR_LIVE_KEY" \
-H "Content-Type: application/json" \
-d '{
"vertical": "dining",
"providers": ["opentable"],
"term": "sushi",
"location": "New York, NY",
"datetime": "2026-11-15T00:15:00Z",
"party_size": 2
}'
# → venues[].image = "https://resizer.otstatic.com/v2/photos/wide/3/..."
When a card is needed

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" \
-H "Authorization: Bearer YOUR_LIVE_KEY" \
-H "Idempotency-Key: dining-001" \
-H "Content-Type: application/json" \
-d '{
"venue_id": "ven_12345678",
"datetime": "2026-11-15T00:15:00Z",
"party_size": 2,
"customer": {
"name": "Jane Smith",
"phone_number": "+15555555555",
"email": "jane.smith.diner@gmail.com"
},
"metadata": { "payment": { "card_number": "4111111111111111", "exp_month": "12", "exp_year": "2027", "cvv": "123", "name_on_card": "Jane Smith", "postal_code": "10014" } }
}'
# → "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." }
],
"read_for": { "date": "2026-11-14", "time": "19:00", "party_size": 1 }
}
},
{
"availability_id": "avail_73693a44433ad6d7",
"kind": "time",
"venue_id": "ven_755aa09d",
"datetime": "2026-11-14T19:15:00-08:00",
"datetime_utc": "2026-11-15T03:15:00Z",
"display_time": "7:15 PM",
"party_size": 1,
"status": "available",
"price_required": false,
"deposit_required": false
},
{
"availability_id": "avail_6193fc91d2b11c4f",
"kind": "time",
"venue_id": "ven_755aa09d",
"datetime": "2026-11-14T19:30:00-08:00",
"datetime_utc": "2026-11-15T03:30:00Z",
"display_time": "7:30 PM",
"party_size": 1,
"status": "available",
"price_required": false,
"deposit_required": false
}
],
"card_required": false
}

Modifying a Reservation

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" \
-H "Authorization: Bearer YOUR_LIVE_KEY"
# → "status": "cancelled"