K-OTP

Quickstart

Get a key, send your first verification code, and verify it.

This page walks through the shortest path: issuing and verifying a code from your server with an sk_ secret key. To call the API directly from a browser, also read about pk_ keys in Authentication.

Create an app and keys in the console

In the console, create an app and issue a server-side sk_ key. This example needs the otp:issue and otp:verify scopes. The app's wallet must hold credits before anything is sent (Credits & billing).

Keep the key in an environment variable, never in source code or a client bundle.

export KOTP_SECRET_KEY="sk_..."

Issue a code

Call POST /v1/issue. Every issue request needs an idempotency key. Create a new key (for example a UUID) per request, and send the same key again when you retry that request.

curl -X POST "https://api.k-otp.dev/v1/issue" \
  -H "Authorization: Bearer $KOTP_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 5b0f8f2e-3c1d-4d7a-9a2b-6f1e0c9d8a71" \
  -d '{"phoneNumber":"01012345678","purpose":"login"}'

The success response (200) never contains the code. Store the issueId, for example in the user's session.

{
	"issueId": "0192f3c4-8b7a-7c3e-9a51-2f4d6e8b1a90",
	"expiresAt": "2026-09-28T03:03:00.000Z",
	"attemptsRemaining": 5,
	"queuedAt": "2026-09-28T03:00:00.000Z"
}

Optional fields (channel, template, lifetime, max attempts, …) are listed in the Issue OTP reference. Defaults: SMS, the default template (otp_default_kr), 180-second lifetime, 5 attempts.

Verify the code

Send the 6-digit code the user entered together with the issueId.

curl -X POST "https://api.k-otp.dev/v1/verify" \
  -H "Authorization: Bearer $KOTP_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"issueId":"0192f3c4-8b7a-7c3e-9a51-2f4d6e8b1a90","code":"123456"}'

A failed verification is still HTTP 200. Always check verified.

{
	"issueId": "0192f3c4-8b7a-7c3e-9a51-2f4d6e8b1a90",
	"verified": false,
	"reasonCode": "MISMATCH",
	"attemptsRemaining": 4,
	"expiresAt": "2026-09-28T03:03:00.000Z"
}

verified: true means the user is verified. A verified issue cannot be verified again (one-time). See Issue lifecycle for how to handle each failure reason.

Next steps

On this page