Meetario Developer API
Build powerful scheduling integrations with our comprehensive REST API. Full control over events, bookings, and webhooks.
Overview
The Calendar Booking API enables you to build applications that integrate with our scheduling platform. The API is RESTful, uses JSON for request and response bodies, and follows standard HTTP response codes and authentication methods.
Fast & Reliable
99.9% uptime, built for performance
Secure
OAuth 2.0, HMAC signatures, rate limiting
Scalable
From startups to enterprise plans
Webhooks
Real-time event notifications with retries
Quick Start — 3 steps
- Create an API token in your dashboard
- Make your first call:
GET /api/v1/events - Start building your integration!
Authentication
The API uses Bearer token authentication. Include your API token in the Authorization header for all requests.
All API endpoints require authentication using a valid API token. Tokens can be created in your account dashboard.
curl -H "Authorization: Bearer pat_1234567890abcdef..." \
"https://meetario.com/api/v1/events"
const response = await fetch('https://meetario.com/api/v1/events', {
headers: {
'Authorization': 'Bearer pat_1234567890abcdef...',
'Content-Type': 'application/json'
}
});
$client = new \GuzzleHttp\Client();
$response = $client->get('https://meetario.com/api/v1/events', [
'headers' => [
'Authorization' => 'Bearer pat_1234567890abcdef...',
'Content-Type' => 'application/json'
]
]);
API Scopes
Control access to different resources using scopes:
Rate Limiting
API requests are rate limited to ensure fair usage and optimal performance for all users.
Rate Limits
- 100 requests per minute (default)
- 1,000 requests per hour
- 10,000 requests per day
- 10 requests per second (burst limit)
Rate Limit Headers
Every API response includes rate limit information in the headers:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1640995200
X-RateLimit-Used: 5
Events
Manage scheduled events, bookings, and appointments through the Events API.
Retrieve a list of events with optional filtering and pagination.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
| page | integer | Page number (default: 1) |
| limit | integer | Items per page (max: 100, default: 20) |
| status | string | Filter by status (pending, confirmed, cancelled, completed) |
| event_type | integer | Filter by event type ID |
Response
{
"data": [
{
"uuid": "evt_abc123def456",
"id": 123,
"status": "confirmed",
"start_time": "2025-06-20T10:00:00Z",
"end_time": "2025-06-20T11:00:00Z",
"timezone": "America/New_York",
"event_type": {
"uuid": "et_789xyz",
"name": "30 Minute Meeting",
"slug": "30-minute-meeting",
"duration": 30
},
"invitee": {
"name": "John Doe",
"email": "john@example.com",
"phone": "+1234567890"
},
"host": {
"name": "Jane Smith",
"email": "jane@example.com"
},
"notes": "Discuss project requirements",
"created_at": "2025-06-15T14:30:00Z",
"updated_at": "2025-06-15T14:30:00Z"
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 1,
"pages": 1
}
}
Create a new event booking.
Request Body
| Field | Type | Description |
|---|---|---|
| event_type_id required | integer | ID of the event type to book |
| attendee_email required | string | Email address of the attendee |
| attendee_name required | string | Full name of the attendee |
| start_time required | string | Start time in ISO 8601 format |
| attendee_phone | string | Phone number of the attendee |
| notes | string | Additional notes for the event |
{
"event_type_id": 123,
"attendee_email": "john@example.com",
"attendee_name": "John Doe",
"attendee_phone": "+1234567890",
"start_time": "2025-06-20T10:00:00Z",
"timezone": "America/New_York",
"notes": "Project discussion",
"custom_field_values": {
"company": "ACME Corp"
}
}
{
"data": {
"uuid": "evt_abc123def456",
"id": 123,
"status": "confirmed",
"start_time": "2025-06-20T10:00:00Z",
"end_time": "2025-06-20T11:00:00Z",
"event_type": {
"name": "30 Minute Meeting",
"duration": 30
},
"invitee": {
"name": "John Doe",
"email": "john@example.com"
},
"created_at": "2025-06-15T14:30:00Z"
}
}
Event Types
Manage your event types - templates that define the structure and settings for bookable events.
Retrieve a list of your event types with optional filtering.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
| page | integer | Page number (default: 1) |
| limit | integer | Items per page (max: 100, default: 20) |
| active | boolean | Filter by active status |
Response
{
"data": [
{
"uuid": "et_abc123def456",
"id": 123,
"name": "30 Minute Meeting",
"slug": "30-minute-meeting",
"description": "A quick 30-minute consultation",
"duration": 30,
"color": "#4F46E5",
"location": {
"type": "zoom_meeting",
"display": "Zoom Call",
"custom": null
},
"is_active": true,
"requires_approval": false,
"scheduling_settings": {
"buffer_time_before": 5,
"buffer_time_after": 10,
"min_advance_booking": 24,
"max_advance_booking": 60,
"available_days": ["monday", "tuesday", "wednesday", "thursday", "friday"]
},
"timezone": "America/New_York",
"payment": {
"is_paid": false,
"price": null,
"currency": "USD",
"payment_method": null
},
"custom_fields": [],
"sort_order": 0,
"created_at": "2025-06-15T14:30:00Z",
"updated_at": "2025-06-15T14:30:00Z",
"uri": "/api/v1/event_types/123",
"scheduling_url": "username/30-minute-meeting"
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 1,
"pages": 1
}
}
Create a new event type.
Request Body
| Field | Type | Description |
|---|---|---|
| name required | string | Name of the event type |
| duration required | integer | Duration in minutes (15-480) |
| description | string | Description of the event type |
| color | string | Hex color code (default: #4F46E5) |
| location | string | zoom_meeting, google_meet, phone_call, in_person, custom |
| timezone | string | Timezone identifier (default: UTC) |
| price | decimal | Price for paid events |
{
"name": "Strategy Session",
"duration": 60,
"description": "Deep dive strategy discussion",
"color": "#7C3AED",
"location": "zoom_meeting",
"timezone": "America/New_York",
"requires_approval": true,
"buffer_time_before": 15,
"buffer_time_after": 15,
"min_advance_booking": 48,
"max_advance_booking": 90,
"available_days": ["monday", "tuesday", "wednesday", "thursday"],
"price": "150.00",
"currency": "USD"
}
Get available time slots for an event type.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
| start_date | string | Start date in YYYY-MM-DD format |
| end_date | string | End date in YYYY-MM-DD format |
{
"data": [
{
"date": "2025-06-20",
"slots": [
{
"start_time": "2025-06-20T09:00:00Z",
"end_time": "2025-06-20T10:00:00Z",
"available": true
},
{
"start_time": "2025-06-20T10:30:00Z",
"end_time": "2025-06-20T11:30:00Z",
"available": true
}
]
}
]
}
Users
Manage user profiles, preferences, and availability settings.
Get the current authenticated user's profile.
Response
{
"data": {
"uuid": "usr_abc123def456",
"id": 123,
"email": "john@example.com",
"name": "John Doe",
"first_name": "John",
"last_name": "Doe",
"avatar_url": "https://example.com/avatar.jpg",
"timezone": "America/New_York",
"position": "Product Manager",
"company": "ACME Corp",
"locale": {
"date_format": "MM/dd/yyyy",
"time_format": "hh:mm a",
"week_start": 1
},
"status": "active",
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-06-15T14:30:00Z",
"uri": "/api/v1/users/me"
}
}
Update the current user's profile information.
Request Body
| Field | Type | Description |
|---|---|---|
| first_name | string | User's first name |
| last_name | string | User's last name |
| timezone | string | User's timezone |
| position | string | Job title/position |
| company | string | Company name |
| date_format | string | Preferred date format |
| time_format | string | Preferred time format |
{
"first_name": "John",
"last_name": "Smith",
"timezone": "Europe/London",
"position": "Senior Product Manager",
"company": "Tech Startup Inc",
"date_format": "dd/MM/yyyy",
"time_format": "HH:mm"
}
Get the user's weekly availability schedule.
Response
{
"data": {
"availability": {
"1": {"enabled": true, "start": "09:00", "end": "17:00"},
"2": {"enabled": true, "start": "09:00", "end": "17:00"},
"3": {"enabled": true, "start": "09:00", "end": "17:00"},
"4": {"enabled": true, "start": "09:00", "end": "17:00"},
"5": {"enabled": true, "start": "09:00", "end": "17:00"},
"6": {"enabled": false, "start": "09:00", "end": "17:00"},
"7": {"enabled": false, "start": "09:00", "end": "17:00"}
},
"timezone": "America/New_York"
}
}
Update the user's weekly availability schedule.
Request Body
| Field | Type | Description |
|---|---|---|
| availability required | object | Weekly availability object (days 1-7) |
| timezone | string | Timezone for the availability times |
{
"availability": {
"1": {"enabled": true, "start": "08:00", "end": "18:00"},
"2": {"enabled": true, "start": "08:00", "end": "18:00"},
"3": {"enabled": true, "start": "08:00", "end": "18:00"},
"4": {"enabled": true, "start": "08:00", "end": "18:00"},
"5": {"enabled": true, "start": "08:00", "end": "16:00"},
"6": {"enabled": false, "start": "09:00", "end": "17:00"},
"7": {"enabled": false, "start": "09:00", "end": "17:00"}
},
"timezone": "America/New_York"
}
Webhooks
Configure webhooks to receive real-time notifications when events occur in your calendar application.
Available webhook events:
Retrieve a list of your configured webhooks.
Response
{
"data": [
{
"uuid": "wh_abc123def456",
"id": 123,
"name": "Main Webhook",
"url": "https://your-app.com/webhooks/calendar",
"events": ["booking.created", "booking.cancelled"],
"status": "active",
"secret": "whsec_1234567890abcdef...",
"headers": {
"X-Custom-Header": "value"
},
"timeout_seconds": 30,
"max_retries": 3,
"verify_ssl": true,
"stats": {
"success_count": 45,
"failure_count": 2,
"success_rate": 95.74,
"last_success_at": "2025-06-15T14:30:00Z",
"last_failure_at": "2025-06-14T09:15:00Z"
},
"created_at": "2025-06-01T10:00:00Z",
"updated_at": "2025-06-15T14:30:00Z"
}
]
}
Create a new webhook.
Request Body
| Field | Type | Description |
|---|---|---|
| name required | string | Name for the webhook |
| url required | string | Webhook endpoint URL |
| events required | array | Array of events to subscribe to |
| headers | object | Custom headers to include |
| timeout_seconds | integer | Request timeout (default: 30) |
| max_retries | integer | Max retry attempts (default: 3) |
| verify_ssl | boolean | Verify SSL certificates (default: true) |
{
"name": "Booking Notifications",
"url": "https://my-app.com/api/webhooks/bookings",
"events": [
"booking.created",
"booking.confirmed",
"booking.cancelled"
],
"headers": {
"X-API-Key": "my-api-key",
"X-Custom-Header": "custom-value"
},
"timeout_seconds": 30,
"max_retries": 3,
"verify_ssl": true
}
Update an existing webhook configuration.
Request Body
| Field | Type | Description |
|---|---|---|
| name | string | Updated name for the webhook |
| url | string | Updated webhook endpoint URL |
| events | array | Updated array of events to subscribe to |
| status | string | active, inactive |
{
"name": "Updated Webhook Name",
"events": [
"booking.created",
"booking.cancelled",
"booking.rescheduled"
],
"status": "active"
}
Delete a webhook permanently.
Response
{
"message": "Webhook deleted successfully"
}
Send a test payload to your webhook endpoint.
Response
{
"message": "Test webhook sent successfully",
"delivery": {
"id": "del_abc123def456",
"status": "delivered",
"response_code": 200,
"response_time_ms": 245,
"sent_at": "2025-06-15T14:30:00Z"
}
}
- Always verify signatures - Use the webhook secret to verify payload authenticity
- Handle idempotency - Process the same webhook multiple times safely
- Respond quickly - Return 2xx status codes within 30 seconds
- Handle failures gracefully - Webhooks will be retried up to 3 times
- Use HTTPS - Only HTTPS URLs are supported for security
Error Handling
The API uses conventional HTTP response codes and returns detailed error information in JSON format.
Error Response Format
{
"error": "validation_error",
"message": "The request is invalid",
"status_code": 422,
"timestamp": "2025-06-15T14:30:00Z",
"details": [
{
"field": "start_time",
"message": "Start time is required"
}
]
}
HTTP Status Codes
| Code | Type | Description |
|---|---|---|
| 200 | Success | Request successful |
| 400 | Bad Request | The request is invalid |
| 401 | Unauthorized | Authentication required |
| 404 | Not Found | Resource not found |
| 422 | Validation Error | Validation failed |
| 429 | Rate Limit | Rate limit exceeded |
Complete Examples
Real-world examples showing how to integrate with the Calendar Booking API.
Complete Booking Flow
1. Get available event types
curl -H "Authorization: Bearer pat_..." \
"https://meetario.com/api/v1/event_types"
2. Check availability
curl -H "Authorization: Bearer pat_..." \
"https://meetario.com/api/v1/event_types/123/availability?start_date=2025-06-20"
3. Create booking
curl -X POST \
-H "Authorization: Bearer pat_..." \
-H "Content-Type: application/json" \
-d '{
"event_type_id": 123,
"attendee_email": "john@example.com",
"attendee_name": "John Doe",
"start_time": "2025-06-20T10:00:00Z"
}' \
"https://meetario.com/api/v1/events"
class CalendarAPI {
constructor(apiToken) {
this.baseUrl = 'https://meetario.com/api/v1';
this.headers = {
'Authorization': `Bearer ${apiToken}`,
'Content-Type': 'application/json'
};
}
async getEventTypes() {
const response = await fetch(`${this.baseUrl}/event_types`, {
headers: this.headers
});
return response.json();
}
async getAvailability(eventTypeId, startDate) {
const response = await fetch(
`${this.baseUrl}/event_types/${eventTypeId}/availability?start_date=${startDate}`,
{ headers: this.headers }
);
return response.json();
}
async createEvent(eventData) {
const response = await fetch(`${this.baseUrl}/events`, {
method: 'POST',
headers: this.headers,
body: JSON.stringify(eventData)
});
return response.json();
}
}
// Usage
const api = new CalendarAPI('pat_your_token_here');
async function bookAppointment() {
try {
// Get available event types
const eventTypes = await api.getEventTypes();
// Check availability
const availability = await api.getAvailability(123, '2025-06-20');
// Create booking
const booking = await api.createEvent({
event_type_id: 123,
attendee_email: 'john@example.com',
attendee_name: 'John Doe',
start_time: '2025-06-20T10:00:00Z'
});
console.log('Booking created:', booking);
} catch (error) {
console.error('Error:', error);
}
}
client = new \GuzzleHttp\Client([
'base_uri' => $this->baseUrl,
'headers' => [
'Authorization' => "Bearer {$apiToken}",
'Content-Type' => 'application/json'
]
]);
}
public function getEventTypes() {
$response = $this->client->get('/event_types');
return json_decode($response->getBody(), true);
}
public function getAvailability($eventTypeId, $startDate) {
$response = $this->client->get("/event_types/{$eventTypeId}/availability", [
'query' => ['start_date' => $startDate]
]);
return json_decode($response->getBody(), true);
}
public function createEvent($eventData) {
$response = $this->client->post('/events', [
'json' => $eventData
]);
return json_decode($response->getBody(), true);
}
}
// Usage
$api = new CalendarAPI('pat_your_token_here');
try {
// Get available event types
$eventTypes = $api->getEventTypes();
// Check availability
$availability = $api->getAvailability(123, '2025-06-20');
// Create booking
$booking = $api->createEvent([
'event_type_id' => 123,
'attendee_email' => 'john@example.com',
'attendee_name' => 'John Doe',
'start_time' => '2025-06-20T10:00:00Z'
]);
echo "Booking created: " . json_encode($booking);
} catch (Exception $e) {
echo "Error: " . $e->getMessage();
}
?>
Support
Get help when you need it with our comprehensive support resources.
Email Support
Get help via email from our API support team
meetario-team@meetario.com