> ## Documentation Index
> Fetch the complete documentation index at: https://partner-docs.contro.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Restricted countries and regions

> Countries and regions where cardholders cannot be onboarded

Cardholders who reside in, or hold identity documents issued by, a restricted country or region cannot be onboarded. The restriction is applied during provider verification and is not configurable per partner.

## Restricted list

| Country or region | ISO 3166-1 alpha-2 |
| - | - |
| Belarus | `BY` |
| Burundi | `BI` |
| Central African Republic | `CF` |
| Cuba | `CU` |
| Iran | `IR` |
| Libya | `LY` |
| Myanmar (Burma) | `MM` |
| North Korea | `KP` |
| Russia | `RU` |
| Somalia | `SO` |
| South Sudan | `SS` |
| Sudan | `SD` |
| Syrian Arab Republic | `SY` |
| Ukraine | `UA` |
| Venezuela | `VE` |
| Zimbabwe | `ZW` |

<Note>
  This list changes as sanctions programs are updated. Treat it as indicative rather than authoritative in your own code — always handle a `rejected` outcome at runtime instead of pre-filtering against a hardcoded copy.
</Note>

## What gets checked

Screening is evaluated against the cardholder's identity data, not their IP address or the country your platform operates from:

* **Residence country** — `residenceCountryCode` on the cardholder, or the address extracted from their KYC session
* **Nationality and document issuing country** — taken from the verified identity document

A cardholder is rejected if either matches the restricted list.

## How rejection surfaces

When the cardholder is rejected, [`cardholder.rejected`](/partner/webhooks/cardholder-approved) fires:

```json theme={null}
{
  "cardholderId": "ch_abc123",
  "externalUserId": "user_42",
  "reason": "..."
}
```

`kycStatus` moves to `"rejected"` and no [`cardholder.approved`](/partner/webhooks/cardholder-approved) event follows. Cards cannot be issued to a rejected cardholder. The `reason` field is present only when the provider supplies one, and is redacted to a safe summary.

Rejection is terminal for that cardholder. Resubmitting the same identity produces the same outcome — do not retry.

## Handling it in your integration

<CodeGroup>
  ```javascript Node theme={null}
  app.post("/webhooks/contro", async (req, res) => {
    if (req.headers["x-contro-event"] === "cardholder.rejected") {
      // Terminal — mark the user ineligible, do not retry issuance
      await markIneligible(req.body.cardholderId);
    }

    res.status(200).send("OK");
  });
  ```

  ```python Python theme={null}
  @app.post("/webhooks/contro")
  async def contro_webhook(request: Request):
      if request.headers.get("x-contro-event") == "cardholder.rejected":
          body = await request.json()
          # Terminal — mark the user ineligible, do not retry issuance
          await mark_ineligible(body["cardholderId"])

      return Response("OK", status_code=200)
  ```
</CodeGroup>

To avoid onboarding users you already know are ineligible, screen for residence country in your own signup flow before calling `POST /partner/cardholders`.

## Related

* [Card holders](/partner/cardholders) — creating and updating cardholders
* [`cardholder.rejected`](/partner/webhooks/cardholder-approved) — cardholder verification outcome
* [Errors](/partner/errors) — error format and status codes
