Introducing K-OTP
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
- Issue. Your server (with an
sk_key) or your web app (with apk_key) callsPOST /v1/issuewith the phone number, a purpose, and an idempotency key. K-OTP generates a 6-digit code and returns anissueId. - Deliver. The code reaches the user as a Kakao AlimTalk message. Its delivery status moves from
queuedtosenttodelivered, and your server can follow it withGET /v1/status. Delivered means the message arrived, not that the user is verified. - Verify. Send the
issueIdand the code the user typed toPOST /v1/verify. The answer isverified: trueonly 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.