{
    "openapi": "3.1.0",
    "info": {
        "title": "Boolet Ltd Support API",
        "version": "1.0.0",
        "description": "Raise and follow support tickets from your own system. Read the guide at https://portal.boolet.co.uk/developers."
    },
    "servers": [
        {
            "url": "https://portal.boolet.co.uk/api/v1"
        }
    ],
    "security": [
        {
            "bearerAuth": []
        }
    ],
    "paths": {
        "/me": {
            "get": {
                "summary": "Check your key",
                "description": "Who the key belongs to, what it may do, and (for Support API keys) your plan and support hours balance.",
                "operationId": "me",
                "parameters": [],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "example": {
                                    "data": {
                                        "owner": "MediTech Ltd",
                                        "key_name": "Production",
                                        "abilities": [
                                            "tickets:read",
                                            "tickets:write"
                                        ],
                                        "expires_at": null,
                                        "support": {
                                            "api_enabled": true,
                                            "plan": "Growth",
                                            "hours_balance": 4.5
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/tickets": {
            "post": {
                "summary": "Create a ticket",
                "description": "Raise a ticket for our developers. Send an Idempotency-Key header, or your own external_reference, so a retry returns the ticket already created (200) instead of creating another. Needs the tickets:write ability.",
                "operationId": "tickets_store",
                "parameters": [
                    {
                        "in": "header",
                        "name": "Idempotency-Key",
                        "required": false,
                        "description": "Any unique value per ticket, up to 100 characters.",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "201": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "example": {
                                    "data": {
                                        "id": "TICKET142",
                                        "external_reference": "EXT-88412",
                                        "title": "Appointments not syncing to calendar",
                                        "description": "Since this morning, online bookings do not appear in the clinic calendar.",
                                        "type": "bug",
                                        "priority": "high",
                                        "status": "open",
                                        "platform": "web",
                                        "page_url": "https://app.example.com/bookings",
                                        "source": "api",
                                        "external_account": {
                                            "id": "site-204",
                                            "name": "Riverside Medical Centre"
                                        },
                                        "reporter": {
                                            "name": "Jane Doe",
                                            "email": "jane@riverside.example"
                                        },
                                        "metadata": {
                                            "app_version": "4.12.1",
                                            "environment": "production"
                                        },
                                        "assignee": null,
                                        "attachments": [],
                                        "time": {
                                            "logged_minutes": 0,
                                            "billable_minutes": 0
                                        },
                                        "created_at": "2026-11-04T09:12:40+00:00",
                                        "updated_at": "2026-11-04T09:12:40+00:00",
                                        "closed_at": null
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "example": {
                                "title": "Appointments not syncing to calendar",
                                "description": "Since this morning, online bookings do not appear in the clinic calendar.",
                                "type": "bug",
                                "priority": "high",
                                "platform": "web",
                                "page_url": "https://app.example.com/bookings",
                                "external_reference": "EXT-88412",
                                "external_account": {
                                    "id": "site-204",
                                    "name": "Riverside Medical Centre"
                                },
                                "reporter": {
                                    "name": "Jane Doe",
                                    "email": "jane@riverside.example"
                                },
                                "metadata": {
                                    "app_version": "4.12.1",
                                    "environment": "production"
                                }
                            }
                        }
                    }
                }
            },
            "get": {
                "summary": "List tickets",
                "description": "Your tickets, newest first, 25 a page (up to 100). Follow links.next, or pass meta.next_cursor as cursor, for the next page. Needs the tickets:read ability.",
                "operationId": "tickets_index",
                "parameters": [
                    {
                        "in": "query",
                        "name": "status",
                        "required": false,
                        "description": "One or more statuses, comma-separated: open, in_progress, client_responded, waiting_for_information, answered, closed.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "in": "query",
                        "name": "external_account_id",
                        "required": false,
                        "description": "Only tickets for one of your customers.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "in": "query",
                        "name": "updated_since",
                        "required": false,
                        "description": "Only tickets changed since this time (ISO 8601). Handy for catching up after downtime.",
                        "schema": {
                            "type": "string",
                            "format": "date-time"
                        }
                    },
                    {
                        "in": "query",
                        "name": "per_page",
                        "required": false,
                        "description": "1 to 100. Default 25.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "in": "query",
                        "name": "cursor",
                        "required": false,
                        "description": "From meta.next_cursor of the previous page.",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "example": {
                                    "data": [
                                        {
                                            "id": "TICKET142",
                                            "external_reference": "EXT-88412",
                                            "title": "Appointments not syncing to calendar",
                                            "description": "Since this morning, online bookings do not appear in the clinic calendar.",
                                            "type": "bug",
                                            "priority": "high",
                                            "status": "open",
                                            "platform": "web",
                                            "page_url": "https://app.example.com/bookings",
                                            "source": "api",
                                            "external_account": {
                                                "id": "site-204",
                                                "name": "Riverside Medical Centre"
                                            },
                                            "reporter": {
                                                "name": "Jane Doe",
                                                "email": "jane@riverside.example"
                                            },
                                            "metadata": {
                                                "app_version": "4.12.1",
                                                "environment": "production"
                                            },
                                            "assignee": null,
                                            "attachments": [],
                                            "time": {
                                                "logged_minutes": 0,
                                                "billable_minutes": 0
                                            },
                                            "created_at": "2026-11-04T09:12:40+00:00",
                                            "updated_at": "2026-11-04T09:12:40+00:00",
                                            "closed_at": null
                                        }
                                    ],
                                    "meta": {
                                        "per_page": 25,
                                        "next_cursor": null,
                                        "prev_cursor": null
                                    },
                                    "links": {
                                        "next": null,
                                        "prev": null
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/tickets/{ticket}": {
            "get": {
                "summary": "Get a ticket",
                "description": "One ticket, by our number (TICKET12) or by your reference (ext:EXT-88412). Needs the tickets:read ability.",
                "operationId": "tickets_show",
                "parameters": [
                    {
                        "in": "path",
                        "name": "ticket",
                        "required": true,
                        "description": "Our ticket number (TICKET12) or ext: and your reference (ext:EXT-88412).",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "example": {
                                    "data": {
                                        "id": "TICKET142",
                                        "external_reference": "EXT-88412",
                                        "title": "Appointments not syncing to calendar",
                                        "description": "Since this morning, online bookings do not appear in the clinic calendar.",
                                        "type": "bug",
                                        "priority": "high",
                                        "status": "open",
                                        "platform": "web",
                                        "page_url": "https://app.example.com/bookings",
                                        "source": "api",
                                        "external_account": {
                                            "id": "site-204",
                                            "name": "Riverside Medical Centre"
                                        },
                                        "reporter": {
                                            "name": "Jane Doe",
                                            "email": "jane@riverside.example"
                                        },
                                        "metadata": {
                                            "app_version": "4.12.1",
                                            "environment": "production"
                                        },
                                        "assignee": null,
                                        "attachments": [],
                                        "time": {
                                            "logged_minutes": 0,
                                            "billable_minutes": 0
                                        },
                                        "created_at": "2026-11-04T09:12:40+00:00",
                                        "updated_at": "2026-11-04T09:12:40+00:00",
                                        "closed_at": null
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            },
            "patch": {
                "summary": "Update a ticket",
                "description": "Change the priority, mark the ticket resolved (status closed) or reopen it (status open). Needs the tickets:write ability.",
                "operationId": "tickets_update",
                "parameters": [
                    {
                        "in": "path",
                        "name": "ticket",
                        "required": true,
                        "description": "Our ticket number (TICKET12) or ext: and your reference (ext:EXT-88412).",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "example": {
                                    "data": {
                                        "id": "TICKET142",
                                        "external_reference": "EXT-88412",
                                        "title": "Appointments not syncing to calendar",
                                        "description": "Since this morning, online bookings do not appear in the clinic calendar.",
                                        "type": "bug",
                                        "priority": "medium",
                                        "status": "closed",
                                        "platform": "web",
                                        "page_url": "https://app.example.com/bookings",
                                        "source": "api",
                                        "external_account": {
                                            "id": "site-204",
                                            "name": "Riverside Medical Centre"
                                        },
                                        "reporter": {
                                            "name": "Jane Doe",
                                            "email": "jane@riverside.example"
                                        },
                                        "metadata": {
                                            "app_version": "4.12.1",
                                            "environment": "production"
                                        },
                                        "assignee": null,
                                        "attachments": [],
                                        "time": {
                                            "logged_minutes": 0,
                                            "billable_minutes": 0
                                        },
                                        "created_at": "2026-11-04T09:12:40+00:00",
                                        "updated_at": "2026-11-04T09:12:40+00:00",
                                        "closed_at": null
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "example": {
                                "priority": "medium",
                                "status": "closed"
                            }
                        }
                    }
                }
            }
        },
        "/tickets/{ticket}/messages": {
            "get": {
                "summary": "List messages",
                "description": "The conversation on a ticket, oldest first. Our internal notes are never included. Needs the tickets:read ability.",
                "operationId": "tickets_messages_index",
                "parameters": [
                    {
                        "in": "path",
                        "name": "ticket",
                        "required": true,
                        "description": "Our ticket number (TICKET12) or ext: and your reference (ext:EXT-88412).",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "example": {
                                    "data": [
                                        {
                                            "id": 1001,
                                            "body": "Thanks, we have found the cause and are deploying a fix now.",
                                            "author": {
                                                "name": "Sam Patel",
                                                "type": "team"
                                            },
                                            "via": "portal",
                                            "attachments": [],
                                            "created_at": "2026-11-04T14:20:03+00:00"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            },
            "post": {
                "summary": "Reply to a ticket",
                "description": "Add a message from your side, written by someone in your system. The ticket moves to client_responded (a closed ticket reopens) and the assigned developer is told. Needs the tickets:write ability.",
                "operationId": "tickets_messages_store",
                "parameters": [
                    {
                        "in": "path",
                        "name": "ticket",
                        "required": true,
                        "description": "Our ticket number (TICKET12) or ext: and your reference (ext:EXT-88412).",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "201": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "example": {
                                    "data": {
                                        "id": 1002,
                                        "body": "It is still happening for bookings made on mobile.",
                                        "author": {
                                            "name": "Jane Doe",
                                            "type": "client"
                                        },
                                        "via": "api",
                                        "attachments": [],
                                        "created_at": "2026-11-04T14:20:03+00:00"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "example": {
                                "body": "It is still happening for bookings made on mobile.",
                                "author": {
                                    "name": "Jane Doe",
                                    "email": "jane@riverside.example"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/tickets/{ticket}/attachments": {
            "post": {
                "summary": "Attach files",
                "description": "Send screenshots or logs as multipart/form-data in files[]. Up to 5 files a request, 10 MB each: png, jpg, jpeg, gif, webp, pdf, txt, log, csv, zip, docx, xlsx, mp4, mov. Needs the tickets:write ability.",
                "operationId": "tickets_attachments_store",
                "parameters": [
                    {
                        "in": "path",
                        "name": "ticket",
                        "required": true,
                        "description": "Our ticket number (TICKET12) or ext: and your reference (ext:EXT-88412).",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "201": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "example": {
                                    "data": {
                                        "id": "TICKET142",
                                        "external_reference": "EXT-88412",
                                        "title": "Appointments not syncing to calendar",
                                        "description": "Since this morning, online bookings do not appear in the clinic calendar.",
                                        "type": "bug",
                                        "priority": "high",
                                        "status": "open",
                                        "platform": "web",
                                        "page_url": "https://app.example.com/bookings",
                                        "source": "api",
                                        "external_account": {
                                            "id": "site-204",
                                            "name": "Riverside Medical Centre"
                                        },
                                        "reporter": {
                                            "name": "Jane Doe",
                                            "email": "jane@riverside.example"
                                        },
                                        "metadata": {
                                            "app_version": "4.12.1",
                                            "environment": "production"
                                        },
                                        "assignee": null,
                                        "attachments": [
                                            {
                                                "name": "screenshot.png",
                                                "size": 182044,
                                                "mime": "image/png"
                                            }
                                        ],
                                        "time": {
                                            "logged_minutes": 0,
                                            "billable_minutes": 0
                                        },
                                        "created_at": "2026-11-04T09:12:40+00:00",
                                        "updated_at": "2026-11-04T09:12:40+00:00",
                                        "closed_at": null
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "requestBody": {
                    "required": true,
                    "content": {
                        "multipart/form-data": {
                            "example": {
                                "files[]": "(binary)"
                            }
                        }
                    }
                }
            }
        },
        "/tickets/{ticket}/time-entries": {
            "get": {
                "summary": "List time logged",
                "description": "Time our developers logged on the ticket, and whether it came off your support hours (billable). Needs the tickets:read ability.",
                "operationId": "tickets_time-entries_index",
                "parameters": [
                    {
                        "in": "path",
                        "name": "ticket",
                        "required": true,
                        "description": "Our ticket number (TICKET12) or ext: and your reference (ext:EXT-88412).",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "example": {
                                    "data": [
                                        {
                                            "id": 77,
                                            "worked_on": "2026-11-04",
                                            "minutes": 45,
                                            "billable": true,
                                            "description": "Fixed the calendar sync job",
                                            "logged_by": "Sam Patel",
                                            "created_at": "2026-11-04T15:02:11+00:00"
                                        }
                                    ],
                                    "meta": {
                                        "logged_minutes": 45,
                                        "billable_minutes": 45
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        }
    },
    "components": {
        "securitySchemes": {
            "bearerAuth": {
                "type": "http",
                "scheme": "bearer",
                "description": "Your API key, e.g. 12|blt_…"
            }
        },
        "responses": {
            "Unauthenticated": {
                "description": "Missing, wrong, revoked or expired key",
                "content": {
                    "application/json": {
                        "example": {
                            "error": {
                                "code": "unauthenticated",
                                "message": "Missing, invalid, revoked or expired API key."
                            }
                        }
                    }
                }
            },
            "Forbidden": {
                "description": "The key may not do this",
                "content": {
                    "application/json": {
                        "example": {
                            "error": {
                                "code": "forbidden",
                                "message": "This API key does not have permission for this action."
                            }
                        }
                    }
                }
            },
            "ValidationFailed": {
                "description": "The request is not valid",
                "content": {
                    "application/json": {
                        "example": {
                            "error": {
                                "code": "validation_failed",
                                "message": "The title field is required.",
                                "fields": {
                                    "title": [
                                        "The title field is required."
                                    ]
                                }
                            }
                        }
                    }
                }
            },
            "RateLimited": {
                "description": "Too many requests; see Retry-After",
                "content": {
                    "application/json": {
                        "example": {
                            "error": {
                                "code": "rate_limited",
                                "message": "Too many requests. Slow down and retry after the time in the Retry-After header."
                            }
                        }
                    }
                }
            }
        }
    }
}