OTP API
Your app sends a one-time code through smsyra; your test reads it back with one call. The call waits for the text to arrive, so a test never sleeps and polls — and no real phone or SIM is involved.
Get the newest code
GET https://api.shriradhatechnologies.com/v1/otp/latest?to=<number>&since=<time or message id>&wait=<0–30> Authorization: Bearer smy_YOUR_KEY
| Parameter | What it does |
|---|---|
to | The number the text went to. 9876543210, +919876543210 and 09876543210 are the same number. |
since | Only texts after this: an ISO time (when your test started) or a message id. Default: the last 10 minutes. |
wait | How long to wait for a text to arrive, 0 to 30 seconds. Default 25. |
It answers with the newest accepted text to that number — the code, how it was found, the text and its DLT result:
{"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"}}codeMethod says how the code was found: from your template’s variable (template), the WebOTP line, a keyword nearby, or a lone 4–8 digit number. candidates lists every number that could have been the code. Nothing arrived in time? 404 with code NO_MESSAGE.
curl -G "https://api.shriradhatechnologies.com/v1/otp/latest" \
-H "Authorization: Bearer smy_YOUR_KEY" \
--data-urlencode "to=9876543210" \
--data-urlencode "wait=25"In a test
// a Playwright test: sign in with a code, no phone needed
const started = new Date().toISOString();
await page.getByLabel("Mobile number").fill("9876543210");
await page.getByRole("button", { name: "Send code" }).click();
const res = await request.get("https://api.shriradhatechnologies.com/v1/otp/latest", {
params: { to: "9876543210", since: started, wait: "25" },
headers: { Authorization: `Bearer ${process.env.SMSYRA_KEY}` },
});
expect(res.status()).toBe(200);
const { code } = await res.json();
await page.getByLabel("Code").fill(code);Keep the key in your CI’s secrets, not in the test file.
More calls for tests
| Call | What it does |
|---|---|
GET /v1/messages?to=&limit=20 | The latest texts to a number, newest first. |
GET /v1/messages/{id} | One text in full: the body, the DLT check, the request and the answer. |
DELETE /v1/messages?to= | Delete every text to a number — clean up between tests. Answers {"deleted": n}. |
Every call takes the same key as Authorization: Bearer smy_…, whichever provider sent the text. At most 10 waits can be open at once per key; more get 429.
Next: make a key fail on purpose to test your retries.