Authentication
All API requests require an API key passed in the X-API-Key header.
curl -X GET "https://api.b5n.io/api/availability?date=2026-01-20" \
-H "X-API-Key: oxb_your_api_key_here"Security Note: API keys are only shown once when created. Store them securely - if lost, you'll need to generate a new key.
API Scopes
| Scope | Description |
|---|---|
availability:read | Check available appointment slots |
appointments:read | View appointment details |
appointments:write | Create and update appointments |
appointments:delete | Cancel appointments |
employees:read | View employee information |
services:read | View service types |
Availability
Appointments
Recurring Appointments
Create and manage recurring appointment series for customers with regular visits. Perfect for weekly therapy sessions, bi-weekly cleanings, monthly check-ups, and more.
Key Concepts
Each recurring series has a unique series_id that links all appointments together. Use this to identify and manage the series.
The first appointment in a series is the parent. All others reference it viaparent_appointment_id.
When creating a series, all occurrences are checked for conflicts. If any date/time is unavailable, the entire series creation fails with a list of conflicting dates.
Each appointment in a series can be updated independently usingPUT /api/appointments/:id.
Recurrence Patterns
| Pattern | Description | Example |
|---|---|---|
weekly | Every week on the same day | Every Monday at 2pm |
biweekly | Every 2 weeks | Every other Monday |
monthly | Once per month on the same date | 15th of each month |
custom | Custom interval (requires interval + interval_unit) | Every 3 days, every 6 weeks |
End Conditions
Specify when the series should end using either count orend_date (not both):
By Count
"recurrence": {
"pattern": "weekly",
"count": 10 // Create 10 appointments
}By End Date
"recurrence": {
"pattern": "weekly",
"end_date": "2026-06-30" // Until June 30
}Cancellation Scopes
When cancelling a recurring appointment, use the scope parameter to control what gets cancelled:
singleCancel only this appointment
Default behavior. Other appointments in the series are unaffected.
futureCancel this and all future
Cancels the specified appointment and all later appointments in the series.
allCancel entire series
Cancels all scheduled/confirmed appointments in the series. Completed appointments are not affected.
Best Practices
- • Check availability first: Verify the time slot is available for all occurrences
- • Use count wisely: Maximum 52 occurrences (about 1 year of weekly appointments)
- • Store series_id: Save the
series_idfrom the response to manage the series later - • Notify customers: When cancelling a series, send appropriate notifications about all affected appointments
Employees
Services
AI Agent Integration
This API is designed for LLM/AI agent tool calling. Each response includes a human-readablesummaryfield that can be used directly in conversation.
// Example response with AI-friendly summary
{
"available": true,
"slots": [...],
"summary": "3 slots available on January 20th: 9am with Mike, 10am with Mike, 2pm with Sarah"
}AI-Friendly Input Handling
- • Empty strings are treated as null/omitted - safe to pass
""for optional fields - • Array wrapper accepted - request body can be
[{...}]and will be unwrapped automatically - • Extra fields are ignored - safe to include metadata like
actionin requests - • Type coercion supported -
duration_minutes: "60"works as well as60
Rate Limiting
API requests are rate limited to 100 requests per minute per API key. Exceeding this limit will result in a 429 Too Many Requests response.
n8n Integration
Use n8n to automate appointment creation from forms, chatbots, or other triggers. Here's how to set up an n8n workflow to create appointments via the B5N Booking API.
Step 1: Create a Webhook Trigger
Add a Webhook node as your trigger. This will receive data from your form, chatbot, or other source.
- • Set HTTP Method to
POST - • Copy the webhook URL to use in your form/chatbot
- • The webhook will receive customer data as JSON
Step 2: Add an HTTP Request Node
Connect an HTTP Request node to call the B5N Booking API.
HTTP Request Node Settings:
━━━━━━━━━━━━━━━━━━━━━━━━━━━
Method: POST
URL: https://your-domain.com/api/appointments
Headers:
X-API-Key: oxb_your_api_key_here
Content-Type: application/json
Body (JSON):
{
"start_time": "{{ $json.appointment_time }}",
"employee_id": "{{ $json.employee_id }}",
"customer_name": "{{ $json.customer_name }}",
"customer_phone": "{{ $json.customer_phone }}",
"customer_email": "{{ $json.customer_email }}",
"service_type": "{{ $json.service_type }}",
"notes": "{{ $json.notes }}"
}Step 3: Example Workflow JSON
Import this workflow into n8n to get started quickly:
{
"nodes": [
{
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"position": [250, 300],
"parameters": {
"httpMethod": "POST",
"path": "book-appointment"
}
},
{
"name": "Create Appointment",
"type": "n8n-nodes-base.httpRequest",
"position": [450, 300],
"parameters": {
"method": "POST",
"url": "https://your-domain.com/api/appointments",
"headers": {
"X-API-Key": "oxb_your_api_key_here"
},
"bodyParameters": {
"start_time": "={{ $json.start_time }}",
"employee_id": "={{ $json.employee_id }}",
"customer_name": "={{ $json.customer_name }}",
"customer_phone": "={{ $json.customer_phone }}"
}
}
}
],
"connections": {
"Webhook": {
"main": [[{ "node": "Create Appointment", "type": "main", "index": 0 }]]
}
}
}Step 4: Test Your Workflow
Send a test request to your webhook URL:
curl -X POST "https://your-n8n-instance.com/webhook/book-appointment" \
-H "Content-Type: application/json" \
-d '{
"start_time": "2026-01-20T14:00:00Z",
"employee_id": "e1111111-1111-1111-1111-111111111111",
"customer_name": "John Smith",
"customer_phone": "+15551234567",
"customer_email": "john@example.com",
"service_type": "drain-cleaning"
}'Pro Tips
- • Use the
/api/availabilityendpoint first to check available slots - • Store your API key in n8n Credentials for better security
- • Add error handling nodes to notify you if booking fails
- • Use the
summaryfield from responses for chatbot replies
n8n AI Chat Agent (Full Integration)
Build a complete AI-powered booking assistant using n8n's chat interface and AI Agent node. This agent can answer questions about services, check employee availability, and book appointments through natural conversation.
Architecture Overview
Nodes Required
Provides a chat interface for users. Enable "Public" to embed on your website or use the n8n chat URL directly.
The brain of your assistant. Configure with OpenAI GPT-4 and connect tools for each API endpoint.
"You are a helpful booking assistant for [Company Name]. Help customers check available services, find appointment times, and book appointments. Always confirm details before booking. Be friendly and professional."
Create separate HTTP Request nodes for each API capability:
get_services→ GET /api/servicesget_employees→ GET /api/employeescheck_availability→ GET /api/availabilitybook_appointment→ POST /api/appointmentslookup_appointment→ GET /api/appointments/lookupMaintains conversation context so the agent remembers previous messages in the chat session.
Tool Configuration Examples
Each HTTP Request tool needs a description so the AI knows when to use it:
// get_services tool
Name: get_services
Description: Get a list of all available services with their names, durations, and prices. Use this when the customer asks what services are offered.
// check_availability tool
Name: check_availability
Description: Check available appointment slots for a specific date. Requires a date parameter in YYYY-MM-DD format. Optionally filter by employee_id or service_type.
// book_appointment tool
Name: book_appointment
Description: Book a new appointment. Requires: start_time (ISO format), employee_id, customer_name, customer_phone. Optional: customer_email, service_type, notes.Sample Conversation
• Drain Cleaning (60 min) - $150
• Pipe Repair (90 min) - $200
• Water Heater Service (120 min) - $300
Would you like to book any of these?
• 9:00 AM with Mike
• 2:00 PM with Mike
• 4:00 PM with Sarah
Which time works best for you?
✓ Drain Cleaning with Mike
✓ Tomorrow at 2:00 PM
✓ John - (555) 123-4567
You'll receive a confirmation. Is there anything else?
Complete Workflow JSON
Copy and import this workflow into n8n. Replace YOUR_API_URL andoxb_your_api_key with your actual values.
{
"name": "B5N Booking AI Chat Agent",
"nodes": [
{
"parameters": {
"public": true,
"initialMessages": "Hi! 👋 I'm your booking assistant. I can help you:\n- View our services\n- Check appointment availability\n- Book an appointment\n- Look up existing bookings\n\nHow can I help you today?",
"options": {}
},
"id": "chat-trigger",
"name": "Chat Trigger",
"type": "@n8n/n8n-nodes-langchain.chatTrigger",
"typeVersion": 1.1,
"position": [0, 0]
},
{
"parameters": {
"options": {
"systemMessage": "You are a helpful booking assistant. Help customers:\n1. Learn about available services\n2. Check appointment availability for specific dates\n3. Book new appointments\n4. Look up existing appointments by phone number\n\nAlways be friendly and professional. Confirm all details before booking. Use the provided tools to interact with the booking system. When showing availability, format times clearly. After booking, confirm all details with the customer."
}
},
"id": "ai-agent",
"name": "AI Agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"typeVersion": 1.7,
"position": [220, 0]
},
{
"parameters": {
"model": "gpt-4o-mini",
"options": {}
},
"id": "openai-chat",
"name": "OpenAI Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"typeVersion": 1,
"position": [0, 200]
},
{
"parameters": {},
"id": "memory",
"name": "Window Buffer Memory",
"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
"typeVersion": 1.2,
"position": [140, 200]
},
{
"parameters": {
"name": "get_services",
"description": "Get all available services with names, durations, and prices. Use when customer asks what services are offered.",
"method": "GET",
"url": "=YOUR_API_URL/api/services",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"options": {}
},
"id": "tool-services",
"name": "Get Services",
"type": "@n8n/n8n-nodes-langchain.toolHttpRequest",
"typeVersion": 1.1,
"position": [280, 200],
"credentials": {
"httpHeaderAuth": {
"name": "B5N Booking API Key"
}
}
},
{
"parameters": {
"name": "get_employees",
"description": "Get all employees who can perform services. Returns employee IDs and names.",
"method": "GET",
"url": "=YOUR_API_URL/api/employees",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"options": {}
},
"id": "tool-employees",
"name": "Get Employees",
"type": "@n8n/n8n-nodes-langchain.toolHttpRequest",
"typeVersion": 1.1,
"position": [420, 200],
"credentials": {
"httpHeaderAuth": {
"name": "B5N Booking API Key"
}
}
},
{
"parameters": {
"name": "check_availability",
"description": "Check available appointment slots. Required parameter: date (YYYY-MM-DD format). Optional: employee_id, service_type, duration_minutes. Returns available time slots.",
"method": "GET",
"url": "=YOUR_API_URL/api/availability",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendQuery": true,
"parametersQuery": {
"values": [
{ "name": "date", "value": "={{ $fromAI('date', 'The date to check in YYYY-MM-DD format') }}" },
{ "name": "employee_id", "value": "={{ $fromAI('employee_id', 'Optional employee ID to filter by', '') }}" },
{ "name": "service_type", "value": "={{ $fromAI('service_type', 'Optional service type slug', '') }}" }
]
},
"options": {}
},
"id": "tool-availability",
"name": "Check Availability",
"type": "@n8n/n8n-nodes-langchain.toolHttpRequest",
"typeVersion": 1.1,
"position": [560, 200],
"credentials": {
"httpHeaderAuth": {
"name": "B5N Booking API Key"
}
}
},
{
"parameters": {
"name": "book_appointment",
"description": "Book a new appointment. Required: start_time (ISO 8601), employee_id (UUID), customer_name, customer_phone. Optional: customer_email, service_type, duration_minutes, notes.",
"method": "POST",
"url": "=YOUR_API_URL/api/appointments",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"start_time\": \"{{ $fromAI('start_time', 'Appointment start time in ISO 8601 format') }}\",\n \"employee_id\": \"{{ $fromAI('employee_id', 'The employee UUID') }}\",\n \"customer_name\": \"{{ $fromAI('customer_name', 'Customer full name') }}\",\n \"customer_phone\": \"{{ $fromAI('customer_phone', 'Customer phone number with country code') }}\",\n \"customer_email\": \"{{ $fromAI('customer_email', 'Customer email address', '') }}\",\n \"service_type\": \"{{ $fromAI('service_type', 'Service type slug', '') }}\",\n \"notes\": \"{{ $fromAI('notes', 'Any special notes or requests', '') }}\"\n}",
"options": {}
},
"id": "tool-book",
"name": "Book Appointment",
"type": "@n8n/n8n-nodes-langchain.toolHttpRequest",
"typeVersion": 1.1,
"position": [700, 200],
"credentials": {
"httpHeaderAuth": {
"name": "B5N Booking API Key"
}
}
},
{
"parameters": {
"name": "lookup_appointment",
"description": "Look up existing appointments by customer phone number. Use when customer wants to check or manage their bookings.",
"method": "GET",
"url": "=YOUR_API_URL/api/appointments/lookup",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendQuery": true,
"parametersQuery": {
"values": [
{ "name": "phone", "value": "={{ $fromAI('phone', 'Customer phone number to look up') }}" }
]
},
"options": {}
},
"id": "tool-lookup",
"name": "Lookup Appointment",
"type": "@n8n/n8n-nodes-langchain.toolHttpRequest",
"typeVersion": 1.1,
"position": [840, 200],
"credentials": {
"httpHeaderAuth": {
"name": "B5N Booking API Key"
}
}
}
],
"connections": {
"Chat Trigger": {
"main": [[{ "node": "AI Agent", "type": "main", "index": 0 }]]
},
"OpenAI Chat Model": {
"ai_languageModel": [[{ "node": "AI Agent", "type": "ai_languageModel", "index": 0 }]]
},
"Window Buffer Memory": {
"ai_memory": [[{ "node": "AI Agent", "type": "ai_memory", "index": 0 }]]
},
"Get Services": {
"ai_tool": [[{ "node": "AI Agent", "type": "ai_tool", "index": 0 }]]
},
"Get Employees": {
"ai_tool": [[{ "node": "AI Agent", "type": "ai_tool", "index": 0 }]]
},
"Check Availability": {
"ai_tool": [[{ "node": "AI Agent", "type": "ai_tool", "index": 0 }]]
},
"Book Appointment": {
"ai_tool": [[{ "node": "AI Agent", "type": "ai_tool", "index": 0 }]]
},
"Lookup Appointment": {
"ai_tool": [[{ "node": "AI Agent", "type": "ai_tool", "index": 0 }]]
}
},
"settings": {
"executionOrder": "v1"
}
}Setup Instructions
Create API Credential in n8n
Go to Credentials → Add → Header Auth. Name it "B5N Booking API Key". Set header name to X-API-Key and value to your API key.
Add OpenAI Credential
Go to Credentials → Add → OpenAI API. Enter your OpenAI API key.
Import the Workflow
Copy the JSON above, go to n8n → Workflows → Import from JSON. Paste and save.
Update API URL
Find & replace YOUR_API_URL with your actual B5N Booking URL (e.g., https://booking.yourcompany.com).
Activate & Test
Activate the workflow. Click "Chat" in the canvas to open the chat interface and test your booking agent!
Embedding the Chat
To embed this chat on your website, enable "Public" in the Chat Trigger settings, then use the embed code:
<script src="https://your-n8n.com/webhook/chat/embed.js"></script>
<link href="https://your-n8n.com/webhook/chat/style.css" rel="stylesheet" />
<script>
createChat({
webhookUrl: 'https://your-n8n.com/webhook/CHAT_ID/chat',
theme: { primaryColor: '#22c55e' }
});
</script>Embed Widget
Add a booking widget to any website. The embed system includes domain-based access control to prevent unauthorized websites from embedding your booking page.
Quick Start
<div id="oxen-booking" data-slug="your-org-slug"></div>
<script src="https://your-domain.com/embed.js" async></script>Domain Security
Control which websites can embed your booking widget via Dashboard → Settings → Embed Widget.
| Setting | Behavior |
|---|---|
| Public mode ON, no domains | All domains allowed |
| Public mode ON + domains configured | Only configured domains allowed |
| Public mode OFF + domains configured | Only configured domains allowed |
| Public mode OFF, no domains | All domains blocked (403) |
Full Documentation: See the Embed Widget Documentation for configuration options, JavaScript API, callbacks, styling, and troubleshooting.
Make.com Integration
Make.com (formerly Integromat) is a visual automation platform. Use it to connect B5N Booking with hundreds of apps like Typeform, Google Forms, HubSpot, Slack, and more.
Quick Setup
Create HTTP Connection
In Make.com → Connections → Add HTTP with Headers. Set X-API-Key header with your API key.
Add HTTP Request Module
Use HTTP → Make a request module to call B5N Booking API endpoints.
Map Your Data
Use Make.com expressions like {{1.field}} to map form data to API parameters.
Check Availability Module
HTTP Request Module Settings:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
URL: https://your-domain.com/api/availability
Method: GET
Query String:
- date: {{formatDate(1.requested_date; "YYYY-MM-DD")}}
- service_type: {{1.service_type}}
Headers:
- X-API-Key: oxb_your_api_key_hereBook Appointment Module
HTTP Request Module Settings:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
URL: https://your-domain.com/api/appointments
Method: POST
Body Type: Raw
Content Type: JSON (application/json)
Request Content:
{
"start_time": "{{2.body.slots[1].start}}",
"employee_id": "{{2.body.slots[1].employee.id}}",
"customer_name": "{{1.customer_name}}",
"customer_phone": "{{1.customer_phone}}",
"customer_email": "{{1.customer_email}}",
"service_type": "{{1.service_type}}"
}Popular Scenarios
Typeform/Google Forms → Check Availability → Book Appointment → Send Confirmation Email
HubSpot Deal Stage Change → Book Appointment → Update Deal with Appointment Details
Webhook (appointment.created) → Create Google Calendar Event → Send Slack Notification
Webhook (appointment.reminder) → Twilio SMS → Log to Google Sheets
Data Mapping Reference
| Expression | Returns |
|---|---|
{{X.body.available}} | true/false |
{{X.body.slots[1].start}} | First slot start time |
{{X.body.slots[1].employee.id}} | Employee ID for booking |
{{X.body.summary}} | Human-readable summary |
{{X.body.confirmation}} | Booking confirmation text |
Complete Guide
For detailed instructions, example scenarios, webhook setup, and troubleshooting, see ourMake.com Integration Guide.