Sari la conținut

Portal clienți ​

Endpoint-uri read-only, filtrate pe client, pentru un site terț care își autentifică singur clienții (de exemplu site-ul atelierului) și le afișează vehiculele, istoricul și lucrările în curs din NOTSOWMS. Site-ul se autentifică cu un Bearer token obișnuit (<tenant-slug>.<key>) și cere datele în numele clientului pe care l-a identificat.

Spre deosebire de comenzile de service și devize, răspunsurile de aici sunt deliberat subțiri: fără note interne, fără token-uri, fără id-uri de mecanic, fără liniile de cost ale atelierului. Modulul service trebuie să fie activ pe tenant.

Capabilități

Citirea cere service:read. Aprobarea unui deviz folosește endpoint-ul existent POST /api/v1/service/estimates/{estimate}/respond, care cere service:write. O cheie pentru un portal de clienți are deci exact aceste două capabilități.

Endpoint-uri ​

MetodăCaleDescriere
GET/api/v1/service/portal/customers/by-email?email=Clientul cu acel email (potrivire exactă, fără majuscule).
GET/api/v1/service/portal/customers/{customer}/overviewClientul, vehiculele lui și toate comenzile care nu sunt ciornă.
GET/api/v1/service/portal/work-orders/{workOrder}?customer_id=O comandă: cronologie, devizul curent cu linii, poze vizibile.

Căutare client după email ​

bash
curl "https://tenant.notsowms.ro/api/v1/service/portal/customers/by-email?email=radu@example.ro" \
  -H "Authorization: Bearer tenant.cheie" -H "Accept: application/json"

Răspuns 200:

json
{
  "data": {
    "id": 12, "first_name": "Radu", "last_name": "Marin", "company_name": null,
    "display_name": "Radu Marin", "email": "radu@example.ro", "phone": "0722000111",
    "duplicates": 0
  }
}

Clienții marcați is_blacklisted sau anonimizați nu sunt returnați. duplicates spune câți alți clienți au același email, ca atelierul să-i poată uni. 404 când nu există, 422 fără email.

Prezentare client ​

bash
curl https://tenant.notsowms.ro/api/v1/service/portal/customers/12/overview \
  -H "Authorization: Bearer tenant.cheie" -H "Accept: application/json"

Răspuns 200 (prescurtat):

json
{
  "data": {
    "customer": { "id": 12, "display_name": "Radu Marin", "email": "radu@example.ro", "phone": "0722000111" },
    "vehicles": [
      { "id": 5, "vehicle_kind": "atv", "make": "CFMoto", "model": "CForce 450", "model_year": 2022,
        "model_variant": null, "registration_plate": "TM12ABC", "vin": null, "engine_cc": 450,
        "current_odometer": 1200, "odometer_unit": "km", "status": "active" }
    ],
    "work_orders": [
      { "id": 142, "number": "WO-2026-000142", "status": "estimate_sent", "status_label": "Deviz trimis",
        "vehicle_id": 5, "title": "Ambreiajul patinează", "created_at": "2026-05-25T09:30:00+00:00",
        "updated_at": "2026-05-25T11:05:00+00:00", "promise_date": null, "closed_at": null,
        "is_awaiting_customer": false,
        "status_path": ["received", "diagnosing", "estimate_pending", "estimate_sent"],
        "estimate": { "id": 31, "version": 1, "status": "sent", "total_cents": 119000, "currency": "RON" },
        "actual_total_cents": null }
    ]
  }
}
  • status_path este lista cronologică a statusurilor prin care a trecut comanda, ca un consumator să poată așeza o stare laterală (awaiting_customer, cancelled) pe ultimul pas liniar atins.
  • title este prima linie din complaint (maxim 120 de caractere) sau Lucrare WO-… dacă lipsește.
  • estimate este cel mai nou deviz care nu e ciornă (o versiune amendată dar netrimisă nu apare).
  • actual_total_cents apare doar când comanda e completed, invoiced sau paid.
  • Comenzile draft nu sunt listate. Maxim 100, cele mai noi primele.

Detaliu comandă ​

customer_id este obligatoriu și trebuie să fie proprietarul comenzii, altfel 404. Ciornele dau tot 404.

bash
curl "https://tenant.notsowms.ro/api/v1/service/portal/work-orders/142?customer_id=12" \
  -H "Authorization: Bearer tenant.cheie" -H "Accept: application/json"

Răspuns 200 (prescurtat): toate câmpurile din rezumatul de mai sus, plus

json
{
  "data": {
    "complaint": "Ambreiajul patinează", "diagnosis": "Discuri uzate", "customer_notes": "Vă sunăm când sosesc piesele.",
    "vehicle": { "id": 5, "make": "CFMoto", "model": "CForce 450", "registration_plate": "TM12ABC" },
    "timeline": [
      { "at": "2026-05-25T09:30:00+00:00", "status": "received", "label": "Primit" },
      { "at": "2026-05-25T11:05:00+00:00", "status": "estimate_sent", "label": "Deviz trimis" }
    ],
    "estimate": {
      "id": 31, "version": 1, "status": "sent", "currency": "RON",
      "subtotal_cents": 100000, "tax_cents": 19000, "total_cents": 119000, "deposit_required_cents": 0,
      "valid_until": "2026-06-01", "customer_message": null, "sent_at": "2026-05-25T11:05:00+00:00", "responded_at": null,
      "lines": [
        { "id": 301, "line_type": "part", "description": "Kit ambreiaj", "quantity": "1.000",
          "unit_price_cents": 60000, "total_cents": 60000, "tax_cents": 11400, "customer_decision": "pending" },
        { "id": 302, "line_type": "labor", "description": "Manoperă", "quantity": "2.000",
          "unit_price_cents": 20000, "total_cents": 40000, "tax_cents": 7600, "customer_decision": "pending" }
      ]
    },
    "photos": [
      { "id": 9, "media_type": "photo", "caption": "Disc uzat", "url": "https://…semnat, valabil 1h…", "created_at": "2026-05-25T10:00:00+00:00" }
    ]
  }
}
  • timeline este în ordine cronologică (cea mai veche prima) și nu conține motivul intern al schimbării.
  • photos conține doar pozele marcate vizibile pentru client; URL-urile sunt semnate și expiră după o oră.
  • Nu apar niciodată: internal_notes, tracking_token, approval_token, id-uri de personal, quoted_total_cents, liniile de manoperă / piese / subcontractare ale atelierului.

Aprobarea devizului din portal ​

Portalul aprobă cu endpoint-ul standard, trimițând doar liniile încă pending:

bash
curl -X POST https://tenant.notsowms.ro/api/v1/service/estimates/31/respond \
  -H "Authorization: Bearer tenant.cheie" -H "Content-Type: application/json" \
  -d '{"responded_via":"tap_link","decisions":[{"line_id":301,"decision":"approved"},{"line_id":302,"decision":"approved"}]}'

Statusul devizului se recalculează din decizii (approved, partially_approved, declined), iar trigger-ul de automatizare estimate_approved se declanșează ca de obicei.

Documentație API notso WMS