Cómo enviar una solicitud POST con curl: referencia completa
Actualmente, existen aproximadamente veinte mil millones de instalaciones de curl ejecutándose en algún lugar del mundo. Esta cifra proviene de su creador, Daniel Stenberg, quien prácticamente lo mantiene en solitario. curl viene integrado en routers, automóviles, satélites, televisores inteligentes, los servidores Linux que sustentan la mayor parte de la web pública y todos los principales entornos de ejecución de LLM. De todos los verbos HTTP que manejan estas instalaciones, POST es el más importante. Una solicitud POST de curl es la forma en que la mayoría de los desarrolladores prueban, depuran o se integran con una API por primera vez.
El informe "Estado de las API 2025" de Postman sitúa la adopción de REST en un 93%. El 82% de las organizaciones operan actualmente, al menos parcialmente, con un enfoque API-first. POST es el verbo que se utiliza al crear, enviar o transmitir datos a un servidor. Las cargas de trabajo de IA aceleraron aún más esta tendencia. El tráfico de API atribuido al uso de IA creció un 73% en 2024 (Postman, 2024), y la documentación de todos los proveedores de LLM ahora comienza con un fragmento de código POST de curl como la "primera llamada" canónica.
Esta guía explica todas las formas posibles de una solicitud POST con curl, desde la más sencilla (una línea) hasta una llamada funcional a una API de pago con criptomonedas. El objetivo: que puedas copiar y pegar el código, no solo leerlo. Ya sea que envíes datos a un servidor por primera vez o que reconstruyas un controlador de webhook a altas horas de la madrugada, los patrones que se muestran a continuación cubren lo que realmente necesitas.
La tabla que aparece a continuación es una versión resumida. Se trata de una guía rápida con las opciones de línea de comandos de curl más utilizadas al enviar solicitudes POST. Cada una se explica con más detalle en las secciones siguientes.
| Bandera | Lo que hace | Cuando lo alcanzas |
|---|---|---|
| `-X POST`, `--request POST` | Fuerza el método de solicitud HTTP a POST. | Método explícito o verbos inusuales |
| `-d`, `--datos` | Envía datos en el cuerpo de la solicitud y configura POST automáticamente. | Campos de formulario, JSON en línea, cargas útiles simples |
| `--data-binary` | Envía archivos o datos binarios sin eliminar los saltos de línea. | Carga de archivos, JSON de gran tamaño, datos binarios sin procesar |
| `--data-urlencode` | Codifica el valor en URL antes de enviarlo. | Valores con espacios o caracteres especiales |
| `--json` | Envía datos con `Content-Type: application/json` y `Accept: application/json`. | curl 7.82.0 o posterior, API JSON |
| `-H`, `--header` | Agrega un encabezado HTTP personalizado | Tipo de contenido, autorización, claves API |
| `-F`, `--form` | Envía datos multipart/form-data con campos de formulario o archivos. | Carga de archivos, formularios con estilo HTML |
| `-u`, `--usuario` | Envía credenciales de autenticación HTTP Basic | API heredadas, autenticación simple de nombre de usuario y contraseña |
| `-i`, `--include` | Incluye encabezados de respuesta en la salida. | Inspeccionando las respuestas del servidor |
| `-v`, `--verbose` | Imprime la solicitud y la respuesta completas, incluyendo los encabezados. | Depuración de una solicitud POST fallida |
Comprender la solicitud POST de curl y el método HTTP.
Una solicitud POST de curl es una solicitud HTTP POST, enviada con el método POST, desde la línea de comandos. La herramienta curl describe su función como "transferir datos" a través de más de dos docenas de protocolos, de los cuales HTTP es solo uno. POST significa: aquí hay algunos datos, haz algo con ellos. La carga útil va en el cuerpo de la solicitud, nunca en la URL. Esta propiedad es la razón por la que POST maneja la creación de recursos, el envío de formularios y cualquier cosa que contenga credenciales. GET almacena los datos en la cadena de consulta, visible para todos los proxies y todos los historiales de navegación. POST no lo hace.
La mayoría de los tutoriales omiten un detalle pequeño pero útil. Al pasar `-d`, curl cambia automáticamente a POST. El parámetro explícito `-X POST`, que especifica un método de solicitud personalizado, es opcional. Muchos ejemplos aún lo incluyen porque leer `-X POST` junto a la carga útil deja clara la intención a simple vista.
Los métodos PUT y POST se confunden con frecuencia, por lo que conviene aclararlo. PUT reemplaza un recurso en una ubicación conocida. POST crea uno nuevo o envía datos para ser procesados en un punto final genérico.

Sintaxis básica de curl POST y el uso de la bandera -d en la práctica.
El comando mínimo curl POST es una línea:
```
curl -d "username=arya&age=16" https://api.example.com/users
```
Eso es todo. Solicitud POST, cuerpo codificado en URL, sin complicaciones. `-d` cumple una triple función: inserta la carga útil en el cuerpo de la solicitud, cambia el método de solicitud a POST y agrega `Content-Type: application/x-www-form-urlencoded` como encabezado predeterminado. De todos modos, suelo pegar el formulario un poco más detallado, porque la intención POST se lee mejor en una revisión de código:
```
curl -X POST -d "username=arya&age=16" https://api.example.com/users
```
Los mismos bytes en la red. Los mismos argumentos de solicitud. Utilicen el que su equipo considere más fácil de analizar. La opción `-d` es la herramienta principal para enviar datos a un servidor desde la línea de comandos y gestiona el noventa por ciento de las tareas que un desarrollador backend realiza con curl: llamadas a la shell, pruebas de webhook, objetivos de Makefile, pasos de GitHub Actions.
Tres variantes cercanas de `-d`. `--data-binary` mantiene los bytes intactos; la variante `-d` elimina los saltos de línea y distorsionará la carga binaria. `--data-urlencode` codifica en porcentaje: `--data-urlencode "name=I am Daniel"` se convierte en `name=I%20am%20Daniel`. `--data-raw` es la solución cuando un valor comienza con `@` y curl no debe leer un archivo. Varias opciones `-d` se combinan con `&`. Funciona bien para formularios. Nunca para JSON.
Un último detalle importante: las comillas simples. Las comillas simples alrededor de la carga útil impiden que el intérprete de comandos interprete el símbolo `$` o las barras invertidas. Si las olvidas, pasarás las 2 de la madrugada preguntándote por qué falta la mitad de tus datos POST.
Estos detalles importan porque curl es uno de los clientes HTTP más probados del planeta. La retrospectiva de Stenberg de diciembre de 2025 registró ocho versiones ese año. Nueve CVE, todas clasificadas como bajas o medias. 2179 casos de prueba activos, 232 más que doce meses antes. La versión 8.11.1, de diciembre de 2024, corrigió la CVE-2024-11053 (una fuga de credenciales de netrc y redireccionamiento). La versión estable actual, a finales de abril de 2026, es curl 8.20.0. Quienes sigan usando una versión anterior a la 7.82.0 aún no tienen la opción `--json` y recurren al patrón anterior de tres opciones.
Enviar datos JSON con curl usando --json o -H
JSON será el lenguaje común de las API REST en 2026. Existen dos maneras de enviar datos mediante POST con curl. La elección de una u otra depende completamente de la versión de curl instalada en el equipo.
Patrón clásico de tres banderas, funciona en todas partes a partir de CentOS 6:
```
curl -X POST \
-H "Content-Type: application/json" \
-d '{"title":"Tea","quantity":2}' \
https://api.example.com/orders
```
Notación abreviada moderna, disponible desde curl 7.82.0 (marzo de 2022):
```
curl --json '{"title":"Tea","quantity":2}' https://api.example.com/orders
```
La bandera `--json` realiza tres funciones: establece `Content-Type: application/json`, establece `Accept: application/json` y envía el cuerpo. Además, permite la composición: si se pasa `--json` varias veces, las cargas útiles se concatenan. Resulta útil al enviar fragmentos JSON a un punto final de transmisión.
Para las cargas útiles JSON almacenadas en un archivo, anteponga `@` a la ruta del archivo. El envío de datos desde un archivo se convierte en el patrón estándar una vez que el objeto JSON es demasiado grande para pegarlo directamente, o una vez que se encuentra en un sistema de control de versiones, o una vez que otro script lo genera:
```
curl -X POST -H "Content-Type: application/json" -d @order.json https://api.example.com/orders
curl --json @order.json https://api.example.com/orders
```
El segundo patrón lee los datos de un archivo llamado `order.json` y los envía con todos los encabezados correctos. Para contenido JSON grande o potencialmente binario, `--data-binary @file.json` es la opción más segura. No elimina los saltos de línea, no interpreta caracteres especiales y envía datos binarios sin procesar a un punto final que espera bytes en lugar de campos de formulario. Un tercer patrón lee los datos de la entrada estándar mediante `-d @-`. Útil para redirigir la salida de otro comando directamente a una solicitud POST de curl.
La siguiente tabla relaciona las cuatro estructuras JSON comunes con un único punto final:
| Patrón | Dominio | Cuándo usar |
|---|---|---|
| En línea, clásico | `-X POST -H "Content-Type: application/json" -d '{"k":"v"}'` | Máxima compatibilidad, cualquier versión de curl. |
| En línea, moderno | `--json '{"k":"v"}'` | curl 7.82.0 o posterior, sintaxis más limpia |
| Desde archivo, seguro | `-X POST -H "..." -d @payload.json` | La carga útil se mantiene en el control de versiones. |
| Desde archivo, binario seguro | `-X POST -H "..." --data-binary @payload.json` | Archivos grandes, cargas útiles con saltos de línea |
Esto es más importante que antes. Todos los principales proveedores de LLM (OpenAI, Anthropic, Mistral, Google) inician la documentación de su API con un ejemplo de solicitud POST con curl que utiliza exactamente esta estructura. El tráfico impulsado por IA aumentó un 73 % el volumen total de llamadas a la API en 2024 (Postman). curl es ahora la referencia estándar para saber cómo llamar a este endpoint.

Tipo de contenido, encabezados y lo que asume curl
La mayoría de las respuestas "415 Unsupported Media Type" se deben a la falta de una cabecera. Con `-d`, curl añade discretamente a tu solicitud `Content-Type: application/x-www-form-urlencoded`. Si envías un cuerpo JSON sin `-H "Content-Type: application/json"` ni `--json`, recibirás un error 415. Sin advertencia, solo el rechazo.
Otros metadatos también se incluyen en el cuerpo de la solicitud: Content-Length, el encabezado de autorización y el X-Request-Id para el seguimiento. Obtener correctamente estos metadatos es fundamental para cualquier integración de API. El objeto JSON en sí es la parte más sencilla.
`-H` añade encabezados personalizados. Repita según sea necesario. Los nombres de los encabezados no distinguen entre mayúsculas y minúsculas; los valores sí. La forma más rápida de depurar una solicitud POST mal configurada es ejecutarla con `-v` una vez, leer la línea de la solicitud y compararla con la documentación de la API. En ocho de cada diez casos, el error aparece en segundos.
Dos notas más. El parámetro Content-Length se establece automáticamente mediante curl a partir del tamaño del cuerpo; rara vez se modifica. El parámetro `Accept: application/json` indica al servidor que responda en JSON en lugar de HTML. Para ello, añada otro `-H` o utilice `--json`, que establece Content-Type y Accept conjuntamente.
Carga de datos de formulario y archivos con curl POST -F
Para datos de formularios con estilo HTML que incluyan archivos, la opción correcta es `-F`. Genera una solicitud `multipart/form-data`. El tipo de contenido es diferente al que se usa por defecto con `-d` (form-urlencoded). El modelo mental es distinto. Los tutoriales de un párrafo suelen confundir ambos conceptos, lo que provoca errores reales.
`-F` una vez por campo. Campo de formulario simple:
```
curl -F "name=Arya" https://api.example.com/submit
```
Carga de archivos:
```
curl -F "file=@/path/to/image.png" https://api.example.com/upload
```
El prefijo `@` le indica a curl que lea el archivo del disco e incluya su contenido en el cuerpo de la solicitud. curl detecta automáticamente el tipo MIME a partir del nombre del archivo; puede modificarlo explícitamente cuando sea necesario.
```
curl -F "[email protected];type=image/png" https://api.example.com/upload
```
Varias opciones `-F` permiten agrupar varios campos o archivos en una sola solicitud:
```
curl -F "title=Holiday" -F "[email protected]" -F "[email protected]" https://api.example.com/album
```
Para el contenido sin procesar de archivos, sin el contenedor multipart (algo común al enviar un archivo JSON o un blob binario a un punto final de transmisión), utilice `--data-binary @file.bin`. Esto envía los bytes del archivo como cuerpo de la solicitud tal cual, con el Content-Type que haya especificado explícitamente.
Autenticación en curl POST: claves básicas, de portador y API.
Tres formas de autenticación cubren casi todas las API REST en 2026. Autenticación básica (nombre de usuario más contraseña, codificada en base64 en un encabezado):
```
curl -u "miusuario:micontraseña" -X POST -d "..." https://api.example.com/login
```
Los tokens de portador, utilizados por la mayoría de las API modernas, incluidas todas las credenciales emitidas por OAuth, se basan en un encabezado de autorización personalizado:
```
curl -H "Authorization: Bearer $TOKEN" --json '{"q":"hello"}' https://api.example.com/query
```
Las claves API suelen residir en un encabezado específico del servicio:
```
curl -H "X-API-Key: $PLISIO_KEY" --json @invoice.json https://api.plisio.net/api/v1/invoices/new
```
Credenciales de una variable de entorno o un gestor de secretos, nunca escritas directamente en el código. ¿Por qué? El informe "State of Secrets Sprawl 2025" de GitGuardian contabilizó 23,8 millones de nuevos secretos filtrados a GitHub público durante 2024. Un aumento del 25 % con respecto a 2023. Más del 90 % de ellos siguieron siendo válidos cinco días después de su exposición. Las credenciales escritas directamente en los scripts de curl son una de las principales causas de estas filtraciones. La sección de seguridad que aparece a continuación describe el flujo de trabajo.
Ejemplo real de solicitud POST con curl: API de pago de Plisio
La documentación de referencia sin un ejemplo real es pura teoría. La solicitud POST curl que se muestra a continuación genera una factura de pago con criptomonedas a través de la API REST de Plisio. Plisio cobra una comisión fija del 0,5%; los procesadores de tarjetas suelen cobrar entre un 2% y un 4%. Plisio admite más de treinta criptomonedas y ofrece integraciones para diecinueve plataformas de comercio electrónico.
Por qué las API de criptomonedas funcionan como objetivos de práctica. Las stablecoins movieron aproximadamente $28 billones en volumen económico real durante 2025. Chainalysis estimó el crecimiento en 133% CAGR desde 2023. El mercado de pasarelas de pago de criptomonedas rondó los $2 mil millones en 2025, camino a $2.39 mil millones en 2026 (según The Business Research Company). BitPay, Coinbase Commerce, Plisio: elija cualquiera. El primer paso de integración con cualquier pasarela moderna es casi siempre un curl POST.
La llamada mínima para crear una nueva factura:
```
curl -X POST https://api.plisio.net/api/v1/invoices/new \
-H "Content-Type: application/json" \
-H "Autorización: Portador $PLISIO_API_KEY" \
-d '{
"source_currency": "USD",
"source_amount": 49.99,
"order_number": "INV-1042",
"currency": "BTC",
"email": "[email protected]",
"order_name": "Annual subscription"
}'
```
Una llamada exitosa devuelve HTTP 201. El cuerpo de la respuesta es un objeto JSON: un ID de factura generado, una URL de factura donde el cliente paga, una dirección de monedero de destino y una marca de tiempo de vencimiento. Utilice `jq` para extraer el campo que necesite a continuación:
```
... | jq '.data.invoice_url'
```
Ese es el patrón completo. Cambia el punto final, cambia la carga útil, y la estructura se mantiene directamente en un cargo de BitPay, un pago de Coinbase Commerce o una intención de pago de Stripe. Las banderas no cambian; solo cambia el JSON.
Depuración de una solicitud POST de curl: -v, --trace, errores
Un POST fallido supone un verdadero rompecabezas para la depuración. Reintentar a ciegas es la peor opción. Cuatro opciones en la línea de comandos cubren la mayoría de las necesidades.
`-v` imprime la línea de la solicitud, cada encabezado de la solicitud y el estado de la respuesta. Esa es la primera opción que debes usar. `--trace-ascii -` es la opción más drástica: envía toda la conversación, incluido el cuerpo de una solicitud POST, a la salida estándar. Usa `curl -i` para insertar los encabezados de respuesta antes del cuerpo. Y `-w "%{http_code}\n"` escribe solo el código de estado HTTP, útil al automatizar comprobaciones de CI contra una API.
Acerca de los códigos de estado que verá con más frecuencia: 400: el servidor procesó su solicitud pero rechazó la carga útil. 401: encabezado de autenticación faltante o no válido. 415: Content-Type incorrecto. 500: el servidor falló al procesar su entrada. Cada uno descarta una capa específica, lo que representa la mitad del valor de ejecutar `-v` en el primer fallo.
Seguridad de las solicitudes POST de curl: claves API, secretos y filtraciones
Todas las referencias omiten esta sección. Todos los análisis posteriores a un incidente la mencionan. Diciembre de 2024: la filtración del Departamento del Tesoro de EE. UU. se remonta a una clave API de BeyondTrust filtrada. Exactamente el tipo de credencial que se encuentra dentro de los encabezados `-H "Authorization: Bearer ..."` en los scripts de producción.
La defensa no es nada glamurosa. Lee los tokens de las variables de entorno. Almacénalos en un gestor de secretos como AWS Secrets Manager, HashiCorp Vault o la CLI de 1Password. Mantén un hook de pre-commit en ejecución con `gitleaks` o `trufflehog`. Rota cualquier token que haya existido en el historial de la shell. Nada de esto es emocionante. Todo funciona. Aplicarlo a cada solicitud POST de curl que envíes es el hábito más importante que un desarrollador backend puede adquirir en 2026.