Skip to content
tafaddal

Private beta

One API to book the real world.

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

Two ways in, one booking flow.

MCP

https://mcp.tafaddal.ai/mcp

Transport
Streamable HTTP
Auth
OAuth sign-in, for consumer agents
MCP client config
{
  "mcpServers": {
    "tafaddal": {
      "url": "https://mcp.tafaddal.ai/mcp"
    }
  }
}

REST

https://api.tafaddal.ai/v1

Format
Form-encoded requests, JSON responses
Auth
API keys, for platforms
Place a hold
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.com

Response

{
  "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

Nine tools, mirrored in REST.

Every MCP tool has a REST endpoint with the same inputs and outputs.

Booking lifecycle

From hold to booking.

held
A hold reserves the slot for 10 minutes while the guest decides and pays.
expired
The time limit passed. The slot goes back on sale.
released
The agent let the hold go early. The slot goes back on sale.
confirmed
The guest paid through checkout, or the booking was confirmed directly because no upfront payment was required.
changed
Moved to another start time within policy. The booking stays confirmed.
cancelled · completed · no_show
How a confirmed booking ends. Refunds and no-show charges follow the host’s policy.
Hold and booking lifecycleA hold starts as held. It becomes expired when its time limit passes, released if the agent lets it go, or confirmed after payment or a direct confirm. A confirmed booking can be changed and stays confirmed, or it ends as cancelled, completed or no_show.paymentor direct confirmtime limit passedagent let it gochangedheldexpiredreleasedconfirmedcancelledcompletedno_show

Principles

Predictable by design.

Errors

Errors you can act on.

Errors return a stable code, a human-readable message and the matching HTTP status.

Error codes
CodeMeaning
slot_unavailableHTTP 409The slot filled or closed before your hold. Check availability again and pick another time.
hold_expiredHTTP 410The hold passed its time limit and the slot was released. Place a new hold.
policy_violationHTTP 422The request breaks the host’s rules, such as party size, cut-off time or an age requirement.
payment_requiredHTTP 402This offer needs payment upfront. Create a checkout instead of confirming directly.
idempotency_conflictHTTP 409The Idempotency-Key was already used for a different request. Use a new key for a new request.
rate_limitedHTTP 429Too many requests. Wait for the Retry-After interval.
not_foundHTTP 404No offer, hold or booking with that ID.

Webhooks

Every change, pushed to you.

  • 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.
booking.confirmed
{
  "id": "evt_5Jq1",
  "type": "booking.confirmed",
  "created_at": "2026-11-11T15:04:31Z",
  "data": {
    "booking_id": "bk_8Q2K",
    "reference": "TF-8Q2K",
    "status": "confirmed"
  }
}
تفضّل

Build with us.

The API is in private beta. Tell us what your agent books and we’ll set you up.

Get early API access