Retry KYC
Handle a UR-initiated request for a user to redo part or all of their KYC. UR issues a retry directive, notifies you over webhook, and your platform claims a new session and drives the user through th
This page documents retry KYC (also called additional KYC): the flow UR uses when an already-onboarded user must resubmit some or all of their KYC data. Typical triggers are a compliance re-check on a live account, remediation after Fiat24 rejects an account, and an onboarding session that expired before it completed.
Retry KYC reuses the endpoints you already integrated for onboarding. What changes is the entry point: instead of calling /create-account, you claim a session that UR created for you, then run only the steps UR asks for.
Only UR operations staff can start a retry. Neither your platform nor the user can start one. POST /api/fma/v1/kyc/session/create fails with 30034 when no retry directive is pending for the user.
"Retry" means two different things across these pages. They are separate mechanisms and do not share endpoints.
The onboarding restart path is documented on Managed Custody SDK KYC and Shared-token KYC reuse. Do not call /create-account to service a retry directive, and do not wait for a retry directive to let a rejected user try onboarding again.
Who starts it
UR operations only
Your platform
When
The user is already onboarded, and compliance wants data resubmitted
Onboarding failed, for example Sumsub returned RED
How you enter
POST /api/fma/v1/kyc/session/create, after fma.additional_kyc.required
POST /api/fma/v1/create-account again, with the same X-External-User-Id
Scope
Only the steps taskType names
The whole onboarding flow
1. Where this fits
Retry KYC works with the onboarding path your partnerId already uses. The dataChannel field in the webhook payload tells you which path applies to the user, and the steps you run come from that path:
dataChannel
Your onboarding path
Retry entry point for the user data
push
Data push to UR
POST /api/fma/v1/kyc/sync-data
shared-token
POST /api/fma/v1/kyc/reuse-share-token, then POST /api/fma/v1/kyc/check
Partners on the pull integration (dataChannel returns pull) are not covered by the current retry catalogue. If you receive a retry webhook with dataChannel: "pull", use your dedicated integration channel before you act on it.
Two payload fields drive everything you do:
taskTypetells you what the user must redo. Treat this field as authoritative.fiat24Modetells you how the session finishes, and specifically whether you call/kyc/submit.
What to read for your channel
Every section applies to every channel except the per-channel walkthroughs in section 5, which you can read selectively:
Your dataChannel
Read in section 5
Skip
push
Push channel
SDK channel, shared-token channel, and the two SDK-only notes about the access-token timeout and the SDK closing immediately
sdk
SDK channel
Push channel, shared-token channel
shared-token
Shared-token channel
Push channel, SDK channel
Read Webhooks alongside this page for the envelope, signature verification, and delivery contract that apply to both retry events.
2. Lifecycle
The diagram below traces one user end to end: first-time onboarding, registration with the banking partner, going live, and then a retry that UR operations issue later. Part A is onboarding, covered in depth on your channel's own page; part B is what this page documents.
Pick your channel. The retry phases are structurally identical across channels, and only the data collection step differs.
Part A is documented in full on Managed Custody SDK KYC.
No Sumsub SDK is involved on this channel. All data collection happens in your own UI, during onboarding and during a retry alike.
Part A is documented in full on Shared-token KYC reuse.
Registration with the banking partner happens once per user, in part A2. That is why most retries carry fiat24Mode: "ops_offline" and need no /kyc/submit. You see auto_register on a retry only when the user never completed that registration, for example when their first onboarding session expired before it reached submit. In that case the retry finishes registration and you receive fma.account.result with status: "activated" in addition to fma.additional_kyc.completed.
3. Webhooks
Retry KYC uses two events. Both belong to the partner-managed (FMA) event family and are sent only to partners on an FMA integration. Subscribe to both:
fma.additional_kyc.required
UR operations creates the directive
Claiming the session and guiding the user
fma.additional_kyc.completed
The user finishes the last step of the retry session
Recording completion; no further call is required
Subscribe to fma.additional_kyc.required and fma.additional_kyc.completed. UR drops an event that has no subscriber, and your platform receives nothing. Confirm both subscriptions through your dedicated integration channel before production traffic starts.
fma.additional_kyc.required
UR sends the following when the directive is created. Like every UR webhook, the retry events arrive in the standard {event, data, timestamp} envelope described in Webhooks:
The data fields carry the following meaning:
directiveId
string
Identifies this retry request. Use it to correlate the completed event and for support tickets.
type
string
Always retry for this flow. Other values are reserved.
taskType
string
What the user must redo: full, passport, address_recheck, or redo_form_a. See section 5.
retryLevel
number
The retry category UR operations selected. Informational; taskType is the field you act on.
fiat24Mode
string
auto_register or ops_offline. Decides whether you call /kyc/submit. See section 6.
dataChannel
string
push, sdk, or shared-token. Matches your integration path.
externalUserId
string
Your user identifier, the same value you send in X-External-User-Id.
urId
number
The user URID, as a 64-bit integer.
retryOfSessionId
string
The session this retry replaces. That session is already sealed.
retryReason
string
Free text from UR operations. Safe to show to your support staff, not to the user.
requiredFields
array
Push channel only: the exact field paths to correct, for example registerRequest.address.street. Empty for other channels.
deadlineAt
number
Unix seconds, or 0 when no deadline is set. Informational only: UR does not expire the directive or the session when it passes, and no event fires at the deadline. Use it to prioritize your outreach to the user. The consequences of missing it are applied off-platform by compliance.
createdAt
number
Unix seconds when UR created the directive.
fma.additional_kyc.completed
UR sends the following when the retry session completes:
Two data fields differ from the required payload:
sessionIdis the retry session that just completed, the same value/kyc/session/createreturned to you.retryOfSessionIdpoints at the session that the completed session replaced, so the two events carry different values in this field. That difference is expected.
directiveId, taskType, retryLevel, and fiat24Mode carry the same values in both events, so you can match them without extra lookups.
Delivery and idempotency
Both events follow the standard delivery contract in Webhooks: at-least-once delivery, signed with EIP-191, retried with jittered exponential backoff over roughly 48 hours until your endpoint returns 2xx.
Two points specific to retries:
Dedupe on
X-Webhook-Request-Id, as you do for every other UR event. That header is stable across the first delivery and every retry of the same message. Return 2xx only after you persist the event.A resent directive does not produce a duplicate event. UR keys outbound emission on a business key derived from the
directiveIdforrequiredand from thesessionIdforcompleted, so if UR operations resend a directive after a delivery incident, you receive the original message rather than a second one. This is UR-side suppression; it is not a substitute for your own idempotency onX-Webhook-Request-Id.
4. Claim the new session
Call POST /api/fma/v1/kyc/session/create after you receive fma.additional_kyc.required. UR consumes the pending directive and creates the session that carries the reduced step list:
Send the partner signature headers you already use for every FMA endpoint. The body is optional: pass {"externalUserId": "your-user-id"} only when you cannot set the X-External-User-Id header.
Keep the following behaviors in mind:
Retrying the call is safe. If your first call succeeded but you lost the response, calling again returns the same
sessionIdas long as that session is still active. UR does not create a second session.The previous session is gone. UR sealed it when operations created the directive. Calls that carry
retryOfSessionIdfail with30006.One pending directive per user. UR allows at most one pending directive for a user at a time.
Poll the state if you need it.
GET /api/fma/v1/kyc/session/currentreturnssessionId,state, anddataChannelfor the active session.
5. What your users must do
The taskType field maps to the following user actions:
taskType
The user redoes
full
Every data collection step, as in first-time onboarding
address_recheck
Address and location proof, then Form A
passport
Identity document scan and face liveness, then Form A
redo_form_a
Form A only; no data is recollected
For taskType: "passport", the user must complete the document scan and a fresh face liveness capture. UR resets both steps, because a new identity document paired with an earlier face capture would defeat the identity binding that the liveness step exists to prove. Tell your support staff to expect two steps, so they do not treat the liveness prompt as a defect.
The state values a retry session reports
GET /api/fma/v1/kyc/session/current reports the step the user is on. A retry session runs a reduced step list, so it reports step names that never appear during first-time onboarding:
Channel and taskType
state sequence
SDK, passport
IdOrPassportOrOtherIdInformationScan, IdAndLiveness, SignFormA
SDK, address_recheck
AddressProof, SignFormA
SDK, full
ConfirmYourCountryOfResidence, AddressProof, IdOrPassportOrOtherIdInformationScan, IdAndLiveness, SignFormA (questionnaire steps interleave)
SDK or shared-token, redo_form_a
SignFormA only
Push, full
PartnerDataIngestion, IdentityVerification, SignFormA, plus AwaitingPenny when the user takes the penny transfer path
Push, address_recheck or redo_form_a
SignFormA only. The session starts at SignFormA; you patch the data with /kyc/sync-data while the state stays there
Do not exhaustively branch on state. If your onboarding code treats the onboarding state set as closed, or fails on an unrecognized value, a retry session will break it. Treat any unrecognized state as "the user has a step left to do", and drive your integration from taskType and from the endpoint responses instead. Completed and Failed remain the only terminal values.
Push channel
Claim the session
Call POST /api/fma/v1/kyc/session/create and store the returned sessionId.
Resubmit the data
Call POST /api/fma/v1/kyc/sync-data. When requiredFields is non-empty, send only those paths; UR merges them into the stored snapshot. When requiredFields is empty and taskType is full, send the complete payload, because UR starts the snapshot empty for a full retry.
Complete identity verification
Run the identity verification step your integration uses, either the penny transfer or the NFC document read. Only taskType: "full" includes this step on the push channel. When state goes straight to SignFormA, skip it.
Sign Form A
Call GET /api/fma/v1/kyc/form-a-info with the sessionId, present the text to the user, then call POST /api/fma/v1/kyc/sign-form with the sessionId and textHash.
Finish the session
Follow section 6: call POST /api/fma/v1/kyc/submit only when fiat24Mode is auto_register.
SDK channel
Claim the session
Call POST /api/fma/v1/kyc/session/create and store the returned sessionId.
Request a Sumsub access token
Call POST /api/fma/v1/kyc/sumsub-access-token with an empty body. Set your client timeout to 60 seconds or more: before UR issues the token, UR resets the specific Sumsub steps the retry targets and verifies that each reset took effect, which can take up to 30 seconds. If your call still times out, the server side usually finished; call again to get the token.
Launch the Sumsub SDK
Relay the token to your app and launch the SDK. The SDK stops at the step or steps the retry targets, not the whole workflow. The user submits that data and the SDK finishes.
Sign Form A
Call GET /api/fma/v1/kyc/form-a-info with the sessionId, then POST /api/fma/v1/kyc/sign-form with the sessionId and textHash. Poll GET /api/fma/v1/kyc/session/current until state is SignFormA if you need a trigger.
Finish the session
Follow section 6: call POST /api/fma/v1/kyc/submit only when fiat24Mode is auto_register.
If the SDK opens and closes immediately without asking the user for anything, stop and report it through your dedicated integration channel with the directiveId. A retry session must always ask the user for the targeted step. An immediate completion means the data was not recollected, and the result is not valid for the compliance review that triggered the retry.
Shared-token channel
Claim the session
Call POST /api/fma/v1/kyc/session/create and store the returned sessionId.
Have the user redo KYC in your Sumsub tenant
Run the steps that taskType names in your own workflow, then mint a fresh single-use share token scoped to UR's clientId. A token you minted for the earlier session is not valid for the retry session.
Hand off the share token
Call POST /api/fma/v1/kyc/reuse-share-token with the new sessionId and the fresh token, then read the verdict with POST /api/fma/v1/kyc/check.
Sign Form A
Call GET /api/fma/v1/kyc/form-a-info, then POST /api/fma/v1/kyc/sign-form.
Finish the session
Follow section 6: call POST /api/fma/v1/kyc/submit only when fiat24Mode is auto_register.
6. How the session finishes: fiat24Mode
fiat24Mode reflects whether the retry session includes the Fiat24 registration step. A user can register with Fiat24 exactly once in their lifetime, so UR includes that step only for a user who never completed it:
fiat24Mode
Registration step
Your last call
How the session ends
auto_register
Included
POST /api/fma/v1/kyc/submit
UR runs the registration, then sends fma.additional_kyc.completed
ops_offline
Not included
POST /api/fma/v1/kyc/sign-form
The session completes on its own after the last step, then UR sends fma.additional_kyc.completed. UR operations handles the Fiat24 side offline
Do not call POST /api/fma/v1/kyc/submit when fiat24Mode is ops_offline. The call fails with 30007, and the session needs no submit: it completes after the last step. Branch on fiat24Mode rather than always calling submit.
7. Two fields named retryLevel
The webhook payload and GET /api/fma/v1/kyc/session/current both return a field named retryLevel, and the two values mean different things:
fma.additional_kyc.required and .completed payload
The retry category UR operations selected
6 for a document rescan
GET /api/fma/v1/kyc/session/current response
How many sessions the user has had, where 0 is the first onboarding
2 for the user third session
Read the retry category from the webhook payload, and read taskType when you need to know what the user must do. Do not derive either one from session/current.
8. Integration checklist
Confirm the following before you handle production retries:
Your webhook endpoint subscribes to
fma.additional_kyc.requiredandfma.additional_kyc.completed.Your webhook handler is idempotent on
X-Webhook-Request-Idand returns 2xx only after it persists the event.Your client timeout for
POST /api/fma/v1/kyc/sumsub-access-tokenis 60 seconds or more, on the SDK channel.Your code branches on
fiat24Modeand calls/kyc/submitonly forauto_register.Your code branches on
taskType, and your support flow expects a liveness capture whenevertaskTypeispassport.Your code drops any
sessionIdyou cached for the user when a retry directive arrives, and uses thesessionIdfrom/kyc/session/create.Your code treats
deadlineAtas informational and does not block the user after it passes.
9. Error reference
The endpoints in this flow return HTTP 200 with a business code. The following codes are specific to retry KYC:
30034
No pending retry directive for this user
No retry is pending. Do not create a session speculatively; wait for fma.additional_kyc.required. Check that your signature headers identify the same partnerId and externalUserId as the webhook.
30006
sessionId not found
The session is sealed, or it belongs to another user or partner. Claim the retry session and use its sessionId.
30031
No active KYC session for this user
The user has no active session. Claim the retry session first.
30007
Session state does not allow this call
For /kyc/submit, this means the retry flow has no registration step, so the mode is ops_offline. Skip the submit; the session completes on its own.
20007
Form A cannot render because stored data is incomplete
On the push channel, resubmit the missing paths with /kyc/sync-data. On other channels, report the directiveId through your dedicated integration channel.
40003
A UR dependency is momentarily unavailable
Retry the call after a few seconds.
10. Glossary
Retry directive
The record UR operations creates to request a retry. Identified by directiveId.
Retry session
The session UR creates when you call /kyc/session/create for a pending directive. Identified by sessionId.
taskType
The authoritative description of what the user must redo in this retry.
fiat24Mode
Whether the retry session includes Fiat24 registration, and therefore whether you call /kyc/submit.
Form A
The declaration text the user signs before UR can act on the KYC data.
Last updated