API docs
Verify
WeSend creates, sends and checks the one-time code. You never store it.
Confirming a user's phone or email takes two calls: start a verification, then check the code the user typed. WeSend keeps only a hash of the code.
1. Send a code
/v1/verifyCreates a code and sends it. If to contains @ it goes by email, otherwise by SMS.
Body
tostringrequired- A phone number or an email address.
fallback_emailstring- Where the code goes if the operator refuses the SMS. Only when
tois a phone number. localestring- The message language:
mn(default) oren. brandstring- The name the message starts with, up to 20 characters. Defaults to the project's brand name.
code_lengthinteger- Digits in the code, 4 to 8. Default 6.
ttlinteger- How long the code is valid, in seconds, 60 to 600. Default 300.
curl -X POST https://api.wesend.mn/v1/verify \
-H "Authorization: Bearer $WESEND_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": "99112233",
"brand": "Shop.mn",
"fallback_email": "[email protected]"
}'{
"id": "c4f1e2d3-7a8b-4c9d-a0e1-f2a3b4c5d6e7",
"status": "pending",
"channel": "sms",
"to": "99112233",
"expires_at": "2026-10-06T08:20:30.000Z",
"credits": 70,
"balance": 4930
}The recipient gets “Shop.mn: Your verification code is 482913”. Keep the id for the next step. The price is that of an ordinary one-part SMS, or of an email.
To resend a code, call /verify again. The recipient's earlier pending code stops working.
2. Check the code
/v1/verify/{id}/checkChecks the code the user typed.
Body
codestringrequired- The code the user typed.
curl -X POST https://api.wesend.mn/v1/verify/c4f1e2d3-7a8b-4c9d-a0e1-f2a3b4c5d6e7/check \
-H "Authorization: Bearer $WESEND_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"code": "482913"
}'{
"id": "c4f1e2d3-7a8b-4c9d-a0e1-f2a3b4c5d6e7",
"status": "approved",
"channel": "sms",
"to": "99112233",
"expires_at": "2026-10-06T08:20:30.000Z"
}A correct code answers 200 with status approved. Otherwise:
One recipient may enter at most 10 wrong codes in 24 hours across all verifications. After that even a request for a new code answers 429 max_attempts_reached. This is what stops code guessing.
Read the status
/v1/verify/{id}Returns the current state of a verification.