OTP en telefoonverificatie via SMS voor AI-coders
Bouw SMS-verificatie in elk project vanuit Claude Code, Cursor, Windsurf of gewoon over HTTP. Codes gaan via je gekoppelde Android, de vergelijking draait constant-time en een harde cap van 5 codes per nummer per dag stopt misbruik nog voor het begint.
Twee endpoints, één retour
Dezelfde logica of de aanroep nou van een AI-assistent via MCP komt, een externe client over HTTPS of je eigen backend.
send_otp
Genereert een code, slaat de hash op met geldigheid en pogingenteller, en duwt de SMS via je gekoppelde Android naar buiten.
Gebruiker leest 'm
De klant krijgt de SMS op zijn toestel en tikt de code in jouw verificatieformulier.
verify_otp
Constant-time vergelijking met de laatst verstuurde code. Geeft verified terug plus het aantal resterende pogingen bij een mismatch.
Alleen POST, Bearer-auth
GET geeft 405. Cookies worden genegeerd. De API-key staat nooit in een URL of in browser-history.
Send-endpoint
POST https://app.sms8.io/ajax/otp-send.php
- phone — verplicht, E.164
- length — 4 tot 8 cijfers, standaard 6
- expires_in — 60 tot 900 seconden, standaard 300
- max_attempts — 1 tot 10, standaard 5
- template — bericht met de placeholder
{code} - option / devices / useRandomDevice — device picker
Verify-endpoint
POST https://app.sms8.io/ajax/otp-verify.php
- phone — verplicht, E.164
- code — de code die de gebruiker tikte
Responses:
{verified: true}bij succes{verified: false, reason: "code_mismatch", attempts_left: 4}- Andere redenen:
expired,not_found,max_attempts
Werkende calls
OTP versturen
curl -X POST https://app.sms8.io/ajax/otp-send.php \ -H "Authorization: Bearer YOUR_SMS8_API_KEY" \ -d "phone=+31612345678" # Override de defaults: # -d "length=6" -d "expires_in=300" # -d "max_attempts=5" # -d "template=Je code is {code}, verloopt zo." # Kies device of SIM: # -d "option=0" --data-urlencode 'devices=["DEVICE_ID"]' # -d "option=1" # broadcast over alle devices # -d "option=2" # broadcast over alle SIMs # -d "useRandomDevice=1" # random afzender
Code verifiëren
curl -X POST https://app.sms8.io/ajax/otp-verify.php \ -H "Authorization: Bearer YOUR_SMS8_API_KEY" \ -d "phone=+31612345678" \ -d "code=123456" # Goed: {"verified": true} # Fout: {"verified": false, "reason": "code_mismatch", "attempts_left": 4}
Vanuit een AI-assistent (MCP)
Hangt Claude Code, Cursor of Windsurf aan mcp.sms8.io, zeg dan: "Bouw SMS-verificatie in m'n signup-flow met sms8 MCP". De assistent roept send_otp en verify_otp met je defaults en regelt de bestaande signup- of login-routes.
Per-user defaults vanuit het dashboard
Eén keer instellen. Ze gelden zodra een aanroeper een veld leeg laat. De harde limieten gelden altijd, wat je ook doet.
Codelengte
4 tot 8 cijfers. Standaard 6. Korter = makkelijker te onthouden, langer = lastiger te raden.
Geldigheid
60 tot 900 seconden. Standaard 300 (5 min). Kort genoeg tegen replay, lang genoeg om in te tikken.
Pogingen
1 tot 10 foute pogingen voordat de code op slot gaat. Standaard 5.
Resend-cooldown
30 tot 600 seconden tussen verzendingen naar hetzelfde nummer. Standaard 60.
SMS-template
Pas de tekst aan aan je merk. Eén regel: de placeholder {code} moet erin staan.
Pas je defaults aan
Live preview reageert op elke aanpassing. Stuur een echte OTP naar je toestel en loop de hele flow door.
Harde caps die je klanten beschermen
5 OTPs per nummer per 24 u
De hardste cap. Niet ophoogbaar. Ook als je key uitlekt, krijgt niemand meer dan 5 codes in 24 rollende uren.
Transactie-locked checks
Cooldown en 24u-cap draaien onder SELECT ... FOR UPDATE. Parallelle aanroepen kunnen er niet omheen.
Constant-time verify
verify_otp gebruikt hash_equals voor de vergelijking. Geen timing-leaks.
Alleen POST, geen cookies
GET op beide endpoints geeft 405. Cookies worden bij auth genegeerd. CSRF via image tag bestaat niet.
Per-OTP pogingenlimiet
Standaard 5 foute pogingen per code. Daarna gaat de code op slot en moet er een nieuwe send_otp komen.
Generieke foutmeldingen
Interne fouten geven Internal error terug. Stack traces komen nooit bij de client uit.
Vragen over OTP
Hoe verstuur ik een OTP via SMS8?
POST naar https://app.sms8.io/ajax/otp-send.php met het telefoonnummer. Het endpoint accepteert een Authorization: Bearer header. Optionele velden: length (4 tot 8), expires_in (60 tot 900 s), max_attempts (1 tot 10), template, plus een device picker.
Hoe werkt verify_otp?
POST het nummer en de code die de gebruiker tikte naar https://app.sms8.io/ajax/otp-verify.php. De server doet een constant-time vergelijking met de laatste OTP en geeft verified: true of verified: false. Bij falen krijg je reason en attempts_left.
Wat is de OTP-abuse cap?
Elk nummer krijgt maximaal 5 OTPs in een rollende 24 uur. Harde cap, niet ophoogbaar, beschermt de ontvanger ook als je key uitlekt.
Heb ik A2P 10DLC nodig voor SMS OTPs via SMS8?
Nee. SMS8 stuurt OTPs via je gekoppelde Android en SIM, dus A2P 10DLC-registratie hoeft niet.
Kan de assistent OTP-verificatie zelf inbouwen?
Ja. De Skill die met Claude Code meekomt leert de assistent wanneer send_otp en verify_otp te roepen. Een prompt als Bouw telefoonverificatie in /signup is genoeg.