This page describes the full request flow behind the native journey for custom integrations that do not use an SDK.
For SDK-based integrations, the SDK handles all of the steps below automatically - you do not need to implement any of this yourself. See the Native journey overview page for the recommended approach.
PrerequisitesBefore starting, your Strivacity application must have a client of the OIDC (using the Journey Flow API) type. See the Application clients documentation for setup instructions.
Flow overview
| Method | Endpoint | Description |
|---|---|---|
| GET | /oauth2/auth | Initiate the OIDC authorization flow. |
| POST | /flow/api/v1/init | Start the journey, get the initial screen. |
| POST | /flow/api/v1/form/{formId} | Submit a form, advance to the next screen. |
| GET | <finalizeUrl> | Finalize the OAuth flow, get the auth code. |
| POST | /oauth2/token | Exchange the auth code for tokens. |
Step 1: Initiate OIDC authorization
GET https://<tenant>/oauth2/auth
?client_id=<clientId>
&redirect_uri=<redirectUrl>
&scope=openid
&response_type=code
&response_mode=query
&code_challenge_method=S256
&code_challenge=<code_challenge>
&state=<state>
&nonce=<nonce>
&sdk=<sdk_mode>
This starts the OAuth 2.0 PKCE authorization code flow. Required parameters:
| Parameter | Description |
|---|---|
client-id | Your OIDC client ID (Journey Flow API type) |
redirect_uri | Must match the registered callback URL on the client |
scope | At minimum openid |
response_type | Must be code |
response_mode | Typically query |
code_challenge | PKCE code challenge (S256) |
code_challenge_method | Must be S256 |
state | Random value to prevent CSRF |
nonce | Random value tied to the ID token |
Optional sdk parameter controls what rendering data is included in flow responses:
| Value | Description |
|---|---|
web | Full response including layout, branding, and render hints. |
web-minimal | Minimal response: layout, branding, and render hints excluded (web). |
ios-minimal | Minimal response for iOS. |
android-minimal | Minimal response for Android. |
Response: HTTP 200 with the login provider URL as a plain string in the response body. Navigate to this URL.
Step 2: Read the session ID from the redirect
After navigating to the login provider URL, Strivacity redirects back to your redirect_uri with a session_id included as a query parameter (or fragment, depending on your response_mode):
https://<your-redirect-uri>?session_id=<sessionId>
No HTTP request is needed: read the session_id value directly from the current URL. All subsequent Journey Flow API calls require it as a Bearer token:
Authorization: Bearer <sessionId>
Step 3: Initialize the journey
POST /flow/api/v1/init
Authorization: Bearer <sessionId>
No request body required. Returns the initial screen state object describing the first step of the journey.
Step 4: Submit forms
POST /flow/api/v1/form/{formId}
Authorization: Bearer <sessionId>
Content-Type: application/json
{
"<widgetId>": "<value>",
...
}
Advance the flow by submitting the values collected for the current form. The formId comes from the forms[].id field of the current screen state. Field names in the request body must exactly match the id of each widget in the form.
Nested object format: The request body is not a flat key-value map. Widget id values use dot notation to describe a path into a nested object, and the submission must reflect that structure. For example, widgets with the ids name.first and name.last must be submitted as:
{
"name": {
"first": "Jane",
"last": "Doe"
}
}
Not as:
{
"name.first": "Jane",
"name.last": "Doe"
}
For each screen, iterate over forms[].widgets to build the UI. Each widget has an id, a type, and type-specific fields (label, value, validators, options, etc.). Collect user input keyed by widget id, apply any validator constraints client-side, and surface messages.global as a top-level error if present. See Rendering Reference for the full widget type reference.
Example: submit identifier screen
POST /flow/api/v1/form/identifier HTTP/1.1
Host: <tenant>
Authorization: Bearer <sessionId>
Content-Type: application/json
{
"identifier": "[email protected]"
}
Success: Returns the next screen state. Repeat until finalizeUrl is present.
Validation failure: Returns the same screen with error messages in messages.
Step 5: Finalize the OAuth flow
When the screen state contains a finalizeUrl, the journey is complete:
GET <finalizeUrl>
Authorization: Bearer <sessionId>
Response: HTTP 302 redirect to your registered redirect_uri with an authorization code:
<redirect_uri>?code=<authCode>&state=<state>
Capture the code value for the next step.
Step 6: Exchange code for tokens
POST /oauth2/token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&client_id=<clientId>
&code_verifier=<codeVerifier>
&code=<authCode>
&redirect_uri=<redirectUrl>
No session token required here; this is a standard OAuth 2.0 token endpoint call.
| Parameter | Description |
|---|---|
grant_type | Must be authorization_code. |
client_id | Same client ID used in step 1. |
code_verifier | The plain PKCE verifier string corresponding to the challenge sent in step 1. |
code | The authorization code from step 5. |
redirect_uri | Must exactly match the value used in step 1. |
Response: JSON with access_token, id_token, and optionally refresh_token.
Screen state object
Every Journey Flow API response returns a screen state object:
| Field | Type | Description |
|---|---|---|
screen | string | Identifier of the current journey step (for example, identification, registration). |
forms | array | List of Form objects, each containing a widgets array. |
layout | object | Layout descriptor defining the visual arrangement of widgets across forms. |
messages | object | Error and informational messages for the current step, including a global message. |
hostedUrl | string | Fallback URL to the hosted login page, if the screen cannot be rendered natively. |
finalizeUrl | string | Present when the journey is complete. Pass to finalizeSession(). |
For the full widget reference, see Rendering reference.
Error handling
- If
messages.globalis present in the response, display it to the user, and allow retry. - If a screen is encountered that the application cannot render, redirect to
hostedUrlto fall back to a hosted journey. - If
finalizeUrlis present, do not render any UI. Proceed directly to step 5.
Additional flow actions
Depending on your journey configuration, the following form endpoints may appear during the flow. Handle them using the same POST/flow/api/v1/form/{formId} pattern.
Reset
Reset the journey to the initial state at any point:
POST /flow/api/v1/form/reset
Authorization: Bearer <sessionId>
Clears all flow progress and returns the same screen state as /flow/api/v1/init. Use this when the user wants to start over, or the flow reaches an unrecoverable state.
Best practices
- Test all branches: Verify login success, login failure, MFA, registration, account activation, and reset flows against your specific journey configuration.
- Store tokens securely: Protect the
access_token,id_token, andrefresh_tokenusing platform-appropriate secure storage. - Handle
hostedUrlreliably: Any screen the application cannot render must fall back tohostedUrl. Do not silently drop unrecognized screens. - Use the SDK where possible: Direct API integration requires manual PKCE, session token management, and handling of evolving flow logic. Strivacity SDKs handle all of this automatically and stay up to date with platform changes.
