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
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.
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.
2. Open the link and return to the app
OpenverificationLink for the applicant. It works until verificationLinkExpiresAt. After a successful verification the applicant is redirected to your redirectUrl.
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:
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 arejected_retryable verification. Choose by what the applicant has to fix.
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