API reference · Frontend

SDK & sessions

The endpoints our web, iOS, Android, React Native and Flutter SDKs call. They are safe to call from a browser or app because they never use your client secret. You only need this page if you are building your own client or want to understand what the SDK does.

Two ways for your frontend to authenticate

Publishable keySession token
HeaderX-QuickAuth-Key: pk_live_…Authorization: Bearer …
Where it comes fromDashboard → Settings → Publishable keyYour backend calls Create a session token
LifetimeUntil you revoke it1 hour
Best forMobile appsWebsites, or when you want no long-lived key in the frontend
Rate limit1,000/hour per platform (300/hour from browsers)Per-number OTP limit only

If you send both headers, the publishable key is used. To stop a key being used from apps you do not own, turn on app restriction for the key in the dashboard and register your Android package name, iOS bundle id or website origin. Mobile SDKs send X-QuickAuth-Package (Android) or X-QuickAuth-Bundle (iOS) so the key can be checked.

Always confirm on your backend

Anything your frontend tells your backend can be forged. After the SDK says “verified”, send the requestId to your backend (our SDKs return it; if you call the API yourself you can send the idToken instead) and call Confirm a verification with your client secret before creating the user’s session.

Create a session token

POST/v1/sdk/session

Your backend calls this to get a short-lived token for your website or app. The frontend then calls the SDK endpoints with Authorization: Bearer <sessionToken> instead of a publishable key. Use this when you do not want a long-lived key in your frontend code.

No request body.

AuthServer keyX-Client-Id + X-Client-Secret

Response · 200

  • sessionTokenstring
    Send it as Authorization: Bearer … on SDK calls.
  • expiresIninteger
    Seconds until it expires — 3600 (1 hour).
  • tokenTypestring
    Always Bearer.

Errors

Request
curl -X POST "https://api.quickauth.in/v1/sdk/session" \
  -H "X-Client-Id: YOUR_CLIENT_ID" \
  -H "X-Client-Secret: YOUR_CLIENT_SECRET"
Response200
{
  "sessionToken": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJxYV9saXZlXzhmMmsxbSIsInNjb3BlIjoic2RrIn0…",
  "expiresIn": 3600,
  "tokenType": "Bearer"
}

Refresh a session token

POST/v1/sdk/session/refresh

Issues a new session token. It behaves exactly like Create a session token — you do not send the old token — and exists so SDKs have a clearly named call to make before the hour runs out.

AuthServer keyX-Client-Id + X-Client-Secret

Response · 200

  • sessionTokenstring
    Send it as Authorization: Bearer … on SDK calls.
  • expiresIninteger
    Seconds until it expires — 3600 (1 hour).
  • tokenTypestring
    Always Bearer.

Errors

Request
curl -X POST "https://api.quickauth.in/v1/sdk/session/refresh" \
  -H "X-Client-Id: YOUR_CLIENT_ID" \
  -H "X-Client-Secret: YOUR_CLIENT_SECRET"
Response200
{
  "sessionToken": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJxYV9saXZlXzhmMmsxbSIsInNjb3BlIjoic2RrIn0…",
  "expiresIn": 3600,
  "tokenType": "Bearer"
}

Send an OTP (from your app)

POST/v1/sdk/auth/initiate

The frontend version of Send an OTP. Our SDKs call it for you; call it directly only if you are building your own client. Your account’s default template, sender and code length always apply.

AuthPublishable keyX-QuickAuth-Key

Request body

  • phonestringrequired
    Country code + number, digits only, optional leading +: +919876543210. No spaces or dashes. Indian numbers must be mobiles.
  • channelstringoptionaldefault auto
    Lower case is fine. Any other value is treated as sms.
    auto — your dashboard’s primary channelsmswhatsapp — (or wa)email
  • deviceTokenstringoptional
    Token from this device’s last successful login, for OneTap. Ignored in browsers.
  • deviceInfoobjectoptional
    Free-form device details. Max 4 KB.

Response · 200

  • stateenum
    OTP_SENT — show the code screenVERIFIED — OneTap approved the device; no code sent
  • sessionIdstring
    The verification id. Send it to Verify. (It is the same value the server API calls requestId.)
  • expiresIninteger
    Seconds the code stays valid. Default 300.
  • deviceTokenstring | null
    Save it on the device for OneTap next time. Null in browsers.

Errors

Request
curl -X POST "https://api.quickauth.in/v1/sdk/auth/initiate" \
  -H "X-QuickAuth-Key: pk_live_YOUR_PUBLISHABLE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "phone": "+919876543210",
  "channel": "auto"
}'
Response200
{
  "state": "OTP_SENT",
  "sessionId": "3f9c1a2b7d4e4f0a9b8c6d5e4f3a2b1c",
  "expiresIn": 300,
  "deviceToken": "a41c0f9e2b7d4c6a8e1f3b5d7c9a0e2f4b6d8c1a3e5f7b9d0c2e4a6f8b1d3c5e"
}

Verify an OTP (from your app)

POST/v1/sdk/auth/verify

Checks the code the user typed. A wrong code returns 200 with state: OTP_FAILED. On success, send the requestId (or the idToken) to your backend and confirm it with Confirm a verification before you create the user’s session.

AuthPublishable keyX-QuickAuth-Key

Request body

  • sessionIdstringrequired
    From Send an OTP.
  • codestringrequired
    The code the user entered.
  • deviceTokenstringoptional
    Marks this device as trusted for OneTap when the code is right.
  • deviceInfoobjectoptional
    Max 4 KB.

Response · 200

  • stateenum
    VERIFIEDOTP_FAILED — wrong code; message says how many tries are left
  • verifiedboolean
    Same as state === "VERIFIED".
  • requestIdstring
  • messagestring
  • idTokenstring | null
    Proof of verification for your backend. Valid 5 minutes. Null on a wrong code.

Errors

Request
curl -X POST "https://api.quickauth.in/v1/sdk/auth/verify" \
  -H "X-QuickAuth-Key: pk_live_YOUR_PUBLISHABLE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "sessionId": "3f9c1a2b7d4e4f0a9b8c6d5e4f3a2b1c",
  "code": "482913"
}'
Response200
{
  "state": "VERIFIED",
  "verified": true,
  "requestId": "3f9c1a2b7d4e4f0a9b8c6d5e4f3a2b1c",
  "message": "Verified successfully",
  "idToken": "eyJhbGciOiJIUzM4NCJ9…"
}

Record an app launch

POST/v1/sdk/attribution/launch

Records that your app was opened, with whatever click and referrer data you have, so launches can later be matched to WhatsApp campaign clicks. Our mobile SDKs send it automatically.

Preview: launches are recorded but matching is not switched on yet, so matched is always false today. Safe to call.

AuthPublishable keyX-QuickAuth-Key

Request body

  • qaClidstringoptional
    Click id from a QuickAuth tracked link (also accepted as qa_clid).
  • installReferrerobjectoptional
    Android install-referrer key/values.
  • urlParamsobjectoptional
    Query parameters from the deep link that opened the app.
  • fingerprintobject | stringoptional
    Device fingerprint.
  • deviceInfoobjectoptional
    Device details.

Response · 200

  • matchedboolean
  • campaignIdstring | null
  • templateIdstring | null
  • variantIdstring | null

Errors

  • 401INVALID_CLIENT_CREDENTIALSPublishable key unknown, app not on the key’s allowed-apps list, or the session token is missing, invalid or expired.
  • 429RATE_LIMIT_EXCEEDEDThe publishable key went over its hourly cap (1,000 per hour per platform, 300 for web).
Request
curl -X POST "https://api.quickauth.in/v1/sdk/attribution/launch" \
  -H "X-QuickAuth-Key: pk_live_YOUR_PUBLISHABLE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "qaClid": "c_7Hq2LmX",
  "urlParams": {
    "utm_source": "whatsapp"
  }
}'
Response200
{
  "matched": false,
  "campaignId": null,
  "templateId": null,
  "variantId": null
}

Record a conversion

POST/v1/sdk/attribution/conversion

Records an in-app event such as a purchase. Preview: accepted and logged; conversion reporting is not live yet. Returns 200 with an empty body.

AuthPublishable keyX-QuickAuth-Key

Request body

  • eventstringrequired
    Event name, e.g. purchase.
  • valuenumberoptional
    Order value.
  • currencystringoptional
    ISO code, e.g. INR.
  • qaClidstringoptional
    Click id, if you have it.
  • metadataobjectoptional
    Anything else you want stored with the event.

Errors

  • 400INVALID_REQUESTevent: must not be blank.
  • 401INVALID_CLIENT_CREDENTIALSPublishable key unknown, app not on the key’s allowed-apps list, or the session token is missing, invalid or expired.
  • 429RATE_LIMIT_EXCEEDEDThe publishable key went over its hourly cap (1,000 per hour per platform, 300 for web).
Request
curl -X POST "https://api.quickauth.in/v1/sdk/attribution/conversion" \
  -H "X-QuickAuth-Key: pk_live_YOUR_PUBLISHABLE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "event": "purchase",
  "value": 1499,
  "currency": "INR"
}'
Chat with us