Skip to main content
Use this flow when you do not operate a Sumsub account. Pods creates the verification, returns a link, and the applicant completes document, selfie, and personal data in the browser. When the verification is approved, Pods finishes the onboarding with the local KYC/AML provider and the profile unlocks Brazil Pix (brlaEnabled). You never handle documents or selfies, and you never generate a share token. You make two kinds of calls: one to start (or restart) the verification, and one to read the result.
Pods Hosted KYC is enabled per account. Ask Pods to enable it before you integrate; until then POST /api/v1/kyc/hosted/sessions returns 403 HOSTED_KYC_NOT_ENABLED.

Before you start

The flow

1

Create the session

Your backend sends the CPF, email, and wallet. You get back a kycUserId and a verificationLink.
2

Open the link

Open verificationLink in the applicant’s browser or a web view. The applicant verifies on the Pods-hosted page.
3

Poll the status

While the applicant verifies, and after they return, poll GET /api/v1/kyc/status until the status is terminal.
4

Handle the outcome

approved unlocks Pix. rejected_retryable can be retried. rejected and blocked are final.

1. Create a session

POST /api/v1/kyc/hosted/sessions
Store kycUserId: it is the only handle you need for status polling and retries. The CPF is never returned. The call is idempotent by CPF. Calling it again for the same CPF returns the same kycUserId. You get the same link while it still has more than five minutes left, and a fresh link after that. It is safe to call whenever your app needs the link again.
verificationLink is a bearer link: anyone who has it can use the verification. Do not log it, and hand it only to the applicant.
If you already verified this person, through this flow or another Pods KYC flow, the response is that profile, with status: "approved" and verificationLink: null: there is nothing to open. To add a wallet, call POST /api/v1/kyc/{kycUserId}/wallets with the kycUserId returned. A person verified only by another Pods customer goes through the verification like anyone else. A profile under analysis, rejected, or blocked also returns no link. Open verificationLink for the applicant. It works until verificationLinkExpiresAt. After a successful verification the applicant is redirected to your redirectUrl.
The redirect is only a hint that the applicant finished. It is not a verdict, and it may never happen (the applicant closes the tab, loses connection, or finishes on a page opened after the link expired). Always read the result from GET /api/v1/kyc/status.
A link that expired does not end the verification. The applicant stays the same: call the session endpoint again for a new link, and keep polling the status.

3. Poll the status

GET /api/v1/kyc/status?kycUserId=550e8400-e29b-41d4-a716-446655440000 Start polling as soon as you show the link, not after the applicant clicks, and poll about every 5 seconds while they are on the hosted page. That way you notice the result even when the redirect never reaches your app. A provider_pending profile with providerResult: KYC_PROVIDER_IMPORT_FAILED passed the verification, but Pods could not finish the onboarding yet. Keep showing “under analysis”: Pods retries transient failures and takes the rest to support. Include the kycUserId if you contact support. While created or rejected_retryable, the status carries verificationLink and verificationLinkExpiresAt. They are null otherwise. reason is present for rejected and rejected_retryable:
Program against reason.code and reason.retryable; show reason.message to the applicant. The codes are the same Pods vocabulary used by the other KYC flows: see rejection reasons.

4. Retry or reset

There are two ways to restart a rejected_retryable verification. Choose by what the applicant has to fix.
Both return the same shape as the session response, with a new verificationLink. A reset keeps the same kycUserId. Reset is allowed only while the status is rejected_retryable, and only a limited number of times per profile. After either call, keep polling the status as before.

5. Errors

Errors use { "error": { "code", "message", "details?" } }. Full list with resolutions: Error codes. A 502 or 503 means the provider could not complete the call: it is safe to call again.

Data handling

  • Documents and selfie are captured and held by the verification provider on the hosted page. They never pass through your servers, and Pods does not store them.
  • CPF: Pods keeps a salted hash and the last four digits. The full CPF is not returned by any route.
  • Link: a short-lived bearer link. Treat it as a secret.
  • Result: Pods keeps the status, the normalized rejection reason, and the identifiers needed for audit and retry.

Next steps

KYC overview

All KYC flows and the shared status model

Move money with Pods Ramp

Quote and execute Pix on-ramp and off-ramp once approved

Backend example

Runnable script: create a session, print the link, poll the status

Error codes

Every code with its resolution