Los feriados oficiales de Chile o Colombia son conocidos con meses de anticipación y los mantiene alguien más. Los días no laborables de tu empresa, no. La mantención anual de planta que se hace cada julio, el cierre por feria sectorial, las vacaciones colectivas de diciembre — esos tienen que entrar en algún lado, y en la mayoría de las empresas ese “algún lado” es una hoja de cálculo, una variable de entorno o un array en el código que alguien modificó hace dos años y nadie recuerda bien.
El resultado es predecible: un cron job que corre el día que la planta está cerrada, una fecha de entrega que cae en vacaciones colectivas, un SLA que se calcula sin considerar el cierre de fin de año.
El patrón que todos terminan implementando (y sus problemas)
La solución habitual es hardcodear las fechas en el código:
// ❌ El clásico
const DIAS_CIERRE = [
"2026-07-15", // Mantención anual
"2026-12-26", // Cierre de año
"2026-12-27",
"2026-12-28",
];
function esHabilEmpresa(fecha) {
if (DIAS_CIERRE.includes(fecha)) return false;
// ... lógica de feriados oficiales
}
El problema no es el código en sí — es que este array vive en el repositorio, lo que significa que:
- Actualizar las fechas del próximo año requiere un deploy
- Si hay varios servicios (backend, workers, scripts de nómina), cada uno tiene su propia copia que diverge con el tiempo
- No hay historial claro de quién cambió qué y cuándo
- El mismo array hay que duplicarlo para cada país donde operas
Y la variante con variables de entorno o base de datos propia no es mucho mejor: requiere mantener un esquema, escribir la lógica de consulta y gestionar el acceso desde cada servicio.
Una alternativa: calendarios personalizados en la API
La idea es simple: defines un calendario con un nombre y un identificador, le agregas las fechas no laborables de tu empresa, y después usas ese calendario como overlay sobre cualquier cálculo de días hábiles. Los feriados oficiales del país siguen funcionando igual — el calendario de empresa se suma encima.
Crear el calendario
curl -X POST https://api.feriados.io/v1/calendars \
-H "Authorization: Bearer frd_tu_key" \
-H "Content-Type: application/json" \
-d '{"name": "Planta Norte", "slug": "planta-norte"}'
El slug es el identificador que vas a usar en los requests. Puede ser cualquier string con letras, números y guiones — planta-norte, vacaciones-2026, feria-expomin.
Agregar las fechas
curl -X POST https://api.feriados.io/v1/calendars/planta-norte/dates \
-H "Authorization: Bearer frd_tu_key" \
-H "Content-Type: application/json" \
-d '{
"dates": [
{ "date": "2026-07-15", "name": "Mantención anual" },
{ "date": "2026-12-26", "name": "Cierre de año" },
{ "date": "2026-12-27", "name": "Cierre de año" },
{ "date": "2026-12-28", "name": "Cierre de año" }
]
}'
Puedes enviar hasta 100 fechas por request. Se ignoran duplicados, así que si corres el script dos veces no hay problema.
Usar el calendario en los cálculos
Desde ese momento, cualquier endpoint de días hábiles acepta el parámetro ?calendar=slug:
# ¿El 15 de julio es hábil en la Planta Norte?
curl "https://api.feriados.io/v1/CL/is-business-day?date=2026-07-15&calendar=planta-norte" \
-H "Authorization: Bearer frd_tu_key"
{
"success": true,
"data": {
"date": "2026-07-15",
"is_business_day": false,
"day_of_week": "Wednesday",
"region": null
},
"meta": { "country": "CL", "calendar": "planta-norte", "total": 1 }
}
Miércoles 15 de julio es un día de semana sin feriado oficial en Chile, pero la API devuelve false porque está en el calendario de la planta. Sin el parámetro ?calendar, devolvería true.
Casos de uso concretos
Cron jobs que respetan el calendario de empresa
const API = "https://api.feriados.io/v1";
const HEADERS = { Authorization: `Bearer ${process.env.FERIADOS_API_KEY}` };
async function esHabilHoy(pais, calendario) {
const hoy = new Date().toISOString().slice(0, 10);
const url = `${API}/${pais}/is-business-day?date=${hoy}&calendar=${calendario}`;
const { data } = await fetch(url, { headers: HEADERS }).then(r => r.json());
return data.is_business_day;
}
// En tu cron de nómina
if (await esHabilHoy("CL", "planta-norte")) {
await procesarNomina();
} else {
console.log("Planta cerrada — nómina se pospone");
}
Fechas de entrega que evitan el cierre
async function proximaFechaEntrega(pais, calendario, diasHabiles = 3) {
const hoy = new Date().toISOString().slice(0, 10);
const url = `${API}/${pais}/business-days/add?date=${hoy}&days=${diasHabiles}&calendar=${calendario}`;
const { data } = await fetch(url, { headers: HEADERS }).then(r => r.json());
return data.result_date;
}
// El pedido se hace el 14 de julio — ¿cuándo llega considerando el cierre de planta?
const entrega = await proximaFechaEntrega("CL", "planta-norte", 3);
// → "2026-07-21" en lugar de "2026-07-17" (saltea el 15/jul)
Días hábiles reales entre dos fechas
// ¿Cuántos días hábiles de empresa hubo en julio?
const res = await fetch(
`${API}/CL/business-days/between?from=2026-07-01&to=2026-07-31&calendar=planta-norte`,
{ headers: HEADERS }
);
const { data } = await res.json();
// data.business_days excluye feriados oficiales + la mantención del 15
Gestionar varios calendarios
Si tu empresa opera en múltiples países o plantas, puedes tener un calendario por contexto y elegir cuál aplicar en cada request:
const CALENDARIOS = {
CL: "planta-santiago",
CO: "planta-bogota",
PE: "planta-lima",
};
async function calcularDeadline(pais, fecha, dias) {
const cal = CALENDARIOS[pais];
const params = cal ? `&calendar=${cal}` : "";
const url = `${API}/${pais}/business-days/add?date=${fecha}&days=${dias}${params}`;
const { data } = await fetch(url, { headers: HEADERS }).then(r => r.json());
return data.result_date;
}
Cada planta tiene sus propios cierres. La lógica del código no cambia — solo el slug del calendario.
Mantener los calendarios actualizado
Al inicio del año, o cuando se confirman los cierres, un script de upsert es suficiente:
# Agregar fechas del próximo año (los duplicados se ignoran automáticamente)
curl -X POST https://api.feriados.io/v1/calendars/planta-norte/dates \
-H "Authorization: Bearer frd_tu_key" \
-H "Content-Type: application/json" \
-d '{
"dates": [
{ "date": "2027-07-14", "name": "Mantención anual 2027" },
{ "date": "2027-12-26", "name": "Cierre de año 2027" },
{ "date": "2027-12-27", "name": "Cierre de año 2027" }
]
}'
Y si una fecha cambia, la eliminas y agregas la correcta:
# Cambió la mantención al 16
curl -X DELETE https://api.feriados.io/v1/calendars/planta-norte/dates/2027-07-14 \
-H "Authorization: Bearer frd_tu_key"
curl -X POST https://api.feriados.io/v1/calendars/planta-norte/dates \
-H "Authorization: Bearer frd_tu_key" \
-H "Content-Type: application/json" \
-d '{"dates": [{"date": "2027-07-16", "name": "Mantención anual 2027"}]}'
Sin deploys, sin modificar variables de entorno, sin coordinar entre equipos.
Los calendarios personalizados están disponibles desde el plan Starter. El plan Free incluye 1 calendario con hasta 10 fechas futuras para probar. Ver planes y límites →
Ver también: Documentación de calendarios personalizados → · SLA en días hábiles para LATAM → · Cron jobs y feriados →