TextPeak API — Overview
The TextPeak API by CommPeak is a REST API for sending messages and running verification flows across multiple channels — SMS, WhatsApp, OTP one-time passwords, and other omnichannel messaging — and for managing the resources those messages depend on.
Everything is served over HTTPS, accepts and returns JSON, and uses a single, consistent authentication header. This page covers what the API includes, how to authenticate, how to make your first call, and how errors are reported.
What you can do
The API is organized into two kinds of operations:
Messaging & verification — the outbound traffic your application generates:
- Send SMS — single or batch (
simple_send,simple_send_single). - Send templated messages — SMS and WhatsApp (
template_send,event_send). - Send WhatsApp media & templates (
whatsapp/send_media,whatsapp/template). - OTP authentication — trigger and verify one-time passwords for login, 2FA, and account confirmation (
otp/auth,otp/verify).
Configuration & management — the resources messaging runs on:
- Streams — create, list, update, and delete messaging streams; generate and reset their tokens.
- Domains — manage the domains associated with your account.
- Senders — manage the sender identities used for outbound messages.
- Stream event templates — define reusable message configurations.
- Webhooks — register endpoints to receive delivery and event callbacks.
- Messages — read sent and incoming message history.
Base URL
All requests go to a single production base URL:
https://gw.commpeak.com/textpeak
Every request that has a body must send Content-Type: application/json; the API only accepts JSON request bodies.
Authentication
Every request is authenticated with a token placed in the Authorization header.
Pass the token as the raw header value — not as a Bearer token.
Send the token string exactly as issued:
Authorization: <token>. Do not prefix it withBearer.
There are three token types. They are not interchangeable — each one authenticates a specific group of endpoints, and using the wrong type returns an authentication error.
| Token type | Authenticates | Where it comes from |
|---|---|---|
| TextPeak API key | All configuration & management endpoints: Streams, Domains, Senders, Stream event templates, Webhooks, message history, and stream token generation/reset. | Generated by you on the TextPeak platform, on the API Keys page. |
| Stream token | All messaging endpoints: simple_send, simple_send_single, template_send, event_send, whatsapp/send_media, whatsapp/template, and file upload. Each token is scoped to a single stream. | Fetch with your API key: GET /streams/{id}/token. Rotate with GET /streams/{id}/token/reset. |
| OTP token | The OTP endpoints only: otp/auth and otp/verify. | The token of a stream configured for OTP. Obtained the same way as a stream token, from an OTP-enabled stream. |
How they fit together: your API key is the account-level credential you manage streams with — including minting the per-stream tokens. A stream token then authorizes the actual message sends for that one stream. The OTP token is the stream token of a stream set up for one-time-password delivery, and it is the only token accepted on the OTP endpoints.
Tokens are secrets. Store them server-side, never expose them in client code, and rotate a stream token with the reset endpoint if it is ever leaked.
Quickstart
A first send is two calls: mint a stream token with your API key, then send a message with that token.
1. Get a stream token (authenticated with your API key):
curl https://gw.commpeak.com/textpeak/streams/36/token \
-H "Authorization: <YOUR_API_KEY>"{ "token": "d2b14ae204e9002338f97b9e4hgg5fcd907f9aa8175b87dfed38373d57c9ff21..." }2. Send an SMS (authenticated with the stream token from step 1):
curl -X POST https://gw.commpeak.com/textpeak/streams/simple_send \
-H "Authorization: <YOUR_STREAM_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"messages": [
{
"internal_id": "123",
"sender": "GLOBAL",
"recipient_phone": "972524265292",
"message_content": "Hello from TextPeak"
}
]
}'A successful response confirms acceptance and returns per-message identifiers you can correlate with delivery webhooks:
{
"status": true,
"task_id": "c51adf4e-77a2-4647-9c23-afa1093d3837",
"messages": [
{
"internal_id": "123",
"message_uuid": "ee6c0954-ad37-4427-a293-8f4ce6f5f8fc",
"conversation_uuid": "cedb22b2-0453-4c7b-b1e6-345bc97055a1"
}
]
}Responses & error handling
Success
Messaging endpoints return "status": true along with the resulting identifiers (task_id, message_uuid, conversation_uuid). Management endpoints return standard HTTP success codes — 200 (OK), 201 (Created), or 204 (No Content).
Error format
When a messaging or OTP request fails, the response body is a consistent JSON envelope:
{
"status": false,
"error_code": "0x12",
"message": "invalid external stream token"
}status—falseon failure.error_code— a stable hexadecimal code identifying the exact condition (see the catalog below). Use this, not the message text, for programmatic handling.message— a human-readable description, useful for logs and debugging.
Always check thestatusfield, not just the HTTP status code.
Most failures use a matching HTTP status (
401,402,422,429, …), but some request-body validation errors are returned with HTTP200and"status": false. Treat any response wherestatusisfalseas a failure regardless of the HTTP code.
Partial failures in batch sends
Batch endpoints (simple_send, template_send) accept many messages in one request. Individual messages can fail without failing the whole request — those come back inline per message, keyed by your internal_id, with an error code and details:
{
"internal_id": "123",
"error": "0x31",
"details": "reached his daily limit 5000"
}Iterate the response array and check each entry rather than assuming an all-or-nothing outcome.
Error code catalog
All codes below come from the messaging/OTP service. Codes are grouped by category; the HTTP column is the status most commonly returned for that code.
Authentication & authorization — apply to any token-authenticated request (stream or OTP token):
| Code | Name | HTTP | Meaning |
|---|---|---|---|
0x11 | auth_error_missing_token | 403 | No token was supplied in the Authorization header. |
0x12 | auth_error_invalid_token | 401 | The token is invalid, expired, or could not be decrypted. |
0x13 | auth_error_ip_acl_restriction | 401 | The request originated from an IP/origin not permitted by the token's access list. |
0x14 | auth_error_invalid_jwt_token | 403 | The JWT presented is invalid or expired. |
0x15 | auth_error_invalid_integration_token | 401 | The integration/OAuth token does not match any stream. |
0x16 | auth_error_banned_ip | 403 | The caller's IP address is banned. |
0x18 | invalid_credentials | 401 | The supplied credentials were rejected. |
0x51 | auth_error_invalid_auth_request | 403 | The authenticated request is malformed (e.g. required metadata missing). |
Validation:
| Code | Name | HTTP | Meaning |
|---|---|---|---|
0x0 | general_error | 500 | An unexpected server-side error occurred. |
0x1 | request_validation_error | 422 / 200 | A field failed validation (missing or malformed). Framework-level body validation may return HTTP 200 with status:false — read the body. |
0x17 | invalid_argument | 400 | A supplied argument is invalid (e.g. bad message id or sender). |
0x20 | auth_restricted_media | 422 | The media type is restricted for this account. |
0x61 | sender_error_missing_sender_to_destination | 422 | No sender is configured for the message's destination. |
0x62 | event_error_invalid_name | 422 | The event template name is unknown or invalid. |
Billing & rate limits:
| Code | Name | HTTP | Meaning |
|---|---|---|---|
0x41 | payment_required | 402 | The account/stream balance is depleted. |
0x30 | limit_error_undefined | 429 | Sending is throttled — no TPS limit is defined for the stream. |
0x31 | limit_error_reached_tps | 429 | The TPS or daily send limit was reached (returned per-message in batch sends). |
0x32 | limit_error_reached_max_otp_requests | 429 | The maximum number of OTP requests for this recipient was reached. |
0x33 | limit_error_reached_max_otp_failures | 429 | The maximum number of OTP verification failures was reached. |
Stream & send:
| Code | Name | HTTP | Meaning |
|---|---|---|---|
0x19 | duplicate_message | 400 | A message with the same identifier was already submitted. |
0x21 | stream_error_not_available | 403 | The stream is not available for this request. |
0x22 | stream_error_not_ready | 403 | The stream is not configured for the requested operation (e.g. not enabled for OTP). |
0x23 | stream_missing_for_messaging_provider | 403 | No stream is configured for the requested messaging provider/channel. |
OTP:
| Code | Name | HTTP | Meaning |
|---|---|---|---|
0x24 | auth_request_failed | 422 | The OTP authentication request could not be created. |
0x25 | duplicate_auth_request | 422 | An OTP code was already requested for this phone number. |
0x26 | invalid_auth_request | 422 | The OTP request is invalid or has expired. |
OTP verification result vs. error.otp/verifyreturns HTTP200with"verification": trueorfalseto report whether the code matched — a wrong code is a normalfalseresult, not an error. The error codes above are raised only when the request itself cannot be processed (rate limits, expired/duplicate requests, unconfigured stream).
Management-endpoint errors
Configuration & management endpoints (Streams, Domains, Senders, templates, webhooks) return the appropriate HTTP status — 400, 401, 403, 404, 422 — with a JSON body describing the problem. Validation failures (422) include the specific field violations. Authentication failures on these endpoints mean the API key is missing or invalid.
Rate limits & quotas
Sending is governed by per-stream throughput and, for OTP, per-recipient caps. When a limit is hit the API returns HTTP 429 with one of the limit codes above:
- Throughput (TPS / daily):
0x30(undefined limit) and0x31(limit reached). In batch sends,0x31is reported per message so the messages that fit are still accepted. - OTP request cap:
0x32— too many OTP requests for a recipient in the allowed window. - OTP failure cap:
0x33— too many failed verification attempts.
On a 429, back off and retry after a short delay with exponential increase; do not retry tight loops. A 402 (payment_required) is not a rate limit — it means the balance is depleted and retrying will not succeed until the account is topped up.
Versioning
This reference documents TextPeak API V2.0.0, served at the base URL above. Changes are additive and backwards-compatible where possible — new fields may appear in responses, so parse JSON leniently and ignore fields you do not recognize. The base URL is stable; breaking changes are introduced under a new version rather than changed in place.
Support & resources
- Reference sections: Streams · Domains · Senders · Stream event templates · Webhooks management · Streams Service (messaging & OTP).
- Support: contact your CommPeak account manager or the CommPeak support team for API keys, stream provisioning, sender registration, and quota changes.