Документация API
Добавьте нужные адреса в любой из 23 сетей и получайте уведомление о каждой входящей транзакции: подписанный webhook, событие API, сообщение в Telegram или email, публикацию в Discord либо Slack.
Аутентификация
В каждом запросе передавайте API-ключ в заголовке Authorization. Доступны два ключа: ck_test_… (sandbox — бесплатная имитация транзакций) и ck_live_… (production).
$ curl https://api.cryptanio.com/v1/watches \
-H "Authorization: Bearer ck_live_4t9G…R1SC"
Быстрый старт
Одного запроса достаточно, чтобы начать наблюдение. Следующая транзакция по адресу вызовет первое уведомление — обычно через несколько секунд после попадания в блок.
$ curl -X POST https://api.cryptanio.com/v1/watches \
-H "Authorization: Bearer ck_live_…" \
-H "Content-Type: application/json" \
-d '{
"project": "1002",
"chain": "ethereum",
"address": "0x7c3A1d4E8b2f6C9a0D5e8F1b4C7a2E5d8B1f9eF2",
"asset": "USDC",
"label": "Main treasury",
"note": "Operations wallet"
}'
{
"id": "1008",
"project_id": "1002",
"service": "monitoring",
"book_address_id": "1007",
"status": "active",
"chain": "ethereum",
"address": "0x7c3A…9eF2",
"asset": "USDC",
"watch_outgoing": false,
"origin_kinds": ["manual"]
}
Configure Webhook, Web Push, Email, Slack, Discord and Telegram destinations for the account or project in the dashboard. Delivery policy belongs to the project, not to an individual address. Test everything against the sandbox first: addresses attached with a ck_test_, можно запустить вручную запросом POST /v1/simulate.
API наблюдений
Объект watch is one address attached to one Monitoring project. The address itself is stored once in the account address book; each project keeps its own direction, asset and event rules. All endpoints live under https://api.cryptanio.com/v1.
| Метод API | Назначение |
|---|---|
| POST/v1/watches | Создаёт watch. Возвращает 201 с объектом watch. |
| GET/v1/watches?project=:id | List one Monitoring project's watches. project is required; chain is optional. |
| GET/v1/watches/:id | Возвращает один watch и его последние платежи. |
| DELETE/v1/watches/:id | Останавливает наблюдение. Транзакции в обработке ещё некоторое время будут приходить в течение защитного периода. |
| GET/v1/payments | Ищет обнаруженные платежи по watch, адресу, идентификатору транзакции или периоду времени. |
| GET/v1/chains | Возвращает сети текущего развёртывания, их правила подтверждения и поддержку токенов. Ключ не требуется. |
| GET/v1/events | Повторно получает доставленные события за период до 30 дней — резервный способ восстановления после недоступности endpoint. |
Поля запроса
| Поле | Тип | Описание |
|---|---|---|
| project | string | Required Monitoring project id. An address cannot exist outside a project route. |
| chain | string | Одно из значений bitcoin, ethereum, solana, tron, ton, bsc, base, xrp, dash. Обязательное поле. Актуальный список возвращает GET /v1/chains. |
| address | string | Адрес получения. Для Solana передавайте кошелёк: связанные token accounts вычисляются и отслеживаются автоматически. |
| label | string | Optional address-book name, up to 60 characters. |
| note | string | Optional account note, up to 280 characters. |
| asset | string | Shortcut for one exact asset: native by default, a supported symbol, or a network-specific identifier. |
| asset_policy | string | exact (default), allow, or all. |
| asset_ids | string[] | Assets included by an allow rule. Each explicit asset becomes its own physical scan target. |
| excluded_asset_ids | string[] | Assets excluded from an all rule. |
| watch_outgoing | boolean | Также уведомлять, когда средства уходят с этого адреса. Исходящие переводы приходят отдельными типами событий — debit.*, но не payment.* — поэтому существующая обработка входящих платежей не меняется. Не каждая сеть поддерживает исходящие операции: неподдерживаемая сеть отклонит создание watch с явной ошибкой, а не выполнит запрос частично. |
| min_confirmations | number | Optional project rule stricter than the network default. |
| min_amount | string | Optional positive amount in minimal units. Smaller movements remain auditable but do not notify. |
| watch_contracts | boolean | Enable supported allowance, owner, threshold and permission events. |
| watch_unexpected_assets | boolean | Report assets outside the accepted rule without crediting them. |
Webhooks
Каждое изменение состояния отправляется одним HTTP POST на ваш endpoint. Доставка работает по принципу at-least-once: повторы возможны и ожидаемы. Удаляйте дубликаты по (chain, tx_id, index, address, asset) или просто по event_id.
Все пользовательские webhooks имеют одну версионированную форму независимо от сети. В кабинете для каждого проекта можно выбрать После подтверждения (подтверждённые состояния, откаты и изменения контрактов), Полный жизненный цикл (все текущие и будущие события, включая ожидающие состояния) либо собственный список событий. Область live/sandbox, валюта оценки и пауза настраиваются независимо. Проект может унаследовать полный маршрут аккаунта или использовать собственный полный маршрут.
| Заголовок | Значение |
|---|---|
| X-Event-Id | Уникальный идентификатор события (ULID). Также присутствует в теле как event_id. |
| X-Event-Type | One of the twelve business types below, or the webhook.test control event. Route on this and never on a field inside the body. |
| X-Timestamp | Unix-время в секундах на момент подписи; входит в подписываемые данные. |
| X-Signature | HMAC-SHA256 в hex-формате для строки <timestamp>.<body>. |
| X-Attempt | Номер попытки доставки, начиная с 1. |
Типы событий
Три семейства намеренно разделены. Маршрутизация идёт по типу, поэтому вывод средств или изменение multisig нельзя случайно принять за входящий платёж из-за непрочитанного поля.
| Тип | Что означает |
|---|---|
| payment.pending | Средства поступили, и сеть увидела транзакцию. Финальности ещё нет. |
| payment.confirmed | Средства поступили, транзакция подтверждена. По этому событию можно выдавать товар. |
| payment.rolled_back | Реорганизация отменила входящую транзакцию. Платёж считается несостоявшимся. |
| debit.pending | Средства уходят с адреса. Только для watches с параметром watch_outgoing. |
| debit.confirmed | Средства ушли, транзакция подтверждена. |
| debit.rolled_back | Реорганизация отменила исходящую транзакцию. |
| contract.approval | Для вашего адреса выдано разрешение на расходование. |
| contract.owner_added | В отслеживаемом multisig появился новый владелец. |
| contract.owner_removed | Из multisig удалён владелец. |
| contract.threshold_changed | Изменилось необходимое число подписей. |
| contract.permissions_changed | Заменён встроенный в сеть набор разрешений аккаунта, включая порог подписей. |
| asset.unexpected | Поступил неожиданный актив. Средства действительно перемещены, но ничего не зачислено. |
Две формы тела, а не двенадцать. Семейства payment.* и debit.* содержат объект payment с суммой. Семейство contract.* и событие asset.unexpected содержат объект contract вместо него — без суммы и глубины подтверждения, потому что эти события ничего не переводят.
Тело события
{
"schema_version": "v1",
"event_id": "1101",
"event_type": "payment.confirmed",
"occurred_at": "2026-09-10T20:00:00Z",
"project_id": "1002",
"mode": "live",
"sandbox": false,
"payment": {
"chain": "ethereum",
"direction": "in",
"asset": {
"symbol": "USDT",
"standard": "erc20",
"contract": "0xdAC17F…1ec7"
},
"address": "0x7c3A…9eF2",
"tx_id": "0x9b41f2…c77d",
"index": 2,
"height": 20731442,
"amount": "10.000000",
"amount_raw": "10000000",
"decimals": 6,
"confirmations": 12,
"valuation": {
"currency": "USD",
"amount": "10.00",
"rate": "1.00",
"rate_at": "2026-09-10T20:00:00Z"
}
},
"invoice": {
"id": "1009",
"reference": "order-4471",
"status": "paid",
"currency": "USD",
"amount": "10.00"
},
"customer": { "id": "customer-1842" },
"product": {
"id": "vps-month", "name": "VPS rental", "quantity": 1
},
"payer": { "comment": "Thank you!" },
"metadata": { "campaign": "summer" }
}
{
"schema_version": "v1",
"event_id": "1102",
"event_type": "debit.confirmed",
"occurred_at": "2026-09-10T20:07:44Z",
"project_id": "1002",
"mode": "live",
"sandbox": false,
"payment": {
"chain": "bitcoin",
"direction": "out",
"asset": { "symbol": "BTC" },
"tx_id": "c1d89fd9…fc8f",
"index": 0,
"address": "bc1qltw…uxjh",
"amount": "0.00435000",
"amount_raw": "435000",
"decimals": 8,
"confirmations": 3
}
}
{
"schema_version": "v1",
"event_id": "1103",
"event_type": "contract.owner_added",
"occurred_at": "2026-09-10T20:19:02Z",
"project_id": "1002",
"mode": "live",
"sandbox": false,
"contract": {
"chain": "ethereum",
"tx_id": "0x4ae1…b902",
"index": 4,
"height": 20731509,
"address": "0x7c3A…9eF2",
"kind": "owner_added",
"detail": { "owner": "0x91Bd…4c7A" }
}
}
- direction принимает значение "in" или "out" и всегда присутствует у платежа. Направление также следует из типа события; используйте удобный вариант, но не определяйте его по знаку суммы — суммы никогда не бывают отрицательными.
- Каждое значение в detail передаётся строкой. Allowance имеет тип uint256, который не помещается в JSON number.
- match_key содержит назначение, переданное самой сетью: комментарий TON или reference Solana Pay. Поле отсутствует в сетях и платежах без такого значения — то есть в большинстве случаев.
- mode принимает значение "live" или "test": какое окружение отправило событие. Значение находится в подписанном теле, а не только в заголовке, поэтому тестовый запрос нельзя выдать production-endpoint без этой пометки.
- amount_raw and amount are strings. The first is exact minimal units for arithmetic; the second is the exact decimal representation for display. Neither passes through a JSON float.
- invoice, customer, product, payer and metadata are immutable snapshots. They are present only when supplied for the matched invoice. invoice.id is Cryptanio's id; invoice.reference is yours.
- index разделяет несколько зачислений в одной транзакции: индекс выхода Bitcoin, индекс лога Ethereum, ноль в Solana.
- valuation is what the payment was worth when it arrived. Its amount and rate are decimal strings, and rate_at fixes the price moment. The invoice currency wins; otherwise the project's selected currency is used. The object is absent when no trustworthy rate was available.
- Optional fields are omitted, not filled with empty strings. The schema is stable across every supported chain; chain-specific source documents are never the customer webhook contract.
Повторные попытки
- Тайм-аут одной попытки: 10 s. Сетевые ошибки, 408, 425, 429 и 5xx повторяются. Перенаправления никогда не выполняются; остальные ответы 3xx/4xx завершают эту доставку.
- Целевая экспоненциальная задержка повторов растёт от 2 s до 15 минут со случайным разбросом. Корректный Retry-After в секундах или в виде HTTP-даты для любого повторяемого ответа задаёт минимальную задержку. Повторные попытки продолжаются в течение 24 часов.
- В пределах одного процесса Cryptanio на один hostname одновременно отправляется только один запрос. Временная ошибка запускает общую паузу для этого хоста; для исправных хостов искусственного лимита запросов в секунду нет.
- 410 Gone retires the destination and its queued backlog. For a primary project route it pauses webhook delivery; deleting an API-created endpoint removes that subscription and closes its backlog too.
- Всё же пропустили событие? GET /v1/events повторно отдаёт события за последние 30 дней.
Queue test is a control event. The dashboard sends webhook.test with the same v1 envelope, signature and project routing but no payment or contract. It bypasses the project's pause and event filter so you can test before enabling delivery.
Проверка подписей
Подпись — это HMAC-SHA256 в hex-формате для строки <timestamp>.<raw body> с секретом webhook в качестве ключа (кабинет → Webhooks). Сравнивайте за постоянное время и отклоняйте устаревшие timestamp, чтобы закрыть повторное воспроизведение.
const crypto = require("node:crypto");
function verify(secret, timestamp, rawBody, signature) {
const expected = crypto
.createHmac("sha256", secret)
.update(`${timestamp}.${rawBody}`)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(expected), Buffer.from(signature));
}
// reject if |now − timestamp| > 300 s, then verify
func verify(secret, ts string, body []byte, sig string) bool {
mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(ts))
mac.Write([]byte("."))
mac.Write(body)
expected := hex.EncodeToString(mac.Sum(nil))
return hmac.Equal([]byte(expected), []byte(sig))
}
Поток событий
GET /v1/stream is a server-sent events feed for live dashboards and local development. It keeps the query/event representation used by GET /v1/events; customer webhooks use the stricter versioned v1 contract documented above.
$ curl -N https://api.cryptanio.com/v1/stream \
-H "Authorization: Bearer ck_live_…"
: connected
retry: 5000
event: payment
data: {"event_id":"01J5WQ…","event_type":"payment.confirmed", … }
: ping
- Каждое событие использует event: payment, а data: contains the stored event representation. Do not use the stream parser as a webhook v1 parser.
- Строки, начинающиеся с двоеточия, — комментарии и встроенный keep-alive SSE. Одна приходит при подключении, затем каждые двадцать секунд, чтобы отличить тихий аккаунт от разорванного соединения.
- Это не архив событий. Приходят только события, возникшие во время подключения. Пропущенные данные доступны через GET /v1/events за последние 30 дней.
- Переподключайтесь свободно — параметр retry: 5000 указывает стандартному EventSource вернуться через пять секунд; браузерные реализации делают это автоматически.
API получателей событий
Subscribe URLs to one project's events without opening the dashboard. A live key creates live endpoints; a test key creates sandbox endpoints, and each key can list or delete only its own mode.
| Метод API | Назначение |
|---|---|
| POST /v1/endpoints | Подписывает URL с протоколом https://. Возвращает endpoint и его secret — секрет показывается только один раз. |
| GET /v1/endpoints | Возвращает подписки аккаунта. Секреты повторно не показываются. |
| DELETE /v1/endpoints/:id | Останавливает доставку на endpoint. |
| GET /v1/health | Проверяет доступность и возвращает текущую версию. Ключ не требуется. |
{
"url": "https://example.com/hooks/cryptanio",
"label": "production",
"project": "1002"
}
→ 201
{
"id": "1010",
"project_id": "1002",
"sandbox": false,
"url": "https://example.com/hooks/cryptanio",
"label": "production",
"secret": "0460765e9292…544ce",
"source": "api",
"created_at": "2026-08-16T13:52:01Z"
}
- Каждый endpoint подписывает события собственным секретом, который возвращается один раз при создании. Проверяйте подпись как описано выше; для ротации создайте новый endpoint и удалите старый.
- The project chooses delivery. Extra webhook endpoints follow that project's event, pause and live/sandbox policy; an individual address does not select channels.
- Public HTTPS on port 443 only. Credentials in URLs, fragments, redirects, loopback/private/link-local addresses and DNS answers containing a non-public address are refused. Environment proxy settings are not inherited.
- The same URL may be registered separately for different projects and for live and sandbox mode. Each registration has its own id and secret.
- До двадцати на аккаунт. Это не тарифный лимит: превращение одного платежа в сотню доставок расходует исходящий трафик и ресурсы чужого endpoint, а обычной интеграции достаточно нескольких адресатов.
API инвойсов
Запросите конкретную сумму и получите событие при её поступлении. Инвойс берёт адрес из вашей адресной книги, удерживает его на время заказа и сопоставляет точную поступившую сумму — не нужно угадывать, какой платёж относится к какой корзине.
Это модуль приёма платежей. Every account gets ten invoices a month; a paid tier raises it. An invoice uses an address already attached to that Payments project, including addresses supplied by a connected address-book list or an automatic address source.
| Метод API | Назначение |
|---|---|
| POST/v1/invoices | Создаёт инвойс. Возвращает 201 с адресом и точной суммой для отображения. |
| GET/v1/invoices | Возвращает список с фильтрами по project, chain, status. |
| GET/v1/invoices/:id | Возвращает текущее состояние одного инвойса. |
| POST/v1/invoices/:id/cancel | Отменяет инвойс и освобождает адрес. Запись остаётся доступной, чтобы отменённый заказ можно было найти. |
Поля запроса
| Поле | Тип | Описание |
|---|---|---|
| chain | string | Обязательное поле. Список совпадает с GET /v1/chains. |
| amount | string | Обязательная десятичная строка в единицах актива — "12.50", не центы и не float. JSON number потеряет младшие разряды токена с 18 знаками после запятой. |
| asset | string | Символ актива. По умолчанию используется нативная монета сети. |
| reference | string | Ваш идентификатор заказа. Возвращается в каждом событии, поэтому отдельное сопоставление не нужно. |
| customer | object | Optional immutable customer snapshot: {"id":"customer-1842"}. The id is yours, not a Cryptanio user id. |
| product | object | Optional immutable product snapshot with id, name and integer quantity. Supply only the fields that apply. |
| payer | object | Optional payer snapshot: {"comment":"Thank you!"}. |
| metadata | object | Up to 20 string key-value pairs. Keys use letters, digits, dot, dash or underscore. Stored with the invoice and echoed in its payment webhooks. |
| invoice_currency | string | Your three-letter order currency, such as USD. Supply it together with invoice_amount; it also takes priority for payment valuation. |
| invoice_amount | string | Your positive decimal order total in invoice_currency. This is separate from crypto amount and is never parsed through a JSON float. |
| project | string | Проект или направление бизнеса. По умолчанию используется первый проект; пул адресов не смешивается между проектами. |
| address | string | Закрепляет один из ваших адресов вместо выбора из пула. Несколько открытых заказов смогут использовать его одновременно и различаться по сумме. |
| tolerance | string | Допустимая недоплата, которая всё ещё считается оплатой, например из-за удержанной у отправителя сетевой комиссии. Пустое значение требует точного совпадения. |
| expires_in | number | Минуты. Инвойс удерживает адрес на весь срок, поэтому значение ограничено сверху. |
{
"chain": "bitcoin",
"amount": "0.0125",
"reference": "order-4471",
"customer": { "id": "customer-1842" },
"product": { "id": "vps-month", "name": "VPS rental", "quantity": 1 },
"payer": { "comment": "Thank you!" },
"metadata": { "campaign": "summer" },
"invoice_currency": "USD",
"invoice_amount": "10.00",
"expires_in": 30
}
→ 201
{
"id": "1009",
"status": "pending",
"reference": "order-4471",
"customer": { "id": "customer-1842" },
"product": { "id": "vps-month", "name": "VPS rental", "quantity": 1 },
"payer": { "comment": "Thank you!" },
"metadata": { "campaign": "summer" },
"invoice_currency": "USD",
"invoice_amount": "10.00",
"chain": "bitcoin",
"asset": "BTC",
"address": "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq",
"asked": "0.0125",
"amount": "0.01250002",
"amount_raw": "1250002",
"decimals": 8,
"sandbox": false,
"expires_at": "2026-08-16T14:22:01Z",
"created_at": "2026-08-16T13:52:01Z"
}
- Показывайте amount, а сверяйте по amount_raw. Если другой открытый заказ на том же адресе уже ждёт такую же круглую сумму, мы добавим несколько минимальных единиц, чтобы различить платежи. asked — согласованная с покупателем сумма; amount — сумма, которая должна фактически поступить.
- Инвойс закрывается теми же событиями, что и остальные процессы. Webhook срабатывает на платёж, а инвойс одновременно переходит в paid. Отдельного потока событий для подписки нет.
- Два состояния требуют решения человека. underpaid и late устанавливают needs_decision и ожидают: Cryptanio не решает за вас, считать ли оплатой недостающую сумму или перевод после срока. Обработайте их в кабинете.
- Тестовый ключ создаёт только sandbox-инвойсы на sandbox-адресах. Интеграционные тесты могут работать весь день, не резервируя адреса реальных заказов: освобождённый адрес ждёт 48 часов перед возвратом в пул, и активные тесты иначе быстро исчерпали бы его.
Жизненный цикл платежа
Каждый платёж проходит явную машину состояний. Каждый переход создаёт одно уведомление, а настроенные каналы получают отдельные доставки.
| Состояние | Значение | Когда приходит |
|---|---|---|
| pending | Транзакция находится в блоке, который ещё может быть отменён. | Через несколько секунд после включения в блок — покажите прогресс на странице оплаты. |
| confirmed | Глубина или финальность достигла уровня, который сеть считает необратимым. | Для каждой сети действует своё правило: финальность протокола в Ethereum, BNB Chain и Base; finalized slot в Solana; solidified block в TRON; ChainLock в Dash; validated ledger в XRP; глубина 3 в Bitcoin. По этому событию можно выдавать товар. |
| rolled_back | Блок покинул цепочку из-за реорганизации либо транзакция завершилась ошибкой. | Только при наличии подтверждения, никогда по отсутствию данных. Событие редкое, но именно оно делает остальные два статуса надёжными. |
Платёж, отменённый реорганизацией и позже снова включённый в блок, создаёт новую последовательность pending → confirmed с новой ревизией — журнал событий остаётся полным и упорядоченным.
Лимиты и оплата
Тарифы мониторинга различаются только объёмом: все сети, каналы и весь API доступны на каждом уровне, включая бесплатный объём. Отличается только уровень поддержки. Полные цены — на странице мониторинга.
| Тариф | Адресов под наблюдением | Уведомлений в месяц | Цена |
|---|---|---|---|
| Бесплатно | 5 | 1,000 | $0 |
| Start | 50 | 10,000 | $9 / месяц |
| Pro | 500 | 100,000 | $29 / месяц |
| Scale | 5,000 | 1,000,000 | $99 / месяц |
- Watch = one address attached to one Monitoring project. Several asset targets for that same project address do not multiply the plan unit.
- Уведомление = одно изменение состояния. Отправка в несколько каналов и повторная доставка одного события не увеличивают использование.
- Превысили лимит? Когда тарифицируемый перерасход выключен, как по умолчанию, уведомления продолжают приходить ещё 48 часов, а мы сообщаем по email: без неожиданных списаний и молча потерянных событий. Если вы сами включите перерасход, оплата ограничится заданным месячным пределом.
- Лимит API: 10 запросов/с на бесплатном уровне, 50 запросов/с на платных тарифах. 429 с заголовком Retry-After при превышении.
Остались вопросы?
Напишите на hello@cryptanio.com — обычно инженер отвечает в течение нескольких часов.