This workflow covers outgoing transfers where PII (Personally Identifiable Information) is required. You collect PII from your end user and submit it via the API before creating the transfer intent.
- Travel Rule setup complete.
- Wallet addresses registered with Notabene.
Create a Travel Rule message with counterparty information:
POST /v1/domains/{domainId}/compliance/travel-rule/providers/{provider}/messagesRequest body:
| Field | Type | Description |
|---|---|---|
originator | object | Originator identifier (contains @id - DID or identifier for the party) |
beneficiary | object | Beneficiary identifier (contains @id - DID or identifier for the party) |
asset | string | Asset identifier (e.g., bip122:000000000019d6689c085ae165831e93/slip44:0). See Notabene asset registry for supported formats. |
amount | string | Transfer amount |
ref | string | Reference identifier for the transfer |
agents | array | Agents involved in the transfer. Each agent has @id, for, and role (values: VASP, Custodian, SettlementAddress, SourceAddress, Gateway, Unknown) |
Response:
| Field | Type | Description |
|---|---|---|
createTransfer201Response.transfer | object | Transfer details from Notabene |
suggestedIntentId | string (uuid) | The intent ID to use when creating the transfer intent |
Get the transfer status to check what PII is required:
GET /v1/domains/{domainId}/compliance/travel-rule/providers/{provider}/messages/{travelRuleId}The response includes a presentation-definition that specifies the required PII fields. It also contains a policyId that you can use when submitting encrypted PII (see Step 4, Option C).
Collect required PII from your end user according to the IVMS-101 standard and the requirements in the presentation-definition.
Submit the collected PII using one of three API endpoints. All PII is encrypted with the receiver's public key.
Use this option when both sender and receiver need access to the PII.
POST /v1/domains/{domainId}/compliance/travel-rule/providers/{provider}/messages/{travelRuleId}/piiRequest body:
| Field | Type | Required | Description |
|---|---|---|---|
ivms101 | object | Yes | IVMS-101 formatted PII data |
originator | object | No | Originator details |
beneficiary | object | No | Beneficiary details |
Response: 200 OK
Use this option for end-to-end encrypted PII that only the receiver can decrypt.
POST /v1/domains/{domainId}/compliance/travel-rule/providers/{provider}/messages/{travelRuleId}/encrypted-piiRequest body:
| Field | Type | Required | Description |
|---|---|---|---|
ivms101 | object | Yes | End-to-end encrypted IVMS-101 data |
Response: 202 Accepted (asynchronous processing)
Use this option when sender and receiver have different jurisdictional requirements. The policyId from Step 2 specifies the applicable compliance policy.
POST /v1/domains/{domainId}/compliance/travel-rule/providers/{provider}/messages/{travelRuleId}/policies/{travelRulePolicyId}/encrypted-piiRequest body: Same as Option B.
Response: 202 Accepted (asynchronous processing)
Options B and C use end-to-end encryption with the receiver's public key. The sender cannot decrypt this data after submission.
Create the Transfer Order intent using the suggestedIntentId returned in Step 1.
Transfer Order intent payload:
| Field | Type | Required | Description |
|---|---|---|---|
payload.accountId | string (uuid) | Yes | Source account ID |
payload.ledgerId | string | No | Ledger identifier |
payload.parameters.operation | object | Yes | Transfer operation details including destination, amount, and type |
payload.type | string | Yes | Must be v0_CreateTransferOrder |
Use the suggestedIntentId from Step 1 when creating the intent. This links the compliance check to your transaction.
If transaction screening is configured (Chainalysis or Elliptic), Ripple Custody screens the transaction first.
- If screening fails (high risk score): The transaction is immediately rejected. No Travel Rule check occurs.
- If screening passes: The workflow proceeds to the Travel Rule check.
Notabene verifies counterparty information and PII.
Ripple Custody evaluates the results:
| Screening Result | Travel Rule Result | Decision |
|---|---|---|
| Approved | Approved | AUTO_APPROVED |
| Rejected | — | AUTO_REJECTED (Travel Rule skipped) |
| Approved | Rejected | AUTO_REJECTED |
| Inconclusive | Inconclusive | NEED_EXPLICIT_DECISION |
If the decision is NEED_EXPLICIT_DECISION, manual review is required in Ripple Custody.
If only one check is configured (screening only or Travel Rule only), the decision is based on that single check.
- If
AUTO_APPROVED: Transaction executes on blockchain, then Notabene is notified of settlement. - If
AUTO_REJECTED: Intent closes, then Notabene is notified of rejection.
Poll the Travel Rule transfer status to confirm successful execution:
GET /v1/domains/{domainId}/compliance/travel-rule/providers/{provider}/messages/{travelRuleId}Key response fields:
| Field | Type | Description |
|---|---|---|
transfer.status | string | Notabene transfer status (e.g., SETTLED, REJECTED) |
transfer.direction | string | OUTGOING for this workflow |
- Send without PII — When PII is not required
- Receive assets — Handle incoming Travel Rule transfers