/v1/otp/verify response, you can register an optional per-request callback URL to receive async notifications when verification succeeds or fails.
This is separate from registered app webhooks (SMS delivery events). Flake callbacks are one-off: you pass callback_url on a specific request, resend, or verify call — no webhook registration in the dashboard is required.
When to use callbacks
How it works
- Request or resend — pass optional
callback_urlandcallback_secret. Karibu associates them with this OTP for its lifetime (minutes_to_expire, default 10 minutes), scoped to the Developer App bound to yourX-API-Keyand the phone number. - Verify — you get the normal synchronous
/verifyresponse first. If a callback URL was set on request/resend (or passed again on verify), Karibu also sends an async webhook to that URL shortly after. - Your endpoint — receives a JSON
flake.verifiedorflake.failedenvelope. Respond with 2xx; Karibu retries on failure.
/v1/otp/invalidate, or issuing a new /request or /resend, replaces the callback association for that (phone, app) pair.
Request fields
Available onPOST /v1/otp/request, POST /v1/otp/resend, and POST /v1/otp/verify:
On verify, you may pass
callback_url without callback_secret — Karibu reuses the secret from the original request/resend when available.
Events
The plaintext OTP code is never included in callback payloads.
flake.verified payload
flake.failed payload (max attempts)
Outbound request shape
Signature verification matches registered webhooks: HMAC-SHA256 over the raw request body bytes.
Testing callbacks end-to-end
Use a public HTTPS request inspector (e.g. webhook.site) or your own staging endpoint.Step 1 — capture a callback URL
- Open webhook.site (or similar) and copy your unique HTTPS URL.
- Optionally choose a test secret, e.g.
test-callback-secret-123.
Step 2 — request an OTP with callback
Use an API key bound to your Developer App — the examples below need onlyX-API-Key.
expires_at, not the code.
Step 3 — verify the code
Submit the code the recipient received:POST with event: "flake.verified".
Step 4 — verify the signature (optional)
If you setcallback_secret, confirm X-Briq-Signature matches HMAC-SHA256 of the raw body. See Webhooks → Verifying signatures.
Step 5 — test failure callback
Request a new OTP (samecallback_url), then call /verify three times with wrong codes. On the third failure you should receive flake.failed with reason: "max_attempts".
API playground
The Karibu OTP API reference documentscallback_url and callback_secret on request, verify, and resend. Use the interactive playground on those endpoints with a bound API key and a webhook.site URL.
422 on bad URLs.
http:// URLs, localhost, and hostnames that resolve to private IPs are rejected at request validation time with a 422 body error — before any OTP is sent.Best practices
- Return 2xx quickly from your callback handler. Briq retries on non-2xx responses with exponential backoff.
- Make handlers idempotent — use
data.flake_idor envelopeidto deduplicate. - Do not block login on callbacks — proceed from the synchronous verify response; process the webhook asynchronously.
- Rotate
callback_secretper environment (staging vs production) and store it server-side only. - Use resend to update the callback — a new
callback_urlon/resendreplaces the callback target for the new OTP window.
What’s next
- Requesting OTP codes — full request payload reference
- Validating OTP codes — verify flow and attempt handling
- Karibu OTP API reference — endpoint contracts and OpenAPI playground