API and webhooks

Connect Ijtimaa to your own systems: CRM, HR system or website.

Keys

A workspace admin makes keys in Admin → Developers. Each key is shown once. Read-only keys can list; write keys can also book and cancel. Send it with every request:

curl https://ijtimaa.chat/api/v1/meetings \
  -H "Authorization: Bearer mj_your_key"

Answers are JSON: { "data": … }, or { "error": "…" } with status 400, 401, 403, 404, 409 or 429. Each key may make 600 requests per hour.

Endpoints

MethodPathWhat it does
GET/api/v1Which workspace the key belongs to.
GET/api/v1/peopleEveryone in the workspace, with their booking page.
GET/api/v1/meeting-types?person=<slug>Active meeting types (lengths, seats, questions, location).
GET/api/v1/slots?type=<id>&from=YYYY-MM-DD&to=YYYY-MM-DD&duration=<min>Free start times (UTC), in the host’s dates.
GET/api/v1/meetings?from=<ISO>&to=<ISO>&status=confirmed|requested|cancelled&person=<slug>Bookings, oldest first (max 500).
GET/api/v1/meetings/<id>One booking.
POST/api/v1/bookingsBook a meeting type for someone. Body: typeId, start, name, email, timezone, duration, note, answers, guests.
POST/api/v1/meetings/<id>/cancelCancel as the host (or decline a request). Body: reason.
POST/api/v1/meetings/<id>/no-showMark that the guest didn’t come. Body: no_show (true/false).

Booking example

curl -X POST https://ijtimaa.chat/api/v1/bookings \
  -H "Authorization: Bearer mj_your_key" -H "Content-Type: application/json" \
  -d '{"typeId":"…","start":"2026-11-08T07:00:00Z","name":"Sara Ali","email":"sara@example.com","timezone":"Asia/Riyadh"}'

Webhooks

Add an https address in Admin → Developers and pick events. We POST JSON like { "event": "booking.created", "created_at": "…", "data": { …the booking… } }. Events:

Every request carries X-Ijtimaa-Signature: t=<unix seconds>,v1=<hex>, where v1 is the HMAC-SHA256 of"<t>.<raw body>" with your webhook secret. Check it, and reject old timestamps:

const [t, v1] = sig.split(',').map((p) => p.split('=')[1]);
const ok = crypto.timingSafeEqual(
  Buffer.from(v1, 'hex'),
  crypto.createHmac('sha256', SECRET).update(t + '.' + rawBody).digest());

Answer with any 2xx status within 10 seconds. Otherwise we try again after 1 minute, 5 minutes, 30 minutes, 2 hours and 6 hours. After 20 failures in a row the webhook is switched off; switch it back on in Admin.