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

# Collecting Travel Rule Information

> When and how to collect Travel Rule metadata from your end users.

Two integration patterns are supported. Pick based on your end users' transfer profile.

## Patterns

### Pattern A: Collect up-front

Collect Travel Rule information at the moment a new destination address is saved. The address cannot be used for above-threshold transfers until valid metadata is attached.

```mermaid theme={null}
flowchart LR
  A[End user adds address] --> B[Your UI collects TR info] --> C["PUT destination address\nwith travelrule_metadata"]
  C --> D[Address ready for any transfer size]
```

**Use this when:** most of your transfers are likely to cross the \$3,000 threshold, or you'd rather collect once and avoid interrupting users at transaction time. Recommended for most integrations.

### Pattern B: Try-catch on transaction

Save the destination address without Travel Rule metadata. Attempt the withdrawal or orchestration. If the transaction crosses the threshold, the API returns a `403` with a typed error. Collect the metadata, `PUT` it onto the destination address, and retry.

```mermaid theme={null}
flowchart TD
  A["POST /v2/transfer/fees/crypto-withdrawal\nor POST /v2/transfer/crypto-withdrawals"] --> B{"Amount?"}
  B -- "< $3,000" --> C[Succeeds]
  B -- "≥ $3,000, no TR metadata" --> D["403 Travel Rule\nInformation Required"]
  D --> E[Your UI prompts for TR info]
  E --> F[PUT destination address with metadata]
  F --> G[Retry the transaction]
```

**Use this when:** most of your transfers are under \$3,000 and you want to avoid front-loading data collection. Common for retail/consumer flows.

### Mixing patterns

You can use both. A common approach: Pattern A for addresses tagged as "business" (likely high-value), Pattern B for addresses tagged as "personal" (likely small transfers).

## Examples

### Crypto Withdrawal

Pattern A — \$5,000 USDG withdrawal to a Coinbase account.

<Steps>
  <Step title="Resolve the receiving VASP">
    See [`GET /v2/travelrule/vasps`](/api-reference/endpoints/vasps/list-vasps) API reference.

    ```bash theme={null}
    GET /v2/travelrule/vasps?search=coinb&limit=10
    ```

    **Response:**

    ```json theme={null}
    {
      "items": [
        {
          "id": "0b3d9f1e-7c2a-4e8b-9f1a-2c3d4e5f6a7b",
          "name": "Coinbase, Inc."
        },
        {
          "id": "1c4e0a2f-8d3b-4f9c-8a2b-3d4e5f6a7b8c",
          "name": "Coinbase Custody Trust"
        }
      ]
    }
    ```

    The user picks *Coinbase, Inc.* from your type-ahead. You capture `vasp.id = "0b3d9f1e-7c2a-4e8b-9f1a-2c3d4e5f6a7b"`.
  </Step>

  <Step title="Save the destination address with Travel Rule metadata">
    See [`PUT /v2/transfer/crypto-destination-address`](/api-reference/endpoints/crypto-destination-addresses/put-crypto-destination-address) API reference.

    ```bash theme={null}
    PUT /v2/transfer/crypto-destination-address
    ```

    **Request:**

    ```json theme={null}
    {
      "crypto_network": "ETHEREUM",
      "address": "0xe4B0aCA9FB669817775274775b20e52118595515",
      "nickname": "alice_coinbase",
      "identity_id": "b8d9f2a1-3c4e-4f5a-9b6d-7e8f0a1b2c3d",
      "travelrule_metadata": {
        "custodian_type": "VASP",
        "beneficiary": {
          "person_details": {
            "first_name": "Alice",
            "last_name": "Smith",
            "physical_address": {
              "country": "USA"
            }
          }
        },
        "vasp": {
          "id": "0b3d9f1e-7c2a-4e8b-9f1a-2c3d4e5f6a7b"
        },
        "transfer_purpose": "Investment"
      }
    }
    ```
  </Step>

  <Step title="Create the withdrawal">
    Travel Rule metadata is resolved from the saved address. See [`POST /v2/transfer/crypto-withdrawals`](/api-reference/endpoints/crypto-withdrawals/create-crypto-withdrawal) API reference.

    ```bash theme={null}
    POST /v2/transfer/crypto-withdrawals
    ```

    **Request:**

    ```json theme={null}
    {
      "ref_id": "unique_withdrawal_ref_001",
      "profile_id": "b7b77d82-e6a7-4ae9-9904-36231aedf985",
      "identity_id": "b8d9f2a1-3c4e-4f5a-9b6d-7e8f0a1b2c3d",
      "asset": "USDG",
      "crypto_network": "ETHEREUM",
      "amount": "5000",
      "destination_address": "0xe4B0aCA9FB669817775274775b20e52118595515"
    }
    ```

    The withdrawal is created. Paxos transmits the Travel Rule message to the receiving institution before broadcasting on-chain.
  </Step>
</Steps>

### Orchestration

<Steps>
  <Step title="Resolve the receiving VASP">
    Same as the [crypto withdrawal example](#crypto-withdrawal) above.
  </Step>

  <Step title="Save the destination address with Travel Rule metadata">
    Same as the [crypto withdrawal example](#crypto-withdrawal) above.
  </Step>

  <Step title="Create the orchestration">
    The orchestration references the saved address by `(network, address)`. See [`POST /v2/orchestration/orchestrations`](/api-reference/endpoints/orchestration/create-orchestration) API reference.

    **Request:**

    ```json theme={null}
    {
      "ref_id": "orch-usdg-eth-001",
      "identity_id": "b8d9f2a1-3c4e-4f5a-9b6d-7e8f0a1b2c3d",
      "source_asset": "USDC",
      "destination_asset": "USDG",
      "source_amount": "5000",
      "source": {
        "profile": {
          "profile_id": "7c4e8f2a-1d3b-4a5e-9f6c-8b2d7e0a4f1c"
        }
      },
      "destination": {
        "crypto": {
          "network": "ETHEREUM",
          "address": "0xe4B0aCA9FB669817775274775b20e52118595515"
        }
      }
    }
    ```

    Travel Rule metadata is resolved from the saved destination address at execution time.
  </Step>
</Steps>

**Orchestration Rules** require Travel Rule metadata on the referenced destination address **regardless of expected transaction size**, because incoming deposits that trigger a rule are unpredictable in amount.

## Testing the rejection flow

Before enforcement begins, above-threshold transfers don't yet return the `403`, so there's no natural way to exercise your [Pattern B](#pattern-b-try-catch-on-transaction) retry path. To trigger the error on demand, send the `X-Paxos-Test-Travel-Rule-Reject` header (any non-empty value) on a transaction request:

```bash highlight={3} theme={null}
curl -X POST 'https://api.sandbox.paxos.com/v2/transfer/crypto-withdrawals' \
  -H 'Authorization: Bearer <token>' \
  -H 'X-Paxos-Test-Travel-Rule-Reject: true' \
  -H 'Content-Type: application/json' \
  -d '{ ...withdrawal body... }'
```

Any request carrying the header returns [`403 Travel Rule Information Required`](/api-reference/problems/travel-rule-information-required) — regardless of amount or whether the destination already has Travel Rule metadata — so you can verify your catch → collect → `PUT` → retry handling end to end. It works on all four transaction endpoints:

* [Create Crypto Withdrawal](/api-reference/endpoints/crypto-withdrawals/create-crypto-withdrawal)
* [Create Crypto Withdrawal Fee](/api-reference/endpoints/fees/create-crypto-withdrawal-fee)
* [Create Orchestration](/api-reference/endpoints/orchestration/create-orchestration)
* [Create Orchestration Rule](/api-reference/endpoints/orchestration-rules/create-orchestration-rule)

> Use this header only while testing in sandbox, and remove it for real transfers — it forces the rejection on the request that carries it.

## Additional scenarios

### Self-transfers (me-to-me)

Set `beneficiary.self = true` and omit `person_details` and `institution_details`; the server resolves the end user's details from their identity. For a self-transfer to an unhosted wallet, set `custodian_type = PRIVATE` and omit `vasp`. For a self-transfer to your own account at another VASP, set `custodian_type = VASP` and still provide `vasp` so Paxos can identify the receiving institution.

### Unhosted/self-hosted wallets

Set `custodian_type` to `PRIVATE` and omit `vasp`. No Travel Rule message is transmitted, but the metadata is still required to record the determination.

### VASP not in the Paxos directory

Provide `vasp.custom_vasp_name` and `vasp.custom_vasp_website` of the provider hosting the wallet. Paxos Compliance handles the off-directory Travel Rule obligation. Paxos continuously expands directory coverage based on customer transaction patterns.

### Updating Travel Rule metadata on an existing address

Call [`PUT /v2/transfer/crypto-destination-address`](/api-reference/endpoints/crypto-destination-addresses/put-crypto-destination-address) with either the `id` of the address or the `crypto_network` and `address` to update the `travelrule_metadata` object. Subsequent transactions to that address will use the updated metadata.
