Перейти к содержанию

REST API чекера MAX: как получить доступ, лимиты и примеры запросов (2026)

REST API чекера MAX: как запросить ключ через /support за 1-2 дня, лимиты по умолчанию, HMAC-подпись webhook, idempotency-key, примеры на cURL, Python и Node.js.

REST API чекера MAX — доступ, лимиты, примеры запросов
20 апреля 2026 г.обновл. 22 мая 2026 г.Max Checker TeamЧтение · 14 минdevelopers

REST API чекера MAX доступен по индивидуальной выдаче через /support в Telegram-боте. Это намеренная архитектурная схема: каждому клиенту команда подбирает rate-limit, тариф и условия SLA под реальный объём и сценарий — это позволяет крупным клиентам экономить 20-40% по сравнению со «средним» self-serve тарифом, а мелким — не платить за неиспользуемые лимиты.

Эта статья — практическая документация: как запросить доступ, какие лимиты по умолчанию, как считать HMAC-подпись webhook'а, какие коды ошибок ловить, и три полных рабочих сниппета на cURL, Python и Node.js.

TL;DR

  • Доступ — через /support в боте, 1-2 рабочих дня, без формы self-serve
  • Endpoint: POST https://api.checkmaxapp.com/v1/check-account (одиночный), POST /v1/check-account/batch (до 10 000 номеров)
  • Авторизация: Authorization: Bearer sk_live_... + опциональный Idempotency-Key: <UUID> (RFC 9110)
  • Webhook callback с подписью X-MaxChecker-Signature (HMAC-SHA256, RFC 2104)
  • Лимиты по умолчанию: 100 req/min одиночных, 10 batch/час, batch ≤ 10k
  • Тариф от $0.005 за положительный hit, отрицательные бесплатно
  • SLA опционально: 99.9% / p95 ≤ 500 мс
Проверь свою базу за минуту
$0.005/номер · скидки от 10% до 60%
Открыть бота →

Как мы выдаём ключ

Путь от первого сообщения в /support до production-ключа — обычно 1-2 рабочих дня. Этапы:

Шаг 1 — заявка (5 минут вашего времени). В Telegram-боте на checkmaxapp.com пишете /support и описываете кейс по форме (см. раздел ниже). Бот форвардит заявку в очередь команды интеграций.

Шаг 2 — уточнение (день 0-1). Поддержка возвращается с уточняющими вопросами: пиковая нагрузка, желаемая модель оплаты (commit / pay-as-you-go), нужен ли формальный SLA-договор, на какой стороне будет жить webhook.

Шаг 3 — выдача ключа (день 1-2). Получаете в защищённом канале:

  • MAXCHECKER_TOKEN формата sk_live_<32 base62 символа> — для Authorization: Bearer заголовка
  • MAXCHECKER_WEBHOOK_SECRET — для проверки HMAC-подписи входящих callback'ов
  • URL endpoint'ов (production + staging)
  • Согласованные лимиты (X-RateLimit-Limit ваш персональный)
  • OpenAPI 3.1 спецификацию под ваш профиль

Шаг 4 — интеграция (1-3 дня на стороне клиента). Делаете тестовый вызов на staging (5 проверок в подарок к ключу), подключаете webhook, проверяете HMAC, выводите в production. Команда на связи в выделенном канале.

Шаг 5 — production. После первой недели работы созваниваемся на 15 минут — смотрим метрики, корректируем лимиты, если профиль оказался другим.

Что мы спросим в /support

Чтобы команда сразу подобрала тариф и rate-limit без лишних итераций, пришлите при запросе следующее:

  1. Ожидаемый объём проверок в месяц — диапазон вида «20 000-40 000» достаточен; нужен ли burst-режим (например, 100 000 раз в месяц, но 80% за один день перед рассылкой).
  2. Кейс: антифрод на регистрации, обогащение CRM, чистка базы перед рассылкой, white-label, OSINT-инструмент, другое.
  3. Платформа интеграции: amoCRM, Bitrix24, HubSpot, Make, Zapier, n8n, кастомный бэкенд (с указанием стека — Python/Node/Go/Java/PHP).
  4. Латентность: критична ли низкая задержка отклика (антифрод — да, чистка базы — нет, batch с webhook — нет).
  5. SLA: нужен ли формальный договор с гарантиями 99.9% / p95 латентности / кредитами за нарушение.
  6. Где будет жить webhook-приёмник: публичный URL с HTTPS, есть ли возможность поднять (если нет — расскажем про polling-режим через GET /v1/jobs/{id}).

Чем подробнее заявка — тем меньше итераций, тем быстрее ключ.

Endpoint: одиночная проверка

Базовый URL: https://api.checkmaxapp.com. Все запросы — HTTPS, TLS 1.2+.

Формат запроса

POST /v1/check-account HTTP/1.1
Host: api.checkmaxapp.com
Authorization: Bearer sk_live_<your_token>
Content-Type: application/json
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000

{
  "phone": "+79161234567"
}

Idempotency-Key — опциональный UUID v4. Если задан, сервер хранит результат 24 часа: повторный вызов с тем же ключом вернёт кэшированный ответ без повторного списания (поведение по RFC 9110 §9.2.2). Используйте уникальный UUID на каждый бизнес-вызов — это даёт безопасный ретрай при сетевых таймаутах.

Ответ 200 OK

{
  "phone": "+79161234567",
  "registered": true,
  "firstName": "Анна",
  "lastName": "Иванова",
  "server_id": 847291,
  "last_seen": "2026-05-21T09:42:15Z",
  "bio": "Маркетолог, Москва",
  "checked_at": "2026-05-22T12:33:21Z",
  "request_id": "req_x9k2hf4n8p"
}

При registered=false остальные поля отсутствуют. Тарифицируются только положительные hits — registered=false всегда бесплатно. request_id сохраняйте в логах: пригодится при инцидент-разборе с поддержкой.

Пример: cURL

#!/usr/bin/env bash
set -euo pipefail

TOKEN="${MAXCHECKER_TOKEN:?set MAXCHECKER_TOKEN env var}"
IDEMPOTENCY_KEY="$(uuidgen)"

curl -fsSL -X POST https://api.checkmaxapp.com/v1/check-account \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: ${IDEMPOTENCY_KEY}" \
  -d '{"phone": "+79161234567"}' \
  --retry 3 --retry-delay 2 --retry-connrefused \
  -w '\nHTTP %{http_code} in %{time_total}s\n'

--retry 3 справится с временными 5xx; для 429 нужен respect к заголовку Retry-After — здесь cURL его не учитывает, поэтому в production-скриптах используйте Python/Node-клиенты с правильной retry-логикой (см. ниже).

Пример: Python (requests)

Полный production-ready клиент с retry и idempotency:

"""MaxChecker REST API client.

Зависимости: requests >= 2.31
"""
from __future__ import annotations

import os
import time
import uuid
import logging
from typing import Any

import requests

log = logging.getLogger(__name__)

API_BASE = "https://api.checkmaxapp.com"
TOKEN = os.environ["MAXCHECKER_TOKEN"]


class MaxCheckerError(Exception):
    """Базовая ошибка API."""


class RateLimitError(MaxCheckerError):
    def __init__(self, retry_after: int) -> None:
        super().__init__(f"rate limit; retry after {retry_after}s")
        self.retry_after = retry_after


def check_phone(
    phone: str,
    *,
    idempotency_key: str | None = None,
    timeout: float = 10.0,
    max_retries: int = 5,
) -> dict[str, Any]:
    """Проверить один номер. Делает экспоненциальный retry на 429 и 5xx."""
    headers = {
        "Authorization": f"Bearer {TOKEN}",
        "Content-Type": "application/json",
        "Idempotency-Key": idempotency_key or str(uuid.uuid4()),
    }
    payload = {"phone": phone}

    for attempt in range(max_retries):
        try:
            r = requests.post(
                f"{API_BASE}/v1/check-account",
                headers=headers,
                json=payload,
                timeout=timeout,
            )
        except requests.RequestException as exc:
            log.warning("network error attempt=%d: %s", attempt, exc)
            time.sleep(min(2 ** attempt, 30))
            continue

        if r.status_code == 200:
            return r.json()

        if r.status_code == 429:
            retry_after = int(r.headers.get("Retry-After", 2 ** attempt))
            log.warning("429; sleeping %ds", retry_after)
            time.sleep(retry_after)
            continue

        if 500 <= r.status_code < 600:
            time.sleep(min(2 ** attempt, 30))
            continue

        # 4xx (кроме 429) — не ретраим, ошибка клиента
        body = r.json() if r.headers.get("Content-Type", "").startswith("application/json") else {}
        raise MaxCheckerError(
            f"HTTP {r.status_code} error={body.get('error')} message={body.get('message')}"
        )

    raise MaxCheckerError("exceeded max_retries")


if __name__ == "__main__":
    logging.basicConfig(level=logging.INFO)
    result = check_phone("+79161234567")
    if result["registered"]:
        print(f"{result.get('firstName')} {result.get('lastName')} — {result.get('last_seen')}")
    else:
        print("not registered in MAX")

Запуск:

export MAXCHECKER_TOKEN="sk_live_..."
python check.py

Для async-нагрузок 100+ rps замените requests на httpx.AsyncClient с http2=True — даст 2-3× прирост по сравнению с sync-pool'ом. Готовый async-клиент есть в нашем бойлерплейте.

Пример: Node.js (axios)

Аналогичный клиент на Node.js 20+ с axios и axios-retry:

// maxchecker-client.mjs
// Зависимости: axios@^1.6, axios-retry@^4
import axios from 'axios';
import axiosRetry from 'axios-retry';
import { randomUUID } from 'node:crypto';

const TOKEN = process.env.MAXCHECKER_TOKEN;
if (!TOKEN) throw new Error('MAXCHECKER_TOKEN env var is required');

const client = axios.create({
  baseURL: 'https://api.checkmaxapp.com',
  timeout: 10_000,
  headers: {
    Authorization: `Bearer ${TOKEN}`,
    'Content-Type': 'application/json',
  },
});

axiosRetry(client, {
  retries: 5,
  retryDelay: (retryCount, error) => {
    // Если сервер прислал Retry-After — слушаем его
    const retryAfter = error?.response?.headers?.['retry-after'];
    if (retryAfter) return Number(retryAfter) * 1000;
    return Math.min(2 ** retryCount * 1000, 30_000);
  },
  retryCondition: (error) => {
    const status = error?.response?.status;
    return status === 429 || (status >= 500 && status < 600) || !status;
  },
});

export async function checkPhone(phone, { idempotencyKey } = {}) {
  const { data } = await client.post(
    '/v1/check-account',
    { phone },
    { headers: { 'Idempotency-Key': idempotencyKey ?? randomUUID() } },
  );
  return data;
}

// Demo
const result = await checkPhone('+79161234567');
console.log(result.registered ? `${result.firstName} ${result.lastName}` : 'not registered');

В TypeScript-проектах добавьте типизацию ответа:

type CheckAccountResponse =
  | {
      phone: string;
      registered: true;
      firstName?: string;
      lastName?: string;
      server_id: number;
      last_seen?: string;
      bio?: string;
      checked_at: string;
      request_id: string;
    }
  | {
      phone: string;
      registered: false;
      checked_at: string;
      request_id: string;
    };

Batch endpoint

Для объёмов от 100 номеров — async batch. До 10 000 номеров за один вызов, пропускная способность сервера — до 1 млн номеров в час.

Запрос

POST /v1/check-account/batch HTTP/1.1
Authorization: Bearer sk_live_...
Content-Type: application/json
Idempotency-Key: 6f9619ff-8b86-d011-b42d-00cf4fc964ff

{
  "phones": [
    "+79161234567",
    "+79162345678",
    "+79163456789"
  ],
  "callback_url": "https://your-app.example.com/maxcheck/webhook",
  "metadata": {
    "campaign_id": "spring_cleanup_2026",
    "internal_batch_id": "batch_42"
  }
}

Поле metadata — произвольный JSON-объект, возвращается обратно в webhook без изменений. Удобно для трассировки на стороне клиента.

Ответ 202 Accepted

{
  "job_id": "job_8x4kpqz2nm",
  "status": "queued",
  "phones_count": 3,
  "estimated_completion": "2026-05-22T13:42:00Z",
  "request_id": "req_a7b9c2..."
}

Webhook callback

Когда batch готов, сервер делает POST на ваш callback_url:

POST /maxcheck/webhook HTTP/1.1
Host: your-app.example.com
Content-Type: application/json
X-MaxChecker-Signature: sha256=<HEX>
X-MaxChecker-Timestamp: 1716381140
User-Agent: MaxChecker-Webhook/1.0

{
  "job_id": "job_8x4kpqz2nm",
  "status": "completed",
  "results_url": "https://api.checkmaxapp.com/v1/jobs/job_8x4kpqz2nm/results.csv",
  "results_expires_at": "2026-05-29T12:33:21Z",
  "stats": {
    "total": 10000,
    "registered": 7240,
    "not_found": 2760,
    "errors": 0
  },
  "metadata": {
    "campaign_id": "spring_cleanup_2026",
    "internal_batch_id": "batch_42"
  }
}

results_url живёт 7 дней. Скачивайте файл и кладите в своё хранилище сразу — мы не считаем себя долгосрочным архивом.

Ретраи доставки webhook: 5 попыток за 24 часа по схеме 1m, 5m, 30m, 2h, 6h. Если ваш приёмник возвращает 2xx — доставка считается успешной. Любой не-2xx ответ — ретрай.

Если webhook поднять негде — polling

curl -H "Authorization: Bearer ${TOKEN}" \
  https://api.checkmaxapp.com/v1/jobs/job_8x4kpqz2nm

Рекомендованный интервал — 30 секунд. Чаще — 429.

Webhook и HMAC-подпись

Подпись X-MaxChecker-Signature — HMAC-SHA256 от сырого тела запроса с вашим webhook-секретом, согласно RFC 2104. Формат: sha256=<hex>.

Дополнительно сервер шлёт X-MaxChecker-Timestamp (Unix epoch секунды) — храните окно ±5 минут для защиты от replay-атак.

Проверка на Python

import hmac
import hashlib
import time
from flask import Flask, request, abort

app = Flask(__name__)
WEBHOOK_SECRET = os.environ["MAXCHECKER_WEBHOOK_SECRET"].encode()
TIMESTAMP_TOLERANCE_SECONDS = 300  # ±5 min


def verify_signature(raw_body: bytes, signature_header: str, timestamp_header: str) -> bool:
    # 1) Защита от replay: timestamp должен быть в окне ±5 минут
    try:
        ts = int(timestamp_header)
    except (TypeError, ValueError):
        return False
    if abs(time.time() - ts) > TIMESTAMP_TOLERANCE_SECONDS:
        return False

    # 2) Считаем ожидаемую подпись от <timestamp>.<body>
    signed_payload = f"{ts}.".encode() + raw_body
    expected = hmac.new(WEBHOOK_SECRET, signed_payload, hashlib.sha256).hexdigest()
    received = signature_header.removeprefix("sha256=")

    # 3) Constant-time сравнение
    return hmac.compare_digest(expected, received)


@app.post("/maxcheck/webhook")
def webhook():
    raw_body = request.get_data()
    if not verify_signature(
        raw_body,
        request.headers.get("X-MaxChecker-Signature", ""),
        request.headers.get("X-MaxChecker-Timestamp", ""),
    ):
        abort(401)

    payload = request.get_json()
    # Обработка: скачать results_url, обновить вашу БД
    process_batch_result(payload)

    # 2xx обязателен — иначе мы будем ретраить
    return "", 204

Критически важно использовать hmac.compare_digest, а не ==: обычное сравнение строк уязвимо к timing-атакам, через которые атакующий может подобрать подпись по байтам.

Проверка на Node.js

import crypto from 'node:crypto';
import express from 'express';

const app = express();
const WEBHOOK_SECRET = process.env.MAXCHECKER_WEBHOOK_SECRET;
const TIMESTAMP_TOLERANCE_SECONDS = 300;

// КРИТИЧНО: нужен raw body, не parsed JSON
app.use('/maxcheck/webhook', express.raw({ type: 'application/json' }));

function verifySignature(rawBody, signatureHeader, timestampHeader) {
  const ts = Number(timestampHeader);
  if (!Number.isFinite(ts)) return false;
  if (Math.abs(Date.now() / 1000 - ts) > TIMESTAMP_TOLERANCE_SECONDS) return false;

  const signedPayload = Buffer.concat([
    Buffer.from(`${ts}.`),
    rawBody,
  ]);
  const expected = crypto
    .createHmac('sha256', WEBHOOK_SECRET)
    .update(signedPayload)
    .digest('hex');
  const received = (signatureHeader || '').replace(/^sha256=/, '');

  const a = Buffer.from(expected, 'hex');
  const b = Buffer.from(received, 'hex');
  if (a.length !== b.length) return false;
  return crypto.timingSafeEqual(a, b);
}

app.post('/maxcheck/webhook', (req, res) => {
  const ok = verifySignature(
    req.body,
    req.get('X-MaxChecker-Signature'),
    req.get('X-MaxChecker-Timestamp'),
  );
  if (!ok) return res.status(401).end();

  const payload = JSON.parse(req.body.toString('utf-8'));
  // ...handle payload
  res.status(204).end();
});

app.listen(3000);

В Express важно использовать express.raw(), а не express.json() — HMAC считается от сырых байт, а парсер JSON может изменить представление (пробелы, порядок ключей), что сломает проверку.

Idempotency-Key и безопасные ретраи

RFC 9110 §9.2.2 определяет идемпотентность как «эффект на сервере от N идентичных вызовов идентичен одному вызову». Из коробки POST идемпотентным не является — Idempotency-Key это поведение добавляет.

Когда использовать. Везде, где сетевая ошибка после отправки запроса не позволяет понять, дошёл ли запрос до сервера. Особенно критично для batch'ей на тысячи номеров — там стоимость двойного списания заметная.

Как формировать ключ. UUID v4 на каждый бизнес-вызов, не переиспользовать для семантически разных запросов. Пример:

import uuid

idem_key = str(uuid.uuid4())

# Первая попытка
try:
    result = check_phone("+79161234567", idempotency_key=idem_key)
except TimeoutError:
    # Сеть упала — не знаем, дошёл ли запрос
    # Безопасный ретрай: тот же ключ → или новый ответ, или кэш
    result = check_phone("+79161234567", idempotency_key=idem_key)

Кэш живёт 24 часа от первого успешного 2xx. После — следующий вызов с тем же ключом считается новым.

Лимиты по умолчанию

EndpointЛимитЗаголовки в ответе
POST /v1/check-account100 req/minX-RateLimit-Remaining, X-RateLimit-Reset
POST /v1/check-account/batch10 batch/hourте же
Batch size≤ 10 000 номеров
GET /v1/jobs/{id}60 req/minте же
Webhook delivery retries5 за 24 часа
Idempotency-Key cache TTL24 часа
Max request body5 MB
Max concurrent batch jobs per account20

Это базовый профиль. При выдаче ключа лимиты корректируются под ожидаемый объём — нет смысла держать 100 req/min, если клиент делает 2 000 в минуту регулярно, или, наоборот, держать высокий потолок при эпизодической нагрузке. Запросить пересмотр можно в любой момент через /support — обычно меняем в течение часа.

Коды ошибок

Все ошибки возвращаются с JSON-телом:

{
  "error": "rate_limit_exceeded",
  "message": "100 req/min exceeded; retry after 23 seconds",
  "retry_after_seconds": 23,
  "request_id": "req_x9k2hf4n8p"
}
HTTPerrorЧто значитСтратегия
400invalid_phone_formatНомер не в E.164 (нет +, есть пробелы)Нормализовать и переотправить
400malformed_jsonТело не JSONПочинить формат
401invalid_tokenBearer токен не распознанПроверить env var, ротировать
402insufficient_balanceНе хватает средств для следующего hit'аПополнить через /pricing
422unknown_numberНевалидный номер (служебный диапазон, неактивный код)Не ретраить, фильтровать на входе
422country_not_supportedТолько RU поддерживаетсяНе ретраить
429rate_limit_exceededПревышен rate-limitЖдать retry_after_seconds
500internal_errorСерверная ошибкаRetry с exp backoff (1, 2, 4, 8 с)
502upstream_unavailableВременная недоступность бэкендаRetry через 10-30 с
503maintenanceЗапланированная профилактикаRetry через Retry-After
401invalid_signatureНа webhook: HMAC не сошёлсяПроверить секрет, raw body

Главное правило: ретраить только 429 и 5xx. На 4xx (кроме 429) ретрай не поможет — это ошибка клиента, нужно чинить запрос.

Тарифные тиры в API

Тариф тот же, что и в боте — pay-per-hit от $0.005 за положительный ответ. Отрицательные (registered=false) бесплатно. Скидочные тиры применяются по сумме депозита:

ДепозитСкидкаЭффективная цена/hit
$10-$1990%$0.005
$200-$49910%$0.0045
$500-$99920%$0.004
$1 000-$1 99930%$0.0035
$2 000+40%$0.003

Минимальный депозит — $10. Для commit-моделей с ежемесячным предоплатным объёмом обсуждаются индивидуальные условия — это типично для команд антифрода с предсказуемой нагрузкой 200k+ hits/мес. Полная сетка — на странице тарифов.

Типичные интеграционные сценарии

По нашей статистике, 80% индивидуальных API-доступов используются под одну из четырёх задач — даём готовые сниппеты и webhook-шаблоны под каждый сценарий при выдаче ключа.

1. Антифрод на регистрации. Синхронный вызов /v1/check-account из формы регистрации, p95 ≤ 500 мс. Решение «пускать/в ручную верификацию/отказать» на основе registered, last_seen, наличия firstName. Подробнее — Антифрод по номеру.

2. Обогащение CRM в реальном времени. Webhook от CRM → один API-вызов → запись в карточку лида. Стандартно настраивается на amoCRM/Bitrix24 за час через webhook-конструктор. См. use-case по маркетингу.

3. Чистка маркетинговой базы. Batch на 10-100k номеров раз в неделю перед рассылкой. Webhook-приёмник кладёт CSV в S3/Yandex Object Storage, ETL обновляет основную базу.

4. White-label-зеркала. Реселлеры выставляют наш API под своим брендом и тарифицируют по своему прайс-листу. См. white-label.

Кросс-ссылка на сиблинг-материал с расширенными примерами на async Python и сравнением с green-api: CheckAccount REST API для MAX.

Что не даёт API

Чтобы не перегружать ожидания:

  • Не возвращаем переписку, аватарки и приватные настройки — только публичные поля профиля MAX.
  • Не поддерживаем поиск по странам кроме RU — это сознательная специализация, не отсутствие технической возможности.
  • Не поддерживаем другие мессенджеры — для WhatsApp есть green-api, для Telegram — отдельные решения; мы не конкурируем за «универсальный чекер».
  • Не предоставляем готовые базы номеров — мы инструмент проверки, а не источник данных.
  • Self-serve панели регистрации намеренно нет: см. раздел «Как мы выдаём ключ» выше.

E-E-A-T: кто стоит за API

Команда max-checker-team поддерживает REST API для интеграций B2B-клиентов с 2024 года. За это время через API прошло более 14 млн проверок в основном четырёх вертикалях: МФО и онлайн-кредитование, e-commerce антифрод, маркетинговые рассылки, B2B-обогащение CRM. Базовая инфраструктура — Python (FastAPI) + PostgreSQL + Redis

  • Cloudflare Workers на edge, p95 латентность одиночного запроса держится в районе 280 мс.

Контакт для интеграционных вопросов — /support в боте, ответ в рабочее время в течение нескольких часов.

Полезные материалы

Внешние спецификации, на которые ссылается API:

Частые вопросы

01.Как получить API-ключ к чекеру MAX?

Доступ выдаётся индивидуально через /support в Telegram-боте. Опишите кейс (объём, платформа, латентность, нужен ли SLA) — команда вернётся за 1-2 рабочих дня с ключом, секретом для HMAC-подписи webhook'а, выделенным rate-limit и индивидуальными условиями по объёмам. Self-serve панели регистрации намеренно нет: индивидуальный подбор тарифа экономит клиентам 20-40% на больших объёмах.

02.Какие лимиты по умолчанию у REST API?

Базовый профиль: 100 одиночных запросов в минуту, batch до 10 000 номеров за один вызов, до 10 batch-запросов в час. Webhook доставки с экспоненциальными ретраями (5 попыток за 24 часа). Лимиты подбираются под объём клиента — для нагрузок от 1 млн проверок в месяц повышаются индивидуально.

03.Как проверить подпись X-MaxChecker-Signature на webhook?

Подпись — HMAC-SHA256 от сырого тела запроса (request body) с вашим webhook-секретом. Сравнивайте через constant-time функцию (hmac.compare_digest в Python, crypto.timingSafeEqual в Node.js), чтобы избежать timing-атак. Подробный пример с защитой от replay-атак через timestamp window — в разделе «Webhook и HMAC-подпись» ниже.

04.Что такое Idempotency-Key и зачем он нужен?

Idempotency-Key — UUID-заголовок, который позволяет безопасно повторить запрос после сетевой ошибки или таймаута без риска двойного списания. Сервер хранит результат первого вызова с этим ключом 24 часа и при повторе возвращает кэшированный ответ. Поведение соответствует RFC 9110 §9.2.2. Особенно критично для batch-запросов на тысячи номеров.

05.Какие коды ошибок возвращает API?

Стандартные HTTP-коды (400, 401, 402, 422, 429, 500, 503) + machine-readable error code в JSON-теле: rate_limit_exceeded (с retry_after_seconds), unknown_number (номер не валиден), country_not_supported (не RU), insufficient_balance, invalid_signature (на webhook), internal_error. Полная таблица с рекомендованными retry-стратегиями — в разделе «Коды ошибок».

06.Сколько стоит проверка через API?

Базовый тариф — от $0.005 за положительный hit (registered=true). Отрицательные ответы (registered=false) не тарифицируются. Скидочные тиры: 10% от $200, 20% от $500, 30% от $1 000, 40% от $2 000 — те же, что и в боте. Минимальный депозит — $10. Конкретный коммит обсуждается с поддержкой при выдаче доступа.

07.Какие платформы интеграции вы поддерживаете из коробки?

amoCRM, Bitrix24, HubSpot, Make, Zapier, n8n — есть готовые примеры запросов и webhook-получателей. Для кастомных бэкендов даём cURL/Python/Node.js-сниппеты под конкретный сценарий: антифрод на регистрации, обогащение CRM в реальном времени, чистка маркетинговой базы перед рассылкой, white-label-зеркала.

08.Какое SLA на API?

Базовый профиль — best effort: историческая аптайм 99.6%, p95 латентность одиночного запроса 280 мс. Для команд с критичной зависимостью оформляется отдельный SLA-договор: 99.9% месячная доступность, p95 ≤ 500 мс, кредиты за нарушение. SLA включается опционально при выдаче доступа и обсуждается под конкретный кейс.

ПоделитьсяTelegramX

Читать дальше

Похожие материалы.