What You'll Learn
- Build vs Buy: Should You Build Your Own Booking System?
- API-First vs Iframe Embedding
- Prerequisites & Setup
- Step 1: Create Resources with the API
- Step 2: Query Availability Slots
- Step 3: Create a Booking (curl, Python, Node.js)
- Step 4: Handle Webhooks & Stripe Deposits
- Step 5: Build Your Booking UI
- Next Steps & Production Deployment
1. Build vs Buy: Should You Build Your Own Booking System?
Every team considers building their own booking system at some point. After all, how hard can availability and scheduling be? The reality is more nuanced.
๐ ๏ธ Build In-House
When it makes sense:
- You have extremely specialized scheduling logic (e.g., medical resource allocation)
- You need full control over every aspect of the UX
- You already have calendar/availability infrastructure
Cost: 3โ6 months engineering time + ongoing maintenance. Typical team cost: $50kโ$150k+
๐ Buy (Booking API)
When it makes sense:
- You want to launch in days, not months
- You need multi-tenant isolation out of the box
- Stripe deposits, webhooks, and idempotency matter
- You want AI agent compatibility (Cursor, Claude Code)
Cost: Free to start, โฌ129/mo at scale. Zero maintenance overhead.
๐ก Recommendation: Start with a booking API to validate your product-market fit. You can always build custom scheduling later if your needs become highly specialized. Most teams never need to โ modern booking APIs handle 95%+ of use cases.
2. API-First vs Iframe Embedding
Not all "embed booking" approaches are equal. There are fundamentally two ways to add booking to your app:
๐ฆ Iframe / SDK Embed
Drop in a pre-built UI via iframe or JavaScript SDK (Calendly-style).
- Fastest to implement (minutes)
- No control over UI/UX
- Limited programmatic control
- No data ownership
- Branding mismatch with your app
- Poor mobile/web responsiveness
๐งฉ API-First Embed
Use a REST API and build your own booking UI that matches your brand.
- Full control over UI/UX
- Seamless integration into your app
- Complete data ownership
- Programmatic booking management
- White-label ready
- AI agent compatible
For developer-built apps, API-first embedding is almost always the right choice. It gives you full ownership of the user experience while the API handles the complex scheduling logic, payment processing, and webhook delivery.
3. Prerequisites & Setup
Before you start, you need:
- curl (or Python 3.8+ / Node.js 18+) to follow the code examples
- An AvailEngine account โ sign up free at api.availengine.com
- Your API key from the Developer Portal
The AvailEngine sandbox lets you test without any setup. Here's the sandbox base URL:
# Sandbox (no API key needed)
SANDBOX_URL=https://api.availengine.com/v1/sandbox
# Production (requires API key)
PROD_URL=https://api.availengine.com/v1
๐ก The sandbox is a fully functional booking system with seeded data. You can create, read, update, and delete bookings just like in production โ no signup required. Perfect for prototyping.
4. Step 1: Create Resources with the API
Every booking in AvailEngine is tied to a resource โ the thing being booked (a meeting room, a stylist, a car wash bay). Let's create one:
# Create a resource (sandbox)
curl -X POST https://api.availengine.com/v1/sandbox/resources \
-H "Content-Type: application/json" \
-d '{
"name": "Consultation Room A",
"type": "meeting_room",
"timezone": "Europe/Berlin",
"slot_duration_minutes": 30,
"buffer_minutes": 15,
"daily_start": "09:00",
"daily_end": "17:00"
}'
Response:
{
"id": "res_abc123",
"name": "Consultation Room A",
"type": "meeting_room",
"slot_duration_minutes": 30,
"buffer_minutes": 15,
"daily_start": "09:00",
"daily_end": "17:00",
"timezone": "Europe/Berlin"
}
5. Step 2: Query Availability Slots
Now that you have a resource, check its availability for a given date range:
# Get available slots for the next 7 days
curl "https://api.availengine.com/v1/sandbox/availability?resource_id=res_abc123&date_from=2026-07-22&date_to=2026-07-29"
Response:
{
"slots": [
{
"start": "2026-07-22T09:00:00+02:00",
"end": "2026-07-22T09:30:00+02:00",
"available": true
},
{
"start": "2026-07-22T09:45:00+02:00",
"end": "2026-07-22T10:15:00+02:00",
"available": true
}
// ... more slots
]
}
Notice the 15-minute buffer between slots โ configured when you created the resource. AvailEngine handles buffer times, overlapping bookings, and recurring availability windows automatically.
6. Step 3: Create a Booking
Now let's create a booking in three languages. Each example creates the same booking โ a 30-minute session in Consultation Room A.
curl
curl -X POST https://api.availengine.com/v1/sandbox/bookings \
-H "Content-Type: application/json" \
-H "Idempotency-Key: unique-req-id-001" \
-d '{
"resource_id": "res_abc123",
"start_time": "2026-07-22T09:00:00+02:00",
"end_time": "2026-07-22T09:30:00+02:00",
"customer": {
"name": "Alice Johnson",
"email": "alice@example.com",
"phone": "+49123456789"
},
"notes": "Initial consultation"
}'
Python
import requests
import uuid
BASE_URL = "https://api.availengine.com/v1/sandbox"
booking = requests.post(
f"{BASE_URL}/bookings",
headers={
"Content-Type": "application/json",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"resource_id": "res_abc123",
"start_time": "2026-07-22T09:00:00+02:00",
"end_time": "2026-07-22T09:30:00+02:00",
"customer": {
"name": "Alice Johnson",
"email": "alice@example.com",
},
"notes": "Initial consultation",
},
).json()
print(booking)
# { "id": "bkg_xyz789", "status": "confirmed", ... }
Node.js
const BASE_URL = "https://api.availengine.com/v1/sandbox";
const crypto = require("crypto");
const response = await fetch(`${BASE_URL}/bookings`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
resource_id: "res_abc123",
start_time: "2026-07-22T09:00:00+02:00",
end_time: "2026-07-22T09:30:00+02:00",
customer: { name: "Alice Johnson", email: "alice@example.com" },
notes: "Initial consultation",
}),
});
const booking = await response.json();
console.log(booking);
// { id: "bkg_xyz789", status: "confirmed", ... }
๐ก Idempotency is critical. Always send an Idempotency-Key header. If the request fails (network timeout, 500 error), you can safely retry with the same key โ AvailEngine will return the original result instead of creating a duplicate booking. This is essential for payment-integrated bookings.
7. Step 4: Handle Webhooks & Stripe Deposits
Booking systems are event-driven by nature. AvailEngine sends HMAC-signed webhooks for 10+ event types including:
booking.createdโ a new booking was confirmedbooking.cancelledโ a booking was cancelledbooking.rescheduledโ time slot changeddeposit.collectedโ Stripe deposit was successfully chargeddeposit.refundedโ deposit was returned on cancellation
Here's how to verify a webhook signature in Node.js:
const crypto = require("crypto");
function verifyWebhook(payload, signature, secret) {
const expected = crypto
.createHmac("sha256", secret)
.update(JSON.stringify(payload))
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature)
);
}
// Usage in your webhook endpoint
app.post("/webhooks/availengine", (req, res) => {
const signature = req.headers["x-availengine-signature"];
if (!verifyWebhook(req.body, signature, process.env.WEBHOOK_SECRET)) {
return res.status(401).send("Invalid signature");
}
// Process the webhook event
handleBookingEvent(req.body);
res.status(200).send("OK");
});
Stripe deposits are handled at booking creation. Pass a deposit amount and the API handles the Stripe PaymentIntent lifecycle โ authorization, capture, and refund โ with proper idempotency for payment retries.
8. Step 5: Build Your Booking UI
With the API working, you now build a native booking UI in your app. A typical booking flow has these screens:
- Service/Resource selector โ List available resources (rooms, staff, time slots)
- Date & Time picker โ Fetch availability from the API, render your own calendar widget
- Customer details form โ Collect name, email, phone
- Payment (optional) โ Use Stripe Elements to collect payment, then create the booking with a deposit
- Confirmation โ Display booking details and sync to Google Calendar via AvailEngine
Because you own the UI, every element matches your brand โ colors, fonts, spacing, animations. No iframe chrome, no third-party branding.
9. Next Steps & Production Deployment
You now have a working embedded booking system. Here's what to do next:
- Complete the official Getting Started guide โ
- Set up your production API key in the Developer Portal
- Configure Stripe Connect to collect payments on bookings
- Enable Google Calendar sync for automatic calendar integration
- Set up webhook endpoints for real-time booking notifications
- Review pricing โ Free โฌ0/mo for 500 bookings, Scale โฌ129/mo for 50k bookings
Ready to Embed Booking in Your App?
Try the sandbox with zero signup. Create a booking in 30 seconds.