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
| Scope | Allows |
|---|---|
service.customer-auth.users.read | List and read end-users. |
service.customer-auth.users.manage | Create, update, suspend, delete end-users; reset passwords; manage MFA. |
service.customer-auth.sessions.verify | Verify a session token from your backend. |
service.customer-auth.sessions.write | Log 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-view | Renders | Needs a session? |
|---|---|---|
auth (default) | Sign in / create account / forgot / reset password | No |
profile | Profile view + edit (name, avatar upload) | Yes |
mfa | Two-factor enrol / disable | Yes |
logout | A sign-out button | Yes |
<!-- 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:
| Field | Type | Required | Description |
|---|---|---|---|
token | string | required | A session token previously issued by POST /sessions or /sessions/mfa. |
Response fields (inside data):
| Field | Type | Description |
|---|---|---|
user | object | End-user identity (public user shape: id, email, status, etc.). |
session | object | Session id and expiry: { jti, expires_at }. |
session.jti | string (uuid) | Session token id. |
session.expires_at | string (date-time) | When the session expires. |
Manage end-users (server)
| Method & path | Scope | Does |
|---|---|---|
GET /api/v1/services/customer-auth/users?status=&search= | users.read | List end-users. |
POST /api/v1/services/customer-auth/users | users.manage | Create an end-user (idempotent). |
PATCH /api/v1/services/customer-auth/users/{id} | users.manage | Suspend, activate, or update metadata. |
POST /api/v1/services/customer-auth/users/{id}/logout | users.manage | Revoke 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:
| Field | Type | Required | Description |
|---|---|---|---|
email | string (email) | required | End-user email (lower-cased, max 254 chars). |
password | string | required | Plaintext password (8-256 chars; bcrypt-hashed server-side). |
name | string | null | optional | Display name (max 200 chars). |
verified | boolean | optional | When true, create the user active with email_verified_at set (skips email verification). |
metadata | object | optional | Arbitrary 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:
| Path | Field | Type | Description |
|---|---|---|---|
| Without MFA | user | object | End-user identity (public user shape). |
| Without MFA | session | object | The issued session token and metadata: token, jti, issued_at, expires_at. |
| With MFA | mfa_required | boolean | Present and true when an MFA challenge is required. |
| With MFA | challenge_token | string | Short-lived (5 min) MFA challenge token. Pass it to POST /sessions/mfa. |
| With MFA | expires_at | string (date-time) | When the MFA challenge token expires. |
Webhook events
| Event | When |
|---|---|
customer-auth.user.created | A new end-user registers. |
customer-auth.user.verified | An end-user confirms their email. |
customer-auth.user.logged_in | An end-user logs in. |
customer-auth.user.password_reset_requested | An end-user starts a password reset. |
customer-auth.user.password_changed | An end-user changes their password. |
customer-auth.user.suspended | An end-user is suspended. |
customer-auth.user.deleted | An end-user is deleted. |
See Webhooks for payload + signature format.