El fin de semana pasado necesitaba un endpoint público para recibir envíos de formularios desde una landing page. Nada del otro mundo — aceptar un POST JSON, validar un par de campos, devolver una respuesta razonable. La cosa entera manejaría unas 50 peticiones por semana. No quería poner una tarjeta de crédito a fichero por un servidor de 20 $/mes, aprender una nueva herramienta de infra, ni esperar a una pipeline de CI cada vez que cambiase tres líneas. Diez minutos después de empezar, la API estaba en vivo en más de 300 ciudades y me costaba cero dólares. Esto es el paso a paso.
Cloudflare Workers
tiene un plan gratuito que es realmente generoso: 100.000 peticiones al día, sin tarjeta de crédito
para registrarse, y tu código corre en el borde en lugar de en una sola región. Para las APIs pequeñas
que necesitan la mayoría de los proyectos personales — receptores de webhooks, manejadores de
formularios, acortadores de enlaces, proxies JSON — puedes publicar y olvidarte. Esta guía te lleva
de "sin cuenta de Cloudflare" a "URL en vivo respondiendo a curl" en unos diez minutos.
Vamos a construir un endpoint real: un validador JSON que acepta un POST, comprueba el payload, y
devuelve una respuesta limpia.
Lo que obtienes gratis (y lo que no)
El plan gratuito de Cloudflare Workers te da 100.000 peticiones al día y 10 milisegundos de tiempo de CPU por petición. Suena justo hasta que te das cuenta de que la mayoría de los endpoints JSON — parsear cuerpo, hacer un poco de trabajo, devolver una respuesta — terminan cómodamente por debajo de 1ms. El techo de 10ms es tiempo de CPU, no wall-clock, así que un fetch upstream que tarde 800ms sigue contando como aproximadamente 1ms de CPU porque tu código está esperando principalmente a I/O.
Lo que no obtienes en el plan gratuito: almacenamiento persistente de alto throughput (Workers KV tiene su propia cuota gratuita — generosa para la mayoría de los casos, pero separada del contador de peticiones), payloads de respuesta grandes, o triggers cron programados con más frecuencia que una vez por minuto. Para un servicio típico de "recibir JSON, hacer algo, devolver JSON" que no necesite base de datos, no chocarás contra una pared.
Instalar Node.js y Wrangler
Wrangler es la CLI de Cloudflare para Workers. Instálala vía npm — necesitarás Node.js 18 o más reciente. Si ya tienes Node, esto es una sola línea:
npm install -g wrangler
# Verify
wrangler --version
# Should print 3.x or higherAhora inicia sesión. Esto abre un navegador para OAuth, crea la cuenta de Cloudflare si no la tienes, y guarda las credenciales localmente:
wrangler login
# Opens https://dash.cloudflare.com/oauth/authorize ...
# After you approve: "Successfully logged in."Andamiar el proyecto
Un comando y tienes un esqueleto de proyecto con valores por defecto sensatos — un handler
fetch de ejemplo, una config wrangler.toml, y el servidor de dev local
ya cableado:
npm create cloudflare@latest free-json-api
# When prompted, pick:
# "Hello World" Worker
# JavaScript (or TypeScript — your call)
# No deploy yet (we'll do that ourselves)
cd free-json-apiEl generador deja todo lo que necesitas en una sola carpeta. Abre src/index.js —
ese es el archivo que ejecuta tu Worker. Vamos a reemplazar su contenido por algo más útil que el
Hello World por defecto.
Escribir la API JSON
Aquí tienes un Worker completo que acepta un POST JSON, valida dos campos requeridos, y devuelve una respuesta limpia. Maneja los modos de fallo comunes — método incorrecto, JSON malformado, campos faltantes — en lugar de caerse en un 500 genérico:
export default {
async fetch(request) {
if (request.method !== 'POST') {
return Response.json(
{ error: 'POST only' },
{ status: 405 },
);
}
let body;
try {
body = await request.json();
} catch {
return Response.json(
{ error: 'Body must be valid JSON' },
{ status: 400 },
);
}
const { email, message } = body;
if (typeof email !== 'string' || typeof message !== 'string') {
return Response.json(
{ error: 'email and message are required (strings)' },
{ status: 422 },
);
}
return Response.json({
ok: true,
receivedAt: new Date().toISOString(),
echo: { email, message },
});
},
};Dos cosas que vale la pena señalar.
Response.json()
serializa el objeto y pone Content-Type: application/json por ti, así que no tienes que
acordarte del encabezado. Y envolver request.json() en un try/catch es el hábito más
importante al construir Workers — sin él, un payload malformado devuelve un 500 opaco del runtime
de Cloudflare en lugar de un 400 útil de tu código.
Probarlo localmente
Wrangler viene con un servidor de dev local que ejecuta el mismo isolate de V8 que Cloudflare usa en producción. Arráncalo con:
npm run dev
# ⛅️ wrangler 3.x
# [wrangler:inf] Ready on http://localhost:8787En otra terminal, atácalo con curl. Prueba primero el camino feliz, luego un
payload roto a propósito — deberías ver errores JSON limpios en lugar de stack traces:
# Happy path
curl -X POST http://localhost:8787 \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]","message":"hello"}'
# {"ok":true,"receivedAt":"2025-10-15T...","echo":{...}}
# Broken JSON (note the missing closing brace)
curl -X POST http://localhost:8787 \
-H "Content-Type: application/json" \
-d '{"email": "ava"'
# {"error":"Body must be valid JSON"}
# Missing required field
curl -X POST http://localhost:8787 \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]"}'
# {"error":"email and message are required (strings)"}Desplegar al mundo — un solo comando
Cuando lo local funciona, súbelo global:
npx wrangler deploy
# Total Upload: 1.18 KiB / gzip: 0.55 KiB
# Uploaded free-json-api (1.34 sec)
# Published free-json-api (4.21 sec)
# https://free-json-api.<your-subdomain>.workers.dev
# Current Deployment ID: ...Esa URL ya está en vivo en cada centro de datos de Cloudflare. Una petición desde Berlín
pega en Frankfurt, una desde Tokio pega en Tokio, una desde São Paulo pega en São Paulo — mismo
código, sin config extra. El bundle eran 1,2 KiB. Prueba la URL en vivo con los mismos comandos
curl que usaste localmente — solo cambia localhost:8787 por el hostname
workers.dev que Wrangler imprimió.
Cuándo se te quedará pequeño el plan gratuito
Durante mucho tiempo, no se te quedará. 100k peticiones/día son aproximadamente 1,15 peticiones por segundo de media en 24 horas — cómodamente más que lo que hacen la mayoría de los proyectos personales, herramientas internas o productos en fase temprana. Lo primero que normalmente te empuja fuera del plan gratuito no es el conteo de peticiones sino el almacenamiento: si empiezas a escribir mucho a KV, R2, o D1, esos tienen sus propias cuotas. El plan de pago arranca en 5 $/mes y te da 10 millones de peticiones, más CPU por petición, y una red de seguridad por tarjeta de crédito para picos. La mayoría de los proyectos no lo necesitan nunca.
Qué viene a continuación
Lo que has publicado es el Worker útil mínimo. Los endpoints reales en producción necesitan unos cuantos hábitos más — CORS para llamadores desde navegador, gestión de secretos para claves de API, caché en el borde para upstreams lentos, y una estrategia para proxear servicios upstream. He cubierto eso en Cloudflare Workers y JSON — Una guía práctica, que retoma donde este artículo termina.
Unas cuantas herramientas que mantengo abiertas mientras construyo Workers que manejan JSON: JSON Formatter para formatear bonito las respuestas, JSON Validator para averiguar exactamente por qué se rechazó un payload, y JSON Path para planificar la lógica de extracción de campos antes de escribirla. El formato JSON en sí está especificado en RFC 8259 — vale la pena echarle un vistazo cuando empieces a manejar entradas raras de usuarios reales.
Para patrones de Worker más profundos — almacenamiento KV, Durable Objects, triggers programados, los bindings de inferencia de IA — la propia galería de ejemplos de Workers de Cloudflare es el mejor recurso que he encontrado. Es una lista copy-pasteable de recetas para los siguientes pasos.
Para cerrar
Cloudflare Workers es ese raro plan gratuito que es realmente viable para proyectos personales reales. Sin tarjeta de crédito para empezar, 100k peticiones al día, y una historia de despliegue que cabe en un solo comando. El patrón de este artículo — aceptar JSON, validar, devolver JSON — cubre una cantidad sorprendente de lo que hacen la mayoría de las APIs. Si has estado posponiendo publicar una API pequeña porque la infra te parecía un coñazo, este es el camino que me habría gustado tomar hace tres años.