eFix API v2 v2.1.0

Программная фиксация веб-страниц: протокол PDF с подписью ТОО «Еавтор» (ЭЦП НУЦ РК), метками времени и снимком страницы. Ключ — в заголовке X-API-Key; ключ выпускается в кабинете, раздел «API и интеграции». Ответы — JSON в UTF-8; даты — ISO 8601 (UTC). На главную

Как обращаться. Ключ передаётся в заголовке X-API-Key. Базовый адрес: https://efix.kz/api/v2. Машинная спецификация — openapi.json (OpenAPI 3.1.0).

Ключи и праваМетодыВебхукиОшибки и ограниченияСхемы

Ключи и права

Ключ выпускается в кабинете: «API и интеграции». Доступ к API включён в тарифах «Профессиональный» и «Корпоративный».

КлючЧейПрава
Основной личный (64 hex-знака)ПользователяВсе права API, которые даёт его роль
Именованный личный, efk_…ПользователяОтмеченные при выпуске
Ключ организации, efk_…Организации; выпускает её администраторОтмеченные при выпуске; действует, пока выпустивший состоит в организации
ПравоЧто даёт
protocol.createЗапуск фиксаций (POST /capture)
protocol.viewСостояние, список, PDF, снимок, видео — свои протоколы и протоколы организации по роли
usage.viewУчёт вызовов (GET /usage)

Право ключа никогда не шире текущей роли владельца в организации: понизили роль — ключ сразу теряет лишнее. После ротации прежний ключ работает ещё 24 часа; отзыв действует сразу. Протоколы, запущенные ключом организации, принадлежат организации; фиксация списывается с владельца ключа. Каждый вызов записывается в журнал — он виден в кабинете и даёт учёт использования.

Методы

post https://efix.kz/api/v2/capture

Запустить фиксацию страницы

Право ключа: protocol.create. Списывает одну фиксацию (подписка → бесплатные → баланс) и ставит задачу; протокол готов через 1–4 минуты. Состояние — по status_url или вебхуком protocol.completed / protocol.failed.

curl -X POST https://efix.kz/api/v2/capture \
  -H 'X-API-Key: efk_…' \
  -H 'Content-Type: application/json' \
  -d '{"url": "https://netology.ru/"}'
Поле запросаТипОписание
device_type string (desktop / mobile / tablet) Тип устройства; неизвестное значение — desktop по умолчанию: desktop
include_video boolean Записать видео (30 с). Только если тариф включает видео; иначе флаг молча игнорируется по умолчанию: False
source_type string Тип источника для проверки площадки (web, social). Закрытые площадки (Facebook, Instagram…) сервер снять не может — ответ 422 с альтернативой по умолчанию: web
url обязательно string Адрес страницы; без схемы подставляется https://. Внутренние адреса (localhost, частные сети) запрещены.
ОтветОписание
201Фиксация запущена
400Не JSON (`invalid_json`), нет url (`missing_url`), длиннее 2048 (`url_too_long`), не адрес (`invalid_url`), внутренний адрес (`blocked_url`)
401Нет ключа (`missing_api_key`), ключ неизвестен/отозван (`invalid_api_key`) или ключ организации больше не действует (`key_inactive`)
402Нет доступных фиксаций
403Тариф без API (`api_access_denied`) или у ключа/роли нет права метода (`forbidden`)
422Площадку сервер не снимает
429Больше 60 запросов в минуту на ключ (`rate_limit_exceeded`, поле `retry_after`)
500Внутренняя ошибка (`internal_error`)
503Очередь недоступна (`queue_unavailable`); списанная фиксация возвращена
get https://efix.kz/api/v2/capture/{protocol_id}

Состояние фиксации

Право ключа: protocol.view. Видны свои протоколы и протоколы организации, если роль владельца ключа это позволяет.

curl https://efix.kz/api/v2/capture/EF-20261012-A1B2C3D4 -H 'X-API-Key: efk_…'
ПараметрГдеТипОписание
protocol_id обязателен path string Номер протокола, например EF-20261012-A1B2C3D4 (регистр не важен)
ОтветОписание
200Состояние
401Нет ключа (`missing_api_key`), ключ неизвестен/отозван (`invalid_api_key`) или ключ организации больше не действует (`key_inactive`)
403Тариф без API (`api_access_denied`) или у ключа/роли нет права метода (`forbidden`)
404Протокол не найден или не виден этому ключу (`not_found`)
429Больше 60 запросов в минуту на ключ (`rate_limit_exceeded`, поле `retry_after`)
get https://efix.kz/api/v2/capture/{protocol_id}/pdf

Скачать PDF-протокол

Право ключа: protocol.view. Только готовый (completed) протокол.

curl -o protocol.pdf https://efix.kz/api/v2/capture/EF-20261012-A1B2C3D4/pdf -H 'X-API-Key: efk_…'
ПараметрГдеТипОписание
protocol_id обязателен path string Номер протокола, например EF-20261012-A1B2C3D4 (регистр не важен)
ОтветОписание
200PDF
401Нет ключа (`missing_api_key`), ключ неизвестен/отозван (`invalid_api_key`) или ключ организации больше не действует (`key_inactive`)
403Тариф без API (`api_access_denied`) или у ключа/роли нет права метода (`forbidden`)
404Протокол не найден/не готов (`not_found`) или нет файла (`file_not_found`)
429Больше 60 запросов в минуту на ключ (`rate_limit_exceeded`, поле `retry_after`)
get https://efix.kz/api/v2/capture/{protocol_id}/screenshot

Скачать снимок страницы

Право ключа: protocol.view. Только готовый протокол.

curl -o page.png https://efix.kz/api/v2/capture/EF-20261012-A1B2C3D4/screenshot -H 'X-API-Key: efk_…'
ПараметрГдеТипОписание
protocol_id обязателен path string Номер протокола, например EF-20261012-A1B2C3D4 (регистр не важен)
ОтветОписание
200PNG
401Нет ключа (`missing_api_key`), ключ неизвестен/отозван (`invalid_api_key`) или ключ организации больше не действует (`key_inactive`)
403Тариф без API (`api_access_denied`) или у ключа/роли нет права метода (`forbidden`)
404Протокол не найден/не готов (`not_found`) или нет файла (`file_not_found`)
429Больше 60 запросов в минуту на ключ (`rate_limit_exceeded`, поле `retry_after`)
get https://efix.kz/api/v2/capture/{protocol_id}/video

Скачать видеозапись

Право ключа: protocol.view. Есть, только если фиксация запускалась с include_video и тариф включает видео.

curl -o video.mp4 https://efix.kz/api/v2/capture/EF-20261012-A1B2C3D4/video -H 'X-API-Key: efk_…'
ПараметрГдеТипОписание
protocol_id обязателен path string Номер протокола, например EF-20261012-A1B2C3D4 (регистр не важен)
ОтветОписание
200Видео
401Нет ключа (`missing_api_key`), ключ неизвестен/отозван (`invalid_api_key`) или ключ организации больше не действует (`key_inactive`)
403Тариф без API (`api_access_denied`) или у ключа/роли нет права метода (`forbidden`)
404Протокол не найден (`not_found`) или видео нет (`video_not_found`)
429Больше 60 запросов в минуту на ключ (`rate_limit_exceeded`, поле `retry_after`)
get https://efix.kz/api/v2/plans

Тарифные планы (без ключа)

curl https://efix.kz/api/v2/plans
ОтветОписание
200Действующие планы
get https://efix.kz/api/v2/protocols

Список протоколов

Право ключа: protocol.view. Свои протоколы и протоколы организации по роли; новые сверху.

curl 'https://efix.kz/api/v2/protocols?status=completed&per_page=50' -H 'X-API-Key: efk_…'
ПараметрГдеТипОписание
page query integer Страница, с 1
per_page query integer На странице, не больше 100
status query string Отбор по состоянию
source_type query string Отбор по типу: web, social, email, messenger, video, mobile…
ОтветОписание
200Страница списка
401Нет ключа (`missing_api_key`), ключ неизвестен/отозван (`invalid_api_key`) или ключ организации больше не действует (`key_inactive`)
403Тариф без API (`api_access_denied`) или у ключа/роли нет права метода (`forbidden`)
429Больше 60 запросов в минуту на ключ (`rate_limit_exceeded`, поле `retry_after`)
post https://efix.kz/api/v2/stamp

eFix Метка: метка времени на файл или хеш

Право ключа: protocol.create. Списывает одну фиксацию. Сервер получает квитанцию RFC 3161 службы НУЦ РК на SHA-256 объекта, OpenTimestamps и запись в реестре eFix (позиция печатается в протоколе), затем PDF «Протокол метки времени» с ЭЦП. Метка удостоверяет существование данных с этим хешем не позднее момента квитанции — не содержание и не авторство. Повтор того же объекта за 15 минут — прежняя метка (200, duplicate).

curl -X POST https://efix.kz/api/v2/stamp \
  -H 'X-API-Key: efk_…' \
  -H 'Content-Type: application/json' \
  -d '{"sha256": "<64 hex>", "filename": "договор.pdf"}'
# файл: curl -X POST https://efix.kz/api/v2/stamp -H 'X-API-Key: efk_…' -F file=@договор.pdf
Поле запросаТипОписание
filename string Имя файла со слов клиента (печатается как заявленное)
note string Пояснение заявителя
sha256 обязательно string SHA-256 объекта; файл на сервер не передаётся
size integer Размер со слов клиента, байт
ОтветОписание
200Повтор: прежняя метка
201Метка запущена
400Нет файла и sha256 (`FILE_OR_SHA256_REQUIRED`), неверный sha256 (`SHA256_REQUIRED`, `BAD_SHA256`), size (`BAD_SIZE`), пустой файл (`EMPTY_FILE`), не JSON (`INVALID_JSON`)
401Нет ключа (`missing_api_key`), ключ неизвестен/отозван (`invalid_api_key`) или ключ организации больше не действует (`key_inactive`)
402Нет доступных фиксаций
403Тариф без API (`api_access_denied`) или у ключа/роли нет права метода (`forbidden`)
409sha256 из формы не совпал с принятыми байтами (`HASH_MISMATCH`)
413Файл больше 512 МБ (`FILE_TOO_LARGE`)
429Больше 60 запросов в минуту на ключ (`rate_limit_exceeded`, поле `retry_after`)
500Внутренняя ошибка (`internal_error`)
503Очередь недоступна (`QUEUE_UNAVAILABLE`); фиксация возвращена
get https://efix.kz/api/v2/stamp/{protocol_id}

Состояние метки

Право ключа: protocol.view. PDF — /capture/{protocol_id}/pdf.

curl https://efix.kz/api/v2/stamp/EF-20261015-A1B2C3D4 -H 'X-API-Key: efk_…'
ПараметрГдеТипОписание
protocol_id обязателен path string Номер протокола, например EF-20261012-A1B2C3D4 (регистр не важен)
ОтветОписание
200Состояние
401Нет ключа (`missing_api_key`), ключ неизвестен/отозван (`invalid_api_key`) или ключ организации больше не действует (`key_inactive`)
403Тариф без API (`api_access_denied`) или у ключа/роли нет права метода (`forbidden`)
404Протокол не найден или не виден этому ключу (`not_found`)
429Больше 60 запросов в минуту на ключ (`rate_limit_exceeded`, поле `retry_after`)
get https://efix.kz/api/v2/usage

Учёт вызовов и фиксаций через API

Право ключа: usage.view. Ключ организации (или ключ участника с ролью «Проверяющий»/«Администратор») видит учёт всей организации, остальные — свой. Период по умолчанию — текущий месяц (UTC). Учёт справочный: оплата по использованию не списывается.

curl 'https://efix.kz/api/v2/usage?from=2026-10-01&to=2026-10-31' -H 'X-API-Key: efk_…'
ПараметрГдеТипОписание
from query string Начало периода, ГГГГ-ММ-ДД (включительно)
to query string Конец периода, ГГГГ-ММ-ДД (включительно)
ОтветОписание
200Сводка
401Нет ключа (`missing_api_key`), ключ неизвестен/отозван (`invalid_api_key`) или ключ организации больше не действует (`key_inactive`)
403Тариф без API (`api_access_denied`) или у ключа/роли нет права метода (`forbidden`)
429Больше 60 запросов в минуту на ключ (`rate_limit_exceeded`, поле `retry_after`)
get https://efix.kz/api/v2/user

Владелец ключа, тариф и сам ключ

Без отдельного права: любой действующий ключ.

curl https://efix.kz/api/v2/user -H 'X-API-Key: efk_…'
ОтветОписание
200Сведения
401Нет ключа (`missing_api_key`), ключ неизвестен/отозван (`invalid_api_key`) или ключ организации больше не действует (`key_inactive`)
403Тариф без API (`api_access_denied`) или у ключа/роли нет права метода (`forbidden`)
429Больше 60 запросов в минуту на ключ (`rate_limit_exceeded`, поле `retry_after`)
get https://efix.kz/api/v2/verify/{protocol_id}

Проверка подлинности протокола (без ключа)

То же, что страница проверки по QR-коду, в машинном виде.

curl https://efix.kz/api/v2/verify/EF-20261012-A1B2C3D4
ПараметрГдеТипОписание
protocol_id обязателен path string Номер протокола, например EF-20261012-A1B2C3D4 (регистр не важен)
ОтветОписание
200Результат проверки
404Протокол не найден или не готов (valid=false, `not_found`)

Вебхуки

Включаются администратором eFix. Пока вебхуки выключены, подписку завести нельзя, а состояние протокола опрашивается по status_url. Подписка заводится в кабинете («API и интеграции»): адрес https://, события и секрет подписи (показывается один раз). У организации подписки общие, их ведёт администратор организации.

СобытиеКогда
order.status_changedЗаказ «По заказу» сменил статус
protocol.completedПротокол готов
protocol.failedФиксация завершилась отказом
pingКнопка «Проверить» в кабинете

Запрос

POST /ваш/адрес HTTP/1.1
Content-Type: application/json; charset=utf-8
User-Agent: eFix-Webhooks/1.0
X-EFix-Event: protocol.completed
X-EFix-Delivery: 3f0c…
X-EFix-Signature: t=1791800000,v1=5d41402abc4b2a76b9719d911017c592…

{"id": "3f0c…", "event": "protocol.completed", "created_at": "2026-10-12T09:30:00Z",
 "data": {"protocol_id": "EF-20261012-A1B2C3D4", "status": "completed",
          "url": "https://netology.ru/", "domain": "netology.ru", "sha256": "…",
          "links": {"status": "https://efix.kz/api/v2/capture/EF-20261012-A1B2C3D4",
                    "verify": "…/verify/EF-20261012-A1B2C3D4"}}}

Проверка подписи

Подпись — HMAC-SHA256 секретом подписки от строки <t>.<тело запроса как пришло, байт в байт>. Отклоняйте запрос, если подпись не совпала или t старше 5 минут; повторную доставку того же события узнавайте по id.

# Python
import hashlib, hmac, time

def подпись_верна(секрет: str, тело: bytes, заголовок: str) -> bool:
    части = dict(ч.split("=", 1) for ч in заголовок.split(","))
    t = int(части["t"])
    if abs(time.time() - t) > 300:
        return False
    ожидаемо = hmac.new(секрет.encode(), f"{t}.".encode() + тело, hashlib.sha256).hexdigest()
    return hmac.compare_digest(ожидаемо, части.get("v1", ""))
// Node.js
const crypto = require("crypto");
function signatureOk(secret, rawBody, header) {
  const p = Object.fromEntries(header.split(",").map(x => x.split("=")));
  if (Math.abs(Date.now() / 1000 - Number(p.t)) > 300) return false;
  const want = crypto.createHmac("sha256", secret).update(`${p.t}.`).update(rawBody).digest("hex");
  return want.length === (p.v1 || "").length &&
         crypto.timingSafeEqual(Buffer.from(want), Buffer.from(p.v1));
}

Доставка и повторы

Ответ 2xx в течение 10 секунд — доставлено. Иначе повтор через 1 мин, 5 мин, 30 мин, 2 ч и 6 ч (всего 6 попыток), затем «не доставлено»; журнал доставок виден в кабинете. Редиректы не выполняются. После 10 неудач подряд подписка выключается — включите её снова в кабинете.

Какие адреса принимаются

Только https:// на портах 443 и 8443, без логина и пароля в адресе. Имя должно вести только на публичные адреса: локальные (127.0.0.0/8, ::1), частные (10/8, 172.16/12, 192.168/16, fc00::/7), link-local и служба метаданных (169.254.0.0/16, fe80::/10), служебные и multicast — запрещены, в том числе внутри IPv6 (::ffff:…, 6to4, NAT64). Адрес проверяется при заведении подписки и перед каждой доставкой, и соединение открывается на проверенный адрес: смена DNS между проверкой и запросом не помогает.

Ошибки и ограничения

Ошибка — JSON {"error": "код", "message": "пояснение"}; код стабилен, текст может меняться. Не больше 60 запросов в минуту на ключ: заголовки X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset; при превышении — 429 и Retry-After.

Схемы

CaptureRequest
ПолеТипОписание
device_type string Тип устройства; неизвестное значение — desktop
include_video boolean Записать видео (30 с). Только если тариф включает видео; иначе флаг молча игнорируется
source_type string Тип источника для проверки площадки (web, social). Закрытые площадки (Facebook, Instagram…) сервер снять не может — ответ 422 с альтернативой
url string Адрес страницы; без схемы подставляется https://. Внутренние адреса (localhost, частные сети) запрещены.
CaptureResponse
ПолеТипОписание
balance_remaining integer Остаток фиксаций на балансе
protocol_id string
source string Откуда списана фиксация
status string
status_url string
success boolean
warnings array Есть, если прислан неподдерживаемый callback_url
Error
ПолеТипОписание
client_sha256 string Хеш из запроса (409 метки)
docs string Ссылка на документацию (401 без ключа)
error string Машинный код ошибки
message string Пояснение на русском
permission string Недостающее право (403 forbidden)
protocol_id string Номер несостоявшегося протокола (503)
retry_after integer Через сколько секунд повторить (429)
server_sha256 string Хеш принятых байт (409 метки)
success boolean false (503)
valid boolean false (404 проверки)
InsufficientBalance
ПолеТипОписание
access_url string Куда подать заявку на фиксации
balance integer
error string
message string
PlatformVerdict
ПолеТипОписание
actions array
allowed boolean
alternative string
error string
message string
platform string
platform_name string
ProtocolList
ПолеТипОписание
pagination object
protocols array
ProtocolListItem
ПолеТипОписание
completed_at string | null
created_at string | null
device_type string
domain string
has_video boolean
protocol_id string
sha256 string | null
signed boolean | null
source_type string
status string
url string
ProtocolStatus
ПолеТипОписание
blockchain object Только для completed: метка OpenTimestamps
completed_at string | null
created_at string | null
device_type string
domain string
error string Только для error: причина отказа
expires_at string | null До какой даты хранится протокол
files object Только для completed
processing_time_ms integer | null
protocol_id string
sha256 string Только для completed: SHA-256 PDF
sha512 string Только для completed
signed boolean Только для completed: PDF подписан ЭЦП
source_type string
status string processing — идёт фиксация; completed — протокол готов; error — отказ (причина в поле error)
url string
video_info object Только для completed
StampRequest
ПолеТипОписание
filename string Имя файла со слов клиента (печатается как заявленное)
note string Пояснение заявителя
sha256 string SHA-256 объекта; файл на сервер не передаётся
size integer Размер со слов клиента, байт
StampStatus
ПолеТипОписание
balance_remaining integer
duplicate boolean Повтор того же объекта за 15 минут: прежняя метка, вторая фиксация не списана
error_message string | null
has_media boolean
has_package boolean
has_pdf boolean
ledger object | null key (STM-…), sealed, position, root_id, root_hash — реестр eFix
message string
object object kind (file|hash), sha256, sha3_256, sha512 (только у файла), filename, size, mime, note
ots object | null status, calendar_url (OpenTimestamps)
price object slug stamp, tenge (null — не назначена), charge: capture — списывается одна фиксация
project_id integer | null
protocol_id string
received_at string Момент приёма сервером, UTC
refunded boolean
signed boolean
source_type string
status string
status_url string
success boolean
tsa object | null gen_time, tsa_url, gov_kz, serial — квитанция RFC 3161 на SHA-256 объекта
verify_url string | null
Usage
ПолеТипОписание
billing string
by_key array
calls integer Вызовов API за период
captures integer Запущенных через API фиксаций
errors integer Вызовов с кодом 4xx/5xx
period object
scope string
UserInfo
ПолеТипОписание
api_key object
balance integer
email string
name string | null
organization object | null
plan object
total_protocols integer Протоколов владельца ключа
VerifyResult
ПолеТипОписание
blockchain object
capture_timestamp string | null
domain string
expires_at string | null
protocol_id string
revoked boolean
sha256 string | null
signed boolean | null
source_type string
superseded_by string | null
valid boolean false — протокол отозван (см. superseded_by)
verify_url string
WebhookEvent
ПолеТипОписание
created_at string
data object Для protocol.* — protocol_id, status, url, domain, source_type, sha256, created_at, completed_at, error (для failed), links.status, links.verify; для order.status_changed — order_number, status, previous_status, due_at, completed_at, links.cabinet
event string
id string Номер события (тот же в X-EFix-Delivery) — для защиты от повторной обработки