Verification (OTP)
The Verify endpoints handle one-time codes end to end — generation, expiry, attempt limits and validation. You never store the code.
Create a service
A verification service holds the settings for a flow — channel, code length, expiry. Create one with POST /verify/services and reuse its id for every verification.
Start and check
POST /verify/services/{id}/challenges sends a code; POST /verify/services/{id}/checks validates the code the user typed. The code lives on our side only — you send a destination and get back a status. Codes go out by email today; SMS delivery is coming soon. Both calls require the sms:send scope.
cURL
curl -X POST https://api.qsendyx.com/api/v1/verify/services/{service_id}/challenges \
-H "Authorization: Bearer $QSENDYX_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "to": "user@example.com", "channel": "email" }'cURL
curl -X POST https://api.qsendyx.com/api/v1/verify/services/{service_id}/checks \
-H "Authorization: Bearer $QSENDYX_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "to": "user@example.com", "code": "481902" }'OTP endpoints are a favourite abuse target — a script can trigger thousands of verifications. Rate-limit by user and by destination on your side too, not only by IP. This matters most once SMS is enabled, where pumping fraud routes codes to premium numbers to collect a share of the termination fee.