Files
Michilis 41f6ae916f first commit
Made-with: Cursor
2026-02-28 02:17:55 +00:00

192 lines
8.8 KiB
JSON

{
"paths": {
"/calendars/{id}/booking-link": {
"post": {
"tags": ["Booking"],
"summary": "Create a booking link",
"description": "Creates a public booking link for a calendar with configurable duration, buffer time, working hours, and timezone. Only the calendar owner can create booking links. Requires `booking:write` scope.",
"operationId": "createBookingLink",
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": { "type": "string", "format": "uuid" },
"description": "Calendar ID"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"required": ["duration_minutes", "timezone", "working_hours"],
"properties": {
"duration_minutes": { "type": "integer", "minimum": 5, "example": 30 },
"buffer_minutes": { "type": "integer", "minimum": 0, "default": 0, "example": 0 },
"timezone": { "type": "string", "example": "America/Asuncion" },
"working_hours": {
"type": "object",
"description": "Working hour windows per day of week",
"properties": {
"mon": { "type": "array", "items": { "$ref": "#/components/schemas/WorkingHourSlot" } },
"tue": { "type": "array", "items": { "$ref": "#/components/schemas/WorkingHourSlot" } },
"wed": { "type": "array", "items": { "$ref": "#/components/schemas/WorkingHourSlot" } },
"thu": { "type": "array", "items": { "$ref": "#/components/schemas/WorkingHourSlot" } },
"fri": { "type": "array", "items": { "$ref": "#/components/schemas/WorkingHourSlot" } },
"sat": { "type": "array", "items": { "$ref": "#/components/schemas/WorkingHourSlot" } },
"sun": { "type": "array", "items": { "$ref": "#/components/schemas/WorkingHourSlot" } }
},
"example": {
"mon": [{ "start": "09:00", "end": "17:00" }],
"tue": [{ "start": "09:00", "end": "17:00" }],
"wed": [{ "start": "09:00", "end": "17:00" }],
"thu": [{ "start": "09:00", "end": "17:00" }],
"fri": [{ "start": "09:00", "end": "17:00" }],
"sat": [],
"sun": []
}
},
"active": { "type": "boolean", "default": true }
}
}
}
}
},
"responses": {
"200": {
"description": "Booking link created",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": ["token", "settings"],
"properties": {
"token": { "type": "string" },
"public_url": { "type": "string", "format": "uri", "example": "https://app.example.com/booking/abc123" },
"settings": {
"type": "object",
"properties": {
"duration_minutes": { "type": "integer" },
"buffer_minutes": { "type": "integer" },
"timezone": { "type": "string" },
"working_hours": { "type": "object" },
"active": { "type": "boolean" }
}
}
}
}
}
}
},
"400": { "description": "Validation error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
"401": { "description": "Not authenticated", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
"403": { "description": "Only owner can create booking links", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
"404": { "description": "Calendar not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
}
}
},
"/booking/{token}/availability": {
"get": {
"tags": ["Booking"],
"summary": "Get public booking availability",
"description": "Returns available time slots for a public booking link within a date range. No authentication required. Computes available slots by subtracting busy blocks and applying buffer time to the working hour windows.",
"operationId": "getBookingAvailability",
"security": [],
"parameters": [
{
"name": "token",
"in": "path",
"required": true,
"schema": { "type": "string" },
"description": "Booking link token"
},
{ "name": "start", "in": "query", "required": true, "schema": { "type": "string", "format": "date-time" }, "description": "Range start (RFC3339)" },
{ "name": "end", "in": "query", "required": true, "schema": { "type": "string", "format": "date-time" }, "description": "Range end (RFC3339)" }
],
"responses": {
"200": {
"description": "Available booking slots",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": ["token", "timezone", "duration_minutes", "slots"],
"properties": {
"token": { "type": "string" },
"timezone": { "type": "string" },
"duration_minutes": { "type": "integer" },
"slots": {
"type": "array",
"items": { "$ref": "#/components/schemas/TimeSlot" }
}
}
}
}
}
},
"400": { "description": "Validation error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
"404": { "description": "Booking link not found or inactive", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
}
}
},
"/booking/{token}/reserve": {
"post": {
"tags": ["Booking"],
"summary": "Reserve a booking slot",
"description": "Reserves a time slot on a public booking link. Creates an event on the calendar. Uses a database transaction with row locking to prevent double-booking. No authentication required.",
"operationId": "reserveBookingSlot",
"security": [],
"parameters": [
{
"name": "token",
"in": "path",
"required": true,
"schema": { "type": "string" },
"description": "Booking link token"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"required": ["name", "email", "slot_start", "slot_end"],
"properties": {
"name": { "type": "string", "example": "Visitor Name" },
"email": { "type": "string", "format": "email", "example": "visitor@example.com" },
"slot_start": { "type": "string", "format": "date-time" },
"slot_end": { "type": "string", "format": "date-time" },
"notes": { "type": "string", "example": "Looking forward to the meeting" }
}
}
}
}
},
"responses": {
"200": {
"description": "Booking confirmed",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": ["ok", "event"],
"properties": {
"ok": { "type": "boolean", "example": true },
"event": { "$ref": "#/components/schemas/Event" }
}
}
}
}
},
"400": { "description": "Validation error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
"404": { "description": "Booking link not found or inactive", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
"409": { "description": "Slot no longer available (conflict)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
}
}
}
}
}