MCP
https://mcp.tafaddal.ai/mcp
- Transport
- Streamable HTTP
- Auth
- OAuth sign-in, for consumer agents
{
"mcpServers": {
"tafaddal": {
"url": "https://mcp.tafaddal.ai/mcp"
}
}
}Private beta
Connect your agent over MCP or REST. Search live inventory, place a hold, collect payment and confirm, with idempotent calls and machine-readable policies. Tours and experiences in Doha first, then salons and spas.
Quickstart
https://mcp.tafaddal.ai/mcp
{
"mcpServers": {
"tafaddal": {
"url": "https://mcp.tafaddal.ai/mcp"
}
}
}https://api.tafaddal.ai/v1
curl https://api.tafaddal.ai/v1/holds \
-H "Authorization: Bearer $TAFADDAL_KEY" \
-H "Idempotency-Key: 6f1c2e" \
-d offer_id=off_dhow_sunset \
-d start=2026-11-12T18:00:00+03:00 \
-d guests=2 \
-d guest_name="Sara Ahmed" \
-d guest_email=sara@example.comResponse
{
"object": "hold",
"id": "hold_8Q2K",
"status": "held",
"start": "2026-11-12T18:00:00+03:00",
"party": 2,
"total": { "amount": 50000, "currency": "QAR" },
"due_now": { "amount": 50000, "currency": "QAR" },
"expires_at": "2026-11-11T18:10:00+03:00"
}Tools
Every MCP tool has a REST endpoint with the same inputs and outputs.
search_offersGET /v1/offersFind bookable experiences and services by place, date, category, party size and price
get_offerGET /v1/offers/{id}Details, media, location and policies for one offer
check_availabilityGET /v1/offers/{id}/availabilityLive slots with remaining capacity and price
hold_slotPOST /v1/holdsHold a slot for 10 minutes
create_checkoutPOST /v1/holds/{id}/checkoutPayment link the guest approves
confirm_bookingPOST /v1/holds/{id}/confirmConfirm when no upfront payment is required
get_bookingGET /v1/bookings/{id}Status and details
change_bookingPOST /v1/bookings/{id}/changeMove to another start time, within policy
cancel_bookingPOST /v1/bookings/{id}/cancelCancel, with the refund the policy allows
Booking lifecycle
heldexpiredreleasedconfirmedchangedcancelled · completed · no_showPrinciples
Send an Idempotency-Key header with every POST. A retry returns the original result, never a second hold or charge.
Amounts are integers in minor units with an ISO 4217 currency. QAR 500.00 is { "amount": 50000, "currency": "QAR" }.
ISO 8601 with an explicit offset. Doha is UTC+3 all year, so 6 pm is 2026-11-12T18:00:00+03:00.
Cancellation windows, deposits, and age or health requirements come back with every offer and hold, so agents can tell guests before they book.
Errors
Errors return a stable code, a human-readable message and the matching HTTP status.
| Code | Meaning |
|---|---|
slot_unavailableHTTP 409 | The slot filled or closed before your hold. Check availability again and pick another time. |
hold_expiredHTTP 410 | The hold passed its time limit and the slot was released. Place a new hold. |
policy_violationHTTP 422 | The request breaks the host’s rules, such as party size, cut-off time or an age requirement. |
payment_requiredHTTP 402 | This offer needs payment upfront. Create a checkout instead of confirming directly. |
idempotency_conflictHTTP 409 | The Idempotency-Key was already used for a different request. Use a new key for a new request. |
rate_limitedHTTP 429 | Too many requests. Wait for the Retry-After interval. |
not_foundHTTP 404 | No offer, hold or booking with that ID. |
Webhooks
booking.confirmedA hold became a booking.booking.changedMoved to another start time, within policy.booking.cancelledThe guest or host cancelled; includes any refund.booking.completedThe experience took place.hold.expiredA hold ran out of time and the slot was released.{
"id": "evt_5Jq1",
"type": "booking.confirmed",
"created_at": "2026-11-11T15:04:31Z",
"data": {
"booking_id": "bk_8Q2K",
"reference": "TF-8Q2K",
"status": "confirmed"
}
}The API is in private beta. Tell us what your agent books and we’ll set you up.
Get early API access