SPINE API
API работает RUENAZ OpenAPI Консоль

SPINE Developer API

Единый API платформы для внешних проектов: почта, SSL-сертификаты, DNS, ящики, домены, вебхуки и Telegram-боты — по одному ключу.

BASE · https://api.spine.maxsystems.az

🔑 Аутентификация

Заголовок Authorization: Bearer spine_sk_… в каждом запросе. Ключ выдаётся в консоли, показывается один раз, отзывается в клик.

⚙️ Учёт и лимиты

Каждый ключ считает запросы; лимит по умолчанию 120/мин (настраивается). Превышение — 429. Суточные/месячные квоты — по желанию.

⚠️ Коды ошибок

401 ключ неверный · 403 нет права · 429 лимит · 400 ошибка запроса (поле error).

Права (скоупы)
СкоупЧто разрешает
mail:sendОтправка писем
mail:readЧтение писем своих ящиков
mail:mailboxesСоздание и управление ящиками
mail:domainsПодключение и статус доменов
cert:issueЗаказ и перевыпуск сертификатов
cert:readСтатус и скачивание сертификатов
dns:readЧтение DNS-записей зоны
dns:recordsУправление DNS-записями зоны
webhooksПодписка на вебхуки (входящие письма, события доставки)
telegram:botsУправление Telegram-ботами проекта
webmail:loginСсылки авто-входа сотрудника в вебмейл (SSO для встраивания)

Почта

POST/v1/mail/sendmail:send

Отправить письмо. Домен отправителя должен быть подключён к почте SPINE и принадлежать проекту.

Параметры
fromадрес отправителя (обязателен)
toполучатель (обязателен)
subjectтема (или template)
text / htmlтело письма
categoryметка для статистики (необязательно)
idempotencyKeyзащита от дублей (необязательно)
Тело запроса
{
  "from": "noreply@ваш-домен",
  "to": "user@example.com",
  "subject": "Привет",
  "text": "Тело письма"
}
Пример ответа
{ "id": "01K…", "status": "sent", "relayMessageId": "…" }
Примеры кода
curl -X POST "https://api.spine.maxsystems.az/v1/mail/send" \
  -H "Authorization: Bearer spine_sk_ВАШ_КЛЮЧ" \
  -H "Content-Type: application/json" \
  -d '{"from":"noreply@ваш-домен","to":"user@example.com","subject":"Привет","text":"Тело письма"}'
const res = await fetch("https://api.spine.maxsystems.az/v1/mail/send", {
  method: "POST",
  headers: {
    "Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
  "from": "noreply@ваш-домен",
  "to": "user@example.com",
  "subject": "Привет",
  "text": "Тело письма"
})
});
const data = await res.json();
import requests

r = requests.post(
  "https://api.spine.maxsystems.az/v1/mail/send",
  headers={"Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ", "Content-Type": "application/json"},
  data='''{"from":"noreply@ваш-домен","to":"user@example.com","subject":"Привет","text":"Тело письма"}'''
)
print(r.status_code, r.json())
$ch = curl_init("https://api.spine.maxsystems.az/v1/mail/send");
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer spine_sk_ВАШ_КЛЮЧ", "Content-Type: application/json"],
  CURLOPT_POSTFIELDS => '{"from":"noreply@ваш-домен","to":"user@example.com","subject":"Привет","text":"Тело письма"}',
]);
$data = json_decode(curl_exec($ch), true);

Сертификаты

POST/v1/certs/issuecert:issue

Заказать SSL-сертификат для домена в управляемой зоне. Выпуск ~15–30 сек.

Параметры
domainsсписок доменов, можно wildcard *.домен (обязателен)
csrсвой CSR — тогда приватный ключ остаётся у вас (необязательно)
autoRenewавтопродление, по умолчанию true
Тело запроса
{ "domains": ["app.ваш-домен", "*.ваш-домен"], "autoRenew": true }
Пример ответа
{ "id": "…", "subject": "app.ваш-домен", "sans": [...], "status": "pending" }
Примеры кода
curl -X POST "https://api.spine.maxsystems.az/v1/certs/issue" \
  -H "Authorization: Bearer spine_sk_ВАШ_КЛЮЧ" \
  -H "Content-Type: application/json" \
  -d '{"domains":["app.ваш-домен","*.ваш-домен"],"autoRenew":true}'
const res = await fetch("https://api.spine.maxsystems.az/v1/certs/issue", {
  method: "POST",
  headers: {
    "Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({ "domains": ["app.ваш-домен", "*.ваш-домен"], "autoRenew": true })
});
const data = await res.json();
import requests

r = requests.post(
  "https://api.spine.maxsystems.az/v1/certs/issue",
  headers={"Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ", "Content-Type": "application/json"},
  data='''{"domains":["app.ваш-домен","*.ваш-домен"],"autoRenew":true}'''
)
print(r.status_code, r.json())
$ch = curl_init("https://api.spine.maxsystems.az/v1/certs/issue");
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer spine_sk_ВАШ_КЛЮЧ", "Content-Type: application/json"],
  CURLOPT_POSTFIELDS => '{"domains":["app.ваш-домен","*.ваш-домен"],"autoRenew":true}',
]);
$data = json_decode(curl_exec($ch), true);
GET/v1/certs/{id}/statuscert:read

Статус сертификата (pending → active | failed).

Пример ответа
{ "status": "active", "notAfter": "…", "daysLeft": 89 }
Примеры кода
curl -X GET "https://api.spine.maxsystems.az/v1/certs/{id}/status" \
  -H "Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"
const res = await fetch("https://api.spine.maxsystems.az/v1/certs/{id}/status", {
  method: "GET",
  headers: {
    "Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"
  }
});
const data = await res.json();
import requests

r = requests.get(
  "https://api.spine.maxsystems.az/v1/certs/{id}/status",
  headers={"Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"}
)
print(r.status_code, r.json())
$ch = curl_init("https://api.spine.maxsystems.az/v1/certs/{id}/status");
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => "GET",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"],
]);
$data = json_decode(curl_exec($ch), true);
GET/v1/certs/{id}/downloadcert:read

Скачать сертификат (fullchain + приватный ключ; для сертов по CSR privkey=null).

Пример ответа
{ "fullchain": "-----BEGIN CERTIFICATE-----…", "privkey": "…" }
Примеры кода
curl -X GET "https://api.spine.maxsystems.az/v1/certs/{id}/download" \
  -H "Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"
const res = await fetch("https://api.spine.maxsystems.az/v1/certs/{id}/download", {
  method: "GET",
  headers: {
    "Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"
  }
});
const data = await res.json();
import requests

r = requests.get(
  "https://api.spine.maxsystems.az/v1/certs/{id}/download",
  headers={"Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"}
)
print(r.status_code, r.json())
$ch = curl_init("https://api.spine.maxsystems.az/v1/certs/{id}/download");
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => "GET",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"],
]);
$data = json_decode(curl_exec($ch), true);

Ящики

POST/v1/mailboxesmail:mailboxes

Создать почтовый ящик на своём домене.

Параметры
nameимя ящика до @ (2–40, [a-z0-9._-])
domainдомен проекта (обязателен)
passwordпароль ящика (мин. 8)
descriptionописание (необязательно)
Тело запроса
{ "name": "info", "domain": "ваш-домен", "password": "…" }
Пример ответа
{ "email": "info@ваш-домен", "id": "…" }
Примеры кода
curl -X POST "https://api.spine.maxsystems.az/v1/mailboxes" \
  -H "Authorization: Bearer spine_sk_ВАШ_КЛЮЧ" \
  -H "Content-Type: application/json" \
  -d '{"name":"info","domain":"ваш-домен","password":"…"}'
const res = await fetch("https://api.spine.maxsystems.az/v1/mailboxes", {
  method: "POST",
  headers: {
    "Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({ "name": "info", "domain": "ваш-домен", "password": "…" })
});
const data = await res.json();
import requests

r = requests.post(
  "https://api.spine.maxsystems.az/v1/mailboxes",
  headers={"Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ", "Content-Type": "application/json"},
  data='''{"name":"info","domain":"ваш-домен","password":"…"}'''
)
print(r.status_code, r.json())
$ch = curl_init("https://api.spine.maxsystems.az/v1/mailboxes");
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer spine_sk_ВАШ_КЛЮЧ", "Content-Type: application/json"],
  CURLOPT_POSTFIELDS => '{"name":"info","domain":"ваш-домен","password":"…"}',
]);
$data = json_decode(curl_exec($ch), true);
GET/v1/mailboxesmail:mailboxes

Список ящиков и групп на доменах проекта. Поле type: personal (личный), shared (общий, доступ у нескольких людей), group (распределительная группа). У групп поле membersCount.

Пример ответа
{ "mailboxes": [ { "id": "…", "email": "ivan@ваш-домен", "type": "personal", "usedBytes": 0 }, { "id": "…", "email": "team@ваш-домен", "type": "group", "membersCount": 4 } ] }
Примеры кода
curl -X GET "https://api.spine.maxsystems.az/v1/mailboxes" \
  -H "Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"
const res = await fetch("https://api.spine.maxsystems.az/v1/mailboxes", {
  method: "GET",
  headers: {
    "Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"
  }
});
const data = await res.json();
import requests

r = requests.get(
  "https://api.spine.maxsystems.az/v1/mailboxes",
  headers={"Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"}
)
print(r.status_code, r.json())
$ch = curl_init("https://api.spine.maxsystems.az/v1/mailboxes");
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => "GET",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"],
]);
$data = json_decode(curl_exec($ch), true);
DELETE/v1/mailboxes/{id}mail:mailboxes

Удалить ящик (только на своём домене).

Пример ответа
{ "deleted": true }
Примеры кода
curl -X DELETE "https://api.spine.maxsystems.az/v1/mailboxes/{id}" \
  -H "Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"
const res = await fetch("https://api.spine.maxsystems.az/v1/mailboxes/{id}", {
  method: "DELETE",
  headers: {
    "Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"
  }
});
const data = await res.json();
import requests

r = requests.delete(
  "https://api.spine.maxsystems.az/v1/mailboxes/{id}",
  headers={"Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"}
)
print(r.status_code, r.json())
$ch = curl_init("https://api.spine.maxsystems.az/v1/mailboxes/{id}");
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => "DELETE",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"],
]);
$data = json_decode(curl_exec($ch), true);
POST/v1/mailboxes/{id}/sharedmail:mailboxes

Пометить ящик общим (shared) или снять пометку. Общий ящик, это личный ящик, к которому дан доступ нескольким людям (support@, info@). Меняет поле type ящика.

Тело запроса
{ "shared": true }
Пример ответа
{ "id": "…", "shared": true }
Примеры кода
curl -X POST "https://api.spine.maxsystems.az/v1/mailboxes/{id}/shared" \
  -H "Authorization: Bearer spine_sk_ВАШ_КЛЮЧ" \
  -H "Content-Type: application/json" \
  -d '{"shared":true}'
const res = await fetch("https://api.spine.maxsystems.az/v1/mailboxes/{id}/shared", {
  method: "POST",
  headers: {
    "Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({ "shared": true })
});
const data = await res.json();
import requests

r = requests.post(
  "https://api.spine.maxsystems.az/v1/mailboxes/{id}/shared",
  headers={"Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ", "Content-Type": "application/json"},
  data='''{"shared":true}'''
)
print(r.status_code, r.json())
$ch = curl_init("https://api.spine.maxsystems.az/v1/mailboxes/{id}/shared");
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer spine_sk_ВАШ_КЛЮЧ", "Content-Type: application/json"],
  CURLOPT_POSTFIELDS => '{"shared":true}',
]);
$data = json_decode(curl_exec($ch), true);
GET/v1/mailboxes/{id}/messagesmail:read

Список последних писем в ящике (свежие сверху). Можно фильтровать по адресу — удобно для панели «переписка с контактом».

Параметры
limitсколько писем вернуть, до 100 (по умолчанию 20)
withадрес контакта: письма ОТ или К нему (переписка с контрагентом)
fromфильтр по отправителю (подстрока адреса)
toфильтр по получателю (подстрока адреса)
Пример ответа
{ "messages": [ { "id": "eaaaaab", "messageId": ["<abc@bank.az>"], "subject": "…", "from": [{"email":"…"}], "receivedAt": "…", "preview": "…" } ] }
Примеры кода
curl -X GET "https://api.spine.maxsystems.az/v1/mailboxes/{id}/messages" \
  -H "Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"
const res = await fetch("https://api.spine.maxsystems.az/v1/mailboxes/{id}/messages", {
  method: "GET",
  headers: {
    "Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"
  }
});
const data = await res.json();
import requests

r = requests.get(
  "https://api.spine.maxsystems.az/v1/mailboxes/{id}/messages",
  headers={"Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"}
)
print(r.status_code, r.json())
$ch = curl_init("https://api.spine.maxsystems.az/v1/mailboxes/{id}/messages");
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => "GET",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"],
]);
$data = json_decode(curl_exec($ch), true);
GET/v1/mailboxes/{id}/messages/{msgId}mail:read

Полное письмо: тело, RFC Message-ID/In-Reply-To/References (для тредирования) и сырые заголовки. Внимание: id в пути — per-mailbox (не глобальный); глобальный ключ — messageId.

Пример ответа
{ "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>"}, …] }
Примеры кода
curl -X GET "https://api.spine.maxsystems.az/v1/mailboxes/{id}/messages/{msgId}" \
  -H "Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"
const res = await fetch("https://api.spine.maxsystems.az/v1/mailboxes/{id}/messages/{msgId}", {
  method: "GET",
  headers: {
    "Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"
  }
});
const data = await res.json();
import requests

r = requests.get(
  "https://api.spine.maxsystems.az/v1/mailboxes/{id}/messages/{msgId}",
  headers={"Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"}
)
print(r.status_code, r.json())
$ch = curl_init("https://api.spine.maxsystems.az/v1/mailboxes/{id}/messages/{msgId}");
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => "GET",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"],
]);
$data = json_decode(curl_exec($ch), true);

Группы

GET/v1/groupsmail:mailboxes

Список распределительных групп проекта. Группа, это адрес team@домен, письмо на который разлетается всем участникам в их личные ящики.

Пример ответа
{ "groups": [ { "id": "…", "email": "team@ваш-домен", "membersCount": 4 } ] }
Примеры кода
curl -X GET "https://api.spine.maxsystems.az/v1/groups" \
  -H "Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"
const res = await fetch("https://api.spine.maxsystems.az/v1/groups", {
  method: "GET",
  headers: {
    "Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"
  }
});
const data = await res.json();
import requests

r = requests.get(
  "https://api.spine.maxsystems.az/v1/groups",
  headers={"Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"}
)
print(r.status_code, r.json())
$ch = curl_init("https://api.spine.maxsystems.az/v1/groups");
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => "GET",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"],
]);
$data = json_decode(curl_exec($ch), true);
POST/v1/groupsmail:mailboxes

Создать распределительную группу name@домен. Домен обязан быть на вашем проекте.

Параметры
domainдомен проекта (обязателен)
nameимя адреса, 2-40 символов [a-z0-9._-] (обязателен)
descriptionописание группы (необязательно)
Тело запроса
{ "domain": "ваш-домен.az", "name": "team", "description": "Вся команда" }
Пример ответа
{ "id": "…", "email": "team@ваш-домен.az" }
Примеры кода
curl -X POST "https://api.spine.maxsystems.az/v1/groups" \
  -H "Authorization: Bearer spine_sk_ВАШ_КЛЮЧ" \
  -H "Content-Type: application/json" \
  -d '{"domain":"ваш-домен.az","name":"team","description":"Вся команда"}'
const res = await fetch("https://api.spine.maxsystems.az/v1/groups", {
  method: "POST",
  headers: {
    "Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({ "domain": "ваш-домен.az", "name": "team", "description": "Вся команда" })
});
const data = await res.json();
import requests

r = requests.post(
  "https://api.spine.maxsystems.az/v1/groups",
  headers={"Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ", "Content-Type": "application/json"},
  data='''{"domain":"ваш-домен.az","name":"team","description":"Вся команда"}'''
)
print(r.status_code, r.json())
$ch = curl_init("https://api.spine.maxsystems.az/v1/groups");
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer spine_sk_ВАШ_КЛЮЧ", "Content-Type: application/json"],
  CURLOPT_POSTFIELDS => '{"domain":"ваш-домен.az","name":"team","description":"Вся команда"}',
]);
$data = json_decode(curl_exec($ch), true);
DELETE/v1/groups/{id}mail:mailboxes

Удалить группу.

Пример ответа
{ "deleted": true }
Примеры кода
curl -X DELETE "https://api.spine.maxsystems.az/v1/groups/{id}" \
  -H "Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"
const res = await fetch("https://api.spine.maxsystems.az/v1/groups/{id}", {
  method: "DELETE",
  headers: {
    "Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"
  }
});
const data = await res.json();
import requests

r = requests.delete(
  "https://api.spine.maxsystems.az/v1/groups/{id}",
  headers={"Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"}
)
print(r.status_code, r.json())
$ch = curl_init("https://api.spine.maxsystems.az/v1/groups/{id}");
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => "DELETE",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"],
]);
$data = json_decode(curl_exec($ch), true);
GET/v1/groups/{id}/membersmail:mailboxes

Участники группы (ящики, в которые разлетается почта).

Пример ответа
{ "members": [ { "id": "…", "email": "ivan@ваш-домен.az" } ] }
Примеры кода
curl -X GET "https://api.spine.maxsystems.az/v1/groups/{id}/members" \
  -H "Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"
const res = await fetch("https://api.spine.maxsystems.az/v1/groups/{id}/members", {
  method: "GET",
  headers: {
    "Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"
  }
});
const data = await res.json();
import requests

r = requests.get(
  "https://api.spine.maxsystems.az/v1/groups/{id}/members",
  headers={"Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"}
)
print(r.status_code, r.json())
$ch = curl_init("https://api.spine.maxsystems.az/v1/groups/{id}/members");
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => "GET",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"],
]);
$data = json_decode(curl_exec($ch), true);
POST/v1/groups/{id}/membersmail:mailboxes

Добавить ящик в группу по его адресу.

Тело запроса
{ "mailbox": "ivan@ваш-домен.az" }
Пример ответа
{ "ok": true, "member": { "id": "…", "email": "ivan@ваш-домен.az" } }
Примеры кода
curl -X POST "https://api.spine.maxsystems.az/v1/groups/{id}/members" \
  -H "Authorization: Bearer spine_sk_ВАШ_КЛЮЧ" \
  -H "Content-Type: application/json" \
  -d '{"mailbox":"ivan@ваш-домен.az"}'
const res = await fetch("https://api.spine.maxsystems.az/v1/groups/{id}/members", {
  method: "POST",
  headers: {
    "Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({ "mailbox": "ivan@ваш-домен.az" })
});
const data = await res.json();
import requests

r = requests.post(
  "https://api.spine.maxsystems.az/v1/groups/{id}/members",
  headers={"Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ", "Content-Type": "application/json"},
  data='''{"mailbox":"ivan@ваш-домен.az"}'''
)
print(r.status_code, r.json())
$ch = curl_init("https://api.spine.maxsystems.az/v1/groups/{id}/members");
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer spine_sk_ВАШ_КЛЮЧ", "Content-Type: application/json"],
  CURLOPT_POSTFIELDS => '{"mailbox":"ivan@ваш-домен.az"}',
]);
$data = json_decode(curl_exec($ch), true);
DELETE/v1/groups/{id}/members/{userId}mail:mailboxes

Убрать участника из группы.

Пример ответа
{ "ok": true }
Примеры кода
curl -X DELETE "https://api.spine.maxsystems.az/v1/groups/{id}/members/{userId}" \
  -H "Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"
const res = await fetch("https://api.spine.maxsystems.az/v1/groups/{id}/members/{userId}", {
  method: "DELETE",
  headers: {
    "Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"
  }
});
const data = await res.json();
import requests

r = requests.delete(
  "https://api.spine.maxsystems.az/v1/groups/{id}/members/{userId}",
  headers={"Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"}
)
print(r.status_code, r.json())
$ch = curl_init("https://api.spine.maxsystems.az/v1/groups/{id}/members/{userId}");
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => "DELETE",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"],
]);
$data = json_decode(curl_exec($ch), true);

Вебмейл (SSO)

POST/v1/webmail/login-linkwebmail:login

Выдать сотруднику одноразовую ссылку авто-входа в ЕГО ящик в вебмейле — чтобы встроить почту в ваше приложение (напр. CRM). Ссылка живёт 60 секунд и одноразовая: открыв её (в новой вкладке или в iframe), сотрудник попадает в почту без второго логина. Ящик обязан быть на вашем домене.

Параметры
mailboxполный адрес ящика сотрудника на вашем домене (обязателен)
Тело запроса
{ "mailbox": "ivan@ваш-домен.az" }
Пример ответа
{ "url": "https://webmail.ваш-домен.az/?login_token=…", "email": "ivan@ваш-домен.az", "expiresIn": 60 }
Примеры кода
curl -X POST "https://api.spine.maxsystems.az/v1/webmail/login-link" \
  -H "Authorization: Bearer spine_sk_ВАШ_КЛЮЧ" \
  -H "Content-Type: application/json" \
  -d '{"mailbox":"ivan@ваш-домен.az"}'
const res = await fetch("https://api.spine.maxsystems.az/v1/webmail/login-link", {
  method: "POST",
  headers: {
    "Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({ "mailbox": "ivan@ваш-домен.az" })
});
const data = await res.json();
import requests

r = requests.post(
  "https://api.spine.maxsystems.az/v1/webmail/login-link",
  headers={"Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ", "Content-Type": "application/json"},
  data='''{"mailbox":"ivan@ваш-домен.az"}'''
)
print(r.status_code, r.json())
$ch = curl_init("https://api.spine.maxsystems.az/v1/webmail/login-link");
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer spine_sk_ВАШ_КЛЮЧ", "Content-Type: application/json"],
  CURLOPT_POSTFIELDS => '{"mailbox":"ivan@ваш-домен.az"}',
]);
$data = json_decode(curl_exec($ch), true);

Домены

POST/v1/maildomainsmail:domains

Подключить домен к почте (создаёт домен, при возможности сам публикует DNS).

Тело запроса
{ "name": "ваш-домен" }
Пример ответа
{ "id": "…", "name": "ваш-домен", "autoDns": { "created": 6 }, "records": [...], "ready": false }
Примеры кода
curl -X POST "https://api.spine.maxsystems.az/v1/maildomains" \
  -H "Authorization: Bearer spine_sk_ВАШ_КЛЮЧ" \
  -H "Content-Type: application/json" \
  -d '{"name":"ваш-домен"}'
const res = await fetch("https://api.spine.maxsystems.az/v1/maildomains", {
  method: "POST",
  headers: {
    "Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({ "name": "ваш-домен" })
});
const data = await res.json();
import requests

r = requests.post(
  "https://api.spine.maxsystems.az/v1/maildomains",
  headers={"Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ", "Content-Type": "application/json"},
  data='''{"name":"ваш-домен"}'''
)
print(r.status_code, r.json())
$ch = curl_init("https://api.spine.maxsystems.az/v1/maildomains");
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer spine_sk_ВАШ_КЛЮЧ", "Content-Type: application/json"],
  CURLOPT_POSTFIELDS => '{"name":"ваш-домен"}',
]);
$data = json_decode(curl_exec($ch), true);
GET/v1/maildomainsmail:domains

Список подключённых доменов проекта.

Пример ответа
{ "domains": [ { "id": "…", "name": "ваш-домен" } ] }
Примеры кода
curl -X GET "https://api.spine.maxsystems.az/v1/maildomains" \
  -H "Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"
const res = await fetch("https://api.spine.maxsystems.az/v1/maildomains", {
  method: "GET",
  headers: {
    "Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"
  }
});
const data = await res.json();
import requests

r = requests.get(
  "https://api.spine.maxsystems.az/v1/maildomains",
  headers={"Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"}
)
print(r.status_code, r.json())
$ch = curl_init("https://api.spine.maxsystems.az/v1/maildomains");
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => "GET",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"],
]);
$data = json_decode(curl_exec($ch), true);
GET/v1/maildomains/{domain}mail:domains

DNS-записи и статус верификации домена.

Пример ответа
{ "name": "ваш-домен", "records": [...], "ready": true }
Примеры кода
curl -X GET "https://api.spine.maxsystems.az/v1/maildomains/{domain}" \
  -H "Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"
const res = await fetch("https://api.spine.maxsystems.az/v1/maildomains/{domain}", {
  method: "GET",
  headers: {
    "Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"
  }
});
const data = await res.json();
import requests

r = requests.get(
  "https://api.spine.maxsystems.az/v1/maildomains/{domain}",
  headers={"Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"}
)
print(r.status_code, r.json())
$ch = curl_init("https://api.spine.maxsystems.az/v1/maildomains/{domain}");
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => "GET",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"],
]);
$data = json_decode(curl_exec($ch), true);

DNS

GET/v1/dns/{zone}/recordsdns:read

Список DNS-записей зоны (зона должна быть привязана к проекту).

Пример ответа
{ "zone": "ваш-домен", "records": [ { "id": "…", "type": "A", "name": "@", "data": "1.2.3.4" } ] }
Примеры кода
curl -X GET "https://api.spine.maxsystems.az/v1/dns/{zone}/records" \
  -H "Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"
const res = await fetch("https://api.spine.maxsystems.az/v1/dns/{zone}/records", {
  method: "GET",
  headers: {
    "Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"
  }
});
const data = await res.json();
import requests

r = requests.get(
  "https://api.spine.maxsystems.az/v1/dns/{zone}/records",
  headers={"Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"}
)
print(r.status_code, r.json())
$ch = curl_init("https://api.spine.maxsystems.az/v1/dns/{zone}/records");
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => "GET",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"],
]);
$data = json_decode(curl_exec($ch), true);
POST/v1/dns/{zone}/recordsdns:records

Создать DNS-запись в зоне проекта.

Параметры
typeA | AAAA | TXT | MX | CNAME | NS | SRV | CAA
nameимя записи ('@' для корня)
dataзначение
priority / ttlдля MX / TTL (необязательно)
Тело запроса
{ "type": "CNAME", "name": "app", "data": "target.example.com" }
Пример ответа
{ "created": true }
Примеры кода
curl -X POST "https://api.spine.maxsystems.az/v1/dns/{zone}/records" \
  -H "Authorization: Bearer spine_sk_ВАШ_КЛЮЧ" \
  -H "Content-Type: application/json" \
  -d '{"type":"CNAME","name":"app","data":"target.example.com"}'
const res = await fetch("https://api.spine.maxsystems.az/v1/dns/{zone}/records", {
  method: "POST",
  headers: {
    "Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({ "type": "CNAME", "name": "app", "data": "target.example.com" })
});
const data = await res.json();
import requests

r = requests.post(
  "https://api.spine.maxsystems.az/v1/dns/{zone}/records",
  headers={"Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ", "Content-Type": "application/json"},
  data='''{"type":"CNAME","name":"app","data":"target.example.com"}'''
)
print(r.status_code, r.json())
$ch = curl_init("https://api.spine.maxsystems.az/v1/dns/{zone}/records");
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer spine_sk_ВАШ_КЛЮЧ", "Content-Type: application/json"],
  CURLOPT_POSTFIELDS => '{"type":"CNAME","name":"app","data":"target.example.com"}',
]);
$data = json_decode(curl_exec($ch), true);
DELETE/v1/dns/{zone}/records/{id}dns:records

Удалить DNS-запись. Для GoDaddy добавь ?data=<значение>.

Пример ответа
{ "deleted": true }
Примеры кода
curl -X DELETE "https://api.spine.maxsystems.az/v1/dns/{zone}/records/{id}" \
  -H "Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"
const res = await fetch("https://api.spine.maxsystems.az/v1/dns/{zone}/records/{id}", {
  method: "DELETE",
  headers: {
    "Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"
  }
});
const data = await res.json();
import requests

r = requests.delete(
  "https://api.spine.maxsystems.az/v1/dns/{zone}/records/{id}",
  headers={"Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"}
)
print(r.status_code, r.json())
$ch = curl_init("https://api.spine.maxsystems.az/v1/dns/{zone}/records/{id}");
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => "DELETE",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"],
]);
$data = json_decode(curl_exec($ch), true);

Вебхуки

POST/v1/webhookswebhooks

Подписаться на события: платформа будет слать POST на ваш URL. secret в ответе — один раз.

Параметры
urlваш https-адрес приёма (обязателен)
eventsmail.received, mail.delivered, mail.bounced, mail.complained
Тело запроса
{ "url": "https://ваш-сервер/webhook", "events": ["mail.received", "mail.bounced"] }
Пример ответа
{ "id": "…", "url": "…", "events": [...], "secret": "whsec_…" }
Примеры кода
curl -X POST "https://api.spine.maxsystems.az/v1/webhooks" \
  -H "Authorization: Bearer spine_sk_ВАШ_КЛЮЧ" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://ваш-сервер/webhook","events":["mail.received","mail.bounced"]}'
const res = await fetch("https://api.spine.maxsystems.az/v1/webhooks", {
  method: "POST",
  headers: {
    "Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({ "url": "https://ваш-сервер/webhook", "events": ["mail.received", "mail.bounced"] })
});
const data = await res.json();
import requests

r = requests.post(
  "https://api.spine.maxsystems.az/v1/webhooks",
  headers={"Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ", "Content-Type": "application/json"},
  data='''{"url":"https://ваш-сервер/webhook","events":["mail.received","mail.bounced"]}'''
)
print(r.status_code, r.json())
$ch = curl_init("https://api.spine.maxsystems.az/v1/webhooks");
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer spine_sk_ВАШ_КЛЮЧ", "Content-Type: application/json"],
  CURLOPT_POSTFIELDS => '{"url":"https://ваш-сервер/webhook","events":["mail.received","mail.bounced"]}',
]);
$data = json_decode(curl_exec($ch), true);
GET/v1/webhookswebhooks

Список ваших вебхуков.

Пример ответа
{ "webhooks": [ { "id": "…", "url": "…", "events": [...], "active": true } ] }
Примеры кода
curl -X GET "https://api.spine.maxsystems.az/v1/webhooks" \
  -H "Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"
const res = await fetch("https://api.spine.maxsystems.az/v1/webhooks", {
  method: "GET",
  headers: {
    "Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"
  }
});
const data = await res.json();
import requests

r = requests.get(
  "https://api.spine.maxsystems.az/v1/webhooks",
  headers={"Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"}
)
print(r.status_code, r.json())
$ch = curl_init("https://api.spine.maxsystems.az/v1/webhooks");
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => "GET",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"],
]);
$data = json_decode(curl_exec($ch), true);
DELETE/v1/webhooks/{id}webhooks

Удалить вебхук.

Пример ответа
{ "deleted": true }
Примеры кода
curl -X DELETE "https://api.spine.maxsystems.az/v1/webhooks/{id}" \
  -H "Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"
const res = await fetch("https://api.spine.maxsystems.az/v1/webhooks/{id}", {
  method: "DELETE",
  headers: {
    "Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"
  }
});
const data = await res.json();
import requests

r = requests.delete(
  "https://api.spine.maxsystems.az/v1/webhooks/{id}",
  headers={"Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"}
)
print(r.status_code, r.json())
$ch = curl_init("https://api.spine.maxsystems.az/v1/webhooks/{id}");
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => "DELETE",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"],
]);
$data = json_decode(curl_exec($ch), true);
GET/v1/webhooks/{id}/deliverieswebhooks

Лог доставок вебхука: статус (pending/delivered/failed), коды, попытки и точное подписанное тело — удобно для отладки подписи.

Пример ответа
{ "deliveries": [ { "id": 42, "event": "mail.received", "status": "failed", "httpCode": 401, "attempts": 7, "payload": "{…}" } ] }
Примеры кода
curl -X GET "https://api.spine.maxsystems.az/v1/webhooks/{id}/deliveries" \
  -H "Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"
const res = await fetch("https://api.spine.maxsystems.az/v1/webhooks/{id}/deliveries", {
  method: "GET",
  headers: {
    "Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"
  }
});
const data = await res.json();
import requests

r = requests.get(
  "https://api.spine.maxsystems.az/v1/webhooks/{id}/deliveries",
  headers={"Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"}
)
print(r.status_code, r.json())
$ch = curl_init("https://api.spine.maxsystems.az/v1/webhooks/{id}/deliveries");
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => "GET",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"],
]);
$data = json_decode(curl_exec($ch), true);
POST/v1/webhooks/{id}/deliveries/{deliveryId}/redeliverwebhooks

Переотправить конкретную доставку сейчас (например, после того как починили верификатор подписи).

Пример ответа
{ "status": "delivered", "httpCode": 200 }
Примеры кода
curl -X POST "https://api.spine.maxsystems.az/v1/webhooks/{id}/deliveries/{deliveryId}/redeliver" \
  -H "Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"
const res = await fetch("https://api.spine.maxsystems.az/v1/webhooks/{id}/deliveries/{deliveryId}/redeliver", {
  method: "POST",
  headers: {
    "Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"
  }
});
const data = await res.json();
import requests

r = requests.post(
  "https://api.spine.maxsystems.az/v1/webhooks/{id}/deliveries/{deliveryId}/redeliver",
  headers={"Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"}
)
print(r.status_code, r.json())
$ch = curl_init("https://api.spine.maxsystems.az/v1/webhooks/{id}/deliveries/{deliveryId}/redeliver");
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"],
]);
$data = json_decode(curl_exec($ch), true);

Telegram-боты

POST/v1/telegram/mybotstelegram:bots

Подключить существующего бота по токену (из BotFather) к платформе.

Тело запроса
{ "token": "123456:ABC-…", "note": "бот проекта" }
Пример ответа
{ "id": "…", "botId": 123456, "username": "MyBot", "name": "My Bot" }
Примеры кода
curl -X POST "https://api.spine.maxsystems.az/v1/telegram/mybots" \
  -H "Authorization: Bearer spine_sk_ВАШ_КЛЮЧ" \
  -H "Content-Type: application/json" \
  -d '{"token":"123456:ABC-…","note":"бот проекта"}'
const res = await fetch("https://api.spine.maxsystems.az/v1/telegram/mybots", {
  method: "POST",
  headers: {
    "Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({ "token": "123456:ABC-…", "note": "бот проекта" })
});
const data = await res.json();
import requests

r = requests.post(
  "https://api.spine.maxsystems.az/v1/telegram/mybots",
  headers={"Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ", "Content-Type": "application/json"},
  data='''{"token":"123456:ABC-…","note":"бот проекта"}'''
)
print(r.status_code, r.json())
$ch = curl_init("https://api.spine.maxsystems.az/v1/telegram/mybots");
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer spine_sk_ВАШ_КЛЮЧ", "Content-Type: application/json"],
  CURLOPT_POSTFIELDS => '{"token":"123456:ABC-…","note":"бот проекта"}',
]);
$data = json_decode(curl_exec($ch), true);
POST/v1/telegram/mybots/bulktelegram:bots

Массовый импорт: подключить сразу много ботов по списку токенов (из BotFather). tokens — массив или текст (по токену на строку).

Тело запроса
{ "tokens": ["123456:AAA…", "234567:BBB…"] }
Пример ответа
{ "total": 2, "added": 2, "failed": 0, "results": [ { "ok": true, "username": "MyBot", "botId": 123456 } ] }
Примеры кода
curl -X POST "https://api.spine.maxsystems.az/v1/telegram/mybots/bulk" \
  -H "Authorization: Bearer spine_sk_ВАШ_КЛЮЧ" \
  -H "Content-Type: application/json" \
  -d '{"tokens":["123456:AAA…","234567:BBB…"]}'
const res = await fetch("https://api.spine.maxsystems.az/v1/telegram/mybots/bulk", {
  method: "POST",
  headers: {
    "Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({ "tokens": ["123456:AAA…", "234567:BBB…"] })
});
const data = await res.json();
import requests

r = requests.post(
  "https://api.spine.maxsystems.az/v1/telegram/mybots/bulk",
  headers={"Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ", "Content-Type": "application/json"},
  data='''{"tokens":["123456:AAA…","234567:BBB…"]}'''
)
print(r.status_code, r.json())
$ch = curl_init("https://api.spine.maxsystems.az/v1/telegram/mybots/bulk");
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer spine_sk_ВАШ_КЛЮЧ", "Content-Type: application/json"],
  CURLOPT_POSTFIELDS => '{"tokens":["123456:AAA…","234567:BBB…"]}',
]);
$data = json_decode(curl_exec($ch), true);
GET/v1/telegram/mybotstelegram:bots

Список ботов проекта.

Пример ответа
{ "bots": [ { "id": "…", "username": "MyBot", "webhookSet": true } ] }
Примеры кода
curl -X GET "https://api.spine.maxsystems.az/v1/telegram/mybots" \
  -H "Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"
const res = await fetch("https://api.spine.maxsystems.az/v1/telegram/mybots", {
  method: "GET",
  headers: {
    "Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"
  }
});
const data = await res.json();
import requests

r = requests.get(
  "https://api.spine.maxsystems.az/v1/telegram/mybots",
  headers={"Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"}
)
print(r.status_code, r.json())
$ch = curl_init("https://api.spine.maxsystems.az/v1/telegram/mybots");
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => "GET",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"],
]);
$data = json_decode(curl_exec($ch), true);
GET/v1/telegram/mybots/{id}telegram:bots

Живой статус бота (getMe + вебхук + команды).

Пример ответа
{ "username": "MyBot", "me": {...}, "webhook": {...}, "commands": [...] }
Примеры кода
curl -X GET "https://api.spine.maxsystems.az/v1/telegram/mybots/{id}" \
  -H "Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"
const res = await fetch("https://api.spine.maxsystems.az/v1/telegram/mybots/{id}", {
  method: "GET",
  headers: {
    "Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"
  }
});
const data = await res.json();
import requests

r = requests.get(
  "https://api.spine.maxsystems.az/v1/telegram/mybots/{id}",
  headers={"Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"}
)
print(r.status_code, r.json())
$ch = curl_init("https://api.spine.maxsystems.az/v1/telegram/mybots/{id}");
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => "GET",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"],
]);
$data = json_decode(curl_exec($ch), true);
POST/v1/telegram/mybots/{id}/webhooktelegram:bots

Направить апдейты бота на ваш сервер (SPINE принимает от Telegram и пересылает вам).

Тело запроса
{ "forwardUrl": "https://ваш-сервер/tg" }
Пример ответа
{ "hookUrl": "https://api.spine.maxsystems.az/v1/tg/hook/123456", "forwardUrl": "…" }
Примеры кода
curl -X POST "https://api.spine.maxsystems.az/v1/telegram/mybots/{id}/webhook" \
  -H "Authorization: Bearer spine_sk_ВАШ_КЛЮЧ" \
  -H "Content-Type: application/json" \
  -d '{"forwardUrl":"https://ваш-сервер/tg"}'
const res = await fetch("https://api.spine.maxsystems.az/v1/telegram/mybots/{id}/webhook", {
  method: "POST",
  headers: {
    "Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({ "forwardUrl": "https://ваш-сервер/tg" })
});
const data = await res.json();
import requests

r = requests.post(
  "https://api.spine.maxsystems.az/v1/telegram/mybots/{id}/webhook",
  headers={"Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ", "Content-Type": "application/json"},
  data='''{"forwardUrl":"https://ваш-сервер/tg"}'''
)
print(r.status_code, r.json())
$ch = curl_init("https://api.spine.maxsystems.az/v1/telegram/mybots/{id}/webhook");
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer spine_sk_ВАШ_КЛЮЧ", "Content-Type: application/json"],
  CURLOPT_POSTFIELDS => '{"forwardUrl":"https://ваш-сервер/tg"}',
]);
$data = json_decode(curl_exec($ch), true);
GET/v1/telegram/mypresetstelegram:bots

Пресеты «фабрика под ключ», доступные проекту (общие + свои): команды, вебхук, профиль.

Пример ответа
{ "presets": [ { "id": "…", "name": "Поддержка", "forwardUrl": "https://…" } ] }
Примеры кода
curl -X GET "https://api.spine.maxsystems.az/v1/telegram/mypresets" \
  -H "Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"
const res = await fetch("https://api.spine.maxsystems.az/v1/telegram/mypresets", {
  method: "GET",
  headers: {
    "Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"
  }
});
const data = await res.json();
import requests

r = requests.get(
  "https://api.spine.maxsystems.az/v1/telegram/mypresets",
  headers={"Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ"}
)
print(r.status_code, r.json())
$ch = curl_init("https://api.spine.maxsystems.az/v1/telegram/mypresets");
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => "GET",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer spine_sk_ВАШ_КЛЮЧ"],
]);
$data = json_decode(curl_exec($ch), true);
POST/v1/telegram/mybots/create-linktelegram:bots

Фабрика: дип-линк создания нового бота. Пользователь подтверждает в Telegram — бот сам подключится к проекту. С presetId бот сразу разворачивается «под ключ» (команды + вебхук + профиль).

Тело запроса
{ "suggestedUsername": "myproject_bot", "presetId": "…(необязательно)" }
Пример ответа
{ "link": "https://t.me/newbot/spinemsbot/myproject_bot" }
Примеры кода
curl -X POST "https://api.spine.maxsystems.az/v1/telegram/mybots/create-link" \
  -H "Authorization: Bearer spine_sk_ВАШ_КЛЮЧ" \
  -H "Content-Type: application/json" \
  -d '{"suggestedUsername":"myproject_bot","presetId":"…(необязательно)"}'
const res = await fetch("https://api.spine.maxsystems.az/v1/telegram/mybots/create-link", {
  method: "POST",
  headers: {
    "Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({ "suggestedUsername": "myproject_bot", "presetId": "…(необязательно)" })
});
const data = await res.json();
import requests

r = requests.post(
  "https://api.spine.maxsystems.az/v1/telegram/mybots/create-link",
  headers={"Authorization": "Bearer spine_sk_ВАШ_КЛЮЧ", "Content-Type": "application/json"},
  data='''{"suggestedUsername":"myproject_bot","presetId":"…(необязательно)"}'''
)
print(r.status_code, r.json())
$ch = curl_init("https://api.spine.maxsystems.az/v1/telegram/mybots/create-link");
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer spine_sk_ВАШ_КЛЮЧ", "Content-Type: application/json"],
  CURLOPT_POSTFIELDS => '{"suggestedUsername":"myproject_bot","presetId":"…(необязательно)"}',
]);
$data = json_decode(curl_exec($ch), true);
WEBHOOKПроверка подписи и доставка

Каждая доставка — POST с заголовками X-Spine-Event (тип события) и X-Spine-Signature: sha256=<hex>. Тело: {"event":"…","ts":"…","data":{…}}.

Подпись = HMAC-SHA256 от сырого тела запроса (байты как пришли, до разбора JSON). Ключ — секрет whsec_… как есть, строкой целиком: НЕ декодировать из base64 и НЕ срезать префикс (это не Svix). Результат — hex, с префиксом sha256=. Сравнивайте в константное время.

Верификатор (Node.js)
const crypto = require("crypto");
function verifySpineWebhook(secret, rawBody, sigHeader) {
  // secret   — строка ЦЕЛИКОМ, включая префикс whsec_ (не декодировать/не обрезать)
  // rawBody  — СЫРОЕ тело запроса (Buffer/строка), до JSON.parse
  // sigHeader— значение заголовка X-Spine-Signature ("sha256=…")
  const expected = "sha256=" + crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
  const a = Buffer.from(sigHeader || ""), b = Buffer.from(expected);
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}
Доставка и повторы

Одна немедленная попытка; при неуспехе — durable-ретраи с экспоненциальным бэкоффом (≈ через 1 мин, 5 мин, 30 мин, 2 ч, 6 ч, 12 ч — до 7 попыток за ~21 час), очередь переживает перезапуск. Успех = ваш ответ 2xx. Лог доставок — GET /v1/webhooks/{id}/deliveries (видно статус, коды и точное подписанное тело); переотправить конкретную — POST /v1/webhooks/{id}/deliveries/{deliveryId}/redeliver. Отвечайте быстро, тяжёлую обработку — в фон (доставка «хотя бы один раз», делайте обработчик идемпотентным).

Событие mail.received — что внутри data

Для входящего письма отдаём его метаданные (message), RFC-заголовки треда (rfc) и сигналы фрода (security):

"data": {
  "mailbox": "you@ваш-домен.az", "mailboxId": "c",
  "message": {
    "id": "eaaaaab",                          // per-mailbox id (НЕ глобальный, см. ниже)
    "from": [{ "email": "sender@bank.az" }], "to": [{ "email": "you@ваш-домен.az" }],
    "subject": "…", "receivedAt": "…", "preview": "…"
  },
  "rfc": {
    "messageId": "<abc123@bank.az>",         // RFC Message-ID — глобально-уникальный ключ письма
    "inReplyTo": ["<prev@you.az>"],           // на что это ответ
    "references": ["<root@…>", "<prev@you.az>"]  // цепочка треда
  },
  "security": {
    "spam": { "isSpam": false, "score": 2.9, "status": "No", "label": "ham", "symbols": "DKIM_VALID(-0.5), …" },
    "auth": { "spf": "pass", "dkim": "pass", "dmarc": "pass" }
  }
}

Идентификаторы: message.id — короткий per-mailbox id (для чтения того же письма через API), НЕ глобальный. Как глобально-уникальный ключ (идемпотентность, тредирование) используйте rfc.messageId; связывайте ответы в тред по rfc.inReplyTo/rfc.references.

security: score — оценка спам-фильтра (стиль rspamd; больше = подозрительнее), isSpam — превысил ли порог; spf/dkim/dmarc — подлинность отправителя (pass/fail/none…). Если письмо без этих заголовков — поле может быть null.

SPINE API · базовый адрес https://api.spine.maxsystems.az · машинное описание /v1/openapi.json