Skip to content
man glossary/curl

glossary define curl

Name

cURL

cURL is the command-line HTTP client developers use to call the WhatsApp Cloud API directly: send messages, upload media and test tokens without code.

Synopsis

curl command, curl.exe

Section

Graph API & SDKs

Level

foundation

▍

Reviewed

Read a curl command flag by flag

5 / 5
curl -i -X POST \
"https://graph.facebook.com/v26.0/{PHONE_NUMBER_ID}/messages" \
-H "Authorization: Bearer $WA_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "919812345678",
"type": "text",
"text": { "body": "Your itinerary is ready." }
}'

Step 5 of 5 · lines 8–10

Recipient with country code, plus a free-form text: this only succeeds while the customer service window is open.

Jump to
Three real-shaped commands: a text send, a multipart media upload and the response curl prints with -i. Step through to see what each flag puts on the wire.

send-text.sh, step 5 of 5, lines 8–10: Recipient with country code, plus a free-form text: this only succeeds while the customer service window is open.

Description

What is cURL?

cURL (the curl command, built on the open-source libcurl library) is a command-line tool for making HTTP requests. For the WhatsApp Cloud API it is the shortest path from an access token to a delivered message: one command sets the method, a URL such as https://graph.facebook.com/v26.0/{PHONE_NUMBER_ID}/messages, the Authorization: Bearer header and a JSON body, then prints the Graph API's response. The sample request in the WhatsApp section of Meta's App Dashboard is a curl command for exactly this reason.

A curl command is a handful of flags that map one-to-one onto the HTTP request: -X POST sets the method, each -H adds a header, -d (or --data) sends a request body, and -F builds a multipart form for file uploads such as the media upload endpoint. -i prints the status line and response headers above the body, which is where you see whether the call returned 200 or an error.

cURL is a tool for exploring, testing and debugging rather than for production sending. It shows exactly what goes over the wire, with no SDK defaults or saved GUI state in between, which makes it the common language of documentation, bug reports and support tickets. A Postman Collection stores the same requests in a GUI with variables and environments, and an SDK wraps them in code; both can import a curl command or be reproduced as one.

Key takeaways

  • cURL is a command-line HTTP client: one command sends a complete Graph API request with headers, a JSON body or a file upload.
  • Every Cloud API call needs an Authorization: Bearer header; JSON bodies also need Content-Type: application/json.
  • Media uploads use multipart form fields (-F), not a JSON body, and curl sets the multipart boundary for you.
  • curl exits successfully on an HTTP 400 unless you pass --fail-with-body, so always look at the status code.
  • On Windows call curl.exe explicitly and send JSON from a file: cmd does not treat single quotes as quotes.

Usage

CURL in code

curl -i -X POST "https://graph.facebook.com/v26.0/{PHONE_NUMBER_ID}/messages" \
-H "Authorization: Bearer $WA_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"messaging_product": "whatsapp",
"to": "919812345678",
"type": "template",
"template": { "name": "hello_world", "language": { "code": "en_US" } }
}'

A template can be sent at any time to an opted-in user; free-form text needs an open customer service window.

Mechanics

How does cURL work?

  1. step 1 — Set the endpoint and method

    Build the URL from the current Graph API version and the object you act on: /{PHONE_NUMBER_ID}/messages to send, /{PHONE_NUMBER_ID}/media to upload, /{WABA_ID}/message_templates to list templates. Pass -X POST for writes; a GET needs no -X.

  2. step 2 — Add the auth header

    Pass -H "Authorization: Bearer $WA_TOKEN" with the access token in an environment variable, so it stays out of shell history, screenshots and pasted commands.

  3. step 3 — Send a JSON body

    Add -H "Content-Type: application/json" and the body with -d, or use --json (curl 7.82 and later), which sets the content type and Accept headers for you. -d @body.json reads the body from a file and sidesteps quoting problems.

  4. step 4 — Upload files as multipart

    For media, switch to -F fields: -F "messaging_product=whatsapp" and -F "file=@invoice.pdf;type=application/pdf". Do not add a Content-Type header by hand; curl writes it with the boundary.

  5. step 5 — Read the status, not just the body

    curl reports success whenever a response arrives, even a 400. Add -i to see the status line, -w "%{http_code}" to print it, or --fail-with-body (curl 7.76+) in scripts so an API error stops the script and still shows the error JSON.

Properties

CURL: key facts and limits

Send endpoint
POST /v26.0/{PHONE_NUMBER_ID}/messages
Auth header
Authorization: Bearer {ACCESS_TOKEN}
JSON body
-d with Content-Type, or --json (curl 7.82+)
File upload
-F fields (multipart/form-data)
Show the status
-i, or -w "%{http_code}"
Fail on HTTP errors
--fail-with-body (curl 7.76+)
On Windows
curl.exe ships with Windows 10 (1803) and later

Example

Example: Smoke-testing a new number in Kochi

A developer at a Kochi travel agency has just registered a business number and wants proof it can send before wiring up the booking system. She exports the token as WA_TOKEN, runs the curl command for the hello_world template to her own phone and gets back a WAMID. A second command with -F uploads a sample itinerary PDF and returns a media ID; a third sends that ID as a document message. When she reruns the commands the next morning they fail with error 190: she had used the 24-hour temporary token from the App Dashboard, so she switches to a system user access token before handing the commands to the backend team.

Why it matters

Why does cURL matter?

When an integration fails, the first question is whether the problem is your code or the request itself. Replaying the call with cURL strips away frameworks, retries and serialisers: if the curl command works, the bug is in your application; if it fails, the Graph API's error body says why. Curl commands are also the format Meta's docs, provider docs and support teams share, so reading and adapting one quickly saves hours.

Caveats

Common mistakes with cURL

  • Pasting the token into the command

    A literal token ends up in shell history, CI logs and the screenshot you share in a ticket. Keep it in an environment variable or a secrets file, and rotate it at once if it leaks.

  • Treating exit code 0 as success

    curl only fails on transport problems by default. A 400 with an error JSON is a finished request, so scripts must check the status code or use --fail-with-body.

  • Quoting JSON on Windows

    cmd.exe does not treat single quotes as quotes, and in Windows PowerShell 5.1 curl is not curl at all. Call curl.exe and send the body with -d @body.json.

  • Setting Content-Type on multipart uploads

    Adding Content-Type: multipart/form-data by hand drops the boundary curl generates, and the upload is rejected. Let -F set the header.

  • Copying samples with an old API version

    Old snippets carry old version numbers. Each Graph API version stops working two years after its successor ships, so update the version in the URL when you reuse a command.

Notes

Best practices for cURL

  • Keep one body.json per message type and send it with -d @body.json: easier to edit, diff and share than inline JSON.
  • Pipe responses through jq to pull out fields, for example jq -r '.messages[0].id' for the WAMID.
  • Use -v only to debug TLS or redirects: it prints the Authorization header, so never paste verbose output publicly.
  • A working curl command is the most portable bug report: Postman and most API tools can import it in one click.

Questions

cURL FAQs

How do I send a WhatsApp message with cURL?
POST a JSON body to /{PHONE_NUMBER_ID}/messages with a Bearer token. Include messaging_product: whatsapp, the recipient in to, a type and the matching object; outside the 24-hour customer service window that type must be template.
Why does curl report success when the WhatsApp API returned an error?
Because curl only fails on network or transport errors by default. An HTTP 400 with an error body is a completed request; add --fail-with-body or print %{http_code} to treat it as a failure.
Should I test the WhatsApp API with cURL or Postman?
Use whichever suits the task. cURL is exact and scriptable; Postman is easier for exploring with saved variables and sharing with a team. They are interchangeable, because Postman imports and exports curl commands.
How do I upload media to the WhatsApp Cloud API with curl?
Use multipart form fields: -F "messaging_product=whatsapp" and -F "file=@path;type=MIME" against /{PHONE_NUMBER_ID}/media. The response holds a media ID that you then send in an image, document, audio or video message.

See InfiQ pricing

Put cURL to work

InfiQ is an official Meta Business Partner. Start a 7-day free trial — no card needed — and see this running on your own number.