Skip to main content

Documentation Index

Fetch the complete documentation index at: https://setup.despia.com/llms.txt

Use this file to discover all available pages before exploring further.

Flat reference for everything the bridge emits. For per-method documentation, see Auth Methods, Sessions, Backend, and Account.

Payload envelope

Shape of every onClerkEvent callback

Events

Every event name the bridge can emit

Status values

What status strings mean

Error codes

Every error.code and what fires it

Quirks

Bridge behavior worth knowing

Platform support

iOS vs Android, +3 Android divergences

Payload envelope

Every onClerkEvent callback receives an object with this shape:
{
    ok: boolean,                                // false means error present
    event: string,                              // see event names below
    status?: string,                            // success detail
    error?: { code: string, message: string },  // when ok === false
    // plus route-specific fields documented per page
}
Always branch on ok first.
window.onClerkEvent = (r) => {
    if (!r.ok) {
        console.error(r.event, r.error.code, r.error.message)
        return
    }
    // success path
}

Events

Every command emits at least one event. Some routes emit only error envelopes, their success transfers into a different event (for example, OAuth success becomes a signIn or signUp event).
EventEmitted byReference
readyConfigureConfigure
stateState snapshotSession State
tokenJWT refreshForce a refresh
signInAny sign-in reaching a sessionAuth Methods
signUpAny sign-up reaching a sessionAuth Methods
emailCodeEmail OTP flowEmail Code
phoneCodeSMS OTP flowPhone Code
secondFactorMFA continuationMFA
resetPasswordPassword reset flowReset Password
passkeyPasskey registrationPasskeys
authviewAuth Sheet closeAuth Sheet
userprofileUser Profile sheet closeUser Profile
signOutSign OutSign Out
attributionAttribution toggleAttribution Sync
ssrSSR toggleBackend
enterpriseSSOEnterprise SSO errorsSuccess transfers to signIn/signUp
ticketMagic Link Ticket errorsSuccess emits signIn
configure, manual, oauth, appleError envelopes onlySuccess of each transfers to a different event
unknownUnrecognized clerk:// hostReturns unknown_command

Status values

status on signIn, signUp, emailCode, phoneCode, secondFactor, and resetPassword is the raw Clerk SDK status, passed through verbatim. Match complete explicitly and treat anything else as “needs another step.”
StatusMeaning
completeSession established. Payload carries userId and (if present) emailAddress. JWT refresher starts.
needs_identifierSign-in missing the identifier
needs_first_factorPassword or other first factor required
needs_second_factorMFA required, continue with method=second_factor
needs_new_passwordPassword reset required
needs_client_trustTrusted-device challenge required
missing_requirementsSign-up missing email/phone verification
abandonedSign-up timed out

Error codes

Every error envelope follows { ok: false, event, error: { code, message } }. error.message is human-readable (Clerk’s own text for SDK errors, the bridge’s text for guard errors). Error codes are grouped by the route that emits them.
CodeTriggered byMeaning
invalid_keyconfigureKey missing or does not start with pk_
reconfigure_in_progressconfigurePrevious tenant switch still running
reconfigure_failedconfigureSDK reconfigure threw
not_configuredAny non-configure routeclerk://configure not called yet
signout_failedsignoutNetwork error during server-side revoke
token_fetch_failedtokenRefresh failed, window.clerkJWT keeps last value
CodeTriggered byMeaning
unsupported_osAll routesBelow the Clerk SDK runtime minimum (iOS 17+, clerk-android’s minimum API level)
sdk_not_linkedAll routesClerk SDK or prebuilt UI not in the build
unknown_commandUnknown hostFor example, clerk://foo
unknown_methodmanualmethod= not recognized
unknown_actionOTP, reset password, passkeyaction= not recognized for the route
missing_paramsManual flowsRequired field absent
missing_stateOTP verify, reset password steps, MFA continuationA later step called before its prerequisite (shared state, one multi-step flow at a time)
CodeTriggered byMeaning
auth_failedpasswordWrong credentials, account locked, etc. Clerk’s message in error.message
oauth_failedoauthUser cancelled, network error, or provider denied
use_native_appleoauth&provider=appleUse method=apple instead
apple_failedappleUser cancelled Sign in with Apple
CodeTriggered byMeaning
email_code_failedemail_codeCode wrong or expired
phone_code_failedphone_codeCode wrong, expired, or SMS send failed
second_factor_failedsecond_factorWrong code, expired, or strategy error
prepare_not_neededsecond_factor&action=prepareStrategy does not require a prepare step (TOTP, backup codes)
reset_password_failedreset_passwordWrong code, expired, password policy rejected, etc.
CodeTriggered byMeaning
enterprise_sso_failedenterprise_ssoUser cancelled, no SSO connection for the domain, or provider error
ticket_failedticketTicket invalid, expired, or already used
passkey_failedpasskeyUser cancelled or no credential
not_signed_inpasskey&action=registerCannot register a passkey without a signed-in user

OAuth providers

Recognized values for method=oauth. Anything else routes to Clerk’s custom provider handler. google, github, microsoft, gitlab, discord, twitter (alias x), twitch, linkedin, linkedin_oidc, facebook, tiktok, dropbox, atlassian, bitbucket, notion, line, instagram, coinbase, spotify, xero, box, slack, linear, hubspot, huggingface, vercel.
provider=apple is rejected with use_native_apple. Use method=apple for the native sheet on iOS or Apple OAuth via Chrome Custom Tabs on Android.

Quirks

despia() calls for clerk:// routes are fire-and-forget. Results arrive through window.onClerkEvent.Events are not buffered. A handler attached after a command was issued misses the result. Wire window.onClerkEvent before any clerk:// call.fetch() and XMLHttpRequest cannot trigger clerk:// URLs. Use despia() to invoke the bridge.
window.clerkJWT populates a tick after sign-in completion, not synchronously. After configure or any flow reaching status: "complete", the JWT refresher starts and window.clerkJWT is written on the next event loop tick.Read window.clerkJWT on your next API call, or force a synchronous refresh with clerk://token if you need the token immediately in the same handler.
Every inbound URL and every outbound event is printed to the platform console with a [Clerk] prefix (Xcode console on iOS, Logcat on Android). The JWT value itself is never logged. Grep for [Clerk] while debugging to trace exactly what the bridge received and what it emitted.Toggle off with ClerkBridge.LOG = false on Android or loggingEnabled = false on iOS.If window.onClerkEvent is not defined as a function when the bridge tries to emit, the bridge logs a console warning identifying which event was dropped. The most common integration mistake is not defining the handler before the first clerk:// call.
The bridge splits the query string at known-key boundaries, so an unencoded &, #, or = inside a password survives intact.Recognized keys: method, type, identifier, password, newPassword, email, emailAddress, firstName, lastName, username, phoneNumber, phone, code, action, provider, ephemeral, mode, dismissable, key, ticket, enabled, header, domains.Values are percent-decoded once. Unrecognized parameter names are folded into the previous value and silently ignored.
Boolean parameters accept true, false, 1, 0, yes, no (case-insensitive).Mode values are lowercase: signin, signup, signinorup (aliases signin_or_up, default).Status values pass through verbatim from the Clerk SDK. Match complete explicitly and treat anything else as “needs more steps.”Phone numbers are normalized to E.164 natively. +1 (555) 123-4567, %2B15551234567, and +15551234567 all reach Clerk as +15551234567.
On the server, trust only the verified sub claim from the JWT. Never accept a client-reported userId as proof of identity. The JWT is verifiable against Clerk’s JWKS, but client-supplied IDs are not.See Backend for verification patterns.

Platform support

Same clerk:// URLs, event names, status strings, error codes, and payload shapes work identically on iOS and Android. Implementation differences happen under the hood, the JS contract is the same.

Under-the-hood differences

ConcerniOSAndroid
Secure session storageKeychainAndroid Keystore
Apple Sign InNative ASAuthorizationControllerApple OAuth via Chrome Custom Tabs
OAuth provider flowASWebAuthenticationSessionChrome Custom Tabs
Sheet containerView controller (page sheet)Activity (bottom sheet dialog)
Passkey provideriCloud KeychainGoogle Password Manager (Credential Manager, API 28+)
Runtime minimumiOS 17+clerk-android’s minimum supported API level
apple_failed exists on Android too, even though the underlying flow is OAuth rather than the native sheet.

Input-inert on Android

Three optional parameters are accepted on both platforms for schema parity but currently have no native effect on Android due to clerk-android SDK limitations. Passing them on Android is a no-op rather than an error.
ParameteriOS behaviorAndroid behavior
clerk://authview?mode=...Opens the requested screen (signin, signup, or signinorup)Always opens the combined sign-in-or-up screen. clerk-android-ui’s AuthView() does not expose a mode parameter
method=oauth&ephemeral=trueSkips shared browser cookies via ASWebAuthenticationSessionInert. Chrome Custom Tab has no ephemeral session option
method=enterprise_sso&ephemeral=trueSkips shared browser cookiesInert. Same SDK limitation as OAuth

Custom OAuth providers

All 26 named providers in the OAuth providers list resolve identically on both platforms. An unrecognized provider value (a custom Clerk OAuth provider configured in your dashboard) runs as Clerk’s generic CUSTOM strategy on Android, the bridge cannot carry the specific provider key. On iOS the exact custom provider key is preserved end-to-end. In both cases the flow runs rather than failing.

Resources

NPM Package

despia-native