Documentación de la API
URL base: https://api.zipcheckup.com/v1
Autenticación
Las solicitudes directas a los endpoints estándar de /v1 requieren una clave de API en el encabezado X-API-Key. El acceso anónimo se limita de forma deliberada a las solicitudes realizadas por páginas de ZipCheckup y a la ruta específica del widget /v1/public/zip/:zip.
curl -H "X-API-Key: YOUR_API_KEY" \
https://api.zipcheckup.com/v1/zip/90210
Obtenga una API key gratis en /api/pricing/. No se necesita tarjeta de crédito.
Límites de uso
Plan gratuito: 100 solicitudes por día, contadas por clave cuando la envía y por dirección IP cuando no. El límite diario se reinicia a medianoche UTC.
| Plan | Límite diario |
|---|---|
| Gratis | 100 solicitudes/día |
| Pro ($49/mes) | 10,000 solicitudes/día |
| Enterprise | Personalizado |
Los encabezados de límite de uso se incluyen en cada respuesta de la API:
| Encabezado | Descripción |
|---|---|
X-RateLimit-Limit | Máximo de solicitudes permitidas por día (por ejemplo, 100) |
X-RateLimit-Remaining | Solicitudes restantes en la ventana actual |
X-RateLimit-Reset | Marca de tiempo Unix cuando se reinicia el límite (medianoche UTC) |
Encabezados de ejemplo:
X-RateLimit-Limit: 100 X-RateLimit-Remaining: 87 X-RateLimit-Reset: 1711929600
Cuando supere el límite, recibirá una respuesta 429 Too Many Requests con una URL de upgrade:
{
"error": { "message": "Rate limit exceeded. Max 100 requests/day.", "status": 429 },
"limit": 100,
"reset": "2026-03-26T00:00:00.000Z",
"upgrade": "https://zipcheckup.com/api/pricing/"
}
¿Necesita más de 100 solicitudes/día? Vea opciones con límites más altos.
Endpoints
Obtener datos de calidad del agua por código postal
Devuelve un Perfil de Seguridad del Hogar completo para un código postal de EE. UU.: puntuación multifuente versionada y cobertura, además de evidencia de agua, contaminantes, infracciones y contexto tipificada por separado.
| Parámetro | Tipo | Descripción |
|---|---|---|
zip | string | Código postal de EE. UU. de 5 dígitos (parámetro de ruta) |
Respuesta de ejemplo:
{
"data": {
"zip": "90210",
"city": "Beverly Hills",
"stateAbbr": "CA",
"homeSafetyScore": 74,
"homeSafetyGrade": "B",
"coverage": "covered",
"contaminants": [
{
"code": "2456",
"name": "Total Trihalomethanes (TTHM)",
"category": "Disinfection Byproducts",
"mcl": 0.08,
"unit": "mg/L",
"violationCount": 1,
"healthBased": false
}
],
"recentViolations": [...],
"systems": [...],
"sourceCoverage": { ... }
},
"meta": {
"schema_version": "2.1.0",
"source_current_at": null,
"materialized_at": "2026-07-27T08:56:13.000Z",
"freshness": { "state": "unknown", "reason": "source_vintage_absent" }
}
}
contaminants enumera los contaminantes con infracciones registradas, no concentraciones medidas. mcl es el límite de la EPA y violationCount indica cuántas infracciones lo mencionan. Los valores medidos, cuando se procesó un informe, están aparte en ccrMeasurements.
Obtener solo el puntaje de seguridad
Devuelve solo el puntaje de seguridad, la calificación y el nivel de riesgo. Respuesta más ligera para paneles y widgets.
Respuesta de ejemplo:
{
"data": {
"zip": "90210",
"score": 74,
"grade": "B",
"coverage": "covered",
"series": "home-safety-v4-cross-vertical",
"modelVersion": "4.0.0",
"componentScores": { "water-compliance": 96, "radon-zone": 50 },
"componentStatus": { "water-compliance": "observed" }
},
"meta": { "schema_version": "2.1.0", "freshness": { "state": "unknown" } }
}
Obtener resumen del estado
Devuelve un resumen para un estado de EE. UU.: puntaje promedio, cantidad de códigos postales, principales infracciones y los códigos postales con peor puntaje.
| Parámetro | Tipo | Descripción |
|---|---|---|
state | string | Abreviatura de 2 letras del estado (por ejemplo, CA, NY, TX) |
Respuesta de ejemplo:
{
"data": {
"state": "CA",
"stateName": "California",
"avgScore": 68,
"totalZips": 1769,
"scoreKnownZipCount": 1769,
"violationKnownZipCount": 1602,
"violationUnknownZipCount": 167,
"topViolations": [...]
},
"meta": { "schema_version": "2.1.0" }
}
Los campos *KnownZipCount y *UnknownZipCount son los denominadores de cada promedio estatal. Un código postal contado como desconocido no fue medido; no es un código postal medido en cero.
Obtener ranking nacional
Devuelve una lista de códigos postales ordenada por puntaje de calidad del agua.
| Parámetro | Tipo | Por defecto | Descripción |
|---|---|---|---|
limit | integer | 50 | Cantidad de resultados (máximo 500) |
order | string | desc | desc = mejores primero, asc = peores primero |
state | string | todos | Filtrar por código de estado de 2 letras |
Obtener referencia de contaminante
Devuelve información de referencia sobre un contaminante: nombre, MCL de la EPA, efectos en la salud y fuentes comunes.
| Parámetro | Tipo | Descripción |
|---|---|---|
code | string | Código del contaminante (de la respuesta del endpoint de código postal) |
Consulta masiva de códigos postales Pro+
Un código postal que la API no puede responder aparece en unavailable con un status tipificado y no como registro vacío en results: no_profile, contract_failed y upstream_unavailable son hechos distintos. returned cuenta lo que hay en results. La cuota se cobra una solicitud por código postal, y un lote con varias versiones de datos informa freshness.state: "unknown" en lugar de una marca de tiempo que no corresponde a ninguno.
Consulta de hasta 100 códigos postales en una sola solicitud. Devuelve objetos completos y versionados del Perfil de Seguridad del Hogar con evidencia tipificada por separado. Solo en Pro y Enterprise.
| Parámetro del cuerpo | Tipo | Descripción |
|---|---|---|
zips | string[] | Arreglo de códigos postales de 5 dígitos (máximo 100) |
fields | string[] | Opcional. Campos a incluir (por ejemplo, ["score","grade","contaminants"]) |
Solicitud de ejemplo:
curl -X POST https://api.zipcheckup.com/v1/bulk/zip \ -H "X-API-Key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"zips": ["90210","10001","60601"]}'
Respuesta de ejemplo:
{
"data": {
"requested": 3,
"returned": 2,
"results": [ { "zip": "90210", "data": { ... } } ],
"unavailable": [
{
"zip": "00000",
"status": "no_profile",
"reason": "No ZipCheckup profile exists for this ZIP code."
}
]
},
"meta": { "freshness": { "state": "unknown", "reason": "bulk_mixed_vintage" } }
}
Formato de respuesta
Todas las respuestas son JSON con la siguiente envoltura:
// Success { "data": { ... }, "meta": { "source": "ZipCheckup multi-source civic data; see data.sourceCoverage", "schema_version": "2.1.0", "source_current_at": null, "materialized_at": "2026-07-27T08:56:13.000Z", "freshness": { "state": "unknown", "reason": "source_vintage_absent" } } } // Error { "error": { "message": "No se encontraron datos para el código postal 00000", "status": 404 } }
No existe un campo ok. Una respuesta correcta trae data y meta; un error trae error con message y status. meta.source_current_at es null cuando la fuente no publica versión, lo cual no significa que los datos sean actuales.
Los planes Pro y Enterprise pueden añadir ?format=csv a los endpoints de código postal, puntuación, estado, rankings, contaminante y condado. Un valor nulo se escribe como #N/A y no como celda vacía, de modo que un dato nunca medido no se suma como si fuera cero; un cero medido sigue siendo 0. La versión del esquema y el token nulo viajan en encabezados X-ZipCheckup-*, porque CSV no tiene envoltura.
Códigos de error
| Estado HTTP | Código de error | Descripción |
|---|---|---|
| 400 | BAD_REQUEST | Parámetros inválidos (por ejemplo, código postal con formato incorrecto) |
| 401 | UNAUTHORIZED | API key ausente o inválida |
| 403 | FORBIDDEN | El endpoint requiere un plan superior (por ejemplo, consulta masiva en el plan gratuito) |
| 404 | NOT_FOUND | No hay datos para el recurso solicitado |
| 429 | RATE_LIMITED | Límite de uso excedido. Vea el encabezado X-RateLimit-Reset |
| 500 | INTERNAL_ERROR | Algo falló de nuestro lado |
Versionado
La API se versiona mediante la ruta de la URL (/v1/). No haremos cambios incompatibles dentro de una misma versión. Se pueden agregar nuevos campos a las respuestas en cualquier momento - su código debe manejar los campos desconocidos sin fallar.
Cuando se publique una nueva versión, la versión anterior tendrá soporte durante al menos 12 meses.