Verify an OTP
Check the code and open the OTP gate for the next 30 minutes.
POST /v1/otp/verifyVerifies the code from /v1/otp/send and
opens the OTP gate for the
patient named in x-end-user-id. Every gated route then accepts requests for that
patient for 30 minutes.
It returns the verification result and nothing else. If you also want the patient's records in the same call, use verify-phone-verification-otp.
Body
| Field | Type | Required | Description |
|---|---|---|---|
otpCode | string | Yes | The code the patient received. |
phoneNumber | string | Yes* | The same number you sent to. |
countryCode | string | No | Defaults to +91. Must match what you sent to. |
channel | string | No | whatsapp (default) or email. |
email | string | Yes* | *Instead of phoneNumber on the email channel. |
Try it
/v1/otp/verifyBody
POST /v1/otp/verify{
"countryCode": "+91",
"phoneNumber": "9811100001"
}https://api.medos.oneUse a dedicated test key, and put your browser's address on its allowlist
A Developer API key authenticates on its own, so it only works from the addresses registered against it — and this page calls from your browser, not your servers. Unless your own public address is on the list you get a 403 naming it, which is the allowlist doing its job. Your browser may also reach us over IPv6 even when your server does not, so the address in the error is often not the one you expected. The key here is kept in memory only and never written to storage, but create a test key for it and deactivate that key when you are done.
Request
curl -sX POST "https://api.medos.one/v1/otp/verify" \
-H "x-api-key: $MEDOS_API_KEY" \
-H "x-end-user-id: $PATIENT_ID" \
-H "Content-Type: application/json" \
-d '{ "countryCode": "+91", "phoneNumber": "9876543210", "otpCode": "418206" }'Response
{
"success": true,
"message": "Phone number verified successfully",
"verified": true,
"channel": "whatsapp",
"sessionId": "svc:billing-sync",
"expiresInMinutes": 30
}| Field | Meaning |
|---|---|
verified | true on success. A failure is a 400, not a 200 with false. |
sessionId | The identity the gate was opened for. For an API key it is dapi: followed by hashes of your key and your x-end-user-id — never the raw values — which is why the next request must carry the same x-end-user-id. |
expiresInMinutes | Always 30. The clock starts now. |
The gate follows x-end-user-id
One API key serves every patient you have, so the gate cannot be keyed to the
key alone — it is keyed to the key and x-end-user-id together. Keep the value
stable across the verify and the booking that follows, and use a distinct value
per patient. Two patients sharing one would share a gate, and one would act on
the other's verification.
Common failures
| Status | Cause |
|---|---|
400 | otpCode missing — { "success": false, "message": "OTP code is required", "verified": false }. |
400 | Invalid or expired code. Send a new one; codes are not reusable. |
400 | Verifying a different destination than you sent to. |