Use webhooks to receive message results and inbound SMS events from TNZ without repeatedly polling the REST API.
Webhook quick answers
What does TNZ send?
Two kinds of events: message results for outbound message delivery status, and inbound SMS for matched replies or incoming SMS messages.
How do I configure it?
Set defaults for an API User in Users > select the User > API > Reporting. A sending request can override the method with NotificationType and the endpoint with WebhookCallbackURL.
How is it secured?
TNZ sends the credentials you configure as an Authorization Bearer value, an X-Sender header, and Sender and APIKey payload fields. Your HTTPS receiver should validate them. See the "How do I configure it" answer for set-up instructions.
What if a webhook fails?
If TNZ does not receive an HTTP 2xx response, it retries every five minutes for up to 24 hours. Your receiver must handle duplicates, and it must not assume events will arrive in order.
An API response is not a delivery result
A successful response to a sending request means TNZ accepted the submission. It does not mean the message reached its recipient. Use a result webhook or query the message status to learn the delivery outcome.
Default settings apply to messages sent by the selected TNZ User.
- Sign in to the TNZ Dashboard.
- Open Users, then select the User that sends the API messages.
- Open the API tab and find the Reporting section.
- Enter a complete HTTPS endpoint in Webhook Callback URL (can be overridden per message by setting the WebhookCallbackURL parameter, and the Status webhook and Inbound SMS webhook share the same URL).
- Set Webhook Callback Format. Choose JSON for most new integrations.
- Set Webhook Callback Version to v3.00.
- Set Webhook Callback Sender and Webhook Callback APIKey. Your receiver will use these values to authenticate incoming requests.
- Set each required report method to API. For example, set SMS Report Method to API for SMS results and SMS Reply Report Method to API for inbound SMS replies.
- Save the User.
Treat the callback APIKey as a secret
Store it in your application's secret manager. Do not put it in source control, screenshots, support tickets, or application logs. This key will appear in the webhook's Authorization header and APIKey body value.
Webhook Callback Format controls the HTTP method and how TNZ encodes the webhook fields.
| Format |
Request sent by TNZ |
When to use it |
| JSON |
HTTP POST with a JSON request body |
Recommended for new integrations. |
| XML |
HTTP POST with an XML request body |
Use when the receiver expects XML. |
| POST |
HTTP POST with form-encoded fields |
Use for an existing receiver that accepts a form post. |
| GET |
HTTP GET with the webhook fields in the query string |
Use only when required by an existing integration. |
GET can expose webhook data in URL logs
Query strings may be stored by web servers, proxies, monitoring services, and browser history. Prefer JSON unless your integration requires another format.
Override webhook settings for one message
Add the following fields to a supported sending request when one message needs a different callback. Omit them to use the selected User's defaults.
| Field |
Purpose |
Value |
NotificationType |
Overrides the User's report method for this message. |
Webhook. Other supported values are Email and None. |
WebhookCallbackURL |
Sets the endpoint for this message's result and any matched SMS reply. |
A complete HTTPS URL, up to 500 characters. |
WebhookCallbackFormat |
Sets the method and encoding for the callback. |
JSON, XML, POST, or GET. |
The relevant fields in a JSON sending request look like this:
{
"NotificationType": "Webhook",
"WebhookCallbackURL": "https://api.example.com/tnz/webhooks",
"WebhookCallbackFormat": "JSON"
}
This is only an excerpt. Include it with the other required fields for the message type you are sending. See the TNZ REST API documentation for complete request schemas.
Results and replies use the same per-message URL
TNZ sends the message result and any matched inbound SMS reply to the callback URL supplied with that message. Check Type to decide how to process the payload.
Authenticate incoming webhooks
Webhook credentials identify requests sent by TNZ. They are configured separately from the credentials your application uses to submit outbound API requests.
| Request value |
Source in the Dashboard |
Receiver check |
Authorization: Bearer ... |
Webhook Callback APIKey |
Require the Bearer prefix and compare the credential with the stored expected value. |
X-Sender |
Webhook Callback Sender |
Compare it with the configured sender value. |
X-Timestamp |
Generated by TNZ |
Require a valid RFC3339 timestamp and apply your configured age and clock-skew rules. |
Sender and APIKey |
The same configured webhook values |
Check them when validating the decoded payload. |
For a JSON webhook, the request headers will follow this pattern:
Authorization: Bearer [Webhook Callback APIKey]
X-Sender: webhook@example.com
X-Timestamp: 2026-08-27T02:14:30.000Z
Content-Type: application/json
- Require HTTPS.
- Validate authentication before acting on the payload.
- Use constant-time secret comparison where your platform supports it.
- Never log the Authorization value or unredacted
APIKey.
- Validate
X-Timestamp. If you reject stale requests, allow at least the 24-hour retry period plus reasonable clock skew so a valid retry is not rejected solely because of its age.
- Limit logging of message text, destinations, prices, and other customer data.
Understand webhook events
| Event |
Type |
Important identifiers |
| SMS result |
SMS |
MessageID and Destination |
| Email result |
Email |
MessageID and Destination |
| Voice or text-to-speech result |
Voice |
MessageID and Destination |
| Fax result |
Fax |
MessageID and Destination |
| Matched SMS reply |
SMSReply |
ReceivedID and the matched outbound MessageID |
| Unmatched inbound SMS |
SMSInbound |
ReceivedID; MessageID may be empty |
A result webhook contains the final result known when the message completes. TNZ does not send another result webhook if a carrier later changes that status. A retry of the original webhook is still possible when your endpoint does not acknowledge it.
Result webhook example
{
"Version": "v3.00",
"Sender": "webhook@example.com",
"APIKey": "[redacted]",
"Type": "SMS",
"Destination": "+6421000001",
"ReceivedID": null,
"MessageID": "a1b2c3d4-e5f6-7890-1234-567890abcdee",
"SentTimeUTC_RFC3339": "2026-08-27T02:14:30.000Z",
"Status": "Success",
"Result": "delivered",
"Message": null,
"SubAccount": "Example Client",
"Price": "0.10",
"Detail": "SMSParts:1"
}
Inbound SMS webhook example
{
"Version": "v3.00",
"Sender": "webhook@example.com",
"APIKey": "[redacted]",
"Type": "SMSReply",
"Destination": "+6421000001",
"ReceivedID": "b2c3d4e5-f678-9012-3456-7890abcdef01",
"MessageID": "a1b2c3d4-e5f6-7890-1234-567890abcdee",
"SentTimeUTC_RFC3339": "2026-08-27T02:16:04.000Z",
"Status": "RECEIVED",
"Result": "RECEIVED",
"Message": "YES",
"Price": null,
"Detail": "InputToNumber:021-000001"
}
These examples show the fields most useful when first implementing a receiver. Payloads can contain additional reporting fields. Use the live webhook specification as the reference for the complete schema.
Important payload fields
| Field |
Meaning |
Version |
The webhook API version, such as v3.00. |
Type |
Identifies whether the payload is a channel result, matched SMS reply, or unmatched inbound SMS. |
MessageID |
Identifies the outbound message. For inbound SMS, it contains the matched outbound ID when TNZ finds one. |
ReceivedID |
The unique identifier for an inbound SMS. It is empty for a result webhook. |
Destination |
The result destination, or the mobile number that sent the inbound SMS. |
Status and Result |
Describe the final message result. Both are RECEIVED for inbound SMS. |
Message |
Contains inbound SMS text. It is empty for a result webhook. |
Sender and APIKey |
Repeat the webhook authentication values configured for the User. |
SubAccount |
The SubAccount associated with the outbound message. |
Price |
The amount charged to the TNZ account holder for the message. TNZ can omit this value for a reseller account when required. |
Detail |
Contains channel-specific details such as SMS part count or the original inbound number format. |
See the result-code guides for channel-specific values: SMS, Email, Voice and text-to-speech, and Fax.
Acknowledge and process webhooks safely
Keep the HTTP request path short. Store the event first, acknowledge it, then run slower business logic separately.
- Validate the authentication headers, timestamp, and basic payload shape.
- Create a duplicate-detection key.
- Persist the event or place it on a durable queue.
- Return a
2xx response promptly.
- Process database updates, notifications, or workflows asynchronously.
Plan for duplicate delivery
Use ReceivedID to identify an inbound SMS. For result events, use a unique MessageID for every sending request when you need reliable correlation and duplicate detection.
TNZ accepts a repeated caller-supplied MessageID as a new request. The resulting callbacks use that same ID and represent independent messages, so MessageID alone cannot distinguish them; this is to support Conversation IDs as a tracking parameter. Omit MessageID from the sending request if you want TNZ to return a unique UUID.
Make each business action safe to repeat. When your application can identify an event it has already processed, return a 2xx response without performing the action again.
Acknowledgements and retries
- Any HTTP
2xx response acknowledges the webhook, including 200, 202, and 204.
- If the TNZ webhook sender does not receive a
2xx response, it retries the webhook every five minutes.
- Retries continue for up to 24 hours.
- Connection failures, timeouts, and non-
2xx responses can therefore produce duplicate deliveries.
- TNZ submits events as their data becomes available and does not preserve delivery order.
Do not delay the response while waiting for an external system if you have already stored the event safely. Return a 2xx response and retry that downstream work within your own application.
Be careful with third-party webhook inspection toolsA service such as
Webhook.site receives the full request, including webhook credentials and message data. Prefer an endpoint controlled by your organisation. If you use an inspection service, use synthetic data and temporary credentials approved for exposure.
Troubleshooting
| Symptom |
What to check |
| No webhook arrives |
Confirm the callback URL is complete and uses HTTPS. Check the relevant result or reply report method is set to API, or that the sending request uses NotificationType: Webhook. |
| The receiver returns 401 or 403 |
Check the Authorization header uses Bearer followed by the configured Webhook Callback APIKey. Also compare X-Sender with Webhook Callback Sender. |
| TNZ retries after the event was processed |
Make sure the receiver returns a 2xx response promptly after storing the event. Add duplicate detection so a retry cannot repeat the business action. |
| The payload is not JSON |
Check the User's Webhook Callback Format and any per-message WebhookCallbackFormat override. |
| A result arrives but a matched SMS reply does not |
Confirm the original request used the intended callback URL and that SMS reporting is configured for API callbacks. Check whether the inbound payload was classified as SMSInbound rather than SMSReply. |
An inbound SMS has no MessageID |
Check Type. An unmatched SMSInbound event may not have an outbound message to reference; use ReceivedID as its identifier. |
| An email reply does not appear |
Email replies go to the message's sender address rather than through an inbound TNZ webhook. Delivery and bounce results can still use result webhooks. |
Frequently asked questions
What does the API response to a sending request mean?
The response tells you whether TNZ accepted the API request. It does not tell you whether the message was delivered. Use a result webhook, the TNZ Dashboard, or the relevant status query to learn the message outcome.
Common REST API v3.00 responses include:
| HTTP status |
Meaning |
200 |
TNZ accepted the submission. This is not a delivery receipt. |
400 |
The request or supplied data is invalid. |
401 |
The API authentication token is invalid. |
403 |
The request was understood but is not permitted. Check the User's permissions and account restrictions. |
404 |
The requested record or endpoint was not found. |
415 |
The request uses an unsupported content type. |
500 |
TNZ encountered a server error. Contact TNZ if it continues. |
The exact responses depend on the operation. See the REST API documentation for the endpoint you are calling.
Where can I find delivery receipts and diagnostic information?
TNZ provides message status, delivery receipts, and rejection information through result webhooks, API status queries, and the TNZ Dashboard. Webhooks are the usual choice when your application needs these updates in real time.
What values can Result contain?
The values depend on the message channel. See the dedicated result-code guides for SMS, Email, Voice and text-to-speech, and Fax.
What happens if I reuse a MessageID?
TNZ accepts the repeated ID and treats the submission as a new request. The resulting webhooks refer to the same MessageID as if the messages were independent. This can be useful when your application deliberately uses MessageID as a conversation ID (such as when wiring up an AI Agent), but it means that ID alone cannot detect a duplicate send.
If you need a unique message identifier, omit MessageID from the sending request. TNZ returns a unique UUID in the API response.
How do I check whether TNZ accepted a message after my connection dropped?
Supply your own stable MessageID when sending, then use the SMS details operation at GET /sms/{MessageID} if the connection drops before you receive the response.
- If the message is found, TNZ accepted it. Do not resubmit it.
- If the message is not found, the submission did not complete and it is safe to retry.
This is the recommended pattern for preventing an OTP or other time-sensitive message from being sent twice after a lost connection.
Does TNZ limit sending rates or destination countries?
TNZ does not apply a rate limit to sending traffic. API query operations can have their own limits; for example, do not poll the SMS details operation more than once per second.
By default, accounts are enabled for delivery to New Zealand and Australia only. Contact your TNZ representative if you need other destinations.
How are webhook requests authenticated?
Configure Webhook Callback Sender and Webhook Callback APIKey in Users > select the User > API > Reporting. TNZ includes them in the Authorization Bearer header, the X-Sender header, and the payload's Sender and APIKey fields. Validate the configured values before accepting an event.
Does TNZ sign webhooks with HMAC, or publish source IPs for an allowlist?
TNZ does not currently add an HMAC signature or restrict webhook delivery to a fixed source IP range. Authenticate requests using the configurable webhook values, require HTTPS, and apply the timestamp and data-handling checks described above.
How do retries affect duplicates and event order?
If TNZ does not receive a 2xx response, it retries every five minutes for up to 24 hours. A lost acknowledgement can cause the same event to arrive again. TNZ sends webhooks as their data is generated and does not preserve their order, so make event processing safe to repeat and do not make it depend on arrival order.
Does the inbound SMS payload identify the number the customer texted?
For a dedicated receiving number, yes. The inbound event includes the destination number the customer texted, the sender's mobile number, the message body, and the timestamp. Webhook routing can also be configured for a dedicated number.
The built-in shared shortcode does not provide per-number webhook configuration. See Receiving SMS messages for the differences between replies and dedicated receiving numbers.
Does TNZ provide programmable inbound Voice webhooks?
Not currently. TNZ supports inbound Voice services such as IVR and voicemail-to-email, but it does not yet send programmable webhooks for events such as call arrival or call completion.
Can I track SubAccounts and pricing in a result webhook?
Yes. A result webhook includes the SubAccount associated with the message and a Price value showing the amount charged to the TNZ account holder, not an end customer. TNZ can turn off the Price value for reseller accounts when required.
Will TNZ send another result if the carrier changes the status later?
No. The result webhook contains the final result known when the message completes. A retry can repeat that same event, but a later carrier status change does not create another result event.
Does the per-message URL receive matched SMS replies?
Yes. TNZ sends both the result and any matched inbound SMS reply to the per-message WebhookCallbackURL. Use Type to process each event correctly.
Does WebhookCallbackFormat change the HTTP method?
It controls both the method and encoding. GET places fields in a query string. POST sends a form post. JSON sends a JSON POST, and XML sends an XML POST.
Do email replies arrive through this webhook?
No. TNZ can send Email delivery and bounce results to a webhook, but a reply goes to the sender address configured for the message. See How Email Replies and Bounces Work with TNZ.
Related documentation and support
Need help with a webhook?
Contact TNZ with the affected User, MessageID or ReceivedID, event time, callback URL domain, and redacted response or error details. Do not send your APIKey.
Contact TNZ Support →