> For the complete documentation index, see [llms.txt](https://docs.ospree.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.ospree.io/developers/api-integration-flows/routing-guide.md).

# Routing Guide

These routing flows serve as reference models and should be adapted to the applicable jurisdiction and your organization’s internal compliance policies.

### Outgoing Flow

Use the outgoing flow to determine the appropriate Travel Rule handling path for a withdrawal.

The flow evaluates the applicable threshold, destination-wallet type, self-hosted wallet verification status, me-to-me transfers, beneficiary VASP discoverability, and available communication method. The outcome identifies whether to create a Travel Rule record, use a supported interoperable protocol or TRP, request wallet verification, invite the beneficiary VASP, or proceed without additional Travel Rule requirements.

<details open>

<summary>Expand Diagram </summary>

{% code expandable="true" %}

```mermaid
graph TD
    R1["R1: Outgoing transfer"] --> D1{"D1: Is the withdrawal amount<br/>above the applicable<br/>Travel Rule threshold?"}

    D1 -- "Yes" --> D2{"D2: Is the destination wallet<br/>self-hosted?"}
    D1 -- "No" --> L6["L6: Travel Rule not required;<br/>proceed with the withdrawal"]

    D2 -- "Yes" --> D3{"D3: Was the self-hosted wallet<br/>previously verified?"}
    D2 -- "No" --> D5{"D5: Is the transfer<br/>a me-to-me transaction?"}

    D3 -- "Yes" --> L1["L1: Create a Travel Rule<br/>record transfer"]
    D3 -- "No" --> D4{"D4: Has the self-hosted wallet<br/>verification now been completed?"}

    D4 -- "Yes" --> L1
    D4 -- "No" --> L5["L5: Send or resend the verification<br/>link and wait for completion"]

    D5 -- "Yes" --> L1
    D5 -- "No" --> D6{"D6: Is the beneficiary VASP discoverable<br/>through the Ospree database<br/>or a wallet check?"}

    D6 -- "Yes" --> L2["L2: Send via a supported<br/>interoperable protocol"]
    D6 -- "No" --> D7{"D7: Has the beneficiary VASP<br/>provided a Travel Address?"}

    D7 -- "Yes" --> L3["L3: Send the transfer via TRP"]
    D7 -- "No" --> L4["L4: Send a VASP invitation"]
```

{% endcode %}

</details>

<table data-header-hidden="false" data-header-sticky data-search="false"><thead><tr><th width="86.6414794921875">Node</th><th width="145.51736450195312">Type</th><th width="365.35235595703125">Node label</th><th width="89.015625">Yes →</th><th width="89.935791015625">No →</th></tr></thead><tbody><tr><td>R1</td><td>Start</td><td>Outgoing transfer</td><td>D1</td><td>—</td></tr><tr><td>D1</td><td>Routing check</td><td><p>Is the withdrawal amount above the applicable Travel Rule threshold? </p><ul><li><a href="https://docs.ospree.io/developers/rule-engine">Rule Engine</a></li></ul></td><td>D2</td><td>L6</td></tr><tr><td>D2</td><td>Routing check</td><td>Is the destination wallet self-hosted? </td><td>D3</td><td>D5</td></tr><tr><td>D3</td><td>Routing check</td><td><p>Was the self-hosted wallet previously verified? </p><ul><li><a href="/developers/blockchain-analytics/verify-address-details.md">Verify Address Details</a></li></ul></td><td>L1</td><td>D4</td></tr><tr><td>D4</td><td>Routing check</td><td><p>Has the self-hosted wallet verification now been completed? </p><ul><li><a href="/developers/blockchain-analytics/verify-address-details.md">Verify Address Details</a></li></ul></td><td>L1</td><td>L5</td></tr><tr><td>D5</td><td>Routing check</td><td>Is the transfer a me-to-me transaction?</td><td>L1</td><td>D6</td></tr><tr><td>D6</td><td>Routing check</td><td>Is the beneficiary VASP discoverable through the Ospree database or a wallet check?</td><td>L2</td><td>D7</td></tr><tr><td>D7</td><td>Routing check</td><td>Has the beneficiary VASP provided a Travel Address? </td><td>L3</td><td>L4</td></tr><tr><td>L1</td><td>Outcome</td><td><p>Create a Travel Rule record transfer</p><ul><li><a href="https://docs.ospree.io/developers/travel-rule/api-endpoints/create-transfer#vasp-to-vasp-deposit-query-record">VASP-to-VASP Deposit Query (Record)</a> </li></ul></td><td>—</td><td>—</td></tr><tr><td>L2</td><td>Outcome</td><td><p>Send via a supported interoperable protocol </p><ul><li><a href="/developers/travel-rule/api-endpoints/create-transfer.md">Create Transfer</a></li></ul></td><td>—</td><td>—</td></tr><tr><td>L3</td><td>Outcome</td><td>Send the transfer via TRP</td><td>—</td><td>—</td></tr><tr><td>L4</td><td>Outcome</td><td><p>Send a VASP invitation </p><ul><li><a href="https://docs.ospree.io/dashboard/accounts-directory/vasps/request-a-vasp">Invite VASP</a></li></ul></td><td>—</td><td>—</td></tr><tr><td>L5</td><td>Outcome</td><td><p>Send or resend the verification link and wait for completion </p><ul><li><a href="https://docs.ospree.io/developers/blockchain-analytics/verify-address-control">Verify Address Control</a></li><li><a href="https://docs.ospree.io/learn/self-hosted-wallet">Self-Hosted Wallet Guide</a></li></ul></td><td>—</td><td>—</td></tr><tr><td>L6</td><td>Outcome</td><td>Travel Rule not required; proceed with the withdrawal</td><td>—</td><td>—</td></tr></tbody></table>

### Incoming Flow

Use the incoming flow to determine the appropriate Travel Rule handling path for a deposit.

The flow evaluates the applicable threshold, whether the source is a whitelisted self-hosted wallet, whether Travel Rule data was received through a supported protocol or platform, and whether missing information may be collected directly from the customer. The outcome identifies whether to create a Travel Rule record, review the transfer, request additional information, use an approved alternative retrieval process, stop the transfer, or proceed without additional Travel Rule requirements.<br>

<details open>

<summary>Expand Diagram</summary>

{% code expandable="true" %}

```mermaid
graph TD
    R1["R1: Incoming<br/>transfer"] --> D1{"D1: Is the incoming<br/>transfer amount above<br/>the applicable Travel Rule<br/>threshold?"}

    D1 -- "Yes" --> D2{"D2: Is the source wallet<br/>a whitelisted<br/>self-hosted wallet?"}
    D1 -- "No" --> L5["L5: Travel Rule not required;<br/>proceed with the<br/>incoming transfer"]

    D2 -- "Yes" --> L1["L1: Create a<br/>Travel Rule record<br/>transfer"]
    D2 -- "No" --> D3{"D3: Was the Travel Rule data<br/>received through a supported<br/>protocol or platform?"}

    D3 -- "Yes" --> L2["L2: Review the transfer<br/>and approve or reject it"]
    D3 -- "No" --> D4{"D4: Does the applicable policy<br/>permit obtaining the required<br/>information directly<br/>from the customer?"}

    D4 -- "Yes" --> L3["L3: Request the required<br/>information directly<br/>from the customer"]
    D4 -- "No" --> L4["L4: Use an approved alternative<br/>retrieval process or stop<br/>the incoming transfer"]
```

{% endcode %}

</details>

<table data-header-hidden="false" data-header-sticky data-search="false"><thead><tr><th width="84.14144897460938">Node</th><th width="118.87237548828125">Type</th><th width="367.50537109375">Node label</th><th width="95.83013916015625">Yes →</th><th width="88.79498291015625">No →</th></tr></thead><tbody><tr><td>R1</td><td>Start</td><td>Incoming transfer</td><td>D1</td><td>—</td></tr><tr><td>D1</td><td>Routing check</td><td><p>Is the incoming transfer amount above the applicable Travel Rule threshold?<br>Rule Engine</p><ul><li><a href="https://docs.ospree.io/developers/rule-engine">Rule Engine</a></li></ul></td><td>D2</td><td>L5</td></tr><tr><td>D2</td><td>Routing check</td><td><p>Is the source wallet a whitelisted self-hosted wallet?</p><ul><li><a href="/developers/blockchain-analytics/verify-address-details.md">Verify Address Details</a></li></ul></td><td>L1</td><td>D3</td></tr><tr><td>D3</td><td>Routing check</td><td><p>Was the Travel Rule data received through a supported protocol or platform?</p><ul><li><a href="https://docs.ospree.io/developers/webhooks/webhook-events">Receive the incoming webhook</a></li><li><a href="https://docs.ospree.io/developers/travel-rule/api-endpoints/retrieve-transfer">Retrieve the transfer details </a></li></ul></td><td>L2</td><td>D4</td></tr><tr><td>D4</td><td>Routing check</td><td>Does the applicable policy permit obtaining the required information directly from the customer?</td><td>L3</td><td>L4</td></tr><tr><td>L1</td><td>Outcome</td><td><p>Create a Travel Rule record transfer</p><ul><li><a href="https://docs.ospree.io/developers/travel-rule/api-endpoints/create-transfer#vasp-to-vasp-deposit-query-record">VASP-to-VASP Deposit Query (Record)</a></li></ul></td><td>—</td><td>—</td></tr><tr><td>L2</td><td>Outcome</td><td><p>Review the transfer and approve or reject it</p><ul><li><a href="https://docs.ospree.io/developers/travel-rule/api-endpoints/action-transfer">Approve or reject the transfer </a></li></ul></td><td>—</td><td>—</td></tr><tr><td>L3</td><td>Outcome</td><td>Request the required information directly from the customer</td><td>—</td><td>—</td></tr><tr><td>L4</td><td>Outcome</td><td>Use an approved alternative retrieval process or stop the incoming transfer</td><td>—</td><td>—</td></tr><tr><td>L5</td><td>Outcome</td><td>Travel Rule not required; proceed with the incoming transfer</td><td>—</td><td>—</td></tr></tbody></table>
