e-packet API

v1.0
Adresa de bază
https://zbdnzolswscjoxhpsbtt.supabase.co/functions/v1/api/v1
Specificația OpenAPI
openapi.json — pentru Postman și alte unelte

API-ul e-packet vă permite să generați AWB-uri din propriul sistem (magazin online, ERP, aplicație), cu prețurile și creditul contului dumneavoastră e-packet.

Cum obțineți o cheie

Cheile API se emit la cerere: contactați-ne. Orice cont e-packet poate primi o cheie. Creditul se alimentează din aplicație, ca de obicei, iar prețurile sunt exact cele pe care le vedeți în aplicație pentru contul dumneavoastră.

Autentificare

Trimiteți cheia la fiecare cerere, în antetul Authorization:

Authorization: Bearer epk_live_…

Cheia este un secret de server. Nu o puneți niciodată într-o pagină web, într-o aplicație mobilă sau într-un depozit de cod public. API-ul nu răspunde cererilor făcute din browser.

Live și test

  • epk_live_… — AWB-uri reale, la curieri.
  • epk_test_… — mediul de test (sandbox) al curierilor, doar pentru DPD și Sameday, singurii curieri cu un mediu de test real. Alt curier cu o cheie de test este refuzat (422, sandbox_not_supported), iar tarifele includ doar DPD și Sameday. AWB-urile de test sunt salvate, dar nu se ia nimic din credit și creditul nu este verificat.

O cheie de test vede doar AWB-urile create cu o cheie de test, iar o cheie live nu le vede.

Limite de utilizare

Cel mult 60 de cereri pe minut pentru o cheie, toate adresele la un loc. Peste limită primiți 429 cu antetul Retry-After; nimic nu este creat sau taxat.

Erori

Toate erorile au aceeași formă: un cod HTTP, un code în engleză (stabil, pentru program), un message în română (pentru oameni) și source, care spune cine a refuzat: courier (curierul) sau e-packet (noi). Pentru erorile de câmp primiți și field.

HTTPcodeCând
401invalid_api_keyCheie lipsă, greșită sau necunoscută
403key_inactiveCheia a fost dezactivată
403account_inactiveContul nu este activ
402insufficient_creditCredit sub minimul pentru generare (20 lei; doar chei live)
404not_foundAdresă necunoscută sau AWB inexistent în contul dumneavoastră
405method_not_allowedMetodă HTTP greșită
422invalid_fieldCâmp lipsă, invalid sau peste limita curierului
422sandbox_not_supportedCurierul nu poate fi folosit cu o cheie de test
429rate_limitedPrea multe cereri
502courier_refusedCurierul a refuzat expedierea
502courier_unavailableCurierul nu a răspuns
500internal_errorEroare la noi; reîncercați

Refuzurile curierului

Când curierul refuză un AWB primiți 502, courier_refused, source: "courier", plus:

  • courier — curierul care a refuzat (DPD, SDY, CGS, FCR, DSC, TCE);
  • reason — motivul, stabil, pentru program (tabelul de mai jos);
  • field — câmpul din cererea dumneavoastră, când curierul îl indică.
{
  "error": {
    "code": "courier_refused",
    "message": "DPD a refuzat codul poștal destinatarului: nu corespunde localității sau adresei. Verificați codul poștal al adresei.",
    "source": "courier",
    "courier": "DPD",
    "reason": "invalid_postcode",
    "field": "recipient.postcode"
  }
}
reasonCe înseamnăCe faceți
invalid_postcodeCodul poștal nu corespunde localității sau adresei, după curierCorectați codul poștal
invalid_phoneTelefon refuzat (la locker este obligatoriu un mobil)Corectați telefonul
invalid_emailEmail refuzat sau lipsăCorectați emailul
invalid_nameNume sau persoană de contact prea lungi ori cu caractere neacceptateScurtați sau simplificați numele
invalid_addressAdresa trebuie corectată (stradă, număr)Corectați adresa
service_not_availableCurierul nu oferă serviciul pe această rută sau cu aceste opțiuniAlt tip de livrare sau alt curier
parcels_not_acceptedGreutatea, numărul sau dimensiunile coletelor nu sunt acceptate pentru serviciuAjustați coletele
options_not_acceptedRamburs, asigurare, deschidere colet sau plata transportului refuzate (de exemplu ramburs peste limita curierului)Ajustați opțiunile
pickup_date_unavailableZi nelucrătoare pentru punctul de predareReîncercați într-o zi lucrătoare
courier_errorProblemă tehnică la curier; datele nu au fost judecateReîncercați peste câteva minute
otherUn refuz pe care nu îl clasificăm încăVerificați datele; dacă sunt corecte, contactați-ne cu ora cererii

Mesajul (message) este scris de noi, nu textul curierului, și se poate îmbunătăți în timp: programul dumneavoastră trebuie să se bazeze pe code și reason, nu pe text. Lista de motive poate crește; tratați orice reason necunoscut ca pe other. Un AWB refuzat nu se taxează.

Rar, o verificare a noastră oprește expedierea înainte să ajungă la curier: primiți tot courier_refused, dar cu source: "e-packet" și reason: "other".

Câmpurile necunoscute sunt refuzate (422), ca o greșeală de scriere să nu treacă neobservată.

Lucruri importante

  • Tariful este o estimare. Nu există rezervare de preț: AWB-ul se taxează la prețul calculat în momentul generării, exact ca în aplicație. Diferențele apar rar (de exemplu la o schimbare de tarif a curierului sau a abonamentului).
  • Cheile de test generează doar cu DPD și Sameday, în mediul lor de test, și nu se taxează. Ceilalți curieri nu au un mediu de test real, așa că sunt refuzați.
  • Fiecare cerere `POST /awb` creează și taxează un AWB nou (cu o cheie live), chiar dacă trimiteți aceeași referință de două ori. Evitarea dublurilor (de exemplu la reîncercare după un timeout) este responsabilitatea sistemului dumneavoastră.
  • Ridicarea se comandă automat după AWB pentru DPD, FAN Courier și Dragon Star, când expeditorul este o adresă. Dacă ridicarea nu poate fi comandată, AWB-ul rămâne valid.
  • Anularea unui AWB nu este disponibilă prin API: contactați-ne.

Limite pe curier

Se aplică, pe lângă regulile câmpurilor, limita mai strictă dintre aplicație și curier. Peste limită primiți 422 cu câmpul vizat, înainte ca ceva să fie trimis curierului.

CurierTipuriLimite
DPD (DPD)D2D, D2L, L2D, L2L31,5 kg pe colet și în total; greutate volumetrică totală (L×l×h÷5000) 31,5 kg; 1–10 colete; latură max. 175 cm; asigurare max. 55.000 lei; deschidere colet doar cu ramburs. Locker: 15 kg (și volumetric ÷5000), 60×37×35 cm
Sameday (SDY)D2D, D2L, L2D, L2L50 kg pe colet; latură max. 300 cm; asigurare max. 50.000 lei. Locker: 20 kg (și volumetric ÷6000), 47×44×39 cm
Cargus (CGS)D2D, D2L100 kg pe colet; latură max. 160 cm; 800 kg facturați pe expediere (volumetric ÷6000); asigurare max. 23.000 lei; livrare sâmbăta (nu la locker). Locker: 15 kg facturați, 60×40×37 cm
FAN Courier (FCR)D2D, D2L, L2D, L2L50 kg în total; 1–10 colete; latură max. 300 cm; bloc max. 20 caractere; fără deschidere colet. FANbox: 30 kg, 45×44,3×40,4 cm. PayPoint (doar livrare): 10 kg, 90×60×60 cm
Dragon Star (DSC)D2D100 kg pe colet; latură max. 300 cm
TCE (TCE)D2D31,5 kg pe colet, în total și volumetric (÷5000); latură max. 300 cm; plic max. 0,3 kg; bloc + scară + etaj + apartament împreună max. 20 caractere

Pentru toți curierii: colet 0,1–100 kg, laturi 1–300 cm (apoi limita curierului); plic cel mult 0,5 kg (TCE 0,3 kg); un singur colet la locker; deschiderea coletului nu se poate la locker sau la plic; asigurarea nu se poate pentru colete peste 32 kg; livrarea sâmbăta doar la Cargus.

Statusuri

Codurile din GET /status (câmpul status). Cele finale nu se mai schimbă.

statusDenumireFinal
creatCreatnu
preluatPreluat de curiernu
preluare_esuataPreluare eșuatănu
in_tranzitÎn tranzitnu
in_livrareÎn livrarenu
avizatAvizatnu
livrare_esuataLivrare eșuatănu
redirectionatRedirecționatnu
retinutReținutnu
avariatAvariatnu
refuzatRefuzat de destinatarnu
retur_in_cursRetur în cursnu
livratLivratda
returnatReturnat expeditoruluida
anulatAnulatda
distrusDistrus / furatda
abandonatAbandonatda
inchis_administrativÎnchis administrativda
necunoscutNecunoscutnu

Formatul etichetei: A6 există la DPD, Sameday și Cargus; FAN Courier tipărește A4; Dragon Star și TCE au o singură etichetă, a curierului. Un format indisponibil devine A4.

Căutare localitate

GET/localities

Id-ul localității se folosește la tarife și la AWB. Fără filtre primiți toate localitățile, în pagini de 1.000.

Parametri

CâmpTipDescriere
searchstring

Numele localității, cel puțin 2 litere. Diacriticele și cratimele nu contează.

countystring

Codul județului (B, CJ, IS, …).

pageinteger

Pagina, de la 1.

Răspunsuri

200O pagină de localități.
{
  "data": [
    {
      "id": 109,
      "name": "CLUJ NAPOCA",
      "display_name": "Cluj Napoca (Cluj)",
      "county": "CJ"
    }
  ],
  "page": 1,
  "page_size": 1000,
  "total": 1,
  "has_more": false
}
422Câmp lipsă, invalid sau peste limită.
{
  "error": {
    "code": "invalid_field",
    "message": "Codul poștal are exact 6 cifre.",
    "field": "recipient.postcode"
  }
}
Altă eroareEroare.

Lockere și puncte de ridicare

GET/lockers

Punctele unui curier, opțional într-o localitate. id se trimite ca locker_id la AWB. Dragon Star și TCE nu au lockere; Cargus livrează la locker, dar nu preia din locker.

Parametri

CâmpTipDescriere
courierobligatoriuDPD | SDY | FCR | CGS
locality_idinteger

Id-ul unei localități din /localities.

pageinteger

Pagina, de la 1.

Răspunsuri

200O pagină de lockere.
422Câmp lipsă, invalid sau peste limită.
{
  "error": {
    "code": "invalid_field",
    "message": "Codul poștal are exact 6 cifre.",
    "field": "recipient.postcode"
  }
}
Altă eroareEroare.

Tarife de la toți curierii

POST/quotes

Prețul final, cu TVA, pentru contul dumneavoastră: cât s-ar lua din credit. Este o estimare: AWB-ul se taxează la prețul din momentul generării. Doar România.

Cu o cheie de test primiți doar tarifele DPD și Sameday.

Corpul cererii (JSON)

CâmpTipDescriere
sender_locality_idobligatoriuinteger
recipient_locality_idobligatoriuinteger
package_typeobligatoriuparcel | envelope
parcelsobligatoriuarray de object

La plic, exact un element, doar cu greutatea.

parcels[].weightobligatoriunumber

kg

parcels[].lengthnumber

cm; obligatoriu la colet.

parcels[].widthnumber

cm; obligatoriu la colet.

parcels[].heightnumber

cm; obligatoriu la colet.

delivery_typeD2D | D2L | L2D | L2L | ALL
cash_on_deliverynumber

Suma rambursului

insurancenumber

Valoarea declarată

open_packageboolean
saturday_deliveryboolean
{
  "sender_locality_id": 14515,
  "recipient_locality_id": 109,
  "package_type": "parcel",
  "parcels": [
    {
      "weight": 2,
      "length": 30,
      "width": 20,
      "height": 10
    }
  ],
  "delivery_type": "ALL",
  "cash_on_delivery": 150
}

Răspunsuri

200O ofertă pe curier și tip de livrare.
{
  "quotes": [
    {
      "courier": "DPD",
      "delivery_type": "D2D",
      "available": true,
      "price": 28.68,
      "currency": "RON"
    },
    {
      "courier": "TCE",
      "delivery_type": "D2D",
      "available": false,
      "reason": "Curierul nu oferă un tarif pentru acest transport."
    }
  ]
}
422Câmp lipsă, invalid sau peste limită.
{
  "error": {
    "code": "invalid_field",
    "message": "Codul poștal are exact 6 cifre.",
    "field": "recipient.postcode"
  }
}
Altă eroareEroare.

Generare AWB

POST/awb

Creează AWB-ul la curier și îl taxează din credit. Dacă creditul este sub 20 lei (inclusiv negativ), cererea este refuzată (402) și nimic nu este creat.

Cu o cheie de test: doar DPD și SDY (altfel 422, sandbox_not_supported), creditul nu este verificat și nu se ia nimic din el.

Fiecare cerere creează un AWB nou, chiar cu aceeași reference.

Pentru o parte la locker (L2D/L2L expeditor, D2L/L2L destinatar) trimiteți locker_id în locul adresei. O parte cu company este o firmă.

Corpul cererii (JSON)

CâmpTipDescriere
courierobligatoriuDPD | SDY | CGS | FCR | DSC | TCE
delivery_typeobligatoriuD2D | D2L | L2D | L2L
senderobligatoriuobject
sender.first_nameobligatoriustring

3–25 caractere

sender.last_nameobligatoriustring

3–25 caractere

sender.companystring

Dacă există

sender.phoneobligatoriustring

0712345678 sau +40712345678; spațiile și cratimele se ignoră.

sender.emailobligatoriustring
sender.locality_idinteger

Pentru adresă. Din /localities.

sender.postcodestring

Pentru adresă. Exact 6 cifre.

sender.streetstring

Pentru adresă. Max. 50.

sender.numberstring

Pentru adresă. Max. 10.

sender.blockstring

Max. 30.

sender.entrancestring

Scara. Max. 10.

sender.floorstring

Etajul. Max. 10.

sender.apartmentstring

Max. 10.

sender.locker_idstring

Pentru locker

recipientobligatoriuobject
recipient.first_nameobligatoriustring

3–25 caractere

recipient.last_nameobligatoriustring

3–25 caractere

recipient.companystring

Dacă există

recipient.phoneobligatoriustring

0712345678 sau +40712345678; spațiile și cratimele se ignoră.

recipient.emailobligatoriustring
recipient.locality_idinteger

Pentru adresă. Din /localities.

recipient.postcodestring

Pentru adresă. Exact 6 cifre.

recipient.streetstring

Pentru adresă. Max. 50.

recipient.numberstring

Pentru adresă. Max. 10.

recipient.blockstring

Max. 30.

recipient.entrancestring

Scara. Max. 10.

recipient.floorstring

Etajul. Max. 10.

recipient.apartmentstring

Max. 10.

recipient.locker_idstring

Pentru locker

package_typeobligatoriuparcel | envelope
parcelsobligatoriuarray de object

La plic, exact un element, doar cu greutatea. La locker, un singur colet.

parcels[].weightobligatoriunumber

kg

parcels[].lengthnumber

cm; obligatoriu la colet.

parcels[].widthnumber

cm; obligatoriu la colet.

parcels[].heightnumber

cm; obligatoriu la colet.

contentsobligatoriustring

Conținutul

cash_on_deliveryobject

Ramburs. Toate cele patru câmpuri sunt obligatorii împreună.

cash_on_delivery.amountobligatoriunumber

Lei.

cash_on_delivery.account_holderobligatoriustring

Nume și prenume

cash_on_delivery.ibanobligatoriustring

Fără spații.

cash_on_delivery.bank_nameobligatoriustring
insurancenumber

Valoarea declarată

open_packageboolean
saturday_deliveryboolean

Doar Cargus

referencestring

Referința dumneavoastră (de ex. numărul comenzii), max. 100. Doar pentru evidență; nu previne dublurile.

{
  "courier": "DPD",
  "delivery_type": "D2D",
  "sender": {
    "first_name": "Ion",
    "last_name": "Popescu",
    "company": "Magazin SRL",
    "phone": "0712345678",
    "email": "comenzi@magazin.ro",
    "locality_id": 14515,
    "postcode": "010011",
    "street": "Strada Exemplu",
    "number": "5"
  },
  "recipient": {
    "first_name": "Ana",
    "last_name": "Ionescu",
    "phone": "0722333444",
    "email": "ana@example.ro",
    "locality_id": 109,
    "postcode": "400001",
    "street": "Strada Mare",
    "number": "12",
    "block": "A2",
    "apartment": "7"
  },
  "package_type": "parcel",
  "parcels": [
    {
      "weight": 2,
      "length": 30,
      "width": 20,
      "height": 10
    }
  ],
  "contents": "Haine",
  "cash_on_delivery": {
    "amount": 150,
    "account_holder": "Ion Popescu",
    "iban": "RO49AAAA1B31007593840000",
    "bank_name": "Banca Transilvania"
  },
  "reference": "COMANDA-1042"
}

Răspunsuri

201AWB creat și taxat.
{
  "awb_number": "80512345678",
  "courier": "DPD",
  "delivery_type": "D2D",
  "price": 31.12,
  "currency": "RON",
  "credit_left": 468.88,
  "reference": "COMANDA-1042",
  "pickup": {
    "requested": true,
    "id": "123456",
    "from": "2026-10-05T09:00:00",
    "to": "2026-10-05T18:00:00"
  }
}
402Eroare.
422Câmp lipsă, invalid sau peste limită.
{
  "error": {
    "code": "invalid_field",
    "message": "Codul poștal are exact 6 cifre.",
    "field": "recipient.postcode"
  }
}
502Eroare.
Altă eroareEroare.

Eticheta AWB (PDF)

GET/label

PDF-ul etichetei, pentru un AWB din contul dumneavoastră. Antetul X-Label-Size spune formatul primit (A4, A6 sau courier_default).

Parametri

CâmpTipDescriere
awbobligatoriustring

Numărul AWB.

sizeA4 | A6

Răspunsuri

200Eticheta.application/pdf
404Eroare.
Altă eroareEroare.

Statusul livrării

GET/status

Statusul unui AWB din contul dumneavoastră. Un status mai nou de 30 de minute nu este cerut din nou curierului; un status final (livrat, returnat, …) nu se mai schimbă.

Parametri

CâmpTipDescriere
awbobligatoriustring

Numărul AWB.

Răspunsuri

200Statusul.
{
  "awb": "80512345678",
  "courier": "DPD",
  "status": "in_tranzit",
  "label": "În tranzit",
  "is_final": false,
  "status_at": "2026-10-05T11:20:00Z",
  "checked_at": "2026-10-05T12:01:00Z"
}
404Eroare.
Altă eroareEroare.