Customer Auth API

Drop-in signup, login and password reset for your own app's end-users. Verify their sessions from your backend with a single call. Your sk_* key routes the request to your workspace (or paired sandbox for sk_test_*).

Scopes

ScopeAllows
service.customer-auth.users.readList and read end-users.
service.customer-auth.users.manageCreate, update, suspend, delete end-users; reset passwords; manage MFA.
service.customer-auth.sessions.verifyVerify a session token from your backend.
service.customer-auth.sessions.writeLog users in, complete MFA, revoke sessions.

Widgets

Customer Auth ships as four separate widgets that share one pk_* key. Pick which one a snippet renders with data-view. The key's domain allowlist gates where any of them can load.

data-viewRendersNeeds a session?
auth (default)Sign in / create account / forgot / reset passwordNo
profileProfile view + edit (name, avatar upload)Yes
mfaTwo-factor enrol / disableYes
logoutA sign-out buttonYes
<!-- The auth widget: drop it on your login page -->
<script src="https://app.softsolz.uk/softsolz.js"
  data-service-id="customer-auth"
  data-public-key="pk_live_…"></script>

Sharing the session with the other widgets

The auth widget posts the session to your page when a user logs in. Store it, then hand it to the profile, mfa and logout widgets with Softsolz.setSession() so they know who is signed in. The token never goes in a URL.

window.addEventListener('message', function (e) {
  if (e.origin !== 'https://embed.softsolz.uk') return;
  if (e.data && e.data.source === 'softsolz' && e.data.type === 'customer-auth.login') {
    var token = e.data.data.session.token;
    // persist token in your app, then:
    window.Softsolz.setSession(token);
  }
});
<!-- Then, anywhere on your app: -->
<script src="https://app.softsolz.uk/softsolz.js"
  data-service-id="customer-auth" data-public-key="pk_live_…"
  data-view="profile"></script>

Softsolz.logout() tells every mounted widget to clear the session. To revoke it server-side, also call POST /sessions/revoke (below). On a server-rendered page you can instead pass the token inline with data-session-token="…", but setSession() is preferred since it keeps the token out of the iframe URL. See Embeds for the loader and allowlist rules.

Verify a session (server)

POST /api/v1/services/customer-auth/sessions/verify · scope service.customer-auth.sessions.verify

Call this from your backend to check the session token the widget hands your app.

curl -X POST https://app.softsolz.uk/api/v1/services/customer-auth/sessions/verify \
  -H "Authorization: Bearer sk_live_…" \
  -H "Content-Type: application/json" \
  -d '{ "token": "…" }'

Response 200:

{ "data": { "user_id": "…", "email": "…", "verified": true } }

Request body fields:

FieldTypeRequiredDescription
tokenstringrequiredA session token previously issued by POST /sessions or /sessions/mfa.

Response fields (inside data):

FieldTypeDescription
userobjectEnd-user identity (public user shape: id, email, status, etc.).
sessionobjectSession id and expiry: { jti, expires_at }.
session.jtistring (uuid)Session token id.
session.expires_atstring (date-time)When the session expires.

Manage end-users (server)

Method & pathScopeDoes
GET /api/v1/services/customer-auth/users?status=&search=users.readList end-users.
POST /api/v1/services/customer-auth/usersusers.manageCreate an end-user (idempotent).
PATCH /api/v1/services/customer-auth/users/{id}users.manageSuspend, activate, or update metadata.
POST /api/v1/services/customer-auth/users/{id}/logoutusers.manageRevoke all their sessions.

Create an end-user

POST /api/v1/services/customer-auth/users · scope service.customer-auth.users.manage. Creates an end-user from a trusted server (idempotent). Returns the public user shape on 201.

Request body fields:

FieldTypeRequiredDescription
emailstring (email)requiredEnd-user email (lower-cased, max 254 chars).
passwordstringrequiredPlaintext password (8-256 chars; bcrypt-hashed server-side).
namestring | nulloptionalDisplay name (max 200 chars).
verifiedbooleanoptionalWhen true, create the user active with email_verified_at set (skips email verification).
metadataobjectoptionalArbitrary tenant-defined metadata.

Log in (server)

POST /api/v1/services/customer-auth/sessions · scope service.customer-auth.sessions.write. Log an end-user in with email + password. Returns a session token, or an MFA challenge if 2FA is enabled.

Response fields (inside data) - the shape depends on whether the end-user has MFA enabled:

PathFieldTypeDescription
Without MFAuserobjectEnd-user identity (public user shape).
Without MFAsessionobjectThe issued session token and metadata: token, jti, issued_at, expires_at.
With MFAmfa_requiredbooleanPresent and true when an MFA challenge is required.
With MFAchallenge_tokenstringShort-lived (5 min) MFA challenge token. Pass it to POST /sessions/mfa.
With MFAexpires_atstring (date-time)When the MFA challenge token expires.

Webhook events

EventWhen
customer-auth.user.createdA new end-user registers.
customer-auth.user.verifiedAn end-user confirms their email.
customer-auth.user.logged_inAn end-user logs in.
customer-auth.user.password_reset_requestedAn end-user starts a password reset.
customer-auth.user.password_changedAn end-user changes their password.
customer-auth.user.suspendedAn end-user is suspended.
customer-auth.user.deletedAn end-user is deleted.

See Webhooks for payload + signature format.