Casi todas las APIs del mundo tienen un endpoint llamado POST /search. Funciona. Pero es una mentira pequeña: HTTP dice que POST modifica algo, y una búsqueda no modifica nada. Después de 16 años sin métodos nuevos, HTTP por fin resolvió ese hueco.

En junio de 2026 el IETF publicó el RFC 10008: The HTTP QUERY Method. Es el primer método HTTP realmente nuevo desde PATCH, en 2010.

El problema: GET no alcanza, POST miente

La consulta típica de toda la vida se ve así:

GET /feed?q=foo&limit=10&sort=-published HTTP/1.1
Host: example.org

Sencillo, hasta que la consulta crece. El RFC enumera cuatro dolores concretos:

  • El límite de tamaño no se conoce. La petición pasa por proxies, CDNs y balanceadores que nadie coordinó entre sí. La recomendación mínima es soportar 8000 octetos, pero nadie te garantiza más.
  • Codificar datos estructurados en una URI es ineficiente. Filtros anidados, arrays, caracteres especiales… todo termina en un string ilegible.
  • Las URIs se registran en logs. Y en historiales, y en marcadores. El cuerpo de la petición, mucho menos.
  • Cada combinación de filtros se vuelve un recurso distinto. Lo cual rara vez es lo que querías modelar.

La salida clásica es usar POST:

POST /feed HTTP/1.1
Host: example.org
Content-Type: application/x-www-form-urlencoded

q=foo&limit=10&sort=-published

Resuelve el tamaño, pero rompe el contrato. Sin conocer la API por dentro, nada en el protocolo indica que esa operación es de solo lectura. Resultado: los intermediarios no cachean, los clientes no reintentan solos, y tu búsqueda se comporta como si fuera peligrosa.

QUERY: cuerpo de POST, semántica de GET

El mismo caso, con el método nuevo:

QUERY /contacts HTTP/1.1
Host: example.org
Content-Type: application/x-www-form-urlencoded
Accept: application/json

select=surname,givenname,email&limit=10

Igual que POST, la consulta viaja en el cuerpo. A diferencia de POST, el método es explícitamente seguro e idempotente. Eso habilita caché y reintentos automáticos sin que nadie tenga que documentarlo aparte.

Comparación rápida

  GET QUERY POST
Seguro Potencialmente no
Idempotente Potencialmente no
Cuerpo Sin semántica definida Esperado Esperado
Cacheable Solo para futuros GET/HEAD
URI para la consulta Sí, por definición Opcional (Location) No

Las reglas que hay que respetar

QUERY no es "POST pero bonito". El RFC es estricto en un punto: el servidor DEBE rechazar la petición si falta el Content-Type o si no coincide con el contenido. Nada de adivinar el tipo leyendo el cuerpo.

Los códigos recomendados para cuando algo sale mal:

  • 400 — falta el media type, o está declarado pero no corresponde al contenido real.
  • 415 — el media type es válido pero el recurso no lo soporta.
  • 422 — el formato está bien y la consulta se entiende, pero no se puede procesar. Por ejemplo, un SQL sintácticamente correcto que apunta a una tabla inexistente.
  • 406 — el cliente pidió un formato de respuesta que no manejas.

Descubrimiento: ¿este endpoint soporta QUERY?

Dos caminos. El clásico, con OPTIONS:

OPTIONS /contacts HTTP/1.1
Host: example.org

HTTP/1.1 200 OK
Allow: GET, QUERY, OPTIONS, HEAD

Y el nuevo: el RFC también registra la cabecera de respuesta Accept-Query, que anuncia qué formatos de consulta acepta el recurso.

HEAD /contacts HTTP/1.1
Host: example.org

HTTP/1.1 200 OK
Accept-Query: "application/jsonpath", application/sql

Ojo con un detalle: Accept-Query es un Structured Field (RFC 9651), no una cabecera de texto libre como Accept. Se parsea distinto. Y su valor aplica a todas las URIs del servidor que compartan el mismo path: el query string se ignora.

La parte elegante: guardar la consulta como URI

Aquí es donde QUERY se pone interesante. Una respuesta exitosa puede incluir dos cabeceras:

HTTP/1.1 200 OK
Content-Type: application/json
Content-Location: /contacts/stored-results/17
Location: /contacts/stored-queries/42
  • Content-Location apunta al resultado de esta consulta. Un GET ahí te devuelve exactamente lo mismo que acabas de recibir.
  • Location apunta a la consulta guardada. Un GET ahí vuelve a ejecutarla, con datos frescos, sin reenviar el cuerpo.

Eso último resuelve un problema real: una vez que el servidor te dio esa URI, tu cliente puede cambiar a GET para el polling y usar peticiones condicionales (If-None-Match, If-Modified-Since) sin volver a mandar un JSON de 40 KB cada 30 segundos.

Caché: donde está el riesgo

Las respuestas a QUERY son cacheables, pero con una condición innegociable: la clave de caché DEBE incorporar el cuerpo de la petición y sus metadatos.

Esto es más delicado que cachear un GET, porque el intermediario tiene que leer el cuerpo completo antes de poder calcular la clave. El RFC permite normalizar el contenido para mejorar la eficiencia (quitar content-encoding, normalizar JSON, etc.), pero advierte lo obvio: una normalización mal hecha produce falsos positivos, y un falso positivo es una respuesta incorrecta servida a otro usuario. Cache poisoning por la puerta de atrás.

Si tu CDN no entiende QUERY, no lo va a cachear mal: lo más probable es que lo rechace. El problema no son los que lo rechazan, son los que lo tratan como POST a medias.

Lo que todavía no puedes hacer

Seamos claros sobre el estado real, a julio de 2026:

  • No hay fetch() con QUERY. El navegador no lo manda hasta que la especificación Fetch de WHATWG lo incorpore.
  • Siempre habrá preflight en cross-origin. QUERY no está en la lista de métodos "CORS-safelisted", así que toda petición cross-origin arrastra un OPTIONS previo.
  • Tu infraestructura puede no saber qué es. WAFs, proxies inversos, load balancers y frameworks viejos pueden rechazar el método o enrutarlo raro. Revisa changelogs antes de asumir soporte.

Traducción práctica: en 2026 QUERY es una historia de servidor a servidor y de API gateways. Y está bien, porque ahí es justamente donde vive el tráfico pesado de búsquedas, reportes y consultas internas.

¿Lo empiezo a usar?

Mi recomendación, en orden:

  1. No migres nada en producción todavía. Verifica primero soporte en tu framework, CDN, proxy y WAF.
  2. Empieza por un salto interno. Si tenés un BFF (backend-for-frontend) hablando con un servicio propio, ese hop es el laboratorio perfecto: controlás las dos puntas.
  3. Mantené el POST /search vivo. Exponé QUERY en paralelo y anunciálo con Allow y Accept-Query. Que el cliente decida.
  4. Si cacheás, auditá la clave. Si el cuerpo no entra en la clave, apagá la caché hasta que entre.

Lo que realmente cambia

QUERY no habilita nada que no pudieras hacer antes con POST. Lo que hace es convertir una convención en un contrato. Antes, "esta búsqueda es segura, podés reintentarla" era algo que documentabas en un README y esperabas que alguien leyera. Ahora es algo que el protocolo declara y que cualquier intermediario puede entender sin conocer tu API.

Dieciséis años esperando un método nuevo, y resultó ser el que ya estábamos usando mal todos los días.


Referencia: RFC 10008 — The HTTP QUERY Method, J. Reschke, J. M. Snell, M. Bishop. IETF, junio de 2026. Standards Track (Proposed Standard). Disponible en rfc-editor.org/info/rfc10008.