Transfer payload structure
Learn about Notabene's flexible agent-based model for cryptocurrency transfers, including roles, chains, and multi-party scenarios.
Overview
Notabene's transfer structure uses a flexible agent-based model to represent all parties involved in a cryptocurrency transfer, from simple peer-to-peer transactions to complex multi-party flows.
Basic Structure
{
"originator": {
"@id": "alice.example.com"
},
"beneficiary": {
"@id": "bob.example.com"
},
"asset": "BTC" // or CAIP19 standard: bip122:000000000019d6689c085ae165831e93/slip44:0",
"amount": "0.003",
"agents": [
// Agent details here
],
"ref": "unique-transfer-id"
}Understanding Agents
Agents represent the entities and wallets involved in executing the transfer. Each agent has:
@id: Unique identifier (DID - Decentralized Identifier, or Wallet address)for: Who this agent representsrole: (Optional) The agent's function in the transfer
The for field is key to understanding transfer flows, creating chains of relationships that determine transfer direction, compliance requirements, and message routing.
Common Agent Roles
While the role field is optional and primarily descriptive, these common values help document the transfer structure:
VASP: Virtual Asset Service Provider (exchange, wallet service, etc.)Custodian: Entity holding assets on behalf of a VASPSourceAddress: The blockchain address sending the assetsSettlementAddress: The blockchain address receiving the assets
Agent Chains
Agents form chains through their for field.
Typical chain structure:
SourceAddress → originatorVASP → originator
SettlementAddress → beneficiaryVASP → beneficiary
Or with custodians:
SettlementAddress → custodian → beneficiaryVASP → beneficiary
Complete Example
{
"originator": {
"@id": "alice.example.com"
},
"beneficiary": {
"@id": "bob.example.com"
},
"asset": "bip122:000000000019d6689c085ae165831e93/slip44:0",
"amount": "0.003",
"agents": [
{
"@id": "did:pkh:bip122:000000000019d6689c085ae165831e93:bc1qn9y...rld0f",
"for": "did:web:vasps.id:exchange-a:us",
"role": "SourceAddress"
},
{
"@id": "did:web:vasps.id:exchange-a:us",
"for": "alice.example.com",
"role": "VASP"
},
{
"@id": "did:web:vasps.id:custodian-x:jp",
"for": "did:web:vasps.id:exchange-b:uk",
"role": "Custodian"
},
{
"@id": "did:web:vasps.id:exchange-b:uk",
"for": "bob.example.com",
"role": "VASP"
},
{
"@id": "did:pkh:bip122:000000000019d6689c085ae165831e93:bc1q7av...ucrg",
"for": "did:web:vasps.id:exchange-b:uk",
"role": "SettlementAddress"
}
],
"ref": "550e8400-e29b-41d4-a716-446655440000"
}This example shows:
- Alice's funds originate from address
bc1qn9y...rld0fcontrolled by Exchange A - Exchange A is Alice's VASP
- Custodian X holds assets for Exchange B
- Exchange B is Bob's VASP
- Bob receives funds at address
bc1q7av...ucrg
| Name | Explanation |
|---|---|
| originator.@id | The DID/IRI of your customer |
| beneficiary.@id | The DID/IRI of the person your customer is sending to |
| asset | The CAIP19 ID or Notabene asset abbreviation of the asset/token being sent |
| amount | The number of that asset being sent, use decimals where needed |
| agents.@id | The DID of the wallet or VASP |
| agents.for | acting on behalf of |
| agents.role | What role the @id has to the "for" |
| ref | The idempotency key |
The different roles available:
| Role | Explanation |
|---|---|
| SourceAddress | The wallet where the funds are going from |
| VASP | Virtual Asset Service Provider |
| Custodian | Providing custody services to VASPs |
| SettlementAddress | The wallet where the funds are going to |
Multi-Party Scenarios
Custodial Arrangements
Many VASPs use third-party custodians to hold assets. The agent structure represents these relationships:
{
"agents": [
{
"@id": "did:web:vasps.id:prime-custody:us",
"for": "did:web:vasps.id:retail-exchange:de",
"role": "Custodian"
},
{
"@id": "did:web:vasps.id:retail-exchange:de",
"for": "bob.example.com",
"role": "VASP"
},
{
"@id": "did:pkh:bip122:000000000019d6689c085ae165831e93:bc1q7av...ucrg",
"for": "did:web:vasps.id:retail-exchange:de",
"role": "SettlementAddress"
}
]
}The settlement address is controlled by the retail exchange, but custody is with Prime Custody. The for chain makes this relationship explicit: SettlementAddress → VASP → beneficiary and Custodian → VASP.
Partial Information Scenarios
The agent structure is flexible, handling cases where not all information is known at transfer creation time.
Missing Source Address
When the originating VASP creates a transfer but hasn't determined the sending address:
{
"agents": [
{
"@id": "did:web:vasps.id:my-exchange:de",
"for": "alice.example.com"
},
{
"@id": "did:web:vasps.id:their-exchange:jp",
"for": "bob.example.com"
},
{
"@id": "did:pkh:bip122:000000000019d6689c085ae165831e93:bc1q7av...ucrg",
"for": "did:web:vasps.id:their-exchange:jp",
"role": "SettlementAddress"
}
]
}Missing Settlement Address
When the beneficiary VASP hasn't assigned a receiving address:
{
"agents": [
{
"@id": "did:pkh:bip122:000000000019d6689c085ae165831e93:bc1qn9y...rld0f",
"for": "did:web:vasps.id:my-exchange:us",
"role": "SourceAddress"
},
{
"@id": "did:web:vasps.id:my-exchange:us",
"for": "alice.example.com"
},
{
"@id": "did:web:vasps.id:their-exchange:ca",
"for": "bob.example.com"
}
]
}First-Party Transfers
When the same person is both originator and beneficiary (e.g., moving funds between their own accounts at different VASPs):
{
"originator": {
"@id": "alice.example.com"
},
"beneficiary": {
"@id": "alice.example.com"
},
"agents": [
{
"@id": "did:web:vasps.id:exchange-a:us",
"for": "alice.example.com"
},
{
"@id": "did:web:vasps.id:exchange-b:uk",
"for": "alice.example.com"
}
]
}Updated about 3 hours ago
