iQuanta · Integration Guide

Manual Booking API

Create a booking with no real Razorpay payment behind it — a free trial, a WBL/scholarship seat, anything booked outside the normal checkout flow. It's treated exactly like a real booking everywhere else: it shows up in Booking Management and the calendar, gets a lead record, and a Google Meet link is generated automatically.

Method & URL
POSThttps://razorpay-dashboard-4cba2.web.app/api/public/bookings
Auth header
X-API-Key: <your key>
Content type
application/json

Authentication

One shared key, sent as a header

Every request needs an X-API-Key header set to the key we'll send you separately (never in this document, and never in chat/email in plaintext if you can help it — use a secrets manager or a one-time share link). It's the same platform-wide key used by the Lead Capture API — one key, valid for every external-facing endpoint.

Call this from your server, not the browser. Anything sent to the page's own JavaScript can be read by anyone who opens dev tools. Have your form or workflow post to your own backend, and have your backend call us with the key attached.

A missing or wrong key gets 401 Unauthorized. If the key hasn't been configured on our end yet, you'll get 503 Service Unavailable instead.

Request

What to send

phone, selectDate, and time are the only required fields — enough to make this a real, schedulable session. Everything else fills in details a real checkout would normally have collected.

FieldTypeNotes
phonestringRequiredAny format — with or without +91, spaces, dashes. Normalized to the last 10 digits, same as everywhere else in the app, so it matches an existing lead if one exists.
selectDatestringRequiredMust look like "25 Aug 2026" — day, 3-letter month, 4-digit year.
timestringRequiredA precise start time like "11:37 AM - 12:22 PM" — must start with H:MM AM or H:MM PM. Not restricted to fixed slots.
namestringOptionalThe student's name.
emailstringOptionalStored lowercase.
amountnumberOptionalRupees, not paise (e.g. 499, not 49900). Defaults to 0 for a free session.
descriptionstringOptionalInternal note about what this booking is for.
mentorEmailstringOptionalAssigns the mentor on the lead right away, instead of leaving it to the default-assignment rule.
Example request body
{
  "name": "Ananya Rao",
  "phone": "9876543210",
  "email": "ananya.rao@example.com",
  "selectDate": "25 Aug 2026",
  "time": "11:00 AM - 12:00 PM",
  "amount": 0,
  "description": "Free trial — referred by Shubhangi",
  "mentorEmail": "shubhangi@iquanta.pro"
}

Response

What you get back

200 OK  Booking created
{
  "paymentId": "manual_mt1nsco66emegf"
}

That id is how this booking is addressed everywhere else — the detail drawer, reschedule, status changes, the Meet link.

400 Bad Request  Missing/invalid field
{ "error": "Session date must be in the form \"18 Aug 2026\"." }
401 Unauthorized  Missing or wrong key
{ "error": "Invalid or missing X-API-Key." }
503 Service Unavailable  Not configured yet
{ "error": "Manual Booking API is not configured." }

Quick start

Calling it

  1. Call this endpoint with your key attached, whenever a free trial or scholarship seat gets booked on your end.

  2. The booking appears immediately in the dashboard — Booking Management, the calendar, and the lead's timeline all pick it up right away.

cURL
curl -X POST https://razorpay-dashboard-4cba2.web.app/api/public/bookings \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_KEY_HERE" \
  -d '{"name":"Ananya Rao","phone":"9876543210","selectDate":"25 Aug 2026","time":"11:00 AM - 12:00 PM"}'
Node.js
await fetch('https://razorpay-dashboard-4cba2.web.app/api/public/bookings', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-API-Key': process.env.IQUANTA_BOOKINGS_KEY
  },
  body: JSON.stringify({ name, phone, selectDate, time, amount: 0 })
});
PHP
// requires the cURL extension
$ch = curl_init('https://razorpay-dashboard-4cba2.web.app/api/public/bookings');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
  'Content-Type: application/json',
  'X-API-Key: ' . getenv('IQUANTA_BOOKINGS_KEY')
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
  'name' => $name, 'phone' => $phone, 'selectDate' => $selectDate, 'time' => $time
]));
$response = curl_exec($ch);

Good to know

What actually happens behind the scenes

This runs through the exact same code path a real Razorpay webhook payment does — it's built into a payment-shaped record with a synthetic id (prefixed manual_, so it never collides with a real pay_... id), marked captured, and upserted the normal way. That means: a lead is found or created by phone, the booking gets the default status (usually "Booked"), and a Google Meet link is generated the same way it would be for a paid session — all with nothing special-cased for the manual case.

Calling this twice with the same details doesn't merge or dedupe — each call creates a brand-new booking with its own id. There's no idempotency key here, unlike the Lead Capture API's phone-based merge.