Как обращаться.
Ключ передаётся в заголовке
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 (регистр не важен) |
| Ответ | Описание |
200 | PDF |
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 (регистр не важен) |
| Ответ | Описание |
200 | PNG |
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`) |
409 | sha256 из формы не совпал с принятыми байтами (`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) — для защиты от повторной обработки |