Introducing K-OTP

The K-OTP team
Oct 2, 2026

K-OTP is live: a phone verification API for apps serving Korean users.

Many apps need to confirm that a user can receive messages at a Korean phone number, at sign-up, at sign-in, or when an account's number changes. Building that yourself means generating codes, delivering them on a channel Korean users actually read, tracking expiry and attempts, and making sure a retried request never sends a second message. K-OTP handles all of it behind two API calls.

Issue, deliver, verify

  1. Issue. Your server (with an sk_ key) or your web app (with a pk_ key) calls POST /v1/issue with the phone number, a purpose, and an idempotency key. K-OTP generates a 6-digit code and returns an issueId.
  2. Deliver. The code reaches the user as a Kakao AlimTalk message. Its delivery status moves from queued to sent to delivered, and your server can follow it with GET /v1/status. Delivered means the message arrived, not that the user is verified.
  3. Verify. Send the issueId and the code the user typed to POST /v1/verify. The answer is verified: true only when the code matches. Codes expire after 3 minutes and allow 5 attempts by default.

What happens next is up to your app: sign the user in, mark the number as confirmed, or ask again. A verified code shows that the user received the message sent to that number; it is not real-name or identity (KYC) verification. The channels guide covers delivery in detail.

Retries send once

Every issue request carries an idempotency key. If a request times out, send it again with the same key: the same key and the same request return the first result, without a second message or a second charge. A different request under a key you already used is rejected with 409 CONFLICT. When the messaging provider's outcome is unclear, K-OTP never resends on its own; if your user did not get the code, issue a new one when they ask for it. See Idempotency & retries.

Little personal data, kept briefly

Issue records keep only a hash of the phone number. Codes are stored as hashes and never returned by the API. Delivery records need the recipient's number to deliver the message: it is stored encrypted and deleted about 24 hours after the delivery reaches a final status. The privacy policy has the details.

Keys for servers and browsers

Use sk_ secret keys on your server and pk_ public keys in the browser. Public keys work only from the origins you register for them, and only for issue and verify.

Prepaid credits

One credit is one OTP send, whether or not the user goes on to verify; verify calls are free. Credits come in packs with bonus credits, there is no subscription, and purchased credits do not expire. One credit wallet per organization is shared by all of its apps. See the pricing page for the packs.

Get started

Create an account in the console, add an app and a key, and follow the quickstart. The JavaScript and TypeScript SDK, @k-otp/sdk, has browser and server clients, React, Vue and Svelte bindings, and headless UI components. Every endpoint is in the API reference.