SSO
Magic link sign-in
When to use
Use magic link sign-in when you want to embed or deep-link customers into the SafeWeb portal from your own application without configuring enterprise SAML.
Prerequisites
- The customer is onboarded and belongs to your partner organization
- The customer has a platform user account
Flow
- Your backend calls
POST /api/v1/integrations/customer/{customerId}/magic-link. - SafeWeb generates a one-time magic link and returns a
url. - You deliver that URL to the customer (redirect, new tab, or in-app browser).
- The customer opens the URL. The portal handles
/auth/confirmwithtoken_hashandtype=magiclink. - The token is verified; on success the customer has an active session and is sent to the portal home configured for your environment.
curl -X POST "https://connect.safeweb.co/api/v1/integrations/customer/{customerId}/magic-link" \
-H "SW-PARTNER-ID: your-partner-id" \
-H "SW-API-KEY: your-api-key"Example response:
{
"success": true,
"url": "https://connect.safeweb.co/auth/confirm?token_hash=...&type=magiclink"
}Link lifetime and sessions
| Property | Behaviour |
|---|---|
| Expiry | Magic links expire one hour after they are created. After expiry, the customer must request a new link (via your integration). |
| Single use | Each link is valid for one successful sign-in. If the token has already been used, confirmation fails and you should generate a new link. |
| Session after sign-in | The portal issues access and refresh tokens. Access tokens are short-lived (typically one hour); the portal refreshes the session while the customer remains active. |
If a customer reports that a link “does not work,” check whether it was already used, has expired, or was opened in an environment that strips query parameters (some in-app browsers or email scanners).
Security
- Treat the returned
urllike a password — anyone with the link can sign in as that customer until it expires (one hour) or is used - Deliver only over HTTPS
- Prefer an immediate redirect from your backend rather than emailing links; if you must email, treat the message as sensitive
- Do not log, cache, or expose URLs in client-side analytics, support tickets, or error reporting
- Prefer server-to-server API calls; never embed your API key in a browser or mobile app
- Request a fresh link for each sign-in attempt; do not reuse URLs across customers or sessions
Integration tips
- Call the API when the customer is ready to sign in, not long in advance — the one-hour window starts at creation time.
- If sign-in fails with an expired or invalid token, call the endpoint again to obtain a new URL.
- Opening the same link twice (e.g. customer double-clicks) consumes the token on the first successful visit; the second attempt fails until you issue a new link.
- Enterprise SSO and magic link sign-in for the same email address are treated as separate sign-in paths; see Enterprise SSO for IdP-based access.
Common errors
| Situation | Typical response |
|---|---|
Invalid or unknown customerId | 404 — customer not found or not owned by partner |
| Customer has no linked platform user | 400 — cannot generate link until the user exists (complete onboarding first) |
| Missing or invalid API headers | 401 / 422 |
| Expired or already-used token (customer-facing) | Confirmation error in the portal — generate a new magic link |
For corporate IdP sign-in instead of magic links, see Enterprise SSO.
API reference
Path Parameters
customerId*string
Customer UUID
Format
uuidHeader Parameters
SW-PARTNER-ID*string
Partner organization identifier
SW-API-KEY*string
API authentication key
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/api/v1/integrations/customer/497f6eca-6276-4993-bfeb-53cbbbba6f08/magic-link" \ -H "SW-PARTNER-ID: string" \ -H "SW-API-KEY: string"{
"success": true,
"url": "https://connect.safeweb.co/auth/confirm?token_hash=example&type=magiclink"
}{
"success": false,
"error": "Invalid route parameters: Customer ID must be a valid UUID"
}{
"success": false,
"error": "Failed to verify org API key"
}{
"success": false,
"error": "Customer not found or does not belong to partner"
}{
"success": false,
"error": "Partner ID and API key are required in headers"
}{
"success": false,
"error": "Failed to generate magic link"
}