{
  "components": {
    "schemas": {
      "CredentialRotated": {
        "additionalProperties": false,
        "properties": {
          "api_key": {
            "type": "string"
          },
          "old_valid_until": {
            "format": "date-time",
            "type": "string"
          },
          "signing_secret": {
            "type": "string"
          }
        },
        "required": [
          "old_valid_until"
        ],
        "type": "object"
      },
      "DailyQueue": {
        "additionalProperties": false,
        "properties": {
          "code": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "sessions": {
            "items": {
              "$ref": "#/components/schemas/DailySession"
            },
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "code",
          "name",
          "sessions"
        ],
        "type": "object"
      },
      "DailyReport": {
        "additionalProperties": false,
        "properties": {
          "business_date": {
            "type": "string"
          },
          "facility": {
            "type": "string"
          },
          "final": {
            "type": "boolean"
          },
          "queues": {
            "items": {
              "$ref": "#/components/schemas/DailyQueue"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "totals": {
            "$ref": "#/components/schemas/DailyTotals"
          }
        },
        "required": [
          "facility",
          "business_date",
          "final",
          "totals",
          "queues"
        ],
        "type": "object"
      },
      "DailySession": {
        "additionalProperties": false,
        "properties": {
          "booked": {
            "format": "int64",
            "type": "integer"
          },
          "completed": {
            "format": "int64",
            "type": "integer"
          },
          "ended_at": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "median_wait_seconds": {
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "name": {
            "type": "string"
          },
          "no_shows": {
            "format": "int64",
            "type": "integer"
          },
          "opened_at": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "name",
          "opened_at",
          "ended_at",
          "booked",
          "completed",
          "no_shows",
          "median_wait_seconds"
        ],
        "type": "object"
      },
      "DailyTotals": {
        "additionalProperties": false,
        "properties": {
          "booked": {
            "format": "int64",
            "type": "integer"
          },
          "cancelled": {
            "format": "int64",
            "type": "integer"
          },
          "completed": {
            "format": "int64",
            "type": "integer"
          },
          "median_consult_seconds": {
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "median_wait_seconds": {
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "no_shows": {
            "format": "int64",
            "type": "integer"
          },
          "remote": {
            "format": "int64",
            "type": "integer"
          },
          "walk_ins": {
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "booked",
          "completed",
          "no_shows",
          "cancelled",
          "walk_ins",
          "remote",
          "median_wait_seconds",
          "median_consult_seconds"
        ],
        "type": "object"
      },
      "Error": {
        "additionalProperties": false,
        "properties": {
          "code": {
            "description": "Stable registry code, e.g. V007",
            "type": "string"
          },
          "field": {
            "description": "Set only on validation failures",
            "type": [
              "string",
              "null"
            ]
          },
          "message": {
            "description": "English fallback, safe to show",
            "type": "string"
          }
        },
        "required": [
          "code",
          "message",
          "field"
        ],
        "type": "object"
      },
      "Integration": {
        "additionalProperties": false,
        "properties": {
          "api_key_hint": {
            "type": "string"
          },
          "api_key_old_valid_until": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "format": "date-time",
            "type": "string"
          },
          "created_by": {
            "type": "string"
          },
          "deliveries_today": {
            "format": "int64",
            "type": "integer"
          },
          "events": {
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "failing_since": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "failures_today": {
            "format": "int64",
            "type": "integer"
          },
          "id": {
            "type": "string"
          },
          "last_used_at": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "type": "string"
          },
          "paused_at": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "signing_secret_hint": {
            "type": "string"
          },
          "signing_secret_old_valid_until": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "state": {
            "enum": [
              "active",
              "paused"
            ],
            "type": "string"
          },
          "url": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "url",
          "events",
          "state",
          "api_key_hint",
          "signing_secret_hint",
          "api_key_old_valid_until",
          "signing_secret_old_valid_until",
          "last_used_at",
          "paused_at",
          "failing_since",
          "created_at",
          "created_by",
          "deliveries_today",
          "failures_today"
        ],
        "type": "object"
      },
      "IntegrationCreated": {
        "additionalProperties": false,
        "properties": {
          "api_key": {
            "type": "string"
          },
          "api_key_hint": {
            "type": "string"
          },
          "api_key_old_valid_until": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "format": "date-time",
            "type": "string"
          },
          "created_by": {
            "type": "string"
          },
          "deliveries_today": {
            "format": "int64",
            "type": "integer"
          },
          "events": {
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "failing_since": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "failures_today": {
            "format": "int64",
            "type": "integer"
          },
          "id": {
            "type": "string"
          },
          "last_used_at": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "type": "string"
          },
          "paused_at": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "signing_secret": {
            "type": "string"
          },
          "signing_secret_hint": {
            "type": "string"
          },
          "signing_secret_old_valid_until": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "state": {
            "enum": [
              "active",
              "paused"
            ],
            "type": "string"
          },
          "url": {
            "type": "string"
          }
        },
        "required": [
          "api_key",
          "signing_secret",
          "id",
          "name",
          "url",
          "events",
          "state",
          "api_key_hint",
          "signing_secret_hint",
          "api_key_old_valid_until",
          "signing_secret_old_valid_until",
          "last_used_at",
          "paused_at",
          "failing_since",
          "created_at",
          "created_by",
          "deliveries_today",
          "failures_today"
        ],
        "type": "object"
      },
      "IntegrationDeliveries": {
        "additionalProperties": false,
        "properties": {
          "items": {
            "items": {
              "$ref": "#/components/schemas/IntegrationDelivery"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "next": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "items",
          "next"
        ],
        "type": "object"
      },
      "IntegrationDelivery": {
        "additionalProperties": false,
        "properties": {
          "attempted_at": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "attempts": {
            "format": "int64",
            "type": "integer"
          },
          "created_at": {
            "format": "date-time",
            "type": "string"
          },
          "duration_ms": {
            "format": "int32",
            "type": [
              "integer",
              "null"
            ]
          },
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "event": {
            "type": "string"
          },
          "id": {
            "type": "string"
          },
          "next_attempt_at": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "sequence": {
            "format": "int64",
            "type": "integer"
          },
          "state": {
            "enum": [
              "pending",
              "delivered",
              "failed",
              "dead"
            ],
            "type": "string"
          },
          "status": {
            "format": "int32",
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "event",
          "sequence",
          "state",
          "status",
          "error",
          "attempts",
          "duration_ms",
          "attempted_at",
          "next_attempt_at",
          "created_at"
        ],
        "type": "object"
      },
      "IntegrationInput": {
        "additionalProperties": false,
        "properties": {
          "events": {
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "name": {
            "type": "string"
          },
          "url": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "IntegrationList": {
        "additionalProperties": false,
        "properties": {
          "events": {
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "items": {
            "items": {
              "$ref": "#/components/schemas/Integration"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "limit": {
            "format": "int64",
            "type": "integer"
          },
          "locked": {
            "type": "boolean"
          }
        },
        "required": [
          "items",
          "events",
          "limit",
          "locked"
        ],
        "type": "object"
      },
      "Integrations-rotateRequest": {
        "additionalProperties": false,
        "properties": {
          "what": {
            "enum": [
              "api_key",
              "signing_secret"
            ],
            "type": "string"
          }
        },
        "required": [
          "what"
        ],
        "type": "object"
      },
      "SnapshotQueue": {
        "additionalProperties": false,
        "properties": {
          "code": {
            "type": "string"
          },
          "current_number": {
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "eta_minutes": {
            "items": {
              "format": "int64",
              "type": "integer"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "name": {
            "type": "string"
          },
          "state": {
            "type": "string"
          },
          "waiting": {
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "code",
          "name",
          "state",
          "current_number",
          "waiting",
          "eta_minutes"
        ],
        "type": "object"
      },
      "SnapshotSession": {
        "additionalProperties": false,
        "properties": {
          "booked": {
            "format": "int64",
            "type": "integer"
          },
          "business_date": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "opened_at": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "name",
          "business_date",
          "opened_at",
          "booked"
        ],
        "type": "object"
      },
      "SnapshotToken": {
        "additionalProperties": false,
        "properties": {
          "arrived": {
            "type": "boolean"
          },
          "number": {
            "format": "int64",
            "type": "integer"
          },
          "patient_name": {
            "type": "string"
          },
          "position": {
            "format": "int64",
            "type": "integer"
          },
          "state": {
            "type": "string"
          },
          "token_code": {
            "type": "string"
          }
        },
        "required": [
          "token_code",
          "number",
          "patient_name",
          "state",
          "position",
          "arrived"
        ],
        "type": "object"
      },
      "V1Queue": {
        "additionalProperties": false,
        "properties": {
          "code": {
            "type": "string"
          },
          "kind": {
            "type": "string"
          },
          "mode": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "state": {
            "enum": [
              "open",
              "paused",
              "closed"
            ],
            "type": "string"
          }
        },
        "required": [
          "code",
          "name",
          "kind",
          "mode",
          "state"
        ],
        "type": "object"
      },
      "V1QueueList": {
        "additionalProperties": false,
        "properties": {
          "items": {
            "items": {
              "$ref": "#/components/schemas/V1Queue"
            },
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "items"
        ],
        "type": "object"
      },
      "V1Snapshot": {
        "additionalProperties": false,
        "properties": {
          "as_of": {
            "format": "date-time",
            "type": "string"
          },
          "queue": {
            "$ref": "#/components/schemas/SnapshotQueue"
          },
          "sequence": {
            "format": "int64",
            "type": "integer"
          },
          "session": {
            "$ref": "#/components/schemas/SnapshotSession"
          },
          "tokens": {
            "items": {
              "$ref": "#/components/schemas/SnapshotToken"
            },
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "queue",
          "session",
          "tokens",
          "as_of",
          "sequence"
        ],
        "type": "object"
      },
      "V1Visit": {
        "additionalProperties": false,
        "properties": {
          "arrived_at": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "booked_at": {
            "format": "date-time",
            "type": "string"
          },
          "booked_for": {
            "type": [
              "string",
              "null"
            ]
          },
          "business_date": {
            "type": "string"
          },
          "called_at": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "completed_at": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "consult_seconds": {
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "mobile": {
            "type": [
              "string",
              "null"
            ]
          },
          "number": {
            "format": "int64",
            "type": "integer"
          },
          "patient_age": {
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "patient_name": {
            "type": "string"
          },
          "queue": {
            "type": "string"
          },
          "session": {
            "type": "string"
          },
          "source": {
            "type": "string"
          },
          "state": {
            "type": "string"
          },
          "token_code": {
            "type": "string"
          }
        },
        "required": [
          "token_code",
          "number",
          "patient_name",
          "patient_age",
          "booked_for",
          "mobile",
          "queue",
          "session",
          "business_date",
          "state",
          "source",
          "booked_at",
          "arrived_at",
          "called_at",
          "completed_at",
          "consult_seconds"
        ],
        "type": "object"
      },
      "V1Visits": {
        "additionalProperties": false,
        "properties": {
          "items": {
            "items": {
              "$ref": "#/components/schemas/V1Visit"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "next": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "items",
          "next"
        ],
        "type": "object"
      },
      "WebhookEvent": {
        "additionalProperties": false,
        "properties": {
          "data": {
            "additionalProperties": {},
            "type": "object"
          },
          "event": {
            "type": "string"
          },
          "facility": {
            "type": "string"
          },
          "occurred_at": {
            "type": "string"
          },
          "sequence": {
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "event",
          "sequence",
          "occurred_at",
          "facility",
          "data"
        ],
        "type": "object"
      }
    },
    "securitySchemes": {
      "api_key": {
        "description": "The integration's API key, dk_live_…: shown once when the integration is created, rotatable with a 24-hour grace window",
        "scheme": "bearer",
        "type": "http"
      },
      "session": {
        "description": "Opaque session token; Authorization: Bearer from the app",
        "in": "cookie",
        "name": "ds",
        "type": "apiKey"
      }
    }
  },
  "info": {
    "description": "A facility can let another system **listen to its queue**. Docly pushes events; nothing outside can write. There is no endpoint that creates a token, calls a patient or changes a queue, and that is a standing position rather than a first-version limit.\n\n**Webhooks are a convenience; the read API is the record.** A delivery to an unreachable endpoint is gone — not queued, not replayed — and the integrator reconciles from the read API instead.\n\n## Built for agents\n\nThe specification is published at a stable address, [`developers.docly.in/openapi.json`](/openapi.json), with a machine-readable summary at [`/llms.txt`](/llms.txt) and this page as plain text at [`/index.md`](/index.md). Paste this into whatever assistant you use:\n\n```text\nIntegrate Docly webhooks using the spec at developers.docly.in/openapi.json. Verify each delivery with HMAC-SHA256 over timestamp.body using the signing secret, and reject anything older than five minutes. Order events by sequence, never by arrival — retries mean deliveries can arrive out of order.\n```\n\n## Authentication\n\nSetting up an integration returns **two secrets, shown once**: an API key the other system uses when it reads from Docly, and a signing secret it uses to verify that a delivery genuinely came from Docly. Two secrets because they do opposite jobs: the key travels on every request, the signing secret is never transmitted at all. Both are hashed at rest and shown exactly once.\n\nThe read API is versioned at `/v1`, because this is the one surface that cannot change under someone. Read-only: every endpoint is a `GET`.\n\n```http\nAuthorization: Bearer dk_live_7f3a9c2b…\n```\n\nEither credential can be rotated on its own, with a grace period where the old and new both work, so deliveries in flight do not fail and a leaked key does not force the signing secret to change with it.\n\n## Verifying a delivery\n\n```http\nPOST https://their-endpoint.example.com/docly\nX-Docly-Event:     token.called\nX-Docly-Delivery:  dlv_8f3a…\nX-Docly-Sequence:  4821\nX-Docly-Signature: t=1696512000,v1=5d41402abc4b2a76b9719d911017c592\n```\n\nHMAC-SHA256 over `t.body` with the signing secret. **Reject anything where `t` is more than five minutes old**, or a captured delivery can be replayed later.\n\n**No delivery ever carries a patient's name, number or age** — only the token's code and number. Nothing about money is deliverable at all.\n\n## Ordering by sequence\n\n**Order is not guaranteed.** Retries mean a delivery can arrive after a later one, so consumers order on `sequence`, never on arrival. Assuming otherwise is how a system shows a patient called before they were created.\n\nEvery event carries a sequence number and a timestamp. A snapshot carries the same `sequence`, so an integrator can tell whether a snapshot is newer than the last event it received.\n\nWhen an endpoint is down, Docly retries with exponential backoff for about 24 hours, then dead-letters. A subscription that keeps failing pauses itself and emails the facility rather than retrying into silence.\n\n## Rate limits\n\nEach API key may make 120 requests a minute to the read API. A request over its limit is answered `429` with `Retry-After`.\n\n## Errors\n\nOne shape everywhere. `field` is set only on validation failures.\n\n```json\n{ \"code\": \"V007\", \"message\": \"Name is required\", \"field\": \"name\" }\n```\n\n`404` means not found **or not yours** — the two are indistinguishable on purpose, so an id cannot be probed for existence.\n",
    "title": "Docly API",
    "version": "0.1.0"
  },
  "openapi": "3.1.0",
  "paths": {
    "/integrations": {
      "get": {
        "description": "Administrators only. Neither secret is ever shown again: only its first characters.",
        "operationId": "integrations-list",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IntegrationList"
                }
              }
            },
            "description": "OK"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Error"
          }
        },
        "security": [
          {
            "session": []
          }
        ],
        "summary": "The facility's integrations, with the event catalogue",
        "tags": [
          "public",
          "Integrations"
        ]
      },
      "post": {
        "description": "Returns two secrets, shown once: an API key for reading from Docly, and a signing secret for verifying deliveries. Pro only (403 P202).",
        "operationId": "integrations-create",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IntegrationInput"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IntegrationCreated"
                }
              }
            },
            "description": "Created"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Error"
          }
        },
        "security": [
          {
            "session": []
          }
        ],
        "summary": "Subscribe a system to the facility's events",
        "tags": [
          "public",
          "Integrations"
        ]
      }
    },
    "/integrations/{id}": {
      "delete": {
        "operationId": "integrations-delete",
        "parameters": [
          {
            "description": "The integration, int_…",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "The integration, int_…",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Error"
          }
        },
        "security": [
          {
            "session": []
          }
        ],
        "summary": "Delete an integration: both credentials stop at once",
        "tags": [
          "public",
          "Integrations"
        ]
      },
      "patch": {
        "operationId": "integrations-update",
        "parameters": [
          {
            "description": "The integration, int_…",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "The integration, int_…",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IntegrationInput"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Integration"
                }
              }
            },
            "description": "OK"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Error"
          }
        },
        "security": [
          {
            "session": []
          }
        ],
        "summary": "Change an integration's name, address or events",
        "tags": [
          "public",
          "Integrations"
        ]
      }
    },
    "/integrations/{id}/deliveries": {
      "get": {
        "description": "Delivered rows are kept 7 days, failed ones 30.",
        "operationId": "integrations-deliveries",
        "parameters": [
          {
            "description": "The integration, int_…",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "The integration, int_…",
              "type": "string"
            }
          },
          {
            "description": "failed: only failed and dead-lettered deliveries",
            "explode": false,
            "in": "query",
            "name": "state",
            "schema": {
              "description": "failed: only failed and dead-lettered deliveries",
              "enum": [
                "failed",
                ""
              ],
              "type": "string"
            }
          },
          {
            "explode": false,
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IntegrationDeliveries"
                }
              }
            },
            "description": "OK"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Error"
          }
        },
        "security": [
          {
            "session": []
          }
        ],
        "summary": "Recent deliveries, newest first",
        "tags": [
          "public",
          "Integrations"
        ]
      }
    },
    "/integrations/{id}/deliveries/{delivery}/replay": {
      "post": {
        "description": "The body is rendered from the event log at send time, with its original sequence.",
        "operationId": "integrations-replay",
        "parameters": [
          {
            "description": "The integration, int_…",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "The integration, int_…",
              "type": "string"
            }
          },
          {
            "description": "The delivery, dlv_…",
            "in": "path",
            "name": "delivery",
            "required": true,
            "schema": {
              "description": "The delivery, dlv_…",
              "type": "string"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Error"
          }
        },
        "security": [
          {
            "session": []
          }
        ],
        "summary": "Send a delivery again, now",
        "tags": [
          "public",
          "Integrations"
        ]
      }
    },
    "/integrations/{id}/resume": {
      "post": {
        "description": "An integration pauses itself when every delivery has failed for 6 hours, or 20 attempts in a row. What it missed is read back from the read API.",
        "operationId": "integrations-resume",
        "parameters": [
          {
            "description": "The integration, int_…",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "The integration, int_…",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Error"
          }
        },
        "security": [
          {
            "session": []
          }
        ],
        "summary": "Resume a paused integration",
        "tags": [
          "public",
          "Integrations"
        ]
      }
    },
    "/integrations/{id}/rotate": {
      "post": {
        "operationId": "integrations-rotate",
        "parameters": [
          {
            "description": "The integration, int_…",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "The integration, int_…",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Integrations-rotateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CredentialRotated"
                }
              }
            },
            "description": "OK"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Error"
          }
        },
        "security": [
          {
            "session": []
          }
        ],
        "summary": "Rotate one credential; the old one keeps working for 24 hours",
        "tags": [
          "public",
          "Integrations"
        ]
      }
    },
    "/v1/queues": {
      "get": {
        "operationId": "v1-queues",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/V1QueueList"
                }
              }
            },
            "description": "OK"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Error"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ],
        "summary": "The facility's queues",
        "tags": [
          "public",
          "Read API"
        ]
      }
    },
    "/v1/queues/{code}/snapshot": {
      "get": {
        "description": "`sequence` is the counter the webhooks carry, so an integrator can tell whether a snapshot is newer than the last event it received.",
        "operationId": "v1-snapshot",
        "parameters": [
          {
            "description": "The queue's code, e.g. p4k",
            "in": "path",
            "name": "code",
            "required": true,
            "schema": {
              "description": "The queue's code, e.g. p4k",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/V1Snapshot"
                }
              }
            },
            "description": "OK"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Error"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ],
        "summary": "A queue's live state",
        "tags": [
          "public",
          "Read API"
        ]
      }
    },
    "/v1/reports/daily": {
      "get": {
        "description": "`final: false` means a session was still running when this was computed; poll again after close.",
        "operationId": "v1-daily",
        "parameters": [
          {
            "description": "YYYY-MM-DD; today when omitted",
            "explode": false,
            "in": "query",
            "name": "date",
            "schema": {
              "description": "YYYY-MM-DD; today when omitted",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DailyReport"
                }
              }
            },
            "description": "OK"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Error"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ],
        "summary": "The day's consolidated summary",
        "tags": [
          "public",
          "Read API"
        ]
      }
    },
    "/v1/visits": {
      "get": {
        "description": "Where anything a missed webhook would have carried is recovered. Oldest first; follow `next` until it is null. Up to 31 days a request.",
        "operationId": "v1-visits",
        "parameters": [
          {
            "description": "YYYY-MM-DD",
            "explode": false,
            "in": "query",
            "name": "from",
            "schema": {
              "description": "YYYY-MM-DD",
              "type": "string"
            }
          },
          {
            "description": "YYYY-MM-DD",
            "explode": false,
            "in": "query",
            "name": "to",
            "schema": {
              "description": "YYYY-MM-DD",
              "type": "string"
            }
          },
          {
            "explode": false,
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/V1Visits"
                }
              }
            },
            "description": "OK"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Error"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ],
        "summary": "Visits: the token-level record",
        "tags": [
          "public",
          "Read API"
        ]
      }
    }
  },
  "servers": [
    {
      "url": "https://api.docly.in"
    }
  ],
  "tags": [
    {
      "description": "Marks a route for this reference",
      "name": "public",
      "x-scalar-ignore": true
    },
    {
      "description": "Versioned at /v1. Read-only: every endpoint is a GET, with the integration's API key.",
      "name": "Read API"
    },
    {
      "description": "The facility's own subscriptions, managed in Docly Desk by an administrator.",
      "name": "Integrations"
    }
  ],
  "webhooks": {
    "day.closed": {
      "post": {
        "description": "Headers: `X-Docly-Event`, `X-Docly-Delivery`, `X-Docly-Sequence`, `X-Docly-Signature: t=…,v1=…`. Verify the signature, then order by `sequence`, never by arrival.",
        "operationId": "webhook-day.closed",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the delivery; anything else is retried"
          }
        },
        "summary": "The day's summary, once its last session ends: the read API's daily report"
      }
    },
    "facility.closed": {
      "post": {
        "description": "Headers: `X-Docly-Event`, `X-Docly-Delivery`, `X-Docly-Sequence`, `X-Docly-Signature: t=…,v1=…`. Verify the signature, then order by `sequence`, never by arrival.",
        "operationId": "webhook-facility.closed",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the delivery; anything else is retried"
          }
        },
        "summary": "The facility, a queue or a doctor closed for today"
      }
    },
    "facility.reopened": {
      "post": {
        "description": "Headers: `X-Docly-Event`, `X-Docly-Delivery`, `X-Docly-Sequence`, `X-Docly-Signature: t=…,v1=…`. Verify the signature, then order by `sequence`, never by arrival.",
        "operationId": "webhook-facility.reopened",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the delivery; anything else is retried"
          }
        },
        "summary": "The facility, a queue or a doctor reopened"
      }
    },
    "practitioner.updated": {
      "post": {
        "description": "Headers: `X-Docly-Event`, `X-Docly-Delivery`, `X-Docly-Sequence`, `X-Docly-Signature: t=…,v1=…`. Verify the signature, then order by `sequence`, never by arrival.",
        "operationId": "webhook-practitioner.updated",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the delivery; anything else is retried"
          }
        },
        "summary": "A doctor was added, changed or removed"
      }
    },
    "queue.updated": {
      "post": {
        "description": "Headers: `X-Docly-Event`, `X-Docly-Delivery`, `X-Docly-Sequence`, `X-Docly-Signature: t=…,v1=…`. Verify the signature, then order by `sequence`, never by arrival.",
        "operationId": "webhook-queue.updated",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the delivery; anything else is retried"
          }
        },
        "summary": "A queue was added, changed or removed"
      }
    },
    "session.delayed": {
      "post": {
        "description": "Headers: `X-Docly-Event`, `X-Docly-Delivery`, `X-Docly-Sequence`, `X-Docly-Signature: t=…,v1=…`. Verify the signature, then order by `sequence`, never by arrival.",
        "operationId": "webhook-session.delayed",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the delivery; anything else is retried"
          }
        },
        "summary": "A session was delayed"
      }
    },
    "session.ended": {
      "post": {
        "description": "Headers: `X-Docly-Event`, `X-Docly-Delivery`, `X-Docly-Sequence`, `X-Docly-Signature: t=…,v1=…`. Verify the signature, then order by `sequence`, never by arrival.",
        "operationId": "webhook-session.ended",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the delivery; anything else is retried"
          }
        },
        "summary": "A session ended"
      }
    },
    "session.opened": {
      "post": {
        "description": "Headers: `X-Docly-Event`, `X-Docly-Delivery`, `X-Docly-Sequence`, `X-Docly-Signature: t=…,v1=…`. Verify the signature, then order by `sequence`, never by arrival.",
        "operationId": "webhook-session.opened",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the delivery; anything else is retried"
          }
        },
        "summary": "A session opened"
      }
    },
    "session.paused": {
      "post": {
        "description": "Headers: `X-Docly-Event`, `X-Docly-Delivery`, `X-Docly-Sequence`, `X-Docly-Signature: t=…,v1=…`. Verify the signature, then order by `sequence`, never by arrival.",
        "operationId": "webhook-session.paused",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the delivery; anything else is retried"
          }
        },
        "summary": "A session paused"
      }
    },
    "session.resumed": {
      "post": {
        "description": "Headers: `X-Docly-Event`, `X-Docly-Delivery`, `X-Docly-Sequence`, `X-Docly-Signature: t=…,v1=…`. Verify the signature, then order by `sequence`, never by arrival.",
        "operationId": "webhook-session.resumed",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the delivery; anything else is retried"
          }
        },
        "summary": "A session resumed"
      }
    },
    "token.called": {
      "post": {
        "description": "Headers: `X-Docly-Event`, `X-Docly-Delivery`, `X-Docly-Sequence`, `X-Docly-Signature: t=…,v1=…`. Verify the signature, then order by `sequence`, never by arrival.",
        "operationId": "webhook-token.called",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the delivery; anything else is retried"
          }
        },
        "summary": "A token was called"
      }
    },
    "token.cancelled": {
      "post": {
        "description": "Headers: `X-Docly-Event`, `X-Docly-Delivery`, `X-Docly-Sequence`, `X-Docly-Signature: t=…,v1=…`. Verify the signature, then order by `sequence`, never by arrival.",
        "operationId": "webhook-token.cancelled",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the delivery; anything else is retried"
          }
        },
        "summary": "A token was cancelled"
      }
    },
    "token.checked_in": {
      "post": {
        "description": "Headers: `X-Docly-Event`, `X-Docly-Delivery`, `X-Docly-Sequence`, `X-Docly-Signature: t=…,v1=…`. Verify the signature, then order by `sequence`, never by arrival.",
        "operationId": "webhook-token.checked_in",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the delivery; anything else is retried"
          }
        },
        "summary": "A patient checked in"
      }
    },
    "token.completed": {
      "post": {
        "description": "Headers: `X-Docly-Event`, `X-Docly-Delivery`, `X-Docly-Sequence`, `X-Docly-Signature: t=…,v1=…`. Verify the signature, then order by `sequence`, never by arrival.",
        "operationId": "webhook-token.completed",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the delivery; anything else is retried"
          }
        },
        "summary": "A token was completed"
      }
    },
    "token.created": {
      "post": {
        "description": "Headers: `X-Docly-Event`, `X-Docly-Delivery`, `X-Docly-Sequence`, `X-Docly-Signature: t=…,v1=…`. Verify the signature, then order by `sequence`, never by arrival.",
        "operationId": "webhook-token.created",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the delivery; anything else is retried"
          }
        },
        "summary": "A token was created"
      }
    },
    "token.no_show": {
      "post": {
        "description": "Headers: `X-Docly-Event`, `X-Docly-Delivery`, `X-Docly-Sequence`, `X-Docly-Signature: t=…,v1=…`. Verify the signature, then order by `sequence`, never by arrival.",
        "operationId": "webhook-token.no_show",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the delivery; anything else is retried"
          }
        },
        "summary": "A token was marked no-show, when its session ended"
      }
    },
    "token.recalled": {
      "post": {
        "description": "Headers: `X-Docly-Event`, `X-Docly-Delivery`, `X-Docly-Sequence`, `X-Docly-Signature: t=…,v1=…`. Verify the signature, then order by `sequence`, never by arrival.",
        "operationId": "webhook-token.recalled",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the delivery; anything else is retried"
          }
        },
        "summary": "A skipped token was recalled"
      }
    },
    "token.reordered": {
      "post": {
        "description": "Headers: `X-Docly-Event`, `X-Docly-Delivery`, `X-Docly-Sequence`, `X-Docly-Signature: t=…,v1=…`. Verify the signature, then order by `sequence`, never by arrival.",
        "operationId": "webhook-token.reordered",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the delivery; anything else is retried"
          }
        },
        "summary": "A token was moved in the queue"
      }
    },
    "token.skipped": {
      "post": {
        "description": "Headers: `X-Docly-Event`, `X-Docly-Delivery`, `X-Docly-Sequence`, `X-Docly-Signature: t=…,v1=…`. Verify the signature, then order by `sequence`, never by arrival.",
        "operationId": "webhook-token.skipped",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the delivery; anything else is retried"
          }
        },
        "summary": "A token was skipped"
      }
    }
  },
  "x-tagGroups": [
    {
      "name": "API reference",
      "tags": [
        "Read API",
        "Integrations"
      ]
    }
  ]
}
