Set up Fast2SMS
bulkV2 with the dlt, dlt_manual, otp and q routes. smsyra answers exactly as Fast2SMS would, keeps the text in your inbox, checks it against your DLT templates — and sends nothing.
What to change
https://api.shriradhatechnologies.com/p/fast2sms/dev/bulkV2- Method
- GET or POST
- Your key goes in
- the authorization header
- Instead of
https://www.fast2sms.com/dev/bulkV2
- Swap https://www.fast2sms.com/dev/bulkV2 for the smsyra URL above.
- Put your smsyra key in the authorization header (the key itself, no “Bearer”).
- On the dlt route, add a provider mapping for each Fast2SMS message id. The dlt_manual and q routes send the text, so they need none.
Need a key? Create a free workspace and make one on its API keys page — it starts with smy_.
Add a provider mapping
On the dlt route Fast2SMS sends its own message id and the values (variables_values=v1|v2|…), never the text. A provider mapping tells smsyra which DLT template that message id stands for, so it can rebuild the text in that order and check it. Without one, the text is kept and marked “Mapping missing”.
The mapping’s reference is the DLT message id on the dlt route. Add it in the app, under Provider mappings.
Send a test text
curl -X POST "https://api.shriradhatechnologies.com/p/fast2sms/dev/bulkV2" \
-H "authorization: smy_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"route":"dlt","sender_id":"ACMEOT","message":"171234","variables_values":"482913|10","numbers":"9876543210"}'What smsyra answers
The same status and body Fast2SMS gives when it takes a text (HTTP 200), so your code carries on as it would in production:
{"return":true,"request_id":"lwdtp7cjyqxvfe9","message":["Message sent successfully"]}The text itself shows up in your inbox the moment it arrives, with the DLT result: Matched, Mismatched (with the first character that differs), or No template.
Test the failures
Each API key has a failure mode, so you can test your retries and error handling without breaking anything. More about failure modes.
| When | smsyra answers |
|---|---|
| A key that is unknown or revokedYour provider's authentication error. Nothing is kept. | HTTP 401{"return":false,"status_code":412,"message":"Invalid Authentication, Check Authorization Key"} |
| Failure mode: Provider errorThe provider's own error. The text is kept as “Simulated error”. | HTTP 400{"return":false,"status_code":415,"message":"Account Disabled"} |
| Failure mode: Provider downA 503, as if the provider were down. The text is kept as “Simulated outage”. | HTTP 503{"return":false,"message":"Service Unavailable"} |
| Failure mode: SlowWaits as long as you set (up to 30 seconds), then answers normally. | The normal answer (HTTP 200), after the wait. |
| Strict DLT on, and the text doesn't matchRefused the way the provider refuses a DLT failure. The text is kept as “Refused (strict DLT)”. | HTTP 400{"return":false,"status_code":424,"message":"Invalid Message ID"}425 Invalid Template on the other routes. |
Read the OTP in your tests
Ask for the newest code sent to a number. The call waits up to 30 seconds for the text to arrive, so a test never sleeps and polls. It takes your key as Authorization: Bearer smy_…, whichever provider sent the text. The OTP API in full.
curl -G "https://api.shriradhatechnologies.com/v1/otp/latest" \
-H "Authorization: Bearer smy_YOUR_KEY" \
--data-urlencode "to=9876543210" \
--data-urlencode "wait=25"It answers HTTP 200 with the code, or 404 NO_MESSAGE after the wait:
{"messageId":"0193…","to":"+919876543210","from":"ACMEOT","body":"482913 is your ACME login code. It is valid for 10 minutes.","code":"482913","codeMethod":"template","candidates":["482913"],"receivedAt":"2026-11-15T10:20:30Z","templateId":"1007123456789012345","dlt":{"status":"MATCHED"}}Other providers
AmazeSMS · MSG91 (Flow v5) · Twilio · Exotel · smsyra JSON