Skip to content
Branch: master
Find file Copy path
Find file Copy path
5 contributors

Users who have contributed to this file

@tomquisel @ramontayag @theaeolianmachine @jedmccaleb @overcat
148 lines (120 sloc) 6.62 KB


SEP: 0003
Title: Compliance protocol
Status: Active
Created: 2017-10-30
Updated: 2018-07-15
Version 1.0.1

Simple Summary

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*
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):

After decoding the data parameter it has a following form:

  "sender": "aldi*",
  "need_info": true,
  "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 same nonce should be sent to fetch updates about the pending 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 both info_status and tx_status are ok.
  • 202 Accepted if both statuses are pending or one is pending and second ok.
  • 400 Bad Request if data sent by the sender is invalid.
  • 403 Forbidden if any of info_status and tx_status are denied.
  • 500 Internal Server Error for server side errors.


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"

Test Cases

Use GoStellar application to check if Compliance protocol was implemented correctly.

Reference implementations

You can’t perform that action at this time.