SEP: 0003
Title: Compliance protocol
Author: stellar.org
Status: Deprecated
Created: 2017-10-30
Updated: 2019-10-04
Version 1.0.1
For most use cases, we actually recommend the workflow specified in SEP-0024 instead of SEP-0003
Complying with Anti-Money Laundering (AML) laws requires financial institutions (FIs) to know not only who their customers are sending money to but who their customers are receiving money from. In some jurisdictions banks are able to trust the AML procedures of other licensed banks. In other jurisdictions each bank must do its own sanction checking of both the sender and the receiver. The Compliance Protocol handles all these scenarios.
The Compliance Protocol is an additional step after federation. In this step the sending FI contacts the receiving FI to get permission to send the transaction. To do this the receiving FI creates an AUTH_SERVER
and adds an AUTH_SERVER
entry to its stellar.toml
.
SEP-9 specifies standard customer information fields that are exchanged between FIs via the Compliance Protocol. The most common fields are:
- First name
- Last name
- Date of birth
- Physical address
To send transaction data to the receiving organization, send HTTP POST to AUTH_SERVER
with Content-Type
equal application/x-www-form-urlencoded
and the following body:
data=<data value>&sig=<sig value>
data
is a block of JSON that contains the following fields:
Name | Data Type | Description |
---|---|---|
sender |
string | The payment address of the customer that is initiating the send. Ex. bob*bank.com |
need_info |
boolean | If the caller needs the recipient's AML info in order to send the payment. |
tx |
string: base64 encoded xdr.Transaction | The transaction that the sender would like to send in XDR format. This transaction is unsigned and it's sequence number should be equal 0 . |
attachment |
string | The full text of the attachment. The hash of this attachment is included as a memo in the transaction. The attachment field follows the Stellar Attachment Convention and should contain at least enough information of the sender to allow the receiving FI to do their sanction check. |
sig is the signature of the data block made by the sending FI. The receiving institution should check that this signature is valid against the public signature key that is posted in the sending FI's stellar.toml (SIGNING_KEY
field).
Example request body (please note it contains both parameters data
and sig
):
data=%7B%22sender%22%3A%22aldi%2AbankA.com%22%2C%22need_info%22%3Atrue%2C%22tx%22%3A%22AAAAAEhAArfpmUJYq%2FQ9SFAH3YDzNLJEBI9i9TXmJ7s608xbAAAAZAAMon0AAAAJAAAAAAAAAAPUg1%2FwDrMDozn8yfiCA8LLC0wF10q5n5lo0GiFQXpPsAAAAAEAAAAAAAAAAQAAAADdvkoXq6TXDV9IpguvNHyAXaUH4AcCLqhToJpaG6cCyQAAAAAAAAAAAJiWgAAAAAA%3D%22%2C%22attachment%22%3A%22%7B%5C%22nonce%5C%22%3A%5C%221488805458327055805%5C%22%2C%5C%22transaction%5C%22%3A%7B%5C%22sender_info%5C%22%3A%7B%5C%22address%5C%22%3A%5C%22678+Mission+St%5C%22%2C%5C%22city%5C%22%3A%5C%22San+Francisco%5C%22%2C%5C%22country%5C%22%3A%5C%22US%5C%22%2C%5C%22first_name%5C%22%3A%5C%22Aldi%5C%22%2C%5C%22last_name%5C%22%3A%5C%22Dobbs%5C%22%7D%2C%5C%22route%5C%22%3A%5C%221%5C%22%2C%5C%22note%5C%22%3A%5C%22%5C%22%2C%5C%22extra%5C%22%3A%5C%22%5C%22%7D%2C%5C%22operations%5C%22%3Anull%7D%22%7D&sig=KgvyQTZsZQoaMy8jdwCUfLayfgfFMUdZJ%2B0BIvEwiH5aJhBXvhV%2BipRok1asjSCUS%2FUaGeGKDoizS1%2BtFiiyAA%3D%3D
After decoding the data
parameter it has a following form:
{
"sender": "aldi*bankA.com",
"need_info": true,
"tx": "AAAAAEhAArfpmUJYq/Q9SFAH3YDzNLJEBI9i9TXmJ7s608xbAAAAZAAMon0AAAAJAAAAAAAAAAPUg1/wDrMDozn8yfiCA8LLC0wF10q5n5lo0GiFQXpPsAAAAAEAAAAAAAAAAQAAAADdvkoXq6TXDV9IpguvNHyAXaUH4AcCLqhToJpaG6cCyQAAAAAAAAAAAJiWgAAAAAA=",
"attachment": "{\"nonce\":\"1488805458327055805\",\"transaction\":{\"sender_info\":{\"address\":\"678 Mission St\",\"city\":\"San Francisco\",\"country\":\"US\",\"first_name\":\"Aldi\",\"last_name\":\"Dobbs\"},\"route\":\"1\",\"note\":\"\",\"extra\":\"\"},\"operations\":null}"
}
A few things to note:
- memo value of
tx
is a sha256 hash of the attachment - nonce is unique to each individual transaction. When a transaction on the receiving end is
pending
, the samenonce
should be sent to fetch updates about thepending
transaction
AUTH_SERVER
will return a JSON object with the following fields:
Name | Data Type | Description |
---|---|---|
info_status |
ok , denied , pending |
If this FI is willing to share AML information or not. |
tx_status |
ok , denied , pending |
If this FI is willing to accept this transaction. |
dest_info |
string | (only present if info_status is ok ) Marshalled JSON of the recipient's AML information. |
error |
string | (only present if info_status or tx_status is error or for internal server errors) Error message |
pending |
integer | (only present if info_status or tx_status is pending ) Estimated number of seconds till the sender can check back for a change in status. The sender should just resubmit this request after the given number of seconds. |
HTTP status code must be equal:
200 OK
if bothinfo_status
andtx_status
areok
.202 Accepted
if both statuses arepending
or one ispending
and secondok
.400 Bad Request
if data sent by the sender is invalid.403 Forbidden
if any ofinfo_status
andtx_status
aredenied
.500 Internal Server Error
for server side errors.
Examples:
200 OK
{
"info_status": "ok",
"tx_status": "ok",
"dest_info": "{\"name\": \"John Doe\"}"
}
202 Accepted
{
"info_status": "ok",
"tx_status": "pending",
"dest_info": "{\"name\": \"John Doe\"}",
"pending": 3600
}
400 Bad Request
{
"info_status": "ok",
"tx_status": "error",
"error": "Invalid country code."
}
403 Forbidden
{
"info_status": "deny",
"tx_status": "ok"
}
500 Internal Server Error
{
"error": "Internal server error"
}
Use GoStellar application to check if Compliance protocol was implemented correctly.
- Reference Compliance server developed by Stellar Development Foundation.
- Compliance structures.