Za razvijalce

    Javni API in webhooki

    Povežite ProEntry s svojo spletno stranjo, Zapierjem ali internim sistemom. Prek REST API-ja berete delovni čas, storitve, račune in rezervacije ter ustvarjate povpraševanja v CRM; z izhodnimi webhooki pa vas ProEntry sam obvesti o novih povpraševanjih, rezervacijah in plačilih.

    API dostop je na voljo v paketih Pro, Ekipa in Premium.

    Avtentikacija

    API ključ ustvarite v aplikaciji: Nastavitve → API dostop. Ključe lahko ustvarja in prekliče lastnik ali vodja podjetja; na podjetje je lahko aktivnih največ 10 ključev. Ključ ima obliko pe_live_ + 32 znakov in se v celoti prikaže samo enkrat, ob kreaciji — shranite ga varno, kasneje je viden le začetek ključa.

    Ključ pošljete z vsakim zahtevkom na enega od dveh načinov (Bearer ima prednost):

    Authorization: Bearer pe_live_...
    # ali
    X-Api-Key: pe_live_...

    Vsak ključ dobi ob kreaciji podmnožico scope-ov (npr. invoices:read) — endpoint brez ustreznega scope-a vrne 403 insufficient_scope. Preklican ključ ali deaktivirano podjetje vrne 401 invalid_key.

    Endpointi

    Osnovni URL: https://<project>.supabase.co/functions/v1/api-v1 (v primerih spodaj $BASE). Uspešen odgovor ima obliko {"data": [...]}; seznami podpirajo paginacijo z ?limit= (1–100, privzeto 50) in ?offset=.

    MetodaPotScopeOpis
    GET/work-hourswork_hours:readDelovni čas podjetja (7 vrstic, day_of_week 0 = ponedeljek … 6 = nedelja).
    GET/servicesservices:readAktivne storitve: id, name, price, duration_minutes.
    POST/inquiriesinquiries:writeUstvari povpraševanje v CRM (brez captche — zahtevek je avtenticiran s ključem).
    GET/invoicesinvoices:readGlave računov (brez postavk): številka, datumi, znesek, status, stranka. Filtri: status, from/to.
    GET/bookingsbookings:readJavne rezervacije s podatki o stranki in storitvah. Filtra from/to (po datumu rezervacije).

    Primer: delovni čas

    curl -H "Authorization: Bearer pe_live_..." \
      "$BASE/work-hours"
    
    # Odgovor:
    {"data": [{"day_of_week": 0, "is_open": true, "open_time": "08:00:00",
      "close_time": "20:00:00", "break_start": "12:00:00", "break_end": "13:00:00"}]}

    Primer: novo povpraševanje

    Obvezni polji sta name in description, plus vsaj eden od phone / email. Opcijsko: serviceType, source in gdprConsent (ob true se zabeleži čas privolitve).

    curl -X POST -H "Authorization: Bearer pe_live_..." \
      -H "Content-Type: application/json" \
      -d '{"name":"Janez Novak","phone":"041123456","description":"Ponudba za ograjo","gdprConsent":true}' \
      "$BASE/inquiries"
    
    # Odgovor (201):
    {"data": {"id": "...", "created_at": "..."}}

    Rate limiti

    60 / min

    Minutni limit na ključ. Ob prekoračitvi: 429, Retry-After: 60, koda rate_limited.

    1000 / dan

    Dnevni limit na ključ. Ob prekoračitvi: 429, Retry-After: 3600, koda rate_limited_day.

    V kvoto se štejejo samo postreženi zahtevki — zavrnjeni z 429 se ne štejejo.

    Webhooki

    ProEntry lahko vaš sistem obvešča o dogodkih s HTTP POST klicem na vaš https:// URL (privatni in lokalni naslovi so blokirani). Ob kreiranju naročnine prejmete secret oblike pe_whsec_<32 hex znakov> — prikazan je samo enkrat in ga kasneje ni mogoče ponovno prebrati. Vaš endpoint mora v 10 sekundah vrniti status 2xx; redirectom ne sledimo.

    Dogodki

    DogodekOpis
    inquiry.createdNovo povpraševanje (ime, kontakt, opis, vir).
    booking.createdNova javna rezervacija (termin, storitve, cena, stranka).
    booking.cancelledPreklic rezervacije (termin, čas in razlog preklica).
    invoice.paidRačun označen kot plačan (številka, znesek, stranka, datum plačila).
    pingTestni dogodek ob preizkusu naročnine — podpisan enako kot pravi dogodki.

    Oblika dostave

    Vsaka dostava je POST z JSON ovojnico. Isti dogodek lahko ob retryju prejmete večkrat — deduplicirajte po id dostave. Vrstni red dostav ni zagotovljen.

    POST <vaš URL>
    Content-Type: application/json
    X-ProEntry-Event: inquiry.created
    X-ProEntry-Delivery: 9c5e6d1e-...
    X-ProEntry-Signature: t=1755856800,v1=5f8a...
    User-Agent: ProEntry-Webhooks/1.0
    
    {
      "id": "9c5e6d1e-...",          // unikaten ID dostave (za deduplikacijo)
      "event": "inquiry.created",    // tip dogodka
      "created_at": "2026-08-22T10:00:00Z",
      "data": { ... }                // payload dogodka
    }

    Preverjanje podpisa

    Header X-ProEntry-Signature ima obliko t=<unix_ts>,v1=<hex>, kjer je v1 HMAC-SHA256 s secretom nad nizom "<unix_ts>.<surovo telo zahtevka>". Podpis vedno preverite nad surovim telesom (pred JSON parse), primerjajte s konstantno-časovno primerjavo in zavrnite zahtevke, kjer je razlika med t in trenutnim časom večja od npr. 5 minut (zaščita pred replay napadi).

    const crypto = require("node:crypto");
    
    function verifyProEntrySignature(rawBody, signatureHeader, secret, toleranceSec = 300) {
      const parts = Object.fromEntries(
        signatureHeader.split(",").map((p) => p.split("=", 2))
      );
      const ts = parseInt(parts.t, 10);
      if (!ts || !parts.v1) return false;
      if (Math.abs(Date.now() / 1000 - ts) > toleranceSec) return false;
    
      const expected = crypto
        .createHmac("sha256", secret)
        .update(`${ts}.${rawBody}`)
        .digest("hex");
      const a = Buffer.from(expected, "hex");
      const b = Buffer.from(parts.v1, "hex");
      return a.length === b.length && crypto.timingSafeEqual(a, b);
    }
    
    // Express: uporabite express.raw({ type: "application/json" }), da dobite surovo telo
    app.post("/webhooks/proentry", express.raw({ type: "application/json" }), (req, res) => {
      const ok = verifyProEntrySignature(
        req.body.toString("utf8"),
        req.get("X-ProEntry-Signature") || "",
        process.env.PROENTRY_WEBHOOK_SECRET
      );
      if (!ok) return res.status(401).end();
      const event = JSON.parse(req.body);
      // ... obdelava; deduplicirajte po event.id
      res.status(200).end();
    });

    Retry politika

    • Dostave obdeluje worker, ki teče vsako minuto — prva dostava tipično do ~1 minuto po dogodku.
    • Neuspela dostava (ne-2xx, timeout, napaka povezave) se ponovi z eksponentnim backoffom min(1 min × 2^poskus, 1 h): ~2 min, 4 min, 8 min, 16 min, 32 min, nato 1 h.
    • Največ 8 poskusov na dostavo; potem je dostava označena kot neuspešna in se ne ponavlja več.
    • Po 20 zaporednih neuspelih poskusih se naročnina samodejno deaktivira. Po odpravi napake jo znova vklopite; dogodki, nastali med deaktivacijo, se ne dostavijo za nazaj.

    Napake

    Vsaka napaka API-ja vrne JSON telo z opisom in strojno berljivo kodo:

    {"error": "<sporočilo>", "code": "<koda>"}
    StatusKodaKdaj
    401invalid_keyManjkajoč, neveljaven ali preklican ključ; tudi deaktivirano podjetje.
    403insufficient_scopeKljuč nima scope-a, ki ga endpoint zahteva.
    404not_foundNeznana pot.
    405method_not_allowedNapačna HTTP metoda za endpoint.
    429rate_limited / rate_limited_dayPresežen minutni oz. dnevni limit — glej Rate limiti.
    400validacijske kodeNeveljavno telo zahtevka (npr. manjkajoča obvezna polja pri POST /inquiries).
    500server_errorNapaka na strežniku — zahtevek ponovite kasneje.

    Pripravljen za začetek?

    Preizkusite ProEntry brezplačno in odkrijte, kako lahko poenostavite svoje poslovanje.

    Pišite nam

    Kontakt

    E-pošta
    info@proentry.si
    Delovni čas
    Pon - Pet: 8:00 - 16:00