Skip to main content

Sending Messages

Every send is a single POST to one of four endpoints, authenticated with your instance's API key. Each returns the same shape — a message id you can later check the status of.

Authorization: Bearer sk_<your instance api key>
Content-Type: application/json

Every response looks like:

{ "id": "83ad449d-c6ef-49c0-97be-c08b5e452d73" }
What counts as "one message"

One outbound send — text, image, location, or contact card — costs exactly one message credit (prepaid mode) or counts toward your plan (fixed mode). Inbound messages and webhook deliveries are never billed. See Billing.

Text​

curl -X POST https://app.tarceel.com/instances/<instanceId>/messages/text \
-H "Authorization: Bearer sk_..." \
-H "Content-Type: application/json" \
-d '{"to": "15551234567", "text": "Hello from Tarceel!"}'

to is a phone number — country code + number, digits only (no +, no spaces, no dashes).

Media​

Image, video, audio, or document — either a public URL or raw base64:

curl -X POST https://app.tarceel.com/instances/<instanceId>/messages/media \
-H "Authorization: Bearer sk_..." \
-H "Content-Type: application/json" \
-d '{
"to": "15551234567",
"type": "image",
"url": "https://example.com/photo.jpg",
"caption": "Your receipt"
}'

Send exactly one of url or base64 — not both. mimetype is required when type is document; filename and caption are optional on any media type.

Location​

curl -X POST https://app.tarceel.com/instances/<instanceId>/messages/location \
-H "Authorization: Bearer sk_..." \
-H "Content-Type: application/json" \
-d '{"to": "15551234567", "latitude": 24.8607, "longitude": 67.0011, "name": "Our office"}'

name and address are optional labels shown alongside the pin.

Contact card​

curl -X POST https://app.tarceel.com/instances/<instanceId>/messages/contact \
-H "Authorization: Bearer sk_..." \
-H "Content-Type: application/json" \
-d '{"to": "15551234567", "fullName": "Jane Doe", "phone": "15559876543"}'

Checking delivery status​

curl https://app.tarceel.com/instances/<instanceId>/messages/<id>/status \
-H "Authorization: Bearer sk_..."
{ "id": "83ad449d-...", "status": "delivered" }

status moves through pending → sent → delivered → read, or failed. Polling works, but if you're sending any real volume, subscribe to the message.status webhook event instead — it fires the moment each transition happens.

Errors you'll actually see​

StatusMeaning
400Bad request — missing/invalid field.
402Payment required — the instance has no credits left, or its subscription isn't active. See Billing.
409The instance's WhatsApp session isn't connected right now (needs a QR scan, or was paused).

Try it without writing any code​

Every instance's detail page in the dashboard has a "Try the API" tab: pick an operation, fill in a small form, and it shows the equivalent request in cURL, Node.js, Python, PHP, Java, and C#/.NET — with that instance's real id and key already filled in. A Send test request button fires it for real and shows you the raw response before you write a single line of your own code.