API-справочник
Базовый URL
https://ec-api.cloud-native.kz/openapi/v1
Аутентификация
Аутентификация выполняется на уровне организации с помощью HMAC-ключа, выданного во вкладке API Keys консоли CNS. Каждый запрос обязан содержать четыре заголовка:
| Заголовок | Описание |
|---|---|
X-App-Id |
Публичный идентификатор ключа. Начинается с cns_ec_… |
X-Timestamp |
Текущее время Unix в секундах. Отклонение более 5 минут — отказ. |
X-Nonce |
Уникальная случайная строка (не менее 16 символов). Повторы блокируются на 10 минут. |
X-Signature |
Доказательство владения секретом. |
Подпись (X-Signature) вычисляется по канонической строке:
METHOD\nPATH\nCANONICAL_QUERY\nX-App-Id\nX-Timestamp\nX-Nonce\nsha256(body-hex)
Текущий режим (MVP): Можно передавать секрет напрямую в
X-Signature— шлюз проверяет его через Argon2. В фазе 2 будет включена полная схема HMAC-SHA256; ключи, выданные сейчас, продолжат работать.
Эндпоинты
| Метод | Путь | Описание |
|---|---|---|
POST |
/contracts |
Отправить договор на подпись. Идемпотентен по (org, foreignContractNo). |
GET |
/contracts/{requestId} |
Получить статус договора. Параметр ?fresh=true — принудительный опрос УЦ. |
POST |
/contracts/{requestId}/revoke |
Отозвать договор до завершения подписания. |
POST |
/contracts/{requestId}/sign-complete |
Зафиксировать подписание. Единственный путь к статусу SIGNED; запускает биллинг. |
POST /contracts
Отправить новый договор на подпись. Повторный запрос с тем же телом возвращает 200 с idempotent: true. Изменение тела при том же foreignContractNo возвращает ошибку 40901.
Запрос
curl -X POST "https://ec-api.cloud-native.kz/openapi/v1/contracts" \
-H "X-App-Id: cns_ec_XXXXXXXXXXXXXXXX" \
-H "X-Timestamp: $(date +%s)" \
-H "X-Nonce: $(uuidgen)" \
-H "X-Signature: <ваш секрет>" \
-H "Content-Type: application/json" \
-d '{
"foreignContractNo": "ORDER-2026-0517",
"contractTitle": "Договор о трансграничных поставках",
"contractFileUrl": "https://files.example.com/contracts/order-2026-0517.pdf",
"fileName": "order-2026-0517.pdf",
"fileSha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
"foreignSignUrl": "https://your-app.example.com/contracts/callback",
"domesticParty": {
"enterpriseName": "Shanghai Trading Co., Ltd",
"uniformCode": "91310000MA1234567X",
"legalName": "Wang Xiao",
"contactName": "Li Mei",
"contactMobile": "+8613800000000",
"contactEmail": "limei@shanghai-trading.example.com"
},
"foreignParty": {
"name": "Kazakh Logistics LLP",
"country": "KZ",
"registerNo": "180440017542"
},
"currency": "USD",
"amount": 12500.00,
"expireTime": "2026-06-30T23:59:59Z",
"notifyMobiles": ["+77001234567"],
"notifyEmails": ["aigerim@kazakh-logistics.example.com"]
}'
Поля запроса
Верхний уровень
| Поле | Тип | Обяз. | Описание |
|---|---|---|---|
foreignContractNo |
string | Да | Номер договора на стороне казахстанского партнёра. Ключ идемпотентности. |
contractTitle |
string | Да | Название договора для отображения. |
contractFileUrl |
string | Да | URL файла договора. CNS хранит только ссылку. |
fileName |
string | Нет | Имя файла для отображения. |
fileSha256 |
string | Нет | SHA-256 хеш файла для проверки целостности. |
foreignSignUrl |
string | Да | URL страницы подписания казахстанского УЦ. |
domesticParty |
object | Да | Данные китайской стороны (см. ниже). |
foreignParty |
object | Да | Данные казахстанской стороны (см. ниже). |
currency |
string | Нет | Код валюты, например USD. |
amount |
number | Нет | Сумма договора. |
expireTime |
string | Нет | Срок действия в ISO-8601 UTC. |
notifyMobiles |
string[] | Нет | Номера для SMS. Хотя бы одно из notifyMobiles/notifyEmails обязательно. |
notifyEmails |
string[] | Нет | Email для уведомлений. Хотя бы одно из notifyMobiles/notifyEmails обязательно. |
domesticParty — китайская сторона
| Поле | Тип | Обяз. | Описание |
|---|---|---|---|
enterpriseName |
string | Да | Название компании. |
uniformCode |
string | Да | Единый социальный кредитный код (USCC), 18 символов. |
legalName |
string | Нет | ФИО законного представителя. |
contactName |
string | Нет | ФИО контактного лица - подписанта. |
contactMobile |
string | Нет | Телефон контактного лица. |
contactEmail |
string | Нет | Email контактного лица. |
foreignParty — казахстанская сторона
| Поле | Тип | Обяз. | Описание |
|---|---|---|---|
name |
string | Да | Название организации. |
country |
string | Нет | Код страны, например KZ. |
registerNo |
string | Нет | БИН, 12 цифр. |
Ответ
HTTP/1.1 201 Created
Content-Type: application/json
{
"requestId": "8c1f7e3a-4d6b-4b1f-9a3a-9f0c2e1b1d77",
"foreignContractNo": "ORDER-2026-0517",
"foreignSignUrl": "https://animall-signature.jgsysj.com/sign/8c1f7e3a...",
"status": "PENDING",
"idempotent": false
}
| Поле | Описание |
|---|---|
requestId |
Уникальный ID договора в CNS. Используйте во всех последующих запросах. |
foreignSignUrl |
Ссылка на страницу подписания УЦ. |
status |
Сразу после создания — PENDING. |
idempotent |
true, если договор уже существовал и возвращён без изменений. |
GET /contracts/{requestId}
Получить текущий статус договора. По умолчанию — локально кэшированное состояние. Параметр ?fresh=true принудительно синхронизирует с УЦ; используйте редко — запросы лимитированы.
Запрос
curl "https://ec-api.cloud-native.kz/openapi/v1/contracts/8c1f7e3a-4d6b-4b1f-9a3a-9f0c2e1b1d77?fresh=true" \
-H "X-App-Id: cns_ec_XXXXXXXXXXXXXXXX" \
-H "X-Timestamp: $(date +%s)" \
-H "X-Nonce: $(uuidgen)" \
-H "X-Signature: <ваш секрет>"
Ответ
HTTP/1.1 200 OK
Content-Type: application/json
{
"requestId": "8c1f7e3a-4d6b-4b1f-9a3a-9f0c2e1b1d77",
"foreignContractNo": "ORDER-2026-0517",
"status": "SENT",
"canSign": true,
"blockReason": null,
"foreignSignUrl": "https://animall-signature.jgsysj.com/sign/8c1f7e3a...",
"signedFileUrl": null,
"signedAt": null,
"createdAt": "2026-05-17T09:42:11Z",
"updatedAt": "2026-05-17T09:43:02Z"
}
| Поле | Описание |
|---|---|
canSign |
true, если подписание ещё возможно. |
blockReason |
Причина блокировки, если canSign: false. |
signedFileUrl |
Заполняется после перехода в SIGNED. |
signedAt |
Временна́я метка подписания ISO-8601. Заполняется после SIGNED. |
POST /contracts/{requestId}/revoke
Отозвать договор, который ещё не подписан. После перехода в SIGNED отзыв невозможен.
Запрос
curl -X POST "https://ec-api.cloud-native.kz/openapi/v1/contracts/8c1f7e3a-4d6b-4b1f-9a3a-9f0c2e1b1d77/revoke" \
-H "X-App-Id: cns_ec_XXXXXXXXXXXXXXXX" \
-H "X-Timestamp: $(date +%s)" \
-H "X-Nonce: $(uuidgen)" \
-H "X-Signature: <ваш секрет>" \
-H "Content-Type: application/json" \
-d '{
"reason": "Клиент отменил заказ до подписания."
}'
Ответ
HTTP/1.1 200 OK
Content-Type: application/json
{
"requestId": "8c1f7e3a-4d6b-4b1f-9a3a-9f0c2e1b1d77",
"foreignContractNo": "ORDER-2026-0517",
"status": "REVOKED",
"canSign": false,
"blockReason": "revoked",
"foreignSignUrl": "https://animall-signature.jgsysj.com/sign/8c1f7e3a...",
"signedFileUrl": null,
"signedAt": null,
"createdAt": "2026-05-17T09:42:11Z",
"updatedAt": "2026-05-17T10:02:55Z"
}
POST /contracts/{requestId}/sign-complete
Зафиксировать, что договор подписан на стороне казахстанского партнёра. Это единственный вызов, который переводит договор в SIGNED и запускает биллинг. Все поля необязательны; рекомендуется передавать как минимум signedFileUrl и signerName.
Запрос
curl -X POST "https://ec-api.cloud-native.kz/openapi/v1/contracts/8c1f7e3a-4d6b-4b1f-9a3a-9f0c2e1b1d77/sign-complete" \
-H "X-App-Id: cns_ec_XXXXXXXXXXXXXXXX" \
-H "X-Timestamp: $(date +%s)" \
-H "X-Nonce: $(uuidgen)" \
-H "X-Signature: <ваш секрет>" \
-H "Content-Type: application/json" \
-d '{
"signerName": "Айгерим Нурланова",
"signerIdcard": "880101300123",
"signedFileUrl": "https://files.example.com/contracts/order-2026-0517.signed.pdf",
"evidenceHash": "d2c39b1f8c5f0e3a1b7d6e2c8f4a9b1d5e7c3f9a2b6e8d0c1f3a5b7e9c2d4f6a",
"tsaSerial": "TSA-2026-9F0C2E1B",
"chainTxId": "0xab12cd34ef56..."
}'
Поля запроса
| Поле | Тип | Обяз. | Описание |
|---|---|---|---|
signerName |
string | Нет | ФИО подписанта. |
signerIdcard |
string | Нет | Номер удостоверения личности подписанта. |
signedFileUrl |
string | Нет | URL подписанного файла. |
evidenceHash |
string | Нет | Хеш доказательной базы. |
tsaSerial |
string | Нет | Серийный номер метки времени TSA. |
chainTxId |
string | Нет | Идентификатор транзакции в блокчейне. |
Ответ
HTTP/1.1 200 OK
Content-Type: application/json
{
"requestId": "8c1f7e3a-4d6b-4b1f-9a3a-9f0c2e1b1d77",
"foreignContractNo": "ORDER-2026-0517",
"status": "SIGNED",
"canSign": false,
"blockReason": null,
"foreignSignUrl": "https://animall-signature.jgsysj.com/sign/8c1f7e3a...",
"signedFileUrl": "https://files.example.com/contracts/order-2026-0517.signed.pdf",
"signedAt": "2026-05-17T11:18:40Z",
"createdAt": "2026-05-17T09:42:11Z",
"updatedAt": "2026-05-17T11:18:42Z"
}
Коды ошибок
| Код | HTTP | Значение |
|---|---|---|
40101 |
401 | Подпись HMAC отсутствует или недействительна; API-ключ отозван. |
40103 |
401 | Отклонение временной метки превышает 5 минут, или nonce уже был использован. |
40301 |
403 | У организации нет активного биллингового аккаунта. |
40901 |
409 | foreignContractNo уже используется с другим телом запроса. |
50200 |
502 | УЦ вернул ошибку. |
50400 |
504 | УЦ не ответил в срок. |
Рекомендуемая схема интеграции
- Вызовите
POST /contracts— передайте данные договора иforeignSignUrl. - Дождитесь перехода в
SENT(опрашивайтеGET /contracts/{requestId}, не злоупотребляя?fresh=true). - Направьте подписанта по активной ссылке
foreignSignUrl. - Если договор нужно отменить — вызовите
POST .../revokeдо подписания. - После подписания казахстанской стороной — вызовите
POST .../sign-completeс доказательной базой. - Сверку записей ведите по паре
requestId+foreignContractNo.
Нужна помощь? Создайте тикет в разделе Поддержка или напишите на cns-support@fcd.kz.