cimplify
TypeScript SDK

Authentication

OTP-based sign-in over phone or email. No passwords. The SDK manages the session token end-to-end; a successful `verifyOtp` call wires the token into every subsequent request.

Construct a client

import { createCimplifyClient } from '@cimplify/sdk'

export const client = createCimplifyClient({
  publicKey: process.env.NEXT_PUBLIC_CIMPLIFY_PUBLIC_KEY!,
})

Full sign-in flow

// 1. Send the code (single string contact: phone in E.164 or email)
const sent = await client.auth.requestOtp('+233244000000')
if (!sent.ok) {
  console.error(sent.error.code, sent.error.message)
  return
}

// 2. Verify: pass the user-entered code first, then the same contact
const verified = await client.auth.verifyOtp('123456', '+233244000000')
if (!verified.ok) {
  console.error(verified.error.code, verified.error.message)
  return
}

// 3. The SDK has already wired the session token into the client.
//    All subsequent requests are authenticated automatically.
console.log(verified.value.customer.id)

requestOtp

Single string argument. The server infers phone vs email from the value. Pass { idempotencyKey } to dedupe a retried send.

// Phone (E.164)
await client.auth.requestOtp('+233244000000')

// Email
await client.auth.requestOtp('jane@example.com')

// Custom idempotency key (otherwise the SDK auto-generates one)
await client.auth.requestOtp('+233244000000', undefined, {
  idempotencyKey: 'send-otp-2024-01-15-abc',
})

verifyOtp

Signature is verifyOtp(code, contact?): the code first, then the contact you sent it to. On success the SDK calls setAccessToken() internally; you do not need to.

const result = await client.auth.verifyOtp('123456', '+233244000000')

if (!result.ok) {
  // Codes you'll see: VALIDATION_ERROR, OTP_EXPIRED, OTP_INVALID
  console.error(result.error.code, result.error.message)
  return
}

const { customer, session_token } = result.value
// session_token is already attached to the client. It's exposed here only
// for cases where you also need to persist it server-side.

Session helpers

const status = await client.auth.getStatus()
if (status.ok) {
  console.log(status.value.is_authenticated)
  console.log(status.value.customer)
  console.log(status.value.session_expires_at)
}

const user = await client.auth.getCurrentUser()    // Result<Customer | null>
const authed = await client.auth.isAuthenticated() // Result<boolean>

updateProfile

Patch the authenticated customer. All fields optional; send only what changes.

const updated = await client.auth.updateProfile({
  name: 'Jane Doe',
  email: 'jane@example.com',
  phone: '+233244000000',
})

if (updated.ok) {
  console.log(updated.value.id, updated.value.name)
}

logout

Clears the server session and the client-side token in one call.

await client.auth.logout()
// client.getAccessToken() is now undefined; subsequent requests are anonymous

React: a sign-in form

'use client'
import { useState } from 'react'
import { useCimplifyClient } from '@cimplify/sdk/react'

export function SignInForm() {
  const client = useCimplifyClient()
  const [contact, setContact] = useState('')
  const [code, setCode] = useState('')
  const [stage, setStage] = useState<'request' | 'verify'>('request')
  const [error, setError] = useState<string | null>(null)

  async function send() {
    const r = await client.auth.requestOtp(contact)
    if (!r.ok) return setError(r.error.message)
    setStage('verify')
  }

  async function verify() {
    const r = await client.auth.verifyOtp(code, contact)
    if (!r.ok) return setError(r.error.message)
    setError(null)
  }

  return stage === 'request' ? (
    <form onSubmit={(e) => { e.preventDefault(); send() }}>
      <input value={contact} onChange={(e) => setContact(e.target.value)} placeholder="Phone or email" />
      <button type="submit">Send code</button>
      {error && <p>{error}</p>}
    </form>
  ) : (
    <form onSubmit={(e) => { e.preventDefault(); verify() }}>
      <input value={code} onChange={(e) => setCode(e.target.value)} placeholder="6-digit code" />
      <button type="submit">Verify</button>
      {error && <p>{error}</p>}
    </form>
  )
}

Method reference

MethodReturns
requestOtp(contact, contactType?, opts?)Result<void>
verifyOtp(code, contact?, opts?)Result<OtpResult>
getStatus()Result<AuthStatus>
getCurrentUser()Result<Customer | null>
isAuthenticated()Result<boolean>
updateProfile(input)Result<Customer>
logout()Result<{ success: boolean }>
  • Checkout Place an order against the authenticated session

  • Orders List and inspect the signed-in customer's orders

  • Error handling CimplifyError shape, OTP_EXPIRED / OTP_INVALID

  • Idempotency Replay-safe OTP requests

On this page