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

smsyra URL for MSG91 (Flow v5)
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/
  1. Swap https://control.msg91.com/api/v5/flow/ for the smsyra URL above (with or without the trailing /).
  2. Put your smsyra key in the authkey header.
  3. Add a provider mapping for each Flow template id, so smsyra knows which DLT template it stands for and the order of its variables.
  4. 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.

Whensmsyra 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