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

# Registered Addresses

> Pre-registered crypto destination addresses for intercompany payouts and a reusable address book

## Overview

A Registered Address is a crypto destination address that your organization whitelists against a customer. Registering screens the address once and records it; a crypto payout with `purpose: intercompany` then requires its `destination.recipient.address` to match a `registered` **`self_custody`** entry for that customer — otherwise the payout returns `422 RECIPIENT_NOT_WHITELISTED`. A `third_party` registration does **not** satisfy the intercompany gate: intercompany moves funds between accounts the customer owns, so the destination must be a wallet the customer controls. For the same reason, the payout request's own `destination.recipient.attestation.custody` must be `self` — a `third_party` attestation declares a change of beneficial owner and returns `422 RECIPIENT_NOT_WHITELISTED` even when the address is registered as `self_custody`. The registered address is a **whitelist match by chain + address that gates the payout**, not a recipient you reference by id: every `POST /v2/payouts` still carries the full `destination.recipient`, and there is no `registeredAddressId` field. For any other purpose, registering is not required — the inline recipient is accepted without a prior whitelist entry.

Registering an address always creates it synchronously and then screens it. Most registrations clear immediately: the `POST` returns **`201`** with status `registered`. When screening needs more time, the `POST` returns **`202`** with status `pending_screening`, and the address is resolved shortly after to either `registered` (usable) or `suspended` (blocked). A registration that screening rejects returns **`409`**. An address in `pending_screening` is **not yet usable** — it gates an intercompany payout only once it is `registered`, so poll the address until it leaves `pending_screening` before relying on it.

## Custody types

A registered address declares who controls the destination wallet, set by the `type` discriminator:

* **`self_custody`** — the customer owns and controls the wallet. Requires `selfCustodyAttestation: true`. Only a `self_custody` address unlocks `purpose: intercompany` payouts.
* **`third_party`** — the wallet belongs to someone else (for example, a counterparty's wallet). Requires `originatorDetails` describing the beneficial owner, used for Travel Rule disclosure. A `third_party` address is screened and recorded, but because it names a different beneficial owner it does **not** satisfy the `intercompany` payout gate:
  * `entityType: "individual"` → `firstName`, `lastName`, `dateOfBirth`, `countryOfCitizenship`
  * `entityType: "business"` → `legalName`, `country`

## Lifecycle

| Status              | Meaning                                                                                                                                                                                                                                                                    |
| ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `registered`        | Screened and ready to receive payouts. A registration that clears immediately returns this with `201`; one that returned `202 pending_screening` reaches it once screening clears.                                                                                         |
| `pending_screening` | Screening has not finished yet. The `POST` returned `202`; the address resolves to `registered` or `suspended` shortly after and is **not usable** for payouts until it becomes `registered`.                                                                              |
| `suspended`         | Blocked for payouts. Returned as a `409` when re-registering an already-suspended address or when a registration is screened and rejected; an address can also become `suspended` when a `pending_screening` screen resolves to a rejection. Don't retry; contact Conduit. |
| `revoked`           | The registration was cancelled via `DELETE`. Terminal.                                                                                                                                                                                                                     |

Re-registering an address that is already `registered` or `pending_screening` for the customer is idempotent — it returns the existing record rather than creating a duplicate.

## Key fields

| Field                    | Type                            | Description                                                                    |
| ------------------------ | ------------------------------- | ------------------------------------------------------------------------------ |
| `id`                     | `wra_*`                         | Unique identifier for the registered address.                                  |
| `chain`                  | string                          | Chain the address is on (e.g. `ethereum`).                                     |
| `address`                | string                          | The destination address. Returned normalized (e.g. lowercased for EVM chains). |
| `type`                   | `self_custody` \| `third_party` | Custody model declared at registration.                                        |
| `selfCustodyAttestation` | boolean                         | Present for `self_custody`; the customer attests they own the wallet.          |
| `originatorDetails`      | object \| null                  | Beneficial-owner disclosure for `third_party`.                                 |
| `status`                 | see above                       | Current status.                                                                |
| `label`                  | string \| null                  | Optional human-readable label.                                                 |

## API surface

* `POST /v2/customers/:customerId/wallets/registered-addresses` — register an address (requires `Idempotency-Key`); returns `201 registered` when screening clears immediately, `202 pending_screening` when it resolves asynchronously, or `409` if screening rejects
* `GET /v2/customers/:customerId/wallets/registered-addresses` — list registered addresses for the customer
* `GET /v2/wallets/registered-addresses/:id` — get a single registered address
* `DELETE /v2/wallets/registered-addresses/:id` — revoke a registered address (terminal)

```bash theme={null}
curl -X POST {{api-host}}/v2/customers/$CUSTOMER_ID/wallets/registered-addresses \
  -H "x-api-key: $API_KEY" \
  -H "idempotency-key: $(uuidgen)" \
  -H "content-type: application/json" \
  -d '{
    "type": "self_custody",
    "chain": "ethereum",
    "address": "0xRecipientAddress",
    "selfCustodyAttestation": true,
    "label": "Treasury cold wallet"
  }'
```

## Testing in sandbox

In the sandbox environment, the screening verdict is deterministic — it is driven by the address you register:

| Address                                                                                                                                                                                                                | Registration outcome                                                                                                                                                             |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Exactly `0xdead000000000000000000000000000000000001` (EVM) or `TMockSanctioned9xZqWvTronAddrABCDe` (Tron), or a `third_party` registration whose originator legal name is `Acme Sanctioned LTD` or `Blocked Entity SA` | `409` — the address is persisted as `suspended` and stays barred                                                                                                                 |
| Starting with `0x999` (EVM), or exactly `TMockReviewPend9xZqWvTronAddrABCDe` (Tron)                                                                                                                                    | `202` `pending_screening` — resolve it with the simulate endpoint below                                                                                                          |
| Starting with `0x000`                                                                                                                                                                                                  | `202` `pending_screening` that never resolves (the automatic re-screen fails it again every time); the simulate endpoint returns `409` for it — revoke it via `DELETE` when done |
| Anything else                                                                                                                                                                                                          | `201` `registered`                                                                                                                                                               |

An address parked `pending_screening` by the `0x999` review value is resolved self-service:

* `POST /v2/sandbox/wallets/registered-addresses/:id/simulate/compliance-decision` with body `{ "outcome": "approve" | "reject" }` — returns `200` with the address at its final status. `approve` moves it to `registered` and releases any deposits from that address that were waiting on its registration; `reject` moves it to `suspended` (not reversible, and re-registering the same address returns `409`).

A resolved verdict never flip-flops: repeating the **same** decision returns `200` with the address's current state (safe for client retries), while a **conflicting** decision returns `409`. The magic values are checked top to bottom — a sanctioned match (address or originator name) wins over the `0x999` review prefix. The fixed Tron review value parks at most once per customer (a resolved registration replays idempotently instead of re-parking); for repeated runs use fresh `0x999` EVM addresses.

```bash theme={null}
curl -X POST {{api-host}}/v2/sandbox/wallets/registered-addresses/$ADDRESS_ID/simulate/compliance-decision \
  -H "x-api-key: $API_KEY" \
  -H "content-type: application/json" \
  -d '{ "outcome": "approve" }'
```
