{"openapi":"3.1.0","info":{"title":"Botovod Agent API","version":"1.0.0","description":"Read https://botovod.srgkslv.ru/agents/quickstart.md before provisioning. Owner session + CSRF for admin writes; per-bot Bearer token for runtime."},"paths":{"/api/bot/messages":{"post":{"tags":["bot-api"],"summary":"Post a message to this bot's chat","description":"Returns {ok: true, message_id: integer}. Use metadata.image_url for an uploaded image.","operationId":"post_message_api_bot_messages_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"BotToken":[]}]}},"/api/bot/events":{"post":{"tags":["bot-api"],"summary":"Create an Inbox event","description":"Returns ok, event_id, and optional message_id. Warning/critical events also appear in chat; set also_post_to_chat for info events.","operationId":"post_event_api_bot_events_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"BotToken":[]}]}},"/api/bot/commands/pending":{"get":{"tags":["bot-api"],"summary":"Claim pending commands for processing","description":"This GET changes state: all returned commands become taken. Run one worker per bot. Unfinished commands are reclaimed after 300 seconds by default. Do not use this endpoint as a health check or cache it.","operationId":"pending_commands_api_bot_commands_pending_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PendingOut"}}}}},"security":[{"BotToken":[]}]}},"/api/bot/commands/{command_id}/complete":{"post":{"tags":["bot-api"],"summary":"Complete or fail a claimed command","description":"Use status=done with result or metadata.image_url; status=failed requires error. Repeating a completed command ID returns idempotent=true without another result. Idempotency-Key is echoed but does not deduplicate other requests.","operationId":"complete_bot_command_api_bot_commands__command_id__complete_post","security":[{"BotToken":[]}],"parameters":[{"name":"command_id","in":"path","required":true,"schema":{"type":"integer","title":"Command Id"}},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompleteIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompleteOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/bot/heartbeat":{"post":{"tags":["bot-api"],"summary":"Update this bot's last-seen timestamp and status","description":"Send status=online every 60 seconds. Recommended statuses: online, offline, error, unknown.","operationId":"heartbeat_api_bot_heartbeat_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HeartbeatIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"BotToken":[]}]}},"/api/bot/uploads/{upload_id}":{"get":{"tags":["bot-api"],"summary":"Download the PDF referenced by a user command","operationId":"download_upload_api_bot_uploads__upload_id__get","security":[{"BotToken":[]}],"parameters":[{"name":"upload_id","in":"path","required":true,"schema":{"type":"string","title":"Upload Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/bot/uploads/image":{"post":{"tags":["bot-api"],"summary":"Upload a PNG, JPEG or WebP image","description":"Multipart form field: file. Returns ok, file_id, path, url, kind. Use url in metadata.image_url; path is a server path, not a download URL.","operationId":"upload_image_api_bot_uploads_image_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_image_api_bot_uploads_image_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"BotToken":[]}]}},"/api/admin/session":{"post":{"tags":["agent-provisioning"],"summary":"Sign in with owner credentials","description":"Use a cookie-preserving HTTP client and application/json. Save csrf_token for write requests. Credentials are never bot runtime credentials.","operationId":"create_session_api_admin_session_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["agent-provisioning"],"summary":"Inspect session and obtain its CSRF token","operationId":"inspect_session_api_admin_session_get","security":[{"AdminSession":[]}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionOut"}}}}}},"delete":{"tags":["agent-provisioning"],"summary":"Sign out","operationId":"delete_session_api_admin_session_delete","security":[{"AdminSession":[]}],"parameters":[{"name":"X-CSRF-Token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Csrf-Token"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/bots":{"get":{"tags":["agent-provisioning"],"summary":"List existing bots without exposing credentials","operationId":"get_bots_api_admin_bots_get","security":[{"AdminSession":[]}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BotsOut"}}}}}},"post":{"tags":["agent-provisioning"],"summary":"Create a bot and issue its runtime token once","operationId":"provision_bot_api_admin_bots_post","security":[{"AdminSession":[]}],"parameters":[{"name":"X-CSRF-Token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Csrf-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBotIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BotCreated"}}}},"409":{"description":"Slug already exists; no token is issued and the existing bot is unchanged"},"403":{"description":"Missing or incorrect X-CSRF-Token"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"Body_create_bot_form_settings_bots_post":{"properties":{"name":{"type":"string","title":"Name"},"description":{"type":"string","title":"Description","default":""},"csrf_token":{"type":"string","title":"Csrf Token"}},"type":"object","required":["name","csrf_token"],"title":"Body_create_bot_form_settings_bots_post"},"Body_inbox_archive_all_inbox_archive_all_post":{"properties":{"csrf_token":{"type":"string","title":"Csrf Token"}},"type":"object","required":["csrf_token"],"title":"Body_inbox_archive_all_inbox_archive_all_post"},"Body_inbox_archive_inbox__event_id__archive_post":{"properties":{"csrf_token":{"type":"string","title":"Csrf Token"}},"type":"object","required":["csrf_token"],"title":"Body_inbox_archive_inbox__event_id__archive_post"},"Body_inbox_read_inbox__event_id__read_post":{"properties":{"csrf_token":{"type":"string","title":"Csrf Token"}},"type":"object","required":["csrf_token"],"title":"Body_inbox_read_inbox__event_id__read_post"},"Body_login_submit_login_post":{"properties":{"email":{"type":"string","title":"Email"},"password":{"type":"string","title":"Password"},"csrf_token":{"type":"string","title":"Csrf Token"}},"type":"object","required":["email","password","csrf_token"],"title":"Body_login_submit_login_post"},"Body_logout_logout_post":{"properties":{"csrf_token":{"type":"string","title":"Csrf Token"}},"type":"object","required":["csrf_token"],"title":"Body_logout_logout_post"},"Body_mobile_pdf_api_mobile_bots__slug__pdf_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"}},"type":"object","required":["file"],"title":"Body_mobile_pdf_api_mobile_bots__slug__pdf_post"},"Body_regenerate_token_form_settings_bots__slug__regenerate_post":{"properties":{"csrf_token":{"type":"string","title":"Csrf Token"}},"type":"object","required":["csrf_token"],"title":"Body_regenerate_token_form_settings_bots__slug__regenerate_post"},"Body_send_command_bots__slug__command_post":{"properties":{"text":{"type":"string","title":"Text"},"csrf_token":{"type":"string","title":"Csrf Token"}},"type":"object","required":["text","csrf_token"],"title":"Body_send_command_bots__slug__command_post"},"Body_upload_image_api_bot_uploads_image_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"}},"type":"object","required":["file"],"title":"Body_upload_image_api_bot_uploads_image_post"},"Body_upload_pdf_bots__slug__upload_pdf_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"},"csrf_token":{"type":"string","title":"Csrf Token"}},"type":"object","required":["file","csrf_token"],"title":"Body_upload_pdf_bots__slug__upload_pdf_post"},"BotCreated":{"properties":{"id":{"type":"integer","title":"Id"},"name":{"type":"string","title":"Name"},"slug":{"type":"string","title":"Slug"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"status":{"type":"string","title":"Status"},"quick_commands":{"items":{"type":"string"},"type":"array","title":"Quick Commands"},"chat_url":{"type":"string","title":"Chat Url"},"token":{"type":"string","title":"Token","description":"Returned only at creation. Store privately; use as Bearer token for /api/bot/*."}},"type":"object","required":["id","name","slug","description","status","quick_commands","chat_url","token"],"title":"BotCreated"},"BotOut":{"properties":{"id":{"type":"integer","title":"Id"},"name":{"type":"string","title":"Name"},"slug":{"type":"string","title":"Slug"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"status":{"type":"string","title":"Status"},"quick_commands":{"items":{"type":"string"},"type":"array","title":"Quick Commands"},"chat_url":{"type":"string","title":"Chat Url"}},"type":"object","required":["id","name","slug","description","status","quick_commands","chat_url"],"title":"BotOut"},"BotsOut":{"properties":{"bots":{"items":{"$ref":"#/components/schemas/BotOut"},"type":"array","title":"Bots"}},"type":"object","required":["bots"],"title":"BotsOut"},"CommandIn":{"properties":{"text":{"type":"string","maxLength":32000,"minLength":1,"title":"Text"},"client_id":{"anyOf":[{"type":"string","maxLength":128,"minLength":1,"pattern":"^[A-Za-z0-9_-]+$"},{"type":"null"}],"title":"Client Id"},"client_created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Client Created At"}},"type":"object","required":["text"],"title":"CommandIn"},"CompleteIn":{"properties":{"status":{"type":"string","title":"Status"},"result":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Result"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata"}},"type":"object","required":["status"],"title":"CompleteIn"},"CompleteOut":{"properties":{"ok":{"type":"boolean","title":"Ok"},"command_id":{"type":"integer","title":"Command Id"},"status":{"type":"string","title":"Status"},"message_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Message Id"},"idempotent":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Idempotent"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"idempotency_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idempotency Key"}},"type":"object","required":["ok","command_id","status"],"title":"CompleteOut"},"CreateBotIn":{"properties":{"name":{"type":"string","maxLength":255,"minLength":1,"title":"Name"},"slug":{"type":"string","maxLength":64,"minLength":1,"pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$","title":"Slug","description":"Stable unique identifier. Reusing a slug returns 409 without changing the existing bot."},"description":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}],"title":"Description"},"quick_commands":{"items":{"type":"string","maxLength":255,"minLength":1},"type":"array","maxItems":30,"title":"Quick Commands"}},"additionalProperties":false,"type":"object","required":["name","slug"],"title":"CreateBotIn"},"EventIn":{"properties":{"title":{"type":"string","title":"Title"},"body":{"type":"string","title":"Body"},"severity":{"type":"string","title":"Severity","default":"info"},"also_post_to_chat":{"type":"boolean","title":"Also Post To Chat","default":false},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata"}},"type":"object","required":["title","body"],"title":"EventIn"},"EventOut":{"properties":{"ok":{"type":"boolean","title":"Ok"},"event_id":{"type":"integer","title":"Event Id"},"message_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Message Id"}},"type":"object","required":["ok","event_id"],"title":"EventOut"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HeartbeatIn":{"properties":{"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata"}},"type":"object","title":"HeartbeatIn"},"ImageOut":{"properties":{"ok":{"type":"boolean","title":"Ok"},"file_id":{"type":"string","title":"File Id"},"path":{"type":"string","title":"Path"},"url":{"type":"string","title":"Url"},"kind":{"type":"string","title":"Kind"}},"type":"object","required":["ok","file_id","path","url","kind"],"title":"ImageOut"},"LoginIn":{"properties":{"email":{"type":"string","maxLength":255,"minLength":1,"title":"Email"},"password":{"type":"string","maxLength":1024,"minLength":1,"format":"password","title":"Password","writeOnly":true}},"type":"object","required":["email","password"],"title":"LoginIn"},"MessageIn":{"properties":{"content":{"type":"string","title":"Content"},"parse_mode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Parse Mode"},"message_type":{"type":"string","title":"Message Type","default":"text"},"severity":{"type":"string","title":"Severity","default":"info"},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata"}},"type":"object","required":["content"],"title":"MessageIn"},"MessageOut":{"properties":{"ok":{"type":"boolean","title":"Ok"},"message_id":{"type":"integer","title":"Message Id"}},"type":"object","required":["ok","message_id"],"title":"MessageOut"},"OkOut":{"properties":{"ok":{"type":"boolean","title":"Ok"}},"type":"object","required":["ok"],"title":"OkOut"},"PendingCommandOut":{"properties":{"id":{"type":"integer","title":"Id"},"text":{"type":"string","title":"Text"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created At"},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata"}},"type":"object","required":["id","text","created_at","metadata"],"title":"PendingCommandOut"},"PendingOut":{"properties":{"commands":{"items":{"$ref":"#/components/schemas/PendingCommandOut"},"type":"array","title":"Commands"}},"type":"object","required":["commands"],"title":"PendingOut"},"SessionOut":{"properties":{"email":{"type":"string","title":"Email"},"csrf_token":{"type":"string","title":"Csrf Token"}},"type":"object","required":["email","csrf_token"],"title":"SessionOut"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}},"securitySchemes":{"BotToken":{"type":"http","description":"Runtime token for one bot, obtained during provisioning. Does not grant admin access.","scheme":"bearer"},"AdminSession":{"type":"apiKey","in":"cookie","name":"session"}}},"servers":[{"url":"https://botovod.srgkslv.ru"}]}