SDK Integration

The integration contract
before you request access

Two things decide whether your integration works: what your payload has to hash to, and which of the two authorization paths an action takes. Both are on this page. The reference documentation, endpoints and SDK packages are delivered with SDK access.

In Short

How do you integrate the Yuthent SDK?

Your app calls the SDK with an actionType, actionContextId, and riskLevel. The device verifies the human and returns a signed proof. Biometric data never leaves the device. Your backend verifies the ACK with Yuthent and executes only on success. One SDK call client-side, verify the ACK server-side. A thin layer.

What You Build

What You Build with Yuthent

Yuthent goes beyond login. It is action-level human verification with signed proof your backend can trust.

Protect Any Action

Login, account recovery, privileged admin actions, approvals, transfers. Not just authentication. Action authority.

Proof Bound to Context

Every approval is tied to a specific action context (actionContextId). Proof cannot be replayed for a different action.

Your Backend Enforces

Your server verifies the proof and decides whether to execute. The app is never the source of truth.

Integration Flow

How Integration Works

Four steps from action request to backend enforcement. Your app collects approval. Your server enforces it.

01

Request Approval

Your app calls the SDK with an actionType, actionContextId, and riskLevel. No PII required.

02

On-Device Verification

The SDK verifies the human on-device and produces a signed proof bundle. Biometric data never leaves the device.

03

Backend Verification

Your backend sends the proof reference to Yuthent Cloud and receives a verified decision (ACK or REJECT).

04

Execute or Block

Your backend executes the action only after verification succeeds. Your server stays the enforcement point.

No biometric data leaves the device at any step.

Action Binding

ACTION_BINDING_INVALID is the contract

You send the action payload with the proof. If what you send does not hash to what the device signed, verification returns ACTION_BINDING_INVALID and you do not execute. That is the whole integration rule, and it is the one error worth writing a test for before you ship.

// what the server does with what you sent
canonical = serialize(actionPayload) // deterministic, key-sorted
computed = base64(sha256(canonical)) // standard base64, padded
computed === signedPayloadHash // continue
otherwise // ACTION_BINDING_INVALID

Two ways to trip it

You mutated the payload between signing and verifying, even by a whitespace-insignificant re-serialize that changes a value. Or you did not send the payload at all. Both return the same code, because from the verifier’s side they are the same failure: it cannot confirm what the human saw.

You cannot turn it off

At Authoritative tier the check is unconditional. Two earlier modes, one advisory and one that skipped the payload, were removed, and there is no tenant setting that restores either. If you are migrating from an integration that relied on one of them, this is the error you will meet first.

It is the same hash on every platform

Android, iOS and the server produce byte-identical canonical bytes from the same payload, held by one golden vector file that ships into all three test suites. You do not need a per-platform branch, and a mismatch is a bug in your payload rather than a difference between the SDKs.

Tier Policy

Policy-Driven Escalation

Your backend policy engine sets the riskLevel per action, and that selects the P/S/E/A tier the SDK enforces. The tier determines how the proof is validated, and whether the action waits on the network.

LOW · SMEDIUM · SHIGH · E

Offline-Capable

Approvals are produced on-device and queued. Your backend syncs the proof later and audits it. Connectivity is not required at action time. HIGH lands on the Explicit tier: the signed proof and the monotonic counter carry the guarantee, so the action completes locally and the proof syncs within the grace window.

Example: clock-in, field approvals, card-not-present, moderate-value transfers

CRITICAL · A

Real-Time Required

CRITICAL is the only level that blocks on the network. It lands on the Authoritative tier, where the synchronous server co-signature is the security boundary, so your backend must verify with Yuthent Cloud before executing. Offline, a CRITICAL action is refused rather than queued.

Example: login, high-value transfers, new beneficiary, account recovery

The Two Paths

Not every authorized action produces a press

If you build assuming a human is challenged every time, you will build the wrong contract and it will fail the first time a customer issues a standing mandate. There are two paths to a valid authorization and your client has to handle both.

Per action

Your policy sets a riskLevel, that selects the tier, and at Explicit or Authoritative the human is challenged for that action. You get a signed proof back and you verify it before executing. This is the path the rest of this page describes.

Under a standing mandate

The human signed the bounds once, in a sealed ceremony: which action types, up to what ceiling, until when. Inside those bounds the action is authorized without interrupting anyone. Nobody is challenged, and that is the design rather than a gap in it.

On the mandate path you ask before you act, and you handle three answers.

MANDATE_AUTHORIZEDHTTP 200

Within bounds. The response carries an ES256 authorizationJws over the tenant, subject, mandate, action type and amount, plus the mandate id and a nonce. No press happened and none is coming. Verify the JWS and proceed.

STEP_UP_REQUIREDHTTP 200

A bound was exceeded, or an oversight actor demanded review. No JWS is issued on this branch. You escalate into the normal sealed ceremony, triggerAction with a mandate context, and the per-action path above takes over from there.

MANDATE_REJECTEDHTTP 403

Terminal, with a reason of MANDATE_REQUIRED when no mandate covers the action, or MANDATE_REVOKED when the one it named has been revoked. This does not escalate and it does not retry. The action fails.

The failure worth designing against is the third one. A revoked mandate fails the next call rather than the next token refresh, so an action that worked a moment ago can stop working with no change on your side. Treat MANDATE_REJECTED as a real state in your flow, not an error to retry.

Data & Privacy

We Don't Need Your Business Data

Biometrics Stay On-Device

Biometric data is never transmitted. Your backend sees decisions and proof references, not biometrics.

Context IDs, Not PII

Payloads use actionType, actionContextId, and riskLevel. No user names, emails, or transaction amounts.

Minimal Payload

The SDK sends only what is needed for verification. Your business logic and user data stay in your system.

For Existing Customers

Already a customer? Use the customer portal for API keys, environments, and monitoring.

Ready to Integrate?

We work directly with engineering teams building security-critical applications. Request SDK access and start a first deployment.