Portafolio Profesional
Portafolio profesional desarrollado para centralizar experiencia, habilidades, proyectos, servicios y contenido técnico en una plataforma moderna y escalable.
|
Backend Developer | Desarrollo de APIs seguras, automatización y soluciones backend escalables | Python • PHP • NestJs • NextJs • React • MySQL • PostgreSQL • AWS • Git • Linux | Divulgando conocimiento para todos

Experiencia y Skills
Experiencia profesional, formación académica y habilidades técnicas conectadas con soluciones backend, APIs e infraestructura.
Profesional independiente · Híbrido
jul 2024 - actualidad · 2 años 1 mes
Villahermosa, Tabasco, México
Desde 2024 he trabajado de manera independiente desarrollando solucion...
sep 2018 - actualidad · 7 años 11 meses
Villahermosa, Tabasco, México
Desde 2018, brindo servicios tecnológicos y soporte técnico especializ...
1/5
Skills
1/5
Sobre mí
Backend, APIs, automatización e infraestructura pensada para resolver problemas reales.
Backend Developer enfocado en el desarrollo de APIs seguras, automatización de procesos y soluciones escalables. Me apasiona construir sistemas eficientes, desde la lógica del servidor y la arquitectura backend hasta la integración con bases de datos y servicios en la nube.
He participado en proyectos académicos y tecnológicos relacionados con plataformas digitales, marketplaces y soluciones orientadas a innovación y tecnología. Además, disfruto compartir contenido técnico sobre backend, bases de datos, APIs y arquitectura de software. Actualmente continúo fortaleciendo mis conocimientos y desarrollando soluciones modernas y escalables.
Cliente
API
Backend
DB
Cloud
Paso 1
Una persona entra a tu sitio, inicia sesión o realiza una acción.
Servicios
Servicios enfocados en backend, APIs, bases de datos, infraestructura cloud y mantenimiento de aplicaciones.
Proyectos
Una selección de proyectos donde aplico backend, APIs, bases de datos, infraestructura y desarrollo full stack.
Blog
Publicaciones técnicas sobre backend, APIs, bases de datos, seguridad, arquitectura y desarrollo de software.
Abres Google Maps. Escribes tu destino. Presionas buscar. Y en apenas unos segundos aparecen: 📍 Tu ubicación. 🛣️ Varias rutas posibles. ⏱️ El tiempo estimado. 🚦 El tráfico. 🚗 Rutas alternativas. 🚧 Avisos sobre incidentes o restricciones. Todo parece inmediato. Pero detrás de ese mapa hay mucho más que una imagen con calles. 👉 Hay sistemas procesando datos geográficos, tráfico, ubicaciones y rutas constantemente para responder una pregunta aparentemente sencilla: “¿Cómo llego hasta ahí?” 🧠 ¿Qué ocurre cuando buscas un lugar? Supongamos que escribes: Aeropuerto de Cancún Para una persona, ese texto tiene un significado claro. Pero una computadora necesita convertirlo en información que pueda procesar. Una de las primeras tareas consiste en identificar qué lugar estás buscando y asociarlo con una posición geográfica. Este proceso está relacionado con la geocodificación . Conceptualmente: "Aeropuerto de Cancún" ↓ Buscar lugar ↓ Identificar ubicación ↓ Latitud y longitud El resultado puede ser algo parecido a: 21.0365, -86.8771 Ahora el sistema ya no trabaja solamente con un nombre. Tiene un punto concreto sobre la Tierra. 📍 ¿Qué son la latitud y longitud? La mayoría de los sistemas de mapas representan ubicaciones mediante coordenadas. Por ejemplo: Latitud: 21.0365 Longitud: -86.8771 La latitud indica la posición de norte a sur. La longitud indica la posición de este a oeste. Con ambas coordenadas es posible representar una ubicación bastante precisa. Así, nombres como: Mi casa Aeropuerto Restaurante Hotel terminan convirtiéndose internamente en coordenadas que los sistemas pueden utilizar para realizar cálculos. 🔎 Pero buscar un lugar no siempre es tan sencillo Imagina que escribes: San José Puede existir más de un lugar con ese nombre. Entonces el sistema puede necesitar considerar otros datos: Tu ubicación actual. El país. El historial de búsqueda. Lugares cercanos. Popularidad. Contexto de la consulta. El objetivo es intentar determinar qué lugar querías encontrar realmente. Por eso una búsqueda geográfica no consiste únicamente en comparar texto. 🔄 También existe la geocodificación inversa Puede ocurrir el proceso contrario. Tu teléfono conoce tus coordenadas: 17.9894, -92.9475 pero necesitas mostrar una dirección comprensible. Entonces el sistema puede convertir: Coordenadas ↓ Calle ↓ Ciudad ↓ Estado ↓ País A este proceso se le conoce como geocodificación inversa . Es útil para mostrar información como: "Estás cerca de Avenida..." en lugar de obligarte a leer números de latitud y longitud. 🛰️ ¿Cómo sabe dónde estás? Tu teléfono puede determinar su ubicación utilizando varias fuentes. Por ejemplo: 🛰️ GPS. 📶 Redes Wi-Fi. 📡 Redes móviles. 📍 Información del dispositivo. Dependiendo del entorno, estas señales pueden combinarse para obtener una ubicación estimada. El sistema operativo entrega esa información a la aplicación si tiene los permisos necesarios. Entonces Google Maps puede trabajar con algo parecido a: Origen: 17.9894, -92.9475 Destino: 21.0365, -86.8771 Ahora ya conoce los dos extremos del problema. 🛣️ ¿Cómo representa Google Maps las calles? Aquí empieza una de las partes más interesantes. Para un sistema de rutas, una ciudad puede representarse como un enorme grafo . Un grafo está formado principalmente por: Nodos + Conexiones Podemos imaginar las intersecciones como nodos. Y las carreteras como conexiones. Por ejemplo: A ───── B │ │ │ │ C ───── D Cada letra puede representar una intersección. Cada línea representa una calle que permite viajar entre ellas. ⚙️ Las conexiones tienen información adicional Una carretera no es solamente: A → B También puede tener información asociada. Por ejemplo: Distancia: 2.4 km Velocidad estimada: 50 km/h Sentido: una dirección Peaje: no Tipo: avenida También pueden existir reglas como: No girar a la izquierda Carretera cerrada Acceso restringido Solo transporte público Toda esa información puede modificar qué rutas son válidas. 🚦 La mejor ruta no siempre es la más corta Imagina dos opciones. Ruta A 10 km Ruta B 13 km A simple vista podríamos elegir la A. Pero ahora agregamos tráfico: Ruta A 10 km 45 minutos Ruta B 13 km 25 minutos Entonces la ruta más larga puede ser mejor. Por eso los sistemas de navegación no buscan únicamente minimizar distancia. Pueden intentar minimizar: Tiempo estimado considerando las condiciones actuales. 🧠 El problema se parece a buscar un camino dentro de un grafo Conceptualmente tenemos: Origen ↓ Miles de posibles caminos ↓ Destino El sistema necesita encontrar una ruta conveniente entre ambos puntos. En informática existen algoritmos clásicos para resolver problemas de caminos, como: Dijkstra. A*. Pero una plataforma a escala global necesita muchas optimizaciones adicionales para responder rápidamente sobre redes viales gigantescas. La idea esencial sigue siendo: 👉 explorar posibles caminos y encontrar uno con un costo conveniente. 💰 ¿Qué significa “costo” en una ruta? En algoritmos de grafos, cada conexión puede tener un costo. Podría ser simplemente: Distancia Pero en navegación real puede representar una combinación de factores. Por ejemplo: Tiempo de viaje + Tráfico + Restricciones + Tipo de vía + Peajes Dependiendo de tus preferencias. Por ejemplo, si activas: Evitar autopistas el costo o la disponibilidad de ciertas carreteras puede cambiar. Si seleccionas: Evitar peajes el sistema busca rutas diferentes. 🚗 El medio de transporte cambia completamente el problema La ruta correcta depende de cómo estés viajando. No es lo mismo: 🚗 Automóvil. 🚶 Caminar. 🚲 Bicicleta. 🚌 Transporte público. Una carretera puede ser excelente para un automóvil pero imposible para un peatón. Una calle puede permitir bicicletas pero tener restricciones para vehículos. Entonces el sistema puede trabajar con redes y reglas diferentes dependiendo del modo seleccionado. 🚶 Una ruta caminando Si eliges caminar, puede considerar: Banquetas Cruces Puentes peatonales Senderos Escaleras que quizá no formen parte de una ruta para automóvil. 🚲 Una ruta en bicicleta Podría considerar: Ciclovías Pendientes Calles permitidas Infraestructura ciclista dependiendo de los datos disponibles. 🚌 Transporte público Aquí el problema se vuelve todavía más interesante. Ahora no basta con saber dónde están las calles. También necesitas: Rutas de autobús Paradas Horarios Estaciones Transbordos Entonces una ruta puede ser: Caminar 500 m ↓ Tomar autobús ↓ Viajar 7 paradas ↓ Cambiar de línea ↓ Caminar 300 m El backend necesita combinar múltiples tipos de información. 🚦 ¿Cómo sabe dónde hay tráfico? Una ruta puede ser correcta geográficamente y aun así ser terrible por tráfico. Por eso Google Maps puede utilizar diferentes fuentes de información para estimar cómo se están moviendo las carreteras. El sistema puede detectar que normalmente un tramo debería recorrerse en: 5 minutos pero actualmente está tardando: 20 minutos Eso indica que existe una condición diferente a la habitual. 📱 Los dispositivos pueden ayudar a estimar movimiento Los teléfonos y dispositivos que comparten cierta información de ubicación de manera agregada pueden contribuir a estimar cómo se mueve el tráfico. Imagina muchos dispositivos desplazándose sobre la misma avenida. Si normalmente avanzan a: 50 km/h pero ahora la mayoría se mueve a: 8 km/h el sistema puede inferir que existe congestión. Naturalmente, plataformas de este tipo también pueden combinar otras fuentes y modelos para mejorar las estimaciones. 🕒 También existe tráfico histórico No toda predicción depende únicamente de lo que está ocurriendo en este segundo. El sistema puede conocer patrones históricos. Por ejemplo: Lunes 8:00 AM ↓ Esta avenida normalmente tiene tráfico Mientras: Domingo 6:00 AM ↓ Normalmente está despejada Entonces el tiempo estimado puede combinar: Condiciones actuales + Patrones históricos + Características de la ruta Eso ayuda a estimar mejor cuánto tardarás. ⏱️ ¿Cómo calcula el tiempo estimado? Supongamos una ruta dividida en varios segmentos. Segmento A 5 minutos Segmento B 8 minutos Segmento C 4 minutos El sistema puede combinar esos tiempos: 5 + 8 + 4 = 17 minutos Pero la realidad es más compleja. Los tiempos pueden variar constantemente. Por eso el ETA, o Estimated Time of Arrival , puede actualizarse mientras conduces. 🚀 ¿Por qué cambia el tiempo durante el viaje? Empiezas con: Llegada: 15:40 Después: Llegada: 15:46 Y más adelante vuelve a: 15:42 No necesariamente significa que el sistema estuviera “equivocado”. Las condiciones pueden estar cambiando. Por ejemplo: Tráfico nuevo Accidente Carretera despejada Cambio de velocidad Ruta diferente El sistema recalcula continuamente utilizando información más reciente. 🔄 ¿Por qué puede ofrecer una ruta nueva mientras conduces? Imagina que empezaste con: Ruta A 30 minutos Unos minutos después ocurre un accidente. Ahora: Ruta A 50 minutos Pero existe otra alternativa: Ruta B 35 minutos El sistema vuelve a evaluar las posibilidades. Entonces puede mostrar: “Se encontró una ruta más rápida.” Conceptualmente: Ruta actual ↓ Condiciones cambian ↓ Recalcular ↓ Comparar alternativas ↓ Ofrecer nueva ruta 🚧 Accidentes, cierres y restricciones No toda modificación viene del tráfico. También pueden existir eventos como: Accidente Carretera cerrada Obras Inundación Restricción temporal Si esa información llega al sistema, puede modificar inmediatamente el grafo utilizado para calcular rutas. Por ejemplo: A ───── B X │ C Si una conexión deja de estar disponible, el algoritmo tiene que buscar otro camino. ↩️ Los sentidos de circulación también importan Imagina: Calle A pero solamente permite conducir: → No puedes tratarla como: ↔ El grafo debe representar esta restricción. Lo mismo ocurre con: No girar No retorno Solo vuelta derecha La ruta tiene que ser legal y físicamente posible, no solamente corta. 🗺️ ¿El teléfono descarga todo el mapa del mundo? No. Sería completamente innecesario. Tu dispositivo necesita principalmente información relacionada con la zona que estás viendo y utilizando. Cuando mueves el mapa: Zona actual ↓ Usuario desplaza ↓ Solicitar nueva información Se descargan los datos necesarios para representar esa nueva región. Esto permite trabajar con mapas enormes sin cargar todo el planeta en memoria. 🧩 El mapa puede dividirse en pequeñas secciones Los sistemas de mapas suelen dividir la superficie en tiles o fragmentos. Conceptualmente: ┌────┬────┬────┐ │ A │ B │ C │ ├────┼────┼────┤ │ D │ E │ F │ ├────┼────┼────┤ │ G │ H │ I │ └────┴────┴────┘ Si estás viendo: E quizá la aplicación también prepare: B D F H porque podrías desplazarte hacia ellas. Así la interfaz se siente fluida. 🔍 El nivel de zoom también cambia lo que necesitas Cuando estás muy alejado, quizá solo necesitas: Países Estados Carreteras principales Pero al acercarte: Calles Negocios Edificios Puntos de interés Mostrar absolutamente todo desde el principio sería innecesario. El sistema entrega más detalle conforme aumenta el zoom. 📍 Buscar lugares es otro problema diferente Cuando escribes: pizza Google Maps no solamente necesita encontrar coordenadas. También debe buscar negocios o puntos de interés relacionados. Puede considerar cosas como: Distancia Coincidencia de nombre Categoría Relevancia Horario entre otros factores. Entonces: Buscar un lugar y: Calcular una ruta son problemas diferentes que trabajan juntos. 🏪 Información de lugares Una ubicación puede tener datos como: Nombre Dirección Coordenadas Categoría Horario Teléfono Y posiblemente otra información asociada. Cuando seleccionas el lugar, esos datos pueden provenir de servicios distintos de los que calculan la ruta. La aplicación los presenta como si todo fuera una sola cosa. 🧠 Una sola pantalla puede utilizar muchos servicios Cuando ves una ruta, detrás pueden existir sistemas especializados en: Geocodificación ↓ Búsqueda de lugares ↓ Mapas ↓ Ruteo ↓ Tráfico ↓ ETA La interfaz integra todos esos resultados. Por eso una aplicación moderna puede parecer sencilla aunque internamente dependa de muchos componentes. 📡 ¿Todo se calcula desde el backend? No necesariamente todo. El dispositivo también realiza trabajo. Por ejemplo: Renderizar mapa Mostrar animaciones Dibujar ruta Actualizar interfaz Obtener ubicación Pero operaciones que requieren enormes cantidades de datos globales suelen apoyarse fuertemente en infraestructura backend. El teléfono no necesita tener almacenadas todas las calles, condiciones de tráfico y lugares del mundo. 🚘 ¿Qué pasa mientras conduces? Tu dispositivo puede enviar actualizaciones de ubicación periódicamente. Conceptualmente: Ubicación 1 ↓ Ubicación 2 ↓ Ubicación 3 ↓ Ubicación 4 La aplicación compara tu posición con la ruta. Si continúas correctamente: Seguir indicaciones Si te desvías: Ubicación ya no coincide ↓ Recalcular ↓ Nueva ruta Todo ocurre casi automáticamente. ↪️ ¿Cómo sabe cuándo decirte “gira a la derecha”? La ruta no es solamente una línea. Puede estar compuesta por instrucciones. Por ejemplo: Avanza 2 km ↓ Gira a la derecha ↓ Continúa 500 m ↓ Toma la salida La aplicación conoce la geometría de la ruta y tu posición aproximada. Entonces puede determinar cuándo estás cerca de una maniobra y mostrar la instrucción correspondiente. 📍 La ubicación nunca es perfectamente exacta Otro detalle importante: El GPS tiene margen de error. Tu teléfono podría estimar que estás en: Punto A cuando realmente estás algunos metros más adelante. En una carretera con varias calles paralelas esto puede crear problemas. Por eso las aplicaciones de navegación necesitan interpretar la ubicación y asociarla con una vía probable. Esto puede relacionarse con técnicas de map matching . 🛣️ ¿Qué es map matching? Supongamos que el GPS devuelve: • ligeramente fuera de la carretera. El sistema puede determinar: “Probablemente el usuario realmente está sobre esta vía.” Entonces ajusta conceptualmente: GPS aproximado ↓ Carretera más probable ↓ Posición utilizada para navegación Esto ayuda a que la ruta no salte constantemente entre calles cercanas. 📴 ¿Y los mapas sin conexión? Cuando descargas un mapa offline, parte de la información geográfica necesaria se almacena localmente. Entonces puedes utilizar ciertas funcionalidades sin conexión. Pero algunas capacidades pueden verse limitadas porque no tienes acceso a información actualizada. Por ejemplo: Mapa base ✅ Rutas posibles ✅ Tráfico en tiempo real ❌ Cambios recientes ❌ dependiendo de lo que se haya descargado y de la funcionalidad disponible. 📦 Caché también ayuda No tendría sentido descargar continuamente el mismo fragmento del mapa. Por eso puede utilizarse caché. Por ejemplo: Solicitar zona ↓ Guardar temporalmente ↓ Usuario vuelve ↓ Reutilizar Esto reduce: Transferencias. Latencia. Uso de datos. Y mejora la experiencia. 🌎 El verdadero desafío es la escala Calcular una ruta dentro de una ciudad ya es interesante. Pero ahora imagina hacerlo para: Millones de usuarios simultáneamente. Cada uno tiene: Origen diferente Destino diferente Horario diferente Medio de transporte diferente Tráfico diferente El backend debe responder rápidamente a todas esas combinaciones. 📈 Los datos también cambian Una red vial no es estática. Constantemente pueden existir: Nuevas carreteras Calles cerradas Negocios nuevos Cambios de sentido Obras Nuevos accesos La plataforma necesita mantener sus datos actualizados. Una ruta perfecta utilizando datos antiguos puede convertirse en una ruta incorrecta. 🔄 Actualizar mapas es un proceso continuo Conceptualmente: Nuevos datos ↓ Validación ↓ Procesamiento ↓ Actualizar información geográfica ↓ Disponible para usuarios Por eso mantener un mapa global actualizado es un problema de datos además de un problema de visualización. ⚠️ Error común: pensar que Maps solo “dibuja calles” La interfaz visual es solamente una pequeña parte. Para responder: ¿Cómo llego? el sistema puede necesitar resolver: ¿Dónde estás? ¿Dónde está el destino? ¿Qué caminos existen? ¿Qué caminos puedes utilizar? ¿Cuánto tardaría cada uno? ¿Qué tráfico hay? ¿Qué ruta conviene ahora? Todo eso ocurre antes de dibujar una simple línea azul sobre la pantalla. 🛠️ ¿Qué podemos aprender de Google Maps como desarrolladores? Este tipo de sistema deja varias ideas interesantes. ✔️ Modelar correctamente los datos puede hacer posible resolver problemas muy complejos. ✔️ Los grafos son fundamentales para representar redes. ✔️ El resultado “óptimo” depende de qué métrica quieras optimizar. ✔️ Los datos en tiempo real pueden cambiar decisiones previamente correctas. ✔️ Dividir grandes cantidades de información en pequeñas partes facilita su entrega. ✔️ Caché y procesamiento distribuido ayudan a reducir latencia. ✔️ Una interfaz sencilla puede esconder múltiples servicios especializados. 🧩 La realidad Cuando escribes: “Aeropuerto de Cancún” y presionas: Cómo llegar el sistema necesita transformar una frase en todo un problema computacional. Conceptualmente: Texto ↓ Lugar ↓ Coordenadas ↓ Red de carreteras ↓ Rutas posibles ↓ Tráfico y restricciones ↓ Tiempo estimado ↓ Mejor alternativa ↓ Mapa Y después continúa repitiendo parte del proceso mientras conduces. Porque la mejor ruta de hace cinco minutos puede no ser la mejor ruta ahora. 💬 Un mapa digital no solamente necesita saber dónde están las calles. Necesita entender cómo están conectadas, cuánto cuesta recorrerlas y cómo están cambiando las condiciones en ese momento. 👉 La próxima vez que Google Maps diga: “Se encontró una ruta más rápida” recuerda que detrás probablemente se volvió a resolver el mismo problema con información más reciente. 🔥 El backend no se ve, pero sin él, nada funciona.
Imagina que tu aplicación necesita saber cuándo ocurre algo fuera de ella. Por ejemplo: 💳 Se confirma un pago. 📦 Cambia el estado de un pedido. 👤 Se registra un usuario en otro sistema. ☁️ Termina un procesamiento externo. Una forma de hacerlo sería preguntar constantemente: ¿Ya ocurrió? ¿Y ahora? ¿Ya? ¿Ya? Ese enfoque se conoce como polling . Funciona. Pero puede generar muchas peticiones innecesarias. 👉 Una alternativa mucho más eficiente es hacer que el otro sistema te avise automáticamente cuando ocurra algo importante. Ese es el principio detrás de los webhooks . 🧠 ¿Qué es un webhook? Un webhook es un mecanismo que permite que un sistema envíe una notificación HTTP a otro sistema cuando ocurre un evento. En lugar de que tu aplicación pregunte: ¿El pago ya fue aprobado? el proveedor puede decirte: El pago acaba de ser aprobado. Y enviar automáticamente esa información a tu servidor. Conceptualmente: Sistema externo ↓ Ocurre evento ↓ Webhook ↓ Tu backend Tu aplicación simplemente necesita estar preparada para recibir esa petición. 🌐 Polling vs webhook La diferencia puede verse fácilmente. Polling Tu aplicación ↓ ¿Cambió algo? ↓ No Tu aplicación ↓ ¿Cambió algo? ↓ No Tu aplicación ↓ ¿Cambió algo? ↓ Sí Tu sistema tiene que preguntar repetidamente. Webhook Tu aplicación ↓ Espera Sistema externo ↓ Ocurre evento ↓ Envía notificación ↓ Tu aplicación reacciona Aquí no necesitas realizar consultas continuamente. El otro sistema inicia la comunicación. ⚙️ ¿Cómo recibe un webhook tu aplicación? Primero necesitas crear un endpoint preparado específicamente para recibir estos eventos. Por ejemplo: POST /webhooks/pagos Después registras esa dirección en el proveedor externo. Conceptualmente: https://api.midominio.com/webhooks/pagos Cuando ocurre un evento importante, el proveedor realiza una petición HTTP hacia esa URL. 🚀 El flujo completo Supongamos que utilizas un proveedor externo para procesar pagos. El usuario realiza una compra. El flujo puede ser: Usuario ↓ Realiza pago ↓ Proveedor procesa ↓ Pago aprobado ↓ Proveedor envía webhook ↓ POST /webhooks/pagos ↓ Tu backend recibe evento ↓ Actualiza pedido El usuario no necesita estar esperando a que tu aplicación consulte constantemente al proveedor. 📦 ¿Qué información puede traer un webhook? Depende del proveedor. Pero podría enviar algo como: { "id": "evt_1842", "type": "payment.completed", "data": { "order_id": 1842, "status": "completed" } } Tu backend recibe el contenido. Después puede revisar: ¿Qué evento ocurrió? Por ejemplo: payment.completed Y ejecutar la lógica correspondiente. 💳 Ejemplo con un pago Supongamos que inicialmente tienes: Pedido #1842 Estado: pendiente El proveedor procesa el pago. Después envía: payment.completed Tu backend puede hacer: Webhook recibido ↓ Validar evento ↓ Buscar pedido 1842 ↓ Actualizar estado ↓ Pedido = pagado Y posteriormente podría iniciar otras tareas. Por ejemplo: Pedido pagado ├── Enviar correo ├── Preparar envío └── Generar factura 📦 Otro ejemplo: seguimiento de envíos Imagina que utilizas una empresa de paquetería. Tu sistema guarda: Pedido #500 Estado: enviado La paquetería podría enviarte eventos como: package.in_transit package.out_for_delivery package.delivered Entonces tu aplicación puede actualizar automáticamente: Enviado ↓ En tránsito ↓ En reparto ↓ Entregado sin estar preguntando constantemente por cada paquete. ☁️ Procesos que tardan mucho tiempo Los webhooks también son útiles cuando una operación tarda demasiado como para mantener una petición HTTP abierta. Por ejemplo: Generar video Procesar archivo Analizar documento Crear reporte Convertir imagen Tu aplicación puede iniciar el trabajo: POST /procesar y recibir: Procesamiento iniciado Después continúa haciendo otras cosas. Minutos más tarde, el sistema externo envía: processing.completed mediante webhook. 🧩 Esto permite procesos asíncronos En lugar de: Aplicación ↓ Solicitar procesamiento ↓ Esperar 5 minutos ↓ Respuesta puedes tener: Aplicación ↓ Solicitar procesamiento ↓ Continuar Y después: Servicio externo ↓ Proceso terminado ↓ Webhook ↓ Aplicación Esto es mucho más adecuado para operaciones largas. 🔐 Pero no puedes confiar en cualquier petición Aquí aparece una parte muy importante. Tu endpoint: POST /webhooks/pagos está preparado para recibir información. Pero ¿qué evita que otra persona haga una petición falsa? Por ejemplo: { "type": "payment.completed", "order_id": 1842 } Si tu backend confía únicamente en el cuerpo recibido, alguien podría intentar marcar pedidos como pagados sin haber realizado ningún pago. Por eso los webhooks deben validarse. 🛡️ Verificar la autenticidad del evento Muchos proveedores incluyen una firma criptográfica en la petición. Por ejemplo, mediante un header: Webhook-Signature: abc123... El proveedor y tu servidor comparten cierta información secreta. Tu backend utiliza esa información para comprobar que el mensaje realmente fue generado por el proveedor y que su contenido no fue modificado. Conceptualmente: Webhook recibido ↓ Leer firma ↓ Calcular firma esperada ↓ Comparar ↓ ¿Coincide? ├── Sí → procesar └── No → rechazar Este paso es crítico. ⚠️ HTTPS también es necesario Los webhooks deberían recibirse mediante: HTTPS y no mediante HTTP sin cifrado. Esto protege la comunicación mientras viaja por la red. Pero HTTPS y firma resuelven problemas diferentes. Podemos pensar: HTTPS ↓ Protege la comunicación Firma ↓ Ayuda a verificar el origen e integridad del evento Ambos son importantes. 🚀 ¿Qué pasa cuando el webhook llega correctamente? El proveedor necesita saber que tu servidor recibió el evento. Normalmente espera una respuesta HTTP exitosa. Por ejemplo: 200 OK o algún otro código exitoso según la integración. Conceptualmente: Proveedor ↓ Webhook ↓ Tu servidor ↓ Procesar ↓ 200 OK Con esa respuesta el proveedor puede considerar que la entrega fue aceptada. 💥 ¿Y si tu servidor está caído? Supongamos: Proveedor ↓ Webhook ↓ ❌ Tu servidor no responde El proveedor podría recibir: Timeout o: 500 Internal Server Error Muchos servicios implementan reintentos. Por ejemplo: Intento 1 → Error ↓ Esperar Intento 2 → Error ↓ Esperar más Intento 3 → Correcto Esto permite que una pequeña caída de tu servidor no haga que pierdas el evento inmediatamente. 🔁 Por eso un webhook puede llegar varias veces Este detalle es fundamental. Supongamos: Webhook llega ↓ Tu backend actualiza pedido ↓ Pero la respuesta 200 nunca llega al proveedor Desde el punto de vista del proveedor: No sé si lo recibió. Entonces puede enviarlo de nuevo. Ahora tu aplicación recibe: payment.completed por segunda vez. 👉 Por eso debes asumir que un webhook puede ser duplicado. 🔐 Aquí aparece nuevamente la idempotencia Supongamos que recibes: evento_id = evt_12345 La primera vez: ¿Ya procesé evt_12345? ↓ No ↓ Procesar ↓ Guardar evt_12345 La segunda: ¿Ya procesé evt_12345? ↓ Sí ↓ No volver a ejecutar efectos Así evitas situaciones como: Enviar dos correos Generar dos facturas Descontar inventario dos veces Un webhook confiable debe soportar duplicados. 🗄️ Guardar los eventos recibidos puede ser muy útil Una estrategia común consiste en registrar información como: event_id tipo fecha payload estado Por ejemplo: evt_12345 payment.completed 2026-08-15 procesado Esto permite: Detectar duplicados. Investigar errores. Auditar eventos. Reprocesar fallos. Saber qué ocurrió. Cuando una integración falla en producción, este historial puede ser extremadamente útil. ⚡ Conviene responder rápido Otro punto importante: No siempre deberías ejecutar toda la lógica pesada antes de responder al proveedor. Imagina: Webhook ↓ Generar factura ↓ Enviar correo ↓ Actualizar inventario ↓ Procesar reporte ↓ Esperar 15 segundos ↓ 200 OK El proveedor podría asumir que tu endpoint tardó demasiado y considerar la entrega fallida. Incluso podría hacer un reintento. 🚀 Una estrategia mejor Puedes hacer: Webhook recibido ↓ Validar firma ↓ Guardar evento ↓ Enviar a cola ↓ 200 OK Y después: Worker ↓ Procesar evento ↓ Actualizar datos ↓ Enviar correo ↓ Generar factura Así confirmas rápidamente la recepción y continúas el trabajo de forma asíncrona. 📬 Webhooks y colas funcionan muy bien juntos Conceptualmente: Proveedor ↓ Webhook ↓ Tu API ↓ Cola de mensajes ↓ Worker ↓ Procesamiento Esto permite desacoplar: Recepción del evento de: Procesamiento del evento Si el procesamiento tarda o falla, no necesitas mantener al proveedor esperando. ⚠️ Pero responder 200 demasiado pronto también puede ser peligroso Supongamos: Recibir webhook ↓ 200 OK ↓ Intentar guardar ↓ ❌ Base de datos falla Ahora el proveedor cree que todo está correcto. Pero tú perdiste el evento. Por eso una estrategia segura suele ser confirmar después de haber almacenado de forma confiable la información necesaria. Por ejemplo: Recibir ↓ Validar ↓ Persistir evento ↓ 200 OK ↓ Procesar después Así aunque el worker falle posteriormente, el evento ya quedó registrado. 🧩 ¿Qué pasa si el evento llega desordenado? Este es otro problema real. Imagina: Evento A: pedido_enviado Evento B: pedido_entregado Normalmente esperamos: Enviado ↓ Entregado Pero por problemas de red o reintentos podrías recibir: Entregado ↓ Enviado Si actualizas el estado ciegamente, podrías terminar regresando el pedido a un estado anterior. 🧠 No siempre puedes asumir el orden Tu procesamiento puede necesitar considerar: Timestamp del evento. Versión. Estado actual. Secuencia. Reglas del negocio. Por ejemplo: Estado actual = entregado Evento recibido = enviado Tal vez debas ignorarlo porque representa información anterior. Esto depende de la integración. ⏰ Los webhooks también pueden llegar tarde Un evento puede ocurrir a: 10:00 pero llegar a: 10:05 por problemas de red o reintentos. Por eso no siempre debes interpretar: Hora de recepción como: Hora en que ocurrió el evento Si el proveedor incluye un timestamp del evento, puede ser útil conservarlo. 💳 Un webhook tampoco siempre debe ser tu única fuente de verdad Imagina que recibes: payment.completed Dependiendo del nivel de riesgo de la operación, tu sistema puede decidir verificar adicionalmente el estado directamente con el proveedor. Por ejemplo: Webhook recibido ↓ Verificar firma ↓ Consultar operación al proveedor ↓ Confirmar estado ↓ Actualizar pedido No siempre es necesario. Pero en operaciones críticas puede utilizarse como capa adicional de validación. 🔎 También existe el problema del replay Supongamos que un atacante obtiene una petición válida previamente enviada. Después intenta reenviarla varias veces. Aunque la firma sea correcta, el evento es antiguo. Por eso algunos esquemas de firma también incluyen información temporal. El backend puede comprobar: Firma válida ✅ Timestamp reciente ✅ Evento no procesado ✅ antes de aceptarlo. 🧠 Webhook no es exactamente lo mismo que WebSocket Los nombres pueden confundir. Un webhook normalmente es: Servidor A ↓ Petición HTTP puntual ↓ Servidor B Un WebSocket mantiene una conexión bidireccional abierta: Cliente ↔ Servidor Los webhooks son especialmente útiles para comunicación servidor a servidor basada en eventos. No son una conexión permanente. 🧩 Tampoco es lo mismo que polling Podemos resumir: Polling Yo te pregunto constantemente. Webhook Tú me avisas cuando algo ocurre. WebSocket Mantenemos una conexión abierta para comunicarnos. Cada uno resuelve problemas diferentes. 🚀 Ejemplo completo con ecommerce Imagina este proceso: Usuario crea pedido ↓ Pedido = pendiente ↓ Redirigir a proveedor de pagos El proveedor procesa el pago. Después: Proveedor ↓ payment.completed ↓ POST /webhooks/payments Tu backend: 1. Recibe evento 2. Verifica firma 3. Revisa event_id 4. Guarda evento 5. Responde 200 6. Envía procesamiento a cola Después el worker: 7. Busca pedido 8. Confirma que no fue procesado 9. Marca pedido como pagado 10. Reserva o actualiza inventario 11. Genera factura 12. Envía confirmación Ahora tienes un flujo mucho más robusto. ⚠️ Error común: confiar en el frontend para confirmar pagos Imagina que después de pagar el proveedor redirige al navegador hacia: /compra-exitosa Y el frontend dice al backend: "El pago fue exitoso." Eso no debería ser suficiente para marcar una compra como pagada. El usuario controla el navegador. Podría intentar acceder directamente a esa URL. La confirmación debería venir desde una fuente confiable, como el proveedor mediante un webhook o una consulta verificada desde el backend. 🔄 ¿Qué ocurre si tu aplicación necesita reconsultar eventos? Aunque los webhooks reduzcan muchísimo el polling, algunos sistemas combinan ambas estrategias. Por ejemplo: Webhook = mecanismo principal pero también: Proceso periódico ↓ Buscar inconsistencias ↓ Consultar proveedor Esto puede funcionar como mecanismo de reconciliación si algún evento se perdió o quedó sin procesar. 🧾 Reconciliación Imagina: Proveedor: Pago 100 = completado Tu sistema: Pago 100 = pendiente Un proceso periódico puede detectar esa diferencia y corregirla. Esto es especialmente importante en sistemas financieros. Los webhooks son muy útiles. Pero diseñar pensando en recuperación y reconciliación aumenta la confiabilidad. 🔍 Observabilidad También necesitas saber qué está ocurriendo con tus webhooks. Conviene medir: Eventos recibidos Eventos válidos Eventos rechazados Duplicados Errores de procesamiento Tiempo de procesamiento Por ejemplo: Webhook payment.completed ↓ 500 errores en 10 minutos debería llamar inmediatamente la atención. 🚨 Alertas Puedes generar alertas cuando: Aumentan errores o: Se acumulan eventos pendientes o: No llegan webhooks durante demasiado tiempo si normalmente existe tráfico constante. Así puedes detectar fallos antes de que los usuarios los reporten. 🧪 ¿Qué deberías probar? No pruebes únicamente: Webhook válido ↓ 200 OK También escenarios como: Firma inválida Evento duplicado Evento fuera de orden Payload inválido Base de datos caída Worker caído Procesamiento lento Evento antiguo Los casos difíciles son precisamente los que suelen aparecer en producción. 🛠️ Buenas prácticas ✔️ Utiliza HTTPS. ✔️ Verifica la firma o mecanismo de autenticidad proporcionado por el proveedor. ✔️ No confíes únicamente en el contenido del payload. ✔️ Guarda un identificador único del evento. ✔️ Diseña el procesamiento para soportar duplicados. ✔️ Registra los eventos recibidos. ✔️ Responde rápidamente después de asegurar la recepción. ✔️ Utiliza colas para trabajos pesados. ✔️ Considera que los eventos pueden llegar tarde o fuera de orden. ✔️ Implementa monitoreo y alertas. 🧩 La realidad La idea de un webhook parece sencilla: Ocurre algo ↓ Enviar POST Pero construir una integración confiable requiere pensar en muchas más cosas. ¿Quién envió el evento? ¿Ya lo procesé? ¿Y si llega dos veces? ¿Y si llega tarde? ¿Y si mi servidor está caído? ¿Y si el procesamiento falla? Ese es el verdadero reto. Los webhooks permiten que diferentes sistemas reaccionen a eventos sin estar consultándose constantemente. Pero la confiabilidad depende de cómo recibes, validas y procesas esos eventos. 💬 Una buena integración no necesita preguntar continuamente si algo cambió. Puede estar preparada para recibir el cambio, validarlo y reaccionar cuando ocurra. 👉 La próxima vez que un pago cambie automáticamente de "pendiente" a "confirmado" sin que actualices manualmente la página, probablemente haya existido algún mecanismo basado en eventos trabajando detrás. 🔥 El backend no se ve, pero sin él, nada funciona.
Abres una aplicación. Consultas tu perfil. Ves tus pedidos. Actualizas una dirección. Creas un nuevo registro. Cada una de esas acciones puede provocar una petición distinta hacia el backend. Por ejemplo: GET /usuarios/25 GET /usuarios/25/pedidos POST /pedidos PATCH /usuarios/25 Pero... 👉 ¿Qué representan realmente esas direcciones? Son endpoints . Y son una de las formas principales en las que una API organiza el acceso a sus recursos. 🧠 ¿Qué es un endpoint? Un endpoint es un punto específico dentro de una API al que un cliente puede enviar una petición. Normalmente combina: Método HTTP + Ruta Por ejemplo: GET /productos puede significar: 👉 Obtener una lista de productos. Mientras que: POST /productos puede utilizarse para crear uno nuevo. La ruta es la misma: /productos pero la operación cambia dependiendo del método HTTP utilizado. ⚙️ ¿Qué representa realmente una ruta? En una API REST es común organizar las rutas alrededor de recursos . Por ejemplo: /usuarios /productos /pedidos /pagos Cada uno representa un tipo de información que existe dentro del sistema. Después, los métodos HTTP indican qué queremos hacer con esos recursos. Por ejemplo: GET /productos puede significar: Consultar productos Mientras que: POST /productos puede significar: Crear producto Y: DELETE /productos/25 puede indicar: Eliminar producto 25 Esto hace que la API sea más predecible. 📦 Recursos y colecciones Una ruta como: /productos normalmente representa una colección . Es decir: Producto 1 Producto 2 Producto 3 Producto 4 ... Mientras que: /productos/25 representa un recurso específico. En este caso: Producto con ID 25 Así podemos tener: GET /productos ↓ Obtener colección y: GET /productos/25 ↓ Obtener un producto 🚀 Un ejemplo completo Supongamos que tenemos una tienda en línea. Cuando el usuario entra al catálogo, el frontend podría enviar: GET /productos El backend responde con una lista. Después el usuario selecciona el producto 42. Entonces: GET /productos/42 Cuando agrega productos y crea un pedido: POST /pedidos Y si posteriormente consulta ese pedido: GET /pedidos/850 Cada endpoint representa una entrada concreta hacia una parte del sistema. 🧩 ¿Qué ocurre dentro del backend? Cuando llega una petición como: GET /usuarios/25 el servidor necesita encontrar qué parte del código debe procesarla. Conceptualmente: Request ↓ Router ↓ Controller ↓ Service ↓ Base de datos ↓ Response La arquitectura exacta depende del framework. Pero normalmente existe un componente de enrutamiento que revisa: Método = GET Ruta = /usuarios/25 y decide qué función debe ejecutarse. 🛣️ El router El router funciona como una especie de mapa. Puede tener reglas conceptualmente parecidas a: GET /usuarios/:id → obtenerUsuario() POST /usuarios → crearUsuario() DELETE /usuarios/:id → eliminarUsuario() Cuando llega: GET /usuarios/25 el router reconoce que: 25 corresponde al parámetro: id y envía la petición hacia la lógica correspondiente. 🔢 Parámetros de ruta Los valores que aparecen dentro de una URL pueden utilizarse para identificar recursos. Por ejemplo: GET /usuarios/25 Aquí: 25 es un parámetro de ruta. Podríamos expresarlo como: /usuarios/{id} Entonces: id = 25 Otro ejemplo: GET /productos/900 significa: id = 900 Estos parámetros permiten crear rutas dinámicas sin definir un endpoint diferente para cada registro. 🧬 Recursos relacionados También podemos representar relaciones. Por ejemplo: GET /usuarios/25/pedidos Esto puede interpretarse como: 👉 Obtener los pedidos pertenecientes al usuario 25. Conceptualmente: Usuario 25 ↓ Pedidos Entonces la URL ya comunica bastante información por sí sola. Eso ayuda a que la API sea intuitiva. ⚠️ Pero no conviene anidar demasiado Podríamos terminar creando algo como: /usuarios/25/pedidos/80/productos/15/comentarios/2 Aunque técnicamente puede funcionar, empieza a ser difícil de mantener y entender. Muchas veces una ruta más directa puede ser mejor. Por ejemplo: /pedidos/80 o: /pedidos/80/productos La estructura debe representar relaciones útiles sin convertir la URL en una cadena interminable. 🔎 Query Parameters No toda la información debe ir dentro de la ruta. También existen los query parameters . Por ejemplo: GET /productos?categoria=laptops Aquí: categoria=laptops no identifica necesariamente un producto específico. Sirve para filtrar la colección. También podríamos tener: GET /productos?pagina=2 o: GET /productos?orden=precio Los query parameters suelen utilizarse para: Filtros. Ordenamiento. Paginación. Búsquedas. Opciones adicionales. 🚀 Un ejemplo con filtros Supongamos: GET /productos devuelve todos los productos. Pero queremos solamente los disponibles. Podríamos hacer: GET /productos?disponible=true Después queremos ordenarlos: GET /productos?disponible=true&orden=precio Así mantenemos el recurso: /productos y utilizamos parámetros para modificar la consulta. 🧠 Los métodos HTTP Los métodos HTTP ayudan a expresar qué tipo de acción se quiere realizar. Los más comunes son: GET POST PUT PATCH DELETE Cada uno tiene un propósito diferente. 🔎 GET Se utiliza principalmente para consultar información. Por ejemplo: GET /usuarios o: GET /usuarios/25 Una petición GET debería limitarse a recuperar datos. No debería utilizarse para modificar información importante. ➕ POST Suele utilizarse para crear recursos. Por ejemplo: POST /usuarios con un cuerpo: { "nombre": "Herman", "email": "correo@email.com" } El backend procesa la información y crea el nuevo usuario. ✏️ PUT PUT suele utilizarse para reemplazar o actualizar un recurso completo según el contrato de la API. Por ejemplo: PUT /usuarios/25 podría enviar toda la representación actualizada del usuario. 🩹 PATCH PATCH suele utilizarse cuando queremos actualizar solamente ciertos campos. Por ejemplo: PATCH /usuarios/25 con: { "nombre": "Nuevo nombre" } Solo se modifica esa propiedad. 🗑️ DELETE Se utiliza para eliminar un recurso. Por ejemplo: DELETE /usuarios/25 indica que queremos eliminar el usuario 25. El backend todavía debe verificar si esa operación está permitida. ⚠️ El método no sustituye las validaciones Que alguien envíe: DELETE /usuarios/25 no significa que el backend tenga que eliminarlo inmediatamente. Primero puede verificar: ¿Existe? ↓ ¿Usuario autenticado? ↓ ¿Tiene permisos? ↓ ¿Puede eliminar este recurso? Los endpoints representan operaciones. Pero las reglas de seguridad y negocio continúan siendo responsabilidad del backend. 🔐 Un endpoint también debe controlar acceso Imagina: GET /usuarios/25 El servidor encuentra al usuario 25. Pero todavía debe preguntarse: ¿Quién está haciendo la petición? Tal vez ese endpoint solamente pueda ser utilizado por: Usuario 25 o por un administrador. Entonces el flujo podría ser: Request ↓ Autenticación ↓ Autorización ↓ Buscar usuario ↓ Responder Un endpoint bien diseñado no solamente encuentra datos. También protege quién puede utilizarlos. 📥 El cuerpo de la petición Algunos endpoints necesitan recibir información adicional. Por ejemplo: POST /pedidos podría enviar: { "productos": [ { "id": 25, "cantidad": 2 } ] } La ruta indica: /pedidos El método indica: POST Y el cuerpo contiene: Datos del nuevo pedido Estas tres partes trabajan juntas. 📤 La respuesta también forma parte del contrato El frontend necesita saber qué puede esperar. Por ejemplo: GET /productos/25 puede responder: { "id": 25, "nombre": "Laptop", "precio": 18000 } Pero si no existe: 404 Not Found Si no tiene permisos: 403 Forbidden Si ocurre un problema interno: 500 Internal Server Error Diseñar buenos endpoints también implica definir respuestas consistentes. 🚦 Los códigos HTTP ayudan a comunicar resultados Algunos códigos comunes son: 200 OK 201 Created 204 No Content 400 Bad Request 401 Unauthorized 403 Forbidden 404 Not Found 409 Conflict 500 Internal Server Error Por ejemplo: POST /usuarios si crea correctamente el recurso podría devolver: 201 Created Esto permite que el cliente entienda qué ocurrió sin depender únicamente del contenido de la respuesta. ⚠️ Error común: rutas como nombres de funciones Es común encontrar APIs con rutas como: /obtenerProductos /crearProducto /eliminarProducto /actualizarProducto Funcionan. Pero en un diseño REST suele ser más predecible utilizar: /productos y dejar que el método indique la acción. Por ejemplo: GET /productos POST /productos PATCH /productos/25 DELETE /productos/25 Esto hace que el diseño sea más uniforme. 🚫 Otro ejemplo poco consistente Imagina: GET /getUsers POST /new-product DELETE /removeOrder/25 PATCH /editCustomer/10 Cada endpoint utiliza una convención diferente. Un desarrollador tendría que memorizar cada ruta. Una estructura consistente sería más fácil: GET /usuarios POST /productos DELETE /pedidos/25 PATCH /clientes/10 La predictibilidad importa. 🧩 Sustantivos en lugar de verbos En REST normalmente las rutas representan recursos. Por eso suele preferirse: /productos en lugar de: /obtenerProductos porque el método HTTP ya representa la acción: GET Entonces: GET + /productos ya significa: Obtener productos ⚠️ Pero REST tampoco significa que nunca pueda haber acciones Hay operaciones que no encajan perfectamente en CRUD. Por ejemplo: POST /pedidos/25/cancelacion o alguna variante equivalente. La idea no es forzar artificialmente todo. El objetivo es mantener una interfaz clara y coherente. Las reglas REST son una guía de diseño, no una competencia por crear la URL más "pura". 🧱 CRUD y endpoints Muchas APIs comienzan con operaciones CRUD: Create Read Update Delete que pueden mapearse a: POST GET PUT/PATCH DELETE Por ejemplo: POST /productos ↓ Create GET /productos/25 ↓ Read PATCH /productos/25 ↓ Update DELETE /productos/25 ↓ Delete Esto crea una relación fácil de entender. 🔢 ¿Qué pasa con la versión de una API? Con el tiempo, una API puede cambiar. Por eso algunas utilizan rutas como: /api/v1/productos Y más adelante: /api/v2/productos El versionado ayuda a introducir cambios importantes sin romper inmediatamente a clientes que todavía utilizan la versión anterior. No todas las APIs necesitan exactamente esta estrategia, pero es una práctica común. 🌐 El frontend no necesita conocer el código interno Supongamos que el backend cambia completamente. Antes: Controller ↓ MySQL Después: Controller ↓ Service ↓ PostgreSQL ↓ Redis Si el contrato sigue siendo: GET /productos/25 y la respuesta mantiene el mismo formato, el frontend no debería necesitar saber que la implementación cambió. Este es uno de los beneficios más importantes de una API. 🤝 El endpoint funciona como un contrato El cliente necesita conocer: Ruta Método Datos de entrada Respuesta Posibles errores Por ejemplo: POST /usuarios puede establecer: Entrada: nombre email contraseña Respuesta: id nombre email Mientras ese contrato se mantenga, el equipo backend puede modificar muchos detalles internos. 📚 Por eso la documentación importa Una buena documentación debería explicar cada endpoint. Por ejemplo: GET /productos/{id} Parámetros id: Identificador del producto Respuesta { "id": 25, "nombre": "Laptop" } Errores 404 → producto no encontrado 401 → usuario no autenticado Esto hace que consumir la API sea mucho más sencillo. 🧪 Los endpoints también deben probarse No basta con probar: GET /productos/25 ↓ 200 OK También deberías comprobar: GET /productos/999999 ↓ 404 o: GET /usuarios/25 ↓ Usuario sin permisos ↓ 403 Y: POST /productos ↓ Datos inválidos ↓ 400 Una API tiene que comportarse correctamente tanto en escenarios exitosos como en errores. 📊 Un endpoint también puede necesitar paginación Imagina: GET /productos y tienes: 2,000,000 productos No deberías devolverlos todos en una sola respuesta. Puedes usar: GET /productos?page=1&limit=50 Entonces: /productos sigue siendo el recurso. Los parámetros controlan cómo queremos consultarlo. 🔎 Búsquedas También podrías tener: GET /productos?search=laptop El endpoint continúa representando productos. Simplemente estamos aplicando una condición. Esto suele ser más limpio que crear: /buscarProductoLaptop o rutas distintas para cada búsqueda. 📈 Ordenamiento Podríamos utilizar: GET /productos?sort=precio o: GET /productos?sort=-precio según la convención elegida. La idea es mantener una estructura consistente. 🛠️ Buenas prácticas ✔️ Utiliza nombres claros para los recursos. ✔️ Mantén una convención consistente entre endpoints. ✔️ Utiliza correctamente los métodos HTTP. ✔️ Usa parámetros de ruta para identificar recursos. ✔️ Utiliza query parameters para filtros, ordenamiento y paginación cuando tenga sentido. ✔️ Evita anidaciones excesivamente profundas. ✔️ Define respuestas y códigos HTTP consistentes. ✔️ Valida siempre la información recibida. ✔️ Protege cada endpoint con autorización cuando corresponda. ✔️ Documenta claramente el contrato. 🧩 La realidad Cuando el frontend envía: GET /usuarios/25/pedidos no está diciendo cómo debe funcionar internamente el backend. No sabe: Qué controlador existe Qué servicio se ejecuta Qué ORM utilizas Qué consulta SQL se genera Qué base de datos tienes Solo conoce una interfaz. El backend recibe la petición, interpreta la ruta y ejecuta toda la lógica necesaria detrás. Por eso los endpoints son una pieza fundamental en el diseño de APIs. 💬 Una API bien diseñada no solamente funciona. También permite que alguien pueda mirar: GET /usuarios/25/pedidos y tener una buena idea de lo que va a recibir. La consistencia hace que una API sea mucho más fácil de aprender, mantener e integrar. 👉 Cuando diseñes un endpoint, intenta pensar desde la perspectiva de quien va a consumirlo. Si necesita memorizar reglas completamente diferentes para cada ruta, probablemente todavía exista espacio para simplificar la API. 🔥 El backend no se ve, pero sin él, nada funciona.
Contacto
Escríbeme un mensaje por WhatsApp.
Mensaje rápido
Llena los campos y se abrirá WhatsApp con un mensaje listo para enviar.