{
  "openapi": "3.1.1",
  "info": {
    "title": "Bibleit REST API",
    "version": "1.0.0-alpha.15",
    "description": "Versioned REST surface with distinct organization service-token and personal bearer authentication. Organization routes require Authorization: Bearer svc_<secret>. Personal routes require existing finite bt_ API/CLI tokens; browser sessions are not accepted. Organization ownership, current status, scopes, processing rules and quotas apply. JSON bodies are bounded to 16 KiB except full presentation PUT, whose transport limit is 2,016,384 bytes and whose document limit is 2,000,000 encoded JSON bytes. Unknown body fields and unknown query fields are rejected. All responses are no-store. Rate limiting is node-local (120 requests/minute per authenticated principal plus existing peer/global admission). Duplicate-sensitive creation POSTs support optional Idempotency-Key with a 24-hour atomic replay contract. Unsupported REST operations reject the header with 422. Credential issuance/rotation and one-use downloads never replay secrets or streams. Service-token PATCH and rotation require strong configuration validators. Catalogue discovery is distinct from enabled libraries. Library PUT accepts an empty JSON object and never downloads content. Organization identity and active memberships require explicit organization.get and membership scopes. Live metadata PATCH edits the name. Live workspace PUT requires a source live.move token and a destination live.create token in X-Destination-Service-Token. Both mutations require the latest Live If-Match validator. Live scripture queue items have stable persisted IDs and zero-based positions. Queue writes use the shared Live If-Match validator. Ordered pagination rejects cursor use after a sequence change. Organization Live Studio GET/PUT use explicit live_studio.get/update scopes and strong settings ETags. PUT preserves the existing complete-settings validation and revision increments; saves notify Lives after commit. Organization presentations support paginated CRUD with strong document ETags. Presentation display PUT requires presentation.present, an explicit current saved revision and the Live If-Match validator; draft saves never publish. Raw binary asset uploads and portable ZIP imports are exceptions to JSON transport limits; require Content-Length, identity encoding and scoped authorization. Assets remain bearer-protected and support single byte ranges. Imports create a new unpublished presentation atomically. Presentation exports are asynchronous requester-private saved-revision jobs. POST their downloads collection with an empty JSON object to consume and stream a completed file once; GET never consumes exports. No ranges or automatic retries for export downloads. Personal /me and /accounts expose only the caller\u2019s personal identity/account. Personal library, scripture and Live routes bind that account explicitly. Personal tokens cannot authenticate organization management, presentations, Studio or workspace moves. Shared Live/control routes select credential type and enforce account ownership. Personal Live DELETE requires If-Match. Tokens are checked freshly after queue/lock waits and at final commits; existing personal scope inheritance and fifteen-minute rotation overlap remain unchanged. No delegated OAuth is implied. Registered public clients can now use Authorization Code with S256 PKCE and explicit browser consent for personal access. Metadata is /.well-known/oauth-authorization-server; OAuth protocol routes stay on https://bibleit.app/oauth, outside the API origin. Opaque oa_ access tokens last at most 15 minutes; optional offline_access enables single-use rotating refresh tokens within a fixed 30-day grant. Code or refresh replay revokes the grant. Existing bt_ and svc_ rules are unchanged. Versioned operator realtime delivery is GET /lives/{live_id}/events with optional opaque after cursor and wait=0..25 seconds. It returns current snapshots or a heartbeat, never a durable event log. Current bearer secret identity, scopes, account ownership and processing policy are checked before delayed delivery. Operator watches do not consume audience seats. The Fern reference is configured for the bibleit organization. SDK generation is maintained separately in bibleit-go. Browser API Explorer execution is disabled: the current API has no cross-origin browser contract or documentation credential proxy. Copy the HTTP examples into a backend or CLI client. The API origin serves the latest major version without a prefix (currently v1), while /v1 stays pinned. Production integrations should use the explicit major version. The existing https://bibleit.app/api/v1 URL remains supported. API-host resource links pin /v1, including links returned through the latest alias. Documentation is hosted at https://docs.bibleit.dev; https://api.bibleit.app/docs redirects there."
  },
  "servers": [
    {
      "url": "https://api.bibleit.app/v1",
      "description": "Pinned REST v1; recommended for integrations."
    },
    {
      "url": "https://api.bibleit.app",
      "description": "Latest major REST API; currently v1. This alias can change major versions."
    },
    {
      "url": "https://bibleit.app/api/v1",
      "description": "Existing REST v1 compatibility URL."
    }
  ],
  "security": [
    {
      "serviceToken": []
    }
  ],
  "paths": {
    "/organizations/{organization_id}/service-tokens": {
      "parameters": [
        {
          "name": "organization_id",
          "in": "path",
          "required": true,
          "description": "Immutable organization UUID bound to the service token.",
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "get": {
        "operationId": "listServiceTokens",
        "summary": "List service tokens",
        "description": "**Required scopes:** `token.get`.\n\nReturns metadata only, never secrets, in stable ascending ID order with keyset pagination. The active-token cap is 100; expired credentials may remain until cleanup.",
        "tags": [
          "Service tokens"
        ],
        "x-required-scopes": [
          "token.get"
        ],
        "responses": {
          "200": {
            "description": "Successful read",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                },
                "description": "Server-generated correlation ID."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceTokenList"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "after",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 128
            },
            "description": "Opaque cursor returned as next_cursor."
          }
        ],
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      },
      "post": {
        "operationId": "createServiceToken",
        "summary": "Create a service token",
        "description": "**Required scopes:** `token.create`.\n\nCreates an organization-owned service identity without a user or member seat. Requested scopes must be a subset of the issuer scopes. This operation is not idempotent; do not automatically retry an ambiguous response. Idempotency-Key is unsupported and rejected with 422 idempotency_not_supported. No secret-bearing response or one-use download stream is retained.\n\n**Response headers:**\n\n- `Location` (201): Relative URL of the created resource.",
        "tags": [
          "Service tokens"
        ],
        "x-required-scopes": [
          "token.create"
        ],
        "responses": {
          "201": {
            "description": "Created",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                },
                "description": "Server-generated correlation ID."
              },
              "Location": {
                "schema": {
                  "type": "string"
                },
                "description": "Relative URL of the created resource."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IssuedServiceToken"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateServiceToken"
              }
            }
          }
        },
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/organizations/{organization_id}/service-tokens/{credential_id}": {
      "parameters": [
        {
          "name": "organization_id",
          "in": "path",
          "required": true,
          "description": "Immutable organization UUID bound to the service token.",
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        },
        {
          "name": "credential_id",
          "in": "path",
          "required": true,
          "description": "",
          "schema": {
            "type": "string"
          }
        }
      ],
      "delete": {
        "operationId": "revokeServiceToken",
        "summary": "Revoke a service token",
        "description": "**Required scopes:** `token.delete`.\n\nImmediately removes the credential. A repeated deletion returns 404.",
        "tags": [
          "Service tokens"
        ],
        "x-required-scopes": [
          "token.delete"
        ],
        "responses": {
          "204": {
            "description": "Deleted",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                },
                "description": "Server-generated correlation ID."
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      },
      "get": {
        "operationId": "getServiceToken",
        "summary": "Read service-token configuration",
        "tags": [
          "Service tokens"
        ],
        "x-required-scopes": [
          "token.get"
        ],
        "description": "**Required scopes:** `token.get`.\n\nReturns configuration metadata only, never a secret or secret hash. Last-use timestamps are available in the list response instead, so authentication does not invalidate editing preconditions.\n\n**Response headers:**\n\n- `ETag` (200): Configuration validator. Excludes volatile last-use metadata, which is available in the token list only. Rotation invalidates this validator.",
        "responses": {
          "200": {
            "description": "Successful operation",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              },
              "ETag": {
                "schema": {
                  "type": "string",
                  "pattern": "^\"token-[a-f0-9]{64}\"$"
                },
                "description": "Configuration validator. Excludes volatile last-use metadata, which is available in the token list only. Rotation invalidates this validator."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceTokenConfiguration"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      },
      "patch": {
        "operationId": "updateServiceToken",
        "summary": "Edit service-token configuration",
        "tags": [
          "Service tokens"
        ],
        "x-required-scopes": [
          "token.create"
        ],
        "description": "**Required scopes:** `token.create`.\n\nSerializes with other organization credential changes. Preserves omitted fields and expiry. Resulting scopes must not exceed the current issuer scopes, including when scopes are omitted. Expired credentials can be explicitly renewed under the existing active-token cap. Editing does not issue a secret.\n\n**Response headers:**\n\n- `ETag` (200): Configuration validator. Excludes volatile last-use metadata, which is available in the token list only. Rotation invalidates this validator.",
        "responses": {
          "200": {
            "description": "Successful operation",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              },
              "ETag": {
                "schema": {
                  "type": "string",
                  "pattern": "^\"token-[a-f0-9]{64}\"$"
                },
                "description": "Configuration validator. Excludes volatile last-use metadata, which is available in the token list only. Rotation invalidates this validator."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceTokenConfiguration"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchServiceToken"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^\"token-[a-f0-9]{64}\"$"
            },
            "description": "Use the latest service-token configuration ETag unchanged. Missing: 428; stale: 412. Wildcards, lists and weak validators are rejected."
          }
        ],
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/organizations/{organization_id}/lives": {
      "parameters": [
        {
          "name": "organization_id",
          "in": "path",
          "required": true,
          "description": "Immutable organization UUID bound to the service token.",
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "get": {
        "operationId": "listLives",
        "summary": "List organization Lives",
        "description": "**Required scopes:** `live.list`.\n\nStable ascending ID order with keyset pagination. Concurrent additions may appear on later pages; this is not a frozen snapshot.",
        "tags": [
          "Lives"
        ],
        "x-required-scopes": [
          "live.list"
        ],
        "responses": {
          "200": {
            "description": "Successful read",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                },
                "description": "Server-generated correlation ID."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LiveList"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "after",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 128
            },
            "description": "Opaque cursor returned as next_cursor."
          }
        ],
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      },
      "post": {
        "operationId": "createLive",
        "summary": "Create an organization Live",
        "description": "**Required scopes:** `live.create`.\n\nUses organization quotas and current domain authorization. Optional Idempotency-Key atomically records a successful creation for 24-hour replay; current authorization is rechecked. Changed payload or original If-Match returns 409 idempotency_conflict. Replay precedes stale-version and quota evaluation.\n\n**Response headers:**\n\n- `Location` (201): Relative URL of the created resource.",
        "tags": [
          "Lives"
        ],
        "x-required-scopes": [
          "live.create"
        ],
        "responses": {
          "201": {
            "description": "Created",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                },
                "description": "Server-generated correlation ID."
              },
              "Location": {
                "schema": {
                  "type": "string"
                },
                "description": "Relative URL of the created resource."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LiveSummary"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "409": {
            "description": "Domain conflict, changed idempotency input (idempotency_conflict), or concurrent retry lock contention (idempotency_in_progress).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input or invalid_idempotency_key.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateLive"
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/lives/{live_id}": {
      "parameters": [
        {
          "name": "live_id",
          "in": "path",
          "required": true,
          "description": "",
          "schema": {
            "type": "string"
          }
        }
      ],
      "get": {
        "operationId": "getLive",
        "summary": "Read Live state",
        "description": "**Required scopes:** `live.get`.\n\nReturns a typed state summary, not the presentation document or audience payload. Foreign organization resources return 404. Supplies the current ETag for metadata and workspace changes. Also accepts finite personal bearer tokens for resources owned by the caller\u2019s personal account. Personal tokens cannot operate organization Lives, use collaborators\u2019/children\u2019s authority, or publish presentations. Current personal token scopes and user permissions are rechecked after waits. Registered delegated OAuth access tokens are accepted within these personal boundaries; /me and account metadata additionally require identity.read.\n\n**Response headers:**\n\n- `ETag` (200): Shared Live sequence validator. Any relevant metadata, display, playback or workspace change invalidates it.",
        "tags": [
          "Lives"
        ],
        "x-required-scopes": [
          "live.get"
        ],
        "responses": {
          "200": {
            "description": "Successful read",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                },
                "description": "Server-generated correlation ID."
              },
              "ETag": {
                "schema": {
                  "type": "string",
                  "pattern": "^\"live-[0-9]+\"$"
                },
                "description": "Shared Live sequence validator. Any relevant metadata, display, playback or workspace change invalidates it."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/Live"
                    },
                    {
                      "$ref": "#/components/schemas/PersonalLive"
                    }
                  ]
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "security": [
          {
            "serviceToken": []
          },
          {
            "personalToken": []
          },
          {
            "delegatedOAuth": [
              "live.get"
            ]
          }
        ],
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      },
      "delete": {
        "operationId": "deleteLive",
        "summary": "Delete a Live",
        "description": "**Required scopes:** `live.delete`.\n\nDeletes through the existing Live registry and domain authorization. Foreign or missing resources return 404. Also accepts finite personal bearer tokens for resources owned by the caller\u2019s personal account. Personal tokens cannot operate organization Lives, use collaborators\u2019/children\u2019s authority, or publish presentations. Current personal token scopes and user permissions are rechecked after waits. Personal deletion requires the current strong Live If-Match; missing/stale return 428/412. Service-token deletion retains its current contract. Registered delegated OAuth access tokens are accepted within these personal boundaries; /me and account metadata additionally require identity.read.",
        "tags": [
          "Lives"
        ],
        "x-required-scopes": [
          "live.delete"
        ],
        "responses": {
          "204": {
            "description": "Deleted",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                },
                "description": "Server-generated correlation ID."
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "security": [
          {
            "serviceToken": []
          },
          {
            "personalToken": []
          },
          {
            "delegatedOAuth": [
              "live.delete"
            ]
          }
        ],
        "parameters": [
          {
            "name": "If-Match",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^\"live-[0-9]+\"$"
            },
            "description": "Required for personal-token deletion. Use the current strong Live ETag. Service-token deletion keeps its existing unconditional semantics."
          }
        ],
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      },
      "patch": {
        "operationId": "updateLiveMetadata",
        "summary": "Edit Live metadata",
        "description": "**Required scopes:** `live.update`.\n\nEdits the name only. Omitted fields are preserved; unknown fields are rejected. No-op edits preserve ETag. Current scope, workspace and persisted sequence are rechecked under the workspace lock before an atomic save. Browser/command metadata edits also invalidate REST validators. Does not change display selection or playback state. Also accepts finite personal bearer tokens for resources owned by the caller\u2019s personal account. Personal tokens cannot operate organization Lives, use collaborators\u2019/children\u2019s authority, or publish presentations. Current personal token scopes and user permissions are rechecked after waits. Registered delegated OAuth access tokens are accepted within these personal boundaries; /me and account metadata additionally require identity.read.\n\n**Response headers:**\n\n- `ETag` (200): Shared Live sequence validator. Any relevant metadata, display, playback or workspace change invalidates it.",
        "tags": [
          "Lives"
        ],
        "x-required-scopes": [
          "live.update"
        ],
        "parameters": [
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^\"live-[0-9]+\"$"
            },
            "description": "Shared Live sequence validator. Any relevant metadata, display, playback or workspace change invalidates it. Missing:428; stale:412; malformed, weak, wildcard or list:422."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LiveMetadataPatch"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful operation",
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string",
                  "pattern": "^\"live-[0-9]+\"$"
                },
                "description": "Shared Live sequence validator. Any relevant metadata, display, playback or workspace change invalidates it."
              },
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/Live"
                    },
                    {
                      "$ref": "#/components/schemas/PersonalLive"
                    }
                  ]
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "security": [
          {
            "serviceToken": []
          },
          {
            "personalToken": []
          },
          {
            "delegatedOAuth": [
              "live.update"
            ]
          }
        ],
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/openapi.json": {
      "get": {
        "operationId": "getOpenApi",
        "summary": "Download the OpenAPI contract",
        "tags": [
          "Discovery"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "OpenAPI 3.1 document",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "description": "",
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/organizations/{organization_id}/translations/{slug}/books/{book_id}/chapters/{chapter}": {
      "parameters": [
        {
          "name": "organization_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        },
        {
          "name": "slug",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128
          }
        },
        {
          "name": "book_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "integer",
            "minimum": 1,
            "maximum": 255
          }
        },
        {
          "name": "chapter",
          "in": "path",
          "required": true,
          "schema": {
            "type": "integer",
            "minimum": 1,
            "maximum": 152
          }
        }
      ],
      "get": {
        "operationId": "readChapter",
        "summary": "Read a chapter",
        "tags": [
          "Scripture"
        ],
        "x-required-scopes": [
          "translation.read"
        ],
        "description": "**Required scopes:** `translation.read`.\n\nRequires the translation in this organization library. Returns canonical book IDs, localized book names, structured verses, edition and attribution. Sparse chapter numbering is preserved; absent resources return 404. No content is installed or fetched by a read.",
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScriptureRead"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/organizations/{organization_id}/translations/{slug}/books/{book_id}/chapters/{chapter}/verses/{verse}": {
      "parameters": [
        {
          "name": "organization_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        },
        {
          "name": "slug",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128
          }
        },
        {
          "name": "book_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "integer",
            "minimum": 1,
            "maximum": 255
          }
        },
        {
          "name": "chapter",
          "in": "path",
          "required": true,
          "schema": {
            "type": "integer",
            "minimum": 1,
            "maximum": 152
          }
        },
        {
          "name": "verse",
          "in": "path",
          "required": true,
          "schema": {
            "type": "integer",
            "minimum": 1,
            "maximum": 255
          }
        }
      ],
      "get": {
        "operationId": "readVerse",
        "summary": "Read a verse",
        "tags": [
          "Scripture"
        ],
        "x-required-scopes": [
          "translation.read"
        ],
        "description": "**Required scopes:** `translation.read`.\n\nRequires the translation in this organization library. Returns canonical book IDs, localized book names, structured verses, edition and attribution. Sparse chapter numbering is preserved; absent resources return 404. No content is installed or fetched by a read.",
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScriptureRead"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/organizations/{organization_id}/translations/{slug}/search": {
      "parameters": [
        {
          "name": "organization_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        },
        {
          "name": "slug",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128
          }
        }
      ],
      "get": {
        "operationId": "searchScripture",
        "summary": "Search organization scripture",
        "tags": [
          "Scripture"
        ],
        "x-required-scopes": [
          "translation.search"
        ],
        "description": "**Required scopes:** `translation.search`.\n\nRequires an enabled organization translation. Results follow native source order, without relevance ranking or cursor pagination. has_more indicates truncation; raise limit up to 100 to see additional matches. Searches share the existing ssh_search allowance (20/minute per principal by default) in addition to REST admission. Query is 1\u2013256 UTF-8 bytes. Unknown or duplicate query parameters are rejected.",
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScriptureSearch"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 256
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          }
        ],
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/lives/{live_id}/display": {
      "parameters": [
        {
          "name": "live_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "get": {
        "operationId": "getLiveDisplay",
        "summary": "Read the Live display",
        "tags": [
          "Live controls"
        ],
        "x-required-scopes": [
          "live.get"
        ],
        "description": "**Required scopes:** `live.get`.\n\nService ownership, current scopes and processing policy are checked inside the serialized Live actor. Updates persist before broadcasting. Sequence changes invalidate display and playback validators together; viewer counts do not. Presentation snapshot metadata is read-only in this slice; editing drafts does not publish them. Also accepts finite personal bearer tokens for resources owned by the caller\u2019s personal account. Personal tokens cannot operate organization Lives, use collaborators\u2019/children\u2019s authority, or publish presentations. Current personal token scopes and user permissions are rechecked after waits. Registered delegated OAuth access tokens are accepted within these personal boundaries; /me and account metadata additionally require identity.read.\n\n**Response headers:**\n\n- `ETag` (200): Strong Live state validator; send unchanged in If-Match for display/playback writes.",
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/LiveDisplay"
                    },
                    {
                      "$ref": "#/components/schemas/PersonalLiveDisplay"
                    }
                  ]
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              },
              "ETag": {
                "schema": {
                  "type": "string"
                },
                "description": "Strong Live state validator; send unchanged in If-Match for display/playback writes."
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "security": [
          {
            "serviceToken": []
          },
          {
            "personalToken": []
          },
          {
            "delegatedOAuth": [
              "live.get"
            ]
          }
        ],
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      },
      "put": {
        "operationId": "replaceLiveDisplay",
        "summary": "Replace or clear the Live display",
        "tags": [
          "Live controls"
        ],
        "x-required-scopes": [
          "live.update"
        ],
        "description": "**Required scopes:** `live.update`.\n\nService ownership, current explicit scopes and processing policy are checked inside the serialized Live actor. Requires live.update plus translation.read for scripture or presentation.present for saved-deck publication. Updates persist before broadcasting. Shared Live sequence validators protect display/playback/metadata/queue changes; viewer counts do not. Presentation publication requires presentation_id and explicit current saved revision. Foreign decks return 404, changed/missing requested revision returns 409 presentation_revision_conflict (no historical revision archive), empty decks/stopped Lives return 409. A fresh immutable snapshot is captured, and the deck revision is rechecked under the same workspace lock as final Live save/media pins, so a concurrent deck change cannot silently publish newer content. Optional slide_id selects a stable slide. When updating the same deck already in Presentation mode, omitted slide_id preserves the selected stable ID when present (otherwise clamps the prior index), and blank/paused state are retained. A new presentation starts at slide zero unless selected explicitly. Saving drafts never publishes; source deletion leaves existing snapshots intact. Empty display clears scripture and switches to Reader without deleting a retained presentation snapshot. Also accepts finite personal bearer tokens for resources owned by the caller\u2019s personal account. Personal tokens cannot operate organization Lives, use collaborators\u2019/children\u2019s authority, or publish presentations. Current personal token scopes and user permissions are rechecked after waits. Registered delegated OAuth access tokens are accepted within these personal boundaries; /me and account metadata additionally require identity.read.\n\n**Response headers:**\n\n- `ETag` (200): Strong Live state validator; send unchanged in If-Match for display/playback writes.",
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/LiveDisplay"
                    },
                    {
                      "$ref": "#/components/schemas/PersonalLiveDisplay"
                    }
                  ]
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              },
              "ETag": {
                "schema": {
                  "type": "string"
                },
                "description": "Strong Live state validator; send unchanged in If-Match for display/playback writes."
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReplaceDisplay"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^\"live-[0-9]+\"$"
            },
            "description": "Use the ETag from the latest display/playback response. Missing: 428; stale: 412. Wildcards, weak validators and lists are not accepted."
          }
        ],
        "x-conditional-scopes": {
          "scripture": [
            "translation.read"
          ],
          "presentation": [
            "presentation.present"
          ]
        },
        "security": [
          {
            "serviceToken": []
          },
          {
            "personalToken": []
          },
          {
            "delegatedOAuth": [
              "live.update"
            ]
          }
        ],
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/lives/{live_id}/playback": {
      "parameters": [
        {
          "name": "live_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "get": {
        "operationId": "getLivePlayback",
        "summary": "Read Live playback state",
        "tags": [
          "Live controls"
        ],
        "x-required-scopes": [
          "live.get"
        ],
        "description": "**Required scopes:** `live.get`.\n\nService ownership, current scopes and processing policy are checked inside the serialized Live actor. Updates persist before broadcasting. Sequence changes invalidate display and playback validators together; viewer counts do not. Presentation snapshot metadata is read-only in this slice; editing drafts does not publish them. Also accepts finite personal bearer tokens for resources owned by the caller\u2019s personal account. Personal tokens cannot operate organization Lives, use collaborators\u2019/children\u2019s authority, or publish presentations. Current personal token scopes and user permissions are rechecked after waits. Registered delegated OAuth access tokens are accepted within these personal boundaries; /me and account metadata additionally require identity.read.\n\n**Response headers:**\n\n- `ETag` (200): Strong Live state validator; send unchanged in If-Match for display/playback writes.",
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Playback"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              },
              "ETag": {
                "schema": {
                  "type": "string"
                },
                "description": "Strong Live state validator; send unchanged in If-Match for display/playback writes."
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "security": [
          {
            "serviceToken": []
          },
          {
            "personalToken": []
          },
          {
            "delegatedOAuth": [
              "live.get"
            ]
          }
        ],
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      },
      "patch": {
        "operationId": "updateLivePlayback",
        "summary": "Update Live playback state",
        "tags": [
          "Live controls"
        ],
        "x-required-scopes": [
          "live.update"
        ],
        "description": "**Required scopes:** `live.update`.\n\nService ownership, current scopes and processing policy are checked inside the serialized Live actor. Updates persist before broadcasting. Sequence changes invalidate display and playback validators together; viewer counts do not. Presentation snapshot metadata is read-only in this slice; editing drafts does not publish them. Also accepts finite personal bearer tokens for resources owned by the caller\u2019s personal account. Personal tokens cannot operate organization Lives, use collaborators\u2019/children\u2019s authority, or publish presentations. Current personal token scopes and user permissions are rechecked after waits. Registered delegated OAuth access tokens are accepted within these personal boundaries; /me and account metadata additionally require identity.read.\n\n**Response headers:**\n\n- `ETag` (200): Strong Live state validator; send unchanged in If-Match for display/playback writes.",
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Playback"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              },
              "ETag": {
                "schema": {
                  "type": "string"
                },
                "description": "Strong Live state validator; send unchanged in If-Match for display/playback writes."
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PlaybackPatch"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^\"live-[0-9]+\"$"
            },
            "description": "Use the ETag from the latest display/playback response. Missing: 428; stale: 412. Wildcards, weak validators and lists are not accepted."
          }
        ],
        "security": [
          {
            "serviceToken": []
          },
          {
            "personalToken": []
          },
          {
            "delegatedOAuth": [
              "live.update"
            ]
          }
        ],
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/organizations/{organization_id}/service-tokens/{credential_id}/rotations": {
      "parameters": [
        {
          "name": "organization_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        },
        {
          "name": "credential_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "post": {
        "operationId": "rotateServiceToken",
        "summary": "Rotate a service-token secret",
        "tags": [
          "Service tokens"
        ],
        "x-required-scopes": [
          "token.create"
        ],
        "description": "**Required scopes:** `token.create`.\n\nImmediately invalidates the old secret and returns the replacement once. Preserves label, scopes, and expiry; does not renew an expired token (404). The caller must hold every target scope. Both authorization and If-Match are checked after the organization lock. Rotation of your own token requires storing the returned replacement before any subsequent calls. Do not retry an ambiguous response with a fresh validator; the previous response secret cannot be recovered. Idempotency-Key is unsupported and rejected with 422 idempotency_not_supported. No secret-bearing response or one-use download stream is retained.\n\n**Response headers:**\n\n- `ETag` (200): Configuration validator. Excludes volatile last-use metadata, which is available in the token list only. Rotation invalidates this validator.",
        "responses": {
          "200": {
            "description": "Successful operation",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              },
              "ETag": {
                "schema": {
                  "type": "string",
                  "pattern": "^\"token-[a-f0-9]{64}\"$"
                },
                "description": "Configuration validator. Excludes volatile last-use metadata, which is available in the token list only. Rotation invalidates this validator."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IssuedServiceToken"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EmptyObject"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^\"token-[a-f0-9]{64}\"$"
            },
            "description": "Use the latest service-token configuration ETag unchanged. Missing: 428; stale: 412. Wildcards, lists and weak validators are rejected."
          }
        ],
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/translations": {
      "get": {
        "operationId": "listTranslationCatalogue",
        "summary": "List reviewed translation editions",
        "tags": [
          "Translations"
        ],
        "x-required-scopes": [
          "translation.list"
        ],
        "description": "**Required scopes:** `translation.list`.\n\nMetadata discovery only. Includes install availability and reviewed rights/provenance. Does not fetch, install, enable translations, or grant scripture access. Entries use lowercase slugs in ascending order. Also accepts finite personal bearer tokens for resources owned by the caller\u2019s personal account. Personal tokens cannot operate organization Lives, use collaborators\u2019/children\u2019s authority, or publish presentations. Current personal token scopes and user permissions are rechecked after waits. Registered delegated OAuth access tokens are accepted within these personal boundaries; /me and account metadata additionally require identity.read.",
        "responses": {
          "200": {
            "description": "Successful operation",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TranslationCollection"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "after",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 128
            },
            "description": "Cursor returned by this collection; book collections use the canonical numeric ID. Translation collections use lowercase slugs."
          }
        ],
        "security": [
          {
            "serviceToken": []
          },
          {
            "personalToken": []
          },
          {
            "delegatedOAuth": [
              "translation.list"
            ]
          }
        ],
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/translations/{slug}": {
      "parameters": [
        {
          "name": "slug",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          }
        }
      ],
      "get": {
        "operationId": "getTranslation",
        "summary": "Read translation edition metadata",
        "tags": [
          "Translations"
        ],
        "x-required-scopes": [
          "translation.get"
        ],
        "description": "**Required scopes:** `translation.get`.\n\nReturns reviewed metadata, canonical book coverage, install availability, rights and provenance. Internal reviewer identity and import configuration are omitted. Unknown editions return 404; uninstalled editions remain discoverable. Also accepts finite personal bearer tokens for resources owned by the caller\u2019s personal account. Personal tokens cannot operate organization Lives, use collaborators\u2019/children\u2019s authority, or publish presentations. Current personal token scopes and user permissions are rechecked after waits. Registered delegated OAuth access tokens are accepted within these personal boundaries; /me and account metadata additionally require identity.read.",
        "responses": {
          "200": {
            "description": "Successful operation",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CatalogueTranslation"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "security": [
          {
            "serviceToken": []
          },
          {
            "personalToken": []
          },
          {
            "delegatedOAuth": [
              "translation.get"
            ]
          }
        ],
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/books": {
      "get": {
        "operationId": "listBooks",
        "summary": "List canonical book definitions",
        "tags": [
          "Translations"
        ],
        "x-required-scopes": [
          "translation.list"
        ],
        "description": "**Required scopes:** `translation.list`.\n\nTranslation-independent dictionary with stable numeric IDs, three-letter codes, aliases and localized names. Numeric ID order; no scripture access is granted. Also accepts finite personal bearer tokens for resources owned by the caller\u2019s personal account. Personal tokens cannot operate organization Lives, use collaborators\u2019/children\u2019s authority, or publish presentations. Current personal token scopes and user permissions are rechecked after waits. Registered delegated OAuth access tokens are accepted within these personal boundaries; /me and account metadata additionally require identity.read.",
        "responses": {
          "200": {
            "description": "Successful operation",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BookCollection"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "after",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 128
            },
            "description": "Cursor returned by this collection; book collections use the canonical numeric ID. Translation collections use lowercase slugs."
          }
        ],
        "security": [
          {
            "serviceToken": []
          },
          {
            "personalToken": []
          },
          {
            "delegatedOAuth": [
              "translation.list"
            ]
          }
        ],
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/translations/{slug}/books": {
      "parameters": [
        {
          "name": "slug",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          }
        }
      ],
      "get": {
        "operationId": "listTranslationBooks",
        "summary": "List a translation edition book coverage",
        "tags": [
          "Translations"
        ],
        "x-required-scopes": [
          "translation.get"
        ],
        "description": "**Required scopes:** `translation.get`.\n\nReviewed catalogue coverage, even if uninstalled or not enabled. Canonical IDs are preserved for partial or New Testament-only editions. This is metadata, not an installed chapter/verse index. Also accepts finite personal bearer tokens for resources owned by the caller\u2019s personal account. Personal tokens cannot operate organization Lives, use collaborators\u2019/children\u2019s authority, or publish presentations. Current personal token scopes and user permissions are rechecked after waits. Registered delegated OAuth access tokens are accepted within these personal boundaries; /me and account metadata additionally require identity.read.",
        "responses": {
          "200": {
            "description": "Successful operation",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BookCollection"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "after",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 128
            },
            "description": "Cursor returned by this collection; book collections use the canonical numeric ID. Translation collections use lowercase slugs."
          }
        ],
        "security": [
          {
            "serviceToken": []
          },
          {
            "personalToken": []
          },
          {
            "delegatedOAuth": [
              "translation.get"
            ]
          }
        ],
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/organizations/{organization_id}/translations": {
      "parameters": [
        {
          "name": "organization_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "get": {
        "operationId": "listOrganizationTranslations",
        "summary": "List the organization translation library",
        "tags": [
          "Translations"
        ],
        "x-required-scopes": [
          "translation.list"
        ],
        "description": "**Required scopes:** `translation.list`.\n\nLists reviewed catalogue editions enabled in the authenticated organization, ordered by canonical slug. Does not include another account library. Current service authority is rechecked after acquiring a shared organization lock.",
        "responses": {
          "200": {
            "description": "Successful operation",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TranslationCollection"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "after",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 128
            },
            "description": "Cursor returned by this collection; book collections use the canonical numeric ID. Translation collections use lowercase slugs."
          }
        ],
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/organizations/{organization_id}/translations/{slug}": {
      "parameters": [
        {
          "name": "organization_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        },
        {
          "name": "slug",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          }
        }
      ],
      "put": {
        "operationId": "enableOrganizationTranslation",
        "summary": "Enable an installed translation in the organization library",
        "tags": [
          "Translations"
        ],
        "x-required-scopes": [
          "translation.enable"
        ],
        "description": "**Required scopes:** `translation.enable`.\n\nRequires an edition in the reviewed catalogue and already installed locally. This endpoint never downloads or installs text. Missing catalogue editions return 404; uninstalled editions return 409 translation_not_installed. Uses current scope/contact/organization checks and serialized organization quota enforcement. An existing membership is a no-op, even at capacity. Does not automatically change existing Live selections.\n\n**Response headers:**\n\n- `Location` (201, 200): Canonical organization library membership URL.",
        "responses": {
          "201": {
            "description": "Successful operation",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              },
              "Location": {
                "schema": {
                  "type": "string"
                },
                "description": "Canonical organization library membership URL."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CatalogueTranslation"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "200": {
            "description": "Already enabled; unchanged membership",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              },
              "Location": {
                "schema": {
                  "type": "string"
                },
                "description": "Canonical organization library membership URL."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CatalogueTranslation"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EmptyObject"
              }
            }
          }
        },
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      },
      "delete": {
        "operationId": "disableOrganizationTranslation",
        "summary": "Remove a translation from the organization library",
        "tags": [
          "Translations"
        ],
        "x-required-scopes": [
          "translation.enable"
        ],
        "description": "**Required scopes:** `translation.enable`.\n\nRemoves only this organization membership. Returns 204 even if already absent. Does not delete installed text, affect another library, or rewrite existing Live selections. Future scripture reads/publications require current library membership.",
        "responses": {
          "204": {
            "description": "Successful operation",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      },
      "get": {
        "operationId": "getOrganizationTranslation",
        "summary": "Read an organization library membership",
        "tags": [
          "Translations"
        ],
        "x-required-scopes": [
          "translation.get"
        ],
        "description": "**Required scopes:** `translation.get`.\n\nReturns reviewed metadata for an edition enabled in the authenticated organization. Absent membership returns 404. Does not fetch text, install content or grant scripture access. Current authority is rechecked after the shared organization lock.",
        "responses": {
          "200": {
            "description": "Enabled organization library entry",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CatalogueTranslation"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/organization": {
      "get": {
        "operationId": "getServiceOrganization",
        "summary": "Discover the service token organization",
        "tags": [
          "Organizations"
        ],
        "x-required-scopes": [
          "organization.get"
        ],
        "description": "**Required scopes:** `organization.get`.\n\nReturns token-bound organization UUID, handle, name, logo URL and website. Excludes contact email, quotas, member directory and internal actor identifiers. Cookie sessions are ignored.",
        "responses": {
          "200": {
            "description": "Successful operation",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Organization"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/organizations/{organization_id}": {
      "parameters": [
        {
          "name": "organization_id",
          "in": "path",
          "required": true,
          "description": "Immutable organization UUID bound to the service token.",
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "get": {
        "operationId": "getOrganization",
        "summary": "Read organization identity",
        "tags": [
          "Organizations"
        ],
        "x-required-scopes": [
          "organization.get"
        ],
        "description": "**Required scopes:** `organization.get`.\n\nReturns token-bound organization UUID, handle, name, logo URL and website. Excludes contact email, quotas, member directory and internal actor identifiers. Cookie sessions are ignored. Mismatched organization IDs or handles return 404.",
        "responses": {
          "200": {
            "description": "Successful operation",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Organization"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/organizations/{organization_id}/members": {
      "parameters": [
        {
          "name": "organization_id",
          "in": "path",
          "required": true,
          "description": "Immutable organization UUID bound to the service token.",
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "get": {
        "operationId": "listOrganizationMembers",
        "summary": "List active organization memberships",
        "tags": [
          "Organizations"
        ],
        "x-required-scopes": [
          "membership.get"
        ],
        "description": "**Required scopes:** `membership.get`.\n\nOrders active memberships by immutable user UUID, with bounded limit and after cursor. Returns display name, personal handle and role only. No private email, invitation, credential or protocol-principal data. Separate pages are fresh snapshots; concurrent membership changes may affect traversal.",
        "responses": {
          "200": {
            "description": "Successful operation",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MembershipPage"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "after",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 128
            },
            "description": "Opaque next_cursor from this collection."
          }
        ],
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/organizations/{organization_id}/members/{member_id}": {
      "parameters": [
        {
          "name": "organization_id",
          "in": "path",
          "required": true,
          "description": "Immutable organization UUID bound to the service token.",
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        },
        {
          "name": "member_id",
          "in": "path",
          "required": true,
          "description": "Immutable user UUID of an active organization membership. Protocol principals and handles are not accepted.",
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "get": {
        "operationId": "getOrganizationMember",
        "summary": "Read an active membership",
        "tags": [
          "Organizations"
        ],
        "x-required-scopes": [
          "membership.get"
        ],
        "description": "**Required scopes:** `membership.get`.\n\nReturns 404 for absent or foreign memberships. ETag is required for subsequent PATCH or DELETE.\n\n**Response headers:**\n\n- `ETag` (200): Strong validator for this membership representation and row revision. Membership writes require the latest value unchanged.",
        "responses": {
          "200": {
            "description": "Successful operation",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              },
              "ETag": {
                "schema": {
                  "type": "string",
                  "pattern": "^\"membership-[a-f0-9]{64}\"$"
                },
                "description": "Strong validator for this membership representation and row revision. Membership writes require the latest value unchanged."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Membership"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      },
      "patch": {
        "operationId": "updateOrganizationMember",
        "summary": "Change a member role",
        "tags": [
          "Organizations"
        ],
        "x-required-scopes": [
          "membership.update"
        ],
        "description": "**Required scopes:** `membership.update`.\n\nChanges an active membership to admin, operator or viewer. Owner roles and ownership transfers are protected (409). Rechecks current explicit service scopes after acquiring the organization lock. Token-management scope alone grants no membership access.\n\n**Response headers:**\n\n- `ETag` (200): Strong validator for this membership representation and row revision. Membership writes require the latest value unchanged.",
        "responses": {
          "200": {
            "description": "Successful operation",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              },
              "ETag": {
                "schema": {
                  "type": "string",
                  "pattern": "^\"membership-[a-f0-9]{64}\"$"
                },
                "description": "Strong validator for this membership representation and row revision. Membership writes require the latest value unchanged."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Membership"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "parameters": [
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^\"membership-[a-f0-9]{64}\"$"
            },
            "description": "Strong validator for this membership representation and row revision. Membership writes require the latest value unchanged. Missing:428; stale:412; malformed, weak, wildcard or list:422."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MembershipPatch"
              }
            }
          }
        },
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      },
      "delete": {
        "operationId": "deleteOrganizationMember",
        "summary": "Remove a member",
        "tags": [
          "Organizations"
        ],
        "x-required-scopes": [
          "membership.delete"
        ],
        "description": "**Required scopes:** `membership.delete`.\n\nRequires the current membership ETag. Owners cannot be removed (409); service principals cannot remove administrators (403). Absent memberships return 204 after scope and precondition syntax checks. Revokes human organization access through the existing membership boundary; independently owned service tokens remain valid.",
        "responses": {
          "204": {
            "description": "Successful operation",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "parameters": [
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^\"membership-[a-f0-9]{64}\"$"
            },
            "description": "Strong validator for this membership representation and row revision. Membership writes require the latest value unchanged. Missing:428; stale:412; malformed, weak, wildcard or list:422."
          }
        ],
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/lives/{live_id}/workspace": {
      "parameters": [
        {
          "name": "live_id",
          "in": "path",
          "required": true,
          "description": "",
          "schema": {
            "type": "string"
          }
        }
      ],
      "put": {
        "operationId": "moveLiveWorkspace",
        "summary": "Move a Live to another organization",
        "description": "**Required scopes:** `live.move`.\n\nRequires the source Authorization bearer with live.move and a destination X-Destination-Service-Token with live.create. Both credentials are revalidated after acquiring sorted workspace locks. Destination mismatch, expiry/revocation or missing destination credential returns 403. Destination total Live quota applies; exhausted capacity or same-workspace requests return 409. Missing/foreign source Lives return 404. Only organization-to-organization moves are supported. Ownership and cleared payloads commit in one transaction before disconnecting viewers and management watchers. Clears scripture payload/reference and presentation snapshots/media pins, resets to hidden Reader mode with pause off, removes collaborators and revokes pending Live invitations. Replaces translation selections and viewer limit with destination library/quota. Existing audience secrets are invalidated while preserving protection. Name, lifecycle status, runtime and viewer styling remain. Returns destination-owned Live and new ETag; source-only credentials lose access. On an ambiguous timeout, inspect through the destination token before retrying. A retry using the old source organization returns 404 once moved.\n\n**Response headers:**\n\n- `ETag` (200): Shared Live sequence validator. Any relevant metadata, display, playback or workspace change invalidates it.",
        "tags": [
          "Lives"
        ],
        "x-required-scopes": [
          "live.move"
        ],
        "parameters": [
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^\"live-[0-9]+\"$"
            },
            "description": "Shared Live sequence validator. Any relevant metadata, display, playback or workspace change invalidates it. Missing:428; stale:412; malformed, weak, wildcard or list:422."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LiveWorkspacePut"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful operation",
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string",
                  "pattern": "^\"live-[0-9]+\"$"
                },
                "description": "Shared Live sequence validator. Any relevant metadata, display, playback or workspace change invalidates it."
              },
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Live"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "x-required-destination-scopes": [
          "live.create"
        ],
        "security": [
          {
            "serviceToken": [],
            "destinationServiceToken": []
          }
        ],
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/lives/{live_id}/queue-items": {
      "parameters": [
        {
          "name": "live_id",
          "in": "path",
          "required": true,
          "description": "",
          "schema": {
            "type": "string"
          }
        }
      ],
      "get": {
        "operationId": "listLiveQueueItems",
        "summary": "List ordered Live queue items",
        "tags": [
          "Lives"
        ],
        "x-required-scopes": [
          "live.get"
        ],
        "description": "**Required scopes:** `live.get`.\n\nThese resources represent the existing scripture stack published to the Live, not a separate draft playlist. Items are one canonical verse in one translation. IDs are scoped by Live, opaque, stable through reorder/metadata changes/restart, and change when a deleted item is recreated. Presentation mode returns 409 for queue reads/writes. Read current items in queue order, including scripture rights and attribution. limit defaults to 50 (1..100). after must be a cursor from this snapshot. Any intervening Live sequence change returns 409 queue_changed; restart traversal. Reads are allowed while stopped. Existing stacks may exceed the REST insertion limit; pagination still returns all items. Also accepts finite personal bearer tokens for resources owned by the caller\u2019s personal account. Personal tokens cannot operate organization Lives, use collaborators\u2019/children\u2019s authority, or publish presentations. Current personal token scopes and user permissions are rechecked after waits. Registered delegated OAuth access tokens are accepted within these personal boundaries; /me and account metadata additionally require identity.read.\n\n**Response headers:**\n\n- `ETag` (200): Shared Live sequence validator. Any relevant metadata, display, playback or workspace change invalidates it.",
        "responses": {
          "200": {
            "description": "Successful operation",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              },
              "ETag": {
                "schema": {
                  "type": "string",
                  "pattern": "^\"live-[0-9]+\"$"
                },
                "description": "Shared Live sequence validator. Any relevant metadata, display, playback or workspace change invalidates it."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/LiveQueuePage"
                    },
                    {
                      "$ref": "#/components/schemas/PersonalLiveQueuePage"
                    }
                  ]
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "after",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 128
            },
            "description": "Opaque sequence-bound next_cursor from this collection."
          }
        ],
        "security": [
          {
            "serviceToken": []
          },
          {
            "personalToken": []
          },
          {
            "delegatedOAuth": [
              "live.get"
            ]
          }
        ],
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      },
      "post": {
        "operationId": "createLiveQueueItem",
        "summary": "Insert a scripture queue item",
        "tags": [
          "Lives"
        ],
        "x-required-scopes": [
          "live.update",
          "translation.read"
        ],
        "description": "**Required scopes:** `live.update`, `translation.read`.\n\nThese resources represent the existing scripture stack published to the Live, not a separate draft playlist. Items are one canonical verse in one translation. IDs are scoped by Live, opaque, stable through reorder/metadata changes/restart, and change when a deleted item is recreated. Presentation mode returns 409 for queue reads/writes. Requires current If-Match; missing:428, stale:412, invalid:422. Current service scopes, organization ownership/status/processing and persisted sequence are rechecked before saving. Stopped Lives return 409. Changes persist before audience publication, switch/retain Reader mode, show remaining verses and resume a paused Live; deleting the last item clears the display. Reads a single enabled/installed verse under the organization library boundary. Inserts before an existing item ID or appends. Duplicate canonical verse/translation returns 409 queue_item_exists. At 100 items insertion returns 409 queue_full. A new item returns 201 with Location. Also accepts finite personal bearer tokens for resources owned by the caller\u2019s personal account. Personal tokens cannot operate organization Lives, use collaborators\u2019/children\u2019s authority, or publish presentations. Current personal token scopes and user permissions are rechecked after waits. Registered delegated OAuth access tokens are accepted within these personal boundaries; /me and account metadata additionally require identity.read. Optional Idempotency-Key atomically records a successful creation for 24-hour replay; current authorization is rechecked. Changed payload or original If-Match returns 409 idempotency_conflict. Replay precedes stale-version and quota evaluation.\n\n**Response headers:**\n\n- `ETag` (201): Shared Live sequence validator. Any relevant metadata, display, playback or workspace change invalidates it.\n- `Location` (201): Relative URL of the created queue item.",
        "responses": {
          "201": {
            "description": "Successful operation",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              },
              "ETag": {
                "schema": {
                  "type": "string",
                  "pattern": "^\"live-[0-9]+\"$"
                },
                "description": "Shared Live sequence validator. Any relevant metadata, display, playback or workspace change invalidates it."
              },
              "Location": {
                "schema": {
                  "type": "string"
                },
                "description": "Relative URL of the created queue item."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LiveQueueItem"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "409": {
            "description": "Domain conflict, changed idempotency input (idempotency_conflict), or concurrent retry lock contention (idempotency_in_progress).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input or invalid_idempotency_key.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateLiveQueueItem"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^\"live-[0-9]+\"$"
            },
            "description": "Shared Live sequence validator. Any relevant metadata, display, playback or workspace change invalidates it. Missing:428; stale:412; malformed, weak, wildcard or list:422."
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "security": [
          {
            "serviceToken": []
          },
          {
            "personalToken": []
          },
          {
            "delegatedOAuth": [
              "live.update",
              "translation.read"
            ]
          }
        ],
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/lives/{live_id}/queue-items/{item_id}": {
      "parameters": [
        {
          "name": "live_id",
          "in": "path",
          "required": true,
          "description": "",
          "schema": {
            "type": "string"
          }
        },
        {
          "name": "item_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-f0-9]{64}$",
            "description": "Opaque stable queue item ID. Preserved through reordering, metadata edits and restart; removing/recreating a verse yields a new ID."
          }
        }
      ],
      "get": {
        "operationId": "getLiveQueueItem",
        "summary": "Read a stable queue item",
        "tags": [
          "Lives"
        ],
        "x-required-scopes": [
          "live.get"
        ],
        "description": "**Required scopes:** `live.get`.\n\nThese resources represent the existing scripture stack published to the Live, not a separate draft playlist. Items are one canonical verse in one translation. IDs are scoped by Live, opaque, stable through reorder/metadata changes/restart, and change when a deleted item is recreated. Presentation mode returns 409 for queue reads/writes. Returns the current position and credited verse. Missing or foreign item IDs return 404. A later reorder can change position while preserving ID. Also accepts finite personal bearer tokens for resources owned by the caller\u2019s personal account. Personal tokens cannot operate organization Lives, use collaborators\u2019/children\u2019s authority, or publish presentations. Current personal token scopes and user permissions are rechecked after waits. Registered delegated OAuth access tokens are accepted within these personal boundaries; /me and account metadata additionally require identity.read.\n\n**Response headers:**\n\n- `ETag` (200): Shared Live sequence validator. Any relevant metadata, display, playback or workspace change invalidates it.",
        "responses": {
          "200": {
            "description": "Successful operation",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              },
              "ETag": {
                "schema": {
                  "type": "string",
                  "pattern": "^\"live-[0-9]+\"$"
                },
                "description": "Shared Live sequence validator. Any relevant metadata, display, playback or workspace change invalidates it."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LiveQueueItem"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "security": [
          {
            "serviceToken": []
          },
          {
            "personalToken": []
          },
          {
            "delegatedOAuth": [
              "live.get"
            ]
          }
        ],
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      },
      "delete": {
        "operationId": "deleteLiveQueueItem",
        "summary": "Remove a queue item",
        "tags": [
          "Lives"
        ],
        "x-required-scopes": [
          "live.update"
        ],
        "description": "**Required scopes:** `live.update`.\n\nThese resources represent the existing scripture stack published to the Live, not a separate draft playlist. Items are one canonical verse in one translation. IDs are scoped by Live, opaque, stable through reorder/metadata changes/restart, and change when a deleted item is recreated. Presentation mode returns 409 for queue reads/writes. Requires current If-Match; missing:428, stale:412, invalid:422. Current service scopes, organization ownership/status/processing and persisted sequence are rechecked before saving. Stopped Lives return 409. Changes persist before audience publication, switch/retain Reader mode, show remaining verses and resume a paused Live; deleting the last item clears the display. Removes this item without renumbering item IDs; remaining positions close the gap. Missing or already removed items return 404. Returns the new shared Live ETag in the 204 response. Also accepts finite personal bearer tokens for resources owned by the caller\u2019s personal account. Personal tokens cannot operate organization Lives, use collaborators\u2019/children\u2019s authority, or publish presentations. Current personal token scopes and user permissions are rechecked after waits. Registered delegated OAuth access tokens are accepted within these personal boundaries; /me and account metadata additionally require identity.read.\n\n**Response headers:**\n\n- `ETag` (204): Shared Live sequence validator. Any relevant metadata, display, playback or workspace change invalidates it.",
        "responses": {
          "204": {
            "description": "Successful operation",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              },
              "ETag": {
                "schema": {
                  "type": "string",
                  "pattern": "^\"live-[0-9]+\"$"
                },
                "description": "Shared Live sequence validator. Any relevant metadata, display, playback or workspace change invalidates it."
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "parameters": [
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^\"live-[0-9]+\"$"
            },
            "description": "Shared Live sequence validator. Any relevant metadata, display, playback or workspace change invalidates it. Missing:428; stale:412; malformed, weak, wildcard or list:422."
          }
        ],
        "security": [
          {
            "serviceToken": []
          },
          {
            "personalToken": []
          },
          {
            "delegatedOAuth": [
              "live.update"
            ]
          }
        ],
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/lives/{live_id}/queue-items/order": {
      "parameters": [
        {
          "name": "live_id",
          "in": "path",
          "required": true,
          "description": "",
          "schema": {
            "type": "string"
          }
        }
      ],
      "put": {
        "operationId": "replaceLiveQueueOrder",
        "summary": "Replace queue ordering",
        "tags": [
          "Lives"
        ],
        "x-required-scopes": [
          "live.update"
        ],
        "description": "**Required scopes:** `live.update`.\n\nThese resources represent the existing scripture stack published to the Live, not a separate draft playlist. Items are one canonical verse in one translation. IDs are scoped by Live, opaque, stable through reorder/metadata changes/restart, and change when a deleted item is recreated. Presentation mode returns 409 for queue reads/writes. Requires current If-Match; missing:428, stale:412, invalid:422. Current service scopes, organization ownership/status/processing and persisted sequence are rechecked before saving. Stopped Lives return 409. Changes persist before audience publication, switch/retain Reader mode, show remaining verses and resume a paused Live; deleting the last item clears the display. Accepts the complete current set of stable item IDs exactly once, in desired order. Unknown, duplicate, extra or omitted IDs return 422 invalid_queue_order. An identical order is a no-op preserving ETag and playback/visibility. Maximum 100 IDs; legacy larger stacks remain readable/removable until reduced below that limit. Returns the ordered snapshot. Also accepts finite personal bearer tokens for resources owned by the caller\u2019s personal account. Personal tokens cannot operate organization Lives, use collaborators\u2019/children\u2019s authority, or publish presentations. Current personal token scopes and user permissions are rechecked after waits. Registered delegated OAuth access tokens are accepted within these personal boundaries; /me and account metadata additionally require identity.read.\n\n**Response headers:**\n\n- `ETag` (200): Shared Live sequence validator. Any relevant metadata, display, playback or workspace change invalidates it.",
        "responses": {
          "200": {
            "description": "Successful operation",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              },
              "ETag": {
                "schema": {
                  "type": "string",
                  "pattern": "^\"live-[0-9]+\"$"
                },
                "description": "Shared Live sequence validator. Any relevant metadata, display, playback or workspace change invalidates it."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/LiveQueuePage"
                    },
                    {
                      "$ref": "#/components/schemas/PersonalLiveQueuePage"
                    }
                  ]
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LiveQueueOrder"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^\"live-[0-9]+\"$"
            },
            "description": "Shared Live sequence validator. Any relevant metadata, display, playback or workspace change invalidates it. Missing:428; stale:412; malformed, weak, wildcard or list:422."
          }
        ],
        "security": [
          {
            "serviceToken": []
          },
          {
            "personalToken": []
          },
          {
            "delegatedOAuth": [
              "live.update"
            ]
          }
        ],
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/organizations/{organization_id}/live-studio": {
      "parameters": [
        {
          "name": "organization_id",
          "in": "path",
          "required": true,
          "description": "Immutable organization UUID bound to the service token.",
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "get": {
        "operationId": "getOrganizationLiveStudio",
        "summary": "Read organization Live Studio settings",
        "tags": [
          "Organizations"
        ],
        "x-required-scopes": [
          "live_studio.get"
        ],
        "description": "**Required scopes:** `live_studio.get`.\n\nService-token organization UUID boundary applies; handles and foreign organization IDs return 404. Personal tokens and browser sessions are not accepted. Only organization_id, revision and normalized settings are returned; editor attribution and internal token principals are omitted. Returns saved settings or effective defaults at revision 0 without creating a settings row. Rechecks current explicit scope after acquiring a shared workspace lock. Studio configuration reads remain available during processing restriction.\n\n**Response headers:**\n\n- `ETag` (200): Strong validator covering the effective settings and revision. Separate from Live playback/display sequence validators. Use unchanged as If-Match on PUT.",
        "responses": {
          "200": {
            "description": "Current organization Live Studio settings",
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string",
                  "pattern": "^\"studio-[a-f0-9]{64}\"$"
                },
                "description": "Strong validator covering the effective settings and revision. Separate from Live playback/display sequence validators. Use unchanged as If-Match on PUT."
              },
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrganizationLiveStudio"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      },
      "put": {
        "operationId": "replaceOrganizationLiveStudio",
        "summary": "Replace organization Live Studio settings",
        "tags": [
          "Organizations"
        ],
        "x-required-scopes": [
          "live_studio.update"
        ],
        "description": "**Required scopes:** `live_studio.update`.\n\nService-token organization UUID boundary applies; handles and foreign organization IDs return 404. Personal tokens and browser sessions are not accepted. Only organization_id, revision and normalized settings are returned; editor attribution and internal token principals are omitted. Requires a current strong Studio If-Match validator: missing 428, stale 412, malformed/weak/wildcard/list 422. Accepts settings only; revision is returned as metadata, not accepted in the body. Preserves existing domain validation and revision semantics. Complete settings are required except optional preset/transition defaults; invalid settings return 422 invalid_design. Identical PUTs still increment revision. Checks current explicit scope, organization status/verification and processing policy under the workspace lock. A processing restriction denies writes (403). Serializes with first saves, browser editor saves, credential changes and organization mutations. Concurrent writes with one validator produce one success and one 412. Persists before notifying organization Lives; changes styling without publishing presentation content or changing individual Live display/playback state. Transient notification failures do not turn a committed write into an error; reconnect/read loads the saved revision.\n\n**Response headers:**\n\n- `ETag` (200): Strong validator covering the effective settings and revision. Separate from Live playback/display sequence validators. Use unchanged as If-Match on PUT.",
        "responses": {
          "200": {
            "description": "Current organization Live Studio settings",
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string",
                  "pattern": "^\"studio-[a-f0-9]{64}\"$"
                },
                "description": "Strong validator covering the effective settings and revision. Separate from Live playback/display sequence validators. Use unchanged as If-Match on PUT."
              },
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrganizationLiveStudio"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "parameters": [
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^\"studio-[a-f0-9]{64}\"$"
            },
            "description": "Strong validator covering the effective settings and revision. Separate from Live playback/display sequence validators. Use unchanged as If-Match on PUT."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PutOrganizationLiveStudio"
              }
            }
          }
        },
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/organizations/{organization_id}/presentations": {
      "parameters": [
        {
          "name": "organization_id",
          "in": "path",
          "required": true,
          "description": "Immutable organization UUID bound to the service token.",
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "get": {
        "operationId": "listPresentations",
        "summary": "List organization presentations",
        "tags": [
          "Presentations"
        ],
        "x-required-scopes": [
          "presentation.list"
        ],
        "description": "**Required scopes:** `presentation.list`.\n\nLists owned presentation summaries in ascending immutable UUID order. Uses limit 1..100 (default 50) and opaque after cursor. Concurrent changes are not a frozen snapshot. Excludes document bodies, creator identifiers, browser permissions, quotas and storage details.",
        "responses": {
          "200": {
            "description": "Successful operation",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PresentationPage"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "after",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 128
            },
            "description": "Opaque next_cursor from the prior page."
          }
        ],
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      },
      "post": {
        "operationId": "createPresentation",
        "summary": "Create an organization presentation",
        "tags": [
          "Presentations"
        ],
        "x-required-scopes": [
          "presentation.create"
        ],
        "description": "**Required scopes:** `presentation.create`.\n\nCreates an empty version-1 presentation at saved revision 0 with the supplied name. Enforces existing organization deck allocation quotas; quota exhaustion returns 409. Service tokens create organization-owned decks without a human creator or member seat. Returns the document and strong ETag even if the creator scope does not include presentation.get. Does not publish to a Live. Optional Idempotency-Key atomically records a successful creation for 24-hour replay; current authorization is rechecked. Changed payload or original If-Match returns 409 idempotency_conflict. Replay precedes stale-version and quota evaluation.\n\n**Response headers:**\n\n- `ETag` (201): Strong validator covering presentation ID, organization, revision and rights-normalized document. Browser/editor saves and changed effective rights notices invalidate it.\n- `Location` (201): Relative presentation resource URL.",
        "responses": {
          "201": {
            "description": "Successful operation",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              },
              "ETag": {
                "schema": {
                  "type": "string",
                  "pattern": "^\"presentation-[a-f0-9]{64}\"$"
                },
                "description": "Strong validator covering presentation ID, organization, revision and rights-normalized document. Browser/editor saves and changed effective rights notices invalidate it."
              },
              "Location": {
                "schema": {
                  "type": "string"
                },
                "description": "Relative presentation resource URL."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Presentation"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "409": {
            "description": "Domain conflict, changed idempotency input (idempotency_conflict), or concurrent retry lock contention (idempotency_in_progress).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input or invalid_idempotency_key.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePresentation"
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/presentations/{presentation_id}": {
      "parameters": [
        {
          "name": "presentation_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          },
          "description": "Immutable presentation UUID; missing, personal or foreign organization resources return 404."
        }
      ],
      "get": {
        "operationId": "getPresentation",
        "summary": "Read a saved presentation",
        "tags": [
          "Presentations"
        ],
        "x-required-scopes": [
          "presentation.get"
        ],
        "description": "**Required scopes:** `presentation.get`.\n\nReads the owned saved document/revision only. Excludes creator attribution, browser flags, quota and media storage metadata. Returns a strong ETag for update/delete. Preserves canonical slide/element IDs and reviewed verse notices.\n\n**Response headers:**\n\n- `ETag` (200): Strong validator covering presentation ID, organization, revision and rights-normalized document. Browser/editor saves and changed effective rights notices invalidate it.",
        "responses": {
          "200": {
            "description": "Successful operation",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              },
              "ETag": {
                "schema": {
                  "type": "string",
                  "pattern": "^\"presentation-[a-f0-9]{64}\"$"
                },
                "description": "Strong validator covering presentation ID, organization, revision and rights-normalized document. Browser/editor saves and changed effective rights notices invalidate it."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Presentation"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      },
      "put": {
        "operationId": "replacePresentation",
        "summary": "Replace a saved presentation document",
        "tags": [
          "Presentations"
        ],
        "x-required-scopes": [
          "presentation.update"
        ],
        "description": "**Required scopes:** `presentation.update`.\n\nFull document replacement retaining supplied slide/element IDs; body accepts document only, not revision. Requires current document If-Match and returns an incremented revision and new ETag, including for identical saves. Current explicit scope, status/processing, ownership and precondition are checked under the workspace lock shared by browser edits, publication and credential changes. Invalid documents/media references return 422; slide/allocation exhaustion returns 409. Transport limit is 2,016,384 bytes; document limit is 2,000,000 encoded JSON bytes. Other REST controls retain their 16 KiB limit. Saving never changes a published Live snapshot.\n\n**Response headers:**\n\n- `ETag` (200): Strong validator covering presentation ID, organization, revision and rights-normalized document. Browser/editor saves and changed effective rights notices invalidate it.",
        "responses": {
          "200": {
            "description": "Successful operation",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              },
              "ETag": {
                "schema": {
                  "type": "string",
                  "pattern": "^\"presentation-[a-f0-9]{64}\"$"
                },
                "description": "Strong validator covering presentation ID, organization, revision and rights-normalized document. Browser/editor saves and changed effective rights notices invalidate it."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Presentation"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PutPresentation"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^\"presentation-[a-f0-9]{64}\"$"
            },
            "description": "Strong validator covering presentation ID, organization, revision and rights-normalized document. Browser/editor saves and changed effective rights notices invalidate it. Missing:428; stale:412; malformed/weak/wildcard/list:422."
          }
        ],
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      },
      "delete": {
        "operationId": "deletePresentation",
        "summary": "Delete a saved presentation",
        "tags": [
          "Presentations"
        ],
        "x-required-scopes": [
          "presentation.delete"
        ],
        "description": "**Required scopes:** `presentation.delete`.\n\nRequires the current presentation ETag. Missing/already deleted/foreign resources return 404. Deletes through existing media retention and quota cleanup. Previously published immutable Live snapshots remain available until explicitly replaced/cleared or restricted by organization policy. Does not require presentation.get. Processing restrictions retain read/delete access while denying create/update/publish.",
        "responses": {
          "204": {
            "description": "Successful operation",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "parameters": [
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^\"presentation-[a-f0-9]{64}\"$"
            },
            "description": "Strong validator covering presentation ID, organization, revision and rights-normalized document. Browser/editor saves and changed effective rights notices invalidate it. Missing:428; stale:412; malformed/weak/wildcard/list:422."
          }
        ],
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/presentations/{presentation_id}/assets": {
      "post": {
        "operationId": "uploadPresentationAsset",
        "summary": "Upload a staged presentation asset",
        "tags": [
          "Presentation assets"
        ],
        "x-required-scopes": [
          "asset.create",
          "presentation.update"
        ],
        "parameters": [
          {
            "name": "presentation_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Presentation UUID belonging to the service token organization."
          },
          {
            "name": "kind",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "image",
                "video"
              ]
            },
            "description": "Image: up to 10 MiB. Video: up to 64 MiB."
          },
          {
            "name": "Content-Length",
            "in": "header",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 67108864
            },
            "description": "Required exact raw body byte count. Missing returns 411, excessive returns 413. Chunked-only requests are unsupported."
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "description": "**Required scopes:** `asset.create`, `presentation.update`.\n\nSend raw bytes, not multipart or JSON. Images are bounded to 10 MiB, dimensions 8192 per side and 40 million pixels; videos to 64 MiB and 4096 per side. Actual bytes, media format and existing codec/container constraints are inspected, regardless of claimed Content-Type. Content-Encoding must be identity. Body reading has a 60-second budget. Existing organization media quotas and upload reservations apply; definitive rejections release reservations and bytes; an ambiguous keyed completion retains its bounded lease until retry/reconciliation or normal expiry. Keyed uploads read and hash the bounded body after authorization, before quota reservation, so full quotas cannot block replay. Fresh scopes and ownership are checked before reservation and completion. Returns safe metadata and a protected asset Location, never a storage key/path. Ready assets are staged for 24 hours; attach through conditional presentation PUT to retain them. Uploading does not change document revision/ETag or publish. Optional Idempotency-Key atomically records a successful creation for 24-hour replay; current authorization is rechecked. Changed payload or original If-Match returns 409 idempotency_conflict. Replay precedes stale-version and quota evaluation.\n\n**Additional request headers:**\n\n- `Content-Length` (required): Required exact raw body byte count. Missing returns 411, excessive returns 413. Chunked-only requests are unsupported.\n- `Idempotency-Key` (optional): Optional case-sensitive retry key, retained 24 hours from successful commit. Scoped to credential principal (stable service-token ID; personal bt_ credential; delegated OAuth grant), account and concrete method/path. Payload, If-Match, query string and Content-Type must match. JSON object key order is ignored; queue reference casing/defaults are normalized; raw upload/import bytes are hashed. Replays retain original success body, Location and ETag with a fresh X-Request-Id, after current authority/ownership/processing/library checks. Same scope/key with changed input:409 idempotency_conflict. Concurrent requests serialize; a contended retry lock can return 409 idempotency_in_progress; bounded database waits can return 503. Errors are not recorded. After expiry, a key is treated as new; original resource/job lifetime is unchanged. No key means no retry guarantee.\n\n**Response headers:**\n\n- `Cache-Control` (201).\n- `Location` (201): Bearer-protected asset resource URL.",
        "requestBody": {
          "required": true,
          "content": {
            "application/octet-stream": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            },
            "image/png": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            },
            "image/jpeg": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            },
            "image/gif": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            },
            "video/mp4": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            },
            "video/webm": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Validated staged asset.",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Location": {
                "schema": {
                  "type": "string"
                },
                "description": "Bearer-protected asset resource URL."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PresentationAsset"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "409": {
            "description": "Domain conflict, changed idempotency input (idempotency_conflict), or concurrent retry lock contention (idempotency_in_progress).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input or invalid_idempotency_key.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/presentations/{presentation_id}/assets/{asset_id}": {
      "get": {
        "operationId": "getPresentationAsset",
        "summary": "Read protected presentation asset bytes",
        "tags": [
          "Presentation assets"
        ],
        "x-required-scopes": [
          "asset.get",
          "presentation.get"
        ],
        "description": "**Required scopes:** `asset.get`, `presentation.get`.\n\nRequires a current bearer token, matching organization, presentation access and an asset referenced by this presentation or its unexpired staged upload. Other decks and foreign assets return 404. No signed/public download URL. Single bounded, open-ended or suffix byte ranges return 206; malformed, unsatisfiable and multi-ranges return 416 Problem Details with Content-Range: bytes */size. No conditional asset caching; all responses are no-store.\n\n**Response headers:**\n\n- `Cache-Control` (200, 206).\n- `Content-Length` (200, 206).\n- `Accept-Ranges` (200, 206).\n- `X-Content-Type-Options` (200, 206).\n- `Content-Security-Policy` (200, 206).\n- `Content-Range` (206).",
        "parameters": [
          {
            "name": "presentation_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Presentation UUID belonging to the service token organization."
          },
          {
            "name": "asset_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-f0-9]{32}$"
            },
            "description": "Opaque asset ID."
          },
          {
            "name": "Range",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional single bytes range, for example bytes=0-1023 or bytes=-1024."
          }
        ],
        "responses": {
          "200": {
            "description": "Complete asset bytes.",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Content-Length": {
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "Accept-Ranges": {
                "schema": {
                  "type": "string",
                  "const": "bytes"
                }
              },
              "X-Content-Type-Options": {
                "schema": {
                  "type": "string",
                  "const": "nosniff"
                }
              },
              "Content-Security-Policy": {
                "schema": {
                  "type": "string",
                  "const": "default-src 'none'; sandbox"
                }
              }
            },
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/gif": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "video/mp4": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "video/webm": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "206": {
            "description": "Requested single byte range.",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Content-Length": {
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "Accept-Ranges": {
                "schema": {
                  "type": "string",
                  "const": "bytes"
                }
              },
              "X-Content-Type-Options": {
                "schema": {
                  "type": "string",
                  "const": "nosniff"
                }
              },
              "Content-Security-Policy": {
                "schema": {
                  "type": "string",
                  "const": "default-src 'none'; sandbox"
                }
              },
              "Content-Range": {
                "schema": {
                  "type": "string",
                  "pattern": "^bytes [0-9]+-[0-9]+/[0-9]+$"
                }
              }
            },
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/gif": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "video/mp4": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "video/webm": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/organizations/{organization_id}/presentation-imports": {
      "post": {
        "operationId": "importPresentation",
        "summary": "Import a portable presentation bundle",
        "tags": [
          "Presentations"
        ],
        "x-required-scopes": [
          "presentation.import",
          "presentation.create",
          "presentation.update",
          "asset.create"
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Organization UUID bound to the service token."
          },
          {
            "name": "Content-Length",
            "in": "header",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 536870912
            },
            "description": "Required exact raw body byte count. Missing returns 411, excessive returns 413. Chunked-only requests are unsupported."
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "description": "**Required scopes:** `presentation.import`, `presentation.create`, `presentation.update`, `asset.create`.\n\nSynchronous atomic import of an existing self-contained .bibleit ZIP bundle. All four scopes are required even without media. At most 512 MiB compressed, 400 MiB expanded, 513 entries including up to 512 assets and a 6 MB manifest. Rejects traversal, duplicate or unlisted entries, invalid manifest/document, checksum mismatch and invalid media. Uses existing portable bundle validation and quotas; malformed bundles return 422, duplicate organization fingerprint or quota exhaustion 409. Preflight scope/ownership/processing checks precede body read; capacity is checked after retry lookup before new writes; current authorization is rechecked under the commit lock. Failed imports roll back database records and newly written files. Allocates fresh deck, slide, element and media IDs, normalizes rights, and returns the saved presentation with Location and ETag. No URL fetching or Live publication. Content-Encoding must be identity; body read budget 60 seconds. Optional Idempotency-Key atomically records a successful creation for 24-hour replay; current authorization is rechecked. Changed payload or original If-Match returns 409 idempotency_conflict. Replay precedes stale-version and quota evaluation.\n\n**Additional request headers:**\n\n- `Content-Length` (required): Required exact raw body byte count. Missing returns 411, excessive returns 413. Chunked-only requests are unsupported.\n- `Idempotency-Key` (optional): Optional case-sensitive retry key, retained 24 hours from successful commit. Scoped to credential principal (stable service-token ID; personal bt_ credential; delegated OAuth grant), account and concrete method/path. Payload, If-Match, query string and Content-Type must match. JSON object key order is ignored; queue reference casing/defaults are normalized; raw upload/import bytes are hashed. Replays retain original success body, Location and ETag with a fresh X-Request-Id, after current authority/ownership/processing/library checks. Same scope/key with changed input:409 idempotency_conflict. Concurrent requests serialize; a contended retry lock can return 409 idempotency_in_progress; bounded database waits can return 503. Errors are not recorded. After expiry, a key is treated as new; original resource/job lifetime is unchanged. No key means no retry guarantee.\n\n**Response headers:**\n\n- `ETag` (201): Strong validator covering presentation ID, organization, revision and rights-normalized document. Browser/editor saves and changed effective rights notices invalidate it.\n- `Location` (201): Relative presentation resource URL.",
        "requestBody": {
          "required": true,
          "content": {
            "application/vnd.bibleit.presentation+zip": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            },
            "application/zip": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            },
            "application/octet-stream": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful operation",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              },
              "ETag": {
                "schema": {
                  "type": "string",
                  "pattern": "^\"presentation-[a-f0-9]{64}\"$"
                },
                "description": "Strong validator covering presentation ID, organization, revision and rights-normalized document. Browser/editor saves and changed effective rights notices invalidate it."
              },
              "Location": {
                "schema": {
                  "type": "string"
                },
                "description": "Relative presentation resource URL."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Presentation"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "409": {
            "description": "Domain conflict, changed idempotency input (idempotency_conflict), or concurrent retry lock contention (idempotency_in_progress).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input or invalid_idempotency_key.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/presentations/{presentation_id}/exports": {
      "post": {
        "operationId": "createPresentationExport",
        "summary": "Queue a saved-revision presentation export",
        "description": "**Required scopes:** `presentation.export`.\n\nCaptures an immutable saved-revision document and pins referenced media. Requires presentation.export only; asset.get and presentation.get are not required. Revision conflict returns 409; invalid slide/format returns 422; nonportable empty decks return 409. Formats: PDF, self-contained HTML ZIP, PNG/JPEG of one selected slide, portable bibleit ZIP. Portable export does not require Node/Chromium; HTML requires Node; PDF/images require Node and Chromium. Rendering errors are asynchronous safe job error codes, never paths/logs. Limits: 8 queued/running jobs globally, 2 per organization; at most 2 workers globally and 1 per organization; busy returns 409. Captured assets total at most 384 MiB; output at most 512 MiB. Initial and terminal retention ten minutes; worker lease five minutes. Expired jobs and files are cleaned up. Does not publish or change the deck. Optional Idempotency-Key supports 24-hour replay. Poll Location after Retry-After seconds. Optional Idempotency-Key atomically records a successful creation for 24-hour replay; current authorization is rechecked. Changed payload or original If-Match returns 409 idempotency_conflict. Replay precedes stale-version and quota evaluation. Replayed export jobs retain their original status/expiry; poll Location for current status and use a new key for a replacement expired job.\n\n**Response headers:**\n\n- `Cache-Control` (202).\n- `Location` (202): Requester-private status resource URL.\n- `Retry-After` (202).",
        "tags": [
          "Presentation exports"
        ],
        "x-required-scopes": [
          "presentation.export"
        ],
        "parameters": [
          {
            "name": "presentation_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Organization-owned presentation UUID. Foreign decks return 404."
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Successful operation.",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Location": {
                "schema": {
                  "type": "string"
                },
                "description": "Requester-private status resource URL."
              },
              "Retry-After": {
                "schema": {
                  "type": "integer",
                  "const": 2
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PresentationExport"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "409": {
            "description": "Domain conflict, changed idempotency input (idempotency_conflict), or concurrent retry lock contention (idempotency_in_progress).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input or invalid_idempotency_key.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePresentationExport"
              }
            }
          }
        },
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      },
      "get": {
        "operationId": "listPresentationExports",
        "summary": "List the requesting service credential\u2019s export jobs",
        "description": "**Required scopes:** `presentation.export`.\n\nPaginated unexpired jobs for this presentation and requesting service credential, ordered by opaque ID. Other tokens in the same organization cannot enumerate these jobs. Secret rotation preserves credential identity and access. Current scope, organization status and processing restrictions are checked under the account lock. Downloaded/expired jobs disappear.\n\n**Response headers:**\n\n- `Cache-Control` (200).",
        "tags": [
          "Presentation exports"
        ],
        "x-required-scopes": [
          "presentation.export"
        ],
        "parameters": [
          {
            "name": "presentation_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Organization-owned presentation UUID. Foreign decks return 404."
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            },
            "description": "Page size."
          },
          {
            "name": "after",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 128
            },
            "description": "Opaque next_cursor from a previous response. At most 128 UTF-8 bytes."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation.",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PresentationExportList"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/presentations/{presentation_id}/exports/{export_id}": {
      "get": {
        "operationId": "getPresentationExport",
        "summary": "Read export job status",
        "description": "**Required scopes:** `presentation.export`.\n\nRead-only polling, with Retry-After: 2. Only the requesting service credential can read the job; secret rotation preserves access. Current authority and presentation access are required; expiry, consumption, foreign presentation or other requester return 404. Failed jobs expose only a stable safe error code. This GET does not consume a file.\n\n**Response headers:**\n\n- `Cache-Control` (200).\n- `Retry-After` (200).",
        "tags": [
          "Presentation exports"
        ],
        "x-required-scopes": [
          "presentation.export"
        ],
        "parameters": [
          {
            "name": "presentation_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Organization-owned presentation UUID. Foreign decks return 404."
          },
          {
            "name": "export_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-f0-9]{32}$"
            },
            "description": "Requester-private export job ID."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation.",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Retry-After": {
                "schema": {
                  "type": "integer",
                  "const": 2
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PresentationExport"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/presentations/{presentation_id}/exports/{export_id}/downloads": {
      "post": {
        "operationId": "downloadPresentationExport",
        "summary": "Consume and download a completed export once",
        "description": "**Required scopes:** `presentation.export`.\n\nSend an empty JSON object. This POST atomically consumes a completed requester-private job and streams its full file as an attachment. GET/HEAD return 405 and never consume. Fresh organization, processing, presentation.export and requesting credential checks apply immediately before consumption. Not-ready/failed jobs return 409; expired, missing, consumed or other-requester jobs return 404. Concurrent attempts have one winner. File is opened before the final authorization/consumption transaction and deleted after the stream closes. No signed/public URLs, redirect, Range, resume or retry guarantee; Range is rejected with 422 before consumption. A disconnected or lost response still consumes the job; create a fresh export to retry. No longer retention or repeatable download is introduced. Body is required application/json with no fields. Idempotency-Key is unsupported and rejected with 422 idempotency_not_supported. No secret-bearing response or one-use download stream is retained.\n\n**Response headers:**\n\n- `Cache-Control` (200).\n- `Content-Length` (200).\n- `Content-Disposition` (200): attachment; filename=\"presentation-<export_id>.<extension>\"\n- `Accept-Ranges` (200).\n- `X-Content-Type-Options` (200).",
        "tags": [
          "Presentation exports"
        ],
        "x-required-scopes": [
          "presentation.export"
        ],
        "parameters": [
          {
            "name": "presentation_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Organization-owned presentation UUID. Foreign decks return 404."
          },
          {
            "name": "export_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-f0-9]{32}$"
            },
            "description": "Requester-private export job ID."
          }
        ],
        "responses": {
          "200": {
            "description": "Full one-use export attachment. Portable and HTML exports are application/zip.",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Content-Length": {
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "maximum": 536870912
                }
              },
              "Content-Disposition": {
                "schema": {
                  "type": "string"
                },
                "description": "attachment; filename=\"presentation-<export_id>.<extension>\""
              },
              "Accept-Ranges": {
                "schema": {
                  "type": "string",
                  "const": "none"
                }
              },
              "X-Content-Type-Options": {
                "schema": {
                  "type": "string",
                  "const": "nosniff"
                }
              }
            },
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "application/zip": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "maxProperties": 0
              },
              "example": {}
            }
          }
        },
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/me": {
      "get": {
        "operationId": "getPersonalIdentity",
        "summary": "Read your personal identity",
        "description": "Authentication only. Returns the caller\u2019s safe identity and immutable personal account UUID. Service tokens and browser cookies cannot authenticate. No user-selecting query is accepted. Registered delegated OAuth access tokens are accepted within these personal boundaries; /me and account metadata additionally require identity.read.",
        "tags": [
          "Personal accounts"
        ],
        "security": [
          {
            "personalToken": []
          },
          {
            "delegatedOAuth": [
              "identity.read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Successful personal resource read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PersonalIdentity"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "x-authenticated-only": true,
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/accounts": {
      "get": {
        "operationId": "listPersonalAccounts",
        "summary": "List your personal account",
        "description": "Authentication only. Lists the caller\u2019s single active personal account, not an organization/global directory. Supports normal limit/after pagination; the bounded collection has next_cursor null. Organization resources remain separate service-token routes. Registered delegated OAuth access tokens are accepted within these personal boundaries; /me and account metadata additionally require identity.read.",
        "tags": [
          "Personal accounts"
        ],
        "security": [
          {
            "personalToken": []
          },
          {
            "delegatedOAuth": [
              "identity.read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Successful personal resource read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PersonalAccountList"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "x-authenticated-only": true,
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            },
            "description": "Page size."
          },
          {
            "name": "after",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 128
            },
            "description": "Opaque next_cursor from a previous response. At most 128 UTF-8 bytes."
          }
        ],
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/accounts/{account_id}": {
      "parameters": [
        {
          "name": "account_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          },
          "description": "Caller\u2019s own immutable personal account UUID; other personal or organization accounts return 404."
        }
      ],
      "get": {
        "operationId": "getPersonalAccount",
        "summary": "Read your personal account",
        "description": "Authentication only. Self-owned personal account metadata. No email, organization memberships, billing details or credential records. Registered delegated OAuth access tokens are accepted within these personal boundaries; /me and account metadata additionally require identity.read.",
        "tags": [
          "Personal accounts"
        ],
        "security": [
          {
            "personalToken": []
          },
          {
            "delegatedOAuth": [
              "identity.read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Successful personal resource read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PersonalAccount"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "x-authenticated-only": true,
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/accounts/{account_id}/translations": {
      "parameters": [
        {
          "name": "account_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          },
          "description": "Caller\u2019s own immutable personal account UUID; other personal or organization accounts return 404."
        }
      ],
      "get": {
        "operationId": "listPersonalTranslations",
        "summary": "List the personal account translation library",
        "tags": [
          "Personal accounts"
        ],
        "x-required-scopes": [
          "translation.list"
        ],
        "description": "**Required scopes:** `translation.list`.\n\nPersonal-account library operation. Requires the documented personal permission and explicit token scope if scoped. The caller must own account_id. Uses only the personal enabled library, existing typed verse/rights metadata and bounded native reads/search. No organization library inheritance, installation, URL fetch or implicit enablement. Fresh personal credential/user/account checks run after acquiring the account lock. Disabled translation access returns 403; unknown canonical book/chapter/verse retains the existing 404 contract. Search uses the existing additional per-user search admission and returns has_more. Registered delegated OAuth access tokens are accepted within these personal boundaries; /me and account metadata additionally require identity.read.",
        "responses": {
          "200": {
            "description": "Successful operation",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TranslationCollection"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "after",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 128
            },
            "description": "Cursor returned by this collection; book collections use the canonical numeric ID. Translation collections use lowercase slugs."
          }
        ],
        "security": [
          {
            "personalToken": []
          },
          {
            "delegatedOAuth": [
              "translation.list"
            ]
          }
        ],
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/accounts/{account_id}/translations/{slug}": {
      "parameters": [
        {
          "name": "account_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          },
          "description": "Caller\u2019s own immutable personal account UUID; other personal or organization accounts return 404."
        },
        {
          "name": "slug",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          }
        }
      ],
      "get": {
        "operationId": "getPersonalTranslation",
        "summary": "Read an personal account library membership",
        "tags": [
          "Personal accounts"
        ],
        "x-required-scopes": [
          "translation.get"
        ],
        "description": "**Required scopes:** `translation.get`.\n\nPersonal-account library operation. Requires the documented personal permission and explicit token scope if scoped. The caller must own account_id. Uses only the personal enabled library, existing typed verse/rights metadata and bounded native reads/search. No organization library inheritance, installation, URL fetch or implicit enablement. Fresh personal credential/user/account checks run after acquiring the account lock. Disabled translation access returns 403; unknown canonical book/chapter/verse retains the existing 404 contract. Search uses the existing additional per-user search admission and returns has_more. Registered delegated OAuth access tokens are accepted within these personal boundaries; /me and account metadata additionally require identity.read.",
        "responses": {
          "200": {
            "description": "Enabled organization library entry",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CatalogueTranslation"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "security": [
          {
            "personalToken": []
          },
          {
            "delegatedOAuth": [
              "translation.get"
            ]
          }
        ],
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/accounts/{account_id}/translations/{slug}/books/{book_id}/chapters/{chapter}": {
      "parameters": [
        {
          "name": "account_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          },
          "description": "Caller\u2019s own immutable personal account UUID; other personal or organization accounts return 404."
        },
        {
          "name": "slug",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128
          }
        },
        {
          "name": "book_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "integer",
            "minimum": 1,
            "maximum": 255
          }
        },
        {
          "name": "chapter",
          "in": "path",
          "required": true,
          "schema": {
            "type": "integer",
            "minimum": 1,
            "maximum": 152
          }
        }
      ],
      "get": {
        "operationId": "readPersonalChapter",
        "summary": "Read a chapter",
        "tags": [
          "Personal accounts"
        ],
        "x-required-scopes": [
          "translation.read"
        ],
        "description": "**Required scopes:** `translation.read`.\n\nPersonal-account library operation. Requires the documented personal permission and explicit token scope if scoped. The caller must own account_id. Uses only the personal enabled library, existing typed verse/rights metadata and bounded native reads/search. No organization library inheritance, installation, URL fetch or implicit enablement. Fresh personal credential/user/account checks run after acquiring the account lock. Disabled translation access returns 403; unknown canonical book/chapter/verse retains the existing 404 contract. Search uses the existing additional per-user search admission and returns has_more. Registered delegated OAuth access tokens are accepted within these personal boundaries; /me and account metadata additionally require identity.read.",
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScriptureRead"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "security": [
          {
            "personalToken": []
          },
          {
            "delegatedOAuth": [
              "translation.read"
            ]
          }
        ],
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/accounts/{account_id}/translations/{slug}/books/{book_id}/chapters/{chapter}/verses/{verse}": {
      "parameters": [
        {
          "name": "account_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          },
          "description": "Caller\u2019s own immutable personal account UUID; other personal or organization accounts return 404."
        },
        {
          "name": "slug",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128
          }
        },
        {
          "name": "book_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "integer",
            "minimum": 1,
            "maximum": 255
          }
        },
        {
          "name": "chapter",
          "in": "path",
          "required": true,
          "schema": {
            "type": "integer",
            "minimum": 1,
            "maximum": 152
          }
        },
        {
          "name": "verse",
          "in": "path",
          "required": true,
          "schema": {
            "type": "integer",
            "minimum": 1,
            "maximum": 255
          }
        }
      ],
      "get": {
        "operationId": "readPersonalVerse",
        "summary": "Read a verse",
        "tags": [
          "Personal accounts"
        ],
        "x-required-scopes": [
          "translation.read"
        ],
        "description": "**Required scopes:** `translation.read`.\n\nPersonal-account library operation. Requires the documented personal permission and explicit token scope if scoped. The caller must own account_id. Uses only the personal enabled library, existing typed verse/rights metadata and bounded native reads/search. No organization library inheritance, installation, URL fetch or implicit enablement. Fresh personal credential/user/account checks run after acquiring the account lock. Disabled translation access returns 403; unknown canonical book/chapter/verse retains the existing 404 contract. Search uses the existing additional per-user search admission and returns has_more. Registered delegated OAuth access tokens are accepted within these personal boundaries; /me and account metadata additionally require identity.read.",
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScriptureRead"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "security": [
          {
            "personalToken": []
          },
          {
            "delegatedOAuth": [
              "translation.read"
            ]
          }
        ],
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/accounts/{account_id}/translations/{slug}/search": {
      "parameters": [
        {
          "name": "account_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          },
          "description": "Caller\u2019s own immutable personal account UUID; other personal or organization accounts return 404."
        },
        {
          "name": "slug",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128
          }
        }
      ],
      "get": {
        "operationId": "searchPersonalScripture",
        "summary": "Search personal account scripture",
        "tags": [
          "Personal accounts"
        ],
        "x-required-scopes": [
          "translation.search"
        ],
        "description": "**Required scopes:** `translation.search`.\n\nPersonal-account library operation. Requires the documented personal permission and explicit token scope if scoped. The caller must own account_id. Uses only the personal enabled library, existing typed verse/rights metadata and bounded native reads/search. No organization library inheritance, installation, URL fetch or implicit enablement. Fresh personal credential/user/account checks run after acquiring the account lock. Disabled translation access returns 403; unknown canonical book/chapter/verse retains the existing 404 contract. Search uses the existing additional per-user search admission and returns has_more. Registered delegated OAuth access tokens are accepted within these personal boundaries; /me and account metadata additionally require identity.read.",
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScriptureSearch"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 256
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          }
        ],
        "security": [
          {
            "personalToken": []
          },
          {
            "delegatedOAuth": [
              "translation.search"
            ]
          }
        ],
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/accounts/{account_id}/lives": {
      "parameters": [
        {
          "name": "account_id",
          "in": "path",
          "required": true,
          "description": "Caller\u2019s own immutable personal account UUID; other personal or organization accounts return 404.",
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "get": {
        "operationId": "listPersonalLives",
        "summary": "List your personal Lives",
        "description": "**Required scopes:** `live.list`.\n\nPersonal-account owner access only. Fresh finite personal token authority, active membership/user/account and account boundary checks apply. No organization/collaborator/child-actor authority. GET uses limit/after pagination. POST creates a Reader Live with the existing personal library and plan quota, serialized under the personal account lock; quota exhaustion returns 409. Creation does not enable organization-only presentation or Live Studio features. Returns the individual /lives/{live_id} URL. Registered delegated OAuth access tokens are accepted within these personal boundaries; /me and account metadata additionally require identity.read.",
        "tags": [
          "Personal accounts"
        ],
        "x-required-scopes": [
          "live.list"
        ],
        "responses": {
          "200": {
            "description": "Successful read",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                },
                "description": "Server-generated correlation ID."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PersonalLiveList"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "after",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 128
            },
            "description": "Opaque cursor returned as next_cursor."
          }
        ],
        "security": [
          {
            "personalToken": []
          },
          {
            "delegatedOAuth": [
              "live.list"
            ]
          }
        ],
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      },
      "post": {
        "operationId": "createPersonalLive",
        "summary": "Create a personal Reader Live",
        "description": "**Required scopes:** `live.create`.\n\nPersonal-account owner access only. Fresh finite personal token authority, active membership/user/account and account boundary checks apply. No organization/collaborator/child-actor authority. GET uses limit/after pagination. POST creates a Reader Live with the existing personal library and plan quota, serialized under the personal account lock; quota exhaustion returns 409. Creation does not enable organization-only presentation or Live Studio features. Returns the individual /lives/{live_id} URL. Optional Idempotency-Key supports 24-hour replay. Registered delegated OAuth access tokens are accepted within these personal boundaries; /me and account metadata additionally require identity.read. Optional Idempotency-Key atomically records a successful creation for 24-hour replay; current authorization is rechecked. Changed payload or original If-Match returns 409 idempotency_conflict. Replay precedes stale-version and quota evaluation.\n\n**Response headers:**\n\n- `Location` (201): Relative URL of the created resource.",
        "tags": [
          "Personal accounts"
        ],
        "x-required-scopes": [
          "live.create"
        ],
        "responses": {
          "201": {
            "description": "Created",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                },
                "description": "Server-generated correlation ID."
              },
              "Location": {
                "schema": {
                  "type": "string"
                },
                "description": "Relative URL of the created resource."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PersonalLiveSummary"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "409": {
            "description": "Domain conflict, changed idempotency input (idempotency_conflict), or concurrent retry lock contention (idempotency_in_progress).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input or invalid_idempotency_key.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateLive"
              }
            }
          }
        },
        "security": [
          {
            "personalToken": []
          },
          {
            "delegatedOAuth": [
              "live.create"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/.well-known/oauth-authorization-server": {
      "get": {
        "operationId": "getOAuthMetadata",
        "summary": "Read OAuth authorization-server metadata",
        "description": "Issuer derives from configured BIBLEIT_PUBLIC_URL/http_public_origin; HTTPS required except literal loopback development. Public registered clients only, token authentication method none. No dynamic registration endpoint.\n\n**Response headers:**\n\n- `Cache-Control` (200).\n- `Referrer-Policy` (200).\n- `Pragma` (200).",
        "tags": [
          "OAuth"
        ],
        "servers": [
          {
            "url": "https://bibleit.app"
          }
        ],
        "security": [],
        "x-oauth-protocol": true,
        "responses": {
          "200": {
            "description": "Authorization-server metadata.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Referrer-Policy": {
                "schema": {
                  "type": "string",
                  "const": "no-referrer"
                }
              },
              "Pragma": {
                "schema": {
                  "type": "string",
                  "const": "no-cache"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthMetadata"
                }
              }
            }
          },
          "default": {
            "description": "OAuth protocol error. Unknown/duplicate/oversized parameters, invalid credentials, policy denial or rate limiting.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthError"
                }
              }
            }
          }
        },
        "x-fern-server-name": "protocol",
        "x-fern-explorer": false
      }
    },
    "/oauth/authorize": {
      "get": {
        "operationId": "authorizeOAuth",
        "summary": "Start registered-client authorization",
        "description": "Validate exact registered redirect URI and explicit allowlisted scopes before any redirect. Require response_type=code, high-entropy state (16\u2013512 bytes), S256 and a 43-character base64url challenge. Unauthenticated users continue through existing login/onboarding using a five-minute opaque request bound to the eventual browser session. GET always requires explicit consent; no automatic approval. Return errors locally for unknown/untrusted callbacks. Clients must verify state and response iss. A resumed request uses only request, with no other query parameters.\n\n**Response headers:**\n\n- `Cache-Control` (200).\n- `Referrer-Policy` (200): Native consent form Origin proof; never sends referrers cross-origin.\n- `Pragma` (200).",
        "tags": [
          "OAuth"
        ],
        "servers": [
          {
            "url": "https://bibleit.app"
          }
        ],
        "security": [
          {
            "browserSession": []
          },
          {}
        ],
        "x-oauth-protocol": true,
        "responses": {
          "200": {
            "description": "Escaped server-rendered consent/connected-app page. No token is issued by GET.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Referrer-Policy": {
                "schema": {
                  "type": "string",
                  "const": "same-origin"
                },
                "description": "Native consent form Origin proof; never sends referrers cross-origin."
              },
              "Pragma": {
                "schema": {
                  "type": "string",
                  "const": "no-cache"
                }
              }
            },
            "content": {
              "text/html; charset=utf-8": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "303": {
            "description": "Validated redirect: existing login/continuation, registered consent result or same-origin settings. Code/denial responses echo state and include iss.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Referrer-Policy": {
                "schema": {
                  "type": "string",
                  "const": "no-referrer"
                }
              },
              "Pragma": {
                "schema": {
                  "type": "string",
                  "const": "no-cache"
                }
              },
              "Location": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "default": {
            "description": "OAuth protocol error. Unknown/duplicate/oversized parameters, invalid credentials, policy denial or rate limiting.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthError"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "response_type",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "const": "code"
            }
          },
          {
            "name": "client_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "redirect_uri",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "scope",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 512,
              "description": "Space-separated explicit registered personal scopes. No empty scope. offline_access alone is invalid."
            }
          },
          {
            "name": "state",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 16,
              "maxLength": 512
            }
          },
          {
            "name": "code_challenge",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^[a-zA-Z0-9_-]{43}$"
            }
          },
          {
            "name": "code_challenge_method",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "const": "S256"
            }
          },
          {
            "name": "request",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^[a-f0-9]{64}$"
            }
          }
        ],
        "x-fern-server-name": "protocol",
        "x-fern-explorer": false
      },
      "post": {
        "operationId": "decideOAuthConsent",
        "summary": "Approve or deny OAuth consent",
        "description": "Requires current browser session, exact session-bound pending request, CSRF cookie/form equality and same Origin. Decision is single-use and expires after five minutes. Approval rechecks registered client, scopes, user/account/membership and current authority under locks. Authorization code expires after 60 seconds; never issued by a GET. Denial redirects access_denied only to the validated redirect. At most five active grants per client/user and twenty per user.\n\n**Additional request headers:**\n\n- `Origin` (required): Must match the browser request origin for CSRF validation.",
        "tags": [
          "OAuth"
        ],
        "servers": [
          {
            "url": "https://bibleit.app"
          }
        ],
        "security": [
          {
            "browserSession": []
          }
        ],
        "x-oauth-protocol": true,
        "responses": {
          "303": {
            "description": "Validated redirect: existing login/continuation, registered consent result or same-origin settings. Code/denial responses echo state and include iss.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Referrer-Policy": {
                "schema": {
                  "type": "string",
                  "const": "no-referrer"
                }
              },
              "Pragma": {
                "schema": {
                  "type": "string",
                  "const": "no-cache"
                }
              },
              "Location": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "default": {
            "description": "OAuth protocol error. Unknown/duplicate/oversized parameters, invalid credentials, policy denial or rate limiting.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthError"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "request": {
                    "type": "string",
                    "pattern": "^[a-f0-9]{64}$"
                  },
                  "csrf": {
                    "type": "string",
                    "pattern": "^[a-f0-9]{64}$"
                  },
                  "decision": {
                    "type": "string",
                    "enum": [
                      "allow",
                      "deny"
                    ]
                  }
                },
                "required": [
                  "request",
                  "csrf",
                  "decision"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            }
          }
        ],
        "x-fern-server-name": "protocol",
        "x-fern-explorer": false
      }
    },
    "/oauth/token": {
      "post": {
        "operationId": "exchangeOAuthToken",
        "summary": "Exchange a code or rotate a refresh token",
        "description": "Public clients send client_id in form; Authorization headers are rejected. Authorization code binds client_id, exact redirect_uri and S256 verifier (43\u2013128 unreserved ASCII characters), expires in 60 seconds, and is single-use. Refresh tokens require offline_access, rotate on every use, and retain the fixed 30-day grant deadline. Reusing a successfully exchanged code or used refresh token revokes the entire grant, including outstanding access/refresh tokens; no retry grace. Wrong client, redirect or verifier cannot exchange the code. Optional refresh scope permanently narrows the grant; it cannot widen. Current user permissions and client enabled status apply. Organization/service/PAT secrets are never issued. No implicit, password or client_credentials grant.\n\n**Response headers:**\n\n- `Cache-Control` (200).\n- `Referrer-Policy` (200).\n- `Pragma` (200).",
        "tags": [
          "OAuth"
        ],
        "servers": [
          {
            "url": "https://bibleit.app"
          }
        ],
        "security": [],
        "x-oauth-protocol": true,
        "responses": {
          "200": {
            "description": "New opaque access token and optional rotating refresh token.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Referrer-Policy": {
                "schema": {
                  "type": "string",
                  "const": "no-referrer"
                }
              },
              "Pragma": {
                "schema": {
                  "type": "string",
                  "const": "no-cache"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthToken"
                }
              }
            }
          },
          "default": {
            "description": "OAuth protocol error. Unknown/duplicate/oversized parameters, invalid credentials, policy denial or rate limiting.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthError"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "oneOf": [
                  {
                    "type": "object",
                    "properties": {
                      "grant_type": {
                        "type": "string",
                        "const": "authorization_code"
                      },
                      "client_id": {
                        "type": "string"
                      },
                      "code": {
                        "type": "string"
                      },
                      "redirect_uri": {
                        "type": "string",
                        "format": "uri"
                      },
                      "code_verifier": {
                        "type": "string",
                        "pattern": "^[a-zA-Z0-9._~-]{43,128}$"
                      }
                    },
                    "required": [
                      "grant_type",
                      "client_id",
                      "code",
                      "redirect_uri",
                      "code_verifier"
                    ],
                    "additionalProperties": false
                  },
                  {
                    "type": "object",
                    "properties": {
                      "grant_type": {
                        "type": "string",
                        "const": "refresh_token"
                      },
                      "client_id": {
                        "type": "string"
                      },
                      "refresh_token": {
                        "type": "string"
                      },
                      "scope": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 512,
                        "description": "Space-separated explicit registered personal scopes. No empty scope. offline_access alone is invalid."
                      }
                    },
                    "required": [
                      "grant_type",
                      "client_id",
                      "refresh_token"
                    ],
                    "additionalProperties": false
                  }
                ]
              }
            }
          }
        },
        "x-fern-server-name": "protocol",
        "x-fern-explorer": false
      }
    },
    "/oauth/revoke": {
      "post": {
        "operationId": "revokeOAuthToken",
        "summary": "Revoke delegated access and refresh tokens",
        "description": "Requires registered public client_id plus token possession. Matching access or refresh token revokes its entire grant. Unknown tokens return the same empty 200 response, including tokens belonging to another client. Existing bt_ and svc_ credentials are unaffected. Authorization headers are rejected.\n\n**Response headers:**\n\n- `Cache-Control` (200).\n- `Referrer-Policy` (200).\n- `Pragma` (200).",
        "tags": [
          "OAuth"
        ],
        "servers": [
          {
            "url": "https://bibleit.app"
          }
        ],
        "security": [],
        "x-oauth-protocol": true,
        "responses": {
          "200": {
            "description": "Revocation processed, including unknown tokens.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Referrer-Policy": {
                "schema": {
                  "type": "string",
                  "const": "no-referrer"
                }
              },
              "Pragma": {
                "schema": {
                  "type": "string",
                  "const": "no-cache"
                }
              }
            }
          },
          "default": {
            "description": "OAuth protocol error. Unknown/duplicate/oversized parameters, invalid credentials, policy denial or rate limiting.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthError"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "client_id": {
                    "type": "string"
                  },
                  "token": {
                    "type": "string"
                  },
                  "token_type_hint": {
                    "type": "string"
                  }
                },
                "required": [
                  "client_id",
                  "token"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "x-fern-server-name": "protocol",
        "x-fern-explorer": false
      }
    },
    "/settings/connected-apps": {
      "get": {
        "operationId": "getConnectedAppsPage",
        "summary": "View connected applications",
        "description": "Existing browser session; unauthenticated users are redirected to login. Lists only this user\u2019s unexpired grants, with disconnect forms. No token hashes or secrets.\n\n**Response headers:**\n\n- `Cache-Control` (200).\n- `Referrer-Policy` (200): Native consent form Origin proof; never sends referrers cross-origin.\n- `Pragma` (200).",
        "tags": [
          "OAuth"
        ],
        "servers": [
          {
            "url": "https://bibleit.app"
          }
        ],
        "security": [
          {
            "browserSession": []
          },
          {}
        ],
        "x-oauth-protocol": true,
        "responses": {
          "200": {
            "description": "Escaped server-rendered consent/connected-app page. No token is issued by GET.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Referrer-Policy": {
                "schema": {
                  "type": "string",
                  "const": "same-origin"
                },
                "description": "Native consent form Origin proof; never sends referrers cross-origin."
              },
              "Pragma": {
                "schema": {
                  "type": "string",
                  "const": "no-cache"
                }
              }
            },
            "content": {
              "text/html; charset=utf-8": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "303": {
            "description": "Validated redirect: existing login/continuation, registered consent result or same-origin settings. Code/denial responses echo state and include iss.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Referrer-Policy": {
                "schema": {
                  "type": "string",
                  "const": "no-referrer"
                }
              },
              "Pragma": {
                "schema": {
                  "type": "string",
                  "const": "no-cache"
                }
              },
              "Location": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "default": {
            "description": "OAuth protocol error. Unknown/duplicate/oversized parameters, invalid credentials, policy denial or rate limiting.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthError"
                }
              }
            }
          }
        },
        "x-fern-server-name": "protocol",
        "x-fern-explorer": false
      },
      "post": {
        "operationId": "disconnectOAuthApp",
        "summary": "Disconnect an application",
        "description": "Browser-only disconnect requires CSRF cookie/form plus same Origin and fresh active identity/account. Revokes the selected own grant and all its tokens. Other users cannot disconnect it.\n\n**Additional request headers:**\n\n- `Origin` (required): Must match the browser request origin for CSRF validation.",
        "tags": [
          "OAuth"
        ],
        "servers": [
          {
            "url": "https://bibleit.app"
          }
        ],
        "security": [
          {
            "browserSession": []
          }
        ],
        "x-oauth-protocol": true,
        "responses": {
          "303": {
            "description": "Validated redirect: existing login/continuation, registered consent result or same-origin settings. Code/denial responses echo state and include iss.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "Referrer-Policy": {
                "schema": {
                  "type": "string",
                  "const": "no-referrer"
                }
              },
              "Pragma": {
                "schema": {
                  "type": "string",
                  "const": "no-cache"
                }
              },
              "Location": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "default": {
            "description": "OAuth protocol error. Unknown/duplicate/oversized parameters, invalid credentials, policy denial or rate limiting.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthError"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "csrf": {
                    "type": "string"
                  },
                  "grant_id": {
                    "type": "string",
                    "pattern": "^[a-f0-9]{32}$"
                  }
                },
                "required": [
                  "csrf",
                  "grant_id"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            }
          }
        ],
        "x-fern-server-name": "protocol",
        "x-fern-explorer": false
      }
    },
    "/me/oauth-grants": {
      "get": {
        "operationId": "listOAuthGrants",
        "summary": "List your connected OAuth applications",
        "description": "**Required scopes:** `token.get`.\n\nRequires an existing finite bt_ personal credential. Delegated OAuth tokens cannot administer grants. Owner-only, current personal authority; no token/hash exposure. Returns at most twenty current grants. Revocation immediately denies access and refresh. Other users receive 404. Browser equivalent is /settings/connected-apps. Requires token.get in current user authority and explicit bt_ scopes when scoped.",
        "tags": [
          "Personal accounts"
        ],
        "security": [
          {
            "personalToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "Own grants.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthGrantList"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "x-required-scopes": [
          "token.get"
        ],
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    },
    "/me/oauth-grants/{grant_id}": {
      "delete": {
        "operationId": "revokeOAuthGrant",
        "summary": "Disconnect your OAuth grant",
        "description": "**Required scopes:** `token.delete`.\n\nRequires an existing finite bt_ personal credential. Delegated OAuth tokens cannot administer grants. Owner-only, current personal authority; no token/hash exposure. Returns at most twenty current grants. Revocation immediately denies access and refresh. Other users receive 404. Browser equivalent is /settings/connected-apps. Requires token.delete in current user authority and explicit bt_ scopes when scoped.",
        "tags": [
          "Personal accounts"
        ],
        "security": [
          {
            "personalToken": []
          }
        ],
        "responses": {
          "204": {
            "description": "Disconnected."
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "x-required-scopes": [
          "token.delete"
        ],
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      },
      "parameters": [
        {
          "name": "grant_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-f0-9]{32}$"
          }
        }
      ]
    },
    "/lives/{live_id}/events": {
      "parameters": [
        {
          "name": "live_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "get": {
        "operationId": "getLiveEvents",
        "summary": "Receive versioned Live events",
        "tags": [
          "Live events"
        ],
        "x-required-scopes": [
          "live.get"
        ],
        "security": [
          {
            "serviceToken": []
          },
          {
            "personalToken": []
          },
          {
            "delegatedOAuth": [
              "live.get"
            ]
          }
        ],
        "description": "**Required scopes:** `live.get`.\n\nBearer-only operator long polling for organization service tokens or owner-only finite personal/delegated OAuth tokens. Omit after for an immediate live.snapshot. Supply the previous cursor for a current live.changed snapshot or a stream.heartbeat with null data if unchanged by the wait deadline (0-25 seconds, default 25). A cursor compares current state; arbitrary valid or old cursors return a current snapshot, never history. Notifications coalesce and may be missed; each recheck reads current authorized state. Reconnect without after to resynchronize. Shared operator watch limit 50 per Live, distinct from audience membership and seat budgets; exhaustion 409. Original service secret hash/expiry, personal credential or OAuth grant, current scopes, ownership and processing policy are rechecked after waits and before every successful delayed response. Secret rotation/revocation/expiry returns 401; removed scopes or processing restrictions 403; missing/moved/deleted resources 404 (an already-revoked watch may return 403). Dependency/revocation-listener failure returns 503. Idle checks use the existing stream authorization cadence (5 seconds by default), capped by the poll deadline. Changes can return before that deadline. Existing HTTP request/peer/principal and stream admission budgets apply; every new poll is charged. No cookies, query-string credentials, audience secrets or Idempotency-Key. No replay log, exactly-once guarantee, SSE/WebSocket upgrade or new CORS policy. Design revisions can change the cursor while sequence is unchanged.",
        "parameters": [
          {
            "name": "after",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^v1:[a-f0-9]{64}$"
            },
            "description": "Previous cursor returned by this resource. Omit to obtain a fresh snapshot on reconnect."
          },
          {
            "name": "wait",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 25,
              "default": 25
            },
            "description": "Maximum intended idle wait in seconds. Dependency/actor queue delays may add normal request latency; clients should allow timeout margin."
          }
        ],
        "responses": {
          "200": {
            "description": "Versioned snapshot, changed snapshot or null-data heartbeat. Always private no-store. Event cursors are not HTTP ETags.",
            "headers": {
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LiveEvent"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "404": {
            "$ref": "#/components/responses/Problem"
          },
          "429": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "x-fern-server-name": "rest",
        "x-fern-explorer": false
      }
    }
  },
  "components": {
    "securitySchemes": {
      "serviceToken": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "svc_ followed by 64 lowercase hexadecimal characters",
        "description": "Organization-owned service token. Issue the initial token in organization credential settings. Scopes are documented per operation via x-required-scopes; they are not OAuth scopes.",
        "x-fern-playground-description": "Organization service token from Credentials. Use a synthetic token in examples; actual credentials belong in the calling backend."
      },
      "destinationServiceToken": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Destination-Service-Token",
        "description": "Destination organization svc_ secret. Must belong to organization_id in the move body and hold live.create. Required in addition to source Authorization bearer; never put this secret in a URL or body."
      },
      "personalToken": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "Existing finite bt_ personal API/CLI token",
        "description": "Personal bearer credential issued through existing account settings or browser-approved CLI flow. Must be active, finite, unexpired, unrevoked, within any rotation overlap, and bound to an active personal membership/user/account. Explicit scopes intersect current user permissions; empty existing personal scopes inherit current user authority. Not an OAuth grant or service token. Browser cookies are ignored."
      },
      "delegatedOAuth": {
        "type": "oauth2",
        "description": "Registered public-client OAuth for personal-account resources only. Exact registered HTTPS or fixed-port literal loopback redirect; S256 required; explicit consent. No organization/presentation authority. identity.read is required for /me and account metadata. Scope intersection with current user authority; no empty-scope inheritance.",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "/oauth/authorize",
            "tokenUrl": "/oauth/token",
            "refreshUrl": "/oauth/token",
            "scopes": {
              "identity.read": "Read basic personal identity and account",
              "offline_access": "Maintain access through rotating refresh tokens for at most thirty days",
              "translation.list": "List available and enabled Bible translations",
              "translation.get": "Read translation details and books",
              "translation.read": "Read personal-library scripture",
              "translation.search": "Search personal-library scripture",
              "live.list": "List owned personal Reader Lives",
              "live.get": "Read personal Live display, playback and queues",
              "live.create": "Create personal Reader Lives within plan limits",
              "live.update": "Edit personal Reader Lives and control scripture display, playback and queues",
              "live.delete": "Delete personal Reader Lives"
            }
          }
        }
      },
      "browserSession": {
        "type": "apiKey",
        "in": "cookie",
        "name": "bibleit_session",
        "description": "Existing secure browser session used only for consent/connected-app UI. Consent POST also requires the matching CSRF cookie/form value and same Origin."
      }
    },
    "schemas": {
      "Problem": {
        "type": "object",
        "properties": {
          "type": {
            "const": "about:blank"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer",
            "minimum": 400,
            "maximum": 599
          },
          "code": {
            "type": "string"
          },
          "request_id": {
            "type": "string",
            "pattern": "^[a-f0-9]{24}$"
          }
        },
        "required": [
          "type",
          "title",
          "status",
          "code",
          "request_id"
        ],
        "additionalProperties": false,
        "examples": [
          {
            "type": "about:blank",
            "title": "Forbidden",
            "status": 403,
            "code": "forbidden",
            "request_id": "000000000000000000000000"
          }
        ]
      },
      "Scope": {
        "type": "string",
        "enum": [
          "server.get",
          "help.get",
          "translation.get",
          "translation.list",
          "translation.read",
          "translation.search",
          "translation.enable",
          "live.get",
          "live.list",
          "live.subscribe",
          "live.create",
          "live.update",
          "live.delete",
          "token.get",
          "token.create",
          "token.delete",
          "live_studio.get",
          "live_studio.update",
          "presentation.get",
          "presentation.list",
          "presentation.create",
          "presentation.update",
          "presentation.delete",
          "presentation.export",
          "presentation.present",
          "organization.get",
          "membership.get",
          "membership.update",
          "membership.delete",
          "live.move",
          "asset.get",
          "asset.create",
          "presentation.import"
        ]
      },
      "ServiceToken": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "organization_id": {
            "type": "string",
            "format": "uuid"
          },
          "label": {
            "type": "string"
          },
          "scopes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Scope"
            }
          },
          "issued_at": {
            "type": "integer"
          },
          "expires_at": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Unix timestamp in seconds; null means no deadline or no recorded use."
          },
          "last_used_at": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Unix timestamp in seconds; null means no deadline or no recorded use."
          }
        },
        "required": [
          "id",
          "organization_id",
          "label",
          "scopes",
          "issued_at",
          "expires_at",
          "last_used_at"
        ],
        "additionalProperties": false
      },
      "CreateServiceToken": {
        "type": "object",
        "properties": {
          "label": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128,
            "description": "At most 128 UTF-8 bytes."
          },
          "scopes": {
            "type": "array",
            "minItems": 1,
            "items": {
              "$ref": "#/components/schemas/Scope"
            },
            "description": "Every scope must be held by the issuer; duplicate entries are normalized."
          },
          "expires_at": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Future Unix seconds, at most 90 days ahead. Omit for 30 days; null explicitly permits no expiration."
          }
        },
        "required": [
          "label",
          "scopes"
        ],
        "additionalProperties": false,
        "examples": [
          {
            "label": "Integration backend",
            "scopes": [
              "live.list",
              "live.get"
            ],
            "expires_at": null
          }
        ]
      },
      "IssuedServiceToken": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "organization_id": {
            "type": "string",
            "format": "uuid"
          },
          "label": {
            "type": "string"
          },
          "scopes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Scope"
            }
          },
          "expires_at": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Unix timestamp in seconds; null means no deadline or no recorded use."
          },
          "secret": {
            "type": "string",
            "pattern": "^svc_[a-f0-9]{64}$",
            "description": "Returned once. Store in a confidential backend."
          }
        },
        "required": [
          "id",
          "organization_id",
          "label",
          "scopes",
          "expires_at",
          "secret"
        ],
        "additionalProperties": false
      },
      "LiveSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "organization_id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "organization_id",
          "name"
        ],
        "additionalProperties": false
      },
      "CreateLive": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128,
            "description": "At most 128 UTF-8 bytes."
          }
        },
        "required": [
          "name"
        ],
        "additionalProperties": false,
        "examples": [
          {
            "name": "Sunday Service"
          }
        ]
      },
      "Live": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "organization_id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "running",
              "stopped"
            ]
          },
          "mode": {
            "type": "string",
            "enum": [
              "reader",
              "presentation"
            ]
          },
          "paused": {
            "type": "boolean"
          },
          "sequence": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "id",
          "organization_id",
          "name",
          "status",
          "mode",
          "paused",
          "sequence"
        ],
        "additionalProperties": false,
        "examples": [
          {
            "id": "sample-live",
            "organization_id": "00000000-0000-4000-8000-000000000001",
            "name": "Sunday Service",
            "status": "stopped",
            "mode": "reader",
            "paused": false,
            "sequence": 0
          }
        ]
      },
      "ServiceTokenList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "maxItems": 100,
            "items": {
              "$ref": "#/components/schemas/ServiceToken"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass this value unchanged as after; null ends the collection."
          }
        },
        "required": [
          "data",
          "next_cursor"
        ],
        "additionalProperties": false
      },
      "LiveList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "maxItems": 100,
            "items": {
              "$ref": "#/components/schemas/LiveSummary"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass this value unchanged as after; null ends the collection."
          }
        },
        "required": [
          "data",
          "next_cursor"
        ],
        "additionalProperties": false
      },
      "TranslationRights": {
        "type": "object",
        "properties": {
          "edition": {
            "type": "string"
          },
          "rights_status": {
            "type": "string"
          },
          "license_id": {
            "type": "string"
          },
          "license_url": {
            "type": "string"
          },
          "source_url": {
            "type": "string"
          },
          "copyright": {
            "type": "string"
          },
          "change_notice": {
            "type": "string"
          },
          "attribution": {
            "type": "string"
          }
        },
        "required": [
          "edition",
          "rights_status",
          "source_url",
          "attribution"
        ],
        "additionalProperties": false
      },
      "Verse": {
        "type": "object",
        "properties": {
          "book_id": {
            "type": "integer",
            "minimum": 1,
            "maximum": 255
          },
          "book": {
            "type": "string"
          },
          "chapter": {
            "type": "integer",
            "minimum": 1,
            "maximum": 152
          },
          "verse": {
            "type": "integer",
            "minimum": 1,
            "maximum": 255
          },
          "text": {
            "type": "string"
          }
        },
        "required": [
          "book_id",
          "book",
          "chapter",
          "verse",
          "text"
        ],
        "additionalProperties": false
      },
      "ScriptureRead": {
        "type": "object",
        "properties": {
          "translation": {
            "type": "string"
          },
          "rights": {
            "$ref": "#/components/schemas/TranslationRights"
          },
          "verses": {
            "type": "array",
            "maxItems": 255,
            "items": {
              "$ref": "#/components/schemas/Verse"
            }
          }
        },
        "required": [
          "translation",
          "rights",
          "verses"
        ],
        "additionalProperties": false
      },
      "ScriptureSearch": {
        "type": "object",
        "properties": {
          "translation": {
            "type": "string"
          },
          "rights": {
            "$ref": "#/components/schemas/TranslationRights"
          },
          "verses": {
            "type": "array",
            "maxItems": 100,
            "items": {
              "$ref": "#/components/schemas/Verse"
            }
          },
          "has_more": {
            "type": "boolean"
          }
        },
        "required": [
          "translation",
          "rights",
          "verses",
          "has_more"
        ],
        "additionalProperties": false
      },
      "DisplayVerse": {
        "type": "object",
        "properties": {
          "book_id": {
            "type": "integer",
            "minimum": 1,
            "maximum": 255
          },
          "book": {
            "type": "string"
          },
          "chapter": {
            "type": "integer",
            "minimum": 1,
            "maximum": 152
          },
          "verse": {
            "type": "integer",
            "minimum": 1,
            "maximum": 255
          },
          "text": {
            "type": "string"
          },
          "translation": {
            "type": "string"
          },
          "rights": {
            "$ref": "#/components/schemas/TranslationRights"
          },
          "attribution": {
            "type": "string"
          }
        },
        "required": [
          "book_id",
          "book",
          "chapter",
          "verse",
          "text",
          "translation",
          "rights",
          "attribution"
        ],
        "additionalProperties": false
      },
      "ScriptureReference": {
        "type": "object",
        "properties": {
          "translation": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128
          },
          "book_id": {
            "type": "integer",
            "minimum": 1,
            "maximum": 255
          },
          "chapter": {
            "type": "integer",
            "minimum": 1,
            "maximum": 152
          },
          "verse_start": {
            "type": "integer",
            "minimum": 1,
            "maximum": 255
          },
          "verse_end": {
            "type": "integer",
            "minimum": 1,
            "maximum": 255
          }
        },
        "required": [
          "translation",
          "book_id",
          "chapter",
          "verse_start"
        ],
        "additionalProperties": false
      },
      "ReplaceDisplay": {
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "type": {
                "const": "empty"
              }
            },
            "required": [
              "type"
            ],
            "additionalProperties": false
          },
          {
            "type": "object",
            "properties": {
              "type": {
                "const": "scripture"
              },
              "reference": {
                "$ref": "#/components/schemas/ScriptureReference"
              }
            },
            "required": [
              "type",
              "reference"
            ],
            "additionalProperties": false
          },
          {
            "$ref": "#/components/schemas/PresentationDisplayReference"
          }
        ],
        "description": "Replace with credited scripture, an explicitly selected saved presentation revision, or clear. Scripture needs translation.read; presentation needs presentation.present in addition to live.update. Saving a presentation never publishes it. Scripture ranges contain 1..100 existing verses in one chapter.",
        "examples": [
          {
            "type": "scripture",
            "reference": {
              "translation": "web",
              "book_id": 1,
              "chapter": 1,
              "verse_start": 1,
              "verse_end": 2
            }
          },
          {
            "type": "empty"
          },
          {
            "type": "presentation",
            "presentation_id": "00000000-0000-4000-8000-000000000001",
            "revision": 1,
            "slide_id": "opening"
          }
        ]
      },
      "PlaybackPatch": {
        "type": "object",
        "properties": {
          "status": {
            "enum": [
              "running",
              "stopped"
            ]
          },
          "paused": {
            "type": "boolean"
          }
        },
        "required": [],
        "additionalProperties": false,
        "minProperties": 1,
        "description": "Change lifecycle status and/or pause state atomically. Pausing a stopped Live returns 409. Stopping resets pause and visibility; starting alone does not redisplay content. paused:false resumes retained content on a running Live.",
        "examples": [
          {
            "paused": true
          },
          {
            "status": "stopped"
          }
        ]
      },
      "Playback": {
        "type": "object",
        "properties": {
          "live_id": {
            "type": "string"
          },
          "status": {
            "enum": [
              "running",
              "stopped"
            ]
          },
          "paused": {
            "type": "boolean"
          },
          "showing": {
            "type": "boolean"
          },
          "sequence": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "live_id",
          "status",
          "paused",
          "showing",
          "sequence"
        ],
        "additionalProperties": false
      },
      "SnapshotSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "deck": {
            "type": "string",
            "format": "uuid"
          },
          "revision": {
            "type": "integer",
            "minimum": 0
          },
          "index": {
            "type": "integer",
            "minimum": 0
          },
          "blank": {
            "type": "boolean"
          },
          "slide_id": {
            "type": "string",
            "pattern": "^[a-zA-Z0-9_-]{1,64}$",
            "description": "Stable selected slide ID from the immutable saved snapshot. Prefer this over the retained zero-based index."
          }
        },
        "required": [
          "id",
          "deck",
          "revision",
          "index",
          "blank",
          "slide_id"
        ],
        "additionalProperties": false
      },
      "LiveDisplay": {
        "type": "object",
        "properties": {
          "live_id": {
            "type": "string"
          },
          "status": {
            "enum": [
              "running",
              "stopped"
            ]
          },
          "paused": {
            "type": "boolean"
          },
          "showing": {
            "type": "boolean"
          },
          "sequence": {
            "type": "integer",
            "minimum": 0
          },
          "organization_id": {
            "type": "string",
            "format": "uuid"
          },
          "type": {
            "enum": [
              "empty",
              "scripture",
              "presentation"
            ]
          },
          "verses": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DisplayVerse"
            }
          },
          "snapshot": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/SnapshotSummary"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "live_id",
          "status",
          "paused",
          "showing",
          "sequence",
          "organization_id",
          "type",
          "verses",
          "snapshot"
        ],
        "additionalProperties": false
      },
      "ServiceTokenConfiguration": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "organization_id": {
            "type": "string",
            "format": "uuid"
          },
          "label": {
            "type": "string"
          },
          "scopes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Scope"
            }
          },
          "issued_at": {
            "type": "integer"
          },
          "expires_at": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Unix timestamp in seconds; null means no deadline or no recorded use."
          }
        },
        "required": [
          "id",
          "organization_id",
          "label",
          "scopes",
          "issued_at",
          "expires_at"
        ],
        "additionalProperties": false
      },
      "PatchServiceToken": {
        "type": "object",
        "properties": {
          "label": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128,
            "description": "At most 128 UTF-8 bytes."
          },
          "scopes": {
            "type": "array",
            "minItems": 1,
            "items": {
              "$ref": "#/components/schemas/Scope"
            },
            "description": "Every scope must be held by the issuer; duplicate entries are normalized."
          },
          "expires_at": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Future Unix seconds, at most 90 days ahead. Omit to preserve the exact existing expiry; null explicitly selects no expiration."
          }
        },
        "required": [],
        "additionalProperties": false,
        "minProperties": 1,
        "description": "Partial configuration edit. Omitted label/scopes/expiry are preserved exactly. expires_at:null explicitly permits no expiration; finite deadlines must be future and at most 90 days ahead. The resulting scopes must be a subset of the caller scopes. Repeated authentication does not change the configuration ETag.",
        "examples": [
          {
            "label": "Integration production"
          },
          {
            "scopes": [
              "live.list",
              "live.get"
            ]
          },
          {
            "expires_at": null
          }
        ]
      },
      "EmptyObject": {
        "type": "object",
        "properties": {},
        "required": [],
        "additionalProperties": false
      },
      "TranslationProvenance": {
        "type": "object",
        "properties": {
          "archive_sha256": {
            "type": [
              "string",
              "null"
            ]
          },
          "reviewed_on": {
            "type": [
              "string",
              "null"
            ]
          },
          "source_id": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "archive_sha256",
          "reviewed_on",
          "source_id"
        ],
        "additionalProperties": false
      },
      "CatalogueTranslation": {
        "type": "object",
        "properties": {
          "slug": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "language": {
            "enum": [
              "en",
              "pt",
              "de",
              "und"
            ]
          },
          "book_ids": {
            "type": "array",
            "maxItems": 84,
            "items": {
              "type": "integer",
              "minimum": 1,
              "maximum": 255
            }
          },
          "rights": {
            "$ref": "#/components/schemas/TranslationRights"
          },
          "installed": {
            "type": "boolean"
          },
          "provenance": {
            "$ref": "#/components/schemas/TranslationProvenance"
          }
        },
        "required": [
          "slug",
          "name",
          "language",
          "book_ids",
          "rights",
          "installed",
          "provenance"
        ],
        "additionalProperties": false
      },
      "BookDefinition": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "minimum": 1,
            "maximum": 255
          },
          "code": {
            "type": "string",
            "pattern": "^[A-Z0-9]{3}$"
          },
          "aliases": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^[A-Z0-9]{3}$"
            }
          },
          "names": {
            "type": "object",
            "properties": {
              "en": {
                "type": "string"
              },
              "pt": {
                "type": "string"
              },
              "de": {
                "type": "string"
              }
            },
            "required": [
              "en",
              "pt",
              "de"
            ],
            "additionalProperties": false
          }
        },
        "required": [
          "id",
          "code",
          "aliases",
          "names"
        ],
        "additionalProperties": false
      },
      "TranslationCollection": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "maxItems": 100,
            "items": {
              "$ref": "#/components/schemas/CatalogueTranslation"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass unchanged as after on the next request; null ends the collection."
          }
        },
        "required": [
          "data",
          "next_cursor"
        ],
        "additionalProperties": false
      },
      "BookCollection": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "maxItems": 100,
            "items": {
              "$ref": "#/components/schemas/BookDefinition"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass unchanged as after on the next request; null ends the collection."
          }
        },
        "required": [
          "data",
          "next_cursor"
        ],
        "additionalProperties": false
      },
      "Organization": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "handle": {
            "type": "string"
          },
          "logo_url": {
            "type": "string"
          },
          "website": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "handle",
          "logo_url",
          "website"
        ],
        "additionalProperties": false
      },
      "Membership": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "organization_id": {
            "type": "string",
            "format": "uuid"
          },
          "display_name": {
            "type": "string"
          },
          "handle": {
            "type": "string"
          },
          "role": {
            "enum": [
              "owner",
              "admin",
              "operator",
              "viewer"
            ]
          }
        },
        "required": [
          "id",
          "organization_id",
          "display_name",
          "handle",
          "role"
        ],
        "additionalProperties": false
      },
      "MembershipPage": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Membership"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "data",
          "next_cursor"
        ],
        "additionalProperties": false
      },
      "MembershipPatch": {
        "type": "object",
        "properties": {
          "role": {
            "enum": [
              "admin",
              "operator",
              "viewer"
            ]
          }
        },
        "required": [
          "role"
        ],
        "additionalProperties": false,
        "examples": [
          {
            "role": "viewer"
          }
        ]
      },
      "LiveMetadataPatch": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128,
            "description": "Nonempty UTF-8 name, at most 128 bytes."
          }
        },
        "required": [
          "name"
        ],
        "additionalProperties": false,
        "examples": [
          {
            "name": "Sunday evening"
          }
        ]
      },
      "LiveWorkspacePut": {
        "type": "object",
        "properties": {
          "organization_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$",
            "description": "Immutable destination organization UUID. Personal workspaces and handles are not accepted."
          }
        },
        "required": [
          "organization_id"
        ],
        "additionalProperties": false,
        "examples": [
          {
            "organization_id": "00000000-0000-4000-8000-000000000002"
          }
        ]
      },
      "LiveQueueItem": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^[a-f0-9]{64}$",
            "description": "Opaque stable queue item ID. Preserved through reordering, metadata edits and restart; removing/recreating a verse yields a new ID."
          },
          "position": {
            "type": "integer",
            "minimum": 0,
            "description": "Zero-based position in the entire current queue, not the current page."
          },
          "verse": {
            "$ref": "#/components/schemas/DisplayVerse"
          }
        },
        "required": [
          "id",
          "position",
          "verse"
        ],
        "additionalProperties": false
      },
      "LiveQueuePage": {
        "type": "object",
        "properties": {
          "live_id": {
            "type": "string"
          },
          "organization_id": {
            "type": "string",
            "format": "uuid"
          },
          "sequence": {
            "type": "integer",
            "minimum": 0
          },
          "data": {
            "type": "array",
            "maxItems": 100,
            "items": {
              "$ref": "#/components/schemas/LiveQueueItem"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Opaque sequence-bound cursor. Pass unchanged as after. Any intervening Live sequence change returns 409; malformed/unknown cursor returns 422."
          }
        },
        "required": [
          "live_id",
          "organization_id",
          "sequence",
          "data",
          "next_cursor"
        ],
        "additionalProperties": false
      },
      "CreateLiveQueueItem": {
        "type": "object",
        "properties": {
          "reference": {
            "type": "object",
            "properties": {
              "translation": {
                "type": "string",
                "minLength": 1,
                "maxLength": 100
              },
              "book_id": {
                "type": "integer",
                "minimum": 1,
                "maximum": 255
              },
              "chapter": {
                "type": "integer",
                "minimum": 1,
                "maximum": 152
              },
              "verse": {
                "type": "integer",
                "minimum": 1,
                "maximum": 255
              }
            },
            "required": [
              "translation",
              "book_id",
              "chapter",
              "verse"
            ],
            "additionalProperties": false
          },
          "before_item_id": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[a-f0-9]{64}$",
            "description": "Insert before this item ID. Omit or use null to append. Unknown anchor returns 404."
          }
        },
        "required": [
          "reference"
        ],
        "additionalProperties": false,
        "examples": [
          {
            "reference": {
              "translation": "web",
              "book_id": 1,
              "chapter": 1,
              "verse": 1
            }
          }
        ]
      },
      "LiveQueueOrder": {
        "type": "object",
        "properties": {
          "item_ids": {
            "type": "array",
            "maxItems": 100,
            "uniqueItems": true,
            "items": {
              "type": "string",
              "pattern": "^[a-f0-9]{64}$",
              "description": "Opaque stable queue item ID. Preserved through reordering, metadata edits and restart; removing/recreating a verse yields a new ID."
            },
            "description": "Complete permutation of the current item IDs. Missing, extra, foreign or duplicate IDs return 422. Empty is valid only for an empty queue."
          }
        },
        "required": [
          "item_ids"
        ],
        "additionalProperties": false,
        "examples": [
          {
            "item_ids": []
          }
        ]
      },
      "LiveStudioSettings": {
        "type": "object",
        "properties": {
          "version": {
            "type": "integer",
            "enum": [
              1
            ]
          },
          "showLogo": {
            "type": "boolean"
          },
          "preset": {
            "enum": [
              "default",
              "midnight",
              "paper",
              "ocean"
            ],
            "default": "default"
          },
          "transition": {
            "enum": [
              "none",
              "fade",
              "slide",
              "slide_up",
              "slide_down",
              "zoom_in",
              "zoom_out",
              "wipe"
            ],
            "default": "none"
          },
          "controls": {
            "type": "object",
            "properties": {
              "theme": {
                "type": "boolean"
              },
              "fullscreen": {
                "type": "boolean"
              },
              "fontSize": {
                "type": "boolean"
              }
            },
            "required": [
              "theme",
              "fullscreen",
              "fontSize"
            ],
            "additionalProperties": false
          },
          "palettes": {
            "type": "object",
            "properties": {
              "dark": {
                "type": "object",
                "properties": {
                  "background": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^#[0-9a-fA-F]{6}$",
                    "description": "Six-digit hexadecimal color; null inherits the selected preset."
                  },
                  "container": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^#[0-9a-fA-F]{6}$",
                    "description": "Six-digit hexadecimal color; null inherits the selected preset."
                  },
                  "translation": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^#[0-9a-fA-F]{6}$",
                    "description": "Six-digit hexadecimal color; null inherits the selected preset."
                  },
                  "reference": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^#[0-9a-fA-F]{6}$",
                    "description": "Six-digit hexadecimal color; null inherits the selected preset."
                  },
                  "text": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^#[0-9a-fA-F]{6}$",
                    "description": "Six-digit hexadecimal color; null inherits the selected preset."
                  }
                },
                "required": [
                  "background",
                  "container",
                  "translation",
                  "reference",
                  "text"
                ],
                "additionalProperties": false
              },
              "light": {
                "type": "object",
                "properties": {
                  "background": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^#[0-9a-fA-F]{6}$",
                    "description": "Six-digit hexadecimal color; null inherits the selected preset."
                  },
                  "container": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^#[0-9a-fA-F]{6}$",
                    "description": "Six-digit hexadecimal color; null inherits the selected preset."
                  },
                  "translation": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^#[0-9a-fA-F]{6}$",
                    "description": "Six-digit hexadecimal color; null inherits the selected preset."
                  },
                  "reference": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^#[0-9a-fA-F]{6}$",
                    "description": "Six-digit hexadecimal color; null inherits the selected preset."
                  },
                  "text": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^#[0-9a-fA-F]{6}$",
                    "description": "Six-digit hexadecimal color; null inherits the selected preset."
                  }
                },
                "required": [
                  "background",
                  "container",
                  "translation",
                  "reference",
                  "text"
                ],
                "additionalProperties": false
              }
            },
            "required": [
              "dark",
              "light"
            ],
            "additionalProperties": false
          },
          "container": {
            "type": "object",
            "properties": {
              "radius": {
                "type": [
                  "integer",
                  "null"
                ],
                "minimum": 0,
                "maximum": 80
              },
              "padding": {
                "type": [
                  "integer",
                  "null"
                ],
                "minimum": 8,
                "maximum": 100
              },
              "border": {
                "type": [
                  "string",
                  "null"
                ],
                "pattern": "^#[0-9a-fA-F]{6}$",
                "description": "Six-digit hexadecimal color; null inherits the selected preset."
              }
            },
            "required": [
              "radius",
              "padding",
              "border"
            ],
            "additionalProperties": false
          },
          "elements": {
            "type": "object",
            "properties": {
              "translation": {
                "type": "object",
                "properties": {
                  "font": {
                    "enum": [
                      "serif",
                      "sans",
                      "mono"
                    ]
                  },
                  "size": {
                    "type": "integer",
                    "minimum": 50,
                    "maximum": 200
                  },
                  "bold": {
                    "type": "boolean"
                  },
                  "italic": {
                    "type": "boolean"
                  },
                  "align": {
                    "enum": [
                      "left",
                      "center",
                      "right"
                    ]
                  },
                  "lineHeight": {
                    "type": "integer",
                    "minimum": 100,
                    "maximum": 200
                  }
                },
                "required": [
                  "font",
                  "size",
                  "bold",
                  "italic",
                  "align",
                  "lineHeight"
                ],
                "additionalProperties": false
              },
              "reference": {
                "type": "object",
                "properties": {
                  "font": {
                    "enum": [
                      "serif",
                      "sans",
                      "mono"
                    ]
                  },
                  "size": {
                    "type": "integer",
                    "minimum": 50,
                    "maximum": 200
                  },
                  "bold": {
                    "type": "boolean"
                  },
                  "italic": {
                    "type": "boolean"
                  },
                  "align": {
                    "enum": [
                      "left",
                      "center",
                      "right"
                    ]
                  },
                  "lineHeight": {
                    "type": "integer",
                    "minimum": 100,
                    "maximum": 200
                  }
                },
                "required": [
                  "font",
                  "size",
                  "bold",
                  "italic",
                  "align",
                  "lineHeight"
                ],
                "additionalProperties": false
              },
              "text": {
                "type": "object",
                "properties": {
                  "font": {
                    "enum": [
                      "serif",
                      "sans",
                      "mono"
                    ]
                  },
                  "size": {
                    "type": "integer",
                    "minimum": 50,
                    "maximum": 200
                  },
                  "bold": {
                    "type": "boolean"
                  },
                  "italic": {
                    "type": "boolean"
                  },
                  "align": {
                    "enum": [
                      "left",
                      "center",
                      "right"
                    ]
                  },
                  "lineHeight": {
                    "type": "integer",
                    "minimum": 100,
                    "maximum": 200
                  }
                },
                "required": [
                  "font",
                  "size",
                  "bold",
                  "italic",
                  "align",
                  "lineHeight"
                ],
                "additionalProperties": false
              }
            },
            "required": [
              "translation",
              "reference",
              "text"
            ],
            "additionalProperties": false
          },
          "order": {
            "type": "array",
            "minItems": 3,
            "maxItems": 3,
            "uniqueItems": true,
            "items": {
              "enum": [
                "translation",
                "reference",
                "text"
              ]
            }
          }
        },
        "required": [
          "version",
          "showLogo",
          "preset",
          "transition",
          "controls",
          "palettes",
          "container",
          "elements",
          "order"
        ],
        "additionalProperties": false,
        "examples": [
          {
            "version": 1,
            "showLogo": true,
            "preset": "default",
            "transition": "none",
            "controls": {
              "theme": true,
              "fullscreen": true,
              "fontSize": true
            },
            "palettes": {
              "dark": {
                "background": null,
                "container": null,
                "translation": null,
                "reference": null,
                "text": null
              },
              "light": {
                "background": null,
                "container": null,
                "translation": null,
                "reference": null,
                "text": null
              }
            },
            "container": {
              "radius": null,
              "padding": null,
              "border": null
            },
            "elements": {
              "translation": {
                "font": "sans",
                "size": 100,
                "bold": true,
                "italic": false,
                "align": "left",
                "lineHeight": 112
              },
              "reference": {
                "font": "sans",
                "size": 100,
                "bold": true,
                "italic": false,
                "align": "left",
                "lineHeight": 112
              },
              "text": {
                "font": "serif",
                "size": 100,
                "bold": false,
                "italic": false,
                "align": "left",
                "lineHeight": 112
              }
            },
            "order": [
              "translation",
              "reference",
              "text"
            ]
          }
        ]
      },
      "LiveStudioSettingsInput": {
        "type": "object",
        "properties": {
          "version": {
            "type": "integer",
            "enum": [
              1
            ]
          },
          "showLogo": {
            "type": "boolean"
          },
          "preset": {
            "enum": [
              "default",
              "midnight",
              "paper",
              "ocean"
            ],
            "default": "default"
          },
          "transition": {
            "enum": [
              "none",
              "fade",
              "slide",
              "slide_up",
              "slide_down",
              "zoom_in",
              "zoom_out",
              "wipe"
            ],
            "default": "none"
          },
          "controls": {
            "type": "object",
            "properties": {
              "theme": {
                "type": "boolean"
              },
              "fullscreen": {
                "type": "boolean"
              },
              "fontSize": {
                "type": "boolean"
              }
            },
            "required": [
              "theme",
              "fullscreen",
              "fontSize"
            ],
            "additionalProperties": false
          },
          "palettes": {
            "type": "object",
            "properties": {
              "dark": {
                "type": "object",
                "properties": {
                  "background": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^#[0-9a-fA-F]{6}$",
                    "description": "Six-digit hexadecimal color; null inherits the selected preset."
                  },
                  "container": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^#[0-9a-fA-F]{6}$",
                    "description": "Six-digit hexadecimal color; null inherits the selected preset."
                  },
                  "translation": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^#[0-9a-fA-F]{6}$",
                    "description": "Six-digit hexadecimal color; null inherits the selected preset."
                  },
                  "reference": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^#[0-9a-fA-F]{6}$",
                    "description": "Six-digit hexadecimal color; null inherits the selected preset."
                  },
                  "text": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^#[0-9a-fA-F]{6}$",
                    "description": "Six-digit hexadecimal color; null inherits the selected preset."
                  }
                },
                "required": [
                  "background",
                  "container",
                  "translation",
                  "reference",
                  "text"
                ],
                "additionalProperties": false
              },
              "light": {
                "type": "object",
                "properties": {
                  "background": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^#[0-9a-fA-F]{6}$",
                    "description": "Six-digit hexadecimal color; null inherits the selected preset."
                  },
                  "container": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^#[0-9a-fA-F]{6}$",
                    "description": "Six-digit hexadecimal color; null inherits the selected preset."
                  },
                  "translation": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^#[0-9a-fA-F]{6}$",
                    "description": "Six-digit hexadecimal color; null inherits the selected preset."
                  },
                  "reference": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^#[0-9a-fA-F]{6}$",
                    "description": "Six-digit hexadecimal color; null inherits the selected preset."
                  },
                  "text": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^#[0-9a-fA-F]{6}$",
                    "description": "Six-digit hexadecimal color; null inherits the selected preset."
                  }
                },
                "required": [
                  "background",
                  "container",
                  "translation",
                  "reference",
                  "text"
                ],
                "additionalProperties": false
              }
            },
            "required": [
              "dark",
              "light"
            ],
            "additionalProperties": false
          },
          "container": {
            "type": "object",
            "properties": {
              "radius": {
                "type": [
                  "integer",
                  "null"
                ],
                "minimum": 0,
                "maximum": 80
              },
              "padding": {
                "type": [
                  "integer",
                  "null"
                ],
                "minimum": 8,
                "maximum": 100
              },
              "border": {
                "type": [
                  "string",
                  "null"
                ],
                "pattern": "^#[0-9a-fA-F]{6}$",
                "description": "Six-digit hexadecimal color; null inherits the selected preset."
              }
            },
            "required": [
              "radius",
              "padding",
              "border"
            ],
            "additionalProperties": false
          },
          "elements": {
            "type": "object",
            "properties": {
              "translation": {
                "type": "object",
                "properties": {
                  "font": {
                    "enum": [
                      "serif",
                      "sans",
                      "mono"
                    ]
                  },
                  "size": {
                    "type": "integer",
                    "minimum": 50,
                    "maximum": 200
                  },
                  "bold": {
                    "type": "boolean"
                  },
                  "italic": {
                    "type": "boolean"
                  },
                  "align": {
                    "enum": [
                      "left",
                      "center",
                      "right"
                    ]
                  },
                  "lineHeight": {
                    "type": "integer",
                    "minimum": 100,
                    "maximum": 200
                  }
                },
                "required": [
                  "font",
                  "size",
                  "bold",
                  "italic",
                  "align",
                  "lineHeight"
                ],
                "additionalProperties": false
              },
              "reference": {
                "type": "object",
                "properties": {
                  "font": {
                    "enum": [
                      "serif",
                      "sans",
                      "mono"
                    ]
                  },
                  "size": {
                    "type": "integer",
                    "minimum": 50,
                    "maximum": 200
                  },
                  "bold": {
                    "type": "boolean"
                  },
                  "italic": {
                    "type": "boolean"
                  },
                  "align": {
                    "enum": [
                      "left",
                      "center",
                      "right"
                    ]
                  },
                  "lineHeight": {
                    "type": "integer",
                    "minimum": 100,
                    "maximum": 200
                  }
                },
                "required": [
                  "font",
                  "size",
                  "bold",
                  "italic",
                  "align",
                  "lineHeight"
                ],
                "additionalProperties": false
              },
              "text": {
                "type": "object",
                "properties": {
                  "font": {
                    "enum": [
                      "serif",
                      "sans",
                      "mono"
                    ]
                  },
                  "size": {
                    "type": "integer",
                    "minimum": 50,
                    "maximum": 200
                  },
                  "bold": {
                    "type": "boolean"
                  },
                  "italic": {
                    "type": "boolean"
                  },
                  "align": {
                    "enum": [
                      "left",
                      "center",
                      "right"
                    ]
                  },
                  "lineHeight": {
                    "type": "integer",
                    "minimum": 100,
                    "maximum": 200
                  }
                },
                "required": [
                  "font",
                  "size",
                  "bold",
                  "italic",
                  "align",
                  "lineHeight"
                ],
                "additionalProperties": false
              }
            },
            "required": [
              "translation",
              "reference",
              "text"
            ],
            "additionalProperties": false
          },
          "order": {
            "type": "array",
            "minItems": 3,
            "maxItems": 3,
            "uniqueItems": true,
            "items": {
              "enum": [
                "translation",
                "reference",
                "text"
              ]
            }
          }
        },
        "required": [
          "version",
          "showLogo",
          "controls",
          "palettes",
          "container",
          "elements",
          "order"
        ],
        "additionalProperties": false,
        "examples": [
          {
            "version": 1,
            "showLogo": true,
            "preset": "default",
            "transition": "none",
            "controls": {
              "theme": true,
              "fullscreen": true,
              "fontSize": true
            },
            "palettes": {
              "dark": {
                "background": null,
                "container": null,
                "translation": null,
                "reference": null,
                "text": null
              },
              "light": {
                "background": null,
                "container": null,
                "translation": null,
                "reference": null,
                "text": null
              }
            },
            "container": {
              "radius": null,
              "padding": null,
              "border": null
            },
            "elements": {
              "translation": {
                "font": "sans",
                "size": 100,
                "bold": true,
                "italic": false,
                "align": "left",
                "lineHeight": 112
              },
              "reference": {
                "font": "sans",
                "size": 100,
                "bold": true,
                "italic": false,
                "align": "left",
                "lineHeight": 112
              },
              "text": {
                "font": "serif",
                "size": 100,
                "bold": false,
                "italic": false,
                "align": "left",
                "lineHeight": 112
              }
            },
            "order": [
              "translation",
              "reference",
              "text"
            ]
          }
        ],
        "description": "Full settings replacement using the existing version-1 Studio model. Only preset and transition may be omitted; they default to default and none. Every other field and all nested keys are required. Unknown fields are rejected at every level."
      },
      "OrganizationLiveStudio": {
        "type": "object",
        "properties": {
          "organization_id": {
            "type": "string",
            "format": "uuid"
          },
          "revision": {
            "type": "integer",
            "minimum": 0,
            "description": "Settings revision independent of any Live sequence. Zero represents unsaved defaults; every accepted PUT increments the revision, even for identical settings."
          },
          "settings": {
            "$ref": "#/components/schemas/LiveStudioSettings"
          }
        },
        "required": [
          "organization_id",
          "revision",
          "settings"
        ],
        "additionalProperties": false
      },
      "PutOrganizationLiveStudio": {
        "type": "object",
        "properties": {
          "settings": {
            "$ref": "#/components/schemas/LiveStudioSettingsInput"
          }
        },
        "required": [
          "settings"
        ],
        "additionalProperties": false,
        "examples": [
          {
            "settings": {
              "version": 1,
              "showLogo": true,
              "preset": "default",
              "transition": "none",
              "controls": {
                "theme": true,
                "fullscreen": true,
                "fontSize": true
              },
              "palettes": {
                "dark": {
                  "background": null,
                  "container": null,
                  "translation": null,
                  "reference": null,
                  "text": null
                },
                "light": {
                  "background": null,
                  "container": null,
                  "translation": null,
                  "reference": null,
                  "text": null
                }
              },
              "container": {
                "radius": null,
                "padding": null,
                "border": null
              },
              "elements": {
                "translation": {
                  "font": "sans",
                  "size": 100,
                  "bold": true,
                  "italic": false,
                  "align": "left",
                  "lineHeight": 112
                },
                "reference": {
                  "font": "sans",
                  "size": 100,
                  "bold": true,
                  "italic": false,
                  "align": "left",
                  "lineHeight": 112
                },
                "text": {
                  "font": "serif",
                  "size": 100,
                  "bold": false,
                  "italic": false,
                  "align": "left",
                  "lineHeight": 112
                }
              },
              "order": [
                "translation",
                "reference",
                "text"
              ]
            }
          }
        ]
      },
      "PresentationElementStyle": {
        "type": "object",
        "properties": {
          "font_size": {
            "type": "number",
            "minimum": 12,
            "maximum": 160
          },
          "font_family": {
            "enum": [
              "sans",
              "serif",
              "mono"
            ]
          },
          "color": {
            "type": "string",
            "pattern": "^#[a-fA-F0-9]{6}$"
          },
          "bold": {
            "type": "boolean"
          },
          "italic": {
            "type": "boolean"
          },
          "align": {
            "enum": [
              "left",
              "center",
              "right"
            ]
          },
          "line_height": {
            "type": "number",
            "minimum": 1,
            "maximum": 2
          },
          "fill": {
            "type": "string",
            "pattern": "^#[a-fA-F0-9]{6}$"
          },
          "stroke": {
            "type": "string",
            "pattern": "^#[a-fA-F0-9]{6}$"
          },
          "stroke_width": {
            "type": "number",
            "minimum": 0,
            "maximum": 20
          },
          "stroke_style": {
            "enum": [
              "solid",
              "dashed",
              "dotted"
            ]
          },
          "opacity": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          }
        },
        "required": [],
        "additionalProperties": false
      },
      "PresentationTextElement": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^[a-zA-Z0-9_-]{1,64}$"
          },
          "type": {
            "const": "text"
          },
          "x": {
            "type": "integer",
            "minimum": 0,
            "maximum": 1279
          },
          "y": {
            "type": "integer",
            "minimum": 0,
            "maximum": 719
          },
          "width": {
            "type": "integer",
            "minimum": 1,
            "maximum": 1280
          },
          "height": {
            "type": "integer",
            "minimum": 1,
            "maximum": 720
          },
          "style": {
            "$ref": "#/components/schemas/PresentationElementStyle"
          },
          "rotation": {
            "type": "integer",
            "minimum": 0,
            "maximum": 359
          },
          "text": {
            "type": "string",
            "minLength": 0,
            "maxLength": 20000,
            "description": "UTF-8 text, at most 20000 bytes; NUL is rejected."
          }
        },
        "required": [
          "id",
          "type",
          "x",
          "y",
          "width",
          "height",
          "text"
        ],
        "additionalProperties": false,
        "description": "Coordinates and dimensions are integer canvas units; x+width must be <=1280 and y+height <=720 (checked by the domain validator). IDs must be unique within a slide."
      },
      "PresentationVerseElement": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^[a-zA-Z0-9_-]{1,64}$"
          },
          "type": {
            "const": "verse"
          },
          "x": {
            "type": "integer",
            "minimum": 0,
            "maximum": 1279
          },
          "y": {
            "type": "integer",
            "minimum": 0,
            "maximum": 719
          },
          "width": {
            "type": "integer",
            "minimum": 1,
            "maximum": 1280
          },
          "height": {
            "type": "integer",
            "minimum": 1,
            "maximum": 720
          },
          "style": {
            "$ref": "#/components/schemas/PresentationElementStyle"
          },
          "rotation": {
            "type": "integer",
            "minimum": 0,
            "maximum": 359
          },
          "text": {
            "type": "string",
            "minLength": 0,
            "maxLength": 20000,
            "description": "UTF-8 text, at most 20000 bytes; NUL is rejected."
          },
          "translation": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "UTF-8 text, at most 200 bytes; NUL is rejected."
          },
          "edition": {
            "type": "string",
            "minLength": 0,
            "maxLength": 2000,
            "description": "UTF-8 text, at most 2000 bytes; NUL is rejected."
          },
          "reference": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "UTF-8 text, at most 200 bytes; NUL is rejected."
          },
          "attribution": {
            "type": "string",
            "minLength": 0,
            "maxLength": 2000,
            "description": "UTF-8 text, at most 2000 bytes; NUL is rejected."
          }
        },
        "required": [
          "id",
          "type",
          "x",
          "y",
          "width",
          "height",
          "text",
          "translation",
          "edition",
          "reference",
          "attribution"
        ],
        "additionalProperties": false,
        "description": "Coordinates and dimensions are integer canvas units; x+width must be <=1280 and y+height <=720 (checked by the domain validator). IDs must be unique within a slide. Known open-license edition/attribution fields are restored from the reviewed catalogue on saves and reads."
      },
      "PresentationShapeElement": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^[a-zA-Z0-9_-]{1,64}$"
          },
          "type": {
            "const": "shape"
          },
          "x": {
            "type": "integer",
            "minimum": 0,
            "maximum": 1279
          },
          "y": {
            "type": "integer",
            "minimum": 0,
            "maximum": 719
          },
          "width": {
            "type": "integer",
            "minimum": 1,
            "maximum": 1280
          },
          "height": {
            "type": "integer",
            "minimum": 1,
            "maximum": 720
          },
          "style": {
            "$ref": "#/components/schemas/PresentationElementStyle"
          },
          "rotation": {
            "type": "integer",
            "minimum": 0,
            "maximum": 359
          },
          "shape": {
            "enum": [
              "rectangle",
              "rounded_rectangle",
              "ellipse",
              "triangle",
              "diamond",
              "arrow",
              "line",
              "line_arrow",
              "elbow_connector",
              "curved_connector"
            ]
          }
        },
        "required": [
          "id",
          "type",
          "x",
          "y",
          "width",
          "height",
          "shape"
        ],
        "additionalProperties": false,
        "description": "Coordinates and dimensions are integer canvas units; x+width must be <=1280 and y+height <=720 (checked by the domain validator). IDs must be unique within a slide."
      },
      "PresentationImageElement": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^[a-zA-Z0-9_-]{1,64}$"
          },
          "type": {
            "const": "image"
          },
          "x": {
            "type": "integer",
            "minimum": 0,
            "maximum": 1279
          },
          "y": {
            "type": "integer",
            "minimum": 0,
            "maximum": 719
          },
          "width": {
            "type": "integer",
            "minimum": 1,
            "maximum": 1280
          },
          "height": {
            "type": "integer",
            "minimum": 1,
            "maximum": 720
          },
          "style": {
            "$ref": "#/components/schemas/PresentationElementStyle"
          },
          "rotation": {
            "type": "integer",
            "minimum": 0,
            "maximum": 359
          },
          "asset": {
            "type": "string",
            "pattern": "^[a-f0-9]{32}$"
          },
          "alt": {
            "type": "string",
            "minLength": 0,
            "maxLength": 1000,
            "description": "UTF-8 text, at most 1000 bytes; NUL is rejected."
          },
          "fit": {
            "enum": [
              "contain",
              "cover"
            ]
          }
        },
        "required": [
          "id",
          "type",
          "x",
          "y",
          "width",
          "height",
          "asset",
          "alt",
          "fit"
        ],
        "additionalProperties": false,
        "description": "Coordinates and dimensions are integer canvas units; x+width must be <=1280 and y+height <=720 (checked by the domain validator). IDs must be unique within a slide."
      },
      "PresentationVideoElement": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^[a-zA-Z0-9_-]{1,64}$"
          },
          "type": {
            "const": "video"
          },
          "x": {
            "type": "integer",
            "minimum": 0,
            "maximum": 1279
          },
          "y": {
            "type": "integer",
            "minimum": 0,
            "maximum": 719
          },
          "width": {
            "type": "integer",
            "minimum": 1,
            "maximum": 1280
          },
          "height": {
            "type": "integer",
            "minimum": 1,
            "maximum": 720
          },
          "style": {
            "$ref": "#/components/schemas/PresentationElementStyle"
          },
          "rotation": {
            "type": "integer",
            "minimum": 0,
            "maximum": 359
          },
          "asset": {
            "type": "string",
            "pattern": "^[a-f0-9]{32}$"
          },
          "fit": {
            "enum": [
              "contain",
              "cover"
            ]
          },
          "poster": {
            "type": "string",
            "pattern": "^[a-f0-9]{32}$"
          },
          "muted": {
            "type": "boolean"
          },
          "loop": {
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "type",
          "x",
          "y",
          "width",
          "height",
          "asset",
          "fit"
        ],
        "additionalProperties": false,
        "description": "Coordinates and dimensions are integer canvas units; x+width must be <=1280 and y+height <=720 (checked by the domain validator). IDs must be unique within a slide."
      },
      "PresentationYouTubeElement": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^[a-zA-Z0-9_-]{1,64}$"
          },
          "type": {
            "const": "youtube"
          },
          "x": {
            "type": "integer",
            "minimum": 0,
            "maximum": 1279
          },
          "y": {
            "type": "integer",
            "minimum": 0,
            "maximum": 719
          },
          "width": {
            "type": "integer",
            "minimum": 1,
            "maximum": 1280
          },
          "height": {
            "type": "integer",
            "minimum": 1,
            "maximum": 720
          },
          "style": {
            "$ref": "#/components/schemas/PresentationElementStyle"
          },
          "rotation": {
            "type": "integer",
            "minimum": 0,
            "maximum": 359
          },
          "video_id": {
            "type": "string",
            "pattern": "^[A-Za-z0-9_-]{11}$"
          }
        },
        "required": [
          "id",
          "type",
          "x",
          "y",
          "width",
          "height",
          "video_id"
        ],
        "additionalProperties": false,
        "description": "Coordinates and dimensions are integer canvas units; x+width must be <=1280 and y+height <=720 (checked by the domain validator). IDs must be unique within a slide."
      },
      "PresentationElement": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/PresentationTextElement"
          },
          {
            "$ref": "#/components/schemas/PresentationVerseElement"
          },
          {
            "$ref": "#/components/schemas/PresentationShapeElement"
          },
          {
            "$ref": "#/components/schemas/PresentationImageElement"
          },
          {
            "$ref": "#/components/schemas/PresentationVideoElement"
          },
          {
            "$ref": "#/components/schemas/PresentationYouTubeElement"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "text": "#/components/schemas/PresentationTextElement",
            "verse": "#/components/schemas/PresentationVerseElement",
            "shape": "#/components/schemas/PresentationShapeElement",
            "image": "#/components/schemas/PresentationImageElement",
            "video": "#/components/schemas/PresentationVideoElement",
            "youtube": "#/components/schemas/PresentationYouTubeElement"
          }
        }
      },
      "PresentationSlide": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^[a-zA-Z0-9_-]{1,64}$"
          },
          "elements": {
            "type": "array",
            "maxItems": 50,
            "items": {
              "$ref": "#/components/schemas/PresentationElement"
            }
          },
          "background": {
            "type": "string",
            "pattern": "^#[a-fA-F0-9]{6}$"
          }
        },
        "required": [
          "id",
          "elements"
        ],
        "additionalProperties": false
      },
      "PresentationDocument": {
        "type": "object",
        "properties": {
          "version": {
            "type": "integer",
            "const": 1
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "UTF-8 text, at most 200 bytes; NUL is rejected."
          },
          "slides": {
            "type": "array",
            "maxItems": 2000,
            "items": {
              "$ref": "#/components/schemas/PresentationSlide"
            }
          }
        },
        "required": [
          "version",
          "name",
          "slides"
        ],
        "additionalProperties": false,
        "description": "Version-1 document, at most 2,000,000 encoded JSON bytes. Slide IDs are unique across the deck, element IDs within each slide. Omitted slide background is preserved as omitted. Save retains caller slide/element IDs; no automatic publishing. Existing same-workspace ready media references are checked by the domain; upload and portable import endpoints provide ready media. Uploading alone never modifies the saved document.",
        "examples": [
          {
            "version": 1,
            "name": "Sunday",
            "slides": [
              {
                "id": "opening",
                "background": "#ffffff",
                "elements": [
                  {
                    "id": "heading",
                    "type": "text",
                    "x": 80,
                    "y": 80,
                    "width": 1120,
                    "height": 560,
                    "text": "Welcome"
                  }
                ]
              }
            ]
          }
        ]
      },
      "Presentation": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "organization_id": {
            "type": "string",
            "format": "uuid"
          },
          "revision": {
            "type": "integer",
            "minimum": 0
          },
          "document": {
            "$ref": "#/components/schemas/PresentationDocument"
          }
        },
        "required": [
          "id",
          "organization_id",
          "revision",
          "document"
        ],
        "additionalProperties": false
      },
      "PresentationSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "organization_id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "revision": {
            "type": "integer",
            "minimum": 0
          },
          "slide_count": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "id",
          "organization_id",
          "name",
          "revision",
          "slide_count"
        ],
        "additionalProperties": false
      },
      "PresentationPage": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "maxItems": 100,
            "items": {
              "$ref": "#/components/schemas/PresentationSummary"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "data",
          "next_cursor"
        ],
        "additionalProperties": false
      },
      "CreatePresentation": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "UTF-8 text, at most 200 bytes; NUL is rejected."
          }
        },
        "required": [
          "name"
        ],
        "additionalProperties": false,
        "examples": [
          {
            "name": "Sunday"
          }
        ]
      },
      "PutPresentation": {
        "type": "object",
        "properties": {
          "document": {
            "$ref": "#/components/schemas/PresentationDocument"
          }
        },
        "required": [
          "document"
        ],
        "additionalProperties": false
      },
      "PresentationDisplayReference": {
        "type": "object",
        "properties": {
          "type": {
            "const": "presentation"
          },
          "presentation_id": {
            "type": "string",
            "format": "uuid"
          },
          "revision": {
            "type": "integer",
            "minimum": 0,
            "maximum": 2147483647
          },
          "slide_id": {
            "type": "string",
            "pattern": "^[a-zA-Z0-9_-]{1,64}$"
          }
        },
        "required": [
          "type",
          "presentation_id",
          "revision"
        ],
        "additionalProperties": false,
        "description": "Explicitly capture the current saved revision of a same-organization deck. This API has no historical revision archive: if the current saved revision differs, return 409 presentation_revision_conflict. Optional slide_id selects a stable saved slide. Missing slide returns 422. Empty decks and stopped Lives return 409."
      },
      "PresentationAsset": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^[a-f0-9]{32}$"
          },
          "organization_id": {
            "type": "string",
            "format": "uuid"
          },
          "presentation_id": {
            "type": "string",
            "format": "uuid"
          },
          "kind": {
            "type": "string",
            "enum": [
              "image",
              "video"
            ]
          },
          "mime": {
            "type": "string",
            "enum": [
              "image/png",
              "image/jpeg",
              "image/gif",
              "video/mp4",
              "video/webm"
            ]
          },
          "width": {
            "type": "integer",
            "minimum": 1,
            "maximum": 8192
          },
          "height": {
            "type": "integer",
            "minimum": 1,
            "maximum": 8192
          },
          "bytes": {
            "type": "integer",
            "minimum": 1,
            "maximum": 67108864
          }
        },
        "required": [
          "id",
          "organization_id",
          "presentation_id",
          "kind",
          "mime",
          "width",
          "height",
          "bytes"
        ]
      },
      "PresentationExport": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^[a-f0-9]{32}$"
          },
          "presentation_id": {
            "type": "string",
            "format": "uuid"
          },
          "organization_id": {
            "type": "string",
            "format": "uuid"
          },
          "revision": {
            "type": "integer",
            "minimum": 0,
            "maximum": 2147483647
          },
          "format": {
            "type": "string",
            "enum": [
              "pdf",
              "html",
              "png",
              "jpeg",
              "bibleit"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "running",
              "completed",
              "failed"
            ]
          },
          "error": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              null,
              "runtime_unavailable",
              "export_cancelled",
              "export_too_large",
              "export_interrupted",
              "export_failed"
            ]
          },
          "bytes": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0,
            "maximum": 536870912
          },
          "created_at": {
            "type": "integer",
            "minimum": 0
          },
          "expires_at": {
            "type": "integer",
            "minimum": 0
          },
          "download_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "Relative POST downloads URL, available only when completed. Requires the requesting credential and current presentation.export scope. Never a public URL."
          }
        },
        "required": [
          "id",
          "presentation_id",
          "organization_id",
          "revision",
          "format",
          "status",
          "error",
          "bytes",
          "created_at",
          "expires_at",
          "download_url"
        ],
        "additionalProperties": false,
        "description": "Safe requester-private job projection. Timestamps are Unix seconds. Jobs snapshot the saved revision at creation; later saves never alter the captured document. Expiry is initially ten minutes and resets to ten minutes on completion/failure. Jobs disappear on expiry, presentation deletion or successful download consumption. Starting a new export removes this requester\u2019s failed jobs."
      },
      "PresentationExportList": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "data": {
            "type": "array",
            "maxItems": 100,
            "items": {
              "$ref": "#/components/schemas/PresentationExport"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "data",
          "next_cursor"
        ]
      },
      "CreatePresentationExport": {
        "oneOf": [
          {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "revision": {
                "type": "integer",
                "minimum": 0,
                "maximum": 2147483647
              },
              "format": {
                "type": "string",
                "enum": [
                  "pdf",
                  "html",
                  "bibleit"
                ]
              },
              "locale": {
                "type": "string",
                "enum": [
                  "en",
                  "pt",
                  "de"
                ],
                "default": "en"
              }
            },
            "required": [
              "revision",
              "format"
            ]
          },
          {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "revision": {
                "type": "integer",
                "minimum": 0,
                "maximum": 2147483647
              },
              "format": {
                "type": "string",
                "enum": [
                  "png",
                  "jpeg"
                ]
              },
              "locale": {
                "type": "string",
                "enum": [
                  "en",
                  "pt",
                  "de"
                ],
                "default": "en"
              },
              "slide_index": {
                "type": "integer",
                "minimum": 0,
                "maximum": 1999,
                "description": "Required zero-based index in this saved revision."
              }
            },
            "required": [
              "revision",
              "format",
              "slide_index"
            ]
          }
        ],
        "description": "Explicit current saved revision. PNG/JPEG require one slide_index; other formats export the whole deck and reject slide_index. Empty presentations support only bibleit. Locale affects exported navigation labels.",
        "examples": [
          {
            "revision": 1,
            "format": "bibleit"
          },
          {
            "revision": 3,
            "format": "png",
            "slide_index": 0,
            "locale": "de"
          }
        ]
      },
      "PersonalLiveSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "account_id": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "id",
          "account_id",
          "name"
        ],
        "additionalProperties": false,
        "description": "Personal-account Reader Live resource. Uses account_id instead of organization_id; only the personal account owner can access it with current personal token authority."
      },
      "PersonalLive": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "running",
              "stopped"
            ]
          },
          "mode": {
            "type": "string",
            "const": "reader"
          },
          "paused": {
            "type": "boolean"
          },
          "sequence": {
            "type": "integer",
            "minimum": 0
          },
          "account_id": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "id",
          "account_id",
          "name",
          "status",
          "mode",
          "paused",
          "sequence"
        ],
        "additionalProperties": false,
        "description": "Personal-account Reader Live resource. Uses account_id instead of organization_id; only the personal account owner can access it with current personal token authority."
      },
      "PersonalLiveDisplay": {
        "type": "object",
        "properties": {
          "live_id": {
            "type": "string"
          },
          "status": {
            "enum": [
              "running",
              "stopped"
            ]
          },
          "paused": {
            "type": "boolean"
          },
          "showing": {
            "type": "boolean"
          },
          "sequence": {
            "type": "integer",
            "minimum": 0
          },
          "type": {
            "type": "string",
            "enum": [
              "empty",
              "scripture"
            ]
          },
          "verses": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DisplayVerse"
            }
          },
          "snapshot": {
            "type": "null"
          },
          "account_id": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "live_id",
          "status",
          "paused",
          "showing",
          "sequence",
          "account_id",
          "type",
          "verses",
          "snapshot"
        ],
        "additionalProperties": false,
        "description": "Personal-account Reader Live resource. Uses account_id instead of organization_id; only the personal account owner can access it with current personal token authority."
      },
      "PersonalLiveQueuePage": {
        "type": "object",
        "properties": {
          "live_id": {
            "type": "string"
          },
          "sequence": {
            "type": "integer",
            "minimum": 0
          },
          "data": {
            "type": "array",
            "maxItems": 100,
            "items": {
              "$ref": "#/components/schemas/LiveQueueItem"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Opaque sequence-bound cursor. Pass unchanged as after. Any intervening Live sequence change returns 409; malformed/unknown cursor returns 422."
          },
          "account_id": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "live_id",
          "account_id",
          "sequence",
          "data",
          "next_cursor"
        ],
        "additionalProperties": false,
        "description": "Personal-account Reader Live resource. Uses account_id instead of organization_id; only the personal account owner can access it with current personal token authority."
      },
      "PersonalLiveList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "maxItems": 100,
            "items": {
              "$ref": "#/components/schemas/PersonalLiveSummary"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass this value unchanged as after; null ends the collection."
          }
        },
        "required": [
          "data",
          "next_cursor"
        ],
        "additionalProperties": false,
        "description": "Personal-account Reader Live resource. Uses account_id instead of organization_id; only the personal account owner can access it with current personal token authority."
      },
      "PersonalIdentity": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "display_name": {
            "type": "string"
          },
          "handle": {
            "type": [
              "string",
              "null"
            ]
          },
          "personal_account_id": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "id",
          "display_name",
          "handle",
          "personal_account_id"
        ],
        "description": "Self-only safe user identity. No email, provider subject, internal principal, credentials or global user directory."
      },
      "PersonalAccount": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "kind": {
            "type": "string",
            "const": "personal"
          },
          "name": {
            "type": "string"
          },
          "handle": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "kind",
          "name",
          "handle"
        ]
      },
      "PersonalAccountList": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "data": {
            "type": "array",
            "maxItems": 1,
            "items": {
              "$ref": "#/components/schemas/PersonalAccount"
            }
          },
          "next_cursor": {
            "type": "null"
          }
        },
        "required": [
          "data",
          "next_cursor"
        ]
      },
      "OAuthScope": {
        "type": "string",
        "enum": [
          "identity.read",
          "offline_access",
          "translation.list",
          "translation.get",
          "translation.read",
          "translation.search",
          "live.list",
          "live.get",
          "live.create",
          "live.update",
          "live.delete"
        ]
      },
      "OAuthError": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "invalid_request",
              "invalid_client",
              "invalid_grant",
              "invalid_scope",
              "invalid_redirect_uri",
              "unsupported_response_type",
              "unsupported_grant_type",
              "access_denied",
              "slow_down",
              "temporarily_unavailable"
            ]
          }
        },
        "required": [
          "error"
        ],
        "description": "OAuth protocol error JSON, rather than REST Problem Details. Error redirects are sent only following a validated, session-bound consent decision. Invalid clients/redirects fail locally."
      },
      "OAuthToken": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "access_token": {
            "type": "string",
            "pattern": "^oa_[a-f0-9]{64}$"
          },
          "token_type": {
            "type": "string",
            "const": "Bearer"
          },
          "expires_in": {
            "type": "integer",
            "minimum": 0,
            "maximum": 900
          },
          "scope": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512
          },
          "refresh_token": {
            "type": "string",
            "pattern": "^or_[a-f0-9]{64}$"
          }
        },
        "required": [
          "access_token",
          "token_type",
          "expires_in",
          "scope"
        ],
        "description": "Opaque access token; at most 15 minutes and never beyond the grant deadline. refresh_token appears only with offline_access. Store tokens securely; hashes alone are retained server-side. Fixed grant lifetime 30 days; refreshing never extends it."
      },
      "OAuthMetadata": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "issuer": {
            "type": "string",
            "format": "uri"
          },
          "authorization_endpoint": {
            "type": "string",
            "format": "uri"
          },
          "token_endpoint": {
            "type": "string",
            "format": "uri"
          },
          "revocation_endpoint": {
            "type": "string",
            "format": "uri"
          },
          "response_types_supported": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "code"
              ]
            }
          },
          "grant_types_supported": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "authorization_code",
                "refresh_token"
              ]
            }
          },
          "token_endpoint_auth_methods_supported": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "none"
              ]
            }
          },
          "revocation_endpoint_auth_methods_supported": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "none"
              ]
            }
          },
          "code_challenge_methods_supported": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "S256"
              ]
            }
          },
          "scopes_supported": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "identity.read",
                "offline_access",
                "translation.list",
                "translation.get",
                "translation.read",
                "translation.search",
                "live.list",
                "live.get",
                "live.create",
                "live.update",
                "live.delete"
              ]
            }
          },
          "authorization_response_iss_parameter_supported": {
            "type": "boolean",
            "const": true
          }
        },
        "required": [
          "issuer",
          "authorization_endpoint",
          "token_endpoint",
          "revocation_endpoint",
          "response_types_supported",
          "grant_types_supported",
          "token_endpoint_auth_methods_supported",
          "revocation_endpoint_auth_methods_supported",
          "code_challenge_methods_supported",
          "scopes_supported",
          "authorization_response_iss_parameter_supported"
        ]
      },
      "OAuthGrant": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^[a-f0-9]{32}$"
          },
          "client_id": {
            "type": "string"
          },
          "client_name": {
            "type": "string"
          },
          "scopes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OAuthScope"
            }
          },
          "expires_at": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "id",
          "client_id",
          "client_name",
          "scopes",
          "expires_at"
        ]
      },
      "OAuthGrantList": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "data": {
            "type": "array",
            "maxItems": 20,
            "items": {
              "$ref": "#/components/schemas/OAuthGrant"
            }
          }
        },
        "required": [
          "data"
        ]
      },
      "LiveEventViewerSettings": {
        "type": "object",
        "properties": {
          "theme": {
            "enum": [
              "dark",
              "light"
            ]
          },
          "scale": {
            "type": "integer",
            "minimum": 0,
            "maximum": 3,
            "description": "Existing viewer font-size step, independent of Studio text size."
          },
          "presentation": {
            "type": "boolean"
          },
          "preset": {
            "enum": [
              "default",
              "midnight",
              "paper",
              "ocean"
            ]
          },
          "transition": {
            "enum": [
              "none",
              "fade",
              "slide",
              "slide_up",
              "slide_down",
              "zoom_in",
              "zoom_out",
              "wipe"
            ]
          }
        },
        "required": [
          "theme",
          "scale",
          "presentation"
        ],
        "additionalProperties": false
      },
      "LiveEventDesign": {
        "type": "object",
        "properties": {
          "settings": {
            "$ref": "#/components/schemas/LiveStudioSettings"
          },
          "revision": {
            "type": "integer",
            "minimum": 0
          },
          "organization": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "settings",
          "revision"
        ],
        "additionalProperties": false,
        "description": "Audience-safe Studio design. revision is independent of the Live sequence. Personal Lives use defaults and omit organization."
      },
      "LiveEventSnapshot": {
        "type": "object",
        "properties": {
          "live": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Live"
              },
              {
                "$ref": "#/components/schemas/PersonalLive"
              }
            ]
          },
          "display": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/LiveDisplay"
              },
              {
                "$ref": "#/components/schemas/PersonalLiveDisplay"
              }
            ]
          },
          "queue": {
            "oneOf": [
              {
                "type": "array",
                "maxItems": 100,
                "items": {
                  "$ref": "#/components/schemas/LiveQueueItem"
                }
              },
              {
                "type": "null"
              }
            ]
          },
          "viewer_settings": {
            "$ref": "#/components/schemas/LiveEventViewerSettings"
          },
          "design": {
            "$ref": "#/components/schemas/LiveEventDesign"
          }
        },
        "required": [
          "live",
          "display",
          "queue",
          "viewer_settings",
          "design"
        ],
        "additionalProperties": false,
        "description": "Current authorized snapshot. Queue is null in presentation mode. Presentation data is immutable snapshot metadata; editable documents, permissions, secrets, publisher identities and media paths are excluded. No audience membership or viewer statistics are created by reading."
      },
      "LiveSnapshotEvent": {
        "type": "object",
        "properties": {
          "schema_version": {
            "type": "integer",
            "const": 1
          },
          "type": {
            "type": "string",
            "enum": [
              "live.snapshot",
              "live.changed"
            ]
          },
          "resource_type": {
            "type": "string",
            "const": "live"
          },
          "resource_id": {
            "type": "string"
          },
          "sequence": {
            "type": "integer",
            "minimum": 0,
            "description": "Current Live content sequence. Studio design revision can change independently. Never use an event cursor as an If-Match validator."
          },
          "cursor": {
            "type": "string",
            "pattern": "^v1:[a-f0-9]{64}$",
            "description": "Opaque current-state comparison token covering the snapshot including independent design revisions. No durable log position, event ID, expiry promise or universal ETag."
          },
          "data": {
            "$ref": "#/components/schemas/LiveEventSnapshot"
          }
        },
        "required": [
          "schema_version",
          "type",
          "resource_type",
          "resource_id",
          "sequence",
          "cursor",
          "data"
        ],
        "additionalProperties": false
      },
      "LiveHeartbeatEvent": {
        "type": "object",
        "properties": {
          "schema_version": {
            "type": "integer",
            "const": 1
          },
          "type": {
            "type": "string",
            "enum": [
              "stream.heartbeat"
            ]
          },
          "resource_type": {
            "type": "string",
            "const": "live"
          },
          "resource_id": {
            "type": "string"
          },
          "sequence": {
            "type": "integer",
            "minimum": 0,
            "description": "Current Live content sequence. Studio design revision can change independently. Never use an event cursor as an If-Match validator."
          },
          "cursor": {
            "type": "string",
            "pattern": "^v1:[a-f0-9]{64}$",
            "description": "Opaque current-state comparison token covering the snapshot including independent design revisions. No durable log position, event ID, expiry promise or universal ETag."
          },
          "data": {
            "type": "null"
          }
        },
        "required": [
          "schema_version",
          "type",
          "resource_type",
          "resource_id",
          "sequence",
          "cursor",
          "data"
        ],
        "additionalProperties": false,
        "examples": [
          {
            "schema_version": 1,
            "type": "stream.heartbeat",
            "resource_type": "live",
            "resource_id": "sample-live",
            "sequence": 3,
            "cursor": "v1:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
            "data": null
          }
        ]
      },
      "LiveEvent": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/LiveSnapshotEvent"
          },
          {
            "$ref": "#/components/schemas/LiveHeartbeatEvent"
          }
        ],
        "description": "Event schema major version 1. Snapshot on connection/reconnection; changed snapshot when comparison differs; null-data heartbeat at wait expiry. Notifications may coalesce, repeat or be missed. Not exactly-once and no historical replay."
      }
    },
    "responses": {
      "Problem": {
        "description": "Error response. 400 malformed JSON; 401 invalid/expired/revoked token; 403 denied scope or domain policy; 404 unknown/foreign resource; 405 unsupported method; 409 quota/conflict or stopped Live; 412 stale state validator; 428 missing If-Match; 413 body too large; 415 unsupported media type; 422 invalid fields; 429 admission budget exhausted; 503 unavailable dependency.",
        "headers": {
          "X-Request-Id": {
            "schema": {
              "type": "string"
            },
            "description": "Server-generated correlation ID."
          },
          "WWW-Authenticate": {
            "schema": {
              "type": "string"
            },
            "description": "Bearer challenge on 401."
          },
          "Allow": {
            "schema": {
              "type": "string"
            },
            "description": "Supported methods on 405."
          },
          "Retry-After": {
            "schema": {
              "type": "integer",
              "minimum": 1
            },
            "description": "Seconds to wait on 429."
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      }
    },
    "parameters": {
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": false,
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 128,
          "pattern": "^[A-Za-z0-9._:-]{1,128}$"
        },
        "example": "integration-7c642889-60eb-47ed-a16c-13e290e3f054",
        "description": "Optional case-sensitive retry key, retained 24 hours from successful commit. Scoped to credential principal (stable service-token ID; personal bt_ credential; delegated OAuth grant), account and concrete method/path. Payload, If-Match, query string and Content-Type must match. JSON object key order is ignored; queue reference casing/defaults are normalized; raw upload/import bytes are hashed. Replays retain original success body, Location and ETag with a fresh X-Request-Id, after current authority/ownership/processing/library checks. Same scope/key with changed input:409 idempotency_conflict. Concurrent requests serialize; a contended retry lock can return 409 idempotency_in_progress; bounded database waits can return 503. Errors are not recorded. After expiry, a key is treated as new; original resource/job lifetime is unchanged. No key means no retry guarantee."
      }
    }
  },
  "tags": [
    {
      "name": "Organizations",
      "description": "Organization identity, active memberships and Live Studio settings."
    },
    {
      "name": "Lives",
      "description": "Live lifecycle, metadata, display, playback and workspace ownership."
    },
    {
      "name": "Translations",
      "description": "Reviewed translation editions, canonical books, organization libraries and scripture reads/search."
    },
    {
      "name": "Service tokens",
      "description": "Organization-owned credentials and conditional configuration/rotation."
    },
    {
      "name": "Discovery",
      "description": "Download the machine-readable OpenAPI contract."
    },
    {
      "name": "Scripture",
      "description": "Scripture API operations."
    },
    {
      "name": "Live controls",
      "description": "Live controls API operations."
    },
    {
      "name": "Presentations",
      "description": "Organization-owned presentation documents and conditional saved-revision CRUD. Publish explicitly using Live display controls."
    },
    {
      "name": "Presentation assets",
      "description": "Scoped raw media uploads and protected byte-range asset access."
    },
    {
      "name": "Presentation exports",
      "description": "Requester-private saved-revision export jobs and explicit one-use authorized downloads."
    },
    {
      "name": "Personal accounts",
      "description": "Self-only identity, personal account, library and Reader Live resources. Finite personal bearer authentication."
    },
    {
      "name": "OAuth",
      "description": "Operator-registered public-client delegation, browser consent, S256 PKCE, rotating refresh and grant revocation. No public dynamic registration or client-credentials/implicit/password grant."
    },
    {
      "name": "Live events",
      "description": "Versioned operator snapshots through bounded bearer-authenticated HTTP long polling. Separate from audience subscriptions."
    }
  ],
  "x-fern-explorer": false
}
