Transfers
A transfer moves crypto or stablecoins from an originator to a beneficiary, each of them a customer of an institution. Before the funds move, the two institutions exchange the Travel Rule data about the transfer.
Three separate things
| What | What it is | In the API |
|---|---|---|
| The transfer | The record of the movement, with its parties and its statuses. Both institutions keep their own copy. | A transfer, with its id. |
| The Travel Rule data | The originator’s and the beneficiary’s details, sent from one institution to the other. | The parties’ ivms, read with include_ivms=true. |
| The settlement | The movement of the funds on the blockchain. | The settlement_id you record on the transfer. |
| What | What it is | In the API |
|---|---|---|
| The transfer | The record of the movement, with its parties and its statuses. Both institutions keep their own copy. | A transfer, with its id. |
| The Travel Rule data | The originator’s and the beneficiary’s details, sent from one institution to the other. | The parties’ ivms, read with include_ivms=true. |
| The settlement | The movement of the funds on the blockchain. | The settlement_id you record on the transfer. |
Authorization comes first and does not depend on the settlement, so a transfer can be authorized and not yet settled, or settled before every institution has authorized it.
What each institution sees
Each institution keeps its own record of the transfer and they share only what they send each other, so two institutions can show different statuses for the same transfer.
| On the transfer | What it says | Who sees it |
|---|---|---|
| Your verdict | What your policies decided: approve, flag or reject. Policies explains it. | Only you |
| Your status | Where your institution stands: Pending, Authorized, Rejected or Canceled. | Every institution on the transfer |
| Requirements | What must happen before an institution can be authorized, such as receiving the Travel Rule data. | Every institution on the transfer |
| Transaction status | Where the transfer stands across every institution and the settlement, such as Active or ReadyToSettle. | Every institution on the transfer |
| On the transfer | What it says | Who sees it |
|---|---|---|
| Your verdict | What your policies decided: approve, flag or reject. Policies explains it. | Only you |
| Your status | Where your institution stands: Pending, Authorized, Rejected or Canceled. | Every institution on the transfer |
| Requirements | What must happen before an institution can be authorized, such as receiving the Travel Rule data. | Every institution on the transfer |
| Transaction status | Where the transfer stands across every institution and the settlement, such as Active or ReadyToSettle. | Every institution on the transfer |
A requirement is set by one institution and usually met by the other. On a deposit, for example, the receiving institution sets the requirement to receive the Travel Rule data, and the sending institution meets it by sending that data. The name check is one the receiving institution sets and meets itself. Every value of every status is listed in Statuses.
How a transfer moves
- The originator’s institution creates the transfer. Notabene finds the beneficiary’s institution from the address, or the transfer names it.
- Each institution’s policies evaluate it, and the requirements on each side open.
- Each institution is authorized once its verdict is to approve and its requirements are met. A flagged transfer waits for a person on that institution’s team.
- When every institution is authorized, the status is
ReadyToSettle. The originator’s institution sends the funds and records the transaction hash.
Withdrawals walks through these steps as the sender and Deposits as the receiver, including a deposit that arrives before its data. Every step is recorded in your audit trail, which Security and status explains.
Reading it in the API
| On the transfer | In the API |
|---|---|
| Your verdict | Your audit trail, as transaction.compliance.evaluated with its decision. |
| Your status | The status of your entry in agents, the one with your DID and the role VASP. |
| Requirements | Under policies, in the entry of the institution that set them: type, status, and from_did, the institution that must meet it. |
| Transaction status | The transfer’s status. |
| Something waits on you | requires_action is true. |
| On the transfer | In the API |
|---|---|
| Your verdict | Your audit trail, as transaction.compliance.evaluated with its decision. |
| Your status | The status of your entry in agents, the one with your DID and the role VASP. |
| Requirements | Under policies, in the entry of the institution that set them: type, status, and from_did, the institution that must meet it. |
| Transaction status | The transfer’s status. |
| Something waits on you | requires_action is true. |
The same requirement names its two institutions differently in a transfer and in an event:
| Where | The institution that set it | The institution that must meet it |
|---|---|---|
| A transfer you read | The entry in agents the requirement sits under | from_did |
The requirements.pending.v3 event | from | agentId |
| Where | The institution that set it | The institution that must meet it |
|---|---|---|
| A transfer you read | The entry in agents the requirement sits under | from_did |
The requirements.pending.v3 event | from | agentId |
curl https://sandbox.notabene.id/api/v1/transfers/8f3c2a1e-5b7d-4c90-a1f2-3e4d5c6b7a80 \ --header 'Authorization: Bearer YOUR_ACCESS_TOKEN'const response = await fetch('https://sandbox.notabene.id/api/v1/transfers/8f3c2a1e-5b7d-4c90-a1f2-3e4d5c6b7a80', { method: 'GET', headers: { Authorization: 'Bearer YOUR_ACCESS_TOKEN', }, }); const answer = response.status === 204 ? null : await response.json();import requests response = requests.get( 'https://sandbox.notabene.id/api/v1/transfers/8f3c2a1e-5b7d-4c90-a1f2-3e4d5c6b7a80', headers={'Authorization': 'Bearer YOUR_ACCESS_TOKEN'}, ) answer = None if response.status_code == 204 else response.json()
What to replace
8f3c2a1e-5b7d-4c90-a1f2-3e4d5c6b7a80: The transfer’s id
{
"id": "8f3c2a1e-5b7d-4c90-a1f2-3e4d5c6b7a80",
"type": "Transfer",
"status": "Active",
"direction": "Incoming",
"counterparty": "did:web:originator.example:pt",
"asset": "eip155:1/slip44:60",
"amount": "0.5",
"requires_action": true,
"agents": [
{
"agent_did": "did:web:originator.example:pt",
"role": "VASP",
"status": "Authorized",
"policies": [
{
"type": "WalletAddressConfirmation",
"status": "Satisfied",
"from_did": "did:web:beneficiary.example:pt"
}
]
},
{
"agent_did": "did:web:beneficiary.example:pt",
"role": "VASP",
"status": "Pending",
"policies": [
{
"type": "ReceiveTRInfo",
"status": "Pending",
"from_did": "did:web:originator.example:pt"
},
{
"type": "Authorization",
"status": "Satisfied",
"from_did": "did:web:originator.example:pt"
},
{
"type": "BeneficiaryNameMatch",
"status": "Pending",
"from_did": "did:web:beneficiary.example:pt"
}
]
}
]
}curl https://sandbox.notabene.id/api/v1/transfers/8f3c2a1e-5b7d-4c90-a1f2-3e4d5c6b7a80 \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN'const response = await fetch('https://sandbox.notabene.id/api/v1/transfers/8f3c2a1e-5b7d-4c90-a1f2-3e4d5c6b7a80', {
method: 'GET',
headers: {
Authorization: 'Bearer YOUR_ACCESS_TOKEN',
},
});
const answer = response.status === 204 ? null : await response.json();import requests
response = requests.get(
'https://sandbox.notabene.id/api/v1/transfers/8f3c2a1e-5b7d-4c90-a1f2-3e4d5c6b7a80',
headers={'Authorization': 'Bearer YOUR_ACCESS_TOKEN'},
)
answer = None if response.status_code == 204 else response.json(){
"id": "8f3c2a1e-5b7d-4c90-a1f2-3e4d5c6b7a80",
"type": "Transfer",
"status": "Active",
"direction": "Incoming",
"counterparty": "did:web:originator.example:pt",
"asset": "eip155:1/slip44:60",
"amount": "0.5",
"requires_action": true,
"agents": [
{
"agent_did": "did:web:originator.example:pt",
"role": "VASP",
"status": "Authorized",
"policies": [
{
"type": "WalletAddressConfirmation",
"status": "Satisfied",
"from_did": "did:web:beneficiary.example:pt"
}
]
},
{
"agent_did": "did:web:beneficiary.example:pt",
"role": "VASP",
"status": "Pending",
"policies": [
{
"type": "ReceiveTRInfo",
"status": "Pending",
"from_did": "did:web:originator.example:pt"
},
{
"type": "Authorization",
"status": "Satisfied",
"from_did": "did:web:originator.example:pt"
},
{
"type": "BeneficiaryNameMatch",
"status": "Pending",
"from_did": "did:web:beneficiary.example:pt"
}
]
}
]
}Here the beneficiary’s institution reads a deposit that the originator’s institution has already authorized. Its own side is still Pending, because the Travel Rule data has not arrived and the name check is open.
Updated about 6 hours ago
