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=.
| Metoda | Pot | Scope | Opis |
|---|---|---|---|
| GET | /work-hours | work_hours:read | Delovni čas podjetja (7 vrstic, day_of_week 0 = ponedeljek … 6 = nedelja). |
| GET | /services | services:read | Aktivne storitve: id, name, price, duration_minutes. |
| POST | /inquiries | inquiries:write | Ustvari povpraševanje v CRM (brez captche — zahtevek je avtenticiran s ključem). |
| GET | /invoices | invoices:read | Glave računov (brez postavk): številka, datumi, znesek, status, stranka. Filtri: status, from/to. |
| GET | /bookings | bookings:read | Javne 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
| Dogodek | Opis |
|---|---|
| inquiry.created | Novo povpraševanje (ime, kontakt, opis, vir). |
| booking.created | Nova javna rezervacija (termin, storitve, cena, stranka). |
| booking.cancelled | Preklic rezervacije (termin, čas in razlog preklica). |
| invoice.paid | Račun označen kot plačan (številka, znesek, stranka, datum plačila). |
| ping | Testni 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>"}| Status | Koda | Kdaj |
|---|---|---|
| 401 | invalid_key | Manjkajoč, neveljaven ali preklican ključ; tudi deaktivirano podjetje. |
| 403 | insufficient_scope | Ključ nima scope-a, ki ga endpoint zahteva. |
| 404 | not_found | Neznana pot. |
| 405 | method_not_allowed | Napačna HTTP metoda za endpoint. |
| 429 | rate_limited / rate_limited_day | Presežen minutni oz. dnevni limit — glej Rate limiti. |
| 400 | validacijske kode | Neveljavno telo zahtevka (npr. manjkajoča obvezna polja pri POST /inquiries). |
| 500 | server_error | Napaka na strežniku — zahtevek ponovite kasneje. |