← Документація / Посібники
Угода щодо API
Формат запитів, області дії (scopes), спискові запити, грошові одиниці, помилки, ідемпотентність, ліміти частоти запитів.
Формат запитів
Кожна операція виконується як POST-запит у стилі RPC:
POST /v1/{module}/{resource}/{action}
Модулі: reference, partners, catalog, sales, purchases, ledger, bank, declarations, files, webhooks, audit. Дії є дієсловами: create, get, update, delete, list, а також предметні дії, як-от issue, register, match, apply-advance, generate.
Автентифікація та області дії (scopes)
Authorization: Bearer <api key>. Ключі містять області дії (scopes), які перевіряються для кожної дії:
{module}:read- дії отримання/списку (get/list){module}:write- модифікації{module}:*або*- підстановочні знаки (wildcards)
Відсутність області дії призводить до помилки 403 forbidden. Відсутній або недійсний ключ призводить до 401 unauthorized.
Спискові запити
Усі дії list мають спільний контракт:
{
"page": 1,
"pageSize": 50,
"sort": [{ "field": "createdAt", "dir": "desc" }],
"filter": [{ "field": "paymentStatus", "op": "eq", "value": "unpaid" }]
}
Оператори фільтрації: eq (дорівнює), ne (не дорівнює), contains (текстовий збіг без урахування регістру, лише для текстових полів), gte (більше або дорівнює), lte (менше або дорівнює), in (будь-яке зі списку до 500 значень). Поля, за якими можна сортувати та фільтрувати, визначено в білому списку для кожного ендпоінту (див. специфікацію OpenAPI), а невідомі поля повертають помилку 400. Додайте totals: ["field", …] до запиту, щоб підсумувати числові поля за всіма рядками, що відповідають умовам; коли записи мають валюту, параметр totalsByCurrency надає такі ж суми, розділені за кодами валют. Відповіді: { rows, total, page, pageSize, totals?, totalsByCurrency? }.
Грошові одиниці та дати
Грошові суми подаються у вигляді десяткових рядків із кількістю знаків після коми до 4 ("121.0000") і ніколи не у вигляді чисел із плаваючою комою (floats). ПДВ (VAT) розраховується для кожного рядка з округленням до найближчого більшого (half-up rounding). Дати мають формат YYYY-MM-DD, а мітки часу (timestamps) відповідають стандарту ISO 8601 у форматі UTC.
Помилки
Єдиний конверт для всіх відповідей:
{
"error": {
"code": "validation",
"message": "Request validation failed",
"requestId": "k1x…",
"key": "request_invalid",
"fieldErrors": { "lines.0.unitPriceExclVat": ["Invalid value"] }
}
}
Коди: validation (400/422, а також 413, якщо завантажений файл або тіло запиту завеликі), unauthorized (401), payment_required (402, термін пробного періоду або передплаченого кредиту закінчився, а повідомлення містить інструкції щодо подальших дій), forbidden (403), not_found (404), conflict (409), idempotency_key_reuse (422), idempotency_in_progress (409), rate_limited (429), internal (5xx). Коли повідомлення є одним із фіксованих, поле key визначає його, щоб клієнт міг показати власний переклад, а params містить значення для нього (наприклад, { "period": "2026-09" } для заблокованого облікового періоду). Включайте requestId під час звернення щодо проблем.
Ідемпотентність
Додайте Idempotency-Key: <any string ≤255 chars> до будь-якого запиту на модифікацію:
- Повторний запит із тим самим ключем і корисним навантаженням (payload) - збережена відповідь відтворюється байт-у-байт із заголовком
x-idempotent-replay: true. - Той самий ключ, інше корисне навантаження (payload) - 422
idempotency_key_reuse. - Одночасний дублікат, поки перший запит ще виконується - 409
idempotency_in_progress. - Ключі належать тому API-ключу або користувачу, який їх надсилає, у межах компанії, для якої виконується виклик, тому дві інтеграції однієї компанії можуть використовувати однаковий ключ. Виклики, зроблені до створення компанії, та виклики
account/*зберігають ключі окремо для кожного користувача, тому повторний викликaccount/companies/createстворює лише одну компанію. - Збережена відповідь повертається лише після того, як викликаюча сторона знову пройде перевірку прав доступу (область дії (scope), роль, компанія та стан розрахунків); інакше запит отримує поточну помилку.
- Ключі втрачають чинність через 24 години. Відповіді з помилками (4xx) також відтворюються; відповіді 5xx не зберігаються, тому повторні спроби виконуються заново.
Ліміти частоти запитів (Rate limits)
300 запитів на хвилину для кожного API-ключа (за наданими обліковими даними; неавтентифіковані запити обмежуються за IP-адресою). У разі отримання помилки 429 дотримуйтеся заголовка retry-after. Заголовки x-ratelimit-* інформують про стан вашого ліміту.
Вебхуки (Webhooks)
Події записуються до транзакційної черги вихідних повідомлень (transactional outbox) у межах тієї ж транзакції бази даних, що й сама зміна. Документ, чию транзакцію було скасовано (rolled back), ніколи не генерує подію, і жодна подія не втрачається. Доставка:
POST-запит на вашу URL-адресу з JSON-подієюx-nordlet-timestamp: <unix seconds>- час підписання доставкиx-nordlet-signature-v2: t=<timestamp>,v1=<hex HMAC-SHA256 of "<timestamp>.<raw body>">з використанням вашого секрету підпискиx-nordlet-signature: sha256=<hex HMAC-SHA256 of the raw body>- залишено без змін для сумісності з наявними приймачамиx-nordlet-deliveryмістить ідентифікатор доставки, який є однаковим під час кожної повторної спроби доставки однієї події- Будь-яка відповідь, окрім діапазону 2xx, або перенаправлення призводять до повторної спроби через 30 секунд, 2 хвилини, 10 хвилин, 30 хвилин, 1 годину, 3 години, 6 годин і 12 годин (загалом приблизно через 24 години), після чого доставка позначається як невдала
- Кожна доставка надсилається лише одним сервером водночас, тому запуск кількох екземплярів API не призведе до подвійної відправки
Перевіряйте x-nordlet-signature-v2 за допомогою порівняння за константний час (constant-time comparison), перш ніж довіряти корисному навантаженню (payload), і відхиляйте доставку, якщо її мітка часу відрізняється від годинника вашого сервера більш ніж на 5 хвилин. Мітка часу є частиною підписаного тексту, тому перехоплену доставку не можна відтворити пізніше зі свіжою міткою часу. Зберігайте ідентифікатори x-nordlet-delivery, які ви вже опрацювали, щоб ігнорувати повтори в межах цього вікна. Невдалу доставку можна надіслати повторно за допомогою webhooks/deliveries/redeliver.
Аудит
Кожна модифікація записується (actor, action, entity, diff) і доступна для запитів через audit/list.
Бухгалтерські гарантії
- Бухгалтерські проведення (journal postings) завжди збалансовані. Це забезпечується відкладеним тригером бази даних під час фіксації транзакції (commit), а не лише кодом додатку.
- Номера документів є безперервними в межах кожної серії чи року, а їх виділення є безпечним щодо паралельного виконання (concurrency-safe).
- Заблоковані облікові періоди відхиляють будь-які проводки з датою всередині них (409).
- М'яко видалені документи (soft-deleted documents) зберігають свій слід аудиту; випущені або зареєстровані документи не можна видалити.