Введение
API Chain Monitor позволяет управлять мониторами кошельков и получать уведомления о транзакциях в реальном времени для Ethereum, BSC, Polygon, Avalanche и Fantom. Создайте API ключ в Панель → API и используйте его для серверных запросов.
Base URL
https://api.chain-monitor.online- • REST JSON API с предсказуемыми URL ресурсов
- • Ethereum, BSC, Polygon, Avalanche, Fantom
- • Уведомления по webhook в реальном времени
Аутентификация
Используйте Bearer токен. Создайте API ключ в Панель → API и передайте его в заголовке Authorization.
Заголовок запроса
Authorization: Bearer api_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxХраните API ключ в безопасности. Не публикуйте его и не добавляйте в репозиторий. При компрометации — смените ключ в панели.
Обработка ошибок
API использует стандартные HTTP-коды ответов.
| Code | Description |
|---|---|
| 200 | Успех |
| 201 | Ресурс создан |
| 400 | Неверный запрос — неверные параметры |
| 401 | Не авторизован — неверный или отсутствующий токен |
| 403 | Доступ запрещён — аккаунт заблокирован |
| 404 | Ресурс не найден |
| 422 | Ошибка валидации |
| 429 | Превышен лимит запросов |
| 500 | Внутренняя ошибка сервера |
Публичные (без авторизации)
Эти эндпоинты не требуют авторизации. Используйте их, чтобы получить UUID сетей и токенов перед созданием мониторов.
GET /public/networks
GET /public/networks — активные сети и токены (без авторизации).
Пример ответа (JSON)
[
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Ethereum",
"slug": "ethereum",
"tokens": [
{ "id": "…", "name": "ETH", "slug": "eth", "type": "native" },
{ "id": "…", "name": "USDT", "slug": "usdt", "type": "token" }
]
}
]GET /public/pack-credits
GET /public/pack-credits — доступные пакеты кредитов (без авторизации).
Пример ответа (JSON)
[
{
"id": "…",
"popular": false,
"count": "1000",
"price": 9.99,
"discount": 0,
"status": "active",
"createdAt": "…",
"updatedAt": "…"
}
]Мониторы кошельков
Мониторы — это адреса блокчейна, которые вы мониторите. У каждого есть сеть, токены, минимальная сумма и опциональный URL webhook.
Получите networkUuid и tokenUuids из GET /public/networks (без авторизации). Используйте network.id и token.id из ответа.
GET /v1/wallets
Возвращает все мониторы кошельков вашего аккаунта.
Пример ответа (JSON)
[
{
"id": "…",
"address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb1",
"networkUuid": "…",
"tokenUuids": ["…"],
"minAmount": "0",
"webhookUrl": null,
"status": "active",
"notifySettings": { "telegram": false, "webhook": true, "notifyIncoming": true, "notifyOutgoing": true },
"network": { /* … */ },
"tokens": [ /* … */ ],
"createdAt": "…",
"updatedAt": "…"
}
]curl -X GET "https://api.chain-monitor.online/v1/wallets" \ -H "Authorization: Bearer api_key_xxx"
POST /v1/wallets
Добавить новый кошелёк для мониторинга.
Тело запроса (JSON)
{
"address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb1",
"networkUuid": "UUID_FROM_GET_PUBLIC_NETWORKS",
"tokenUuids": ["TOKEN_UUID_FROM_NETWORK"],
"minAmount": "100",
"webhookUrl": "https://your-app.com/webhook",
"notifySettings": {
"webhook": true,
"telegram": false,
"notifyIncoming": true,
"notifyOutgoing": true
}
}Пример ответа (JSON)
{
"id": "…",
"address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb1",
"status": "active",
"tokenUuids": ["…"],
"minAmount": "100",
"webhookUrl": "https://your-app.com/webhook",
"notifySettings": { "webhook": true, "telegram": false, "notifyIncoming": true, "notifyOutgoing": true },
"network": { /* … */ },
"tokens": [ /* … */ ],
"createdAt": "…",
"updatedAt": "…"
}curl -X POST "https://api.chain-monitor.online/v1/wallets" \
-H "Authorization: Bearer api_key_xxx" \
-H "Content-Type: application/json" \
-d '{ ... }'PATCH /v1/wallets/:id
Изменить настройки: токены, минимальная сумма, URL webhook.
Необязательные поля — отправляйте только то, что нужно изменить.
{
"tokenUuids": ["…"],
"minAmount": "50",
"webhookUrl": "https://example.com/hook",
"notifySettings": { "webhook": true },
"status": "paused"
}DELETE /v1/wallets/:id
Удалить монитор кошелька. Связанные данные удаляются.
curl -X DELETE "https://api.chain-monitor.online/v1/wallets/WALLET_UUID" \ -H "Authorization: Bearer api_key_xxx"
POST /v1/wallets/:id/toggle
Включить или приостановить мониторинг кошелька.
Пример ответа (JSON)
{ "status": "paused" } // or "active"Уведомления
Список и получение записей уведомлений по API-ключу (те же фильтры, что и в панели).
GET /v1/notifications
Параметры: limit (1–100, по умолчанию 25), offset (по умолчанию 0), status, channel, networkSlug. Ответ: { notifications, total }.
Пример ответа (JSON)
{ "notifications": [ { "id": "…", "userId": "…", "walletId": "…", "channel": "webhook", "eventType": "transaction_detected", "status": "sent", "transactionHash": "0x…", "networkSlug": "ethereum", "payload": { }, "createdAt": "…" } ], "total": 42 }curl -G "https://api.chain-monitor.online/v1/notifications" \ --data-urlencode "limit=25" \ --data-urlencode "offset=0" \ -H "Authorization: Bearer api_key_xxx"
GET /v1/notifications/:id
Получить одно уведомление по ID.
Маршрут GET /notifications (без v1) доступен только с JWT сессии панели.
Страницы оплаты (API-ключ)
Автоматизация страниц оплаты: добавить адрес в пул или создать платёж, который займёт свободный кошелёк для выбранной сети.
POST /v1/payment-pages/pool-wallets
Добавляет один адрес в пул страницы оплаты. paymentPageUuid берётся из панели при создании страницы.
{
"paymentPageUuid": "PAGE_UUID_FROM_DASHBOARD",
"wallet": "0x…",
"networkUuid": "…"
}Пример ответа (JSON)
{
"uuid": "…",
"wallet": "0x…",
"paymentPageUuid": "…",
"status": "free",
"networkUuid": "…",
"network": { "id": "…", "name": "Ethereum", "slug": "ethereum" },
"createdAt": "…",
"updatedAt": "…"
}POST /v1/payment-pages/payments
Резервирует следующий свободный кошелёк в пуле для сети и фиксирует сумму и токен. Вернёт 400, если свободных адресов нет.
{
"paymentPageUuid": "…",
"networkUuid": "…",
"tokenUuid": "…",
"amount": "100.50",
"webHookUrl": "https://optional-callback.example/hook",
"dataOrder": { "orderId": "shop-123" }
}Пример ответа (JSON)
{
"uuid": "…",
"webHookUrl": "https://…",
"status": "waiting",
"wallet": "0x…",
"networkUuid": "…",
"tokenUuid": "…",
"amount": "100.50",
"dataOrder": { "orderId": "shop-123" },
"dataTx": null,
"createdAt": "…",
"updatedAt": "…"
}Webhooks
Когда транзакция совпадает с вашим монитором (сеть, токен, минимальная сумма), мы отправляем POST-запрос на ваш webhook URL. В теле передаются данные транзакции (txHash, network, direction, asset, amount, from, to, timestamp). После создания первого API-ключа выдаётся секрет подписи webhook (один раз в разделе API); в запросе будет заголовок X-Webhook-Signature для проверки тела.
HTTP-запрос
Метод POST, заголовок Content-Type: application/json, тело — JSON в UTF-8. В корне: eventType, userId, при необходимости correlationId, время в ISO8601 и data (детали транзакции). Ответьте HTTP 2xx для успешной приёмки; иные коды могут привести к повторным доставкам.
Откуда берётся секрет подписи
Секрет показывается один раз в Панель → API при создании первого API-ключа. Формат: whsec_ и далее hex. Один секрет на аккаунт — все мониторы кошельков используют его. Ротация API-ключа снова не показывает секрет. Если потеряли — обратитесь в поддержку.
Заголовок X-Webhook-Signature
Если для аккаунта сохранён секрет, каждый webhook содержит этот заголовок. Значение — строка из 64 шестнадцатеричных символов (0-9, a-f): это дайджест HMAC-SHA256 от сырого тела, записанный в hex без префикса.
Как именно считается подпись
Пусть rawBody — точная последовательность байт тела запроса как пришла по сети (до JSON.parse). Пусть secret — ваша строка whsec_… в кодировке UTF-8.
- signature_hex = HMAC-SHA256(ключ = secret как UTF-8, сообщение = rawBody)
- X-Webhook-Signature = signature_hex в виде строки hex в нижнем регистре (64 символа).
В Node.js это совпадает с: crypto.createHmac('sha256', secret).update(rawBody).digest('hex'), если rawBody — Buffer или строка с теми же байтами, что и HTTP-тело.
Когда заголовка нет
Пока для аккаунта не создан и не сохранён секрет, заголовок X-Webhook-Signature не отправляется. После создания первого API-ключа и сохранения секрета новые доставки включают заголовок.
Проверка на вашем сервере
Читайте сырое тело на уровне HTTP (Buffer / Uint8Array / строка сырых байт). Не пересобирайте JSON из объекта — пробелы и порядок полей должны совпадать с отправленными. Посчитайте ожидаемый hex тем же HMAC. Сравните заголовок с ожидаемым значением за постоянное время (например crypto.timingSafeEqual для двух Buffer из hex-строк).
Типичные ошибки
- Использовать JSON.stringify(объект) вместо сырого тела — дайджест не совпадёт.
- Обрезать или менять тело до проверки.
- Сравнение hex без учёта регистра или обычное строковое сравнение вместо защищённого от timing-атак.
Node.js (Express) — проверка с сырым телом
import express from 'express';
import { createHmac, timingSafeEqual } from 'crypto';
const app = express();
app.post(
'/webhook',
express.raw({ type: 'application/json' }),
(req, res) => {
const secret = process.env.CHAIN_MONITOR_WEBHOOK_SECRET; // whsec_...
const rawBody = req.body; // Buffer — must match bytes we sent
const sigHeader = (req.get('x-webhook-signature') || '').trim().toLowerCase();
const expected = createHmac('sha256', secret).update(rawBody).digest('hex');
const a = Buffer.from(sigHeader, 'utf8');
const b = Buffer.from(expected, 'utf8');
if (a.length !== b.length || !timingSafeEqual(a, b)) {
return res.status(401).send('invalid signature');
}
const payload = JSON.parse(rawBody.toString('utf8'));
// ... handle payload
return res.status(200).send('ok');
}
);Пример JSON-тела
{
"eventType": "transaction_detected",
"userId": "uuid",
"correlationId": "tx-0x...-timestamp",
"timestamp": "2024-01-15T10:30:00Z",
"data": {
"txHash": "0x...",
"network": "Ethereum",
"blockNumber": 19485738,
"direction": "in",
"asset": "USDT",
"amount": "250.00",
"from": "0x...",
"to": "0x...",
"timestamp": "2024-01-15T10:30:00Z",
"txHashLink": "https://etherscan.io/tx/0x...",
"fromLink": "https://etherscan.io/address/0x...",
"toLink": "https://etherscan.io/address/0x..."
}
}Контакты
Нужна помощь? Используйте страницу контактов для вопросов по интеграции и поддержке.
Email: support@chain-monitor.online
Контакты →