{"openapi":"3.0.3","info":{"title":"SPINE API","version":"1.0.0","description":"Единый API платформы SPINE для внешних проектов. Вебхуки подписываются HMAC-SHA256 от сырого тела запроса; ключ — секрет whsec_… ЦЕЛИКОМ строкой (не декодировать, не срезать префикс), результат hex в заголовке X-Spine-Signature: sha256=<hex>; тип события — в X-Spine-Event. Доставка: одна немедленная попытка + durable-ретраи с бэкоффом (до ~21ч); лог и переотправка — /v1/webhooks/{id}/deliveries и /v1/webhooks/{id}/deliveries/{deliveryId}/redeliver. Портал и примеры — https://api.spine.maxsystems.az/v1/docs."},"servers":[{"url":"https://api.spine.maxsystems.az"}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"Ключ spine_sk_… со скоупами"}}},"security":[{"apiKey":[]}],"paths":{"/v1/mail/send":{"post":{"summary":"Отправить письмо. Домен отправителя должен быть подключён к почте SPINE и принадлежать проекту.","tags":["Почта"],"security":[{"apiKey":["mail:send"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"id":"01K…","status":"sent","relayMessageId":"…"}}}},"401":{"description":"Неверный ключ"},"403":{"description":"Не хватает права"},"429":{"description":"Лимит частоты"}},"requestBody":{"required":true,"description":"from — адрес отправителя (обязателен); to — получатель (обязателен); subject — тема (или template); text / html — тело письма; category — метка для статистики (необязательно); idempotencyKey — защита от дублей (необязательно)","content":{"application/json":{"example":{"from":"noreply@ваш-домен","to":"user@example.com","subject":"Привет","text":"Тело письма"}}}}}},"/v1/certs/issue":{"post":{"summary":"Заказать SSL-сертификат для домена в управляемой зоне. Выпуск ~15–30 сек.","tags":["Сертификаты"],"security":[{"apiKey":["cert:issue"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":"{ \"id\": \"…\", \"subject\": \"app.ваш-домен\", \"sans\": [...], \"status\": \"pending\" }"}}},"401":{"description":"Неверный ключ"},"403":{"description":"Не хватает права"},"429":{"description":"Лимит частоты"}},"requestBody":{"required":true,"description":"domains — список доменов, можно wildcard *.домен (обязателен); csr — свой CSR — тогда приватный ключ остаётся у вас (необязательно); autoRenew — автопродление, по умолчанию true","content":{"application/json":{"example":{"domains":["app.ваш-домен","*.ваш-домен"],"autoRenew":true}}}}}},"/v1/certs/{id}/status":{"get":{"summary":"Статус сертификата (pending → active | failed).","tags":["Сертификаты"],"security":[{"apiKey":["cert:read"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"status":"active","notAfter":"…","daysLeft":89}}}},"401":{"description":"Неверный ключ"},"403":{"description":"Не хватает права"},"429":{"description":"Лимит частоты"}}}},"/v1/certs/{id}/download":{"get":{"summary":"Скачать сертификат (fullchain + приватный ключ; для сертов по CSR privkey=null).","tags":["Сертификаты"],"security":[{"apiKey":["cert:read"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"fullchain":"-----BEGIN CERTIFICATE-----…","privkey":"…"}}}},"401":{"description":"Неверный ключ"},"403":{"description":"Не хватает права"},"429":{"description":"Лимит частоты"}}}},"/v1/mailboxes":{"post":{"summary":"Создать почтовый ящик на своём домене.","tags":["Ящики"],"security":[{"apiKey":["mail:mailboxes"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"email":"info@ваш-домен","id":"…"}}}},"401":{"description":"Неверный ключ"},"403":{"description":"Не хватает права"},"429":{"description":"Лимит частоты"}},"requestBody":{"required":true,"description":"name — имя ящика до @ (2–40, [a-z0-9._-]); domain — домен проекта (обязателен); password — пароль ящика (мин. 8); description — описание (необязательно)","content":{"application/json":{"example":{"name":"info","domain":"ваш-домен","password":"…"}}}}},"get":{"summary":"Список ящиков и групп на доменах проекта. Поле type: personal (личный), shared (общий, доступ у нескольких людей), group (распределительная группа). У групп поле membersCount.","tags":["Ящики"],"security":[{"apiKey":["mail:mailboxes"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"mailboxes":[{"id":"…","email":"ivan@ваш-домен","type":"personal","usedBytes":0},{"id":"…","email":"team@ваш-домен","type":"group","membersCount":4}]}}}},"401":{"description":"Неверный ключ"},"403":{"description":"Не хватает права"},"429":{"description":"Лимит частоты"}}}},"/v1/mailboxes/{id}":{"delete":{"summary":"Удалить ящик (только на своём домене).","tags":["Ящики"],"security":[{"apiKey":["mail:mailboxes"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"deleted":true}}}},"401":{"description":"Неверный ключ"},"403":{"description":"Не хватает права"},"429":{"description":"Лимит частоты"}}}},"/v1/mailboxes/{id}/shared":{"post":{"summary":"Пометить ящик общим (shared) или снять пометку. Общий ящик, это личный ящик, к которому дан доступ нескольким людям (support@, info@). Меняет поле type ящика.","tags":["Ящики"],"security":[{"apiKey":["mail:mailboxes"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"id":"…","shared":true}}}},"401":{"description":"Неверный ключ"},"403":{"description":"Не хватает права"},"429":{"description":"Лимит частоты"}},"requestBody":{"required":true,"content":{"application/json":{"example":{"shared":true}}}}}},"/v1/groups":{"get":{"summary":"Список распределительных групп проекта. Группа, это адрес team@домен, письмо на который разлетается всем участникам в их личные ящики.","tags":["Группы"],"security":[{"apiKey":["mail:mailboxes"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"groups":[{"id":"…","email":"team@ваш-домен","membersCount":4}]}}}},"401":{"description":"Неверный ключ"},"403":{"description":"Не хватает права"},"429":{"description":"Лимит частоты"}}},"post":{"summary":"Создать распределительную группу name@домен. Домен обязан быть на вашем проекте.","tags":["Группы"],"security":[{"apiKey":["mail:mailboxes"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"id":"…","email":"team@ваш-домен.az"}}}},"401":{"description":"Неверный ключ"},"403":{"description":"Не хватает права"},"429":{"description":"Лимит частоты"}},"requestBody":{"required":true,"description":"domain — домен проекта (обязателен); name — имя адреса, 2-40 символов [a-z0-9._-] (обязателен); description — описание группы (необязательно)","content":{"application/json":{"example":{"domain":"ваш-домен.az","name":"team","description":"Вся команда"}}}}}},"/v1/groups/{id}":{"delete":{"summary":"Удалить группу.","tags":["Группы"],"security":[{"apiKey":["mail:mailboxes"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"deleted":true}}}},"401":{"description":"Неверный ключ"},"403":{"description":"Не хватает права"},"429":{"description":"Лимит частоты"}}}},"/v1/groups/{id}/members":{"get":{"summary":"Участники группы (ящики, в которые разлетается почта).","tags":["Группы"],"security":[{"apiKey":["mail:mailboxes"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"members":[{"id":"…","email":"ivan@ваш-домен.az"}]}}}},"401":{"description":"Неверный ключ"},"403":{"description":"Не хватает права"},"429":{"description":"Лимит частоты"}}},"post":{"summary":"Добавить ящик в группу по его адресу.","tags":["Группы"],"security":[{"apiKey":["mail:mailboxes"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"ok":true,"member":{"id":"…","email":"ivan@ваш-домен.az"}}}}},"401":{"description":"Неверный ключ"},"403":{"description":"Не хватает права"},"429":{"description":"Лимит частоты"}},"requestBody":{"required":true,"content":{"application/json":{"example":{"mailbox":"ivan@ваш-домен.az"}}}}}},"/v1/groups/{id}/members/{userId}":{"delete":{"summary":"Убрать участника из группы.","tags":["Группы"],"security":[{"apiKey":["mail:mailboxes"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"ok":true}}}},"401":{"description":"Неверный ключ"},"403":{"description":"Не хватает права"},"429":{"description":"Лимит частоты"}}}},"/v1/mailboxes/{id}/messages":{"get":{"summary":"Список последних писем в ящике (свежие сверху). Можно фильтровать по адресу — удобно для панели «переписка с контактом».","tags":["Ящики"],"security":[{"apiKey":["mail:read"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"messages":[{"id":"eaaaaab","messageId":["<abc@bank.az>"],"subject":"…","from":[{"email":"…"}],"receivedAt":"…","preview":"…"}]}}}},"401":{"description":"Неверный ключ"},"403":{"description":"Не хватает права"},"429":{"description":"Лимит частоты"}},"parameters":[{"name":"limit","in":"query","description":"сколько писем вернуть, до 100 (по умолчанию 20)","required":false,"schema":{"type":"string"}},{"name":"with","in":"query","description":"адрес контакта: письма ОТ или К нему (переписка с контрагентом)","required":false,"schema":{"type":"string"}},{"name":"from","in":"query","description":"фильтр по отправителю (подстрока адреса)","required":false,"schema":{"type":"string"}},{"name":"to","in":"query","description":"фильтр по получателю (подстрока адреса)","required":false,"schema":{"type":"string"}}]}},"/v1/mailboxes/{id}/messages/{msgId}":{"get":{"summary":"Полное письмо: тело, RFC Message-ID/In-Reply-To/References (для тредирования) и сырые заголовки. Внимание: id в пути — per-mailbox (не глобальный); глобальный ключ — messageId.","tags":["Ящики"],"security":[{"apiKey":["mail:read"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":"{ \"id\": \"eaaaaab\", \"messageId\": \"<abc@bank.az>\", \"inReplyTo\": [\"<prev@you.az>\"], \"references\": [\"<root@…>\"], \"subject\": \"…\", \"from\": […], \"to\": […], \"receivedAt\": \"…\", \"text\": \"тело письма\", \"headers\": [{\"name\":\"Message-ID\",\"value\":\"<abc@bank.az>\"}, …] }"}}},"401":{"description":"Неверный ключ"},"403":{"description":"Не хватает права"},"429":{"description":"Лимит частоты"}}}},"/v1/webmail/login-link":{"post":{"summary":"Выдать сотруднику одноразовую ссылку авто-входа в ЕГО ящик в вебмейле — чтобы встроить почту в ваше приложение (напр. CRM). Ссылка живёт 60 секунд и одноразовая: открыв её (в новой вкладке или в iframe), сотрудник попадает в почту без второго логина. Ящик обязан быть на вашем домене.","tags":["Вебмейл (SSO)"],"security":[{"apiKey":["webmail:login"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"url":"https://webmail.ваш-домен.az/?login_token=…","email":"ivan@ваш-домен.az","expiresIn":60}}}},"401":{"description":"Неверный ключ"},"403":{"description":"Не хватает права"},"429":{"description":"Лимит частоты"}},"requestBody":{"required":true,"description":"mailbox — полный адрес ящика сотрудника на вашем домене (обязателен)","content":{"application/json":{"example":{"mailbox":"ivan@ваш-домен.az"}}}}}},"/v1/maildomains":{"post":{"summary":"Подключить домен к почте (создаёт домен, при возможности сам публикует DNS).","tags":["Домены"],"security":[{"apiKey":["mail:domains"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":"{ \"id\": \"…\", \"name\": \"ваш-домен\", \"autoDns\": { \"created\": 6 }, \"records\": [...], \"ready\": false }"}}},"401":{"description":"Неверный ключ"},"403":{"description":"Не хватает права"},"429":{"description":"Лимит частоты"}},"requestBody":{"required":true,"content":{"application/json":{"example":{"name":"ваш-домен"}}}}},"get":{"summary":"Список подключённых доменов проекта.","tags":["Домены"],"security":[{"apiKey":["mail:domains"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"domains":[{"id":"…","name":"ваш-домен"}]}}}},"401":{"description":"Неверный ключ"},"403":{"description":"Не хватает права"},"429":{"description":"Лимит частоты"}}}},"/v1/maildomains/{domain}":{"get":{"summary":"DNS-записи и статус верификации домена.","tags":["Домены"],"security":[{"apiKey":["mail:domains"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":"{ \"name\": \"ваш-домен\", \"records\": [...], \"ready\": true }"}}},"401":{"description":"Неверный ключ"},"403":{"description":"Не хватает права"},"429":{"description":"Лимит частоты"}}}},"/v1/dns/{zone}/records":{"get":{"summary":"Список DNS-записей зоны (зона должна быть привязана к проекту).","tags":["DNS"],"security":[{"apiKey":["dns:read"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"zone":"ваш-домен","records":[{"id":"…","type":"A","name":"@","data":"1.2.3.4"}]}}}},"401":{"description":"Неверный ключ"},"403":{"description":"Не хватает права"},"429":{"description":"Лимит частоты"}}},"post":{"summary":"Создать DNS-запись в зоне проекта.","tags":["DNS"],"security":[{"apiKey":["dns:records"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"created":true}}}},"401":{"description":"Неверный ключ"},"403":{"description":"Не хватает права"},"429":{"description":"Лимит частоты"}},"requestBody":{"required":true,"description":"type — A | AAAA | TXT | MX | CNAME | NS | SRV | CAA; name — имя записи ('@' для корня); data — значение; priority / ttl — для MX / TTL (необязательно)","content":{"application/json":{"example":{"type":"CNAME","name":"app","data":"target.example.com"}}}}}},"/v1/dns/{zone}/records/{id}":{"delete":{"summary":"Удалить DNS-запись. Для GoDaddy добавь ?data=<значение>.","tags":["DNS"],"security":[{"apiKey":["dns:records"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"deleted":true}}}},"401":{"description":"Неверный ключ"},"403":{"description":"Не хватает права"},"429":{"description":"Лимит частоты"}}}},"/v1/webhooks":{"post":{"summary":"Подписаться на события: платформа будет слать POST на ваш URL. secret в ответе — один раз.","tags":["Вебхуки"],"security":[{"apiKey":["webhooks"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":"{ \"id\": \"…\", \"url\": \"…\", \"events\": [...], \"secret\": \"whsec_…\" }"}}},"401":{"description":"Неверный ключ"},"403":{"description":"Не хватает права"},"429":{"description":"Лимит частоты"}},"requestBody":{"required":true,"description":"url — ваш https-адрес приёма (обязателен); events — mail.received, mail.delivered, mail.bounced, mail.complained","content":{"application/json":{"example":{"url":"https://ваш-сервер/webhook","events":["mail.received","mail.bounced"]}}}}},"get":{"summary":"Список ваших вебхуков.","tags":["Вебхуки"],"security":[{"apiKey":["webhooks"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":"{ \"webhooks\": [ { \"id\": \"…\", \"url\": \"…\", \"events\": [...], \"active\": true } ] }"}}},"401":{"description":"Неверный ключ"},"403":{"description":"Не хватает права"},"429":{"description":"Лимит частоты"}}}},"/v1/webhooks/{id}":{"delete":{"summary":"Удалить вебхук.","tags":["Вебхуки"],"security":[{"apiKey":["webhooks"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"deleted":true}}}},"401":{"description":"Неверный ключ"},"403":{"description":"Не хватает права"},"429":{"description":"Лимит частоты"}}}},"/v1/webhooks/{id}/deliveries":{"get":{"summary":"Лог доставок вебхука: статус (pending/delivered/failed), коды, попытки и точное подписанное тело — удобно для отладки подписи.","tags":["Вебхуки"],"security":[{"apiKey":["webhooks"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"deliveries":[{"id":42,"event":"mail.received","status":"failed","httpCode":401,"attempts":7,"payload":"{…}"}]}}}},"401":{"description":"Неверный ключ"},"403":{"description":"Не хватает права"},"429":{"description":"Лимит частоты"}}}},"/v1/webhooks/{id}/deliveries/{deliveryId}/redeliver":{"post":{"summary":"Переотправить конкретную доставку сейчас (например, после того как починили верификатор подписи).","tags":["Вебхуки"],"security":[{"apiKey":["webhooks"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"status":"delivered","httpCode":200}}}},"401":{"description":"Неверный ключ"},"403":{"description":"Не хватает права"},"429":{"description":"Лимит частоты"}}}},"/v1/telegram/mybots":{"post":{"summary":"Подключить существующего бота по токену (из BotFather) к платформе.","tags":["Telegram-боты"],"security":[{"apiKey":["telegram:bots"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"id":"…","botId":123456,"username":"MyBot","name":"My Bot"}}}},"401":{"description":"Неверный ключ"},"403":{"description":"Не хватает права"},"429":{"description":"Лимит частоты"}},"requestBody":{"required":true,"content":{"application/json":{"example":{"token":"123456:ABC-…","note":"бот проекта"}}}}},"get":{"summary":"Список ботов проекта.","tags":["Telegram-боты"],"security":[{"apiKey":["telegram:bots"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"bots":[{"id":"…","username":"MyBot","webhookSet":true}]}}}},"401":{"description":"Неверный ключ"},"403":{"description":"Не хватает права"},"429":{"description":"Лимит частоты"}}}},"/v1/telegram/mybots/bulk":{"post":{"summary":"Массовый импорт: подключить сразу много ботов по списку токенов (из BotFather). tokens — массив или текст (по токену на строку).","tags":["Telegram-боты"],"security":[{"apiKey":["telegram:bots"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"total":2,"added":2,"failed":0,"results":[{"ok":true,"username":"MyBot","botId":123456}]}}}},"401":{"description":"Неверный ключ"},"403":{"description":"Не хватает права"},"429":{"description":"Лимит частоты"}},"requestBody":{"required":true,"content":{"application/json":{"example":{"tokens":["123456:AAA…","234567:BBB…"]}}}}}},"/v1/telegram/mybots/{id}":{"get":{"summary":"Живой статус бота (getMe + вебхук + команды).","tags":["Telegram-боты"],"security":[{"apiKey":["telegram:bots"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":"{ \"username\": \"MyBot\", \"me\": {...}, \"webhook\": {...}, \"commands\": [...] }"}}},"401":{"description":"Неверный ключ"},"403":{"description":"Не хватает права"},"429":{"description":"Лимит частоты"}}}},"/v1/telegram/mybots/{id}/webhook":{"post":{"summary":"Направить апдейты бота на ваш сервер (SPINE принимает от Telegram и пересылает вам).","tags":["Telegram-боты"],"security":[{"apiKey":["telegram:bots"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"hookUrl":"https://api.spine.maxsystems.az/v1/tg/hook/123456","forwardUrl":"…"}}}},"401":{"description":"Неверный ключ"},"403":{"description":"Не хватает права"},"429":{"description":"Лимит частоты"}},"requestBody":{"required":true,"content":{"application/json":{"example":{"forwardUrl":"https://ваш-сервер/tg"}}}}}},"/v1/telegram/mypresets":{"get":{"summary":"Пресеты «фабрика под ключ», доступные проекту (общие + свои): команды, вебхук, профиль.","tags":["Telegram-боты"],"security":[{"apiKey":["telegram:bots"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"presets":[{"id":"…","name":"Поддержка","forwardUrl":"https://…"}]}}}},"401":{"description":"Неверный ключ"},"403":{"description":"Не хватает права"},"429":{"description":"Лимит частоты"}}}},"/v1/telegram/mybots/create-link":{"post":{"summary":"Фабрика: дип-линк создания нового бота. Пользователь подтверждает в Telegram — бот сам подключится к проекту. С presetId бот сразу разворачивается «под ключ» (команды + вебхук + профиль).","tags":["Telegram-боты"],"security":[{"apiKey":["telegram:bots"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"link":"https://t.me/newbot/spinemsbot/myproject_bot"}}}},"401":{"description":"Неверный ключ"},"403":{"description":"Не хватает права"},"429":{"description":"Лимит частоты"}},"requestBody":{"required":true,"content":{"application/json":{"example":{"suggestedUsername":"myproject_bot","presetId":"…(необязательно)"}}}}}}}}