PostCargo REST API
Documentatie completa · v1.0 · Production-ready
API-ul PostCargo permite oricarui magazin online sau ERP sa integreze direct serviciile noastre de curierat: calcul preturi pe 12 curieri, generare AWB automata, tracking live, webhooks pentru status updates si retururi. Foloseste-l prin pluginuri oficiale (WooCommerce, Shopify) sau direct prin REST.
https://api.postcargo.ro
Cele mai populare endpoint-uri
Autentificare
API-ul foloseste doua tipuri de autentificare:
X-API-Key
Pentru integrari (WooCommerce, ERP, scripts). O cheie pe integrare, revocabila oricand.
X-API-Key: pcg_live_xxxxxxxxxxxxxxxx
Bearer JWT
Pentru actiuni administrative (gestionare chei, setari tenant). Obtinut prin login.
Authorization: Bearer eyJhbGc...
Format raspuns
Toate raspunsurile au structura:
{
"success": true,
"data": { ... },
"meta": { "page": 1, "total": 42 }
}
Erori:
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Missing required field: weight"
}
}
Coduri eroare
| HTTP | Code | Cauza |
|---|---|---|
| 400 | VALIDATION_ERROR | Camp lipsa sau invalid |
| 401 | UNAUTHORIZED | Cheie API invalida sau expirata |
| 403 | FORBIDDEN | Permisiune insuficienta |
| 403 | CANCEL_DISABLED | Anularea AWB prin API e dezactivata; trimite cererea pe suport@postcargo.ro |
| 404 | NOT_FOUND | Resursa inexistenta |
| 429 | RATE_LIMITED | Prea multe cereri (vezi headerul Retry-After) |
| 500 | INTERNAL_ERROR | Eroare server (logata pe partea noastra) |
| 503 | COURIER_UNAVAILABLE | API curier offline temporar |
Rate limiting
Limita implicita: 100 cereri / minut per cheie API. Headerele de raspuns:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 87
X-RateLimit-Reset: 1714650000
Retry-After: 12
Limita poate fi crescuta pentru clientii cu volum mare. Contact: suport@postcargo.ro
Permisiuni
Cheile API pot avea permisiuni granulare. Implicit, cheile noi au ["*"] (acces complet).
pricing:readCalculeaza preturishipments:createCreeaza expediereshipments:readCiteste expedierishipments:cancelAnulare dezactivata — suport@postcargo.roawb:createGenereaza AWBawb:readDescarca AWB PDFtracking:readTrackingwebhooks:manageWebhooksapi_keys:manageGestioneaza chei (necesita JWT)tenant:manageSetari cont (necesita JWT)Auth & Conturi
/v1/auth/register
Public
Creeaza un cont nou + tenant + prima cheie API.
Contul necesita aprobare manuala
Fiecare cont API este verificat de echipa PostCargo. Pana la aprobare, contul are
status: "pending", nu primesti JWT, iar cheia API returnata este respinsa
cu 403. Primesti email cand contul este activat, apoi te autentifici cu
POST /v1/auth/login.
Body
{
"tenant_name": "Magazinul Meu SRL",
"email": "owner@magazin.ro",
"password": "parola_min_8",
"name": "Ion Popescu",
"phone": "0722123456"
}
phone este optional, dar grabeste verificarea contului.
Response 201
{
"success": true,
"data": {
"user": { "id": 1, "email": "owner@magazin.ro", "role": "owner" },
"tenant": { "id": 1, "name": "Magazinul Meu SRL", "slug": "magazinul-meu-srl", "status": "pending" },
"api_key": "pcg_live_a1b2c3d4e5...",
"status": "pending_approval",
"message": "Contul a fost creat si asteapta aprobarea echipei PostCargo."
}
}
Salveaza api_key acum: nu mai este afisata a doua oara. Devine functionala dupa aprobare.
/v1/auth/login
Public
Login cu email + parola. Returneaza JWT + refresh token.
curl -X POST https://api.postcargo.ro/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"owner@magazin.ro","password":"parola"}'
Erori specifice
| Cod | HTTP | Ce inseamna |
|---|---|---|
ACCOUNT_PENDING | 403 | Contul nu a fost aprobat inca. Aparea email la activare. |
ACCOUNT_SUSPENDED | 403 | Contul a fost suspendat. Contacteaza PostCargo. |
AUTHENTICATION_ERROR | 401 | Email sau parola greşite. |
/v1/auth/refresh
Reinnoieste JWT folosind refresh token.
{ "refresh_token": "rfk_..." }
/v1/auth/api-keys
JWT + API Key
Listeaza toate cheile API ale tenant-ului — cu request_count + last_used_at + last_used_ip.
{
"success": true,
"data": [
{
"id": 1,
"key_prefix": "pcg_live_a1b2",
"label": "WooCommerce - Magazin principal",
"permissions": ["*"],
"is_active": true,
"last_used_at": "2026-05-03T20:30:12+03:00",
"last_used_ip": "82.77.123.45",
"request_count": 1432,
"expires_at": null,
"created_at": "2026-05-01T18:00:00+03:00"
}
]
}
/v1/auth/api-keys
Genereaza o cheie noua. Cheia complet apare o singura data in raspuns; salveaza-o.
// Body
{
"label": "WooCommerce - magazin nou",
"permissions": ["pricing:read", "shipments:create", "awb:create"],
"expires_in_days": 365
}
// Response
{
"success": true,
"data": {
"id": 5,
"label": "WooCommerce - magazin nou",
"api_key": "pcg_live_xxxxxxxxxxxxxxxxxxxx",
"key_prefix": "pcg_live_xxxx"
}
}
/v1/auth/api-keys/{id}/logs
Loguri detaliate pe o cheie. Filtre disponibile: ?page=1&per_page=50&status=200&platform=woocommerce&from=2026-05-01&to=2026-05-31
{
"success": true,
"data": {
"key": { "id": 1, "label": "...", "request_count": 1432 },
"stats_24h": { "total": 245, "success": 240, "errors": 5, "avg_ms": 187 },
"logs": [
{
"id": 9876, "method": "POST", "endpoint": "/v1/pricing/quote",
"status_code": 200, "duration_ms": 215, "ip": "82.77.x",
"source_platform": "woocommerce", "created_at": "..."
}
]
},
"meta": { "page": 1, "per_page": 50, "total": 1432, "total_pages": 29 }
}
/v1/auth/api-keys/usage
Stats agregate (toate cheile, ultimele 7-90 zile). ?days=7
{
"data": {
"totals": { "total": 12450, "success": 12200, "errors": 250, "avg_ms": 195 },
"by_day": [{ "day": "2026-05-01", "total": 1820, "success": 1810, "errors": 10 }],
"by_platform": [{ "platform": "woocommerce", "total": 11230 }],
"top_endpoints": [{ "endpoint": "/v1/pricing/quote", "total": 6420 }]
}
}
/v1/auth/api-keys/{id}
Revoca cheia. Integrarea care o foloseste va inceta sa functioneze imediat.
/v1/auth/forgot-password
Public
Trimite pe email linkul de resetare a parolei. Raspunsul este acelasi si daca emailul nu exista, ca sa nu se poata afla ce conturi sunt inregistrate.
{ "email": "owner@magazin.ro" }
/v1/auth/reset-password/validate
Public
Verifica daca un token de resetare este inca valid, inainte de a afisa formularul. Parametru query: ?token=...
/v1/auth/reset-password
Public
Schimba parola folosind tokenul primit pe email. Tokenul se consuma o singura data si invalideaza sesiunile existente.
{ "token": "...", "password": "parola_noua_min_8" }
Public (fara auth)
/health
Public
{ "success": true, "data": { "status": "ok", "version": "1.0.0", "php": "8.3.30" } }
/v1/couriers
Public
Lista publica a celor 12 curieri integrati (logo, descriere, pret pornire, features).
Pricing
/v1/pricing/quote
Calculeaza pretul pentru toti curierii activi simultan. Recomandat pentru checkout in WooCommerce/Shopify.
Body
{
"from": { "city": "Bucuresti", "county": "Bucuresti", "postcode": "010101" },
"to": { "city": "Cluj-Napoca", "county": "Cluj", "postcode": "400001" },
"package": {
"type": "colet",
"weight": 2.5,
"length": 30, "width": 20, "height": 15,
"value_declared": 250,
"cod_amount": 0
},
"options": {
"saturday_delivery": false,
"open_on_delivery": false,
"insurance": true
}
}
Trimite length,
width si height:
curierii factureaza greutatea volumetrica (L x l x h / 5000) cand e mai mare decat cea reala, iar fara dimensiuni
un colet mare si usor este cotat sub tariful real.
Response
{
"success": true,
"data": [
{
"courier_code": "gls",
"courier_name": "GLS Romania",
"price": 19.57,
"price_without_vat": 19.57,
"price_with_vat": 23.68,
"vat_rate": 21,
"list_price_without_vat": 26.10,
"list_price_with_vat": 31.58,
"discount_percent": 25,
"discount_amount": 7.90,
"discount_name": "Reducere Cont Nou",
"discount_source": "site",
"estimated_days": "1-3",
"source": "live",
"currency": "RON"
}
]
}
Preţ, TVA si reducere
| Camp | Ce contine |
|---|---|
list_price_without_vat | Tariful de lista, inainte de reducere (fara TVA). |
price / price_without_vat | Cat se plateste, fara TVA, dupa reducere. Acesta e costul de transport pe care il pui in checkout. |
price_with_vat | Acelasi preţ, cu TVA inclus. |
discount_source | site = reducerea activa pe postcargo.ro, preluata automat. tenant = procent setat pentru contul tau. none = fara reducere. |
source | live = tarif real al curierului. estimated = tarif de rezerva din configuratie, folosit cand curierul nu raspunde; poate diferi de cel real. |
Reducerea se aplica peste suma cu TVA, exact ca pe postcargo.ro, apoi se recalculeaza valoarea fara TVA. Implicit este cea activa pe site; poate fi schimbata per cont de echipa PostCargo.
/v1/pricing/calculate
Pret pentru un singur curier specific. Body identic cu /quote, plus "courier": "fan-courier".
/v1/pricing/calculate-all
Preturile de la toti curierii activi pe contul tau, intr-un singur apel. Body identic cu /quote. Util pentru a afisa clientului toate opţiunile la checkout.
/v1/pricing/couriers
Curierii pentru care contul tau poate cere preturi, cu marja configurata. Diferenta faţă de /v1/couriers: acela e public si general, acesta reflecta configuraţia contului.
Localitati
Nomenclatorul de localitati folosit de postcargo.ro. Foloseste-l pentru autocomplete in checkout: tariful depinde de judet, iar un oras scris greşit duce la alt preţ sau la o expediere respinsa.
/v1/geo/cities
Localitatile care incep cu textul cautat. Parametri:
q (minim 1 caracter) si
limit (implicit 15, maxim 50).
curl "https://api.postcargo.ro/v1/geo/cities?q=clu&limit=5" \
-H "X-API-Key: pcg_live_..."
Response
{
"success": true,
"data": [
{
"value": "Cluj-Napoca (Cluj)",
"label": "Cluj-Napoca",
"id": 12345,
"county": "Cluj",
"county_id": 14,
"postal_code": "400001"
}
]
}
Trimite label ca oras si
county ca judet cand ceri preţul sau creezi expedierea.
Bucuresti se expediaza pe sector
Pentru q=bucuresti primesti cele
6 sectoare, fiecare cu sector: 1..6, nu orasul generic. Curierii
tarifeaza diferit pe sector, iar o adresa fara sector poate fi respinsa la ridicare.
/v1/geo/counties
Toate judetele, cu numele exact asteptat de API la calculul de preţ si la creare expediere.
Expedieri
/v1/shipments
Creeaza expediere fara generare AWB (status: draft). AWB se genereaza separat (vezi /v1/awb).
Pentru expeditor si destinatar, company si contact sunt opţionale, dar recomandate cand partea e o firma: unii curieri (DPD) cer pe AWB persoana juridica si persoana de contact. Daca company lipseste, partea e tratata ca persoana fizica.
{
"courier_code": "fan-courier",
"external_id": "wc_order_1234",
"sender": {
"name": "Magazinul Meu", "phone": "0712345678",
"company": "Magazinul Meu SRL", "contact": "Ion Popescu",
"city": "Bucuresti", "county": "Bucuresti",
"address": "Str Exemplu 10", "postcode": "010101"
},
"recipient": {
"name": "Maria Popescu", "phone": "0723456789",
"city": "Cluj-Napoca", "county": "Cluj",
"address": "Str Aurel Vlaicu 25", "postcode": "400001"
},
"package": {
"type": "colet", "weight": 2.5,
"length": 30, "width": 20, "height": 15,
"value_declared": 250,
"cod_amount": 0,
"content": "Carti, articole personale"
}
}
/v1/shipments
Filtre: ?status=delivered&courier=fan-courier&page=1&per_page=50&from=2026-05-01
/v1/shipments/{id}
Detaliile complete (sender, recipient, package, awb, tracking history).
/v1/shipments/{id}/cancel
DEZACTIVAT
Anularea AWB-urilor prin API nu este disponibila. Pentru a anula un AWB, trimite un email la suport@postcargo.ro cu numarul AWB si motivul anularii. Cererea o tratam manual la curier si primesti confirmarea pe email.
Endpoint-ul rămâne inregistrat, dar raspunde:
{
"success": false,
"error": {
"code": "CANCEL_DISABLED",
"message": "Anularea AWB-urilor prin API este dezactivata. Trimite cererea de anulare pe suport@postcargo.ro, cu numarul AWB si motivul, si o tratam manual la curier."
}
}
De ce. Fiecare curier are propria fereastra de anulare si unele se inchid in cateva minute de la ridicarea comenzii. Un AWB marcat anulat la noi, dar rămas activ la curier, inseamna colet livrat fara plata. De aceea anularile trec printr-o verificare manuala.
Facturare. Cand anulam AWB-ul, scoatem expedierea si din facturare. Daca era deja pe o factura emisa, suma se corecteaza prin storno; iti spunem in raspunsul pe email.
/v1/shipments/{id}
DEZACTIVAT
Forma echivalenta a anularii, dezactivata la fel. Raspunde cu 403 CANCEL_DISABLED. Cererile de anulare se trimit pe suport@postcargo.ro.
/v1/shipments/{id}/tracking
Starea curenta a expedierii. Daca expedierea nu are inca AWB, raspunsul este 400 VALIDATION_ERROR — genereaza-l intai.
{
"success": true,
"data": {
"awb_number": "1234567890",
"status": "in_transit",
"courier_code": "fan-courier",
"recipient": { "name": "Ion Popescu", "city": "Cluj-Napoca", "county": "Cluj" },
"created_at": "2026-05-03 09:15:00",
"updated_at": "2026-05-03 18:30:00"
}
}
Valori posibile pentru status: draft, pending, awb_generated, picked_up, in_transit, out_for_delivery, delivered, returned, cancelled.
/v1/tracking/{awb}
Aceleasi date, dar cautate dupa numarul AWB in loc de id-ul expedierii. Util cand stochezi doar AWB-ul. Raspunsul este identic cu cel de mai sus.
AWB (Air Waybill)
/v1/shipments/{shipment_id}/awb
Genereaza AWB la curierul ales. Returneaza numarul AWB + calea PDF-ului.
Forma echivalenta, acceptata si ea: POST /v1/awb/{shipment_id}. Daca expedierea are deja AWB, raspunsul este 400 VALIDATION_ERROR.
{
"success": true,
"data": {
"awb_number": "1234567890",
"price": 24.20,
"cost_price": 18.00,
"status": "awb_generated",
"pdf_url": "/v1/shipments/8/awb/pdf"
}
}
/v1/shipments/{shipment_id}/awb/pdf
Returneaza PDF binar al AWB-ului. Headers: Content-Type: application/pdf.
Forma echivalenta: GET /v1/awb/{id}/pdf, unde {id} poate fi id-ul expedierii sau numarul AWB. Ruta cere acelasi header de autentificare ca restul API-ului, deci linkul nu poate fi deschis direct in browser.
Tenant (cont)
/v1/tenant/settings
Datele contului: nume, slug, domeniu, plan, stare si setarile proprii.
/v1/tenant/settings
Actualizeaza datele contului. Planul si starea contului se schimba doar de PostCargo.
{ "name": "Magazinul Meu SRL", "domain": "magazin.ro" }
/v1/tenant/billing
Datele fiscale ale contului si ce mai lipseste pentru a putea emite factura. status.is_complete spune daca poti expedia.
{
"success": true,
"data": {
"billing": {
"billing_company": "MAGAZINUL MEU SRL",
"billing_cui": "14399840",
"billing_reg_com": "J40/1234/2020",
"billing_address": "Str. Exemplu 12",
"billing_city": "Bucuresti",
"billing_county": "Bucuresti",
"billing_postal": "010011",
"billing_iban": "RO49AAAA1B31007593840000",
"billing_bank": "Banca Transilvania",
"billing_email": "facturi@magazin.ro"
},
"status": { "is_complete": true, "missing_fields": [], "missing_labels": [] }
}
}
/v1/tenant/billing
Salveaza datele fiscale. Poti trimite doar o parte din campuri; CUI-ul si IBAN-ul sunt validate (cifra de control), iar prefixul RO din CUI si spatiile din IBAN se normalizeaza automat.
POST /v1/shipments raspunde cu 422 BILLING_DATA_REQUIRED pana cand sunt completate.
{
"billing_company": "MAGAZINUL MEU SRL",
"billing_cui": "RO14399840",
"billing_address": "Str. Exemplu 12",
"billing_city": "Bucuresti",
"billing_county": "Bucuresti",
"billing_iban": "RO49 AAAA 1B31 0075 9384 0000",
"billing_bank": "Banca Transilvania"
}
/v1/tenant/couriers
Lista celor 12 curieri PostCargo cu detalii (logo, descriere, features, pret pornire) si flag is_enabled pentru tenant.
/v1/tenant/couriers/{code}
Activeaza/dezactiveaza un curier pentru contul tau. Body: {"is_active": true}
/v1/tenant/couriers/{code}
Scoate complet curierul din configuraţia contului. Expedierile deja create cu el rămân neatinse.
/v1/tenant/stats
Stats agregate: total expedieri, by status, by courier, ultimele 5.
/v1/tenant/seo
Setarile pentru pagina publica de tracking a coletelor tale (titlu, descriere, widget).
/v1/tenant/seo
Actualizeaza setarile SEO ale paginii de tracking.
Webhooks
/v1/webhooks
Lista webhook-urilor configurate.
/v1/webhooks
Configureaza un webhook care primeste evenimente (shipment.created, shipment.delivered, awb.generated, etc).
{
"url": "https://magazin.ro/postcargo-webhook",
"events": ["shipment.delivered", "shipment.cancelled"],
"secret": "secret_pentru_HMAC"
}
/v1/webhooks/{id}
Sterge webhook-ul. Nu mai primeşti evenimente pe acel URL.
Integrari (publice)
/v1/integrations
Public
Lista pluginurilor disponibile (WooCommerce activ; Shopify, PrestaShop in lucru).
/v1/integrations/woocommerce/info
Public
Versiune curenta plugin, cerinte WP/WooCommerce, marime, data ultimului build.
/v1/integrations/woocommerce/download
Public
Descarca postcargo-shipping.zip direct. Auto-build cand sursa devine mai noua decat .zip-ul cached.