{"openapi":"3.1.0","info":{"title":"Huella Vital Directory API","version":"1.0.0","description":"Public read API for the Huella Vital veterinary directory of Venezuela:\nclinics, cities, services and price aggregates.\n\n- **Auth**: none required for read access.\n- **Rate limit**: best-effort, 60 requests/minute per client IP (token bucket\n  in memory per server instance — serverless instances do not share state).\n  Over the limit you get `429` with `Retry-After`.\n- **Caching**: responses carry `Cache-Control: public, s-maxage=300,\n  stale-while-revalidate=3600` and are CDN-cacheable.\n- **Errors**: every error uses the shape `{ \"error\": { \"code\", \"message\" } }`.\n\nHuman documentation with copy-paste examples: https://huellavital.com/api-docs","contact":{"name":"Huella Vital","url":"https://huellavital.com"},"license":{"name":"Proprietary"}},"servers":[{"url":"https://huellavital.com","description":"Production"}],"tags":[{"name":"discovery","description":"API self-description"},{"name":"clinics","description":"Veterinary clinics"},{"name":"cities","description":"Cities and barrios"},{"name":"services","description":"Service catalogue"},{"name":"prices","description":"Price aggregates"}],"paths":{"/api/v1":{"get":{"tags":["discovery"],"operationId":"getDiscoveryIndex","summary":"Discovery index","description":"Version, endpoint list, documentation links and live record counts.","responses":{"200":{"description":"API discovery document.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per window per client IP."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests remaining in the current window."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the budget fully refills."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Discovery"}}}},"429":{"description":"Rate limit exceeded. See `Retry-After` header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/clinics":{"get":{"tags":["clinics"],"operationId":"listClinics","summary":"List clinics","description":"Paginated clinic list. Stable ordering: rating descending (unrated last), then review count, then slug.","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1},"description":"1-based page number."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"description":"Page size (max 100)."},{"name":"city","in":"query","required":false,"schema":{"type":"string","example":"caracas"},"description":"Filter by city slug (see GET /api/v1/cities). Unknown slugs return 400."},{"name":"service","in":"query","required":false,"schema":{"type":"string","example":"urgencias-24h"},"description":"Filter by service slug (see GET /api/v1/services). Unknown slugs return 400."},{"name":"q","in":"query","required":false,"schema":{"type":"string","maxLength":100,"example":"trinidad"},"description":"Case- and diacritic-insensitive substring match on the clinic name."},{"name":"has_phone","in":"query","required":false,"schema":{"type":"string","enum":["true","false"]},"description":"Keep only clinics with (\"true\") or without (\"false\") a phone number."}],"responses":{"200":{"description":"A page of clinics.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per window per client IP."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests remaining in the current window."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the budget fully refills."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClinicPage"}}}},"400":{"description":"Invalid query parameter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded. See `Retry-After` header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/clinics/{slug}":{"get":{"tags":["clinics"],"operationId":"getClinic","summary":"Get one clinic","description":"Full clinic object: hours, description (when available), schema-ready prices map (empty today), related URLs.","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","example":"clinica-veterinaria-la-trinida-caracas"},"description":"Clinic slug as returned by GET /api/v1/clinics."}],"responses":{"200":{"description":"The clinic.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per window per client IP."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests remaining in the current window."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the budget fully refills."}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ClinicDetail"}},"required":["data"]}}}},"404":{"description":"No clinic with that slug.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded. See `Retry-After` header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/cities":{"get":{"tags":["cities"],"operationId":"listCities","summary":"List cities","responses":{"200":{"description":"Cities with clinic counts, sorted by count descending.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per window per client IP."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests remaining in the current window."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the budget fully refills."}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/City"}}},"required":["data"]}}}},"429":{"description":"Rate limit exceeded. See `Retry-After` header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/cities/{ciudad}":{"get":{"tags":["cities"],"operationId":"getCity","summary":"Get one city","description":"City detail plus its barrios (neighborhoods) with clinic counts.","parameters":[{"name":"ciudad","in":"path","required":true,"schema":{"type":"string","example":"caracas"},"description":"City slug as returned by GET /api/v1/cities."}],"responses":{"200":{"description":"The city with its barrios.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per window per client IP."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests remaining in the current window."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the budget fully refills."}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/CityDetail"}},"required":["data"]}}}},"404":{"description":"No city with that slug.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded. See `Retry-After` header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/services":{"get":{"tags":["services"],"operationId":"listServices","summary":"List services","description":"The 8-service public catalogue with per-service clinic counts.","responses":{"200":{"description":"Service catalogue.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per window per client IP."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests remaining in the current window."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the budget fully refills."}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Service"}}},"required":["data"]}}}},"429":{"description":"Rate limit exceeded. See `Retry-After` header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/prices":{"get":{"tags":["prices"],"operationId":"getPrices","summary":"Price aggregates","description":"Service price averages, aggregate stats, and the sparse set of verified clinic-level price reports. Clinic-level prices are not yet populated for most clinics — check `data.coverage` before building on price data.","responses":{"200":{"description":"Price aggregates.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed per window per client IP."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests remaining in the current window."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the budget fully refills."}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Pricing"}},"required":["data"]}}}},"429":{"description":"Rate limit exceeded. See `Retry-After` header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/openapi.json":{"get":{"tags":["discovery"],"operationId":"getOpenApiSpec","summary":"This OpenAPI document","responses":{"200":{"description":"OpenAPI 3.1 specification (JSON)."},"429":{"description":"Rate limit exceeded. See `Retry-After` header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Machine-readable code: invalid_parameter, unknown_city, unknown_service, not_found, method_not_allowed, rate_limited, internal_error."},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]},"Discovery":{"type":"object","properties":{"name":{"type":"string"},"version":{"type":"string"},"description":{"type":"string"},"documentation":{"type":"string","format":"uri"},"openapi":{"type":"string","format":"uri"},"endpoints":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"methods":{"type":"array","items":{"type":"string"}},"description":{"type":"string"}}}},"counts":{"type":"object","properties":{"clinics":{"type":"integer"},"cities":{"type":"integer"},"services":{"type":"integer"}}},"rateLimit":{"type":"object","properties":{"policy":{"type":"string"},"limit":{"type":"integer"},"windowSeconds":{"type":"integer"},"note":{"type":"string"}}}}},"ClinicSummary":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"city":{"type":"object","properties":{"name":{"type":"string"},"slug":{"type":"string"}},"required":["name","slug"]},"neighborhood":{"type":["object","null"],"properties":{"name":{"type":"string"},"slug":{"type":"string"}}},"address":{"type":"string"},"phone":{"type":["string","null"]},"services":{"type":"array","items":{"type":"string"}},"rating":{"type":["number","null"]},"reviews":{"type":"integer"},"coordinates":{"type":["object","null"],"properties":{"lat":{"type":"number"},"lng":{"type":"number"}},"description":"Null today — geocoding is not yet populated."},"isEmergency":{"type":"boolean"},"url":{"type":"string","format":"uri","description":"Canonical web page URL."}},"required":["slug","name","city","services","reviews","isEmergency","url"]},"ClinicDetail":{"allOf":[{"$ref":"#/components/schemas/ClinicSummary"},{"type":"object","properties":{"id":{"type":"string"},"email":{"type":["string","null"]},"website":{"type":["string","null"]},"hours":{"type":"array","items":{"type":"string"}},"description":{"type":["string","null"]},"prices":{"type":"object","additionalProperties":{"type":"number"},"description":"Schema-ready; empty object today — clinic-level prices are not yet populated."},"images":{"type":"array","items":{"type":"string"}},"lastUpdated":{"type":"string"},"source":{"type":"string"},"urls":{"type":"object","properties":{"self":{"type":"string","format":"uri"},"web":{"type":"string","format":"uri"},"city":{"type":"string","format":"uri"},"neighborhood":{"type":["string","null"],"format":"uri"}}}}}]},"ClinicPage":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ClinicSummary"}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"},"hasNextPage":{"type":"boolean"},"hasPrevPage":{"type":"boolean"}}},"filters":{"type":"object","properties":{"city":{"type":["string","null"]},"service":{"type":["string","null"]},"q":{"type":["string","null"]},"has_phone":{"type":["boolean","null"]}}}},"required":["data","pagination","filters"]},"City":{"type":"object","properties":{"name":{"type":"string"},"slug":{"type":"string"},"clinicCount":{"type":"integer"},"url":{"type":"string","format":"uri"}},"required":["name","slug","clinicCount","url"]},"CityDetail":{"allOf":[{"$ref":"#/components/schemas/City"},{"type":"object","properties":{"barrios":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"slug":{"type":"string"},"clinicCount":{"type":"integer"},"url":{"type":"string","format":"uri"}}}}}}]},"Service":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"clinicCount":{"type":"integer"},"url":{"type":"string","format":"uri"}},"required":["slug","name","clinicCount","url"]},"Pricing":{"type":"object","properties":{"currency":{"type":"string","example":"USD"},"generatedAt":{"type":"string"},"stats":{"type":"object"},"serviceAverages":{"type":"object","additionalProperties":{"type":"object","properties":{"average":{"type":"number"},"range":{"type":"array","items":{"type":"number"},"minItems":2,"maxItems":2}}}},"clinicPrices":{"type":"object","description":"Verified clinic-level price reports keyed by clinic name (sparse)."},"coverage":{"type":"object","properties":{"clinicsWithPrices":{"type":"integer"},"totalClinics":{"type":"integer"}}},"note":{"type":"string"}},"required":["currency","serviceAverages","clinicPrices","coverage","note"]}}}}