How the native journey works

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.

🚧

Prerequisites

Before 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

MethodEndpointDescription
GET/oauth2/authInitiate the OIDC authorization flow.
POST/flow/api/v1/initStart 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/tokenExchange 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:

ParameterDescription
client-idYour OIDC client ID (Journey Flow API type)
redirect_uriMust match the registered callback URL on the client
scopeAt minimum openid
response_typeMust be code
response_modeTypically query
code_challengePKCE code challenge (S256)
code_challenge_methodMust be S256
stateRandom value to prevent CSRF
nonceRandom value tied to the ID token

Optional sdk parameter controls what rendering data is included in flow responses:

ValueDescription
webFull response including layout, branding, and render hints.
web-minimalMinimal response: layout, branding, and render hints excluded (web).
ios-minimalMinimal response for iOS.
android-minimalMinimal 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.

ParameterDescription
grant_typeMust be authorization_code.
client_idSame client ID used in step 1.
code_verifierThe plain PKCE verifier string corresponding to the challenge sent in step 1.
codeThe authorization code from step 5.
redirect_uriMust 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:

FieldTypeDescription
screenstringIdentifier of the current journey step (for example, identification, registration).
formsarrayList of Form objects, each containing a widgets array.
layoutobjectLayout descriptor defining the visual arrangement of widgets across forms.
messagesobjectError and informational messages for the current step, including a global message.
hostedUrlstringFallback URL to the hosted login page, if the screen cannot be rendered natively.
finalizeUrlstringPresent when the journey is complete. Pass to finalizeSession().

For the full widget reference, see Rendering reference.

Error handling

  • If messages.global is present in the response, display it to the user, and allow retry.
  • If a screen is encountered that the application cannot render, redirect to hostedUrl to fall back to a hosted journey.
  • If finalizeUrl is 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, and refresh_token using platform-appropriate secure storage.
  • Handle hostedUrl reliably: Any screen the application cannot render must fall back to hostedUrl. 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.