{"product":"1-chat","audience":"Внешние агенты, работающие с перепиской по API-ключу или через подключение (OAuth)","base_url":"https://app.1-chat.ru/api","base_url_confirmed":true,"auth":{"header":"Authorization","format":"Bearer <ключ>","token_prefix":"sk_1chat_","websocket_supported":false},"scopes":[{"id":"read","title":"Чтение","example":"sk_1chat_ro_…","description":"Видит переписку, ничего не меняет"},{"id":"write","title":"Запись","example":"sk_1chat_rw_…","description":"Видит переписку и может отправлять сообщения от имени владельца ключа"}],"methods":{"read":[{"method":"GET","path":"/v1/attachments/{attachment_id}/raw","summary":"Содержимое вложения"},{"method":"GET","path":"/v1/changes","summary":"Что изменилось с прошлого раза — вместо опроса списка диалогов"},{"method":"GET","path":"/v1/conversations","summary":"Список диалогов"},{"method":"GET","path":"/v1/conversations/{conversation_id}","summary":"Карточка диалога"},{"method":"GET","path":"/v1/conversations/{conversation_id}/assignment-events","summary":"История диалога в команде: кто брал, кому передавал и почему"},{"method":"GET","path":"/v1/conversations/{conversation_id}/messages","summary":"История переписки"},{"method":"GET","path":"/v1/conversations/{conversation_id}/participants","summary":"Участники диалога"},{"method":"GET","path":"/v1/integrations","summary":"Подключённые аккаунты и остаток новых собеседников на сегодня"},{"method":"GET","path":"/v1/team/handoff-categories","summary":"Причины передачи, которые предлагает рабочее пространство"},{"method":"GET","path":"/v1/team/members","summary":"Кто в команде — кому можно передать диалог"},{"method":"GET","path":"/v1/webhook-endpoints","summary":"Свои вебхуки и их состояние"}],"write":[{"method":"POST","path":"/v1/conversations/recipients/search","summary":"Найти собеседника по телефону или имени"},{"method":"POST","path":"/v1/conversations/start","summary":"Начать диалог с новым собеседником"},{"method":"DELETE","path":"/v1/conversations/{conversation_id}/assignment","summary":"Отпустить диалог — свой; владелец отпускает любой"},{"method":"POST","path":"/v1/conversations/{conversation_id}/assignment","summary":"Взять диалог; забрать чужой (force) может только ключ владельца"},{"method":"DELETE","path":"/v1/conversations/{conversation_id}/help-call","summary":"Отменить передачу — свою; владелец отменяет любую"},{"method":"PATCH","path":"/v1/conversations/{conversation_id}/help-call","summary":"Изменить причину и комментарий передачи — свою; владелец любую"},{"method":"POST","path":"/v1/conversations/{conversation_id}/help-call","summary":"Передать свой диалог человеку — он станет ведущим, когда примет"},{"method":"POST","path":"/v1/conversations/{conversation_id}/help-call/accept","summary":"Принять диалог, который передали вам"},{"method":"DELETE","path":"/v1/conversations/{conversation_id}/help-call/escalate","summary":"Снять срочность с передачи"},{"method":"POST","path":"/v1/conversations/{conversation_id}/help-call/escalate","summary":"Сделать передачу срочной — у позванного сирена, пока не примет"},{"method":"POST","path":"/v1/conversations/{conversation_id}/messages","summary":"Отправить сообщение"},{"method":"POST","path":"/v1/conversations/{conversation_id}/messages/{message_id}/reactions","summary":"Поставить реакцию"},{"method":"DELETE","path":"/v1/conversations/{conversation_id}/messages/{message_id}/reactions/{emoji}","summary":"Снять реакцию"},{"method":"POST","path":"/v1/conversations/{conversation_id}/read","summary":"Отметить диалог прочитанным"},{"method":"POST","path":"/v1/conversations/{conversation_id}/typing","summary":"Показать собеседнику «печатает» — повторять, пока пишете"},{"method":"POST","path":"/v1/uploads","summary":"Загрузить вложение для отправки — его id передаётся в attachment_ids сообщения"},{"method":"POST","path":"/v1/webhook-endpoints","summary":"Зарегистрировать вебхук — заявка, которую включает человек"}],"default_policy":"deny","default_policy_note":"Список разрешённого, а не запрещённого: существующий метод, которого здесь нет, отвечает 403 — в том числе метод, который появится в будущем. Несуществующий путь отвечает 404, так что опечатку в адресе легко отличить от нехватки прав."},"mcp":{"available":true,"transport":"streamable_http","url":"https://app.1-chat.ru/api/v1/mcp/","protocol_version_latest":"2026-07-28","auth":"api_key_header","auth_methods":["api_key_header","oauth"],"connector":{"available":true,"auth":"oauth","url":"https://app.1-chat.ru/api/v1/mcp/","clients_supported":[{"id":"claude","title":"Claude","vendor":"Anthropic"},{"id":"chatgpt","title":"ChatGPT","vendor":"OpenAI"},{"id":"codex","title":"Codex","vendor":"OpenAI"},{"id":"cursor","title":"Cursor","vendor":"Anysphere"},{"id":"gemini","title":"Gemini","vendor":"Google"},{"id":"perplexity","title":"Perplexity","vendor":"Perplexity AI"},{"id":"n8n","title":"n8n","vendor":"n8n"}],"other_clients_allowed":true,"scopes":["read","write"],"approver_roles":["owner","admin"],"consent_required":true,"takes_operator_seat":true},"install_required":false,"tools":[{"name":"register_webhook","scope":"write","title":"Зарегистрировать вебхук","summary":"Просит присылать события на ваш адрес, чтобы не ждать и не опрашивать вообще. Подходит, если вы не живёте постоянно: просыпаетесь по входящему запросу вместо того, чтобы держать соединение.\nВ ответе придёт secret — он показывается ОДИН РАЗ, сохраните его сразу. Каждая доставка подписана: заголовок X-1chat-Signature содержит sha256 от HMAC по строке «метка_времени.тело» с этим секретом; проверяйте подпись, иначе ваш адрес открыт всем.\nВАЖНО: вебхук создаётся ВЫКЛЮЧЕННЫМ. Доставка начнётся после того, как человек включит его в интерфейсе — скажите ему об этом, сами включить вы не можете. Проверить состояние: list_webhooks."},{"name":"list_webhooks","scope":"read","title":"Состояние вебхуков","summary":"Ваши вебхуки и их состояние. Смотрите сюда, чтобы понять, включил ли человек зарегистрированный вами адрес: is_active=true означает, что события уже идут. Здесь же видно, сколько событий накопилось и не отключили ли адрес за неудачные доставки."},{"name":"wait_for_changes","scope":"read","title":"Дождаться нового","summary":"Ждёт, пока в переписке что-нибудь произойдёт, и возвращает только изменения — новые сообщения, смену статусов, обновления диалогов. ИСПОЛЬЗУЙТЕ ЭТО ВМЕСТО ПОВТОРНЫХ ВЫЗОВОВ list_conversations: один вызов ждёт до 30 секунд и возвращается сразу, как только событие появилось, вместо десятка проверок впустую.\nПервый раз вызывайте с since=0 и wait=0 — получите текущий курсор без ожидания. Дальше передавайте cursor из прошлого ответа в since. Если пришёл status=gap, курсор устарел: перечитайте list_conversations и начните с нового cursor.\nconversation:typing — собеседник пишет (или записывает голосовое) до момента until: лучше дождаться его сообщения, чем отвечать на половину мысли. conversation:assignment_updated — сменился ведущий."},{"name":"list_conversations","scope":"read","title":"Список диалогов","summary":"Диалоги по всем подключённым мессенджерам. Уведомлений о новых сообщениях у API нет — новые обнаруживаются сравнением last_message_at."},{"name":"get_conversation","scope":"read","title":"Карточка диалога","summary":"Один диалог: собеседник, последнее сообщение, счётчик непрочитанных."},{"name":"list_messages","scope":"read","title":"История переписки","summary":"Сообщения диалога, новые первыми. Листается курсором: передайте next_before_seq из ответа в before_seq, чтобы уйти глубже в историю. Пустой next_before_seq означает, что история кончилась."},{"name":"list_participants","scope":"read","title":"Участники диалога","summary":"Кто участвует в диалоге, с именами и идентификаторами в мессенджере."},{"name":"list_accounts","scope":"read","title":"Подключённые аккаунты","summary":"Подключённые аккаунты мессенджеров и сколько новых собеседников каждому из них осталось на сегодня. Смотрите сюда до того, как начинать диалоги пачкой: предел считается по аккаунту, общий с людьми, и при исчерпании start_conversation вернёт отказ. state.can_send=false значит, что из аккаунта сейчас писать нельзя (state.title и state.message объясняют почему, например нужен вход); войти снова может только владелец в интерфейсе."},{"name":"search_recipients","scope":"write","title":"Найти собеседника","summary":"Ищет человека в мессенджере по номеру телефона или имени пользователя, чтобы написать тому, с кем переписки ещё не было. Ничего не отправляет и диалог не создаёт. У каждого найденного смотрите can_message: не всякому можно написать, причина будет в reason. Дальше передайте query в start_conversation."},{"name":"start_conversation","scope":"write","title":"Начать диалог","summary":"Создаёт диалог с собеседником, найденным через search_recipients, и возвращает его идентификатор — отправлять сообщение нужно отдельным вызовом send_message. Само по себе ничего не отправляет и собеседника не беспокоит. Если диалог с этим человеком уже есть, вернётся он же, дубликата не будет и предел новых собеседников при этом не тратится."},{"name":"send_message","scope":"write","title":"Отправить сообщение","summary":"Отправляет текст в существующий диалог от имени владельца ключа. Ответ приходит только после подтверждения мессенджером, до полутора минут. ВСЕГДА передавайте client_id (свой UUID на каждое новое сообщение): повтор с тем же client_id безопасен — второй раз не отправится, вернётся уже созданное. БЕЗ client_id повтор отправит сообщение второй раз. Файл: сначала upload_file, его id — в attachment_ids; text тогда — подпись, можно без него. Написать новому собеседнику нельзя, только в уже существующий диалог. Если аккаунту диалога нужен вход (can_send=false у диалога), отправка отклоняется с объяснением — повторять бесполезно, пока владелец не войдёт снова."},{"name":"upload_file","scope":"write","title":"Загрузить файл","summary":"Готовит файл к отправке в диалог: по публичной ссылке (сервер скачает сам) или из base64. Возвращает id — передайте его в attachment_ids send_message. Сам по себе файл никому не уходит. До 50 МБ; PDF и другие документы уходят файлом, картинки — фото, если не указан kind. Каждый id отправляется один раз: для второго сообщения загрузите снова."},{"name":"mark_conversation_read","scope":"write","title":"Отметить диалог прочитанным","summary":"Обнуляет счётчик непрочитанных. Счётчик общий на диалог, а не на пользователя: он обнулится и у людей, работающих с этим диалогом в интерфейсе. С to_messenger=true собеседник ещё и увидит «прочитано» в мессенджере (capabilities.read_receipts в list_accounts); в диалоге, который ведёт другой, ничего не меняется."},{"name":"set_reaction","scope":"write","title":"Поставить реакцию","summary":"Ставит эмодзи-реакцию на сообщение."},{"name":"remove_reaction","scope":"write","title":"Снять реакцию","summary":"Снимает ранее поставленную реакцию."},{"name":"list_team","scope":"read","title":"Команда","summary":"Кто сейчас в команде: user_id, имя, роль (owner, admin или operator) и is_me — это вы сами. Нужен, чтобы передать диалог человеку через hand_over."},{"name":"list_handoff_categories","scope":"read","title":"Причины передачи","summary":"Причины, которые рабочее пространство предлагает для hand_over: берите подходящую дословно. Это подсказки, а не ограничение — если ни одна не подходит, напишите свою. is_default=true — владелец список не менял."},{"name":"take_conversation","scope":"write","title":"Взять диалог","summary":"Делает вас ведущим диалога. Писать в диалог может только ведущий; свободный диалог send_message берёт сам, так что звать это нужно, чтобы занять диалог до ответа. Диалог, который ведёт другой, без force не взять — ответ conversation_assigned, в нём сказано, кто ведёт. force=true забирает диалог у ведущего, но только если ключ выпущен владельцем или администратором рабочего пространства; ключ оператора получит admin_only. Забирайте чужой диалог, только если вас об этом прямо попросили."},{"name":"release_conversation","scope":"write","title":"Отпустить диалог","summary":"Перестать вести свой диалог: он станет свободным, и любой из команды сможет его взять. Чтобы отдать диалог конкретному человеку, используйте hand_over."},{"name":"hand_over","scope":"write","title":"Передать диалог человеку","summary":"Просит человека (user_id из list_team) забрать ваш диалог. Ведущим он станет, только когда примет; до этого диалог остаётся за вами и вы можете отвечать. Одна передача на диалог: новая заменяет прежнюю. Скажите, зачем зовёте: category — причина (из list_handoff_categories или своими словами), note — что человеку знать до того, как он откроет диалог. Принятие придёт событием conversation:assignment_updated."},{"name":"cancel_hand_over","scope":"write","title":"Отменить передачу","summary":"Отзывает вашу просьбу забрать диалог, пока её не приняли."},{"name":"update_hand_over","scope":"write","title":"Изменить причину передачи","summary":"Меняет причину и комментарий открытой передачи; меняется только то, что передали, пустая строка стирает. Можно тому, кто позвал (или ключу владельца). Нет передачи — help_call_not_found."},{"name":"show_typing","scope":"write","title":"Показать «печатает»","summary":"Собеседник видит «печатает» около пяти секунд. Повторяйте раз в 4 секунды, пока готовите ответ; чаще звать можно, лишнее склеится. Только в своём или свободном диалоге, диалог при этом не занимается. Где мессенджер не умеет (capabilities.typing=false в list_accounts), ничего не происходит."},{"name":"escalate_hand_over","scope":"write","title":"Сделать передачу срочной","summary":"Усиливайте, только если позванный долго не подключается, а вопрос важный: у него включится сирена, пока он не примет диалог. Можно тому, кто позвал (или ключу владельца). Нет передачи — help_call_not_found."},{"name":"deescalate_hand_over","scope":"write","title":"Снять срочность","summary":"Возвращает передачу в обычный вид; сама передача остаётся."},{"name":"accept_hand_over","scope":"write","title":"Принять переданный диалог","summary":"Становитесь ведущим диалога, который передали именно вам."}]},"channels":[{"id":"whatsapp","title":"WhatsApp","note":null},{"id":"telegram","title":"Telegram (бот)","note":"Подключение через бота. Сообщения уходят от имени бота."},{"id":"telegram_client","title":"Telegram (личный аккаунт)","note":"Подключение личного аккаунта. Сообщения уходят от имени человека."},{"id":"max","title":"MAX","note":null}],"message_statuses":[{"id":"queued","meaning":"Принято к отправке"},{"id":"sent","meaning":"Мессенджер принял сообщение"},{"id":"failed","meaning":"Отправить не удалось"}],"limits":{"requests_per_minute":300,"rate_limit_scope":"key","rate_limit_ip_cap_per_minute":3000,"rate_limit_window":"calendar_minute","active_keys_per_workspace":20,"new_contacts_per_account_per_day":10,"new_contacts_window":"rolling_24h","new_contacts_limit_configurable":true,"new_contacts_limit_source":"tenant_override_then_plan_then_default","key_expires":false,"conversations_page":{"default":50,"max":200},"messages_page":{"default":50,"max":200},"messages_pagination":"cursor","changes_max_wait_seconds":30,"webhook_endpoints_per_user":5,"upload_max_bytes":52428800},"can":["Читать список диалогов по всем подключённым мессенджерам сразу","Ждать новых сообщений, не опрашивая API вхолостую","Получать вебхук на свой адрес, когда держать соединение негде","Читать историю переписки и участников диалога","Скачивать вложения","Находить собеседника по телефону или имени пользователя","Начинать диалог с тем, с кем ещё не переписывались","Отправлять сообщения с текстом и файлами","Отмечать диалог прочитанным","Ставить и снимать реакции","Давать человеку ссылку на диалог или сообщение в интерфейсе"],"cannot":[{"what":"Подключать и отключать каналы","why":"Каналы подключает человек через интерфейс — это решение, а не пробел"},{"what":"Работать с биллингом, оплатой и тарифами","why":"Закрыто полностью"},{"what":"Входить, регистрироваться, управлять аккаунтом","why":"Закрыто полностью"},{"what":"Создавать и отзывать API-ключи","why":"Ключ не управляет ключами, в том числе собой"},{"what":"Подключаться к WebSocket","why":"Поток реального времени доступен только интерфейсу; агент ждёт изменений через /v1/changes или получает вебхук"},{"what":"Видеть групповые чаты и каналы","why":"Агенту доступна только личная переписка"}],"notes":[{"id":"new_contacts_are_capped","title":"Лимит новых чатов на подключение за 24 часа","body":"По умолчанию — 10; тариф и исключение для рабочего пространства могут менять предел. Текущий лимит возвращается в outreach подключений. Считается создание нового для 1-чат диалога через /conversations/start, даже без отправки сообщения. Предел считается по каждому подключённому аккаунту отдельно и скользящим окном в 24 часа, а не по календарным суткам. Он общий с людьми: то, что оператор начал вручную, тоже входит в счёт. При превышении приходит 429 с кодом new_contacts_daily_limit и временем, через которое освободится место. Предел защищает аккаунт от блокировки мессенджером — обходить его, заводя второй ключ, бессмысленно: счёт ведётся по аккаунту.","severity":"important"},{"id":"webhooks_for_scheduled_agents","title":"Агенту без постоянного процесса — вебхук","body":"Ожидание через /v1/changes подходит процессу, который живёт всегда. Агенту, который просыпается и завершается, ждать негде — для него зарегистрируйте вебхук в интерфейсе, и мы постучимся сами. Каждая доставка подписана: заголовок X-1chat-Signature содержит HMAC-SHA256 от метки времени и тела через точку, ключ выдаётся при создании. Доставка не реже одного раза, поэтому дедуплицируйте по seq события.","severity":"normal"},{"id":"start_before_send","title":"Новому собеседнику пишут в два шага","body":"Сначала найдите его по телефону или имени пользователя, затем начните диалог — в ответ придёт его идентификатор, и уже в него отправляется сообщение. Проверяйте поле can_message в результатах поиска: не всякому найденному можно написать.","severity":"normal"},{"id":"secret_shown_once","title":"Секрет показывается один раз","body":"В базе хранится только хеш ключа, поэтому перечитать секрет позже невозможно — ни через интерфейс, ни через поддержку. Потерянный ключ заменяется перевыпуском.","severity":"important"},{"id":"send_is_synchronous","title":"Отправка сообщения синхронная","body":"Ответ приходит только после того, как мессенджер подтвердил приём, и на медленных каналах это занимает до полутора минут. Закладывайте это в таймауты клиента.","severity":"important"},{"id":"retry_with_client_id","title":"Повторяйте отправку только с тем же client_id","body":"Передавайте client_id — свой UUID на каждое новое сообщение. Повтор с тем же client_id в том же диалоге не отправит второй раз, а вернёт уже созданное сообщение, так что ретрай после таймаута безопасен. Без client_id повтор отправит сообщение второй раз.","severity":"important"},{"id":"no_push","title":"Вместо опроса — ожидание изменений","body":"WebSocket ключам закрыт, но опрашивать список диалогов не нужно: GET /v1/changes принимает курсор и держит запрос до 30 секунд, возвращаясь в тот момент, когда событие действительно появилось. Один ждущий запрос заменяет десяток пустых проверок. Первый вызов — since=0 и wait=0, чтобы узнать текущий курсор; дальше передавайте cursor из ответа. Ответ status=gap означает, что курсор устарел и состояние надо перечитать целиком.","severity":"important"},{"id":"sending_files","title":"Файл отправляется в два шага","body":"Сначала POST /v1/uploads — multipart с полем file, а также conversation_id и, если нужно, kind (file, image, video, audio, voice; без него — по MIME-типу, PDF уходит документом). В ответ придёт id. Затем отправьте сообщение с этим id в attachment_ids; text тогда — подпись, его можно не передавать. Файл — до 50 МБ, каждый id уходит один раз. В MCP то же самое делают upload_file (по ссылке или base64) и send_message.","severity":"normal"},{"id":"account_is_not_channel","title":"Диалог принадлежит аккаунту, а не типу мессенджера","body":"integration_account_id — это конкретное подключение, channel — его тип. Считать их одним и тем же нельзя, даже если сейчас на каждый мессенджер приходится одно подключение.","severity":"normal"},{"id":"account_needs_login","title":"Из аккаунта, которому нужен вход, писать нельзя","body":"Если сессию закрыли или мессенджер её завершил, чаты аккаунта остаются и читаются, но отправка, реакции, поиск собеседника и импорт отвечают 409 с кодом integration_needs_login и состоянием аккаунта. Так же, с кодом integration_not_running, отвечает аккаунт, который сейчас не удаётся подключить. Смотрите заранее state.can_send у аккаунта в list_accounts: он учитывает и то и другое. can_send у диалога говорит только о том, нужен ли аккаунту вход. Войти снова может только владелец рабочего пространства в интерфейсе.","severity":"important"},{"id":"unread_is_shared","title":"Счётчик непрочитанных общий на диалог","body":"Он не разделён по пользователям: если диалог прочитал один оператор, счётчик обнулится у всех, включая агента.","severity":"normal"},{"id":"no_delivery_receipts","title":"Статусы «доставлено» и «прочитано» не приходят","body":"Узнать, прочитал ли собеседник сообщение, нельзя — этого не отдают сами мессенджеры.","severity":"normal"},{"id":"web_links","title":"Ссылку на диалог берите из ответа","body":"У диалога и у сообщения есть web_url — адрес, по которому человек откроет его в интерфейсе: после входа, в нужном рабочем пространстве, на нужном сообщении. Ссылаясь на диалог, давайте человеку web_url, а не составляйте адрес сами.","severity":"important"},{"id":"attachments_need_auth","title":"Вложения скачиваются через API","body":"Прямых ссылок в хранилище нет: запрос за содержимым вложения требует того же заголовка авторизации.","severity":"normal"}],"security":[{"id":"hash_only_storage","title":"Секрет не хранится","body":"В базе лежит только хеш ключа. Утечка дампа базы не даёт рабочих ключей, но и восстановить потерянный ключ нельзя."},{"id":"revocation_is_immediate","title":"Отзыв и перевыпуск действуют немедленно","body":"Старый секрет перестаёт работать сразу: агенты, которые им пользуются, получат 401 со следующего запроса. Ждать истечения чего-либо не нужно."},{"id":"last_used_is_visible","title":"Видно, когда ключом пользовались в последний раз","body":"У каждого ключа отображается дата последнего обращения — по ней видно, работает ли выданный ключ и не пользуется ли им кто-то, кто не должен."},{"id":"one_key_per_agent","title":"Отдельный ключ на каждого агента","body":"Так скомпрометированный ключ отзывается по одному, не задев остальных, и по дате последнего использования видно, чей именно перестал работать."},{"id":"write_acts_as_you","title":"Ключ на запись пишет вашим клиентам от вашего имени","body":"Обращайтесь с ним как с паролем: держите в переменных окружения или менеджере секретов, не кладите в репозиторий, не пересылайте в переписке. Если задача только читать — выдавайте ключ на чтение."},{"id":"workspace_scoped","title":"Ключ работает в пределах одного воркспейса","body":"Того, где он создан. Чужие диалоги по нему недоступны."}],"errors":[{"status":401,"code":"invalid_api_key","meaning":"Ключ не существует, отозван или перевыпущен"},{"status":403,"code":"api_key_scope_forbidden","meaning":"Метод недоступен ключам"},{"status":403,"code":"api_key_read_only","meaning":"Ключом на чтение вызван метод записи"},{"status":403,"code":"api_key_channel_forbidden","meaning":"Диалог в мессенджере, закрытом для ключей"},{"status":404,"code":null,"meaning":"Объект не найден или принадлежит другому воркспейсу"},{"status":409,"code":"integration_needs_login","meaning":"Аккаунту нужен вход: писать из него нельзя, пока владелец не войдёт снова"},{"status":409,"code":"integration_not_running","meaning":"Аккаунт сейчас не работает: писать из него нельзя"},{"status":422,"code":null,"meaning":"Некорректное тело запроса"},{"status":429,"code":"global_rate_limited","meaning":"Превышена частота запросов"},{"status":429,"code":"new_contacts_daily_limit","meaning":"Исчерпан дневной предел новых собеседников для этого аккаунта"}],"version":"a68e92844066f698"}