Процес: влезни е-фактури
Оваа страница те води од нула до влезна е-фактура што е преземена, потврдена и одлучена. Не треба да знаеш ништо однапред: секој чекор кажува што правиш, ти дава готова команда, покажува каков одговор да очекуваш и што да направиш ако добиеш нешто друго.
Сè се случува на sandbox серверот (https://sandbox.api.earhiva.mk). Таму документите за проба
ги создаваш ти, со една команда — не чекаш вистинска фактура од партнер.
Патот на влезната фактура
Дел со наслов „Патот на влезната фактура“Влезната фактура оди во спротивна насока од излезната, и ти си оној што одлучува:
| # | Каде | Што се случува |
|---|---|---|
| 1 | Испраќачот | ја издава фактурата и ја праќа преку УЈП |
| 2 | УЈП | ја заведува и ни ја предава |
| 3 | eArhiva.mk | ја зема, ја чува и ти ја нуди преку API |
| 4 | Твојот софтвер | ја повлекува, ја потврдува како преземена и одлучува — прифаќа или одбива |
⛔ Одлуката има рок. Секоја фактура носи decisionDeadline; по тој ден УЈП ја прифаќа сама, а
одлука пратена потоа се одбива. Тоа е единствениот дел од овој тек што не може да се повтори.
Што ти треба
Дел со наслов „Што ти треба“| Што | Зошто |
|---|---|
| клуч за sandbox | истиот како за излезните; ако веќе го имаш, продолжи на чекорот 2 |
команда curl | за повиците; ја има на Windows 10 и 11, macOS и Linux |
jq или кој било преглед на JSON | одговорите тука се JSON, не XML |
Чекорите
Дел со наслов „Чекорите“-
Побарај пристап
Дел со наслов „Побарај пристап“Ако веќе имаш клуч од процесот за излезни фактури, прескокни го овој чекор — истиот клуч ги отвора и двете насоки.
Ако немаш, побарај го по е-пошта на support@earhiva.mk, со наслов
Барање за пристап кон sandbox серверот, и наведи: име на компанијата, лице за контакт, е-пошта, телефон и име на апликацијата што ќе го користи API. -
Провери дека клучот работи
Дел со наслов „Провери дека клучот работи“Барање · ова го извршуваш ти curl -i "https://sandbox.api.earhiva.mk/api/integration/v1/ping" \-H "X-Api-Key: <ВАШИОТ КЛУЧ>" \-H "X-Software-Id: <ИМЕ И ВЕРЗИЈА НА ВАШАТА АПЛИКАЦИЈА>"Првиот ред мора да е
HTTP/1.1 200 OK, а телото{"ok": true, "keyValid": true, …}.Добиваш Што значи Што правиш 401соEARH-1001клучот не е препишан точно, или е истечен копирај го повторно, без празни места 400соEARH-1008го нема заглавието X-Software-Idдодај го — задолжително е во секој повик -
Создај документи за проба
Дел со наслов „Создај документи за проба“На sandbox ти ги создаваш влезните фактури. Една команда прави серија од петнаесет, по една за секое сценарио — со содржина, без содржина, со поминат рок, со веќе потврдена одлука:
Барање · ова го извршуваш ти curl -i -X POST "https://sandbox.api.earhiva.mk/api/integration/v1/sandbox/seed" \-H "X-Api-Key: <ВАШИОТ КЛУЧ>" \-H "X-Software-Id: <ИМЕ И ВЕРЗИЈА НА ВАШАТА АПЛИКАЦИЈА>" \-H "Content-Type: application/json" \-d '{"seed": 21, "reset": true}'Одговор од API-то · скратен {"seed": 21,"created": 15,"deleted": 15, // reset ги тргна претходно создадените"documents": [{ "scenario": "full", "docUid": "eah_i_…", "euid": "SEED-21-full","expect": "format=original и format=pdf враќаат 200; format=ubl враќа 404" },{ "scenario": "deadlinePassed", "docUid": "eah_i_…", "euid": "SEED-21-deadlinePassed","expect": "POST decision враќа 409 EARH-3006 — рокот поминал" }// … уште тринаесет]}📌
seedе број на серијата, не случајност. Ист број дава иста серија — исти износи, исти датуми, исти испраќачи. Затоа тест напишан денес важи и утре. Изостанат број значи1.📌 Читај го
expect. За секој документ стои што точно треба да се случи со него — по тоа пишуваш тврдење во тестот, наместо да погодуваш.Добиваш Што значи Што правиш 400соEARH-2030име на сценарио што не постои одговорот ги набројува дозволените — земи од таму 404соEARH-1009ја повикуваш адресата надвор од sandbox оваа команда постои само на sandbox серверот Ако наместо серија ти треба една фактура со твоја содржина — свој број, износи и PDF — тоа е
POST sandbox/inbound. -
Повлечи ги новите фактури
Дел со наслов „Повлечи ги новите фактури“onlyNotImported=trueги дава само оние што сè уште не си ги потврдил — тоа е списокот што твојот софтвер го обработува:Барање · ова го извршуваш ти curl -i "https://sandbox.api.earhiva.mk/api/integration/v1/inbound?onlyNotImported=true&pageSize=100" \-H "X-Api-Key: <ВАШИОТ КЛУЧ>" \-H "X-Software-Id: <ИМЕ И ВЕРЗИЈА НА ВАШАТА АПЛИКАЦИЈА>"Одговор од API-то · еден ред од списокот {"items": [{"docUid": "eah_i_01M2AA6FNY8D2Y6Z7NXEGZ4810","receivedAt": "2026-09-12T10:02:01.534351","senderName": "Ветерник ДООЕЛ","senderEdb": "MK4080012345678","ackedAt": null, // сè уште не е потврдена"status": 120,"rejectionReason": null,"decisionDeadline": "2026-09-27"}],"totalCount": 20,"page": 1,"pageSize": 100,"totalPages": 1,"nextFrom": null}Копирај го
docUid— секој нареден чекор го бара.Ако сакаш Додај само од еден испраќач &senderEdb=MK4080012345678само од одреден датум &dateFrom=2026-09-01T00:00:00Zпоголема страница &pageSize=500— тоа е и највисоката дозволенаДобиваш Што значи Што правиш 400соEARH-3005побара страница поголема од 500 одговорот ја именува дозволената 400соEARH-2020параметар што не може да се прочита detailго именува — на пример датум во погрешен облик -
Прочитај го деталот
Дел со наслов „Прочитај го деталот“Барање · ова го извршуваш ти curl -i "https://sandbox.api.earhiva.mk/api/integration/v1/inbound/<docUid>" \-H "X-Api-Key: <ВАШИОТ КЛУЧ>" \-H "X-Software-Id: <ИМЕ И ВЕРЗИЈА НА ВАШАТА АПЛИКАЦИЈА>"Одговор од API-то · вредностите се пример {"docUid": "eah_i_01M2AA6F71MZ3MPCEPTYBADT6H","receivedAt": "2026-09-12T10:02:01.057626","senderName": "Модрина ДОО","senderEdb": "MK4030995155258","ackedAt": null,"documentNumber": "021-001","amount": 83252.79,"currency": null,"status": 120,"rejectionReason": null,"decisionDeadline": "2026-09-27" // ⛔ прочитај го ПРЕД да одлучуваш}Поле Што прави со него твојот софтвер status110примена,120во обработка,140одобрена,150одбиенаdecisionDeadlineденот до кој одлуката мора да падне; по него УЈП прифаќа сама rejectionReasonтекст, само кај одбиена фактура ackedAtкога ти си ја презел; nullзначи дека сè уште не сиНепознат
docUidвраќа404соEARH-3001— истиот одговор како за документ на друга организација, намерно. -
Преземи ја содржината
Дел со наслов „Преземи ја содржината“Содржината се бара изречно, со
format:Барање · ова го извршуваш ти curl -i "https://sandbox.api.earhiva.mk/api/integration/v1/inbound/<docUid>/file?format=original" \-H "X-Api-Key: <ВАШИОТ КЛУЧ>" \-H "X-Software-Id: <ИМЕ И ВЕРЗИЈА НА ВАШАТА АПЛИКАЦИЈА>" \-o dokument.binformatШто враќа originalфајлот онака како што пристигнал — секогаш достапен кога документот воопшто носи содржина pdfсамо ако со документот дошол PDF ublсамо ако документот пристигнал како UBL XML Одговорот носи
Content-Dispositionсо име изведено одdocUid.Добиваш Што значи Што правиш 404соEARH-3002тој облик не постои за овој документ проба со original; ако и тој враќа3002, документот е без содржина400соEARH-2020го нема formatдодај го — не се подразбира 409соEARH-9003обликот постоел, а содржината не е достапна пиши на поддршката и прати го docUid; останатите податоци се читаат нормално -
Потврди дека си ја презел
Дел со наслов „Потврди дека си ја презел“Потврдата кажува дека документот е влезен во твојот систем. По неа тој излегува од списокот со
onlyNotImported=true:Барање · ова го извршуваш ти curl -i -X POST "https://sandbox.api.earhiva.mk/api/integration/v1/inbound/<docUid>/ack" \-H "X-Api-Key: <ВАШИОТ КЛУЧ>" \-H "X-Software-Id: <ИМЕ И ВЕРЗИЈА НА ВАШАТА АПЛИКАЦИЈА>"Одговор од API-то { "docUid": "eah_i_01M2AA6F…", "ackedAt": "2026-09-12T10:02:19.162282" }📌 Повторена потврда не е грешка и не го поместува времето — го враќа она од првиот пат. Значи слободно повикај ја повторно ако не си сигурен дали првиот повик поминал.
⛔ Потврдата не е одлука. Таа кажува „го презедов”, не „се согласувам”. Одлуката е чекорот 8, и само таа стигнува до УЈП.
-
Одлучи — прифати или одбиј
Дел со наслов „Одлучи — прифати или одбиј“Телото носи
accepted, и само кај одбивање уште причина и коментар:Прифаќање · ова го извршуваш ти curl -i -X POST "https://sandbox.api.earhiva.mk/api/integration/v1/inbound/<docUid>/decision" \-H "X-Api-Key: <ВАШИОТ КЛУЧ>" \-H "X-Software-Id: <ИМЕ И ВЕРЗИЈА НА ВАШАТА АПЛИКАЦИЈА>" \-H "Content-Type: application/json" \-d '{"accepted": true}'Одбивање · причината е шифра од шифрарникот curl -i -X POST "https://sandbox.api.earhiva.mk/api/integration/v1/inbound/<docUid>/decision" \-H "X-Api-Key: <ВАШИОТ КЛУЧ>" \-H "X-Software-Id: <ИМЕ И ВЕРЗИЈА НА ВАШАТА АПЛИКАЦИЈА>" \-H "Content-Type: application/json" \-d '{"accepted": false, "rejectReasonCode": "O-1", "comment": "Погрешен износ во ставката"}'Шифрите за причина се читаат од шифрарникот — не ги впишувај од глава:
Барање · ова го извршуваш ти curl -s "https://sandbox.api.earhiva.mk/api/integration/v1/codelists/reject-reasons" \-H "X-Api-Key: <ВАШИОТ КЛУЧ>" \-H "X-Software-Id: <ИМЕ И ВЕРЗИЈА НА ВАШАТА АПЛИКАЦИЈА>"Одговор од API-то · скратен {"type": "reject-reasons","items": [{ "code": "O-1", "name": "Погрешно пресметан ДДВ (несоодветна даночна основа, ДДВ стапка, …)" },{ "code": "O-4", "name": "Прометот не е извршен" }]}Ако е во ред, одговорот е
200:Одговор од API-то · одлуката е запишана {"docUid": "eah_i_01M2AA6F…","accepted": true,"confirmedByTaxAuthority": false, // УЈП сè уште не ја потврдил"confirmedAt": null,"failureCode": null}📌
200значи „запишано кај нас”, не „потврдено кај УЈП”. Пријавувањето натаму оди по него; дали УЈП веќе го потврдил стои воconfirmedByTaxAuthority. Состојбата ја читаш соGET inbound/{docUid}: по прифаќање статусот станува140, по одбивање150иrejectionReasonго носи текстот на причината.Ако не е:
Добиваш Што значи Што правиш 400соEARH-2022телото не е употребливо: одбивање без причина или без коментар, прифаќање што носи причина или коментар, или неактивна причина detailкажува кое од четирите; поправи го телото409соEARH-3006предоцна е: рокот поминал, или одлуката е веќе потврдена кај УЈП нема што да се поправи — состојбата не се враќа 404соEARH-3001нема таков документ провери го docUid409соEARH-9002одлуката не може да се пренесе поради нешто кај нас не е грешка во барањето; повтори подоцна, а ако се задржи — пиши на поддршката ⛔ Празно тело значи одбивање без причина, не „нема одлука” — и затоа враќа
EARH-2022. Полетоacceptedе задолжително. -
Повлекувај само што се сменило
Дел со наслов „Повлекувај само што се сменило“За редовна работа не го повлекувај целиот список. Со
by=updatedодговорот носиnextFrom— почетна точка за следниот повик:Прв повик curl -s "https://sandbox.api.earhiva.mk/api/integration/v1/inbound?by=updated&pageSize=500" \-H "X-Api-Key: <ВАШИОТ КЛУЧ>" -H "X-Software-Id: <ВАШАТА АПЛИКАЦИЈА>"Следен повик · со вредноста од nextFrom curl -s "https://sandbox.api.earhiva.mk/api/integration/v1/inbound?by=updated&dateFrom=2026-09-12T09:57:08.4498392%2B02:00&pageSize=500" \-H "X-Api-Key: <ВАШИОТ КЛУЧ>" -H "X-Software-Id: <ВАШАТА АПЛИКАЦИЈА>"📌
by=createdне враќаnextFrom— таму стоиnull. Инкрементално повлекување е ветено само соby=updated: документ примен пред месец дена чија состојба се сменила вчера влегува во второто, не во првото.⚠️ Границата е вклучителна: последниот документ од претходниот повик може да се појави и во следниот. Тоа е намерно — подобро еден повторен ред отколку испуштен.
Готово
Дел со наслов „Готово“Ако чекорот 8 е исполнет, твојот софтвер ги повлекува влезните е-фактури, ја презема содржината и
одлучува по нив. Петте повици — GET inbound, GET inbound/{docUid},
GET inbound/{docUid}/file, POST ack и POST decision — се целото што ти треба. Во продукција се
менува само адресата и клучот, а документите доаѓаат од вистински испраќачи наместо од sandbox/seed.
Каде понатаму
Дел со наслов „Каде понатаму“| Кога ти треба | Оди на |
|---|---|
| статусите на влезен документ и премините меѓу нив | Влезни документи |
| серија документи по сценарија, со објаснување за секое | Серија по сценарија |
| една фактура со твоја содржина и свој PDF | Една фактура со своја содржина |
значењето на секоја шифра EARH-xxxx | Каталог на грешки |
| праќање фактури наместо примање | Процес: излезни е-фактури |