DEV Community

Listara.ro
Listara.ro

Posted on

Publică anunțuri prin API: curl, JSON și joburi asincrone (tutorial Listara)

Dacă ai un catalog propriu (o agenție imobiliară, un CRM) și vrei să publici anunțuri fără să le introduci manual, poți folosi API-ul public al Listara, o platformă românească de anunțuri. Mai jos parcurgem cu curl și JSON tot fluxul: token, câmpuri dinamice, creare, verificarea rezultatului, actualizare. Endpointurile și câmpurile sunt cele din documentația publică.

Ce ai nevoie

  • un cont cu acces API (dacă rolul contului nu îl permite, primești 403);
  • un token Bearer creat din contul tău, la secțiunea Acces API;
  • curl și jq.
export API="https://listara.ro/api/v1"
export LISTARA_TOKEN="tokenul-tau-din-acces-api"
Enter fullscreen mode Exit fullscreen mode

Cererile protejate cer headerele Authorization: Bearer {token}, Content-Type: application/json și Accept: application/json. Fără ultimul, unele endpointuri pot răspunde cu redirect în loc de 401 JSON.

Reguli de la început

  • POST /listings acceptă category_id 1 (Anunțuri), 2 (Imobiliare), 3 (Locuri de muncă) sau 5 (Licitații). Valoarea 4 (Magazin) este respinsă: produsele au endpoint separat, POST /products.
  • subcategory_id și child_category_id trebuie să aparțină categoriei alese.
  • La categoria 1, purpose este obligatoriu (sell, buy, service_offer, service_seek); la joburi, hiring sau seeking; la imobiliare și licitații se omite.

Pasul 1: citește câmpurile categoriei

Endpointul este public. Exemplu pentru Imobiliare → De vânzare → Apartament:

curl -s "$API/categories/2/fields?child_category_id=24" -H "Accept: application/json"
Enter fullscreen mode Exit fullscreen mode

Răspunsul (scurtat) arată cheile din attributes:

{
  "data": {
    "category_id": 2,
    "sub_category_id": 6,
    "child_category_id": 24,
    "child_category": { "id": 24, "name": "Apartament" },
    "fields": [
      { "key": "etaj", "type": "number", "required": false },
      { "key": "an_constructie", "type": "number", "required": false },
      { "key": "camere", "type": "number", "required": false },
      { "key": "bai", "type": "number", "required": false },
      { "key": "suprafata_utila", "type": "number", "required": false }
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode

La alte subcategorii există câmpuri obligatorii (la Autoturisme, de exemplu, marca, model, an_fabricatie, kilometraj), iar la câmpurile select trimiți value din options. Verifică endpointul înainte să construiești payload-ul.

Pasul 2: creează anunțul

Fișierul apartament.json:

{
  "category_id": 2,
  "subcategory_id": 6,
  "child_category_id": 24,
  "title": "Apartament 3 camere Florești",
  "description": "<p>Apartament luminos, finisat modern.</p>",
  "price": 95000,
  "price_currency_code": "EUR",
  "price_type": "fixed",
  "reference": "APT-0001",
  "location": { "judet": "Cluj", "oras": "Florești", "adresa": "Str. Eroilor 5" },
  "attributes": { "camere": "3", "bai": "2", "suprafata_utila": "72" },
  "images": ["https://example.com/apartament-living.jpg"]
}
Enter fullscreen mode Exit fullscreen mode

description este HTML cu text vizibil; price_type poate fi fixed, negotiable sau standard; price_currency_code (RON sau EUR) este opțional, implicit RON; images sunt URL-uri HTTPS publice (maximum 20), obligatorii la creare; reference este un identificator al tău, returnat pentru mapare.

curl -s -X POST "$API/listings" \
  -H "Authorization: Bearer $LISTARA_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d @apartament.json
Enter fullscreen mode Exit fullscreen mode

Răspunsul este HTTP 202 Accepted: anunțul intră într-o coadă de procesare.

{
  "message": "Listing creation queued successfully.",
  "data": {
    "job_id": "00000000-0000-4000-8000-000000000001",
    "status": "pending",
    "listing_id": null,
    "error": null
  }
}
Enter fullscreen mode Exit fullscreen mode

Pasul 3: urmărește jobul

GET /listing-jobs/{job_id} până când status devine completed (cu listing_id) sau failed (cu error):

JOB_ID=$(curl -s -X POST "$API/listings" \
  -H "Authorization: Bearer $LISTARA_TOKEN" \
  -H "Content-Type: application/json" -H "Accept: application/json" \
  -d @apartament.json | jq -r '.data.job_id')

until [ "$STATUS" = "completed" ] || [ "$STATUS" = "failed" ]; do
  sleep 5
  R=$(curl -s "$API/listing-jobs/$JOB_ID" \
    -H "Authorization: Bearer $LISTARA_TOKEN" -H "Accept: application/json")
  STATUS=$(echo "$R" | jq -r '.data.status')
  echo "status: $STATUS"
done
echo "$R" | jq '.data | {status, listing_id, error}'
Enter fullscreen mode Exit fullscreen mode

Pasul 4: actualizează anunțul

Cu listing_id din pasul anterior:

curl -s -X PUT "$API/listings/1234" \
  -H "Authorization: Bearer $LISTARA_TOKEN" \
  -H "Content-Type: application/json" -H "Accept: application/json" \
  -d '{
    "title": "Apartament 3 camere Florești, preț actualizat",
    "price": 92000,
    "price_type": "negotiable",
    "location": { "judet": "Cluj", "oras": "Florești", "adresa": "Str. Eroilor 5" },
    "attributes": { "suprafata_utila": "72" }
  }'
Enter fullscreen mode Exit fullscreen mode

La actualizare, images este opțional.

Erori și limite

  • 401: token lipsă sau invalid. 403: rolul nu are acces API. 422: validare eșuată (câmpuri obligatorii, imagini, taxonomie nepotrivită).
  • Maximum 150 de joburi în așteptare per cont; global, aproximativ 60 de joburi procesate pe minut.
  • Pentru volum mare: POST /listings/bulk (până la 100 de anunțuri pe request) sau import CSV/JSON, până la 5.000 de anunțuri pe fișier. Detaliile sunt în documentație.

Fluxul e același la orice categorie: alegi taxonomia, citești câmpurile, trimiți POST, urmărești jobul.

Notă de transparență: lucrez la Listara.ro, platforma al cărei API este folosit aici. Pentru modificări, consultă documentația oficială.

Top comments (0)