← Документация / Ръководства
API конвенции
Структура на заявките, обхвати на удостоверяване, списъчни заявки, парични суми, грешки, идемпотентност, лимити на заявките.
Структура на заявките
Всяка операция е с RPC стил и се изпълнява чрез POST:
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>. Ключовете носят обхвати, които се проверяват за всяко действие:
{module}:read- действия за извличане и извеждане на списъци (get/list){module}:write- модифициращи операции{module}:*или*- общи маски (wildcards)
Липсващ обхват води до 403 forbidden. Липсващ или невалиден ключ води до 401 unauthorized.
Списъчни заявки (list queries)
Всички действия от тип 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). ДДС се изчислява за всеки ред поотделно с коефициент на закръгляване нагоре при полусума (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: <произволен низ с дължина до 255 знака> към всяка модифицираща заявка:
- Повторен опит със същия ключ и полезен товар (payload) - съхраненият отговор се възпроизвежда до байт точно с хедър
x-idempotent-replay: true. - Същят ключ, но с различен полезен товар - връща се 422
idempotency_key_reuse. - Едновременен дубликат, докато първата заявка все още се обработва - връща се 409
idempotency_in_progress. - Ключовете принадлежат на API ключа или потребителя, който ги изпраща, в рамките на компанията, от чието име се прави заявката, така че две интеграции на една и съща компания могат да използват един и същ ключ. Заявките, направени преди създаването на компанията, както и
account/*заявките, запазват ключовете за всеки потребител поотделно, така че повтаряща се заявкаaccount/companies/createсъздава само една компания. - Съхраненият отговор се връща само след като извикващата страна премине отново през същите проверки за права (обхват, роля, компания и статус на плащане); в противен случай заявката получава актуалната грешка.
- Ключовете изтичат след 24 часа. Отговорите с грешки (4xx) също се възпроизвеждат; отговорите 5xx не се съхраняват, така че при повторни опити те се изпълняват наново.
Лимити на заявките (rate limits)
300 заявки в минута за един API ключ (на база предоставени идентификационни данни; неавтентифицираните заявки се лимитират на база IP адрес). При получаване на 429 следвайте указанията в хедъра retry-after. Хедърите x-ratelimit-* предоставят информация за наличния ви лимит.
Уебхукове (webhooks)
Събитията се записват в транзакционна опашка за изходящи съобщения (outbox) в рамките на същата база данни и транзакция като самата промяна - отмененият (rolled-back) документ никога не генерира събитие и нито едно събитие не се губи. Доставка:
POSTзаявка към вашия URL адрес с JSON събитиетоx-nordlet-timestamp: <unix seconds>- моментът, в който е подписана доставкатаx-nordlet-signature-v2: t=<timestamp>,v1=<hex HMAC-SHA256 на "<timestamp>.<raw body>">, генериран с вашия секрет за абонаментx-nordlet-signature: sha256=<hex HMAC-SHA256 на суровото тяло>, запазен непроменен за съществуващи получателиx-nordlet-deliveryсъдържа идентификатора на доставката, който остава същият при всеки нов опит за същата доставка- Отговор, който не е в диапазона 2xx, или пренасочване (redirect) води до нов опит след 30 секунди, 2 минути, 10 минути, 30 минути, 1 час, 3 часа, 6 часа и 12 часа (общо около 24 часа), преди доставката да бъде маркирана като неуспешна
- Всяка доставка се изпраща само от един сървър едновременно, така че стартирането на няколко API инстанции няма да доведе до двойно изпращане
Проверявайте подписа x-nordlet-signature-v2 чрез сравнение с фиксирано време (constant-time comparison), преди да се доверите на полезния товар, и отхвърляйте доставки, чийто времеви отпечатък се различава с повече от 5 минути от системното ви време. Времевият отпечатък е част от подписания текст, така че заловена доставка не може да бъде възпроизведена по-късно с нов времеви отпечатък. Съхранявайте обработените идентификатори от x-nordlet-delivery, за да пренебрегвате дублирани събития в рамките на този прозорец. Неуспешната доставка може да бъде изпратена отново чрез webhooks/deliveries/redeliver.
Одит (audit)
Всяка модифицираща операция се записва (actor, action, entity, diff) и може да бъде извличана чрез заявка към audit/list.
Счетоводни гаранции
- Журналните контировки винаги са балансирани - това се гарантира от отложен тригер в базата данни по време на фиксиране (commit), а не само от приложния код.
- Номерата на документите са непрекъснати (gapless) в рамките на съответната серия и година, а разпределението им е безопасно при едновременен достъп (concurrency-safe).
- Заключените счетоводни периоди отхвърлят всякакви счетоводни записвания с дата в тях (409).
- Документите с меко изтриване (soft-deleted) запазват своята одитна пътека; издадените или регистрирани документи не могат да бъдат изтривани.