{"openapi":"3.1.0","info":{"title":"Teritoriu.digital API","version":"1.0.0","description":"API public, versionat, construit exclusiv peste release-uri promovate. Fiecare răspuns provine dintr-un bundle verificat fail-closed (contract public v1); indisponibilitatea Supabase sau a surselor oficiale nu afectează răspunsurile. Nu există încă un domeniu de producție — acest document descrie contractul, nu un deployment live.","license":{"name":"AGPL-3.0-only","url":"https://github.com/ciprian-rus/teritoriu.digital/blob/main/LICENSE"}},"paths":{"/api/v1/territories":{"get":{"summary":"Listează și caută unități teritoriale","description":"Căutare tolerantă la diacritice pe denumire, filtre exacte și paginare cursor deterministă, servite direct din release-ul public `stable`.","parameters":[{"name":"q","in":"query","description":"Căutare pe denumire, tolerantă la diacritice (ex. \"brasov\" găsește \"BRAȘOV\").","schema":{"type":"string"}},{"name":"siruta","in":"query","description":"Cod SIRUTA exact (schema `ro.ins.siruta`).","schema":{"type":"string"}},{"name":"territoryId","in":"query","description":"Identificator persistent UUIDv7 exact.","schema":{"type":"string","format":"uuid"}},{"name":"type","in":"query","description":"Filtru exact pe `territoryType`.","schema":{"$ref":"#/components/schemas/TerritoryType"}},{"name":"status","in":"query","schema":{"$ref":"#/components/schemas/TerritoryStatus"}},{"name":"countyTerritoryId","in":"query","description":"Restrânge rezultatele la un singur județ (după `territoryId`-ul județului).","schema":{"type":"string","format":"uuid"}},{"name":"cursor","in":"query","description":"Cursor opac primit în `nextCursor` de la răspunsul anterior.","schema":{"type":"string"}},{"name":"limit","in":"query","description":"Numărul maxim de rezultate pe pagină (implicit 50, maxim 200).","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}}],"responses":{"200":{"description":"Pagină de rezultate.","headers":{"ETag":{"schema":{"type":"string"}},"Cache-Control":{"schema":{"type":"string"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TerritoryListResponse"},"examples":{"sirutaLookup":{"summary":"GET /api/v1/territories?siruta=1017 — răspuns real, capturat live","value":{"release":{"releaseId":"2026.07.23.3","schemaVersion":"1.0.0","manifestSha256":"9b236c6992a65420a4f6ab3cb95020a9a76ba0d9de12c756776c6e129bdbbeca"},"total":1,"nextCursor":null,"items":[{"territoryId":"019f8e0f-4c41-7148-96d8-c4ad595c6a0d","officialName":"MUNICIPIUL ALBA IULIA","normalizedName":"municipiul alba iulia","shortName":"ALBA IULIA","territoryType":"municipality","administrativeRole":"local_uat","administrativeLevel":2,"parentTerritoryId":"019f8e0f-4c41-7361-b40e-e1c7744fd4e4","countyTerritoryId":"019f8e0f-4c41-7361-b40e-e1c7744fd4e4","status":"active","identifiers":[{"scheme":"ro.ins.siruta","value":"1017","status":"active","validFrom":null,"validTo":null}]}]}}}}}},"304":{"description":"Conținutul nu s-a schimbat față de `If-None-Match`."},"429":{"description":"Prea multe cereri de la aceeași sursă într-o fereastră de timp.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Secunde până la reset."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"rateLimited":{"value":{"error":{"code":"RATE_LIMITED","message":"too many requests"}}}}}}},"503":{"description":"Release-ul public nu a putut fi descărcat sau verificat.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"releaseUnavailable":{"value":{"error":{"code":"RELEASE_UNAVAILABLE","message":"failed to fetch release asset manifest.json: HTTP 503"}}}}}}}}}},"/api/v1/territories/{territoryId}":{"get":{"summary":"O unitate teritorială, cu strămoși și descendenți imediați","description":"Strămoșii sunt lanțul complet până la rădăcină, în ordine de la părinte direct spre rădăcină. Descendenții sunt numai copiii imediați, nu tot subarborele — un județ poate avea mii de descendenți transitivi.","parameters":[{"name":"territoryId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Teritoriul găsit, cu strămoși și descendenți imediați.","headers":{"ETag":{"schema":{"type":"string"}},"Cache-Control":{"schema":{"type":"string"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TerritoryDetailResponse"},"examples":{"albaIulia":{"summary":"GET /api/v1/territories/019f8e0f-4c41-7148-96d8-c4ad595c6a0d — răspuns real, capturat live (children trunchiat la 1 din mai multe pentru lizibilitate)","value":{"release":{"releaseId":"2026.07.23.3","schemaVersion":"1.0.0","manifestSha256":"9b236c6992a65420a4f6ab3cb95020a9a76ba0d9de12c756776c6e129bdbbeca"},"territory":{"territoryId":"019f8e0f-4c41-7148-96d8-c4ad595c6a0d","officialName":"MUNICIPIUL ALBA IULIA","normalizedName":"municipiul alba iulia","shortName":"ALBA IULIA","territoryType":"municipality","administrativeRole":"local_uat","administrativeLevel":2,"parentTerritoryId":"019f8e0f-4c41-7361-b40e-e1c7744fd4e4","countyTerritoryId":"019f8e0f-4c41-7361-b40e-e1c7744fd4e4","status":"active","identifiers":[{"scheme":"ro.ins.siruta","value":"1017","status":"active","validFrom":null,"validTo":null}]},"ancestors":[{"territoryId":"019f8e0f-4c41-7361-b40e-e1c7744fd4e4","officialName":"JUDEȚUL ALBA","normalizedName":"județul alba","shortName":"ALBA","territoryType":"county","administrativeRole":"county_uat","administrativeLevel":1,"parentTerritoryId":null,"countyTerritoryId":"019f8e0f-4c41-7361-b40e-e1c7744fd4e4","status":"active","identifiers":[{"scheme":"eu.eurostat.nuts","value":"RO121","status":"active","validFrom":null,"validTo":null},{"scheme":"ro.ins.siruta","value":"10","status":"active","validFrom":null,"validTo":null}]}],"children":[{"territoryId":"019f8e0f-4c41-7406-bf16-07556b9964c0","officialName":"ALBA IULIA","normalizedName":"alba iulia","shortName":"ALBA IULIA","territoryType":"component_locality","administrativeRole":"locality","administrativeLevel":3,"parentTerritoryId":"019f8e0f-4c41-7148-96d8-c4ad595c6a0d","countyTerritoryId":"019f8e0f-4c41-7361-b40e-e1c7744fd4e4","status":"active","identifiers":[{"scheme":"ro.ins.siruta","value":"1026","status":"active","validFrom":null,"validTo":null}]}]}}}}}},"304":{"description":"Conținutul nu s-a schimbat față de `If-None-Match`."},"404":{"description":"Niciun teritoriu cu acest `territoryId` în release-ul curent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"notFound":{"summary":"Răspuns real, capturat live pentru un territoryId inexistent","value":{"error":{"code":"TERRITORY_NOT_FOUND","message":"no territory with territoryId 00000000-0000-7000-8000-000000000000 in release 2026.07.23.3"}}}}}}},"429":{"description":"Prea multe cereri de la aceeași sursă într-o fereastră de timp.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Secunde până la reset."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"rateLimited":{"value":{"error":{"code":"RATE_LIMITED","message":"too many requests"}}}}}}},"503":{"description":"Release-ul public nu a putut fi descărcat sau verificat.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"releaseUnavailable":{"value":{"error":{"code":"RELEASE_UNAVAILABLE","message":"failed to fetch release asset manifest.json: HTTP 503"}}}}}}}}}},"/api/v1/territories/{territoryId}/descendants":{"get":{"summary":"Subarborele complet (transitiv) al unui teritoriu, paginat","description":"Toți descendenții, nu doar copiii imediați — un județ poate avea mii. Paginat la fel ca `/api/v1/territories` (cursor determinist după `territoryId`), cu aceleași filtre `type`/`status`.","parameters":[{"name":"territoryId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"type","in":"query","schema":{"$ref":"#/components/schemas/TerritoryType"}},{"name":"status","in":"query","schema":{"$ref":"#/components/schemas/TerritoryStatus"}},{"name":"cursor","in":"query","description":"Cursor opac primit în `nextCursor` de la răspunsul anterior.","schema":{"type":"string"}},{"name":"limit","in":"query","description":"Numărul maxim de rezultate pe pagină (implicit 50, maxim 200).","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}}],"responses":{"200":{"description":"Pagină din subarborele complet.","headers":{"ETag":{"schema":{"type":"string"}},"Cache-Control":{"schema":{"type":"string"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TerritoryListResponse"}}}},"304":{"description":"Conținutul nu s-a schimbat față de `If-None-Match`."},"404":{"description":"Niciun teritoriu cu acest `territoryId` în release-ul curent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Prea multe cereri de la aceeași sursă într-o fereastră de timp.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Secunde până la reset."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Release-ul public nu a putut fi descărcat sau verificat.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/changelog":{"get":{"summary":"Diferența determinist calculată față de release-ul anterior","description":"Coduri SIRUTA adăugate/modificate/retrase între release-ul curent și cel imediat anterior, calculate de pipeline la publicare (nu la cerere). Nu clasifică încă redenumiri/divizări/comasări ca atare.","responses":{"200":{"description":"Diferența față de release-ul anterior.","headers":{"ETag":{"schema":{"type":"string"}},"Cache-Control":{"schema":{"type":"string"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangelogResponse"},"examples":{"baseline":{"summary":"GET /api/v1/changelog — răspuns real, capturat live","value":{"release":{"releaseId":"2026.07.23.3","schemaVersion":"1.0.0","manifestSha256":"9b236c6992a65420a4f6ab3cb95020a9a76ba0d9de12c756776c6e129bdbbeca"},"previousReleaseId":"2026.07.23.2","baseline":true,"added":[],"changed":[],"removed":[],"sourceRecordChanged":[],"unchanged":16978,"ratios":{"changed":0,"removed":0,"totalDelta":0}}}}}}},"304":{"description":"Conținutul nu s-a schimbat față de `If-None-Match`."},"429":{"description":"Prea multe cereri de la aceeași sursă într-o fereastră de timp.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Secunde până la reset."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Release-ul public nu a putut fi descărcat sau verificat.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"schemas":{"TerritoryType":{"type":"string","enum":["country","macroregion","development_region","county","bucharest","sector","municipality","city","commune","component_locality","village","other"]},"TerritoryStatus":{"type":"string","enum":["active","inactive","provisional"]},"Identifier":{"type":"object","required":["scheme","value","status"],"properties":{"scheme":{"type":"string"},"value":{"type":"string"},"status":{"type":"string","enum":["active","historical","provisional"]},"validFrom":{"type":["string","null"],"format":"date"},"validTo":{"type":["string","null"],"format":"date"}}},"Territory":{"type":"object","required":["territoryId","officialName","normalizedName","territoryType","administrativeRole","administrativeLevel","status","identifiers"],"properties":{"territoryId":{"type":"string","format":"uuid"},"officialName":{"type":"string"},"normalizedName":{"type":"string"},"shortName":{"type":["string","null"]},"territoryType":{"$ref":"#/components/schemas/TerritoryType"},"administrativeRole":{"type":"string"},"administrativeLevel":{"type":"integer"},"parentTerritoryId":{"type":["string","null"],"format":"uuid"},"countyTerritoryId":{"type":["string","null"],"format":"uuid"},"status":{"$ref":"#/components/schemas/TerritoryStatus"},"identifiers":{"type":"array","items":{"$ref":"#/components/schemas/Identifier"}}}},"TerritoryListResponse":{"type":"object","required":["release","total","nextCursor","items"],"properties":{"release":{"type":"object","required":["releaseId","schemaVersion","manifestSha256"],"properties":{"releaseId":{"type":"string"},"schemaVersion":{"type":"string"},"manifestSha256":{"type":"string","pattern":"^[0-9a-f]{64}$"}}},"total":{"type":"integer","description":"Numărul total de rezultate care satisfac filtrele, înainte de paginare."},"nextCursor":{"type":["string","null"]},"items":{"type":"array","items":{"$ref":"#/components/schemas/Territory"}}}},"TerritoryDetailResponse":{"type":"object","required":["release","territory","ancestors","children"],"properties":{"release":{"type":"object","required":["releaseId","schemaVersion","manifestSha256"],"properties":{"releaseId":{"type":"string"},"schemaVersion":{"type":"string"},"manifestSha256":{"type":"string","pattern":"^[0-9a-f]{64}$"}}},"territory":{"$ref":"#/components/schemas/Territory"},"ancestors":{"type":"array","description":"De la părintele direct spre rădăcină.","items":{"$ref":"#/components/schemas/Territory"}},"children":{"type":"array","description":"Numai copiii imediați, nu tot subarborele.","items":{"$ref":"#/components/schemas/Territory"}}}},"ChangelogResponse":{"type":"object","required":["release","previousReleaseId","baseline","added","changed","removed","sourceRecordChanged","unchanged","ratios"],"properties":{"release":{"type":"object","required":["releaseId","schemaVersion","manifestSha256"],"properties":{"releaseId":{"type":"string"},"schemaVersion":{"type":"string"},"manifestSha256":{"type":"string","pattern":"^[0-9a-f]{64}$"}}},"previousReleaseId":{"type":["string","null"]},"baseline":{"type":"boolean","description":"Adevărat dacă acest release nu are un release anterior comparabil în mod semnificativ."},"added":{"type":"array","items":{"type":"string"},"description":"Coduri SIRUTA noi față de release-ul anterior."},"changed":{"type":"array","items":{"type":"string"}},"removed":{"type":"array","items":{"type":"string"}},"sourceRecordChanged":{"type":"array","items":{"type":"string"},"description":"Înregistrarea sursă s-a schimbat fără schimbare de identitate publicată."},"unchanged":{"type":"integer"},"ratios":{"type":"object","required":["changed","removed","totalDelta"],"properties":{"changed":{"type":"number"},"removed":{"type":"number"},"totalDelta":{"type":"number"}}}}},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}