Skip to main content

Re-verification and remediation

Verification is not permanent. This is what happens when it lapses, needs more evidence, or has to be withdrawn.

Before you begin​

  • A cardholder with a current attestation — see KYC lifecycle and statuses.
  • A view on your own re-verification policy. We record what you assert; the cadence is yours.

How it works​

Three situations bring a verified cardholder back into scope, and they differ in urgency:

SituationTriggerUrgency
Periodic re-verificationexpires_at approachingPlanned
Review requiredSomething needs more evidencePrompt
RevocationVerification must be withdrawnImmediate

All three are handled the same way — by reporting a new attestation, which supersedes the previous one. Nothing is deleted; the chain is what an audit reads.

The chain​

Only the newest has is_current: true. The earlier ones stay readable.

Steps​

1. Track expiry yourself​

Set expires_at when you report an outcome:

{
"status": "approved",
"verified_at": "2026-07-29T11:04:00Z",
"provider": "Acme Identity",
"expires_at": "2028-07-29T00:00:00Z"
}

Then find what is falling due:

curl "$ALETA_BASE_URL/v1/cardholders/chd_01HX8ZQ2K4M7P9RSTVWXYZAB/kyc" \
-H "Authorization: Bearer $ALETA_ACCESS_TOKEN"
We do not currently notify you before expiry

There is no cardholder.kyc_expiring_soon event. Drive re-verification from your own scheduler against the expires_at values you set, the same way you would any other renewal.

Omitting expires_at means no expiry is tracked at all — which is a valid choice if your policy has no fixed cadence, but make it deliberately rather than by forgetting the field.

2. Re-verify and report again​

curl -X POST "$ALETA_BASE_URL/v1/cardholders/chd_01HX8ZQ2K4M7P9RSTVWXYZAB/kyc" \
-H "Authorization: Bearer $ALETA_ACCESS_TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"status": "approved",
"verified_at": "2028-06-14T09:22:00Z",
"provider": "Acme Identity",
"provider_reference": "chk_c81f04",
"method": "document_and_selfie",
"expires_at": "2030-06-14T00:00:00Z",
"notes": "Scheduled biennial re-verification"
}'

A new provider_reference — this is a new check, not a re-statement of the old one. Reusing the previous reference makes the chain unauditable.

3. Handle review_required​

Report it when your process needs more from the cardholder but has not concluded:

-d '{
"status": "review_required",
"verified_at": "2028-06-01T10:00:00Z",
"provider": "Acme Identity",
"notes": "Address proof older than 3 months, awaiting replacement"
}'

This blocks card activation immediately, and fires cardholder.kyc_review_required.

Use notes for operational context. Do not put the evidence itself there — see identity documents.

4. Understand what happens to live cards​

This is the part worth getting right before you need it.

ReportedEffect on existing active cards
review_requiredNo automatic change. Cards keep working
rejectedNo automatic change. Cards keep working
Expiry passingNo automatic change. Cards keep working

Changing kyc_status does not freeze anything. A cardholder whose verification you have just revoked still holds a spendable card until you act on it.

That is deliberate — an automatic freeze on every review_required would cut cardholders off mid-transaction for what is often a paperwork issue. But it means remediation is a two-step process, and skipping the second step is the failure mode:

# 1. Record the outcome
POST /v1/cardholders/{id}/kyc { "status": "rejected", ... }

# 2. Act on the cards — this does not happen for you
GET /v1/cardholders/{id}/cards
POST /v1/cards/{card_id}/freeze # reversible, for review
POST /v1/cards/{card_id}/close # terminal, for revocation

Freeze for review_required; it is reversible and the usual outcome is that the cardholder supplies what was missing. Close for a genuine rejected — see freeze, replace, close.

5. Restoring after remediation​

Report approved again and unfreeze:

POST /v1/cardholders/{id}/kyc { "status": "approved", ... }
POST /v1/cards/{card_id}/unfreeze

A closed card cannot come back. If you closed rather than froze, issue a replacement.

Verifying​

  • A new attestation appears with is_current: true, and the previous one is still readable with is_current: false
  • kyc_status reflects the newest outcome
  • The matching webhook fired
  • Cards were not touched automatically — confirm this in sandbox, because assuming otherwise is the mistake this page exists to prevent
  • After freezing, a simulated authorization declines with card_not_active

Common errors​

StatuscodeFix
422kyc_attestation_expiredThe attestation in force is past expires_at. Re-verify and report
422kyc_provider_requiredEvery attestation names who verified, including re-verifications
422kyc_attestation_incompleteverified_at missing or in the future
422card_closedClosure is terminal. Issue a replacement instead of unfreezing