{BASE} = https://authentica-merge-integration.t2.sa.

Request body

You register exactly one URL for the app: returnUrl, the GET landing page. There is no second URL to register — nothing is delivered to your server, so there is no receiver to point at. See Get your credentials.

returnUrl is matched as a whole string

Registration is an exact, case-sensitive, whole-string comparison against the URLs on your app. Not a prefix match, not a host match:
  • no trailing slash unless the registered value has one
  • no query string appended
  • http vs https, www vs bare host, and localhost ports all matter
Any mismatch fails the session create with invalid_return_url — the browser never leaves your app, so this shows up in your own logs, not the user’s.

Channel (sms only)

OTP is delivered by SMS to a phone number: Any other value → invalid_channel. A missing or unusable destinationdestination_required.

Operation sensitivity

How risky the action behind this session is. Set by your backend when creating the session: Sensitivity is per session, so the same integration can use "normal" on one route and "sensitive" on another. Anything other than those two values → invalid_operation_sensitivity.

Example

curl

Idempotency

POST /session is the call your HTTP client retries on timeout, and the one that costs money in SMS — so a retry must not text the user twice. Send an optional Idempotency-Key header (any unique string per logical attempt, up to 255 characters), following the IETF Idempotency-Key draft: Only a successful response is stored for replay — a failure is retryable as normal. Keys are retained for 24 hours and are scoped to your client_id.
Do not reuse one key for two different attempts. “Retry of the same attempt” gets the same key; “the user pressed send again” gets a new one — otherwise the second attempt either replays a stale response or fails with 422.

Success response

HTTP 200, isSuccess: true:

The handoff token

handoff is the capability that opens the hosted verify page. It is:
  • Single-use — redeemed the first time it is POSTed to verifyUrl. A replay returns 400.
  • Short-lived — TTL expiresInSeconds (120 s today). Create the session at the moment the user is ready to verify, not minutes ahead.
  • URL-forbidden — it must only ever travel in a request body. GET {verifyUrl} with any query string is rejected with 400.
Pass verifyUrl and handoff down to the browser together, and hand off with an auto-submitting form — see Frontend overview.

Client platform (web / mobile)

platform tells Authentica which kind of client finishes the flow. Your backend sets it per session — a browser cannot choose it, because it rides on the authenticated POST /session call. It only changes which returnUrl schemes are accepted; the return itself is unchanged. Either way the return carries the same ?session_id=…&state=…; only the accepted returnUrl schemes differ. A mobile return is just that same ?session_id=&state= appended to your registered deep link. For the full mobile integration, see Mobile apps.

Common errors

What to do with the response

  1. Store sessionId next to state on the pending action, along with what the action actually is.
  2. Return verifyUrl and handoff — and nothing else — to your frontend:
The browser POSTs the token into the hosted page. When the user comes back, your landing page reads the outcome with GET /session/{sessionId}.

Where to call this

Only from your backend, inside whichever route owns the action your frontend triggered — /verify/start, /payments/confirm, /profile/change-phone, and so on.