Tema
Greške, limiti i paginacija
Oblik greške
Svaka greška API-ja je JSON istog oblika:
json
{
"statusCode": 404,
"error": "NOT_FOUND",
"message": "Property not found"
}| Polje | Značenje |
|---|---|
statusCode | HTTP status, isti kao status odgovora |
error | mašinski kod; na njega se oslanjajte u kodu |
message | opis na engleskom, za log (ne prikazujte ga posetiocu doslovno) |
details | opciono; kod VALIDATION lista problema po poljima |
Greška validacije (400):
json
{
"statusCode": 400,
"error": "VALIDATION",
"message": "Request validation failed",
"details": [
{
"keyword": "invalid_literal",
"instancePath": "/consent",
"schemaPath": "#/consent/invalid_literal",
"params": { "issue": { "code": "invalid_literal", "expected": true, "path": ["consent"], "message": "Invalid literal value, expected true" } },
"message": "Invalid literal value, expected true"
}
]
}Polje sa problemom je u instancePath (/consent, /location/city …).
Statusi i kodovi
| Status | error | Kada |
|---|---|---|
| 400 | VALIDATION | telo ili parametri ne odgovaraju šemi (npr. pageSize > 100, nedostaje consent: true) |
| 400 | BAD_REQUEST | logička greška, npr. termin pokazivanja u prošlosti, neispravan bbox |
| 401 | UNAUTHORIZED | nema x-api-key, ključ ne počinje sa pk_, ključ je nepoznat, opozvan ili istekao |
| 402 | LICENCE | plan agencije ne uključuje opciju (npr. ai za asistenta) |
| 403 | FORBIDDEN | ključ nema opseg, Origin nije dozvoljen, agencija je suspendovana, pogrešan token za glas |
| 404 | NOT_FOUND | oglas ne postoji, nije aktivan ili nije objavljen na sajt |
| 429 | RATE_LIMITED | previše zahteva (vidi ispod) |
| 429 | AI_QUOTA, VOICE_QUOTA | potrošen mesečni limit AI-ja ili glasa agencije |
| 500 | INTERNAL | greška na serveru; javite nam vreme i x-request-id ako se ponavlja |
| 503 | AI_DISABLED, AI_UNAVAILABLE, VOICE_DISABLED | AI ili glas nisu dostupni |
Svaki odgovor nosi zaglavlje x-request-id. Možete poslati i sopstveno (8–100 znakova: slova, brojevi, . _ :-, npr. UUID); tada ga Propertio koristi u svojim logovima i vraća u odgovoru, inače pravi svoj. Uz prijavu problema pošaljite tu vrednost i vreme zahteva. Iz pregledača su čitljiva zaglavlja x-request-id, retry-after i x-ratelimit-* (CORS ih otkriva).
Limiti zahteva
Limiti se broje po IP adresi pozivaoca i po ruti, u prozoru od jednog minuta:
| Ruta | Limit |
|---|---|
GET /v1/agency, GET /v1/properties, GET /v1/properties/{idOrSlug} | 600 / min |
GET /v1/agents | 300 / min |
POST /v1/assistant | 30 / min |
POST /v1/voice/speak, GET /v1/voice/confirmation | 60 / min |
POST /v1/inquiries, POST /v1/viewing-requests | 20 / min |
feedovi (/plugins/…/feed/…, /xml/…) | 120 / min |
Ispred API-ja je i opšti limit od oko 30 zahteva u sekundi po IP adresi (sa kratkim „burstom“); preko njega proxy vraća 503.
Svaki odgovor nosi zaglavlja x-ratelimit-limit, x-ratelimit-remaining i x-ratelimit-reset (sekunde do novog prozora). Odgovor 429 nosi i retry-after:
json
{ "statusCode": 429, "error": "RATE_LIMITED", "message": "Too many requests. Wait a moment and try again (see the Retry-After header)." }Pozivi sa servera dele jednu IP adresu
Kada sajt zove API sa servera (preporučeno), svi posetioci troše isti limit, jer Propertio vidi samo IP adresu servera. Keširajte odgovore (npr. Next.js revalidate: 60, statičko generisanje, ili keš od par minuta) umesto da svaki prikaz stranice zove API.
Ponovni pokušaj: 429 i 503 su privremeni. Sačekajte retry-after (ili eksponencijalno, počev od 1 s) pa pokušajte ponovo. 4xx greške osim 429 se ne ponavljaju bez izmene zahteva.
Paginacija
Lista oglasa je paginirana brojem strane:
| Parametar | Podrazumevano | Opseg |
|---|---|---|
page | 1 | ≥ 1 |
pageSize | 20 | 1–100 |
json
{
"items": [ /* PublicProperty … */ ],
"page": 2,
"pageSize": 12,
"total": 87
}Broj strana je Math.ceil(total / pageSize). Strana iza poslednje vraća prazan items. Za prolaz kroz sve oglase (sitemap, statičko generisanje) koristite pageSize=100 ili SDK metodu properties.all().
GET /v1/agents nije paginiran (vraća sve agente agencije).
Verzije
Putanja /v1 je stabilna: polja se mogu dodavati, ali se postojeća ne uklanjaju i ne menjaju značenje bez nove verzije. Zato ignorišite nepoznata polja u odgovorima, a ne odbijajte ih. Izmene se beleže u changelogu.