Última actualización 2026-07-15
Referencia de API
Resumen
Esta página es para desarrolladores y operadores que integran las API de meridian — los visitantes habituales pueden omitirla. Todas las rutas API son manejadores Next.js App Router bajo src/app/api/. Tiempo y geocode requieren OPENWEATHER_API_KEY. Las rutas cron requieren Authorization: Bearer CRON_SECRET. Las rutas admin requieren cookie de sesión admin autenticada (meridian_admin_session) tras iniciar sesión en /login, salvo que ALLOW_DEV_ADMIN_BYPASS aplique en desarrollo.
GET /api/weather
Query: lat, lon, scope (current|hourly|daily|minutely), trigger opcional, lang. Devuelve payload del tiempo más fetchedAt, cacheHit, freshness, source, trigger, tokensUsed. La cabecera X-Cache refleja la capa de caché. Errores: 400 invalid params, 404 location not found, 429 rate_limited, 502 upstream_error o service_unavailable.
POST /api/weather/batch
Body: { cities: [{ lat, lon, scopes?: string[], id?, lang?, maxAgeMs?, trigger? }], trigger?, lang? }. Devuelve { cities: [{ lat, lon, scopes: { scope: { data, meta } | { error } } }] }. Scopes por ciudad, no un array de nivel superior. Limitado a 20 peticiones/minuto por IP. Usado por hooks del panel y detalle de ciudad.
GET /api/weather/history
Query: lat, lon, from, to opcionales (fechas ISO), limit. Devuelve { summary, observations, forecasts: { hourly, daily } } de weather_observations y weather_forecast_archive.
GET /api/geocode
Query: q (mín. 2 caracteres), parámetros context opcionales. Devuelve array normalizado: name, country, state, lat, lon, label. Límite upstream 5 resultados. En caché L2 con scope geocode. Limitado a 60 peticiones/minuto por IP.
GET /api/recent-checks
Sin parámetros. Devuelve { checks, source } donde source es popular cuando existen filas disparadas por búsqueda, o empty cuando no hay ninguna. Límite por defecto 20 de location_weather_checks ordenadas por volumen de búsqueda (triggers search_select y search_preview). La API no tiene respaldo showcase — la UI de inicio puede mostrar ciudades populares de demostración cuando está vacía si SHOW_DEMO_POPULAR_SEARCHES está activado. La columna Cerca de ti no usa esta ruta.
/api/subscriptions
GET ?clientId= — listar suscripciones activas del cliente. POST — crear { clientId, email, type, cityName?, cityLat?, cityLon?, frequency?, alertOnRain?, alertOnStorm?, alertPrefs? }. PATCH — actualizar alertPrefs en fila city_alerts { clientId, id, alertPrefs }. DELETE — body { clientId, cityLat, cityLon, types[] }. Tipos: newsletter, city_weekly, city_alerts.
GET /api/unsubscribe
Query: token (unsubscribe_token UUID). Desactiva la suscripción y devuelve confirmación HTML.
GET /api/alerts/[alertId]
Devuelve alerta normalizada: id, senderName, event, start, end, description. Fuente: scope alert en caché.
Rutas cron
GET /api/cron/weekly-digests — enviar correos de resumen semanal agrupados por correo del suscriptor. GET /api/cron/weather-alerts — evaluar alertPrefs contra OpenWeather, Open-Meteo y feeds NWS y enviar correos de alerta. Ambas requieren Bearer CRON_SECRET.
Rutas admin
Uso y config: GET /api/admin/usage; GET|PATCH /api/admin/config; legacy PATCH /api/admin/settings { refreshIntervalMs }. Usuarios y auth: GET|POST /api/admin/users; POST /api/admin/users/invite; GET /api/admin/me. Datos: GET /api/admin/checks; GET /api/admin/locations; GET|PATCH /api/admin/subscriptions; GET /api/admin/mailing-summary; GET /api/admin/analytics. Conectores: GET|PATCH /api/admin/connections; GET|PATCH /api/admin/openweather-key; GET|PATCH /api/admin/email-key. CMS de correo: GET|POST|PATCH /api/admin/email-templates; POST /api/admin/email/test, /compose, /sync. AdSense: GET /api/admin/adsense/report; POST /api/admin/adsense/sync; OAuth GET /api/admin/adsense/oauth/start, /callback, /disconnect. CMS: GET|PATCH /api/admin/cms-pages. Todas requieren meridian_admin_session salvo bypass de desarrollo.
Rutas de anuncios
GET /api/ads/config — { scriptEnabled, clientId, consentRequired }. GET /api/ads?placement=dashboard|hero|recent-checks|city-detail — config de colocación con slotId si está definido. GET /api/ads/placeholder-bg — búsqueda hero para superficies placeholder. Ruta app GET /ads.txt — línea de editor AdSense desde env. Colocaciones AdSlot activas: dashboard, hero, city-detail. env de slot recent-checks existe pero inicio no tiene AdSlot.
Otras rutas públicas
GET /api/platform/limits — instantánea pública de cuota. POST /api/analytics/collect — beacon de analytics first-party. GET /api/location/region — ayuda IP/región. POST /api/weather/inaccurate-report — marcar datos incorrectos. GET /api/weather/map-tile/[layer]/[z]/[x]/[y] — mosaicos overlay hero OSM. Auth: POST /api/auth/login, /logout; POST /api/auth/forgot-password; POST /api/auth/reset-password/[token]; GET|POST /api/auth/invite/[token]; GET /api/auth/session.
Forma de error
Errores JSON típicamente { error: code, message: string }. Códigos ApiError incluyen invalid_request, service_unavailable, location_not_found, rate_limited, upstream_error, unauthorized, not_found, limit_reached.