Set up MSG91 (Flow v5)
Flow API v5 (template id + variables), and the older sendhttp.php. smsyra answers exactly as MSG91 (Flow v5) would, keeps the text in your inbox, checks it against your DLT templates — and sends nothing.
What to change
https://api.shriradhatechnologies.com/p/msg91/api/v5/flow- Method
- POST
- Your key goes in
- the authkey header
- Instead of
https://control.msg91.com/api/v5/flow/
- Swap https://control.msg91.com/api/v5/flow/ for the smsyra URL above (with or without the trailing /).
- Put your smsyra key in the authkey header.
- Add a provider mapping for each Flow template id, so smsyra knows which DLT template it stands for and the order of its variables.
- Still on sendhttp.php? Use /p/msg91/api/sendhttp.php with the authkey parameter; it carries the text and DLT_TE_ID, so it needs no mapping.
Need a key? Create a free workspace and make one on its API keys page — it starts with smy_.
Add a provider mapping
MSG91 Flow never sends the text itself: only a Flow template id and the variable values. A provider mapping tells smsyra which DLT template that id stands for and which value fills which {#var#}, so smsyra can rebuild the text and check it. Without one, the text is kept and marked “Mapping missing”.
The mapping’s reference is the Flow template_id (or flow_id). Add it in the app, under Provider mappings.
Send a test text
curl -X POST "https://api.shriradhatechnologies.com/p/msg91/api/v5/flow" \
-H "authkey: smy_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"template_id":"6634c1f2d6fc0523b82c0a12","sender":"ACMEOT","recipients":[{"mobiles":"919876543210","otp":"482913","minutes":"10"}]}'What smsyra answers
The same status and body MSG91 (Flow v5) gives when it takes a text (HTTP 200), so your code carries on as it would in production:
{"message":"5762846b4f8d285d378b4567","type":"success"}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 200{"message":"Invalid authkey","type":"error","code":"201"} |
| Failure mode: Provider errorThe provider's own error. The text is kept as “Simulated error”. | HTTP 200{"message":"Internal error, please contact your account manager","type":"error","code":"506"} |
| Failure mode: Provider downA 503, as if the provider were down. The text is kept as “Simulated outage”. | HTTP 503{"message":"Service Unavailable","type":"error"} |
| 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 200{"message":"Template mismatch","type":"error","code":"400"} |
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 · Fast2SMS · Twilio · Exotel · smsyra JSON