Frequently Asked Questions
Possible reasons include incorrect callback URL configuration in the Sinch dashboard, forgetting to set 'delivery_report' in the send request, server or firewall issues, or errors in the webhook handler code. Check logs in your application, ngrok, and the Sinch dashboard for clues.
Use the Sinch SMS API with a Node.js library like Axios to send messages. Create a request payload including the recipient number, message body, your Sinch number, and set 'delivery_report' to 'full' or 'per_recipient' to receive delivery status updates via webhooks. Send the POST request to the /batches endpoint of the Sinch API using your Service Plan ID and API token for authentication.
A DLR callback is a notification Sinch sends to your application's webhook URL when the status of a sent SMS message changes (e.g., delivered, failed). This provides real-time feedback on message delivery outcomes.
ngrok creates a public, secure tunnel to your locally running application, allowing Sinch to send DLR webhooks to your local development environment. It's essential for testing the callback functionality without deploying your application.
Use 'full' for a summary of delivery status changes per message batch, suitable for basic tracking. 'per_recipient' sends individual callbacks for each recipient's status change (more detailed but potentially noisier), which is often preferred for granular tracking and analysis.
Yes, create a POST route in your Express app that matches the callback URL configured in your Sinch account. The route handler should parse the JSON payload, log the status, and update your internal systems based on the reported message status (e.g., delivered, failed). Ensure the endpoint responds quickly with 200 OK.
Store your Sinch Service Plan ID, API Token, Sinch virtual number, and region in a .env file. Load these environment variables into your Node.js application at runtime using the 'dotenv' package. Never hardcode API credentials directly in your source code, as it poses security risks.
The optional 'client_reference' field lets you send a custom identifier (e.g., your internal message ID) along with the SMS request. Sinch includes this reference in the DLR callback, allowing you to easily link the status update to the original message in your database.
Log into your Sinch Dashboard, navigate to SMS > APIs > Your Service Plan ID. Under 'Callback URLs', enter the HTTPS URL of your application's webhook endpoint, which is usually your server address plus '/webhooks/dlr', e.g., https://your-server.com/webhooks/dlr or https://your-ngrok-id.ngrok.io/webhooks/dlr.
The 'Delivered' status typically indicates successful delivery of the SMS message to the recipient's handset. However, there can be carrier-specific nuances, and it's not always a 100% guarantee of being read by the recipient.
Use a queue system like Redis, RabbitMQ, or BullMQ. Your webhook handler should quickly acknowledge receipt of the DLR and then place the DLR data onto the queue for background processing. This improves responsiveness and prevents blocking the main thread.
Always use HTTPS. If Sinch supports it, implement signature verification using a shared secret to authenticate webhooks. Consider IP whitelisting if Sinch provides its outgoing IP addresses. In any case, rate-limit your webhook endpoint to mitigate abuse.
Log the failure reason and status code from the DLR. Update your application's message status accordingly. Implement retry mechanisms with exponential backoff, but respect potential opt-outs or blocks to avoid excessive sending attempts. Notify administrators or users about critical failures.
Create a table with columns for a unique message ID, Sinch batch ID, client reference, recipient, sender, message body, status, timestamps, error messages, and any other relevant metadata. Index the Sinch batch ID and client reference for fast lookups.
Process DLRs asynchronously. Use database indexing for efficient lookups. Implement connection pooling for database interactions. Load test your application to identify bottlenecks. Consider caching status information (with appropriate invalidation) for frequently accessed data.