Skip to main content
Once a code is in flight, three lifecycle endpoints let you keep state coherent without rebuilding the request flow: All three are scoped to the Developer App bound to your X-API-Key. Karibu resolves the app from the key — omit app_key when the key is bound. An OTP issued under app A cannot be touched via app B.

Resend

Issue a new OTP after invalidating the previous one. Body shape and channel-specific fields are identical to /v1/otp/request; only the path changes.

Common request fields

These fields are the same on every channel: sender_id and message_template are SMS-only — they appear in the SMS tab below and are silently ignored on "call" and "whatsapp".

Success response

Errors mirror /request exactly. See Error scenarios.
request vs resend — what’s the difference? Functionally both invalidate any prior active OTP and dispatch a new one. Use /resend when the end user explicitly clicks “Resend code”; this lets you treat it differently in your analytics, rate-limits, or UI without changing payloads.
Switching channels on resend is allowed — e.g. user clicks “I didn’t get the SMS, send via WhatsApp instead.” Just send the new delivery_method. The previous active OTP is invalidated regardless of which channel issued it.

Channel-specific payload & code samples

Customisable via sender_id and message_template.Channel-specific fields:

Invalidate

Force-expire any active OTP for a phone scoped to the Developer App bound to your X-API-Key. Useful on logout, security events (suspicious activity, password change), or when the user changes their phone number.

Request body

Success response

Idempotent. Calling this when there is no active OTP also returns 200 — it simply has nothing to invalidate. Safe to fire from a logout handler without checking state first.
Callbacks cleared. /invalidate also removes the callback association for that (phone, app) pair. Issue a new /request or /resend with callback_url if you need callbacks on the next OTP.

Code samples


Status

Inspect the currently active OTP for a phone, scoped to the Developer App bound to your X-API-Key, without triggering a send. Useful for UI countdowns, diagnostics, and idempotent UX (e.g. “an OTP was already sent — please check your phone”).

Query parameters

Success response

No active OTP

The HTTP response body wraps status_code: 404, but the underlying HTTP response itself is 200 OK. Inspect body.success and body.status_code, not the raw HTTP status, when handling this endpoint.

Code samples


Best practices

  • Use /status to drive countdown UI, not speculative resends. Polling is cheap; firing duplicate /request calls invalidates the in-flight code and confuses the user.
  • Always invalidate on logout. It’s idempotent — no need to check state first.
  • Treat is_valid: true, remaining_attempts: 0 as a locked OTP. The user has burned all 3 attempts and must resend.
For full payload tables, error matrices, and the canonical reference, see the Karibu OTP API reference.