{
  "openapi": "3.1.0",
  "info": {
    "title": "Kendr Developer API",
    "version": "1.0.0",
    "summary": "One authenticated API for governed models, search surfaces, knowledge bases, connectors, marketplace packs, and usage billing.",
    "description": "Kendr lets customers create scoped API keys, use browser or app sessions, authorize OAuth clients, call admin-enabled models through OpenAI- and Anthropic-compatible formats, run unified search surfaces, manage Cloud KBs, and inspect exact credit usage. Upstream provider credentials remain in the Kendr administrator control plane and are never returned to API consumers."
  },
  "servers": [
    {
      "url": "https://api.kendr.org",
      "description": "Example production origin. Replace with your deployed Kendr host."
    }
  ],
  "tags": [
    {
      "name": "Voice",
      "description": "Realtime bidirectional PCM conversations, transcripts, and bounded session renewal."
    },
    {
      "name": "Public",
      "description": "Public catalog and developer assets."
    },
    {
      "name": "Auth",
      "description": "Hosted browser-session auth endpoints."
    },
    {
      "name": "App",
      "description": "Installed app auth, notifications, and telemetry endpoints."
    },
    {
      "name": "OAuth",
      "description": "First-party OAuth endpoints for Kendr desktop and CLI sign-in."
    },
    {
      "name": "Customer",
      "description": "Wallet, API key, and dashboard operations for authenticated customers."
    },
    {
      "name": "Enterprise",
      "description": "Organization lifecycle, members, RBAC, privacy, audit, and exports."
    },
    {
      "name": "School",
      "description": "School plan eligibility, weekly credit allowance, institution onboarding, and learner administration."
    },
    {
      "name": "Query",
      "description": "Hosted unified surface query execution."
    },
    {
      "name": "Cloud KB",
      "description": "Hosted Kendr Cloud knowledge-base indexing, sharing, retrieval, and evaluation."
    },
    {
      "name": "Models",
      "description": "Governed model discovery, generation, streaming, asynchronous video generation, and video analysis."
    },
    {
      "name": "LLM",
      "description": "Kendr-native model catalog and live response compatibility routes."
    },
    {
      "name": "Marketplace",
      "description": "Public skill and workflow pack discovery plus authenticated installation state."
    },
    {
      "name": "Developer",
      "description": "Authenticated skill-pack and workflow-pack drafting, validation, archive, and submission operations."
    },
    {
      "name": "Connectors",
      "description": "User-authorized application connectors. Provider credentials are configured separately by administrators."
    },
    {
      "name": "Billing",
      "description": "Wallet, purchases, reservations, settlement, and exact usage reporting."
    },
    {
      "name": "Admin",
      "description": "Administrator-only connector, model, routing, user, release, and governance operations."
    }
  ],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer"
      },
      "apiKeyHeader": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key"
      },
      "sessionCookie": {
        "type": "apiKey",
        "in": "cookie",
        "name": "kendr_session"
      },
      "appSessionHeader": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Kendr-Session"
      },
      "kendrOAuth": {
        "type": "oauth2",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://kendr.org/oauth/authorize",
            "tokenUrl": "https://api.kendr.org/oauth/token",
            "refreshUrl": "https://api.kendr.org/oauth/token",
            "scopes": {
              "profile": "Read your Kendr profile name and account id.",
              "email": "Read your Kendr account email address.",
              "offline_access": "Issue a refresh token so the app can keep you signed in.",
              "app": "Call Kendr app and user-authenticated endpoints as you."
            }
          }
        }
      }
    },
    "schemas": {
      "VoiceAudioInput": {
        "type": "object",
        "required": [
          "encoding",
          "sample_rate_hz",
          "channels"
        ],
        "properties": {
          "encoding": {
            "type": "string",
            "enum": [
              "pcm_s16le"
            ]
          },
          "sample_rate_hz": {
            "type": "integer",
            "minimum": 0,
            "enum": [
              16000
            ]
          },
          "channels": {
            "type": "integer",
            "minimum": 0,
            "enum": [
              1
            ]
          }
        }
      },
      "VoiceAudioOutput": {
        "type": "object",
        "required": [
          "encoding",
          "sample_rate_hz",
          "channels"
        ],
        "properties": {
          "encoding": {
            "type": "string",
            "enum": [
              "pcm_s16le"
            ]
          },
          "sample_rate_hz": {
            "type": "integer",
            "minimum": 0,
            "enum": [
              24000
            ]
          },
          "channels": {
            "type": "integer",
            "minimum": 0,
            "enum": [
              1
            ]
          }
        }
      },
      "VoiceCatalogResponse": {
        "type": "object",
        "required": [
          "object",
          "data",
          "protocol",
          "model",
          "input_audio",
          "output_audio",
          "max_duration_seconds"
        ],
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "list"
            ]
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "id",
                "object"
              ],
              "properties": {
                "id": {
                  "type": "string",
                  "example": "tiffany"
                },
                "object": {
                  "type": "string",
                  "enum": [
                    "voice"
                  ]
                }
              }
            }
          },
          "protocol": {
            "type": "string",
            "enum": [
              "kendr.voice.v1"
            ]
          },
          "model": {
            "type": "string",
            "enum": [
              "amazon.nova-2-sonic-v1:0"
            ]
          },
          "input_audio": {
            "type": "object",
            "required": [
              "encoding",
              "sample_rate_hz",
              "channels",
              "frame_bytes"
            ],
            "properties": {
              "encoding": {
                "type": "string",
                "enum": [
                  "pcm_s16le"
                ]
              },
              "sample_rate_hz": {
                "type": "integer",
                "minimum": 0,
                "enum": [
                  16000
                ]
              },
              "channels": {
                "type": "integer",
                "minimum": 0,
                "enum": [
                  1
                ]
              },
              "frame_bytes": {
                "type": "integer",
                "minimum": 0,
                "enum": [
                  1024
                ]
              }
            }
          },
          "output_audio": {
            "$ref": "#/components/schemas/VoiceAudioOutput"
          },
          "max_duration_seconds": {
            "type": "integer",
            "minimum": 30,
            "maximum": 450,
            "example": 450,
            "description": "Deployment-configured limit for this connection; renew with a fresh billed session."
          }
        }
      },
      "VoiceContextMessage": {
        "type": "object",
        "required": [
          "role",
          "content"
        ],
        "properties": {
          "role": {
            "type": "string",
            "enum": [
              "user",
              "assistant"
            ]
          },
          "content": {
            "type": "string",
            "minLength": 1,
            "maxLength": 4000,
            "description": "Nonblank text. No system role is accepted."
          }
        },
        "additionalProperties": false
      },
      "VoiceClientContext": {
        "type": "object",
        "properties": {
          "timezone": {
            "type": "string",
            "maxLength": 100,
            "default": "",
            "example": "Asia/Kolkata"
          },
          "utc_offset_minutes": {
            "type": "integer",
            "minimum": -840,
            "maximum": 840,
            "default": 0
          },
          "locale": {
            "type": "string",
            "maxLength": 40,
            "default": "",
            "example": "en-IN"
          },
          "temperature_unit": {
            "type": "string",
            "enum": [
              "",
              "celsius",
              "fahrenheit"
            ],
            "default": ""
          }
        },
        "additionalProperties": false,
        "description": "All fields are optional. Strings must not contain control characters."
      },
      "VoiceStart": {
        "type": "object",
        "required": [
          "type",
          "mode",
          "voice_id"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "start"
            ]
          },
          "mode": {
            "type": "string",
            "enum": [
              "full"
            ]
          },
          "voice_id": {
            "type": "string",
            "minLength": 1,
            "example": "tiffany",
            "description": "Required catalog ID; per-session choice, never reads or changes browser preferences."
          },
          "context": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/VoiceContextMessage"
            },
            "maxItems": 40,
            "default": [],
            "description": "Ordered history, at most 24,000 Unicode characters by default (deployment configurable). The entire start message must fit within 32 KiB."
          },
          "tools_enabled": {
            "type": "boolean",
            "default": false,
            "description": "Enable Kendr built-in server-executed tools. Custom client tools are not accepted."
          },
          "client_context": {
            "$ref": "#/components/schemas/VoiceClientContext"
          },
          "continuation_token": {
            "type": "string",
            "maxLength": 2048,
            "description": "Optional opaque token from the last ready event; expires about ten minutes after issue and must match the authenticated account and explicit voice_id. Does not restore history or bypass billing."
          }
        },
        "additionalProperties": false
      },
      "VoiceControl": {
        "type": "object",
        "required": [
          "type"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "end",
              "barge_in"
            ]
          }
        },
        "additionalProperties": false,
        "description": "End terminates the session, not an utterance. Barge-in requests playback clearing; keep sending microphone audio."
      },
      "VoiceReadyEvent": {
        "type": "object",
        "required": [
          "type",
          "protocol",
          "session_id",
          "mode",
          "model",
          "voice_id",
          "continuation_token",
          "input_audio",
          "output_audio",
          "max_duration_seconds"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "session.ready"
            ]
          },
          "protocol": {
            "type": "string",
            "enum": [
              "kendr.voice.v1"
            ]
          },
          "session_id": {
            "type": "string"
          },
          "mode": {
            "type": "string",
            "enum": [
              "full"
            ]
          },
          "model": {
            "type": "string",
            "enum": [
              "amazon.nova-2-sonic-v1:0"
            ]
          },
          "voice_id": {
            "type": "string"
          },
          "continuation_token": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "input_audio": {
            "$ref": "#/components/schemas/VoiceAudioInput"
          },
          "output_audio": {
            "$ref": "#/components/schemas/VoiceAudioOutput"
          },
          "max_duration_seconds": {
            "type": "integer",
            "minimum": 30,
            "maximum": 450,
            "example": 450,
            "description": "Deployment-configured limit for this connection; renew with a fresh billed session."
          }
        }
      },
      "VoiceStatusEvent": {
        "type": "object",
        "required": [
          "type",
          "state"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "status"
            ]
          },
          "state": {
            "type": "string",
            "enum": [
              "connecting",
              "listening",
              "thinking",
              "speaking"
            ]
          }
        }
      },
      "VoiceTranscriptEvent": {
        "type": "object",
        "required": [
          "type",
          "role",
          "text",
          "final",
          "delta"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "transcript"
            ]
          },
          "role": {
            "type": "string",
            "enum": [
              "user",
              "assistant"
            ]
          },
          "text": {
            "type": "string"
          },
          "final": {
            "type": "boolean",
            "description": "Final text replaces the current partial utterance; do not append it again."
          },
          "delta": {
            "type": "boolean",
            "description": "True means append text to the current role's partial utterance. Final events have delta=false."
          }
        }
      },
      "VoicePlaybackClearEvent": {
        "type": "object",
        "required": [
          "type"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "playback.clear"
            ]
          }
        }
      },
      "VoiceToolEvent": {
        "type": "object",
        "required": [
          "type",
          "id",
          "name",
          "state"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "tool"
            ]
          },
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "state": {
            "type": "string",
            "enum": [
              "started",
              "completed",
              "failed"
            ]
          }
        }
      },
      "VoiceErrorEvent": {
        "type": "object",
        "required": [
          "type",
          "code",
          "message",
          "retryable",
          "fatal"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "error"
            ]
          },
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "retryable": {
            "type": "boolean"
          },
          "fatal": {
            "type": "boolean",
            "description": "Terminal rejection may close with 1008 without session.ended. Nonfatal errors can precede a renewable terminal event; keep reading."
          }
        }
      },
      "VoiceUsage": {
        "type": "object",
        "required": [
          "input_speech_tokens",
          "input_text_tokens",
          "output_speech_tokens",
          "output_text_tokens",
          "total_input_tokens",
          "total_output_tokens"
        ],
        "properties": {
          "input_speech_tokens": {
            "type": "integer",
            "minimum": 0
          },
          "input_text_tokens": {
            "type": "integer",
            "minimum": 0
          },
          "output_speech_tokens": {
            "type": "integer",
            "minimum": 0
          },
          "output_text_tokens": {
            "type": "integer",
            "minimum": 0
          },
          "total_input_tokens": {
            "type": "integer",
            "minimum": 0
          },
          "total_output_tokens": {
            "type": "integer",
            "minimum": 0
          }
        },
        "description": "Cumulative provider-reported usage per connection, not settled credits."
      },
      "VoiceEndedEvent": {
        "type": "object",
        "required": [
          "type",
          "reason",
          "renewable",
          "reconnect",
          "usage",
          "billing_units"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "session.ended"
            ]
          },
          "reason": {
            "type": "string",
            "example": "max_duration"
          },
          "renewable": {
            "type": "boolean",
            "description": "Canonical renewal signal; each new connection requires authentication, start, and a new hold."
          },
          "reconnect": {
            "type": "boolean",
            "deprecated": true,
            "description": "Compatibility alias of renewable."
          },
          "usage": {
            "$ref": "#/components/schemas/VoiceUsage"
          },
          "billing_units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Nonzero audio_input_million_tokens, text_input_million_tokens, audio_output_million_tokens, text_output_million_tokens as decimal strings. Not a final charge receipt; settlement follows socket close."
          }
        }
      },
      "VoiceHttpError": {
        "type": "object",
        "required": [
          "ok",
          "error"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "enum": [
              false
            ]
          },
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "request_id": {
                "type": "string"
              },
              "details": {
                "type": [
                  "object",
                  "array",
                  "string",
                  "number",
                  "boolean",
                  "null"
                ],
                "description": "Optional additional JSON error details."
              }
            }
          }
        }
      },
      "VoiceServerEvent": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/VoiceReadyEvent"
          },
          {
            "$ref": "#/components/schemas/VoiceStatusEvent"
          },
          {
            "$ref": "#/components/schemas/VoiceTranscriptEvent"
          },
          {
            "$ref": "#/components/schemas/VoicePlaybackClearEvent"
          },
          {
            "$ref": "#/components/schemas/VoiceToolEvent"
          },
          {
            "$ref": "#/components/schemas/VoiceErrorEvent"
          },
          {
            "$ref": "#/components/schemas/VoiceEndedEvent"
          }
        ],
        "discriminator": {
          "propertyName": "type"
        }
      },
      "AudioSpeechRequest": {
        "type": "object",
        "required": [
          "model",
          "input",
          "voice"
        ],
        "additionalProperties": false,
        "properties": {
          "model": {
            "type": "string",
            "enum": [
              "kendr-tts",
              "gpt-4o-mini-tts"
            ],
            "example": "kendr-tts"
          },
          "input": {
            "type": "string",
            "minLength": 1,
            "maxLength": 4096,
            "example": "Welcome to the listening section.",
            "description": "Exact text to speak; the limit counts Unicode characters."
          },
          "voice": {
            "type": "string",
            "enum": [
              "alloy",
              "ash",
              "ballad",
              "coral",
              "echo",
              "fable",
              "nova",
              "onyx",
              "sage",
              "shimmer",
              "verse",
              "marin",
              "cedar"
            ],
            "example": "nova",
            "description": "Consistent built-in voice identity."
          },
          "instructions": {
            "type": "string",
            "maxLength": 4096,
            "example": "Speak with a natural Southern British English accent at a clear, steady exam pace.",
            "description": "Optional accent and delivery instructions, preserved upstream."
          },
          "response_format": {
            "type": "string",
            "enum": [
              "mp3",
              "wav"
            ],
            "default": "mp3"
          },
          "speed": {
            "type": "number",
            "minimum": 0.25,
            "maximum": 4.0,
            "default": 1.0
          }
        }
      },
      "AudioTranscriptionRequest": {
        "type": "object",
        "required": [
          "file",
          "model"
        ],
        "additionalProperties": false,
        "properties": {
          "file": {
            "type": "string",
            "format": "binary",
            "description": "WebM/Opus, Ogg/Opus, M4A/MP4/AAC, MP3 or WAV recording, at most 3 MiB and 120 seconds. Multipart filename and media type must match."
          },
          "model": {
            "type": "string",
            "enum": [
              "kendr-transcribe",
              "gpt-4o-mini-transcribe",
              "whisper-1"
            ],
            "example": "kendr-transcribe"
          },
          "response_format": {
            "type": "string",
            "enum": [
              "json"
            ],
            "default": "json"
          },
          "language": {
            "type": "string",
            "pattern": "^[a-z]{2}$",
            "example": "en",
            "description": "Optional ISO-639-1 language hint. No translation is performed."
          }
        }
      },
      "AudioTranscriptionResponse": {
        "type": "object",
        "required": [
          "text"
        ],
        "additionalProperties": false,
        "properties": {
          "text": {
            "type": "string",
            "description": "Unedited transcript. Empty or digitally silent recordings return an empty string."
          },
          "usage": {
            "type": "object",
            "required": [
              "type",
              "seconds"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "duration"
                ]
              },
              "seconds": {
                "type": "number",
                "minimum": 0,
                "maximum": 120
              }
            }
          }
        }
      },
      "AudioErrorEnvelope": {
        "type": "object",
        "required": [
          "error"
        ],
        "additionalProperties": false,
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "message",
              "type",
              "code",
              "param"
            ],
            "properties": {
              "message": {
                "type": "string"
              },
              "type": {
                "type": "string",
                "example": "invalid_request_error"
              },
              "code": {
                "type": "string",
                "example": "input_too_long"
              },
              "param": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          }
        }
      },
      "VideoGenerationRequest": {
        "type": "object",
        "required": [
          "prompt"
        ],
        "properties": {
          "model": {
            "type": "string",
            "enum": [
              "kendr-video"
            ],
            "default": "kendr-video",
            "description": "Provider-neutral Kendr video alias."
          },
          "video_model": {
            "type": "string",
            "enum": [
              "grok-imagine-video",
              "grok-imagine-video-1.5",
              "veo-3.1-generate-preview",
              "veo-3.1-fast-generate-preview",
              "veo-3.1-lite-generate-preview"
            ],
            "description": "Optional exact model. Omit for automatic routing. Veo uses 4/6/8 seconds (8 for 1080p), landscape or portrait, and audio. Its default duration is 8 seconds."
          },
          "prompt": {
            "type": "string",
            "minLength": 1,
            "maxLength": 32000
          },
          "duration_seconds": {
            "type": "integer",
            "minimum": 4,
            "maximum": 30,
            "default": 5
          },
          "aspect_ratio": {
            "type": "string",
            "enum": [
              "adaptive",
              "16:9",
              "4:3",
              "1:1",
              "3:4",
              "9:16",
              "21:9"
            ],
            "default": "16:9"
          },
          "resolution": {
            "type": "string",
            "enum": [
              "720p",
              "1080p"
            ],
            "default": "720p"
          },
          "generate_audio": {
            "type": "boolean",
            "default": true
          },
          "seed": {
            "type": "integer",
            "minimum": 0,
            "maximum": 4294967295
          },
          "conversation_id": {
            "type": "string",
            "maxLength": 160,
            "pattern": "^[A-Za-z0-9_-]{1,160}$"
          },
          "request_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 160,
            "pattern": "^[A-Za-z0-9][A-Za-z0-9._:/-]{0,159}$",
            "description": "Stable idempotency key body alternative. If Idempotency-Key is also sent, both values must match."
          }
        },
        "additionalProperties": false
      },
      "GeneratedVideo": {
        "type": "object",
        "required": [
          "id",
          "url",
          "title",
          "mimeType",
          "model",
          "durationSeconds",
          "aspectRatio",
          "resolution",
          "sizeBytes",
          "sha256"
        ],
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^vid_[a-f0-9]{24}$"
          },
          "url": {
            "type": "string",
            "pattern": "^/api/me/generated-videos/vid_[a-f0-9]{24}$",
            "description": "Authenticated Kendr media URL; never a provider or bucket URL."
          },
          "title": {
            "type": "string"
          },
          "mimeType": {
            "type": "string",
            "enum": [
              "video/mp4",
              "video/quicktime"
            ]
          },
          "model": {
            "type": "string",
            "enum": [
              "kendr-video"
            ]
          },
          "durationSeconds": {
            "type": "integer",
            "minimum": 4,
            "maximum": 30
          },
          "aspectRatio": {
            "type": "string"
          },
          "resolution": {
            "type": "string",
            "enum": [
              "720p",
              "1080p"
            ]
          },
          "sizeBytes": {
            "type": "integer",
            "minimum": 1
          },
          "sha256": {
            "type": "string",
            "pattern": "^[a-f0-9]{64}$"
          }
        },
        "additionalProperties": false
      },
      "VideoGenerationJob": {
        "type": "object",
        "required": [
          "id",
          "object",
          "request_id",
          "model",
          "status",
          "progress",
          "prompt",
          "duration_seconds",
          "aspect_ratio",
          "resolution",
          "generate_audio",
          "cancellation_supported",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^vjob_[a-f0-9]{24}$"
          },
          "object": {
            "type": "string",
            "enum": [
              "video.generation.job"
            ]
          },
          "request_id": {
            "type": "string"
          },
          "model": {
            "type": "string",
            "enum": [
              "kendr-video"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "submitting",
              "running",
              "succeeded",
              "failed",
              "cancelled"
            ]
          },
          "progress": {
            "type": "number",
            "minimum": 0,
            "maximum": 100
          },
          "phase": {
            "type": "string",
            "enum": [
              "finalizing"
            ],
            "description": "Present while status is running and the provider has finished rendering: Kendr is downloading, validating, and privately storing the media."
          },
          "prompt": {
            "type": "string"
          },
          "duration_seconds": {
            "type": "integer",
            "minimum": 4,
            "maximum": 30
          },
          "aspect_ratio": {
            "type": "string"
          },
          "resolution": {
            "type": "string",
            "enum": [
              "720p",
              "1080p"
            ]
          },
          "generate_audio": {
            "type": "boolean"
          },
          "seed": {
            "type": "integer",
            "minimum": 0,
            "maximum": 4294967295
          },
          "cancellation_supported": {
            "type": "boolean",
            "description": "True only before provider submission. This provider has no upstream cancellation operation."
          },
          "video": {
            "$ref": "#/components/schemas/GeneratedVideo"
          },
          "usage": {
            "type": "object",
            "required": [
              "completion_tokens",
              "total_tokens"
            ],
            "properties": {
              "completion_tokens": {
                "type": "integer",
                "minimum": 0
              },
              "total_tokens": {
                "type": "integer",
                "minimum": 0
              }
            },
            "additionalProperties": false
          },
          "error_code": {
            "type": "string"
          },
          "error_message": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "completed_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "additionalProperties": false
      },
      "VideoGenerationResponse": {
        "type": "object",
        "required": [
          "ok",
          "job"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "job": {
            "$ref": "#/components/schemas/VideoGenerationJob"
          }
        },
        "additionalProperties": false
      },
      "RewardSubmission": {
        "type": "object",
        "required": [
          "id",
          "task_key",
          "credits",
          "state"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "task_key": {
            "type": "string"
          },
          "task_title": {
            "type": "string"
          },
          "credits": {
            "type": "integer",
            "minimum": 0
          },
          "challenge_code": {
            "type": "string",
            "description": "Ownership proof that must appear in submitted public content when present."
          },
          "target_url": {
            "type": "string",
            "format": "uri"
          },
          "evidence_url": {
            "type": "string",
            "format": "uri"
          },
          "evidence_notes": {
            "type": "string"
          },
          "state": {
            "type": "string",
            "enum": [
              "draft",
              "verifying",
              "needs_review",
              "approved",
              "rejected"
            ]
          },
          "verification_method": {
            "type": "string",
            "enum": [
              "public_content_ai",
              "social_follow_review"
            ]
          },
          "verification_confidence": {
            "type": [
              "number",
              "null"
            ],
            "minimum": 0,
            "maximum": 1
          },
          "verification_summary": {
            "type": "string"
          },
          "verification_checks": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "review_notes": {
            "type": "string"
          },
          "credited_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "RewardStartRequest": {
        "type": "object",
        "required": [
          "task_key"
        ],
        "properties": {
          "task_key": {
            "type": "string"
          }
        },
        "additionalProperties": false
      },
      "RewardEvidenceRequest": {
        "type": "object",
        "required": [
          "submission_id",
          "evidence_url"
        ],
        "properties": {
          "submission_id": {
            "type": "string",
            "format": "uuid"
          },
          "evidence_url": {
            "type": "string",
            "format": "uri"
          },
          "evidence_notes": {
            "type": "string",
            "maxLength": 1000
          }
        },
        "additionalProperties": false
      },
      "AdminRewardReviewRequest": {
        "type": "object",
        "required": [
          "submission_id",
          "decision",
          "notes"
        ],
        "properties": {
          "submission_id": {
            "type": "string",
            "format": "uuid"
          },
          "decision": {
            "type": "string",
            "enum": [
              "approve",
              "reject"
            ]
          },
          "notes": {
            "type": "string",
            "maxLength": 1000
          }
        },
        "additionalProperties": false
      },
      "SocialProfile": {
        "type": "object",
        "required": [
          "key",
          "label",
          "url",
          "enabled",
          "is_custom"
        ],
        "properties": {
          "key": {
            "type": "string",
            "pattern": "^[a-z][a-z0-9_-]{0,39}$"
          },
          "label": {
            "type": "string",
            "minLength": 1,
            "maxLength": 60
          },
          "url": {
            "type": "string",
            "maxLength": 2000
          },
          "enabled": {
            "type": "boolean"
          },
          "is_custom": {
            "type": "boolean"
          }
        },
        "additionalProperties": false
      },
      "SocialProfileInput": {
        "type": "object",
        "required": [
          "key",
          "label",
          "url",
          "enabled"
        ],
        "properties": {
          "key": {
            "type": "string",
            "pattern": "^[a-z][a-z0-9_-]{0,39}$"
          },
          "label": {
            "type": "string",
            "minLength": 1,
            "maxLength": 60
          },
          "url": {
            "type": "string",
            "maxLength": 2000
          },
          "enabled": {
            "type": "boolean"
          }
        },
        "additionalProperties": false
      },
      "AdminSocialProfilesRequest": {
        "type": "object",
        "required": [
          "expected_revision",
          "profiles"
        ],
        "properties": {
          "expected_revision": {
            "type": "integer",
            "minimum": 0
          },
          "profiles": {
            "type": "array",
            "maxItems": 32,
            "items": {
              "$ref": "#/components/schemas/SocialProfileInput"
            }
          }
        },
        "additionalProperties": false
      },
      "EnterpriseSettings": {
        "type": "object",
        "properties": {
          "centralized_billing": {
            "type": "boolean"
          },
          "member_api_keys": {
            "type": "boolean"
          },
          "allow_member_kb_create": {
            "type": "boolean"
          },
          "require_verified_domain": {
            "type": "boolean"
          },
          "default_knowledge_visibility": {
            "type": "string",
            "enum": [
              "private",
              "team"
            ]
          },
          "knowledge_model_egress": {
            "type": "string",
            "enum": [
              "kendr_hosted_only",
              "kendr_hosted_or_local",
              "any_configured_provider"
            ],
            "description": "Controls whether desktop RAG may place organization passages into Kendr Hosted, local, or external BYOK model context."
          },
          "data_residency_region": {
            "type": "string",
            "enum": [
              "auto",
              "us",
              "eu",
              "in",
              "apac"
            ]
          },
          "retention_days": {
            "type": "integer",
            "minimum": 1,
            "maximum": 3650,
            "description": "Retention window for expired KB evaluations and pipeline artifacts. Enforced by the background maintenance worker."
          },
          "member_directory_visibility": {
            "type": "string",
            "enum": [
              "managers",
              "organization"
            ]
          },
          "usage_visibility": {
            "type": "string",
            "enum": [
              "billing",
              "managers"
            ]
          },
          "infrastructure_visibility": {
            "type": "string",
            "enum": [
              "managers"
            ]
          },
          "audit_retention_days": {
            "type": "integer",
            "minimum": 90,
            "maximum": 3650,
            "description": "Retention window for organization and knowledge-base audit events. Hash-chain continuity is retained through a retention anchor."
          },
          "legal_hold": {
            "type": "boolean",
            "description": "Pauses automated retention and destructive KB/storage/account operations. Only the canonical owner can change it; confirmation is always required and disabling also requires a reason."
          },
          "monthly_spend_limit_micros": {
            "type": "integer",
            "minimum": 0,
            "nullable": true
          },
          "default_member_spend_limit_micros": {
            "type": "integer",
            "minimum": 0,
            "nullable": true,
            "description": "Default monthly cap applied to members without an individual limit; owners and admins are exempt."
          },
          "connector_policy": {
            "type": "string",
            "enum": [
              "all",
              "none",
              "allowlist"
            ],
            "description": "Whether members may link app connectors: all, none, or only those in allowed_connectors."
          },
          "allowed_connectors": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Connector keys members may link when connector_policy is allowlist."
          },
          "connector_tool_policy": {
            "type": "string",
            "enum": [
              "all",
              "allowlist"
            ],
            "description": "Whether every connector action may run, or only those in allowed_connector_tools. Linking an app and being allowed to use each of its actions are separate decisions."
          },
          "allowed_connector_tools": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Approved actions as connector.tool, or connector.* for a whole connector. Enforced before the stored credential is fetched, so a blocked action never reaches the provider."
          },
          "notetaker_policy": {
            "type": "string",
            "enum": [
              "all",
              "managers",
              "none"
            ],
            "description": "Who may send the Kendr Notetaker into a meeting."
          },
          "routing_policy": {
            "type": "object",
            "description": "Organization-portal routing controls: allowed_providers, denied_providers, allowed_models, denied_models, and the whole-number max_cost_premium_percent. Router API normalizes the percentage to its fractional cost guard. A request may narrow this policy but never widen it; advanced region, retention, live-SLO, and search-path controls are not editable through this portal contract yet."
          },
          "mcp_policy": {
            "type": "string",
            "enum": [
              "all",
              "none",
              "allowlist"
            ],
            "description": "Whether members may add remote MCP servers: all, none, or only hosts matching allowed_mcp_domains."
          },
          "allowed_mcp_domains": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Host patterns (supports *.suffix) members' MCP servers must match when mcp_policy is allowlist."
          },
          "allow_personal_billing_fallback": {
            "type": "boolean"
          }
        },
        "additionalProperties": false
      },
      "EnterpriseOrganization": {
        "type": "object",
        "required": [
          "id",
          "name",
          "plan",
          "status",
          "seat_limit"
        ],
        "properties": {
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "plan": {
            "type": "string",
            "enum": [
              "enterprise"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "suspended",
              "closed"
            ]
          },
          "owner_user_id": {
            "type": "integer"
          },
          "billing_user_id": {
            "type": "integer"
          },
          "seat_limit": {
            "type": "integer"
          },
          "allowed_domain": {
            "type": "string"
          },
          "wallet_type": {
            "type": "string",
            "enum": [
              "organization"
            ]
          },
          "credit_balance_micros": {
            "type": "integer"
          },
          "credit_balance_exact": {
            "type": "number"
          },
          "settings": {
            "$ref": "#/components/schemas/EnterpriseSettings"
          }
        }
      },
      "UnifiedQueryRequest": {
        "type": "object",
        "required": [
          "surface",
          "query"
        ],
        "properties": {
          "surface": {
            "type": "string",
            "enum": [
              "web_search",
              "ai_search",
              "web_answer",
              "google_search",
              "google_images",
              "google_news",
              "google_maps",
              "google_places",
              "google_routes",
              "google_shopping",
              "google_scholar",
              "google_videos",
              "google_autocomplete",
              "google_flights",
              "google_hotels"
            ],
            "description": "Kendr surface to run. The web_search surface runs Kendr Web Search; provider-native search is reached through the model APIs instead."
          },
          "query": {
            "type": "string",
            "description": "Primary query string."
          },
          "params": {
            "type": "object",
            "additionalProperties": true,
            "description": "Optional surface parameters such as gl, hl, page, location, or travel dates."
          }
        },
        "examples": [
          {
            "surface": "google_search",
            "query": "best llm observability tools",
            "params": {
              "gl": "us",
              "hl": "en",
              "page": 1
            }
          }
        ]
      },
      "UnifiedQueryResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "surface": {
            "type": "string"
          },
          "credits_charged": {
            "type": "integer"
          },
          "remaining_credits": {
            "type": "integer"
          },
          "data": {
            "type": "object",
            "additionalProperties": true
          },
          "normalized": {
            "type": "object",
            "additionalProperties": true
          }
        }
      },
      "InputTokenPriceTier": {
        "type": "object",
        "required": [
          "min_input_tokens"
        ],
        "properties": {
          "min_input_tokens": {
            "type": "integer",
            "minimum": 1,
            "description": "Inclusive input-token count at which this provider rate tier applies. Use 200001 for provider rules expressed as more than 200K tokens."
          },
          "input_per_million": {
            "type": "number",
            "minimum": 0
          },
          "cached_input_per_million": {
            "type": "number",
            "minimum": 0
          },
          "cache_write_per_million": {
            "type": "number",
            "minimum": 0
          },
          "output_per_million": {
            "type": "number",
            "minimum": 0
          },
          "reasoning_per_million": {
            "type": "number",
            "minimum": 0
          }
        },
        "anyOf": [
          {
            "required": [
              "input_per_million"
            ]
          },
          {
            "required": [
              "cached_input_per_million"
            ]
          },
          {
            "required": [
              "cache_write_per_million"
            ]
          },
          {
            "required": [
              "output_per_million"
            ]
          },
          {
            "required": [
              "reasoning_per_million"
            ]
          }
        ],
        "description": "Provider token-price overrides for the whole request once the inclusive input threshold is reached. At least one rate override is required; omitted rate fields inherit the base card.",
        "additionalProperties": false
      },
      "HostedLlmPricingTier": {
        "type": "object",
        "required": [
          "min_input_tokens"
        ],
        "properties": {
          "min_input_tokens": {
            "type": "integer",
            "minimum": 1,
            "description": "Inclusive input-token count at which this customer credit quote applies."
          },
          "credits_per_million_input": {
            "type": "number",
            "nullable": true
          },
          "credits_per_million_cached_input": {
            "type": "number",
            "nullable": true
          },
          "credits_per_million_output": {
            "type": "number",
            "nullable": true
          }
        },
        "description": "Account-aware credit prices for the whole request at a higher input-context tier.",
        "additionalProperties": false
      },
      "HostedLlmModel": {
        "type": "object",
        "properties": {
          "alias": {
            "type": "string",
            "example": "kc-glm-5"
          },
          "display_name": {
            "type": "string"
          },
          "provider": {
            "type": "string",
            "example": "Kendr Hosted"
          },
          "available": {
            "type": "boolean"
          },
          "supports_streaming": {
            "type": "boolean",
            "description": "True only when the current catalog has an executable, attested route that can satisfy a streamed request for this alias or managed pool."
          },
          "status_reason": {
            "type": "string"
          },
          "credits_per_million_input": {
            "type": "number",
            "nullable": true
          },
          "credits_per_million_cached_input": {
            "type": "number",
            "nullable": true
          },
          "credits_per_million_output": {
            "type": "number",
            "nullable": true
          },
          "pricing_tiers": {
            "type": "array",
            "description": "Higher-context customer credit quotes. min_input_tokens is inclusive and the selected tier applies to all token categories in the request.",
            "items": {
              "$ref": "#/components/schemas/HostedLlmPricingTier"
            }
          }
        },
        "additionalProperties": true
      },
      "HostedLlmModelsResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "models": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HostedLlmModel"
            }
          }
        }
      },
      "HostedLlmResponseRequest": {
        "type": "object",
        "required": [
          "model"
        ],
        "properties": {
          "model": {
            "type": "string",
            "example": "kendr-intelligent"
          },
          "input": {
            "description": "Text or structured input for Responses-compatible calls."
          },
          "messages": {
            "type": "array",
            "description": "Chat-style messages for clients that already track roles.",
            "items": {
              "type": "object",
              "properties": {
                "role": {
                  "type": "string",
                  "enum": [
                    "system",
                    "user",
                    "assistant"
                  ]
                },
                "content": {
                  "type": "string"
                }
              },
              "required": [
                "role",
                "content"
              ]
            }
          },
          "instructions": {
            "type": "string"
          },
          "max_output_tokens": {
            "type": "integer",
            "minimum": 1
          },
          "stream": {
            "type": "boolean",
            "default": false,
            "description": "Set true for server-sent events or false for one complete JSON response. Exact-model routes stream provider deltas. Kendr managed routes first emit route/search progress, then stream deltas from the selected model when the selected tool path supports safe live relay. After the first answer delta, disconnecting detaches the subscriber while Kendr finishes and settles the idempotent request; retrieve that result with the same key instead of starting a second generation."
          },
          "web_search": {
            "type": "boolean",
            "description": "Tri-state web-search control. Omit it to let Kendr decide from the current request, set true to request current web context, or set false to prohibit web search for this request."
          },
          "request_id": {
            "type": "string",
            "description": "Optional idempotency key. The Idempotency-Key header is also accepted."
          },
          "conversation_id": {
            "type": "string",
            "description": "Stable conversation identifier. Kendr managed routing keeps a compatible selected model sticky for later turns with the same identifier."
          },
          "client_context": {
            "type": "object",
            "description": "Optional per-request locale context used by Kendr Core. Precise location is ignored unless share_location is explicitly true.",
            "properties": {
              "timezone": {
                "type": "string",
                "example": "Asia/Kolkata"
              },
              "utc_offset_minutes": {
                "type": "integer",
                "minimum": -840,
                "maximum": 840
              },
              "locale": {
                "type": "string",
                "example": "en-IN"
              },
              "temperature_unit": {
                "type": "string",
                "enum": [
                  "celsius",
                  "fahrenheit"
                ]
              },
              "share_location": {
                "type": "boolean",
                "default": false
              },
              "location": {
                "type": "object",
                "additionalProperties": true
              }
            },
            "additionalProperties": false
          },
          "tools": {
            "type": "array",
            "description": "Server-executed tool declarations. Use {\"type\": \"kendr_app\", \"selection\": \"auto\"} to offer the signed-in user's connected, chat-capable OAuth applications for relevance-based selection; credentials remain server-side and only selected applications are invoked. Use {\"type\": \"kendr_mcp\", \"server_id\": \"mcp_...\"} to activate a specific registered MCP server that is enabled and trusted (managed at /api/me/mcp-servers). At most 8 MCP servers per request. Kendr-hosted read-only app bridges use portable function calling on compatible tool-capable routes. Other connected apps, Kendr MCP, and provider-native MCP tools require an OpenAI Responses route; Kendr managed routes restrict candidates automatically. Other provider-native tool declarations pass through to compatible routes. Server-executed connected-app combinations return one complete response so credentials and hidden tool progress remain private. Arbitrary custom MCP combinations also return one complete response so a disconnect cannot repeat a mutation or lose a hidden provider tool trace. Pending server tool calls are never returned.",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "response_format": {
            "type": "object",
            "additionalProperties": true
          },
          "text": {
            "type": "object",
            "description": "OpenAI Responses text options. `text.format` with type json_schema (name, schema, optional strict) or json_object requests structured output; Kendr maps it onto response_format, routes only to models that can produce it, and validates the answer against the schema. An explicit response_format takes precedence.",
            "additionalProperties": true
          },
          "optimization": {
            "type": "object",
            "description": "Compatibility optimizer policy for exact-model, Flash, Research, and custom routes. Kendr Intelligent and Kendr Coder always use Kendr Optimizer; their Direct variants always preserve the original context.",
            "properties": {
              "profile": {
                "type": "string",
                "enum": [
                  "general",
                  "code",
                  "research"
                ],
                "default": "code",
                "description": "Selects which details the optimizer treats as critical for the task."
              },
              "mode": {
                "type": "string",
                "enum": [
                  "off",
                  "balanced",
                  "aggressive"
                ],
                "default": "off",
                "description": "balanced is recommended; aggressive targets a smaller retained context and denser output. Legacy auto and safe values are accepted and treated as balanced."
              },
              "engine": {
                "type": "string",
                "enum": [
                  "kendr_optimizer"
                ],
                "default": "kendr_optimizer",
                "description": "The embedded, verification-gated Kendr Optimizer portfolio."
              },
              "allow_lossy_context": {
                "type": "boolean",
                "default": false,
                "description": "Must be true before extractive tool-output pruning can run. The embedded optimizer otherwise uses only representation-safe and recoverable engines."
              }
            },
            "additionalProperties": false
          },
          "metadata": {
            "type": "object",
            "description": "Application metadata and optional Kendr request controls.",
            "properties": {
              "require_web_search": {
                "type": "boolean",
                "default": false,
                "description": "When true, fail instead of answering without current web context."
              },
              "intelligent_reroute": {
                "type": "boolean",
                "default": false,
                "description": "When true for a Kendr managed route, ignore a compatible sticky route and classify/select a model again."
              }
            },
            "additionalProperties": true
          }
        },
        "anyOf": [
          {
            "required": [
              "input"
            ]
          },
          {
            "required": [
              "messages"
            ]
          }
        ],
        "additionalProperties": true
      },
      "HostedLlmResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "request_id": {
            "type": "string"
          },
          "model": {
            "type": "string"
          },
          "output_text": {
            "type": "string"
          },
          "credits_charged": {
            "type": "integer"
          },
          "credit_micros_charged": {
            "type": "integer"
          },
          "remaining_credits": {
            "type": "integer"
          },
          "remaining_credit_micros": {
            "type": "integer"
          },
          "usage": {
            "type": "object",
            "additionalProperties": true
          },
          "kendr_usage": {
            "type": "object",
            "description": "Final credit settlement metadata.",
            "additionalProperties": true
          },
          "kendr_optimization": {
            "type": "object",
            "nullable": true,
            "description": "Applied strategies, quality checks, estimated token and credit savings, and optimizer version. Final kendr_usage remains the authoritative settled charge.",
            "properties": {
              "enabled": {
                "type": "boolean"
              },
              "profile": {
                "type": "string",
                "enum": [
                  "general",
                  "code",
                  "research"
                ]
              },
              "requested_mode": {
                "type": "string",
                "enum": [
                  "off",
                  "balanced",
                  "aggressive"
                ]
              },
              "resolved_mode": {
                "type": "string",
                "enum": [
                  "off",
                  "balanced",
                  "aggressive"
                ]
              },
              "engine": {
                "type": "string",
                "enum": [
                  "kendr_optimizer"
                ],
                "description": "Engine that produced the optimization."
              },
              "engine_version": {
                "type": "string"
              },
              "original_input_tokens_estimated": {
                "type": "integer",
                "minimum": 0
              },
              "optimized_input_tokens_estimated": {
                "type": "integer",
                "minimum": 0
              },
              "estimated_input_tokens_avoided": {
                "type": "integer",
                "minimum": 0
              },
              "estimated_credits_saved_micros": {
                "type": "integer",
                "minimum": 0,
                "description": "Rate-card-priced estimated input saving in microcredits. Do not subtract it again from the settled charge."
              },
              "estimated_credits_without_optimization_micros": {
                "type": "integer",
                "minimum": 0,
                "description": "Comparable estimated charge without the measured input reduction."
              },
              "compression_ratio_bps": {
                "type": "integer",
                "minimum": 0,
                "maximum": 10000
              },
              "strategies": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "skipped_strategies": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "quality_guard": {
                "type": "object",
                "additionalProperties": true
              },
              "fallback_reason": {
                "type": "string",
                "nullable": true
              },
              "latency_ms": {
                "type": "integer",
                "minimum": 0
              },
              "shadow": {
                "type": "boolean",
                "description": "When true, this is a preview-only receipt and no optimized request or saving was applied."
              },
              "optimizer_receipt_version": {
                "type": "string"
              },
              "optimizer_status": {
                "type": "string",
                "enum": [
                  "applied",
                  "skipped",
                  "shadow",
                  "reverted"
                ]
              },
              "verified_savings": {
                "type": "boolean",
                "description": "False for preflight estimates until paired provider usage establishes a verified baseline."
              },
              "cache_impact": {
                "type": "string",
                "enum": [
                  "none",
                  "prefix_preserved",
                  "unknown",
                  "invalidated"
                ]
              },
              "warnings": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            },
            "additionalProperties": true
          },
          "kendr_routing": {
            "type": "object",
            "nullable": true,
            "description": "Managed-routing metadata: the selected Kendr model alias, task category, reason code, confidence, requested tools, latency, and fallback outcome.",
            "additionalProperties": true
          },
          "kendr_core": {
            "type": "object",
            "description": "Read-only Kendr Core utilities selected for the turn and their completion status.",
            "additionalProperties": true
          }
        }
      },
      "HostedAnthropicMessageRequest": {
        "type": "object",
        "required": [
          "model",
          "messages"
        ],
        "properties": {
          "model": {
            "type": "string",
            "example": "kendr-intelligent"
          },
          "messages": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "role",
                "content"
              ],
              "properties": {
                "role": {
                  "type": "string",
                  "enum": [
                    "user",
                    "assistant"
                  ]
                },
                "content": {}
              },
              "additionalProperties": true
            }
          },
          "system": {
            "description": "Anthropic-compatible system text or content blocks."
          },
          "max_tokens": {
            "type": "integer",
            "minimum": 1
          },
          "stream": {
            "type": "boolean",
            "default": false
          },
          "web_search": {
            "type": "boolean",
            "description": "Omit for automatic selection, set true to request search, or false to prohibit it."
          },
          "tools": {
            "type": "array",
            "description": "Server-executed tool declarations. Use {\"type\": \"kendr_app\", \"selection\": \"auto\"} for relevance-based selection from the signed-in user's connected, chat-capable OAuth applications, or {\"type\": \"kendr_mcp\", \"server_id\": \"mcp_...\"} for one specific registered trusted MCP server. Application credentials remain server-side. Same rules as /v1/responses: at most 8 MCP servers; Kendr-hosted read-only app bridges can use compatible tool-capable routes, while other connected apps and MCP servers require OpenAI Responses; pending server tool calls are never returned to the client.",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "metadata": {
            "type": "object",
            "properties": {
              "require_web_search": {
                "type": "boolean",
                "default": false
              },
              "intelligent_reroute": {
                "type": "boolean",
                "default": false
              }
            },
            "additionalProperties": true
          },
          "optimization": {
            "type": "object",
            "description": "Compatibility optimizer policy for exact-model, Flash, Research, and custom routes. Kendr Intelligent and Kendr Coder always use Kendr Optimizer; their Direct variants always preserve the original context.",
            "properties": {
              "profile": {
                "type": "string",
                "enum": [
                  "general",
                  "code",
                  "research"
                ],
                "default": "code"
              },
              "mode": {
                "type": "string",
                "enum": [
                  "off",
                  "balanced",
                  "aggressive"
                ],
                "default": "off"
              },
              "engine": {
                "type": "string",
                "enum": [
                  "kendr_optimizer"
                ],
                "default": "kendr_optimizer"
              },
              "allow_lossy_context": {
                "type": "boolean",
                "default": false,
                "description": "Must be true before extractive tool-output pruning can run."
              }
            },
            "additionalProperties": false
          }
        },
        "additionalProperties": true
      },
      "AiPreferencesRequest": {
        "type": "object",
        "properties": {
          "default_model": {
            "type": "string",
            "description": "Default enabled Kendr model alias."
          },
          "mode_models": {
            "type": "object",
            "description": "Mode-to-alias overrides, for example chat, research, code, or agentic.",
            "additionalProperties": {
              "type": "string"
            }
          }
        },
        "additionalProperties": false
      },
      "VoicePreferenceRequest": {
        "type": "object",
        "required": [
          "voice_id"
        ],
        "properties": {
          "voice_id": {
            "type": "string",
            "enum": [
              "ambre",
              "amy",
              "arjun",
              "beatrice",
              "carlos",
              "carolina",
              "florian",
              "kiara",
              "lennart",
              "leo",
              "lorenzo",
              "lupe",
              "matthew",
              "olivia",
              "tiffany",
              "tina"
            ],
            "description": "Allowlisted Amazon Nova 2 Sonic voice identifier."
          }
        },
        "additionalProperties": false
      },
      "VoiceOption": {
        "type": "object",
        "required": [
          "id",
          "name",
          "locale",
          "language",
          "style",
          "polyglot"
        ],
        "properties": {
          "id": {
            "type": "string",
            "enum": [
              "ambre",
              "amy",
              "arjun",
              "beatrice",
              "carlos",
              "carolina",
              "florian",
              "kiara",
              "lennart",
              "leo",
              "lorenzo",
              "lupe",
              "matthew",
              "olivia",
              "tiffany",
              "tina"
            ]
          },
          "name": {
            "type": "string"
          },
          "locale": {
            "type": "string"
          },
          "language": {
            "type": "string"
          },
          "style": {
            "type": "string"
          },
          "polyglot": {
            "type": "boolean"
          }
        },
        "additionalProperties": false
      },
      "UserRoutingProfile": {
        "type": "object",
        "required": [
          "id",
          "alias",
          "model_aliases",
          "slot",
          "revision"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "alias": {
            "type": "string",
            "minLength": 3,
            "maxLength": 32,
            "pattern": "^[a-z][a-z0-9]*(?:[-_][a-z0-9]+)*$",
            "description": "Immutable account-scoped model alias. Kendr and kc prefixes are reserved."
          },
          "model_aliases": {
            "type": "array",
            "minItems": 2,
            "maxItems": 12,
            "uniqueItems": true,
            "items": {
              "type": "string"
            },
            "description": "Enabled physical model aliases eligible for Kendr-controlled routing. Array order does not select the routing algorithm."
          },
          "model_count": {
            "type": "integer",
            "minimum": 2,
            "maximum": 12
          },
          "slot": {
            "type": "integer",
            "minimum": 1,
            "maximum": 5
          },
          "revision": {
            "type": "integer",
            "minimum": 1
          },
          "last_used_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "additionalProperties": false
      },
      "CreateUserRoutingProfileRequest": {
        "type": "object",
        "required": [
          "alias",
          "model_aliases"
        ],
        "properties": {
          "alias": {
            "type": "string",
            "minLength": 3,
            "maxLength": 32,
            "pattern": "^[a-z][a-z0-9]*(?:[-_][a-z0-9]+)*$",
            "example": "frontier-picks"
          },
          "model_aliases": {
            "type": "array",
            "minItems": 2,
            "maxItems": 12,
            "uniqueItems": true,
            "items": {
              "type": "string"
            },
            "example": [
              "kc-gpt-5.6-sol",
              "kc-claude-sonnet-5"
            ]
          }
        },
        "additionalProperties": false
      },
      "UpdateUserRoutingProfileRequest": {
        "type": "object",
        "description": "Replace the eligible model set. Supply the latest revision in this body or in the If-Match request header; omitting both returns HTTP 428.",
        "required": [
          "model_aliases"
        ],
        "properties": {
          "revision": {
            "type": "integer",
            "minimum": 1,
            "example": 1,
            "description": "Revision returned by the latest read. Optional when the same revision is supplied in If-Match; stale revisions return HTTP 409."
          },
          "model_aliases": {
            "type": "array",
            "minItems": 2,
            "maxItems": 12,
            "uniqueItems": true,
            "items": {
              "type": "string"
            },
            "example": [
              "kc-gpt-5.6-sol",
              "kc-claude-sonnet-5"
            ]
          }
        },
        "additionalProperties": false
      },
      "CreateMeetingNotetakerRequest": {
        "type": "object",
        "required": [
          "meeting_url"
        ],
        "properties": {
          "title": {
            "type": "string",
            "maxLength": 300
          },
          "meeting_url": {
            "type": "string",
            "format": "uri",
            "description": "Public HTTPS Meet, Zoom, Teams, or Webex join URL."
          },
          "scheduled_start": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "scheduled_end": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "expected_duration_seconds": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 60,
            "maximum": 10800,
            "default": 3600
          },
          "bot_name": {
            "type": "string",
            "maxLength": 120,
            "description": "Visible participant name. Defaults to '<owner first name> Kendr Notetaker'."
          },
          "language": {
            "type": "string",
            "maxLength": 32,
            "default": "auto"
          },
          "summary_template": {
            "type": "string",
            "enum": [
              "standard",
              "executive",
              "standup",
              "sales",
              "interview"
            ],
            "default": "standard"
          },
          "summary_instructions": {
            "type": "string",
            "maxLength": 2000,
            "description": "Optional formatting emphasis. Evidence, uncertainty, and the required output schema always take precedence."
          },
          "notetaker_enabled": {
            "type": "boolean",
            "default": true
          },
          "save_to_sources": {
            "type": "boolean",
            "default": true
          },
          "project_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "calendar_event_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "participants": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "name"
              ],
              "properties": {
                "name": {
                  "type": "string"
                },
                "email": {
                  "type": "string",
                  "format": "email"
                }
              },
              "additionalProperties": false
            }
          }
        },
        "additionalProperties": false
      },
      "MeetingNotetaker": {
        "type": "object",
        "required": [
          "id",
          "title",
          "meeting_url",
          "platform",
          "status",
          "join_state",
          "expected_duration_seconds",
          "notetaker_enabled"
        ],
        "properties": {
          "id": {
            "type": "string",
            "example": "mtg_0123456789abcdef"
          },
          "can_manage": {
            "type": "boolean",
            "description": "False when the completed report is visible through a shared Project; owner-only start, stop, and delete actions are unavailable."
          },
          "title": {
            "type": "string"
          },
          "meeting_url": {
            "type": "string",
            "format": "uri"
          },
          "platform": {
            "type": "string",
            "enum": [
              "google_meet",
              "zoom",
              "microsoft_teams",
              "webex"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "scheduled",
              "joining",
              "recording",
              "processing",
              "completed",
              "failed",
              "cancelled"
            ]
          },
          "join_state": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "launch_unconfirmed",
                  "connecting",
                  "waiting_room",
                  "joined",
                  "recording_permission_prompt",
                  "recording_permission_denied",
                  "recording"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Safe normalized capture lifecycle used for accurate join and admission guidance."
          },
          "scheduled_start": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "scheduled_end": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "expected_duration_seconds": {
            "type": "integer",
            "minimum": 60,
            "maximum": 10800
          },
          "notetaker_enabled": {
            "type": "boolean",
            "description": "Whether the owner has enabled capture for this scheduled meeting."
          },
          "started_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "ended_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "duration_seconds": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0
          },
          "participants": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "transcript": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "mom": {
            "type": "object"
          },
          "source_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "private_notes": {
            "type": "string",
            "maxLength": 12000,
            "description": "Owner-only working notes; omitted for shared-project readers."
          },
          "summary_template": {
            "type": "string",
            "enum": [
              "standard",
              "executive",
              "standup",
              "sales",
              "interview"
            ]
          },
          "summary_instructions": {
            "type": "string",
            "maxLength": 2000
          },
          "error_message": {
            "type": "string"
          }
        },
        "additionalProperties": true
      },
      "MeetingComment": {
        "type": "object",
        "required": [
          "id",
          "meeting_id",
          "user_id",
          "body",
          "created_at",
          "can_delete"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "meeting_id": {
            "type": "string"
          },
          "user_id": {
            "type": "integer"
          },
          "author_name": {
            "type": "string"
          },
          "author_email": {
            "type": "string",
            "format": "email"
          },
          "body": {
            "type": "string",
            "maxLength": 4000
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "can_delete": {
            "type": "boolean"
          }
        },
        "additionalProperties": false
      },
      "PurchaseVerificationRequest": {
        "type": "object",
        "required": [
          "razorpay_order_id",
          "razorpay_payment_id",
          "razorpay_signature"
        ],
        "properties": {
          "razorpay_order_id": {
            "type": "string"
          },
          "razorpay_payment_id": {
            "type": "string"
          },
          "razorpay_signature": {
            "type": "string",
            "description": "Razorpay checkout signature verified by Kendr."
          }
        },
        "additionalProperties": false
      },
      "ConnectorStartRequest": {
        "type": "object",
        "properties": {
          "redirect_after": {
            "type": "string",
            "default": "/app/connectors",
            "description": "Safe Kendr path opened after OAuth completes."
          }
        },
        "additionalProperties": true
      },
      "AdminUserUpsertRequest": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "minimum": 1,
            "description": "Existing user id. Omit to create an account."
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "full_name": {
            "type": "string",
            "maxLength": 120
          },
          "account_role": {
            "type": "string",
            "enum": [
              "customer",
              "admin"
            ]
          },
          "is_active": {
            "type": "boolean",
            "default": true
          },
          "email_verified": {
            "type": "boolean",
            "description": "Administrator attestation that this account may claim its current email address. New administrator-created accounts default to verified; changing an email without this field resets verification."
          },
          "password": {
            "type": "string",
            "description": "Optional replacement password. Never returned."
          },
          "initial_credits": {
            "type": "integer",
            "minimum": 0,
            "maximum": 10000000,
            "description": "Creation-time credit grant."
          }
        },
        "additionalProperties": false
      },
      "AdminCreditAdjustmentRequest": {
        "type": "object",
        "required": [
          "user_id",
          "credits_delta"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "minimum": 1
          },
          "credits_delta": {
            "type": "integer",
            "description": "Non-zero signed whole-credit adjustment."
          },
          "description": {
            "type": "string",
            "maxLength": 240
          }
        },
        "additionalProperties": false
      },
      "AdminModelConnectorRequest": {
        "type": "object",
        "required": [
          "provider_key",
          "display_name",
          "adapter_kind",
          "enabled"
        ],
        "properties": {
          "provider_key": {
            "type": "string"
          },
          "display_name": {
            "type": "string"
          },
          "adapter_kind": {
            "type": "string"
          },
          "base_url": {
            "type": "string",
            "format": "uri",
            "description": "Empty uses the native provider default."
          },
          "region": {
            "type": "string",
            "description": "Required by Amazon Bedrock."
          },
          "api_key": {
            "type": "string",
            "description": "Replacement provider credential. Never returned."
          },
          "clear_api_key": {
            "type": "boolean",
            "default": false
          },
          "enabled": {
            "type": "boolean"
          },
          "config": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "additionalProperties": false
      },
      "AdminProviderModelAccessRequest": {
        "type": "object",
        "required": [
          "enabled"
        ],
        "description": "An enabled-only patch preserves pricing. Supplying any base pricing field replaces the complete base card: token and hybrid modes require input_per_million and output_per_million, while unit and hybrid modes require valid unit_prices. Omit input_token_price_tiers to preserve existing tiers; send an empty array to clear them.",
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "pricing_mode": {
            "type": "string",
            "enum": [
              "token",
              "unit",
              "hybrid"
            ],
            "default": "token"
          },
          "input_per_million": {
            "type": "number",
            "minimum": 0,
            "description": "Required with output_per_million for a token or hybrid base-card replacement."
          },
          "cached_input_per_million": {
            "type": "number",
            "minimum": 0
          },
          "cache_write_per_million": {
            "type": "number",
            "minimum": 0
          },
          "output_per_million": {
            "type": "number",
            "minimum": 0,
            "description": "Required with input_per_million for a token or hybrid base-card replacement."
          },
          "unit_prices": {
            "type": "object",
            "description": "Provider prices keyed by billable unit. Required and non-empty for unit mode; hybrid mode must provide its applicable token and unit prices.",
            "additionalProperties": {
              "type": "number",
              "minimum": 0
            }
          },
          "input_token_price_tiers": {
            "type": "array",
            "description": "Optional higher-context provider rates. Each min_input_tokens boundary is inclusive. Omit this field to preserve current tiers; send [] to clear them.",
            "items": {
              "$ref": "#/components/schemas/InputTokenPriceTier"
            }
          },
          "currency": {
            "type": "string",
            "default": "USD"
          }
        },
        "additionalProperties": false
      },
      "AdminAppConnectorProviderRequest": {
        "type": "object",
        "properties": {
          "client_id": {
            "type": "string"
          },
          "client_secret": {
            "type": "string",
            "description": "Replacement OAuth secret. Never returned."
          },
          "clear_client_secret": {
            "type": "boolean",
            "default": false
          },
          "tenant_id": {
            "type": "string",
            "description": "Microsoft tenant id, domain, common, organizations, or consumers."
          },
          "auth_url": {
            "type": "string",
            "format": "uri"
          },
          "token_url": {
            "type": "string",
            "format": "uri"
          }
        },
        "additionalProperties": false
      },
      "AdminAppConnectorRequest": {
        "type": "object",
        "properties": {
          "display_name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "category": {
            "type": "string"
          },
          "icon": {
            "type": "string"
          },
          "auth_url": {
            "type": "string",
            "format": "uri"
          },
          "token_url": {
            "type": "string",
            "format": "uri"
          },
          "env_prefix": {
            "type": "string"
          },
          "enabled": {
            "type": "boolean"
          },
          "requires_admin_consent": {
            "type": "boolean"
          },
          "sort_order": {
            "type": "integer",
            "minimum": 1,
            "maximum": 10000
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "additionalProperties": false
      },
      "AdminModelUpdateRequest": {
        "type": "object",
        "required": [
          "alias"
        ],
        "properties": {
          "alias": {
            "type": "string",
            "description": "Must match the path alias."
          },
          "enabled": {
            "type": "boolean"
          },
          "intelligent_candidate": {
            "type": "boolean"
          },
          "verifier": {
            "type": "boolean",
            "description": "Legacy catalog role; managed routing does not invoke an answer verifier."
          },
          "route_id": {
            "type": "string",
            "format": "uuid"
          },
          "route_status": {
            "type": "string",
            "enum": [
              "staged",
              "healthy",
              "degraded",
              "disabled",
              "retired"
            ]
          }
        },
        "additionalProperties": false
      },
      "AdminRoutingPolicyRequest": {
        "type": "object",
        "required": [
          "policy",
          "sha256",
          "signature"
        ],
        "properties": {
          "policy": {
            "type": "object",
            "additionalProperties": true
          },
          "sha256": {
            "type": "string",
            "description": "Hex SHA-256 of the canonical policy artifact."
          },
          "signature": {
            "type": "string",
            "description": "Deployment-approved artifact signature."
          },
          "activate": {
            "type": "boolean",
            "default": false
          }
        },
        "additionalProperties": false
      },
      "AdminRoutingCostControlUpdate": {
        "type": "object",
        "required": [
          "product_alias",
          "strategy",
          "provider_strategy",
          "max_request_cost_usd",
          "max_fallback_cost_usd",
          "fast_chat_max_output_tokens",
          "general_max_output_tokens",
          "coding_max_output_tokens",
          "thinking_max_output_tokens",
          "research_max_output_tokens",
          "agentic_max_output_tokens",
          "vision_max_output_tokens",
          "document_max_output_tokens",
          "fast_chat_reasoning_effort",
          "general_reasoning_effort",
          "coding_reasoning_effort",
          "thinking_reasoning_effort",
          "research_reasoning_effort",
          "agentic_reasoning_effort",
          "vision_reasoning_effort",
          "response_verbosity",
          "response_cache_enabled",
          "response_cache_ttl_seconds"
        ],
        "properties": {
          "product_alias": {
            "type": "string",
            "enum": [
              "kendr-intelligent",
              "kendr-coder",
              "kendr-research",
              "kendr-flash"
            ]
          },
          "strategy": {
            "type": "string",
            "enum": [
              "economy",
              "balanced",
              "quality",
              "fastest"
            ]
          },
          "provider_strategy": {
            "type": "string",
            "enum": [
              "price",
              "price_first",
              "balanced",
              "latency"
            ],
            "description": "Physical-provider posture after logical model selection. price_first (platform default) lets routes within price_first_band_ratio of the cheapest qualified route compete on reliability, then latency, then price; routes outside the band remain fallbacks only. price picks the cheapest qualified route outright; balanced and latency use the weighted ranking."
          },
          "price_first_band_ratio": {
            "type": "number",
            "minimum": 0,
            "maximum": 1,
            "default": 0.05,
            "description": "Fraction above the cheapest qualified route's estimated cost that still counts as price-competitive under price_first (0.05 = five percent). Ignored by the other provider strategies. Every cost-control response (the list, the PATCH echo and plan snapshots) returns it as a JSON number as well."
          },
          "max_request_cost_usd": {
            "type": "number",
            "nullable": true,
            "exclusiveMinimum": 0,
            "maximum": 1000
          },
          "max_fallback_cost_usd": {
            "type": "number",
            "nullable": true,
            "exclusiveMinimum": 0,
            "maximum": 1000
          },
          "fast_chat_max_output_tokens": {
            "type": "integer",
            "minimum": 1,
            "maximum": 32768
          },
          "general_max_output_tokens": {
            "type": "integer",
            "minimum": 1,
            "maximum": 32768
          },
          "coding_max_output_tokens": {
            "type": "integer",
            "minimum": 1,
            "maximum": 32768
          },
          "thinking_max_output_tokens": {
            "type": "integer",
            "minimum": 1,
            "maximum": 32768
          },
          "research_max_output_tokens": {
            "type": "integer",
            "minimum": 1,
            "maximum": 32768
          },
          "agentic_max_output_tokens": {
            "type": "integer",
            "minimum": 1,
            "maximum": 32768
          },
          "vision_max_output_tokens": {
            "type": "integer",
            "minimum": 1,
            "maximum": 32768
          },
          "document_max_output_tokens": {
            "type": "integer",
            "minimum": 1,
            "maximum": 32768,
            "description": "Output floor applied when the request positively asks for a document, report, guide, or artifact (PDF/DOCX/PPTX). Never lowers a higher task cap; clamped to what the pool can execute."
          },
          "fast_chat_reasoning_effort": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "none",
              "low",
              "medium",
              "high",
              null
            ]
          },
          "general_reasoning_effort": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "none",
              "low",
              "medium",
              "high",
              null
            ]
          },
          "coding_reasoning_effort": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "none",
              "low",
              "medium",
              "high",
              null
            ]
          },
          "thinking_reasoning_effort": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "none",
              "low",
              "medium",
              "high",
              null
            ]
          },
          "research_reasoning_effort": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "none",
              "low",
              "medium",
              "high",
              null
            ]
          },
          "agentic_reasoning_effort": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "none",
              "low",
              "medium",
              "high",
              null
            ]
          },
          "vision_reasoning_effort": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "none",
              "low",
              "medium",
              "high",
              null
            ]
          },
          "response_verbosity": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "low",
              "medium",
              "high",
              null
            ]
          },
          "response_cache_enabled": {
            "type": "boolean",
            "description": "Exact-input reuse for the same user and billing account. Search, tools, images, and continuations remain ineligible."
          },
          "response_cache_ttl_seconds": {
            "type": "integer",
            "minimum": 1,
            "maximum": 86400
          }
        },
        "additionalProperties": false
      },
      "AdminOptimizerSettingsRequest": {
        "type": "object",
        "required": [
          "enabled",
          "shadow",
          "latency_budget_ms",
          "min_gain_tokens",
          "min_gain_percent_bps",
          "preserve_recent_messages",
          "max_tool_result_chars"
        ],
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "shadow": {
            "type": "boolean"
          },
          "latency_budget_ms": {
            "type": "integer",
            "minimum": 1,
            "maximum": 1000
          },
          "min_gain_tokens": {
            "type": "integer",
            "minimum": 0,
            "maximum": 1000000
          },
          "min_gain_percent_bps": {
            "type": "integer",
            "minimum": 0,
            "maximum": 10000
          },
          "preserve_recent_messages": {
            "type": "integer",
            "minimum": 0,
            "maximum": 512
          },
          "max_tool_result_chars": {
            "type": "integer",
            "minimum": 1024,
            "maximum": 2097152
          }
        },
        "additionalProperties": false
      },
      "DeveloperSkillPackDraftRequest": {
        "type": "object",
        "required": [
          "slug"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "minimum": 1,
            "description": "Existing draft id. Omit to create a draft."
          },
          "slug": {
            "type": "string",
            "maxLength": 80
          },
          "label": {
            "type": "string",
            "maxLength": 200
          },
          "description": {
            "type": "string",
            "maxLength": 800
          },
          "author": {
            "type": "string",
            "maxLength": 160
          },
          "version": {
            "type": "string",
            "default": "0.1.0"
          },
          "homepage": {
            "type": "string",
            "format": "uri"
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "skill_markdown": {
            "type": "string",
            "description": "SKILL.md source generated into the canonical archive."
          },
          "mcp_json": {
            "type": "string",
            "description": "JSON text for mcp.json."
          },
          "server_py": {
            "type": "string",
            "description": "Optional Python MCP server source."
          },
          "server_filename": {
            "type": "string",
            "description": "Simple .py filename used with server_py."
          }
        },
        "additionalProperties": false
      },
      "DeveloperWorkflowPackDraftRequest": {
        "type": "object",
        "required": [
          "slug"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "minimum": 1,
            "description": "Existing draft id. Omit to create a draft."
          },
          "slug": {
            "type": "string",
            "maxLength": 80
          },
          "label": {
            "type": "string",
            "maxLength": 200
          },
          "description": {
            "type": "string",
            "maxLength": 800
          },
          "author": {
            "type": "string",
            "maxLength": 160
          },
          "version": {
            "type": "string",
            "default": "0.1.0"
          },
          "homepage": {
            "type": "string",
            "format": "uri"
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "workflows": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "workflow_json": {
            "type": "string",
            "description": "A JSON object or array of workflow definitions."
          },
          "required_skill_packs": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "optional_skill_packs": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "required_mcp_servers": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "optional_mcp_servers": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "additionalProperties": false
      },
      "CloudKnowledgeBaseSource": {
        "type": "object",
        "required": [
          "kind",
          "value"
        ],
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "attachment",
              "file",
              "link"
            ]
          },
          "value": {
            "type": "string",
            "description": "URL, attachment reference, or inline text payload."
          },
          "label": {
            "type": "string"
          },
          "content": {
            "type": "string",
            "description": "Optional extracted/plain text supplied by a trusted client."
          },
          "bytes_total": {
            "type": "integer",
            "minimum": 0
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true
          },
          "access_policy": {
            "$ref": "#/components/schemas/CloudKnowledgeBaseSourceAccessPolicy"
          }
        },
        "additionalProperties": true
      },
      "CloudKnowledgeBaseSourceAccessPolicy": {
        "type": "object",
        "properties": {
          "visibility": {
            "type": "string",
            "enum": [
              "inherit",
              "restricted"
            ]
          },
          "user_ids": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "organization_roles": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "owner",
                "admin",
                "billing",
                "member",
                "viewer"
              ]
            }
          }
        },
        "additionalProperties": false
      },
      "CloudKnowledgeBasePipelineConfig": {
        "type": "object",
        "description": "Staged RAG pipeline configuration for extraction, cleaning, chunking, embeddings, vector storage, reranking, and answer model.",
        "additionalProperties": true
      },
      "CloudKnowledgeBaseAccessPolicy": {
        "type": "object",
        "properties": {
          "visibility": {
            "type": "string",
            "enum": [
              "private",
              "team",
              "shared-link"
            ]
          },
          "owner_id": {
            "type": "string"
          },
          "team_ids": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "user_ids": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "role": {
            "type": "string",
            "enum": [
              "viewer",
              "editor"
            ]
          },
          "allow_public_link": {
            "type": "boolean"
          },
          "source_permissions_enabled": {
            "type": "boolean"
          }
        },
        "additionalProperties": true
      },
      "CloudKnowledgeBaseCreateRequest": {
        "type": "object",
        "required": [
          "name",
          "sources"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "sources": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CloudKnowledgeBaseSource"
            }
          },
          "retrieval_algorithm": {
            "type": "string",
            "enum": [
              "auto",
              "lexical",
              "vector",
              "hybrid"
            ]
          },
          "pipeline_config": {
            "$ref": "#/components/schemas/CloudKnowledgeBasePipelineConfig"
          },
          "access_policy": {
            "$ref": "#/components/schemas/CloudKnowledgeBaseAccessPolicy"
          },
          "vector_connection_id": {
            "type": "integer",
            "minimum": 1
          },
          "storage_mode": {
            "type": "string",
            "enum": [
              "managed",
              "mirror",
              "private"
            ]
          }
        },
        "additionalProperties": true
      },
      "CloudKnowledgeBase": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "indexing",
              "ready",
              "failed",
              "cancelled"
            ]
          },
          "progress_percent": {
            "type": "integer"
          },
          "chunk_count": {
            "type": "integer"
          },
          "retrieval_algorithm": {
            "type": "string"
          },
          "vector_store_provider": {
            "type": "string",
            "example": "kendr-cloud"
          },
          "storage_mode": {
            "type": "string",
            "enum": [
              "managed",
              "mirror",
              "private"
            ]
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "additionalProperties": true
      },
      "CloudKnowledgeBaseTestRequest": {
        "type": "object",
        "required": [
          "query"
        ],
        "properties": {
          "query": {
            "type": "string"
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 12
          },
          "consumer_provider": {
            "type": "string",
            "description": "Downstream provider receiving retrieved passages, when used by a desktop run."
          },
          "consumer_mode": {
            "type": "string",
            "enum": [
              "hosted",
              "local",
              "api",
              "knowledge_test"
            ]
          },
          "purpose": {
            "type": "string",
            "enum": [
              "desktop_run",
              "desktop_knowledge_test",
              "knowledge_test"
            ]
          }
        }
      },
      "CloudKnowledgeBaseTestResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "kb_id": {
            "type": "string"
          },
          "evaluation_id": {
            "type": "string"
          },
          "query": {
            "type": "string"
          },
          "hits": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "diagnostics": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "answer": {
            "type": "string"
          },
          "credit_micros_charged": {
            "type": "integer"
          }
        },
        "additionalProperties": true
      },
      "CreateApiKeyRequest": {
        "type": "object",
        "required": [
          "label"
        ],
        "properties": {
          "label": {
            "type": "string",
            "description": "Human-friendly key label such as Production or Staging."
          },
          "environment": {
            "type": "string",
            "enum": [
              "production",
              "development"
            ],
            "default": "production"
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "models:read",
                "models:invoke",
                "connectors:read",
                "connectors:invoke",
                "usage:read",
                "knowledge:read",
                "knowledge:write",
                "meetings:read",
                "meetings:write",
                "releases:write",
                "audit:read",
                "admin:read",
                "admin:write"
              ]
            },
            "description": "Omit to use the standard models, connectors, and usage scopes. The admin:read and admin:write scopes cover platform administration and are refused unless the account is a Kendr administrator."
          }
        }
      },
      "AppPasswordAuthRequest": {
        "type": "object",
        "required": [
          "email",
          "password"
        ],
        "properties": {
          "email": {
            "type": "string",
            "format": "email"
          },
          "password": {
            "type": "string"
          },
          "full_name": {
            "type": "string"
          }
        }
      },
      "OtpRequest": {
        "type": "object",
        "required": [
          "email"
        ],
        "properties": {
          "email": {
            "type": "string",
            "format": "email"
          },
          "purpose": {
            "type": "string",
            "enum": [
              "login",
              "signup",
              "login_or_signup"
            ],
            "default": "login_or_signup"
          }
        }
      },
      "OtpVerifyRequest": {
        "type": "object",
        "required": [
          "email",
          "code"
        ],
        "properties": {
          "email": {
            "type": "string",
            "format": "email"
          },
          "code": {
            "type": "string",
            "minLength": 6,
            "maxLength": 6
          },
          "full_name": {
            "type": "string"
          },
          "purpose": {
            "type": "string",
            "enum": [
              "login",
              "signup",
              "login_or_signup"
            ],
            "default": "login_or_signup"
          },
          "referral_code": {
            "type": "string"
          },
          "terms_accepted": {
            "type": "boolean"
          }
        }
      },
      "AppInstallationRequest": {
        "type": "object",
        "properties": {
          "installation_id": {
            "type": "string"
          },
          "installationId": {
            "type": "string"
          },
          "platform": {
            "type": "string"
          },
          "app_version": {
            "type": "string"
          },
          "appVersion": {
            "type": "string"
          },
          "channel": {
            "type": "string"
          },
          "source": {
            "type": "string"
          }
        },
        "additionalProperties": true
      },
      "AppSkillPackInstallationRequest": {
        "type": "object",
        "required": [
          "slug",
          "install_source"
        ],
        "properties": {
          "slug": {
            "type": "string",
            "example": "docker"
          },
          "pack_id": {
            "type": "string",
            "example": "docker"
          },
          "label": {
            "type": "string",
            "example": "Docker MCP"
          },
          "description": {
            "type": "string"
          },
          "author": {
            "type": "string",
            "example": "Kendr"
          },
          "version": {
            "type": "string",
            "example": "0.1.0"
          },
          "installed_version": {
            "type": "string",
            "example": "0.1.0"
          },
          "homepage": {
            "type": "string",
            "format": "uri"
          },
          "install_source": {
            "type": "string",
            "format": "uri"
          },
          "archive_sha256": {
            "type": "string"
          },
          "enabled": {
            "type": "boolean"
          },
          "installation_id": {
            "type": "string"
          },
          "mcp_server_names": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "skills": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "label": {
                  "type": "string"
                },
                "description": {
                  "type": "string"
                },
                "relative_path": {
                  "type": "string"
                },
                "enabled": {
                  "type": "boolean"
                }
              }
            }
          }
        },
        "additionalProperties": true
      },
      "AppSkillPackInstallation": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "pack_slug": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "version": {
            "type": "string"
          },
          "installed_version": {
            "type": "string"
          },
          "install_source": {
            "type": "string"
          },
          "enabled": {
            "type": "boolean"
          },
          "skills": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "last_synced_at": {
            "type": "string"
          }
        },
        "additionalProperties": true
      },
      "AppWorkflowPackInstallationRequest": {
        "type": "object",
        "required": [
          "slug",
          "install_source"
        ],
        "properties": {
          "slug": {
            "type": "string",
            "example": "devops-workflows"
          },
          "pack_id": {
            "type": "string",
            "example": "devops-workflows"
          },
          "label": {
            "type": "string",
            "example": "DevOps Workflows"
          },
          "description": {
            "type": "string"
          },
          "author": {
            "type": "string",
            "example": "Kendr"
          },
          "version": {
            "type": "string",
            "example": "0.1.0"
          },
          "installed_version": {
            "type": "string",
            "example": "0.1.0"
          },
          "homepage": {
            "type": "string",
            "format": "uri"
          },
          "install_source": {
            "type": "string",
            "format": "uri"
          },
          "archive_sha256": {
            "type": "string"
          },
          "enabled": {
            "type": "boolean"
          },
          "installation_id": {
            "type": "string"
          },
          "required_skill_packs": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "optional_skill_packs": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "required_mcp_servers": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "optional_mcp_servers": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "workflows": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          }
        },
        "additionalProperties": true
      },
      "AppWorkflowPackInstallation": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "pack_slug": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "version": {
            "type": "string"
          },
          "installed_version": {
            "type": "string"
          },
          "install_source": {
            "type": "string"
          },
          "enabled": {
            "type": "boolean"
          },
          "dependency_status": {
            "type": "object",
            "additionalProperties": true
          },
          "workflows": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "last_synced_at": {
            "type": "string"
          }
        },
        "additionalProperties": true
      },
      "AppWorkflowBundle": {
        "type": "object",
        "properties": {
          "schema_version": {
            "type": "integer",
            "default": 1
          },
          "source": {
            "type": "string",
            "example": "desktop"
          },
          "installation_id": {
            "type": "string"
          },
          "client_updated_at": {
            "type": "string"
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "workflows": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          }
        },
        "additionalProperties": true
      },
      "AppActivityRequest": {
        "type": "object",
        "properties": {
          "installation_id": {
            "type": "string"
          },
          "installationId": {
            "type": "string"
          },
          "platform": {
            "type": "string"
          },
          "app_version": {
            "type": "string"
          },
          "appVersion": {
            "type": "string"
          },
          "source": {
            "type": "string"
          }
        },
        "additionalProperties": true
      },
      "AppErrorReportRequest": {
        "type": "object",
        "required": [
          "message"
        ],
        "properties": {
          "installation_id": {
            "type": "string"
          },
          "installationId": {
            "type": "string"
          },
          "platform": {
            "type": "string"
          },
          "app_version": {
            "type": "string"
          },
          "appVersion": {
            "type": "string"
          },
          "error_name": {
            "type": "string"
          },
          "errorName": {
            "type": "string"
          },
          "error_code": {
            "type": "string"
          },
          "errorCode": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "details": {
            "type": "string"
          },
          "stack_trace": {
            "type": "string"
          },
          "stackTrace": {
            "type": "string"
          },
          "severity": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email"
          }
        },
        "additionalProperties": true
      },
      "AppFeedbackRequest": {
        "type": "object",
        "required": [
          "message"
        ],
        "properties": {
          "installation_id": {
            "type": "string"
          },
          "installationId": {
            "type": "string"
          },
          "platform": {
            "type": "string"
          },
          "app_version": {
            "type": "string"
          },
          "appVersion": {
            "type": "string"
          },
          "category": {
            "type": "string"
          },
          "rating": {
            "type": "integer"
          },
          "message": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email"
          }
        },
        "additionalProperties": true
      },
      "CreatePurchaseRequest": {
        "type": "object",
        "properties": {
          "package_id": {
            "type": "integer",
            "description": "Configured package id to purchase."
          },
          "package_slug": {
            "type": "string",
            "description": "Configured package slug to purchase."
          }
        },
        "anyOf": [
          {
            "required": [
              "package_id"
            ]
          },
          {
            "required": [
              "package_slug"
            ]
          }
        ]
      },
      "RevokeApiKeyRequest": {
        "type": "object",
        "required": [
          "api_key_id"
        ],
        "properties": {
          "api_key_id": {
            "type": "integer",
            "description": "Identifier of the customer API key to revoke."
          }
        }
      },
      "OAuthTokenResponse": {
        "type": "object",
        "properties": {
          "access_token": {
            "type": "string"
          },
          "token_type": {
            "type": "string",
            "example": "Bearer"
          },
          "expires_in": {
            "type": "integer"
          },
          "refresh_token": {
            "type": "string"
          },
          "scope": {
            "type": "string"
          }
        }
      },
      "OAuthDeviceCodeResponse": {
        "type": "object",
        "properties": {
          "device_code": {
            "type": "string"
          },
          "user_code": {
            "type": "string"
          },
          "verification_uri": {
            "type": "string",
            "format": "uri"
          },
          "verification_uri_complete": {
            "type": "string",
            "format": "uri"
          },
          "expires_in": {
            "type": "integer"
          },
          "interval": {
            "type": "integer"
          },
          "scope": {
            "type": "string"
          }
        }
      },
      "PublicPricingContract": {
        "type": "object",
        "required": [
          "markup",
          "credit_expiration_policy",
          "purchased_credit_expiration_policy",
          "purchased_credits_expire",
          "promotional_credit_expiration_policy",
          "credit_top_up_policy",
          "monthly_plans"
        ],
        "properties": {
          "markup": {
            "type": "object",
            "required": [
              "percent",
              "basis",
              "scope",
              "policy"
            ],
            "properties": {
              "percent": {
                "type": "number",
                "enum": [
                  5
                ]
              },
              "direct_percent": {
                "type": "number",
                "enum": [
                  5
                ]
              },
              "intelligent_percent": {
                "type": "number",
                "enum": [
                  5
                ]
              },
              "basis": {
                "type": "string",
                "enum": [
                  "provider_cost"
                ]
              },
              "scope": {
                "type": "string",
                "enum": [
                  "all_models_and_routing_modes"
                ]
              },
              "policy": {
                "type": "string",
                "enum": [
                  "fixed_5_percent"
                ]
              }
            },
            "additionalProperties": false
          },
          "credit_expiration_policy": {
            "type": "string",
            "enum": [
              "purchased_never_expire_promotional_grant_specific"
            ]
          },
          "purchased_credit_expiration_policy": {
            "type": "string",
            "enum": [
              "never_expires"
            ]
          },
          "purchased_credits_expire": {
            "type": "boolean",
            "enum": [
              false
            ]
          },
          "promotional_credit_expiration_policy": {
            "type": "string",
            "enum": [
              "grant_specific"
            ]
          },
          "promotional_credit_default_expiration_days": {
            "type": "integer",
            "minimum": 1
          },
          "credit_top_up_policy": {
            "type": "object",
            "required": [
              "currency",
              "bands"
            ],
            "properties": {
              "currency": {
                "type": "string",
                "enum": [
                  "USD"
                ]
              },
              "bands": {
                "type": "array",
                "minItems": 4,
                "items": {
                  "type": "object",
                  "required": [
                    "minimum_usd",
                    "maximum_usd",
                    "credits_per_usd"
                  ],
                  "properties": {
                    "minimum_usd": {
                      "type": "number",
                      "minimum": 0
                    },
                    "maximum_usd": {
                      "anyOf": [
                        {
                          "type": "number",
                          "minimum": 0
                        },
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "credits_per_usd": {
                      "type": "integer",
                      "minimum": 1
                    }
                  },
                  "additionalProperties": false
                }
              }
            },
            "additionalProperties": false
          },
          "monthly_plans": {
            "type": "array",
            "minItems": 4,
            "items": {
              "type": "object",
              "required": [
                "slug",
                "name",
                "price_usd",
                "credits"
              ],
              "properties": {
                "slug": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "price_usd": {
                  "type": "integer",
                  "minimum": 1
                },
                "credits": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "additionalProperties": false
            }
          }
        },
        "additionalProperties": false
      }
    }
  },
  "paths": {
    "/api/health": {
      "get": {
        "tags": [
          "Public"
        ],
        "summary": "Read the Kendr health status",
        "responses": {
          "200": {
            "description": "Health payload returned.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "503": {
            "description": "Service is unhealthy."
          }
        }
      }
    },
    "/api/catalog": {
      "get": {
        "tags": [
          "Public"
        ],
        "summary": "Read the public Kendr catalog",
        "description": "Returns active packages, enabled surfaces, SDK resources, and the customer-facing API guide.",
        "responses": {
          "200": {
            "description": "Catalog loaded.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "pricing": {
                      "$ref": "#/components/schemas/PublicPricingContract"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    },
    "/api/openapi.json": {
      "get": {
        "tags": [
          "Public"
        ],
        "summary": "Download the Kendr OpenAPI document",
        "responses": {
          "200": {
            "description": "OpenAPI JSON document.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    },
    "/api/kb/cloud": {
      "get": {
        "tags": [
          "Cloud KB"
        ],
        "summary": "List hosted Kendr Cloud knowledge bases visible to the caller",
        "security": [
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          },
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Cloud knowledge bases returned.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "knowledge_bases": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CloudKnowledgeBase"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Caller is not authenticated."
          }
        }
      },
      "post": {
        "tags": [
          "Cloud KB"
        ],
        "summary": "Create a hosted Kendr Cloud knowledge base and queue indexing",
        "security": [
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          },
          {
            "sessionCookie": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CloudKnowledgeBaseCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Cloud KB created and indexing queued."
          },
          "402": {
            "description": "Not enough credits for indexing."
          }
        }
      }
    },
    "/api/kb/cloud/estimate": {
      "post": {
        "tags": [
          "Cloud KB"
        ],
        "summary": "Estimate credits and storage for a hosted cloud KB build",
        "security": [
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          },
          {
            "sessionCookie": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CloudKnowledgeBaseCreateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Estimate returned."
          }
        }
      }
    },
    "/api/kb/cloud/{kb_id}/test": {
      "post": {
        "tags": [
          "Cloud KB"
        ],
        "summary": "Run a retrieval test query with explainable chunk scores",
        "security": [
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "kb_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CloudKnowledgeBaseTestRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Retrieval test completed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CloudKnowledgeBaseTestResponse"
                }
              }
            }
          },
          "402": {
            "description": "Not enough credits for query/rerank/answer usage."
          }
        }
      }
    },
    "/api/kb/cloud/{kb_id}/rebuild": {
      "post": {
        "tags": [
          "Cloud KB"
        ],
        "summary": "Queue a hosted KB rebuild from the requested pipeline stage",
        "security": [
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "kb_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Rebuild queued."
          }
        }
      }
    },
    "/api/kb/cloud/{kb_id}/access": {
      "post": {
        "tags": [
          "Cloud KB"
        ],
        "summary": "Update hosted KB access policy and source-access metadata",
        "security": [
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "kb_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "access_policy": {
                    "$ref": "#/components/schemas/CloudKnowledgeBaseAccessPolicy"
                  },
                  "source_access": {
                    "type": "object",
                    "additionalProperties": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Access policy updated."
          }
        }
      }
    },
    "/api/kb/cloud/{kb_id}/sources": {
      "get": {
        "tags": [
          "Cloud KB"
        ],
        "summary": "List sources permitted by the caller's knowledge-base and source ACLs",
        "security": [
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "kb_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Permitted sources returned."
          }
        }
      },
      "post": {
        "tags": [
          "Cloud KB"
        ],
        "summary": "Add sources and queue durable hosted indexing",
        "security": [
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "kb_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/CloudKnowledgeBaseSource"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "sources": {
                        "type": "array",
                        "items": {
                          "$ref": "#/components/schemas/CloudKnowledgeBaseSource"
                        }
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Sources created and indexing queued."
          }
        }
      }
    },
    "/api/kb/cloud/{kb_id}/sources/{source_id}": {
      "put": {
        "tags": [
          "Cloud KB"
        ],
        "summary": "Update a source, its ACL, and queue reindexing when content changed",
        "security": [
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "kb_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "source_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CloudKnowledgeBaseSource"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Source updated."
          }
        }
      },
      "delete": {
        "tags": [
          "Cloud KB"
        ],
        "summary": "Delete a source and its tenant-filtered vectors",
        "security": [
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "kb_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "source_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Source deleted."
          }
        }
      }
    },
    "/api/kb/cloud/{kb_id}/sources/{source_id}/file": {
      "get": {
        "tags": [
          "Cloud KB"
        ],
        "summary": "Open or download the original file stored behind a source",
        "description": "Streams the uploaded original, or the indexed text for note sources. Only PDF, image, and plain-text media render inline; every other format downloads as an opaque attachment.",
        "security": [
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "kb_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "source_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "download",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "encoding",
            "in": "query",
            "required": false,
            "description": "Set to `base64` for a JSON envelope instead of raw bytes.",
            "schema": {
              "type": "string",
              "enum": [
                "base64"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Source file returned."
          },
          "404": {
            "description": "Source not found, or it has no stored file."
          },
          "413": {
            "description": "The stored file exceeds the Sources download limit."
          }
        }
      }
    },
    "/api/kb/cloud/{kb_id}/sources/{source_id}/reindex": {
      "post": {
        "tags": [
          "Cloud KB"
        ],
        "summary": "Queue a durable, retryable reindex job for one source",
        "security": [
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "kb_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "source_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Source reindex queued."
          }
        }
      }
    },
    "/api/kb/cloud/{kb_id}/pipeline/artifacts": {
      "get": {
        "tags": [
          "Cloud KB"
        ],
        "summary": "Inspect retained extraction, cleaning, chunking, and embedding artifacts",
        "security": [
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "kb_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "stage",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Pipeline artifacts returned."
          }
        }
      }
    },
    "/api/auth/session": {
      "get": {
        "tags": [
          "Auth"
        ],
        "summary": "Inspect the hosted browser session",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Session status returned.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    },
    "/api/auth/otp/request": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "Send a browser sign-in or signup verification code through AWS SES",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OtpRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Authentication code sent."
          },
          "400": {
            "description": "Email address was invalid or rate limited."
          },
          "502": {
            "description": "AWS SES did not accept the email."
          }
        }
      }
    },
    "/api/auth/otp/verify": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "Verify a browser authentication code and create a session cookie",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OtpVerifyRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Code verified and browser session cookie set."
          },
          "400": {
            "description": "Code was invalid or expired."
          }
        }
      }
    },
    "/api/auth/register": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "Register with email and password and receive a browser session cookie",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AppPasswordAuthRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "User registered and browser session cookie set."
          },
          "400": {
            "description": "Registration payload was invalid."
          }
        }
      }
    },
    "/api/auth/login": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "Authenticate with email and password and refresh the browser session cookie",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AppPasswordAuthRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "User authenticated and browser session cookie set."
          },
          "400": {
            "description": "Login payload was invalid."
          }
        }
      }
    },
    "/api/auth/logout": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "Log out the hosted browser session",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Browser session logged out."
          }
        }
      }
    },
    "/api/app/auth/register": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "Register from an installed app and receive an app session token",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AppPasswordAuthRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "User registered and app session returned."
          },
          "400": {
            "description": "Registration payload was invalid."
          }
        }
      }
    },
    "/api/app/auth/login": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "Authenticate from an installed app and receive an app session token",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AppPasswordAuthRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "User authenticated and app session returned."
          },
          "400": {
            "description": "Login payload was invalid."
          }
        }
      }
    },
    "/api/app/auth/otp/request": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "Send an installed-app login code through AWS SES",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OtpRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Login code sent."
          },
          "400": {
            "description": "Email address was invalid or rate limited."
          },
          "502": {
            "description": "AWS SES did not accept the email."
          }
        }
      }
    },
    "/api/app/auth/otp/verify": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "Verify an installed-app login code and return an app session token",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OtpVerifyRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Code verified and app session returned."
          },
          "400": {
            "description": "Code was invalid or expired."
          }
        }
      }
    },
    "/api/app/auth/session": {
      "get": {
        "tags": [
          "Auth"
        ],
        "summary": "Inspect the current app session",
        "security": [
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "App session status returned."
          },
          "401": {
            "description": "App session header or OAuth bearer token is missing or invalid."
          }
        }
      }
    },
    "/api/app/auth/profile": {
      "put": {
        "tags": [
          "Auth"
        ],
        "summary": "Sync the installed app profile name to Kendr",
        "security": [
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "full_name": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Profile updated and app session returned."
          },
          "401": {
            "description": "App session header or OAuth bearer token is missing or invalid."
          }
        }
      }
    },
    "/api/app/auth/verify-email": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "Confirm an email address from a mailed verification link",
        "description": "Consumes the single-use token from the verification email and marks the address as proved. Takes no session: the link is usually opened on a different device from the one the account is signed in on. Until an address is confirmed, artifact grants, project invitations and organization invitations addressed to it stay pending.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "token"
                ],
                "properties": {
                  "token": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Address confirmed, or already confirmed."
          },
          "400": {
            "description": "The link was invalid, expired, or already used for another address."
          }
        }
      }
    },
    "/api/app/auth/verify-email/send": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "Send a fresh email verification link",
        "description": "Replaces any outstanding link for the signed-in account. Rate limited to one request per minute.",
        "security": [
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Verification email sent, or the address was already confirmed."
          },
          "400": {
            "description": "Asked again inside the resend cooldown."
          },
          "401": {
            "description": "App session header or OAuth bearer token is missing or invalid."
          },
          "502": {
            "description": "The verification email could not be delivered."
          }
        }
      }
    },
    "/api/app/auth/logout": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "Log out an installed app session",
        "security": [
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "App session logged out."
          },
          "401": {
            "description": "App session header or OAuth bearer token is missing or invalid."
          }
        }
      }
    },
    "/api/app/notifications": {
      "get": {
        "tags": [
          "App"
        ],
        "summary": "Read active app notifications",
        "description": "Returns the currently active notification set. Authenticated callers may receive notifications scoped to authenticated users.",
        "responses": {
          "200": {
            "description": "Notifications returned."
          }
        }
      }
    },
    "/api/app/installations": {
      "post": {
        "tags": [
          "App"
        ],
        "summary": "Record an app installation event",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AppInstallationRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Installation event recorded."
          },
          "400": {
            "description": "Installation payload was invalid."
          }
        }
      }
    },
    "/api/workflows/catalog": {
      "get": {
        "tags": [
          "Marketplace"
        ],
        "summary": "List public workflow packs",
        "description": "Returns installable workflow packs with dependency metadata for skill packs and MCP servers.",
        "responses": {
          "200": {
            "description": "Workflow catalog returned."
          }
        }
      }
    },
    "/api/workflows/packs/{slug}/archive": {
      "get": {
        "tags": [
          "Marketplace"
        ],
        "summary": "Download a workflow-pack archive",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Workflow pack archive returned."
          },
          "404": {
            "description": "Workflow pack not found."
          }
        }
      }
    },
    "/api/app/skills/installations": {
      "get": {
        "tags": [
          "App"
        ],
        "summary": "List skill packs installed by the current Kendr account",
        "security": [
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          },
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Skill installation records returned.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "installations": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/AppSkillPackInstallation"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "App session header or OAuth bearer token is missing or invalid."
          }
        }
      },
      "post": {
        "tags": [
          "App"
        ],
        "summary": "Create or update a hosted skill-pack installation record",
        "security": [
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          },
          {
            "sessionCookie": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AppSkillPackInstallationRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Skill installation record synchronized."
          },
          "400": {
            "description": "Skill installation payload was invalid."
          },
          "401": {
            "description": "App session header or OAuth bearer token is missing or invalid."
          }
        }
      }
    },
    "/api/app/workflows/installations": {
      "get": {
        "tags": [
          "App"
        ],
        "summary": "List workflow packs installed by the current Kendr account",
        "security": [
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          },
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Workflow installation records returned.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "installations": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/AppWorkflowPackInstallation"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "App session header or OAuth bearer token is missing or invalid."
          }
        }
      },
      "post": {
        "tags": [
          "App"
        ],
        "summary": "Create or update a hosted workflow-pack installation record",
        "description": "Synchronizes installed workflow metadata and blocks enablement when required skill-pack dependencies are missing, disabled, or outdated.",
        "security": [
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          },
          {
            "sessionCookie": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AppWorkflowPackInstallationRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Workflow installation record synchronized."
          },
          "400": {
            "description": "Workflow installation payload was invalid."
          },
          "401": {
            "description": "App session header or OAuth bearer token is missing or invalid."
          }
        }
      }
    },
    "/api/app/workflows": {
      "get": {
        "tags": [
          "App"
        ],
        "summary": "Read the current Kendr account workflow bundle",
        "description": "Returns the signed-in user's synced capability scopes and event workflows. Empty accounts return an empty bundle.",
        "security": [
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          },
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Workflow bundle returned.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "bundle": {
                      "$ref": "#/components/schemas/AppWorkflowBundle"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "App session header or OAuth bearer token is missing or invalid."
          }
        }
      },
      "put": {
        "tags": [
          "App"
        ],
        "summary": "Replace the current Kendr account workflow bundle",
        "description": "Synchronizes the signed-in user's desktop workflow snapshot without creating any built-in workflows.",
        "security": [
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          },
          {
            "sessionCookie": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AppWorkflowBundle"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Workflow bundle synchronized."
          },
          "400": {
            "description": "Workflow bundle payload was invalid."
          },
          "401": {
            "description": "App session header or OAuth bearer token is missing or invalid."
          }
        }
      }
    },
    "/api/app/developer/skill-packs": {
      "get": {
        "tags": [
          "Developer"
        ],
        "summary": "List skill-pack drafts owned by the signed-in developer",
        "security": [
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          },
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Owned skill-pack drafts and catalog metadata returned."
          },
          "401": {
            "description": "Kendr user authentication required."
          }
        }
      },
      "post": {
        "tags": [
          "Developer"
        ],
        "summary": "Create or update a developer skill-pack draft",
        "description": "Builds and validates a canonical skill-pack archive from editor fields. Include id to update an editable owned draft.",
        "security": [
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          },
          {
            "sessionCookie": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeveloperSkillPackDraftRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Saved draft, validation result, and refreshed owned catalog returned."
          },
          "400": {
            "description": "Draft or generated archive was invalid."
          },
          "401": {
            "description": "Kendr user authentication required."
          }
        }
      }
    },
    "/api/app/developer/skill-packs/{pack_id}/validate": {
      "post": {
        "tags": [
          "Developer"
        ],
        "summary": "Validate an owned developer skill-pack archive",
        "security": [
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "pack_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Normalized draft and validation diagnostics returned."
          },
          "401": {
            "description": "Kendr user authentication required."
          },
          "404": {
            "description": "Owned draft not found."
          }
        }
      }
    },
    "/api/app/developer/skill-packs/{pack_id}/submit": {
      "post": {
        "tags": [
          "Developer"
        ],
        "summary": "Submit a valid skill-pack draft for review",
        "security": [
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "pack_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Draft status changed to pending_review."
          },
          "400": {
            "description": "Validation errors must be corrected first."
          },
          "401": {
            "description": "Kendr user authentication required."
          },
          "404": {
            "description": "Owned draft not found."
          }
        }
      }
    },
    "/api/app/developer/skill-packs/{pack_id}/archive": {
      "get": {
        "tags": [
          "Developer"
        ],
        "summary": "Download an owned developer skill-pack archive",
        "security": [
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "pack_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Canonical ZIP archive returned.",
            "content": {
              "application/zip": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "description": "Kendr user authentication required."
          },
          "404": {
            "description": "Owned draft not found."
          }
        }
      },
      "put": {
        "tags": [
          "Developer"
        ],
        "summary": "Replace an editable skill-pack draft with an uploaded archive",
        "security": [
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "pack_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/zip": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Normalized archive, draft metadata, and validation result returned."
          },
          "400": {
            "description": "Archive was invalid or too large."
          },
          "401": {
            "description": "Kendr user authentication required."
          },
          "404": {
            "description": "Owned draft not found."
          }
        }
      }
    },
    "/api/app/developer/workflow-packs": {
      "get": {
        "tags": [
          "Developer"
        ],
        "summary": "List workflow-pack drafts owned by the signed-in developer",
        "security": [
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          },
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Owned workflow-pack drafts and catalog metadata returned."
          },
          "401": {
            "description": "Kendr user authentication required."
          }
        }
      },
      "post": {
        "tags": [
          "Developer"
        ],
        "summary": "Create or update a developer workflow-pack draft",
        "description": "Builds and validates a canonical workflow-pack archive from editor fields. Include id to update an editable owned draft.",
        "security": [
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          },
          {
            "sessionCookie": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeveloperWorkflowPackDraftRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Saved draft, validation result, and refreshed owned catalog returned."
          },
          "400": {
            "description": "Draft or generated archive was invalid."
          },
          "401": {
            "description": "Kendr user authentication required."
          }
        }
      }
    },
    "/api/app/developer/workflow-packs/{pack_id}/validate": {
      "post": {
        "tags": [
          "Developer"
        ],
        "summary": "Validate an owned developer workflow-pack archive",
        "security": [
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "pack_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Normalized draft and validation diagnostics returned."
          },
          "401": {
            "description": "Kendr user authentication required."
          },
          "404": {
            "description": "Owned draft not found."
          }
        }
      }
    },
    "/api/app/developer/workflow-packs/{pack_id}/submit": {
      "post": {
        "tags": [
          "Developer"
        ],
        "summary": "Submit a valid workflow-pack draft for review",
        "security": [
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "pack_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Draft status changed to pending_review."
          },
          "400": {
            "description": "Validation errors must be corrected first."
          },
          "401": {
            "description": "Kendr user authentication required."
          },
          "404": {
            "description": "Owned draft not found."
          }
        }
      }
    },
    "/api/app/developer/workflow-packs/{pack_id}/archive": {
      "get": {
        "tags": [
          "Developer"
        ],
        "summary": "Download an owned developer workflow-pack archive",
        "security": [
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "pack_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Canonical ZIP archive returned.",
            "content": {
              "application/zip": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "description": "Kendr user authentication required."
          },
          "404": {
            "description": "Owned draft not found."
          }
        }
      },
      "put": {
        "tags": [
          "Developer"
        ],
        "summary": "Replace an editable workflow-pack draft with an uploaded archive",
        "security": [
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "pack_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/zip": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Normalized archive, draft metadata, and validation result returned."
          },
          "400": {
            "description": "Archive was invalid or too large."
          },
          "401": {
            "description": "Kendr user authentication required."
          },
          "404": {
            "description": "Owned draft not found."
          }
        }
      }
    },
    "/api/app/activity": {
      "post": {
        "tags": [
          "App"
        ],
        "summary": "Record app activity",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AppActivityRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Activity recorded."
          },
          "400": {
            "description": "Activity payload was invalid."
          }
        }
      }
    },
    "/api/app/errors": {
      "post": {
        "tags": [
          "App"
        ],
        "summary": "Record an app error report",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AppErrorReportRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Error report recorded."
          },
          "400": {
            "description": "Error payload was invalid."
          }
        }
      }
    },
    "/api/app/feedback": {
      "post": {
        "tags": [
          "App"
        ],
        "summary": "Record app feedback",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AppFeedbackRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Feedback recorded."
          },
          "400": {
            "description": "Feedback payload was invalid."
          }
        }
      }
    },
    "/api/desktop/updates": {
      "get": {
        "tags": [
          "App"
        ],
        "summary": "List Kendr Desktop update feeds",
        "responses": {
          "200": {
            "description": "Desktop update channels and files returned."
          }
        }
      }
    },
    "/api/cli/releases": {
      "get": {
        "tags": [
          "App"
        ],
        "summary": "List standalone Kendr CLI releases",
        "responses": {
          "200": {
            "description": "Versioned CLI ZIPs for the three supported channels returned."
          }
        }
      }
    },
    "/api/public/app-stats": {
      "get": {
        "tags": [
          "Public"
        ],
        "summary": "Read public Kendr distribution stats",
        "description": "Returns aggregate lifetime install and artifact download counts without user, IP, or installation identifiers.",
        "responses": {
          "200": {
            "description": "Public distribution stats returned."
          }
        }
      }
    },
    "/api/public/social-profiles": {
      "get": {
        "tags": [
          "Public"
        ],
        "summary": "Read enabled Kendr social profiles",
        "description": "Returns only administrator-enabled public social links for website surfaces.",
        "responses": {
          "200": {
            "description": "Enabled public social profiles returned.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "profiles": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/SocialProfile"
                      }
                    },
                    "updated_at": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/growth/events": {
      "post": {
        "tags": [
          "Public"
        ],
        "summary": "Record public growth attribution events",
        "description": "Captures page, CTA, download, and campaign events for aggregate admin marketing analytics.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Growth event recorded."
          }
        }
      }
    },
    "/api/enterprise/inquiries": {
      "post": {
        "tags": [
          "Public"
        ],
        "summary": "Submit an enterprise pricing and onboarding inquiry",
        "description": "Captures company, buyer, seat, usage, and timeline details for admin-led enterprise onboarding.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "company_name",
                  "contact_name",
                  "email",
                  "use_case"
                ],
                "properties": {
                  "company_name": {
                    "type": "string"
                  },
                  "contact_name": {
                    "type": "string"
                  },
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "phone": {
                    "type": "string"
                  },
                  "title": {
                    "type": "string"
                  },
                  "company_size": {
                    "type": "string"
                  },
                  "seat_count": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "expected_usage": {
                    "type": "string"
                  },
                  "timeline": {
                    "type": "string"
                  },
                  "budget_range": {
                    "type": "string"
                  },
                  "use_case": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Enterprise inquiry recorded."
          },
          "400": {
            "description": "Inquiry payload was invalid."
          }
        }
      }
    },
    "/api/early-access": {
      "post": {
        "tags": [
          "Public"
        ],
        "summary": "Create or update an early-access lead",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "name": {
                    "type": "string"
                  },
                  "marketingOptIn": {
                    "type": "boolean",
                    "description": "Consent to release and product update email. Omit to leave an existing choice unchanged."
                  },
                  "interest": {
                    "type": "string"
                  },
                  "sourcePage": {
                    "type": "string"
                  },
                  "formContext": {
                    "type": "string"
                  }
                },
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Existing lead updated."
          },
          "201": {
            "description": "Lead created."
          }
        }
      }
    },
    "/downloads/desktop/{channel}/{filename}": {
      "get": {
        "tags": [
          "App"
        ],
        "summary": "Fetch a Kendr Desktop update file",
        "parameters": [
          {
            "name": "channel",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "win-x64",
                "linux-x64",
                "mac-arm64",
                "win-arm64",
                "mac-x64",
                "linux-arm64"
              ]
            }
          },
          {
            "name": "filename",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Update file returned."
          },
          "404": {
            "description": "Update file not found."
          }
        }
      }
    },
    "/api/admin/desktop-updates": {
      "get": {
        "tags": [
          "Admin"
        ],
        "summary": "List published desktop release channels and artifacts",
        "description": "API keys require releases:write and an active administrator account.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "responses": {
          "200": {
            "description": "Windows, macOS, and Linux release channels returned."
          },
          "401": {
            "description": "Admin authorization required."
          }
        }
      }
    },
    "/api/admin/desktop-updates/{channel}/{filename}": {
      "put": {
        "tags": [
          "Admin"
        ],
        "summary": "Upload a Kendr Desktop update file",
        "description": "API keys require releases:write and an active administrator account.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "parameters": [
          {
            "name": "channel",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "win-x64",
                "linux-x64",
                "mac-arm64",
                "win-arm64",
                "mac-x64",
                "linux-arm64"
              ]
            }
          },
          {
            "name": "filename",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/octet-stream": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Update file uploaded."
          },
          "401": {
            "description": "Admin authorization required."
          }
        }
      },
      "delete": {
        "tags": [
          "Admin"
        ],
        "summary": "Delete one published Kendr Desktop update file",
        "description": "API keys require releases:write and an active administrator account.",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "channel",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "win-x64",
                "linux-x64",
                "mac-arm64",
                "win-arm64",
                "mac-x64",
                "linux-arm64"
              ]
            }
          },
          {
            "name": "filename",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Update file deleted and channel metadata regenerated."
          },
          "401": {
            "description": "Admin authorization required."
          },
          "404": {
            "description": "Update file not found."
          }
        }
      }
    },
    "/downloads/cli/{channel}/{filename}": {
      "get": {
        "tags": [
          "App"
        ],
        "summary": "Fetch a standalone Kendr CLI archive",
        "parameters": [
          {
            "name": "channel",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "win-x64",
                "linux-x64",
                "mac-arm64",
                "win-arm64",
                "mac-x64",
                "linux-arm64"
              ]
            }
          },
          {
            "name": "filename",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "CLI ZIP returned."
          },
          "404": {
            "description": "CLI release not found."
          }
        }
      }
    },
    "/api/admin/cli-releases": {
      "get": {
        "tags": [
          "Admin"
        ],
        "summary": "List staged and published standalone CLI archives",
        "description": "API keys require releases:write and an active administrator account.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "responses": {
          "200": {
            "description": "CLI releases returned."
          },
          "401": {
            "description": "Admin authorization required."
          }
        }
      }
    },
    "/api/admin/cli-releases/{channel}/{filename}": {
      "put": {
        "tags": [
          "Admin"
        ],
        "summary": "Stage one versioned standalone CLI ZIP",
        "description": "API keys require releases:write and an active administrator account.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "parameters": [
          {
            "name": "channel",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "win-x64",
                "linux-x64",
                "mac-arm64",
                "win-arm64",
                "mac-x64",
                "linux-arm64"
              ]
            }
          },
          {
            "name": "filename",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/zip": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "CLI archive staged."
          },
          "400": {
            "description": "Filename, matrix, or archive manifest was invalid."
          },
          "401": {
            "description": "Admin authorization required."
          }
        }
      },
      "delete": {
        "tags": [
          "Admin"
        ],
        "summary": "Delete one standalone CLI archive",
        "description": "API keys require releases:write and an active administrator account.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "parameters": [
          {
            "name": "channel",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "win-x64",
                "linux-x64",
                "mac-arm64",
                "win-arm64",
                "mac-x64",
                "linux-arm64"
              ]
            }
          },
          {
            "name": "filename",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "CLI archive deleted."
          },
          "401": {
            "description": "Admin authorization required."
          },
          "404": {
            "description": "CLI archive not found."
          }
        }
      }
    },
    "/api/admin/releases/matrix": {
      "get": {
        "tags": [
          "Admin"
        ],
        "summary": "Report which channels a version can publish and what the rest still need",
        "description": "Lists present, missing, and unexpected artifacts per channel, and which channels can publish right now. API keys require releases:write and an active administrator account.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "parameters": [
          {
            "name": "version",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "example": "2.1.2"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Per-channel release matrix completeness returned."
          },
          "400": {
            "description": "Version was not a semantic version."
          },
          "401": {
            "description": "Admin authorization required."
          }
        }
      }
    },
    "/api/admin/releases/publish": {
      "post": {
        "tags": [
          "Admin"
        ],
        "summary": "Publish the desktop and CLI channels that are complete for one version",
        "description": "Publishes every channel whose canonical file set is complete; no channel waits on another, so one platform can ship on its own. Passing `channels` restricts the publish to that selection and rejects an incomplete one instead of skipping it. A channel can never be moved to an older version than it already serves. API keys require releases:write and an active administrator account.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "version"
                ],
                "properties": {
                  "version": {
                    "type": "string",
                    "example": "2.1.2"
                  },
                  "channels": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "win-x64",
                        "linux-x64",
                        "mac-arm64",
                        "win-arm64",
                        "mac-x64",
                        "linux-arm64"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Complete channels published and their desktop updater metadata generated."
          },
          "400": {
            "description": "No channel was complete, or a named channel was incomplete or unexpected."
          },
          "401": {
            "description": "Admin authorization required."
          }
        }
      }
    },
    "/api/chrome-extension/releases": {
      "get": {
        "tags": [
          "App"
        ],
        "summary": "List published Kendr for Chrome releases",
        "description": "Returns versioned direct-download and Chrome Web Store ZIP artifacts. `latest_version` and `current_direct_bundle` always select the newest direct connector archive.",
        "responses": {
          "200": {
            "description": "Chrome extension release catalog returned."
          }
        }
      }
    },
    "/downloads/chrome/{filename}": {
      "get": {
        "tags": [
          "App"
        ],
        "summary": "Download a versioned Kendr for Chrome release",
        "description": "Use `latest.zip` for the current direct connector archive. The response preserves the selected versioned filename in Content-Disposition and includes its server-generated SHA-256 checksum.",
        "parameters": [
          {
            "name": "filename",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Chrome extension ZIP returned."
          },
          "404": {
            "description": "Chrome extension release not found."
          }
        }
      }
    },
    "/api/admin/chrome-extension-releases": {
      "get": {
        "tags": [
          "Admin"
        ],
        "summary": "List Chrome extension release history",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Chrome extension release history returned."
          },
          "401": {
            "description": "Admin authorization required."
          }
        }
      }
    },
    "/api/admin/chrome-extension-releases/{filename}": {
      "put": {
        "tags": [
          "Admin"
        ],
        "summary": "Upload a versioned Kendr for Chrome ZIP",
        "description": "Accepts `kendr-chrome-connector-<semver>.zip` or `kendr-for-chrome-store-<semver>.zip`. The server validates the contained extension manifest and computes SHA-256 metadata.",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "filename",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/zip": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            },
            "application/octet-stream": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Chrome extension ZIP uploaded."
          },
          "400": {
            "description": "Filename, archive, or manifest validation failed."
          },
          "401": {
            "description": "Admin authorization required."
          }
        }
      },
      "delete": {
        "tags": [
          "Admin"
        ],
        "summary": "Delete one Chrome extension release ZIP",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "filename",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Chrome extension ZIP deleted."
          },
          "401": {
            "description": "Admin authorization required."
          },
          "404": {
            "description": "Chrome extension release not found."
          }
        }
      }
    },
    "/.well-known/oauth-authorization-server": {
      "get": {
        "tags": [
          "OAuth"
        ],
        "summary": "Read OAuth authorization server metadata",
        "responses": {
          "200": {
            "description": "OAuth discovery metadata returned."
          }
        }
      }
    },
    "/oauth/authorize": {
      "get": {
        "tags": [
          "OAuth"
        ],
        "summary": "Start the Kendr OAuth authorization code flow",
        "description": "Public Kendr clients use this endpoint with PKCE to obtain a user-approved authorization code.",
        "parameters": [
          {
            "name": "response_type",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "code"
              ]
            }
          },
          {
            "name": "client_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "redirect_uri",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "scope",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "state",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "code_challenge",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "code_challenge_method",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "S256"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Consent page or native app return page rendered."
          },
          "302": {
            "description": "Redirect to portal sign-in or back to the client callback."
          }
        }
      }
    },
    "/oauth/token": {
      "post": {
        "tags": [
          "OAuth"
        ],
        "summary": "Exchange Kendr OAuth grants for bearer tokens",
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Token pair issued.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthTokenResponse"
                }
              }
            }
          },
          "400": {
            "description": "OAuth protocol error."
          }
        }
      }
    },
    "/oauth/device/code": {
      "post": {
        "tags": [
          "OAuth"
        ],
        "summary": "Start the Kendr OAuth device code flow",
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Device code issued.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthDeviceCodeResponse"
                }
              }
            }
          }
        }
      }
    },
    "/oauth/userinfo": {
      "get": {
        "tags": [
          "OAuth"
        ],
        "summary": "Resolve the Kendr user behind an access token",
        "security": [
          {
            "kendrOAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "User info returned."
          },
          "401": {
            "description": "Bearer token missing or invalid."
          }
        }
      }
    },
    "/api/me/dashboard": {
      "get": {
        "tags": [
          "Customer"
        ],
        "summary": "Load the customer dashboard payload",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Dashboard payload returned."
          },
          "401": {
            "description": "Cookie session, app session header, or OAuth bearer token is missing or expired."
          }
        }
      }
    },
    "/api/me/organization": {
      "get": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Read the caller's privacy-filtered enterprise account",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Organization, membership, allowed member data, permissions, and allowed analytics returned."
          },
          "401": {
            "description": "Authentication is missing or expired."
          }
        }
      },
      "patch": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Update enterprise identity, seats, domain, and privacy policy",
        "description": "Lifecycle and legal-hold changes are owner-only. Send confirmation equal to the exact organization name or slug. A non-empty reason is required for suspension and for disabling legal hold.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "allowed_domain": {
                    "type": "string"
                  },
                  "seat_limit": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "active",
                      "suspended",
                      "closed"
                    ]
                  },
                  "settings": {
                    "$ref": "#/components/schemas/EnterpriseSettings"
                  },
                  "confirmation": {
                    "type": "string",
                    "description": "Exact organization name or slug for lifecycle and legal-hold changes."
                  },
                  "reason": {
                    "type": "string",
                    "description": "Required when disabling legal hold and when suspending or closing an organization."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Organization policy updated and audited."
          },
          "403": {
            "description": "The caller lacks organization-management permission."
          }
        }
      }
    },
    "/api/me/organization/invitations": {
      "post": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Invite an enterprise member",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email",
                  "role"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "role": {
                    "type": "string",
                    "enum": [
                      "admin",
                      "billing",
                      "member",
                      "viewer"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "One-time invitation created, delivered when email is configured, and audited."
          },
          "403": {
            "description": "The caller lacks member-management permission."
          }
        }
      }
    },
    "/api/me/organization/invitations/bulk": {
      "post": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Invite enterprise members in bulk",
        "description": "Invite many members at once from a CSV upload. Supply either a pre-parsed `entries` array or raw `csv` text with an `email,role` header. Each row is validated independently and reported back with its own status; seats and domain policy are enforced per row.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "entries": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "required": [
                        "email"
                      ],
                      "properties": {
                        "email": {
                          "type": "string",
                          "format": "email"
                        },
                        "role": {
                          "type": "string",
                          "enum": [
                            "admin",
                            "billing",
                            "member",
                            "viewer"
                          ]
                        }
                      }
                    }
                  },
                  "csv": {
                    "type": "string",
                    "description": "Raw CSV text with an email,role header row."
                  },
                  "default_role": {
                    "type": "string",
                    "enum": [
                      "admin",
                      "billing",
                      "member",
                      "viewer"
                    ],
                    "default": "member"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Batch processed; per-row results and a summary are returned even when some rows are skipped."
          },
          "403": {
            "description": "The caller lacks member-management permission."
          }
        }
      }
    },
    "/api/me/organization/invitations/accept": {
      "post": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Accept an enterprise invitation",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "token"
                ],
                "properties": {
                  "token": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Membership activated atomically within the seat limit."
          }
        }
      }
    },
    "/api/me/organization/invitations/revoke": {
      "post": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Revoke a pending enterprise invitation",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "invitation_id"
                ],
                "properties": {
                  "invitation_id": {
                    "type": "integer",
                    "minimum": 1
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Invitation revoked and audited."
          }
        }
      }
    },
    "/api/me/organization/members/update": {
      "post": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Update a member role, state, billing access, or spend limit",
        "description": "Canonical ownership cannot be changed through this operation; use the atomic transfer endpoint.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "user_id"
                ],
                "properties": {
                  "user_id": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "role": {
                    "type": "string",
                    "enum": [
                      "admin",
                      "billing",
                      "member",
                      "viewer"
                    ]
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "active",
                      "suspended"
                    ]
                  },
                  "billing_enabled": {
                    "type": "boolean"
                  },
                  "spend_limit_micros": {
                    "type": "integer",
                    "minimum": 0,
                    "nullable": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Member policy updated, access revoked when suspended, and event audited."
          }
        }
      }
    },
    "/api/me/organization/members/remove": {
      "post": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Offboard or suspend an enterprise member",
        "description": "Immediately revokes sessions, desktop OAuth tokens, organization API keys, invitations, explicit knowledge grants, and reservations that have not crossed an external provider boundary. Submitted asynchronous video work remains privately tombstoned while its bounded reservation is retained for terminal billing reconciliation.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "user_id"
                ],
                "properties": {
                  "user_id": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "mode": {
                    "type": "string",
                    "enum": [
                      "removed",
                      "suspended"
                    ],
                    "default": "removed"
                  },
                  "reason": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Member offboarded and all organization access revoked."
          }
        }
      }
    },
    "/api/me/organization/transfer": {
      "post": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Atomically transfer ownership or billing responsibility",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "user_id"
                ],
                "properties": {
                  "user_id": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "transfer": {
                    "type": "string",
                    "enum": [
                      "ownership",
                      "billing",
                      "both"
                    ]
                  },
                  "demote_previous_owner": {
                    "type": "boolean",
                    "default": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Canonical responsibility and member roles transferred in one transaction."
          }
        }
      }
    },
    "/api/me/organization/leave": {
      "post": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Leave an enterprise account",
        "description": "Canonical owners and billing owners must transfer responsibility first.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Membership removed, organization access revoked, and the current session signed out.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "status",
                    "organization_id",
                    "signed_out"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "left"
                      ]
                    },
                    "organization_id": {
                      "type": "integer"
                    },
                    "signed_out": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/me/organization/close": {
      "post": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Close an enterprise account",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "confirmation",
                  "reason"
                ],
                "properties": {
                  "confirmation": {
                    "type": "string",
                    "description": "Exact organization name or slug."
                  },
                  "reason": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Account closed, access revoked, and retention deadline returned."
          }
        }
      }
    },
    "/api/auth/school/discover": {
      "post": {
        "tags": [
          "School"
        ],
        "summary": "Report whether an email belongs to an approved institution",
        "description": "Returns the institution name, learner policy, and plan facts for the sign-in page. Rate limited per IP; never returns learner data.",
        "responses": {
          "200": {
            "description": "School plan availability for the address returned."
          }
        }
      }
    },
    "/api/public/school-plan": {
      "get": {
        "tags": [
          "School",
          "Public"
        ],
        "summary": "Public school plan facts",
        "description": "Price, list price, weekly allowance, period length, and whether card payments are enabled, read from the admin-managed settings.",
        "responses": {
          "200": {
            "description": "School plan facts returned."
          }
        }
      }
    },
    "/api/me/school": {
      "get": {
        "tags": [
          "School",
          "Customer"
        ],
        "summary": "The signed-in account's school plan status",
        "description": "Eligibility, learner status, the active period with this week's allowance, and period history. Reading it releases any weekly tranche that is due.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "School plan status returned."
          }
        }
      }
    },
    "/api/me/school/request": {
      "post": {
        "tags": [
          "School",
          "Customer"
        ],
        "summary": "Request the school plan, or activate it on an auto-approve institution",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Updated school plan status returned."
          }
        }
      }
    },
    "/api/me/school/request-institution": {
      "post": {
        "tags": [
          "School",
          "Customer"
        ],
        "summary": "Ask Kendr to onboard the signed-in learner's institution",
        "description": "Files one application per email domain and counts every later learner who asks.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Institution request recorded."
          }
        }
      }
    },
    "/api/me/school/application-verify": {
      "post": {
        "tags": [
          "School",
          "Customer"
        ],
        "summary": "Confirm an institution application by signing in with an address on its domain",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Institution contact verified."
          }
        }
      }
    },
    "/api/auth/sso/discover": {
      "post": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Report whether an email domain signs in through company SSO",
        "description": "Answers only for domains an organization has verified by DNS.",
        "responses": {
          "200": {
            "description": "SSO availability for the address returned."
          }
        }
      }
    },
    "/api/auth/sso/start": {
      "post": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Begin an OIDC single sign-on request and return the provider URL",
        "description": "Creates a single-use state with a nonce and PKCE challenge. Pass test=true to run a configuration test that does not sign anyone in.",
        "responses": {
          "200": {
            "description": "Authorization URL returned."
          }
        }
      }
    },
    "/api/auth/sso/callback": {
      "get": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Complete single sign-on and start a session",
        "description": "Validates the provider's ID token (signature, issuer, audience, expiry, nonce) and requires the asserted email to sit in the organization's DNS-verified domain.",
        "responses": {
          "302": {
            "description": "Redirected to the application with a session cookie, or back to sign-in with an error."
          }
        }
      }
    },
    "/api/me/organization/sso": {
      "get": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Read the organization's single sign-on configuration",
        "description": "The client secret is never returned; only whether one is stored.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "SSO configuration returned for owners and admins."
          }
        }
      },
      "post": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Create or update the organization's OIDC connection",
        "description": "Enforcement is refused until a test sign-in has succeeded, and changing the issuer, client id, or secret clears that test. Just-in-time provisioning requires a verified domain and cannot grant owner or admin roles.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "SSO configuration saved."
          }
        }
      }
    },
    "/api/me/organization/roles": {
      "get": {
        "tags": [
          "Enterprise"
        ],
        "summary": "List custom roles and the delegatable permission catalogue",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Custom roles, available permissions, and the built-in role matrix."
          }
        }
      },
      "post": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Create or update a custom role",
        "description": "A custom role is a bundle of permissions granted through teams. Ownership transfer, closing the account, and leaving are never delegatable. Owners and admins only: anyone who can write roles could otherwise grant themselves everything.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Role saved."
          }
        }
      }
    },
    "/api/me/organization/roles/delete": {
      "post": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Delete a custom role",
        "description": "Grants of the role are removed with it, so anyone who held permissions only through it loses them immediately.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Role deleted."
          }
        }
      }
    },
    "/api/me/organization/teams/manage": {
      "get": {
        "tags": [
          "Enterprise"
        ],
        "summary": "List teams with their members and granted roles",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Teams returned."
          }
        }
      },
      "post": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Create, rename, delete a team, or change its members and granted roles",
        "description": "Actions: create, rename, delete, add_member, remove_member, grant_role, revoke_role. Owners and admins only, because attaching a role to a team is how permissions are handed out.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Teams returned after the change."
          }
        }
      }
    },
    "/api/me/organization/permissions": {
      "get": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Effective permissions for a member, and where each one comes from",
        "description": "Every permission with whether it is granted and the source of each grant: the built-in role, or the team and custom role that supplied it. Pass user_id to inspect somebody else, which requires permission to view members; without it you get your own.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Effective permission report returned."
          }
        }
      }
    },
    "/api/me/organizations": {
      "get": {
        "tags": [
          "Enterprise"
        ],
        "summary": "List every enterprise this person belongs to",
        "description": "A person may hold several active enterprise memberships, with a different role in each. Returns them best-role first alongside the organization this session is currently acting in.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Memberships and the active organization returned."
          }
        }
      }
    },
    "/api/me/organizations/switch": {
      "post": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Point this session at one of the person's organizations",
        "description": "Stored on the session, so it changes only this browser or device and never what an API key does. Pass organization_id 0 to clear the choice and fall back to the default. Switching to an organization the caller is not an active member of is refused.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          }
        ],
        "responses": {
          "200": {
            "description": "Session switched."
          }
        }
      }
    },
    "/api/me/organization/scim": {
      "get": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Read the SCIM directory connection status",
        "description": "Reports whether directory provisioning is enabled, the token prefix, and when the directory last called. The token itself is never returned.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Directory status returned for owners and admins."
          }
        }
      }
    },
    "/api/me/organization/scim/token": {
      "post": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Issue or rotate the SCIM directory token",
        "description": "Returns the bearer token exactly once; only a hash is stored. Rotating invalidates the previous token. Requires a DNS-verified work-email domain, because the directory may only provision addresses at that domain.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Directory token issued."
          }
        }
      }
    },
    "/api/me/organization/scim/disable": {
      "post": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Disable SCIM directory provisioning",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Directory provisioning disabled."
          }
        }
      }
    },
    "/scim/v2/Users": {
      "get": {
        "tags": [
          "Enterprise"
        ],
        "summary": "SCIM 2.0: list members, optionally filtered by userName",
        "description": "Authenticated with the organization's directory bearer token, not a Kendr session. Supports filters of the form userName eq \"value\".",
        "responses": {
          "200": {
            "description": "SCIM ListResponse returned."
          }
        }
      },
      "post": {
        "tags": [
          "Enterprise"
        ],
        "summary": "SCIM 2.0: provision a member",
        "description": "Only addresses at the organization's DNS-verified domain may be provisioned. Seat limits apply.",
        "responses": {
          "201": {
            "description": "Member provisioned."
          }
        }
      }
    },
    "/scim/v2/Users/{id}": {
      "get": {
        "tags": [
          "Enterprise"
        ],
        "summary": "SCIM 2.0: read one member",
        "responses": {
          "200": {
            "description": "SCIM User returned."
          }
        }
      },
      "patch": {
        "tags": [
          "Enterprise"
        ],
        "summary": "SCIM 2.0: activate or deactivate a member",
        "description": "Setting active to false suspends the membership and performs the same lifecycle-safe revocation as administrative offboarding. Submitted asynchronous video work is hidden and tombstoned while its bounded reservation remains available for terminal billing reconciliation. The organization owner and billing user cannot be deprovisioned this way.",
        "responses": {
          "200": {
            "description": "SCIM User returned."
          }
        }
      },
      "delete": {
        "tags": [
          "Enterprise"
        ],
        "summary": "SCIM 2.0: deprovision a member",
        "description": "Removes the membership and revokes sessions and desktop tokens.",
        "responses": {
          "204": {
            "description": "Member deprovisioned."
          }
        }
      }
    },
    "/scim/v2/ServiceProviderConfig": {
      "get": {
        "tags": [
          "Enterprise"
        ],
        "summary": "SCIM 2.0: service provider capabilities",
        "responses": {
          "200": {
            "description": "Capability document returned."
          }
        }
      }
    },
    "/api/me/mfa": {
      "get": {
        "tags": [
          "Account"
        ],
        "summary": "Two-factor status for the signed-in account",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Whether a second factor is enrolled, and how many backup codes remain."
          }
        }
      }
    },
    "/api/me/mfa/start": {
      "post": {
        "tags": [
          "Account"
        ],
        "summary": "Begin two-factor enrolment",
        "description": "Returns a TOTP secret and otpauth URI. The factor does nothing until a code confirms it. Refused when the deployment has no durable credential encryption key, since a restart would destroy the secret.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Enrolment secret issued."
          }
        }
      }
    },
    "/api/me/mfa/confirm": {
      "post": {
        "tags": [
          "Account"
        ],
        "summary": "Confirm two-factor enrolment with a code",
        "description": "Returns single-use backup codes exactly once; only their hashes are stored.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Two-factor enabled."
          }
        }
      }
    },
    "/api/me/mfa/disable": {
      "post": {
        "tags": [
          "Account"
        ],
        "summary": "Turn two-factor off",
        "description": "Requires a current authenticator code or an unused backup code.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Two-factor disabled."
          }
        }
      }
    },
    "/api/auth/mfa/verify": {
      "post": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Complete a sign-in that owes a second factor",
        "description": "The primary factor returns mfa_required with a single-use challenge instead of a session. Accepts an authenticator code or a backup code. A spent time step is refused, so a code cannot be replayed while it is still otherwise valid.",
        "responses": {
          "200": {
            "description": "Session issued."
          }
        }
      }
    },
    "/api/auth/mfa/enroll/start": {
      "post": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Begin enrolment during sign-in when the organization requires a second factor",
        "description": "Enrolment happens through the sign-in challenge, because a requirement that needed an existing session would lock out the people it is meant to onboard.",
        "responses": {
          "200": {
            "description": "Enrolment secret issued."
          }
        }
      }
    },
    "/api/auth/mfa/enroll/confirm": {
      "post": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Finish enrolment and complete the sign-in",
        "responses": {
          "200": {
            "description": "Two-factor enabled and session issued."
          }
        }
      }
    },
    "/api/me/organization/connectors": {
      "get": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Inventory every app connection held by an active member",
        "description": "Owner, connector, account, granted scopes, when it was last authorized, expiry and health. Scoped by joining membership, so a person's connections appear only while they are an active member.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Connector inventory returned for owners and admins."
          }
        }
      }
    },
    "/api/me/organization/connectors/disconnect": {
      "post": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Force-disconnect one member's app connection",
        "description": "Marks the connection revoked and clears the stored credential. The target must be an active member of the caller's organization.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Connection disconnected."
          }
        }
      }
    },
    "/api/admin/approvals/request": {
      "post": {
        "tags": [
          "Admin"
        ],
        "summary": "Raise a four-eyes approval request for an irreversible operator action",
        "description": "Actions: organization.purge, user.credit_adjustment. A different Kendr operator must approve before the action will run; the approval is single-use and expires.",
        "responses": {
          "200": {
            "description": "Approval request raised."
          }
        }
      }
    },
    "/api/admin/approvals/review": {
      "post": {
        "tags": [
          "Admin"
        ],
        "summary": "Approve or decline another operator's request",
        "description": "The operator who raised the request cannot approve it, and the approver cannot also be the one who runs the action.",
        "responses": {
          "200": {
            "description": "Decision recorded."
          }
        }
      }
    },
    "/api/me/organization/sessions": {
      "get": {
        "tags": [
          "Enterprise"
        ],
        "summary": "List every active member's live sessions, desktop tokens, and linked devices",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Session and device inventory returned for owners and admins."
          }
        }
      }
    },
    "/api/me/organization/sessions/revoke": {
      "post": {
        "tags": [
          "Enterprise"
        ],
        "summary": "End one member's sessions and desktop tokens without removing them",
        "description": "Deletes the member's sessions, revokes their desktop OAuth tokens, and records an audit event. The member keeps their membership.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Sessions and desktop tokens revoked."
          }
        }
      }
    },
    "/api/me/organization/domain/token": {
      "post": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Issue a DNS TXT token proving control of the work-email domain",
        "description": "Returns the record name and value to publish. Issuing a new token replaces any previous one.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Verification token issued with DNS publishing instructions."
          }
        }
      }
    },
    "/api/me/organization/domain/verify": {
      "post": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Check DNS for the verification record and mark the domain verified",
        "description": "Reads TXT records at _kendr-verification.<domain> and at the apex. Verification is bound to the domain it passed for, so changing the allowed domain clears it.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Domain ownership verified."
          }
        }
      }
    },
    "/api/me/organization/audit": {
      "get": {
        "tags": [
          "Enterprise"
        ],
        "summary": "List filtered, paginated, tamper-evident audit events",
        "description": "Also accepts a Kendr API key carrying the `audit:read` scope, so a SIEM can pull the trail without a browser session. That scope is not granted by default, so an existing model-access key does not gain the audit trail.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "event_type",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "actor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "outcome",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Audit page and hash-chain integrity result returned."
          }
        }
      }
    },
    "/api/me/organization/audit/export": {
      "get": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Export filtered enterprise audit events as CSV",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "CSV audit export returned and the export itself audited."
          }
        }
      }
    },
    "/api/me/organization/audit/destinations": {
      "get": {
        "tags": [
          "Enterprise"
        ],
        "summary": "List SIEM destinations audit events are streamed to",
        "description": "Includes how far behind each destination is (`pending_events`) and why it is failing. The signing secret is never returned; `has_signing_secret` only reports that one is stored.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Destinations with delivery health and lag returned."
          }
        }
      },
      "post": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Add a SIEM destination for streamed audit events",
        "description": "The endpoint must be public HTTPS; addresses resolving to private or link-local space are refused, and the check is repeated on every delivery. Returns the HMAC signing secret exactly once. Streaming starts from the current moment unless `deliver_existing_events` is set.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Destination created and the signing secret returned once."
          }
        }
      }
    },
    "/api/me/organization/audit/destinations/update": {
      "post": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Rename, retarget, pause, refilter, or rotate the secret of a destination",
        "description": "Re-enabling a destination clears its accumulated backoff. Rotating returns a new signing secret once.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Destination updated."
          }
        }
      }
    },
    "/api/me/organization/audit/destinations/delete": {
      "post": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Remove a SIEM destination and stop streaming to it",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Destination removed."
          }
        }
      }
    },
    "/api/me/organization/billing": {
      "get": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Billing profile, contacts and wallet position",
        "description": "The `capabilities` block states plainly what this billing model does not include: Kendr bills as a prepaid credit wallet, so accounts have statements of movement rather than tax invoices, and no payment method is stored here \u2014 a low balance raises an alert to the billing contacts instead of charging automatically.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Billing profile, contacts and wallet returned."
          }
        }
      },
      "post": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Save the billing profile",
        "description": "Legal entity, address, tax identity, purchase order, statement note, currency, contract and renewal dates, and the low-balance alert threshold. Changing the threshold or the renewal date re-arms the corresponding alert.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Billing profile saved and audited."
          }
        }
      }
    },
    "/api/me/organization/billing/contacts": {
      "post": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Add, update, or remove a billing contact",
        "description": "Accounts-payable addresses are usually not Kendr users, so billing contacts are their own list rather than a flag on membership. Pass `action: \"remove\"` with `contact_id` to delete one.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Billing contact saved or removed."
          }
        }
      }
    },
    "/api/me/organization/billing/statements": {
      "get": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Monthly statements of credits purchased and consumed",
        "description": "Every requested month is returned even when empty, because a gap reads as lost data to somebody reconciling. The closing balance is read from the credit ledger rather than recomputed, so a statement can never disagree with the ledger it summarises.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "months",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 24,
              "default": 6
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Statements returned."
          }
        }
      }
    },
    "/api/me/organization/billing/statements/export": {
      "get": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Download the statements as CSV",
        "description": "Carries the buyer's own legal entity, tax identity, purchase order and note in the header rows, because the person reconciling the file is rarely the person who exported it.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "CSV statement export returned."
          }
        }
      }
    },
    "/api/me/organization/support": {
      "get": {
        "tags": [
          "Enterprise"
        ],
        "summary": "List support cases, or read one with its messages",
        "description": "Returns the published first-response targets alongside the cases, so the form can say what choosing a severity commits Kendr to. Pass `case_id` for a single case and its full message thread.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "case_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "open",
                "awaiting_customer",
                "resolved",
                "closed"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Support cases returned."
          }
        }
      },
      "post": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Open a support case",
        "description": "Any active member may open a case \u2014 the person hitting the problem is usually not an administrator. The first-response target is stamped onto the case from its severity at open time and does not move if the policy later changes.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Case opened."
          }
        }
      }
    },
    "/api/me/organization/support/reply": {
      "post": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Add a customer reply to a case",
        "description": "Returns the case to the open queue. Deliberately does not satisfy the first-response target \u2014 only a Kendr reply can do that.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Reply added."
          }
        }
      }
    },
    "/api/me/organization/support/escalate": {
      "post": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Escalate a case",
        "description": "Separate from severity: severity is the impact, escalation says the current handling is not working. Requires a reason and an administrator.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Case escalated and audited."
          }
        }
      }
    },
    "/api/me/organization/support/close": {
      "post": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Close a support case",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Case closed and audited."
          }
        }
      }
    },
    "/api/me/organization/adoption": {
      "get": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Seat adoption, engagement, feature reach, per-team spend and a spend forecast",
        "description": "Derived entirely from existing records: `last_active_at` on each membership and the user id on every usage event. Seats that were never used are counted separately from seats that went quiet. Spend for a person in several teams is split between them rather than counted in each, so team shares sum to the attributed total, and spend by people in no team is reported as `unassigned` rather than dropped. The forecast is a straight-line run rate (`method: straight_line_run_rate`), not a model.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "period_days",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 7,
              "maximum": 180,
              "default": 30
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Adoption, engagement, chargeback and forecast returned."
          }
        }
      }
    },
    "/api/me/organization/audit/deliveries": {
      "get": {
        "tags": [
          "Enterprise"
        ],
        "summary": "List recent delivery attempts for audit streaming",
        "description": "A failed attempt never advances the cursor, so the same events reappear on the next successful delivery rather than leaving a gap in the stream.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "destination_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Delivery attempt history returned."
          }
        }
      }
    },
    "/api/me/organization/export": {
      "get": {
        "tags": [
          "Enterprise"
        ],
        "summary": "Export organization configuration, people, delegation, usage, knowledge metadata, and audit",
        "description": "Includes teams, custom roles, team membership, workspaces and audit-streaming configuration alongside members, invitations, knowledge metadata, analytics and the audit chain. Carries a `retention_coverage` statement naming the classes the retention windows delete and the classes they deliberately do not reach. No credential is included: audit destination signing secrets are omitted.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Organization JSON export returned and audited."
          }
        }
      }
    },
    "/api/me/referrals": {
      "get": {
        "tags": [
          "Customer"
        ],
        "summary": "Load the current customer's referral program summary",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Referral code, share URLs, totals, and reward policy returned."
          },
          "401": {
            "description": "Cookie session, app session header, or OAuth bearer token is missing or expired."
          }
        }
      }
    },
    "/api/me/rewards": {
      "get": {
        "tags": [
          "Customer"
        ],
        "summary": "Load the reward catalog, current submissions, referral progress, and earned credits",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Reward task state and verification progress returned."
          },
          "401": {
            "description": "An authenticated customer session is required."
          }
        }
      }
    },
    "/api/me/rewards/start": {
      "post": {
        "tags": [
          "Customer"
        ],
        "summary": "Start a one-time reward task and receive its ownership challenge",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RewardStartRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Reward draft created or existing active submission returned."
          },
          "400": {
            "description": "Task is unavailable, already exhausted, or not a submitted-evidence task."
          }
        }
      }
    },
    "/api/me/rewards/submit": {
      "post": {
        "tags": [
          "Customer"
        ],
        "summary": "Submit public evidence for SSRF-safe deterministic and AI verification",
        "description": "Public-content tasks require the per-draft ownership challenge in the published content. Credits are granted transactionally only after approval; uncertain claims move to administrator review.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RewardEvidenceRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Verification decision and refreshed reward state returned."
          },
          "400": {
            "description": "Evidence URL, ownership, attempt limit, or submission state is invalid."
          }
        }
      }
    },
    "/api/me/api-keys": {
      "get": {
        "tags": [
          "Customer"
        ],
        "summary": "List customer API keys",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Current customer API keys returned."
          },
          "401": {
            "description": "Cookie session, app session header, or OAuth bearer token is missing or expired."
          }
        }
      },
      "post": {
        "tags": [
          "Customer"
        ],
        "summary": "Create a customer API key",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateApiKeyRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "API key created and raw token returned once."
          },
          "401": {
            "description": "Cookie session, app session header, or OAuth bearer token is missing or expired."
          }
        }
      }
    },
    "/api/me/purchases": {
      "post": {
        "tags": [
          "Customer"
        ],
        "summary": "Purchase a credit package",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePurchaseRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Purchase recorded and credits added."
          },
          "401": {
            "description": "Cookie session, app session header, or OAuth bearer token is missing or expired."
          }
        }
      }
    },
    "/api/me/api-keys/revoke": {
      "post": {
        "tags": [
          "Customer"
        ],
        "summary": "Revoke a customer API key",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RevokeApiKeyRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "API key revoked."
          },
          "401": {
            "description": "Cookie session, app session header, or OAuth bearer token is missing or expired."
          }
        }
      }
    },
    "/api/me/ai/preferences": {
      "get": {
        "tags": [
          "Customer"
        ],
        "summary": "Read the signed-in user's Kendr model selections",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Model preferences returned."
          }
        }
      },
      "post": {
        "tags": [
          "Customer"
        ],
        "summary": "Save default and mode-specific Kendr model aliases",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AiPreferencesRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Model preferences saved."
          }
        }
      }
    },
    "/api/me/voice/preferences": {
      "get": {
        "tags": [
          "Customer"
        ],
        "summary": "Read the signed-in user's Nova 2 Sonic voice preference",
        "description": "Returns the allowlisted voice catalog and whether a first-use selection is required. Preview audio and live conversations stream through Kendr's same-origin voice WebSocket; AWS credentials are never returned to the browser.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Voice preference and catalog returned."
          }
        }
      },
      "post": {
        "tags": [
          "Customer"
        ],
        "summary": "Save the signed-in user's Nova 2 Sonic voice",
        "description": "Updates only the voice field and preserves every saved model preference. The selected voice applies to the next voice session.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VoicePreferenceRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Voice preference saved."
          },
          "400": {
            "description": "The voice identifier is not supported."
          }
        }
      }
    },
    "/api/me/routing-profiles": {
      "get": {
        "tags": [
          "Customer"
        ],
        "summary": "List the signed-in user's custom model routing profiles",
        "description": "Profiles are private to the authenticated user. Each profile supplies an eligible model set while Kendr retains control of classification, policy, cost, quality, and availability routing.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Active profiles, the account limit, and remaining slots returned.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "profiles": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/UserRoutingProfile"
                      }
                    },
                    "limit": {
                      "type": "integer",
                      "const": 5
                    },
                    "remaining": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 5
                    },
                    "lifetime_limit": {
                      "type": "integer",
                      "const": 100
                    },
                    "lifetime_used": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 100
                    },
                    "lifetime_remaining": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 100
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "A customer session or app-scoped OAuth token is required."
          }
        }
      },
      "post": {
        "tags": [
          "Customer"
        ],
        "summary": "Create a custom model routing profile",
        "description": "Creates one of at most five active account-owned aliases. Deleted aliases remain permanently reserved to protect existing integrations, so each account may create at most 100 distinct routing profile names over its lifetime (20 full rotations of the active slots). Only enabled physical models may be selected; clients cannot provide routing algorithms, weights, or priorities.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateUserRoutingProfileRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Routing profile created."
          },
          "400": {
            "description": "The alias or selected model list is invalid, reserved, duplicated, or over the five-active-profile limit."
          },
          "401": {
            "description": "A customer session or app-scoped OAuth token is required."
          },
          "409": {
            "description": "The account has exhausted its lifetime limit of 100 permanently reserved routing profile names."
          }
        }
      }
    },
    "/api/me/routing-profiles/{profile_id}": {
      "put": {
        "tags": [
          "Customer"
        ],
        "summary": "Replace the selected models in a routing profile",
        "description": "The public alias is immutable so chat and API integrations remain stable. Send the latest revision in the body or as If-Match; stale writes are rejected.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "profile_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional alternative to the revision body field."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateUserRoutingProfileRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Routing profile updated and its revision incremented."
          },
          "404": {
            "description": "No active profile with that id belongs to the authenticated user."
          },
          "409": {
            "description": "The submitted revision is stale."
          },
          "428": {
            "description": "A revision precondition is required."
          }
        }
      },
      "delete": {
        "tags": [
          "Customer"
        ],
        "summary": "Delete a routing profile",
        "description": "Soft-deletes the alias as a permanent tombstone, frees one of the five slots, and moves saved model preferences that used it to Kendr Intelligent.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "profile_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "revision",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1
            },
            "description": "Latest profile revision. May instead be sent in the JSON body or If-Match header."
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "revision": {
                    "type": "integer",
                    "minimum": 1
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Routing profile deleted and dependent preferences moved to Kendr Intelligent."
          },
          "404": {
            "description": "No active profile with that id belongs to the authenticated user."
          },
          "409": {
            "description": "The submitted revision is stale."
          },
          "428": {
            "description": "A revision precondition is required."
          }
        }
      }
    },
    "/api/me/billing/summary": {
      "get": {
        "tags": [
          "Billing"
        ],
        "summary": "Read the wallet, recent model reservations, settled usage, packages, and purchases",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Exact microcredit billing summary returned."
          }
        }
      }
    },
    "/api/me/purchases/verify": {
      "post": {
        "tags": [
          "Billing"
        ],
        "summary": "Verify a Razorpay payment and settle purchased Kendr credits",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PurchaseVerificationRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Purchase verified and wallet updated."
          }
        }
      }
    },
    "/api/me/connectors": {
      "get": {
        "tags": [
          "Connectors"
        ],
        "summary": "List application connectors available to the signed-in user",
        "description": "Returns administrator-enabled connector services and the current user's connection state. OAuth client secrets are never returned.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "User connector catalog returned."
          }
        }
      }
    },
    "/api/me/meeting-notes/search": {
      "get": {
        "tags": [
          "Customer"
        ],
        "summary": "Search meeting titles, reports, transcripts, and participants",
        "description": "Searches meetings the signed-in user can read. The query must contain at least two characters. API keys require meetings:read.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 2,
              "maxLength": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Matching meeting rows returned."
          },
          "400": {
            "description": "Search query is missing or too short."
          }
        }
      }
    },
    "/api/me/meeting-notes/workflow-destinations": {
      "get": {
        "tags": [
          "Customer"
        ],
        "summary": "List approved task-workflow destinations",
        "description": "Reads the connected user's Google Tasks lists, Todoist projects, Slack channels, Asana projects, Jira projects, Microsoft Teams channels, Microsoft Planner plans/buckets, Linear teams/projects, or ClickUp lists for target selection. Returns only destination ids and display labels; access tokens and meeting content are never returned. API keys require meetings:read.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "destination",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "google_tasks",
                "todoist",
                "slack",
                "asana",
                "jira",
                "teams",
                "planner",
                "linear",
                "clickup"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Safe destination catalog returned."
          },
          "400": {
            "description": "The destination is invalid."
          },
          "409": {
            "description": "The destination must be reconnected with the required permission."
          },
          "502": {
            "description": "The provider could not load its destination catalog."
          },
          "503": {
            "description": "The provider is temporarily unavailable."
          }
        }
      }
    },
    "/api/me/meeting-notes/analytics": {
      "get": {
        "tags": [
          "Customer"
        ],
        "summary": "Read owner-only meeting type and action-item analytics",
        "description": "Aggregates the authenticated owner's meeting reports within the requested period. Shared Project reports are excluded so analytics never reveal another user's meeting history. API keys require meetings:read.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 365,
              "default": 30
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Owner meeting analytics returned."
          },
          "400": {
            "description": "The period is outside the supported range."
          }
        }
      }
    },
    "/api/me/meeting-notes": {
      "get": {
        "tags": [
          "Customer"
        ],
        "summary": "List AI meeting notes and discover upcoming supported calendar calls",
        "description": "Returns compact meeting rows (transcripts are detail-only), connected Google/Outlook Calendar call candidates, per-source calendar status, and live-capture/report readiness. API keys require meetings:read.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Meeting notes, calendar events, and readiness returned."
          }
        }
      },
      "post": {
        "tags": [
          "Customer"
        ],
        "summary": "Create scheduled AI meeting notes",
        "description": "Creates an idempotent notetaker for calendar_event_id, validates the public meeting URL, and optionally targets account or shared Project Sources. Enabled notes with a scheduled_start automatically join at that time; no credits are reserved before the due time. Capture is limited to three hours. API keys require meetings:write.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateMeetingNotetakerRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Meeting notes created, or the calendar event's existing notes returned."
          }
        }
      }
    },
    "/api/me/meeting-notes/preferences": {
      "get": {
        "tags": [
          "Customer"
        ],
        "summary": "Read completed-summary, workflow, and retention preferences",
        "description": "Returns the account owner's email delivery preference, explicit automatic action-item handoff settings, and personal report-retention policy. Automatic external writes and automatic report deletion are disabled by default. API keys require meetings:read.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Meeting email preference returned."
          }
        }
      },
      "post": {
        "tags": [
          "Customer"
        ],
        "summary": "Update completed-summary, workflow, and retention preferences",
        "description": "Disabling email suppresses queued deliveries. Automatic action-item handoff is opt-in, requires a selected Google Tasks, Todoist, Slack, Asana, Jira, Microsoft Teams, Microsoft Planner, Linear, or ClickUp destination, and uses durable per-item status with no silent provider retries. Personal report deletion is off by default and accepts only 30, 90, or 365 days; active captures and legal-held accounts are never deleted. API keys require meetings:write.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email_summary_enabled"
                ],
                "properties": {
                  "email_summary_enabled": {
                    "type": "boolean"
                  },
                  "auto_task_handoff_enabled": {
                    "type": "boolean",
                    "default": false
                  },
                  "auto_task_handoff_destination": {
                    "type": "string",
                    "enum": [
                      "google_tasks",
                      "todoist",
                      "slack",
                      "asana",
                      "jira",
                      "teams",
                      "planner",
                      "linear",
                      "clickup"
                    ]
                  },
                  "auto_task_handoff_target_id": {
                    "type": "string",
                    "maxLength": 320
                  },
                  "retention_days": {
                    "type": "integer",
                    "enum": [
                      0,
                      30,
                      90,
                      365
                    ],
                    "default": 0
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Meeting email preference updated."
          }
        }
      }
    },
    "/api/me/meeting-notes/presets": {
      "get": {
        "tags": [
          "Customer"
        ],
        "summary": "List reusable meeting capture presets",
        "description": "Returns the caller's saved meeting capture workflows. API keys require meetings:read.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Meeting presets returned."
          }
        }
      },
      "post": {
        "tags": [
          "Customer"
        ],
        "summary": "Create or update a reusable meeting capture preset",
        "description": "Upserts a named owner preset for duration, language, summary style, bot name, source/email behavior, and Project audience. A target Project requires contribute access. API keys require meetings:write.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 80
                  },
                  "title": {
                    "type": "string",
                    "maxLength": 300
                  },
                  "expected_duration_seconds": {
                    "type": "integer",
                    "minimum": 60,
                    "maximum": 10800
                  },
                  "language": {
                    "type": "string",
                    "default": "auto"
                  },
                  "summary_template": {
                    "type": "string",
                    "enum": [
                      "standard",
                      "executive",
                      "standup",
                      "sales",
                      "interview"
                    ]
                  },
                  "summary_instructions": {
                    "type": "string",
                    "maxLength": 2000
                  },
                  "bot_name": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "save_to_sources": {
                    "type": "boolean"
                  },
                  "email_summary_enabled": {
                    "type": "boolean"
                  },
                  "project_id": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 180
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Meeting preset saved."
          },
          "400": {
            "description": "Preset is invalid."
          },
          "403": {
            "description": "The target Project is not writable by the caller."
          }
        }
      }
    },
    "/api/me/meeting-notes/presets/{preset_id}": {
      "delete": {
        "tags": [
          "Customer"
        ],
        "summary": "Delete a reusable meeting capture preset",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "preset_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Meeting preset deleted."
          },
          "404": {
            "description": "Meeting preset not found."
          }
        }
      }
    },
    "/api/me/meeting-notes/calendar-sync": {
      "post": {
        "tags": [
          "Customer"
        ],
        "summary": "Discover and import upcoming connected-calendar calls",
        "description": "Fetches supported upcoming calls from connected Google Calendar and Outlook Calendar accounts, then idempotently creates scheduled placeholders keyed by the source calendar event. Enabled placeholders are picked up by the durable auto-join worker at scheduled_start; sync itself never starts a bot or reserves meeting credits.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Calendar calls synchronized and the refreshed meeting overview returned."
          }
        }
      }
    },
    "/api/me/meeting-notes/{meeting_id}": {
      "get": {
        "tags": [
          "Customer"
        ],
        "summary": "Read the meeting report, transcript, topics, sentiment, questions, decisions, and tasks",
        "description": "API keys require meetings:read. Completed reports saved to a shared Project are readable by Project members; lifecycle operations remain owner-only. Add transcript_offset and transcript_limit to request a bounded transcript window (limit 1-500); transcript_query filters speaker/text before pagination without exposing other meetings.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "meeting_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "transcript_offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            },
            "description": "Zero-based segment offset for a bounded transcript window."
          },
          {
            "name": "transcript_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 200
            },
            "description": "Maximum transcript segments to return."
          },
          {
            "name": "transcript_query",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "description": "Optional case-insensitive speaker/text filter applied before pagination."
          }
        ],
        "responses": {
          "200": {
            "description": "Full meeting report returned, optionally with a bounded transcript window."
          },
          "400": {
            "description": "Transcript pagination parameters are invalid."
          },
          "404": {
            "description": "Meeting notes not found."
          }
        }
      },
      "delete": {
        "tags": [
          "Customer"
        ],
        "summary": "Delete inactive meeting notes",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "meeting_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Meeting notes deleted."
          },
          "400": {
            "description": "Active capture must be stopped first."
          }
        }
      }
    },
    "/api/me/meeting-notes/{meeting_id}/workflow": {
      "get": {
        "tags": [
          "Customer"
        ],
        "summary": "Read post-completion workflow status",
        "description": "Owner-only status for an explicitly enabled automatic task handoff, including durable attempts, provider-safe error states, and aggregate results. API keys require meetings:read.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "meeting_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Workflow status returned."
          },
          "403": {
            "description": "Only the owner can view workflow status."
          }
        }
      },
      "post": {
        "tags": [
          "Customer"
        ],
        "summary": "Retry a post-completion workflow",
        "description": "Owner-only retry for an enabled automatic task handoff. The run is queued durably and idempotent provider task records prevent duplicate creation. API keys require meetings:write.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "meeting_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Workflow retry queued."
          },
          "404": {
            "description": "No workflow exists for this meeting."
          },
          "409": {
            "description": "Workflow is running or automatic handoff is disabled."
          }
        }
      }
    },
    "/api/me/meeting-notes/{meeting_id}/audit": {
      "get": {
        "tags": [
          "Customer"
        ],
        "summary": "Read the owner-only meeting activity audit",
        "description": "Returns bounded, redacted lifecycle events for capture, report sharing, comments, delivery, task handoff, and workflow actions. Shared Project readers cannot access the owner's audit. API keys require meetings:read.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "meeting_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Meeting audit events returned."
          },
          "403": {
            "description": "Only the meeting owner can view the audit."
          }
        }
      }
    },
    "/api/me/meeting-notes/{meeting_id}/audio": {
      "get": {
        "tags": [
          "Customer"
        ],
        "summary": "Stream private meeting audio with transcript-compatible byte ranges",
        "description": "Owners and shared-Project readers can stream the completed report's mixed MP3 through an authenticated Kendr proxy. Provider URLs are never returned or persisted. The browser may send one standard Range header. API keys require meetings:read.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "meeting_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Range",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^bytes="
            },
            "description": "A single standard byte range."
          }
        ],
        "responses": {
          "200": {
            "description": "Complete private MP3 stream.",
            "headers": {
              "Accept-Ranges": {
                "schema": {
                  "type": "string",
                  "enum": [
                    "bytes"
                  ]
                }
              },
              "Content-Disposition": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "audio/mpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "206": {
            "description": "Requested MP3 byte range.",
            "headers": {
              "Accept-Ranges": {
                "schema": {
                  "type": "string",
                  "enum": [
                    "bytes"
                  ]
                }
              },
              "Content-Range": {
                "schema": {
                  "type": "string"
                }
              },
              "Content-Disposition": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "audio/mpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "description": "Authentication is required."
          },
          "404": {
            "description": "Meeting report is not visible to this account."
          },
          "503": {
            "description": "The provider media is still processing, expired, or temporarily unavailable."
          }
        }
      }
    },
    "/api/me/meeting-notes/{meeting_id}/start": {
      "post": {
        "tags": [
          "Customer"
        ],
        "summary": "Start the configured meeting capture bot",
        "description": "Starts an owner-controlled capture. API keys require meetings:write. The bot leaves after prolonged inactivity or at the three-hour limit.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "meeting_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Capture is joining or recording."
          },
          "402": {
            "description": "The billing wallet cannot cover the meeting."
          },
          "503": {
            "description": "Capture outcome is ambiguous; retry/status reconciliation is required."
          }
        }
      }
    },
    "/api/me/meeting-notes/{meeting_id}/recover": {
      "post": {
        "tags": [
          "Customer"
        ],
        "summary": "Recover notes from a finalized transcript after a Kendr deadline incident",
        "description": "Owner-only, idempotent repair for a deadline-failed note whose finalized transcript is already durable. Incident recovery charges are waived and historical completion email is suppressed. API keys require meetings:write.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "meeting_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Meeting minutes recovered or an existing completed result returned."
          },
          "400": {
            "description": "The failure is ineligible or no finalized transcript is durable."
          },
          "409": {
            "description": "A concurrent recovery already owns the completion lease."
          }
        }
      }
    },
    "/api/me/meeting-notes/{meeting_id}/settings": {
      "post": {
        "tags": [
          "Customer"
        ],
        "summary": "Enable or disable a scheduled meeting notetaker",
        "description": "Owner-only, scheduled-only action. API keys require meetings:write. Disabled notetakers are never claimed for automatic joining and cannot be started manually.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "meeting_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "notetaker_enabled"
                ],
                "properties": {
                  "notetaker_enabled": {
                    "type": "boolean"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Scheduled notetaker setting updated; returns {ok, meeting}."
          },
          "400": {
            "description": "Payload is invalid or the meeting is no longer scheduled."
          },
          "404": {
            "description": "Owner-controlled meeting not found."
          }
        }
      }
    },
    "/api/me/meeting-notes/{meeting_id}/tasks/{task_id}": {
      "post": {
        "tags": [
          "Customer"
        ],
        "summary": "Update an extracted action item's status, owner, title, or due date",
        "description": "Only the meeting owner may edit action items. Updates are allowed after the report is processing or completed and preserve the rest of the generated report. API keys require meetings:write.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "meeting_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "task_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "open",
                      "in_progress",
                      "completed",
                      "cancelled"
                    ]
                  },
                  "title": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 500
                  },
                  "owner": {
                    "type": "string",
                    "maxLength": 180
                  },
                  "due_at": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time"
                  }
                },
                "minProperties": 1,
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated meeting report returned."
          },
          "400": {
            "description": "Invalid action item payload or report state."
          },
          "403": {
            "description": "Only the meeting owner can edit action items."
          },
          "404": {
            "description": "Meeting or action item not found."
          }
        }
      }
    },
    "/api/me/meeting-notes/{meeting_id}/task-handoffs": {
      "get": {
        "tags": [
          "Customer"
        ],
        "summary": "List external task handoffs for a meeting report",
        "description": "Owner-only audit of approved Google Tasks, Todoist, Slack, Asana, Jira, Microsoft Teams, Microsoft Planner, Linear, and ClickUp handoffs. Provider ids and retry states are returned, but no provider credential is exposed. API keys require meetings:read.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "meeting_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Task handoff audit returned."
          },
          "403": {
            "description": "Only the meeting owner can view task handoffs."
          }
        }
      },
      "post": {
        "tags": [
          "Customer"
        ],
        "summary": "Create approved external tasks from meeting action items",
        "description": "Owner-only, explicit-confirmation workflow for sending action items to Google Tasks, Todoist, a Slack channel, an Asana project, a Jira project, a Microsoft Teams channel, a Microsoft Planner plan or bucket, Linear, or a ClickUp list. Handoffs are idempotent per meeting/task/destination, retain provider status for retry, and require the connector's approved authorization. API keys require meetings:write.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "meeting_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "destination",
                  "task_ids",
                  "confirm"
                ],
                "properties": {
                  "destination": {
                    "type": "string",
                    "enum": [
                      "google_tasks",
                      "todoist",
                      "slack",
                      "asana",
                      "jira",
                      "teams",
                      "planner",
                      "linear",
                      "clickup"
                    ]
                  },
                  "task_ids": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 100,
                    "uniqueItems": true,
                    "items": {
                      "type": "string"
                    }
                  },
                  "target_id": {
                    "type": "string",
                    "maxLength": 320,
                    "description": "Google Task list id, Todoist project id, Slack channel id, Asana project id, Jira cloud id/project key target, Microsoft Teams team_id|channel_id target, Microsoft Planner plan or plan|bucket target, Linear team/team|project target, or ClickUp list id. Omit only for Google Tasks or Todoist defaults."
                  },
                  "confirm": {
                    "type": "boolean",
                    "const": true,
                    "description": "Must be true to prove the owner explicitly approved provider mutation."
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Per-task handoff results returned; status may be partial when one provider call fails."
          },
          "400": {
            "description": "Invalid selection or report state."
          },
          "403": {
            "description": "Owner approval, enterprise policy, connector enablement, or write scope is missing."
          },
          "409": {
            "description": "Connector must be connected or reconnected with write permission."
          }
        }
      }
    },
    "/api/me/meeting-notes/{meeting_id}/notes": {
      "post": {
        "tags": [
          "Customer"
        ],
        "summary": "Save owner-only working notes for a meeting",
        "description": "Owner-only private notes for live capture or report review. Notes are never returned to shared-project readers. API keys require meetings:write.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "meeting_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "notes"
                ],
                "properties": {
                  "notes": {
                    "type": "string",
                    "maxLength": 12000
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Private meeting notes saved and the owner-visible meeting returned."
          },
          "400": {
            "description": "Notes payload is invalid."
          },
          "403": {
            "description": "Only the meeting owner can save private notes."
          },
          "404": {
            "description": "Meeting not found."
          }
        }
      }
    },
    "/api/me/meeting-notes/{meeting_id}/sharing": {
      "post": {
        "tags": [
          "Customer"
        ],
        "summary": "Change or revoke a meeting report's Project audience",
        "description": "Owner-only sharing control. Send a writable project_id to share a completed report with that Project's existing readers, or null to make the report private again. Active captures cannot change audience. Private working notes remain owner-only. API keys require meetings:write.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "meeting_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "project_id"
                ],
                "properties": {
                  "project_id": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 180
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Project audience updated and the owner-visible meeting returned."
          },
          "400": {
            "description": "Payload is invalid or capture is active."
          },
          "403": {
            "description": "Only the meeting owner may change sharing, and the target project must be writable by that owner."
          },
          "404": {
            "description": "Meeting not found."
          }
        }
      }
    },
    "/api/me/meeting-notes/{meeting_id}/share-links": {
      "get": {
        "tags": [
          "Customer"
        ],
        "summary": "List owner-managed meeting report share links",
        "description": "Owner-only inventory of active, expired, and revoked links. The secret token is never returned after creation. API keys require meetings:read.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "meeting_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Share-link inventory returned."
          },
          "403": {
            "description": "Only the meeting owner can manage share links."
          }
        }
      },
      "post": {
        "tags": [
          "Customer"
        ],
        "summary": "Create a revocable meeting report share link",
        "description": "Creates a read-only or signed-in-comment link for a completed report. The one-time secret is returned only in this response; private notes and capture controls are never included. API keys require meetings:write.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "meeting_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "permission": {
                    "type": "string",
                    "enum": [
                      "read",
                      "comment"
                    ],
                    "default": "read"
                  },
                  "expires_in_days": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "minimum": 1,
                    "maximum": 365,
                    "default": 30
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Share link created; the secret token is returned once."
          },
          "400": {
            "description": "Invalid permission, expiry, or report state."
          },
          "403": {
            "description": "Only the meeting owner can create share links."
          }
        }
      }
    },
    "/api/me/meeting-notes/{meeting_id}/share-links/{share_id}": {
      "delete": {
        "tags": [
          "Customer"
        ],
        "summary": "Revoke a meeting report share link",
        "description": "Owner-only immediate revocation. Existing provider media URLs are unaffected because share links never expose them. API keys require meetings:write.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "meeting_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "share_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Share link revoked."
          },
          "404": {
            "description": "Share link not found."
          }
        }
      }
    },
    "/api/shared/meeting-notes/{token}": {
      "get": {
        "tags": [
          "Customer"
        ],
        "summary": "Read a link-shared meeting report",
        "description": "Anonymous read of a completed report through a revocable, expiring opaque token. Private working notes, lifecycle controls, provider URLs, and owner credentials are omitted. Add transcript_offset and transcript_limit for a bounded transcript window (limit 1-500); transcript_query filters speaker/text before pagination.",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 20,
              "maxLength": 500
            }
          },
          {
            "name": "transcript_offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            },
            "description": "Zero-based segment offset for a bounded transcript window."
          },
          {
            "name": "transcript_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 200
            },
            "description": "Maximum transcript segments to return."
          },
          {
            "name": "transcript_query",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "description": "Optional case-insensitive speaker/text filter applied before pagination."
          }
        ],
        "responses": {
          "200": {
            "description": "Shared report returned."
          },
          "404": {
            "description": "Share link is invalid, revoked, expired, or the report was deleted."
          }
        }
      }
    },
    "/api/shared/meeting-notes/{token}/audio": {
      "get": {
        "tags": [
          "Customer"
        ],
        "summary": "Stream audio for a link-shared meeting report",
        "description": "Anonymous byte-range audio playback authorized by the same revocable share token. Kendr proxies the provider media and never redirects to or returns the provider URL.",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 20,
              "maxLength": 500
            }
          },
          {
            "name": "Range",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^bytes="
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Private MP3 stream authorized by the share token.",
            "content": {
              "audio/mpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "206": {
            "description": "Requested MP3 byte range.",
            "content": {
              "audio/mpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "404": {
            "description": "Share link is invalid, revoked, expired, or the report was deleted."
          },
          "503": {
            "description": "Provider audio is still processing, expired, or temporarily unavailable."
          }
        }
      }
    },
    "/api/shared/meeting-notes/{token}/comments": {
      "post": {
        "tags": [
          "Customer"
        ],
        "summary": "Add a signed-in comment through a comment-enabled share link",
        "description": "Requires a Kendr account session and a share link created with comment permission. The share secret controls report access; the signed-in account identifies the commenter.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 20,
              "maxLength": 500
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "body"
                ],
                "properties": {
                  "body": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4000
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Comment added."
          },
          "401": {
            "description": "A Kendr account session is required to comment."
          },
          "403": {
            "description": "The share link is read-only."
          },
          "404": {
            "description": "Share link is invalid, revoked, or expired."
          }
        }
      }
    },
    "/api/me/meeting-notes/{meeting_id}/summary-delivery": {
      "get": {
        "tags": [
          "Customer"
        ],
        "summary": "Read per-recipient completed-summary delivery status",
        "description": "Owner-only delivery audit showing validated recipient address, provenance, retry count, and status. API keys require meetings:read.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "meeting_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Summary delivery audit returned."
          },
          "403": {
            "description": "Only the meeting owner may view delivery recipients."
          }
        }
      }
    },
    "/api/me/meeting-notes/{meeting_id}/summary-delivery/retry": {
      "post": {
        "tags": [
          "Customer"
        ],
        "summary": "Retry failed summary recipients",
        "description": "Owner-only explicit retry. Sent recipients are never requeued, and automatic email must currently be enabled. API keys require meetings:write.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "meeting_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Eligible recipients requeued and current delivery state returned."
          },
          "400": {
            "description": "Meeting is incomplete or automatic email is disabled."
          }
        }
      }
    },
    "/api/me/meeting-notes/{meeting_id}/comments": {
      "get": {
        "tags": [
          "Customer"
        ],
        "summary": "List collaboration comments on a completed meeting report",
        "description": "Owners and members with shared-Project read access can list comments. API keys require meetings:read.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "meeting_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Comment thread returned."
          },
          "404": {
            "description": "Meeting report not found."
          }
        }
      },
      "post": {
        "tags": [
          "Customer"
        ],
        "summary": "Comment on a completed meeting report",
        "description": "Owners and members with shared-Project contribute access can comment. API keys require meetings:write.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "meeting_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "body"
                ],
                "properties": {
                  "body": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4000
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Comment created."
          },
          "403": {
            "description": "Project contribute access is required."
          },
          "404": {
            "description": "Meeting report not found."
          }
        }
      }
    },
    "/api/me/meeting-notes/{meeting_id}/comments/{comment_id}": {
      "delete": {
        "tags": [
          "Customer"
        ],
        "summary": "Delete a meeting-report comment",
        "description": "The comment author or meeting owner may delete it. API keys require meetings:write.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "meeting_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "comment_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Comment deleted."
          },
          "403": {
            "description": "Only the author or meeting owner may delete the comment."
          },
          "404": {
            "description": "Meeting report or comment not found."
          }
        }
      }
    },
    "/api/me/meeting-notes/{meeting_id}/stop": {
      "post": {
        "tags": [
          "Customer"
        ],
        "summary": "Stop capture and begin meeting-note finalization",
        "description": "Live providers finalize asynchronously via their authenticated webhook. Signed provider usage is settled internally before the configured exact meeting-summary model builds the report. API keys require meetings:write. The explicitly enabled local development provider may accept transcript segments in this request.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "meeting_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Capture stopped or processing."
          }
        }
      }
    },
    "/api/me/connectors/{connector_key}/start": {
      "post": {
        "tags": [
          "Connectors"
        ],
        "summary": "Start OAuth authorization for an enabled application connector",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "connector_key",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConnectorStartRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Authorization URL and expiring state returned."
          }
        }
      }
    },
    "/api/me/connectors/{connector_key}/invoke": {
      "post": {
        "tags": [
          "Connectors"
        ],
        "summary": "Run one read-only tool on a connected application connector",
        "description": "Kendr resolves and refreshes the stored OAuth credential, calls the provider, and returns only the result. The access token is never sent to the client, and connectors expose read-only tools only. Read invocable_tools on /api/me/connectors to discover the available tool names and argument schemas.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "connector_key",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "tool"
                ],
                "properties": {
                  "tool": {
                    "type": "string"
                  },
                  "arguments": {
                    "type": "object"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result returned."
          },
          "404": {
            "description": "Connector or tool is not invocable."
          },
          "409": {
            "description": "The connector must be connected or reconnected."
          },
          "502": {
            "description": "The provider rejected the request."
          }
        }
      }
    },
    "/api/me/connectors/{connector_key}/disconnect": {
      "post": {
        "tags": [
          "Connectors"
        ],
        "summary": "Disconnect the user's account from an application connector",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "connector_key",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Stored user authorization was revoked or removed."
          }
        }
      }
    },
    "/api/me/mcp-servers": {
      "get": {
        "tags": [
          "Connectors"
        ],
        "summary": "List remote MCP servers configured by the signed-in user",
        "description": "Returns server metadata and encrypted credential state. Stored authorization and custom-header values are never returned.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "MCP server configurations returned without secrets."
          }
        }
      },
      "post": {
        "tags": [
          "Connectors"
        ],
        "summary": "Create or update a trusted remote MCP server",
        "description": "Stores optional authorization and custom HTTP headers encrypted. Pass an existing id to update without replacing stored credentials. When account MCP verification is enabled, provide a recent X-Kendr-MCP-Verification token.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "X-Kendr-MCP-Verification",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "format": "password"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name",
                  "server_label",
                  "server_url",
                  "trusted"
                ],
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  },
                  "server_label": {
                    "type": "string",
                    "pattern": "^[A-Za-z0-9_-]+$"
                  },
                  "server_url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "description": {
                    "type": "string"
                  },
                  "authorization": {
                    "type": "string",
                    "format": "password"
                  },
                  "clear_authorization": {
                    "type": "boolean"
                  },
                  "headers": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string",
                      "format": "password"
                    }
                  },
                  "clear_headers": {
                    "type": "boolean"
                  },
                  "allowed_tools": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "enabled": {
                    "type": "boolean"
                  },
                  "trusted": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "MCP server configuration saved."
          },
          "428": {
            "description": "Account-email verification is required."
          }
        }
      }
    },
    "/api/me/mcp-servers/{server_id}": {
      "delete": {
        "tags": [
          "Connectors"
        ],
        "summary": "Delete one of the signed-in user's MCP server configurations",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "server_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Kendr-MCP-Verification",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "format": "password"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "MCP server configuration deleted."
          },
          "428": {
            "description": "Account-email verification is required."
          }
        }
      }
    },
    "/api/me/security": {
      "get": {
        "tags": [
          "Connectors"
        ],
        "summary": "Read account security settings for MCP configuration changes",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "MCP account-security state and masked email returned."
          }
        }
      }
    },
    "/api/me/security/mcp-verification/request": {
      "post": {
        "tags": [
          "Connectors"
        ],
        "summary": "Send an MCP configuration verification code to the account email",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "201": {
            "description": "A short-lived verification challenge was created."
          }
        }
      }
    },
    "/api/me/security/mcp-verification/verify": {
      "post": {
        "tags": [
          "Connectors"
        ],
        "summary": "Exchange an account-email code for a short-lived MCP change token",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "challenge_id",
                  "code"
                ],
                "properties": {
                  "challenge_id": {
                    "type": "string"
                  },
                  "code": {
                    "type": "string",
                    "pattern": "^[0-9]{6}$"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A short-lived verification token was returned."
          }
        }
      }
    },
    "/api/me/security/mcp-verification/settings": {
      "post": {
        "tags": [
          "Connectors"
        ],
        "summary": "Enable or disable two-step verification for MCP configuration changes",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "X-Kendr-MCP-Verification",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "password"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "enabled"
                ],
                "properties": {
                  "enabled": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "MCP change-verification setting updated."
          },
          "428": {
            "description": "Account-email verification is required."
          }
        }
      }
    },
    "/api/skills/catalog": {
      "get": {
        "tags": [
          "Marketplace"
        ],
        "summary": "List public Kendr skill packs and install metadata",
        "responses": {
          "200": {
            "description": "Public skill-pack catalog returned."
          }
        }
      }
    },
    "/api/skills/packs/{slug}": {
      "get": {
        "tags": [
          "Marketplace"
        ],
        "summary": "Read one public skill-pack manifest",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Skill-pack detail returned."
          },
          "404": {
            "description": "Skill pack not found."
          }
        }
      }
    },
    "/api/skills/packs/{slug}/archive": {
      "get": {
        "tags": [
          "Marketplace"
        ],
        "summary": "Download a published skill-pack archive",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "ZIP archive returned."
          }
        }
      }
    },
    "/api/workflows/packs/{slug}": {
      "get": {
        "tags": [
          "Marketplace"
        ],
        "summary": "Read one public workflow-pack manifest",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Workflow-pack detail returned."
          },
          "404": {
            "description": "Workflow pack not found."
          }
        }
      }
    },
    "/api/kb/cloud/{kb_id}/runs": {
      "get": {
        "tags": [
          "Cloud KB"
        ],
        "summary": "List recent indexing and rebuild runs for a Cloud KB",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "kb_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Pipeline runs returned."
          }
        }
      }
    },
    "/api/kb/cloud/{kb_id}/evaluations": {
      "get": {
        "tags": [
          "Cloud KB"
        ],
        "summary": "List recent retrieval evaluations for a Cloud KB",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "kb_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Evaluation history returned."
          }
        }
      }
    },
    "/api/kb/cloud/{kb_id}": {
      "patch": {
        "tags": [
          "Cloud KB"
        ],
        "summary": "Rename a Cloud KB or update its description",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "kb_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 180
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 1000
                  }
                },
                "minProperties": 1,
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Cloud KB metadata updated and audited."
          }
        }
      },
      "delete": {
        "tags": [
          "Cloud KB"
        ],
        "summary": "Delete a Cloud KB owned by the caller",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "kb_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Cloud KB and its managed artifacts were deleted."
          }
        }
      }
    },
    "/api/admin/rewards": {
      "get": {
        "tags": [
          "Admin"
        ],
        "summary": "List reward submissions and verification-review counts",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "draft",
                "verifying",
                "needs_review",
                "approved",
                "rejected"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Reward claims and review queue counts returned."
          }
        }
      }
    },
    "/api/admin/social-profiles": {
      "get": {
        "tags": [
          "Admin"
        ],
        "summary": "Read administrator-managed social profiles",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "responses": {
          "200": {
            "description": "Known and custom social profiles returned."
          }
        }
      },
      "post": {
        "tags": [
          "Admin"
        ],
        "summary": "Replace administrator-managed social profiles",
        "description": "Validates public HTTPS platform profiles, persists the complete configuration, and updates rewards and public website links.",
        "security": [
          {
            "sessionCookie": []
          },
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AdminSocialProfilesRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Social profiles saved."
          },
          "400": {
            "description": "One or more social profiles are invalid."
          },
          "409": {
            "description": "The submitted social-profile revision is stale."
          }
        }
      }
    },
    "/api/admin/rewards/review": {
      "post": {
        "tags": [
          "Admin"
        ],
        "summary": "Approve or reject a reward claim after AI pre-verification",
        "description": "Approval locks the claim, grants personal-wallet credits through the canonical ledger, and records the ledger id in the same transaction.",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AdminRewardReviewRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Claim reviewed and refreshed review queue returned."
          },
          "400": {
            "description": "Claim state or review decision is invalid."
          }
        }
      }
    },
    "/api/admin/users": {
      "get": {
        "tags": [
          "Admin"
        ],
        "summary": "List customer accounts with usage and activity aggregates",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000,
              "default": 300
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Customer accounts and aggregate account activity returned."
          }
        }
      },
      "post": {
        "tags": [
          "Admin"
        ],
        "summary": "Create or update a customer account",
        "description": "Updates identity, display name, account role, active and email-verification state, and an optional replacement password for compatible clients. Accounts and enterprise owners provisioned by a Kendr administrator are verified at creation.",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AdminUserUpsertRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Customer account saved and complete detail returned."
          }
        }
      }
    },
    "/api/admin/enterprise/organizations": {
      "get": {
        "tags": [
          "Admin",
          "Enterprise"
        ],
        "summary": "List enterprise organizations, seats, wallet balances, KB counts, and usage",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Enterprise organization directory returned.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "organizations": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/EnterpriseOrganization"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Admin",
          "Enterprise"
        ],
        "summary": "Provision an enterprise organization and its owner",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "organization_name",
                  "owner_email"
                ],
                "properties": {
                  "organization_name": {
                    "type": "string"
                  },
                  "owner_email": {
                    "type": "string",
                    "format": "email"
                  },
                  "owner_name": {
                    "type": "string"
                  },
                  "seat_limit": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "allowed_domain": {
                    "type": "string"
                  },
                  "initial_credits": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "settings": {
                    "$ref": "#/components/schemas/EnterpriseSettings"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Enterprise organization provisioned with an organization-scoped wallet."
          }
        }
      }
    },
    "/api/admin/enterprise/organizations/update": {
      "post": {
        "tags": [
          "Admin",
          "Enterprise"
        ],
        "summary": "Update an enterprise profile, wallet, policy, or lifecycle state",
        "description": "Suspension and closure require an exact organization name or slug confirmation plus a reason. A request carrying only a credit delta is treated as a wallet adjustment and needs no second factor below `KENDR_ADMIN_CREDIT_STEP_UP_THRESHOLD`; at or above it, and for any request that also changes an organization field, the operator must confirm with the emailed code.",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "organization_id"
                ],
                "properties": {
                  "organization_id": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "name": {
                    "type": "string"
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "active",
                      "suspended",
                      "closed"
                    ]
                  },
                  "confirmation": {
                    "type": "string"
                  },
                  "reason": {
                    "type": "string"
                  },
                  "seat_limit": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "allowed_domain": {
                    "type": "string"
                  },
                  "settings": {
                    "$ref": "#/components/schemas/EnterpriseSettings"
                  },
                  "credits_delta": {
                    "type": "integer",
                    "description": "Whole-credit central-wallet adjustment (positive grants, negative deducts)."
                  },
                  "credit_micros_delta": {
                    "type": "integer"
                  },
                  "credit_description": {
                    "type": "string"
                  },
                  "billing_profile": {
                    "type": "object",
                    "description": "Account contact and paperwork. Narrower than the tenant-facing billing save on purpose: alert thresholds, renewal dates, and currency stay with the account so an operator edit cannot re-arm a low-balance alert.",
                    "properties": {
                      "legal_entity_name": {
                        "type": "string"
                      },
                      "billing_address": {
                        "type": "string"
                      },
                      "contact_name": {
                        "type": "string"
                      },
                      "contact_email": {
                        "type": "string",
                        "format": "email"
                      },
                      "contact_phone": {
                        "type": "string",
                        "description": "Kept as typed, minus undiallable characters; 6 to 20 digits."
                      },
                      "tax_id": {
                        "type": "string"
                      },
                      "purchase_order": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Enterprise organization updated and audited."
          }
        }
      }
    },
    "/api/admin/enterprise/organizations/detail": {
      "get": {
        "tags": [
          "Admin",
          "Enterprise"
        ],
        "summary": "Full operator view of one enterprise organization",
        "description": "Members with role, access and per-member usage, invitations, billing profile and contacts, knowledge bases, and the most recent audit events. Assembled from the organization id rather than a membership, because an operator holds none in the tenant.",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Organization detail returned."
          },
          "400": {
            "description": "The organization id is missing or does not name an enterprise organization."
          }
        }
      }
    },
    "/api/admin/enterprise/organizations/members": {
      "post": {
        "tags": [
          "Admin",
          "Enterprise"
        ],
        "summary": "Change membership, invitations, or ownership of an enterprise organization",
        "description": "Actions: `update` (role, status, billing access, spend ceiling), `offboard` (remove or suspend, with a knowledge-ownership disposition), `invite`, `revoke_invitation`, and `transfer` (canonical ownership, billing responsibility, or both). A Kendr-admin invitation creates or reactivates the account and marks its current address verified, so the member does not repeat account verification. Ownership and billing must land on active members, the account must keep an active owner, and a transfer requires an exact name/slug confirmation plus a reason. Closed organizations reject membership changes until reactivated.",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "organization_id",
                  "action"
                ],
                "properties": {
                  "organization_id": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "action": {
                    "type": "string",
                    "enum": [
                      "update",
                      "offboard",
                      "invite",
                      "revoke_invitation",
                      "transfer"
                    ]
                  },
                  "user_id": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "role": {
                    "type": "string",
                    "enum": [
                      "admin",
                      "billing",
                      "member",
                      "viewer"
                    ]
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "active",
                      "suspended"
                    ]
                  },
                  "billing_enabled": {
                    "type": "boolean"
                  },
                  "spend_limit_micros": {
                    "type": "integer",
                    "minimum": 0,
                    "nullable": true
                  },
                  "mode": {
                    "type": "string",
                    "enum": [
                      "removed",
                      "suspended"
                    ]
                  },
                  "reason": {
                    "type": "string"
                  },
                  "invitation_id": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "transfer": {
                    "type": "string",
                    "enum": [
                      "ownership",
                      "billing",
                      "both"
                    ]
                  },
                  "confirmation": {
                    "type": "string"
                  },
                  "demote_previous_owner": {
                    "type": "boolean",
                    "default": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Membership change applied and audited; refreshed organization detail returned. An invite whose email could not be sent returns `delivery_status: \"manual\"` with a one-time link."
          },
          "400": {
            "description": "The action, target, or confirmation is invalid, or an invariant would be broken."
          }
        }
      }
    },
    "/api/admin/enterprise/organizations/purge": {
      "post": {
        "tags": [
          "Admin",
          "Enterprise"
        ],
        "summary": "Permanently purge a closed enterprise organization",
        "description": "Immediately erases a CLOSED tenant and its data, bypassing the retention wait. Requires an exact name/slug confirmation and a reason. Legal hold blocks the purge, and the organization must already be closed. Irreversible.",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "organization_id",
                  "confirmation",
                  "reason"
                ],
                "properties": {
                  "organization_id": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "confirmation": {
                    "type": "string",
                    "description": "Exact organization name or slug."
                  },
                  "reason": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Purge completed or erasure started; result status is returned."
          },
          "403": {
            "description": "The caller is not an administrator, or the organization is under legal hold."
          }
        }
      }
    },
    "/api/public/plans": {
      "get": {
        "tags": [
          "Public",
          "Billing"
        ],
        "summary": "Public catalog of credit passes",
        "description": "Plus, Pro, Max and Superman as 30-day passes with a weekly credit allowance and a discount against the pay-as-you-go bands, plus the School plan facts. Read from the admin-managed catalog.",
        "responses": {
          "200": {
            "description": "Plan catalog returned."
          }
        }
      }
    },
    "/api/admin/plans": {
      "get": {
        "tags": [
          "Admin",
          "Billing"
        ],
        "summary": "Read the credit plan catalog",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Catalog, revision, and history returned."
          }
        }
      },
      "post": {
        "tags": [
          "Admin",
          "Billing"
        ],
        "summary": "Save the credit plan catalog",
        "description": "Revision-guarded. Each plan carries slug, name, weekly credits, period days, rollover, renewal window, and prices per currency.",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Catalog saved."
          },
          "409": {
            "description": "The catalog changed since it was loaded."
          }
        }
      }
    },
    "/api/admin/plans/periods": {
      "get": {
        "tags": [
          "Admin",
          "Billing"
        ],
        "summary": "List an account's plan periods across every pass",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Periods returned."
          }
        }
      }
    },
    "/api/admin/plans/grant": {
      "post": {
        "tags": [
          "Admin",
          "Billing"
        ],
        "summary": "Grant or renew a paid pass for an account",
        "description": "Starts a period and releases the first weekly tranche. A plan whose weekly tranche reaches the credit step-up threshold requires the emailed administrator code.",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Period granted."
          }
        }
      }
    },
    "/api/admin/plans/revoke": {
      "post": {
        "tags": [
          "Admin",
          "Billing"
        ],
        "summary": "Revoke an account's active pass, optionally forfeiting remaining credits",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Period revoked."
          }
        }
      }
    },
    "/api/admin/school/overview": {
      "get": {
        "tags": [
          "Admin",
          "School"
        ],
        "summary": "School plan overview: needs-action counts, funnel, credit exposure, sweep health",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Overview returned."
          }
        }
      }
    },
    "/api/admin/school/settings": {
      "get": {
        "tags": [
          "Admin",
          "School"
        ],
        "summary": "Read the school plan settings document",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Settings, revision, and history returned."
          }
        }
      },
      "post": {
        "tags": [
          "Admin",
          "School"
        ],
        "summary": "Save the school plan settings document",
        "description": "Revision-guarded: pass expected_revision from the last read. Allowance, period, pricing display, eligibility defaults, verification policy, and email toggles. Values are frozen onto periods at activation.",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Settings saved."
          },
          "409": {
            "description": "The document changed since it was loaded."
          }
        }
      }
    },
    "/api/admin/school/domains": {
      "get": {
        "tags": [
          "Admin",
          "School"
        ],
        "summary": "List approved, pending, and paused institutions",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Institutions returned."
          }
        }
      },
      "post": {
        "tags": [
          "Admin",
          "School"
        ],
        "summary": "Create or update an institution",
        "description": "Refuses public mailbox domains and bare academic suffixes. Approval requires the verification policy to be met.",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Institution saved."
          }
        }
      }
    },
    "/api/admin/school/learners": {
      "get": {
        "tags": [
          "Admin",
          "School"
        ],
        "summary": "List learners with their period and this week's allowance",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "requested",
                "approved",
                "declined",
                "revoked"
              ]
            }
          },
          {
            "name": "domain_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "user_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Learners returned."
          }
        }
      }
    },
    "/api/admin/school/learners/approve": {
      "post": {
        "tags": [
          "Admin",
          "School"
        ],
        "summary": "Approve a learner and start their period with the first weekly tranche",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Learner approved."
          }
        }
      }
    },
    "/api/admin/school/learners/grant": {
      "post": {
        "tags": [
          "Admin",
          "School"
        ],
        "summary": "Grant or renew a period for any account on an approved institution",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Period granted."
          }
        }
      }
    },
    "/api/admin/school/learners/bulk-approve": {
      "post": {
        "tags": [
          "Admin",
          "School"
        ],
        "summary": "Approve every requested learner of an institution",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Approvals and failures returned."
          }
        }
      }
    },
    "/api/admin/school/learners/decline": {
      "post": {
        "tags": [
          "Admin",
          "School"
        ],
        "summary": "Decline a pending learner request with a reason",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Learner declined."
          }
        }
      }
    },
    "/api/admin/school/learners/revoke": {
      "post": {
        "tags": [
          "Admin",
          "School"
        ],
        "summary": "Revoke a learner's access, optionally forfeiting remaining school credits",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Learner revoked."
          }
        }
      }
    },
    "/api/admin/school/learners/extend": {
      "post": {
        "tags": [
          "Admin",
          "School"
        ],
        "summary": "Extend a running period by whole weeks",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Period extended."
          }
        }
      }
    },
    "/api/admin/school/applications": {
      "get": {
        "tags": [
          "Admin",
          "School"
        ],
        "summary": "List institution applications with verification evidence",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Applications returned."
          }
        }
      }
    },
    "/api/admin/school/applications/contact": {
      "post": {
        "tags": [
          "Admin",
          "School"
        ],
        "summary": "Email the institution contact a sign-in link that verifies their address",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Verification email queued."
          }
        }
      }
    },
    "/api/admin/school/applications/dns-token": {
      "post": {
        "tags": [
          "Admin",
          "School"
        ],
        "summary": "Issue the DNS TXT record an institution can publish to prove its domain",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Record returned."
          }
        }
      }
    },
    "/api/admin/school/applications/dns-check": {
      "post": {
        "tags": [
          "Admin",
          "School"
        ],
        "summary": "Check the institution's DNS TXT record",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Check result returned."
          }
        }
      }
    },
    "/api/admin/school/applications/onboard": {
      "post": {
        "tags": [
          "Admin",
          "School"
        ],
        "summary": "Approve the institution, close the application, and email the contact",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Institution onboarded."
          }
        }
      }
    },
    "/api/admin/school/applications/close": {
      "post": {
        "tags": [
          "Admin",
          "School"
        ],
        "summary": "Close an application with a reason",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Application closed."
          }
        }
      }
    },
    "/api/admin/enterprise/inquiries": {
      "get": {
        "tags": [
          "Admin"
        ],
        "summary": "List enterprise pricing inquiries",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "new",
                "contacted",
                "qualified",
                "onboarded",
                "closed"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000,
              "default": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Enterprise inquiries returned."
          }
        }
      },
      "post": {
        "tags": [
          "Admin"
        ],
        "summary": "Update enterprise inquiry follow-up status",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "id"
                ],
                "properties": {
                  "id": {
                    "type": "integer"
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "new",
                      "contacted",
                      "qualified",
                      "onboarded",
                      "closed"
                    ]
                  },
                  "notes": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Inquiry updated and refreshed list returned."
          }
        }
      }
    },
    "/api/admin/enterprise/inquiries/onboard": {
      "post": {
        "tags": [
          "Admin"
        ],
        "summary": "Create an enterprise organization from an inquiry",
        "description": "Creates or reuses the owner user, creates the enterprise organization, default workspace, central billing membership, optional initial credit grant, audit event, and links the inquiry.",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "inquiry_id"
                ],
                "properties": {
                  "inquiry_id": {
                    "type": "integer"
                  },
                  "organization_name": {
                    "type": "string"
                  },
                  "owner_email": {
                    "type": "string",
                    "format": "email"
                  },
                  "owner_name": {
                    "type": "string"
                  },
                  "allowed_domain": {
                    "type": "string"
                  },
                  "seat_limit": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 1000
                  },
                  "initial_credits": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "notes": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Enterprise organization onboarded from inquiry."
          }
        }
      }
    },
    "/api/admin/users/{user_id}": {
      "get": {
        "tags": [
          "Admin"
        ],
        "summary": "Read one account and its purchases, ledger, model usage, keys, app activity, downloads, errors, and feedback",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Complete account activity detail returned."
          }
        }
      }
    },
    "/api/admin/users/credits": {
      "post": {
        "tags": [
          "Admin"
        ],
        "summary": "Apply an audited credit adjustment to a customer wallet",
        "description": "Adjustments below `KENDR_ADMIN_CREDIT_STEP_UP_THRESHOLD` (default 10,000 credits) need no second factor: granting credits is routine support work. They remain admin-only, still require a written reason of at least four characters, and the ledger entry names the operator and records `step_up: \"not_required\"`. At or above the threshold -- in either direction, since removing credits is no less consequential -- the operator must confirm with the emailed code, and the request answers `403` with `status: \"step_up_required\"` until it carries a verified token. A second operator's approval is honoured when `approval_request_id` is supplied but is never demanded by amount.",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AdminCreditAdjustmentRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Wallet adjusted and refreshed account detail returned."
          },
          "403": {
            "description": "A second operator's approval is required for an adjustment of this size."
          }
        }
      }
    },
    "/api/admin/connectors": {
      "get": {
        "tags": [
          "Admin"
        ],
        "summary": "List model-provider connectors and discovered provider models",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Connector health, credential hints, and model enablement returned."
          }
        }
      }
    },
    "/api/admin/connectors/{provider_key}": {
      "put": {
        "tags": [
          "Admin"
        ],
        "summary": "Save an encrypted provider credential and connector configuration",
        "description": "Native model and search providers use their documented default base URL. Amazon Bedrock additionally requires the API-key region. Supplying an empty api_key preserves the current secret unless clear_api_key is true.",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "provider_key",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "bedrock",
                "openai",
                "anthropic",
                "google",
                "xai",
                "deepseek",
                "zai",
                "qwen",
                "byteplus",
                "kimi",
                "mistral",
                "sarvam",
                "tokenra",
                "ollama",
                "brave_search",
                "jev",
                "typesafe"
              ]
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AdminModelConnectorRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Connector configuration saved without returning the secret."
          }
        }
      }
    },
    "/api/admin/connectors/{provider_key}/test": {
      "post": {
        "tags": [
          "Admin"
        ],
        "summary": "Test a provider credential and discover available models",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "provider_key",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Connection health and discovered model count returned."
          }
        }
      }
    },
    "/api/admin/connectors/{provider_key}/decide": {
      "post": {
        "tags": [
          "Admin"
        ],
        "summary": "Evaluate typed Jev decisions with an enabled, tested connector",
        "description": "Uses provider credits. Jev returns choice, score, or noul answers; this does not change live model routing. The hosted jev service and direct typesafe service use separate credentials.",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "provider_key",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "jev",
                "typesafe"
              ]
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "state",
                  "questions"
                ],
                "additionalProperties": false,
                "properties": {
                  "model": {
                    "type": "string",
                    "default": "jev-1.13.0"
                  },
                  "state": {
                    "oneOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "object"
                      },
                      {
                        "type": "array"
                      }
                    ]
                  },
                  "questions": {
                    "type": "object",
                    "minProperties": 1,
                    "maxProperties": 64,
                    "additionalProperties": {
                      "type": "object",
                      "required": [
                        "type",
                        "instructions"
                      ],
                      "properties": {
                        "type": {
                          "type": "string",
                          "enum": [
                            "choice",
                            "score",
                            "noul"
                          ]
                        },
                        "instructions": {
                          "oneOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "object"
                            },
                            {
                              "type": "array"
                            }
                          ]
                        },
                        "criteria": {
                          "description": "Choice: 1\u2013255 option descriptions; score: 2\u201310 ordered levels; noul: optional true/false descriptions.",
                          "oneOf": [
                            {
                              "type": "object"
                            },
                            {
                              "type": "array"
                            }
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Resolved model, validated typed answers, and provider usage."
          },
          "400": {
            "description": "Invalid decision request."
          },
          "503": {
            "description": "Connector disabled or connection test required."
          }
        }
      }
    },
    "/api/admin/connectors/{provider_key}/models/{model_id}": {
      "patch": {
        "tags": [
          "Admin"
        ],
        "summary": "Enable or disable one discovered provider model",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "provider_key",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "model_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AdminProviderModelAccessRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Provider-model enablement updated."
          }
        }
      }
    },
    "/api/admin/app-connectors": {
      "get": {
        "tags": [
          "Admin"
        ],
        "summary": "List OAuth application providers and user-facing connector services",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Provider setup metadata, callback URL, and service configuration returned."
          }
        }
      }
    },
    "/api/admin/app-connectors/providers/{provider}": {
      "post": {
        "tags": [
          "Admin"
        ],
        "summary": "Save an OAuth application registration for an application provider",
        "description": "Stores client ID, an encrypted client secret, tenant information when applicable, and approved authorization/token URL overrides.",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "provider",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AdminAppConnectorProviderRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Provider registration saved without returning the secret."
          }
        }
      }
    },
    "/api/admin/app-connectors/{connector_key}": {
      "post": {
        "tags": [
          "Admin"
        ],
        "summary": "Enable or disable one user-facing application connector",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "connector_key",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AdminAppConnectorRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Application connector configuration updated."
          }
        }
      }
    },
    "/api/admin/llm-models": {
      "get": {
        "tags": [
          "Admin"
        ],
        "summary": "List governed model aliases and healthy provider routes",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Aliases and routes returned."
          }
        }
      }
    },
    "/api/admin/llm-models/{alias}": {
      "patch": {
        "tags": [
          "Admin"
        ],
        "summary": "Update a governed model alias or provider-route role",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "alias",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AdminModelUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Alias configuration updated."
          }
        }
      }
    },
    "/api/admin/routing/policies": {
      "get": {
        "tags": [
          "Admin"
        ],
        "summary": "List signed model-routing policy artifacts",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Routing policies returned."
          }
        }
      },
      "post": {
        "tags": [
          "Admin"
        ],
        "summary": "Publish and optionally activate a signed routing policy artifact",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AdminRoutingPolicyRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Routing policy stored."
          }
        }
      }
    },
    "/api/admin/routing/cost-controls": {
      "get": {
        "tags": [
          "Admin"
        ],
        "summary": "Read live Admin-authoritative routing and generation cost controls",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "All managed-product cost controls returned."
          }
        }
      },
      "patch": {
        "tags": [
          "Admin"
        ],
        "summary": "Update one managed product's routing and generation cost controls",
        "description": "Changes apply to new immutable plans. Generation defaults also act as ceilings; unsupported exact controls fail closed.",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AdminRoutingCostControlUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Validated controls saved for new plans."
          }
        }
      }
    },
    "/api/admin/routing/optimizer": {
      "get": {
        "tags": [
          "Admin"
        ],
        "summary": "Read optimizer rollout, quality-guard, fallback, and estimated token savings telemetry",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Thirty-day optimizer summary returned."
          }
        }
      }
    },
    "/api/admin/routing/optimizer/settings": {
      "get": {
        "tags": [
          "Admin"
        ],
        "summary": "Read live optimizer rollout and compression settings",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Optimizer settings returned."
          }
        }
      },
      "patch": {
        "tags": [
          "Admin"
        ],
        "summary": "Update optimizer rollout settings without restarting Router API",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AdminOptimizerSettingsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Validated optimizer settings saved."
          }
        }
      }
    },
    "/api/admin/billing/usage": {
      "get": {
        "tags": [
          "Admin"
        ],
        "summary": "Read aggregate model token, provider-cost, Kendr-cost, and microcredit usage",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Aggregate usage totals returned."
          }
        }
      }
    },
    "/api/v1/query": {
      "post": {
        "tags": [
          "Query"
        ],
        "summary": "Execute a hosted Kendr query",
        "description": "Accepts one Kendr surface request and charges credits only after successful execution. The web_search surface is served by Kendr Web Search.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UnifiedQueryRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Query completed successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UnifiedQueryResponse"
                }
              }
            }
          },
          "400": {
            "description": "Payload or params were invalid."
          },
          "401": {
            "description": "No valid API key, app session header, OAuth bearer token, or customer session was supplied."
          },
          "402": {
            "description": "Not enough credits remain in the wallet."
          },
          "502": {
            "description": "The request could not be completed."
          }
        }
      }
    },
    "/api/v1/llm/models": {
      "get": {
        "tags": [
          "LLM"
        ],
        "summary": "List Kendr-hosted LLM aliases and credit pricing",
        "description": "Returns Kendr-branded model aliases, upstream provider mappings, availability, and credit rates. Provider keys are never returned.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Hosted LLM model catalog returned.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HostedLlmModelsResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/models": {
      "get": {
        "tags": [
          "Models"
        ],
        "summary": "List available Kendr aliases using the OpenAI model-list shape",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "responses": {
          "200": {
            "description": "OpenAI-compatible model list returned."
          }
        }
      }
    },
    "/v1/responses": {
      "post": {
        "tags": [
          "Models"
        ],
        "summary": "Generate an OpenAI-compatible response through Kendr Cloud",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional. Supply a stable value for retry-safe replays; one is generated per request when absent."
          },
          {
            "name": "X-Kendr-Idempotency-Replay-Only",
            "in": "header",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false
            },
            "description": "Recovery only. With true, this request may return an existing settled replay but can never plan, reserve credits, or invoke a provider. Send the exact original body and Idempotency-Key."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/HostedLlmResponseRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Response completed and Kendr credits charged once. With stream=true, the content type is text/event-stream."
          },
          "401": {
            "description": "Kendr API key is missing or invalid."
          },
          "402": {
            "description": "Wallet balance cannot cover the reservation."
          },
          "429": {
            "description": "Per-user request limit exceeded."
          },
          "502": {
            "description": "The selected provider route failed before successful settlement; the reservation is released."
          }
        }
      }
    },
    "/v1/chat/completions": {
      "post": {
        "tags": [
          "Models"
        ],
        "summary": "Generate an OpenAI-compatible chat completion through Kendr Cloud",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Kendr-Idempotency-Replay-Only",
            "in": "header",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false
            },
            "description": "Lookup-only recovery for the exact original body and idempotency key; never starts a generation."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/HostedLlmResponseRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Chat completion returned with kendr_usage billing metadata."
          }
        }
      }
    },
    "/v1/voice/voices": {
      "get": {
        "tags": [
          "Voice"
        ],
        "operationId": "listVoiceVoices",
        "summary": "Discover realtime voices and audio configuration",
        "description": "Requires API-key models:read. Returns allowed IDs, protocol, PCM formats, frame size, and configured duration; does not invoke the provider or guarantee available capacity. File-audio voices are a different catalog.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-required-scopes": [
          "models:read"
        ],
        "responses": {
          "200": {
            "description": "Voice catalog.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoiceCatalogResponse"
                }
              }
            }
          },
          "400": {
            "description": "Malformed request or WebSocket upgrade.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoiceHttpError"
                }
              }
            }
          },
          "401": {
            "description": "A valid Kendr API key is required; app sessions and OAuth are not accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoiceHttpError"
                }
              }
            }
          },
          "403": {
            "description": "Required API-key scope missing or supplied Origin is untrusted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoiceHttpError"
                }
              }
            }
          },
          "503": {
            "description": "Voice service or authentication dependency unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoiceHttpError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/voice/stream": {
      "get": {
        "tags": [
          "Voice"
        ],
        "operationId": "openVoiceStream",
        "summary": "Open a paid realtime voice WebSocket",
        "description": "Connect to wss://api.kendr.org/v1/voice/stream with an API key scoped models:invoke. Send VoiceStart as the first text message; full mode and an explicit catalog voice_id are required. Wait for session.ready before binary audio. Native/server clients may omit Origin; a supplied Origin must be trusted. Browser native WebSocket cannot set key headers: use your own authenticated backend relay. Cookies, app sessions, OAuth, query credentials, and free preview are unsupported. Credit/capacity/provider failures after upgrade use VoiceErrorEvent, not HTTP errors. Each connection reserves and settles credits independently; continuation is not replay or idempotency. See https://kendr.org/docs/api-voice.html.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-required-scopes": [
          "models:invoke"
        ],
        "externalDocs": {
          "url": "https://kendr.org/docs/api-voice.html"
        },
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional for native/server clients; if supplied, must match a deployment-trusted origin."
          }
        ],
        "responses": {
          "101": {
            "description": "Switching Protocols. Subsequent JSON control/events and raw binary PCM follow kendr.voice.v1; this is not a JSON response or SSE stream."
          },
          "400": {
            "description": "Malformed request or WebSocket upgrade.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoiceHttpError"
                }
              }
            }
          },
          "401": {
            "description": "A valid Kendr API key is required; app sessions and OAuth are not accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoiceHttpError"
                }
              }
            }
          },
          "403": {
            "description": "Required API-key scope missing or supplied Origin is untrusted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoiceHttpError"
                }
              }
            }
          },
          "503": {
            "description": "Voice service or authentication dependency unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoiceHttpError"
                }
              }
            }
          }
        },
        "x-websocket": {
          "url": "wss://api.kendr.org/v1/voice/stream",
          "protocol": "kendr.voice.v1",
          "firstMessage": {
            "$ref": "#/components/schemas/VoiceStart"
          },
          "clientControl": {
            "$ref": "#/components/schemas/VoiceControl"
          },
          "serverEvent": {
            "$ref": "#/components/schemas/VoiceServerEvent"
          },
          "inputAudio": {
            "encoding": "pcm_s16le",
            "sample_rate_hz": 16000,
            "channels": 1,
            "frame_bytes": 1024,
            "frame_duration_ms": 32
          },
          "outputAudio": {
            "encoding": "pcm_s16le",
            "sample_rate_hz": 24000,
            "channels": 1,
            "max_frame_bytes": 16384
          },
          "maxClientMessageBytes": 32768,
          "exampleClient": "https://kendr.org/docs/examples/voice_stream.py"
        }
      }
    },
    "/v1/audio/speech": {
      "post": {
        "tags": [
          "Models"
        ],
        "summary": "Generate a complete MP3 or WAV speech file",
        "description": "Uses the same Kendr key as chat and an enabled, priced speech route. Returns raw audio bytes at a fixed 24 kHz mono sample format after provider-reported usage is settled. Accent and pacing instructions are preserved. Generated audio and input text are not retained by Kendr for replay. Discover active speech routes using the audio_speech capability in GET /v1/models.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            },
            "description": "Optional duplicate-execution guard. Omitted keys are generated per request. Completed audio is not retained; reuse returns 409 without generating or charging again."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AudioSpeechRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Raw MP3 or WAV bytes, never JSON or base64. Cache-Control: no-store.",
            "content": {
              "audio/mpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "audio/wav": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "description": "Invalid audio input, model, voice, format, language, or duration.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudioErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "A valid Kendr API key with models:invoke is required.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudioErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "The key or billing account cannot invoke this audio route.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudioErrorEnvelope"
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits; error.code is credit_balance_exhausted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudioErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "This idempotency key is already active or completed. Audio and transcripts are not retained for replay.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudioErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded; error.code is rate_limit_exceeded. Honor Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudioErrorEnvelope"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            }
          },
          "503": {
            "description": "The configured audio route, codec, or upstream provider is unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudioErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/transcriptions": {
      "post": {
        "tags": [
          "Models"
        ],
        "summary": "Transcribe an uploaded recording",
        "description": "Accepts browser WebM/Opus, Ogg/Opus and Safari M4A/AAC plus MP3/WAV. Recordings are limited to 3 MiB and 120 seconds, decoded transiently in memory, and not persisted by Kendr. Returns the unedited transcript with optional duration; empty and digitally silent recordings return an empty transcript without an upstream generation charge. Transcripts are not retained for replay. Discover active transcription routes using audio_transcription in GET /v1/models.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            },
            "description": "Optional duplicate-execution guard. Omitted keys are generated per request. Completed audio is not retained; reuse returns 409 without generating or charging again."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/AudioTranscriptionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Transcript and optional duration. Cache-Control: no-store.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudioTranscriptionResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid audio input, model, voice, format, language, or duration.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudioErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "A valid Kendr API key with models:invoke is required.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudioErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "The key or billing account cannot invoke this audio route.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudioErrorEnvelope"
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits; error.code is credit_balance_exhausted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudioErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "This idempotency key is already active or completed. Audio and transcripts are not retained for replay.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudioErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded; error.code is rate_limit_exceeded. Honor Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudioErrorEnvelope"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            }
          },
          "503": {
            "description": "The configured audio route, codec, or upstream provider is unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudioErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/v1/messages": {
      "post": {
        "tags": [
          "Models"
        ],
        "summary": "Generate an Anthropic-compatible message through Kendr Cloud",
        "description": "Accepts model, messages, optional system, max_tokens, tools, metadata, and stream. The response includes Kendr billing metadata.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Kendr-Idempotency-Replay-Only",
            "in": "header",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false
            },
            "description": "Lookup-only recovery for the exact original body and idempotency key; never starts a generation."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/HostedAnthropicMessageRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Anthropic-compatible message returned with kendr_usage."
          }
        }
      }
    },
    "/v1/messages/count_tokens": {
      "post": {
        "tags": [
          "Models"
        ],
        "summary": "Estimate input tokens for an Anthropic-compatible message request",
        "description": "Free, Anthropic-compatible token counting. Returns {\"input_tokens\": n} using the same estimator as the router's planner.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "model": {
                    "type": "string"
                  },
                  "messages": {
                    "type": "array",
                    "items": {
                      "type": "object"
                    }
                  },
                  "system": {},
                  "tools": {
                    "type": "array",
                    "items": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Token estimate returned."
          }
        }
      }
    },
    "/v1/videos/generations": {
      "post": {
        "tags": [
          "Models"
        ],
        "summary": "Queue a provider-neutral asynchronous video generation",
        "description": "Reserves credits using the selected route's approved billing units: duration and resolution for Grok/Veo, or an output-token ceiling for token-priced routes. Applies enterprise provider/model/retention policy and returns a durable job. Credentials and provider media URLs remain private. Kendr retention removes Kendr-held copies, but an accepted upstream task cannot be deleted through the current provider API.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 160,
              "pattern": "^[A-Za-z0-9][A-Za-z0-9._:/-]{0,159}$"
            },
            "description": "Required stable replay key. Reuse with a different request returns 409. The request_id body field is an explicit compatibility alternative."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VideoGenerationRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Video job accepted or its idempotent replay returned.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VideoGenerationResponse"
                }
              }
            }
          },
          "400": {
            "description": "Video controls or request body were invalid."
          },
          "401": {
            "description": "Valid Kendr authentication with models:invoke is required."
          },
          "403": {
            "description": "The authenticated credential lacks models:invoke or account access."
          },
          "402": {
            "description": "Available credits cannot cover the configured reservation ceiling."
          },
          "409": {
            "description": "The idempotency key belongs to a different request."
          },
          "502": {
            "description": "No enabled, priced kendr-video route was available."
          }
        }
      }
    },
    "/v1/videos/generations/{job_id}": {
      "get": {
        "tags": [
          "Models"
        ],
        "summary": "Read a video-generation job",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^vjob_[a-f0-9]{24}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Account-scoped job state returned.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VideoGenerationResponse"
                }
              }
            }
          },
          "401": {
            "description": "Valid Kendr authentication with models:invoke is required."
          },
          "403": {
            "description": "The authenticated credential lacks models:invoke."
          },
          "404": {
            "description": "No job belongs to the authenticated account."
          }
        }
      }
    },
    "/v1/videos/generations/{job_id}/cancel": {
      "post": {
        "tags": [
          "Models"
        ],
        "summary": "Cancel a queued video generation",
        "description": "Cancellation succeeds and releases the reservation only before provider submission. After submission, the provider exposes no cancellation operation, so Kendr continues polling and settles actual usage.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^vjob_[a-f0-9]{24}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Queued job cancelled, or an already-terminal state returned.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VideoGenerationResponse"
                }
              }
            }
          },
          "401": {
            "description": "Valid Kendr authentication with models:invoke is required."
          },
          "403": {
            "description": "The authenticated credential lacks models:invoke."
          },
          "404": {
            "description": "No job belongs to the authenticated account."
          },
          "409": {
            "description": "The provider task was already submitted and cannot be cancelled upstream."
          }
        }
      }
    },
    "/api/v1/videos/generations": {
      "post": {
        "tags": [
          "Models"
        ],
        "summary": "App/session alias for POST /v1/videos/generations",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 160,
              "pattern": "^[A-Za-z0-9][A-Za-z0-9._:/-]{0,159}$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VideoGenerationRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Video job accepted or replayed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VideoGenerationResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request."
          },
          "401": {
            "description": "Authentication required."
          },
          "402": {
            "description": "Reservation cannot be funded."
          },
          "403": {
            "description": "The authenticated credential lacks models:invoke or account access."
          },
          "409": {
            "description": "Idempotency conflict."
          },
          "502": {
            "description": "No priced route is available."
          }
        }
      }
    },
    "/api/v1/videos/generations/{job_id}": {
      "get": {
        "tags": [
          "Models"
        ],
        "summary": "App/session alias for GET /v1/videos/generations/{job_id}",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^vjob_[a-f0-9]{24}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Account-scoped job state returned.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VideoGenerationResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required."
          },
          "403": {
            "description": "The authenticated credential lacks models:invoke."
          },
          "404": {
            "description": "Job not found."
          }
        }
      }
    },
    "/api/v1/videos/generations/{job_id}/cancel": {
      "post": {
        "tags": [
          "Models"
        ],
        "summary": "App/session alias for POST /v1/videos/generations/{job_id}/cancel",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^vjob_[a-f0-9]{24}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Queued job cancelled or terminal state returned.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VideoGenerationResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required."
          },
          "403": {
            "description": "The authenticated credential lacks models:invoke."
          },
          "404": {
            "description": "Job not found."
          },
          "409": {
            "description": "Already submitted; upstream cancellation is unavailable."
          }
        }
      }
    },
    "/api/me/generated-videos/{video_id}": {
      "get": {
        "tags": [
          "Models"
        ],
        "summary": "Stream an authenticated generated video",
        "description": "Owner- or shared-project-authorized private media delivery. Supports one HTTP byte range and never redirects to a provider or object-store URL.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "video_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^vid_[a-f0-9]{24}$"
            }
          },
          {
            "name": "Range",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^bytes="
            },
            "description": "A single standard byte range."
          },
          {
            "name": "download",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false
            },
            "description": "Use attachment rather than inline Content-Disposition."
          }
        ],
        "responses": {
          "200": {
            "description": "Complete private video.",
            "headers": {
              "Accept-Ranges": {
                "schema": {
                  "type": "string",
                  "enum": [
                    "bytes"
                  ]
                }
              },
              "Content-Disposition": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "video/mp4": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "video/quicktime": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "206": {
            "description": "Requested byte range.",
            "headers": {
              "Accept-Ranges": {
                "schema": {
                  "type": "string",
                  "enum": [
                    "bytes"
                  ]
                }
              },
              "Content-Range": {
                "schema": {
                  "type": "string"
                }
              },
              "Content-Disposition": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "video/mp4": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "video/quicktime": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "description": "Valid Kendr authentication with models:invoke is required."
          },
          "403": {
            "description": "The authenticated credential lacks models:invoke."
          },
          "404": {
            "description": "Video is not owned by or shared with this account."
          },
          "416": {
            "description": "The byte range was invalid or unsatisfiable."
          },
          "503": {
            "description": "Private video storage is temporarily unavailable."
          }
        }
      }
    },
    "/v1/video/analyses": {
      "post": {
        "tags": [
          "Models"
        ],
        "summary": "Queue an asynchronous Kendr video analysis",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "source_url"
                ],
                "properties": {
                  "model": {
                    "type": "string",
                    "default": "kc-pegasus-1.2"
                  },
                  "source_url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "prompt": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Video analysis queued."
          }
        }
      }
    },
    "/v1/video/analyses/{analysis_id}": {
      "get": {
        "tags": [
          "Models"
        ],
        "summary": "Read the current state of a video analysis",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "parameters": [
          {
            "name": "analysis_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Analysis state returned."
          },
          "404": {
            "description": "Analysis was not found for this account."
          }
        }
      }
    },
    "/api/v1/openapi.json": {
      "get": {
        "tags": [
          "Models"
        ],
        "summary": "Download the model gateway OpenAPI contract",
        "responses": {
          "200": {
            "description": "Model-specific OpenAPI document returned."
          }
        }
      }
    },
    "/api/v1/models": {
      "get": {
        "tags": [
          "Models"
        ],
        "summary": "List available models using the OpenAI model-list shape",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "responses": {
          "200": {
            "description": "OpenAI-compatible model list returned."
          }
        }
      }
    },
    "/api/v1/responses": {
      "post": {
        "tags": [
          "Models"
        ],
        "summary": "Alias of POST /v1/responses",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Kendr-Idempotency-Replay-Only",
            "in": "header",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false
            },
            "description": "Lookup-only recovery for the exact original body and idempotency key; never starts a generation."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/HostedLlmResponseRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Response completed."
          }
        }
      }
    },
    "/api/v1/chat/completions": {
      "post": {
        "tags": [
          "Models"
        ],
        "summary": "Alias of POST /v1/chat/completions",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Kendr-Idempotency-Replay-Only",
            "in": "header",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false
            },
            "description": "Lookup-only recovery for the exact original body and idempotency key; never starts a generation."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/HostedLlmResponseRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Chat completion returned."
          }
        }
      }
    },
    "/api/v1/llm/responses": {
      "post": {
        "tags": [
          "LLM"
        ],
        "summary": "Generate through a Kendr-hosted LLM alias",
        "description": "Routes the prompt through KendrWeb to the configured upstream provider, reserves wallet credits before execution, and debits only after successful provider usage.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Prevents duplicate charging for a retried successful request."
          },
          {
            "name": "X-Kendr-Idempotency-Replay-Only",
            "in": "header",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false
            },
            "description": "Set true only to retrieve the exact original request's settled replay. This mode never plans, reserves credits, or invokes a provider."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/HostedLlmResponseRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Generation completed and credits were charged once. stream=false returns JSON. stream=true returns Kendr named SSE on a safe live route; a stateful non-streamable tool path may return the same complete JSON shape with X-Kendr-Stream-Mode: buffered.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HostedLlmResponse"
                }
              },
              "text/event-stream": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Payload, model, pricing, rate limit, or idempotency state was invalid."
          },
          "401": {
            "description": "No valid API key, app session header, OAuth bearer token, or customer session was supplied."
          },
          "402": {
            "description": "Available credits are below the required reservation."
          },
          "502": {
            "description": "The upstream provider request failed; reservation was released and credits were not debited."
          }
        }
      }
    },
    "/api/v1/llm/responses/replay": {
      "post": {
        "tags": [
          "LLM"
        ],
        "summary": "Retrieve a settled LLM response without executing again",
        "description": "Authenticated, empty-body replay lookup scoped to the caller, wallet, and original Idempotency-Key. This endpoint never fingerprints a request body, applies a generation rate limit, plans, reserves credits, settles, or invokes a provider. Successful responses use Cache-Control: private, no-store.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          },
          {
            "sessionCookie": []
          },
          {
            "appSessionHeader": []
          },
          {
            "kendrOAuth": [
              "app"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The exact idempotency key used by the original model request."
          }
        ],
        "responses": {
          "200": {
            "description": "The settled response replay was returned without new execution.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HostedLlmResponse"
                }
              }
            }
          },
          "400": {
            "description": "Idempotency-Key is missing or invalid."
          },
          "401": {
            "description": "No valid Kendr authentication was supplied."
          },
          "403": {
            "description": "The authenticated actor cannot access the billed wallet."
          },
          "404": {
            "description": "No request exists in the authenticated actor and wallet scope for this key."
          },
          "409": {
            "description": "The original request is still active or ended without a settled response."
          },
          "410": {
            "description": "The settled replay has expired."
          }
        }
      }
    }
  }
}
