Regulatory compliance
This page describes the regulatory compliance integration details when processing eligible deposits or withdrawals.
Transaction Eligibility
Eligible Deposits
Eligible deposits are defined as transactions that arrive in your wallets that originated from a wallet outside of your Balance Custody instance over $1,000 CAD or part of a sum of deposits within 24hrs totalling over $10,000 CAD as required by FINTRAC. Balance Custody will determine whether deposits require submission of additional information.
Eligible Withdrawals
Eligible withdrawals are defined as transactions originating from wallets in your Balance Custody instance that are destined for a wallet outside of your Balance Custody account (e.g. to an External Account) in the amount of more than $1,000 CAD.
Canada-Eligible Travel Rule
Transactions with an originator in Canada where the transaction amount exceeds $1,000 CAD require details of the beneficiary's VASP unless the destination is self-custodied.
USA-Eligible Travel Rule
Transactions with an originator in the USA where the transaction amount exceeds $3,000 USD require details of the beneficiary's VASP unless the destination is self-custodied.
Processing Deposits
When receiving eligible deposits, your organization information is automatically set as the Beneficiary Entity, and you may be required to provide information about an Originator Entity and/or a Third Party Entity if applicable.
Via the UI
You will see Eligible Deposits reflected in the "Alerts" page, where you will be able to submit this information.
Via the API
You can query for all eligible deposits that require additional information using the following API call: GET /api/v1/transactions
.
For example:
Look for the regulatory_status
field in the transaction records returned from the above call. If this field is set to missing_travel_rule_info
, then you can only submit Originator Entity information. If this field is set to missing_lvctr_info
, then you will optionally be able to submit Third Party Entity information. Please refer to the entity struct definitions below to see which fields are required for missing_travel_rule_info
vs missing_lvctr_info
status.
Please note that the determination of regulatory_status
is made by Balance, and it is possible for a transaction record to transition from missing_travel_rule_info
to missing_lvctr_info
, in which case you will be able to submit additional information.
You can then submit Originator Entity and Third Party Entity information using the following API call: PUT /api/v1/transactions/:id
.
For example:
Originator Entity Struct
Common Fields:
kind
- string; required; one of:individual
,corporate
address1
- string; required for bothmissing_travel_rule_info
andmissing_lvctr_info
address2
- string; optional; accepted for bothmissing_travel_rule_info
andmissing_lvctr_info
city
- string; required for bothmissing_travel_rule_info
andmissing_lvctr_info
state
- string; required for bothmissing_travel_rule_info
andmissing_lvctr_info
; must be one of the values in List of states/provinces accepted by the APIpostcode
- string; required for bothmissing_travel_rule_info
andmissing_lvctr_info
country
- string; required for bothmissing_travel_rule_info
andmissing_lvctr_info
; must be one of the values in List of states/provinces accepted by the APIclient_number
- string; optional; accepted for bothmissing_travel_rule_info
andmissing_lvctr_info
id_doc_type_code
- integer; required formissing_lvctr_info
; signifies an "Identification Document Type Code"; please seeList of Identification Type Codes accepted by the API
id_doc_type_code_other
- string; optional; accepted formissing_lvctr_info
; signifies another "Identification Document Type" only ifid_doc_type_code
is selected as3
for individual or7
for corporate entity typeid_doc_number
- string; required formissing_lvctr_info
; signifies an Identification Document Numberid_doc_jurisdiction_country
- string; required formissing_lvctr_info
; signifies an Identification Document Jurisdiction Country; must be one of the values in List of countries accepted by the APIid_doc_jurisdiction_state
- string; required formissing_lvctr_info
; signifies an Identification Document Jurisdiction State/Province; must be one of the values in List of states/provinces accepted by the APIdevice_type_code
- integer; optional; signifies a "Device Type Code"; please seeList of Device Type Codes accepted by the API
device_type_code_other
- string; optional; signifies another "Device Type Code"; required only ifdevice_type_code
is selected as4
device_identification_number
- string; optional; signifies Device Identification Numberdevice_ip_address
- string; optional; signifies an IPv4 or IPv6 stringrequested_at
- string; date in ISO8601 format; optional; signifies date/time of the online session when the transfer occurred
Fields for kind=individual
:
firstname
- string; required for bothmissing_travel_rule_info
andmissing_lvctr_info
lastname
- string; required for bothmissing_travel_rule_info
andmissing_lvctr_info
occupation
- string; required formissing_lvctr_info
dob
- string; required formissing_lvctr_info
; must be specified inYYYY-MM-DD
formatemail
- string; optional; accepted formissing_lvctr_info
Fields for kind=corporate
:
corporate_name
- string; required for bothmissing_travel_rule_info
andmissing_lvctr_info
authorized_person_first_name
- string; required formissing_lvctr_info
; signifies first name of the person authorized to bind the entity or act with respect to the accountauthorized_person_last_name
- string; required formissing_lvctr_info
authorized_person_other
- string; optional; accepted formissing_lvctr_info
; e.g., Sr., Jr., Esq.incorporation_number
- string; optional only if entity is not registered/incorporated; accepted formissing_lvctr_info
; registration number or similar, if the entity is incorporated/registeredregistration_country
- string; optional only if entity is not registered/incorporated; accepted formissing_lvctr_info
; signifies this entity's Registration Country if the entity is incorporated/registered; must be one of the values in List of countries accepted by the APIregistration_state
- string; optional only if entity is not registered/incorporated; accepted formissing_lvctr_info
; signifies this entity's Registration State/Province if the entity is incorporated/registered; must be one of the values in List of states/provinces accepted by the APInature_of_business
- string; required formissing_lvctr_info
Third Party Entity Struct
Common Fields:
kind
- one of:individual
,corporate
address1
- stringaddress2
- stringcity
- stringstate
- string; must be one of the values in List of states/provinces accepted by the APIpostcode
- stringcountry
- string; must be one of the values in List of states/provinces accepted by the APInature_of_relationship_code
- integer; signifies an "Nature of Relationship Type Code"; please see List of Nature of Relationship Type Codes accepted by the APInature_of_relationship_code_other
- string; signifies another "Nature of Relationship Code" ifnature_of_relationship_code
is selected as9
Fields for kind=individual
:
firstname
- stringlastname
- stringoccupation
- stringdob
- must be specified inYYYY-MM-DD
format
Fields for kind=corporate
:
corporate_name
- stringnature_of_business
- string
Default Originator Entity
You are able to use the API to specify a Default Originator Entity for your wallets. Doing so will associate a specified originator with deposits to a given wallet, however you will still be required to confirm this via the API or the UI. Documentation on how to submit a Default Originator Entity can be found here: PUT /api/v1/wallets/:wallet_id
In the UI, if a Default Originator Entity is set for a receiving wallet, you will see all the Originator Entity fields pre-filled with this information when reviewing a transaction via the Alerts page.
In the API, if a default originator entity is set for a receiving wallet, you will see an originator_entity
field when querying for deposits using the GET /api/v1/transactions/:id
and the GET /api/v1/wallets/:wallet_id/transactions/:transaction_id
calls. The entity will have an is_confirmed: false
field set. This is done purely for convenience, as you will then still be required to submit an originator_entity
for that deposit.
Processing Withdrawals
When sending Eligible Withdrawals, your organization information is automatically set as the Originator Entity, and you are required to provide information about the Beneficiary Entity.
Via the UI
A Beneficiary Information form will be presented to you to fill in the required fields in the Transaction Builder after the "Build" step if the transaction is eligible.
Via the API
When submitting a withdrawal request, you will get a 400 error, with the following body: {"error":"param is missing or the value is empty: beneficiary_entity"}
if the transaction requires a Beneficiary Entity, but does not include it in the request payload. You should handle that error by providing the beneficiary_entity
field.
For example:
It is possible to add multiple beneficiaries to the API call by adding a beneficiary_entities
field to the request body. the beneficiary_entities contains an array of the beneficiary_entity structs.
For example:
Note that a request will result in a 400 error if the request body contains both beneficiary_entity and beneficiary_entities fields simultaniously.
As of the 27th of July 2023 the beneficiary entity would require the email field to be present.
Beneficiary Entity Struct
Common Fields:
kind
- required; can be one of:individual
,corporate
email
- required; string; must be of a valid email formataddress1
- required; stringaddress2
- optional; stringcity
- required; stringstate
- required; string; can be state, province, etc; must be one of the values in List of states/provinces accepted by the APIpostcode
- required; string; can be postal code, zip code, etc.country
- required; string; must be one of the values in List of countries accepted by the APIclient_number
- optional; string; account number or other reference number (if any)
Fields for USA/Canada-eligible travel rule where the destination wallet is hosted by a service provider such as Kraken, Coinbase, Wealthsimple.
service_provider_name
- name of the service provider; stringservice_provider_email
- email address for compliance or legal inquiries used by the service provider; string
Fields for kind=individual
:
firstname
- required forindividual
kind; stringlastname
- required forindividual
kind; string
Fields for kind=corporate
:
corporate_name
- required forcorporate
kind; string
Examples
Individual
Corporate
List of countries accepted by the API
List of states/provinces accepted by the API
Accepts any non-empty string, except when the country is set to Canada, United States, or Mexico. In those cases, the values below are accepted:
List of Identification Type Codes accepted by the API
This is an integer type.
For kind=individual
entities the accepted values are:
1
- Birth certificate2
- Passport3
- Other4
- Driver's licence5
- Provincial health card14
- Citizenship card15
- Certificate of Indian Status32
- Permanent resident card33
- Record of landing34
- Credit file35
- Government issued identification36
- Insurance documents37
- Provincial or territorial identity card38
- Record of employment39
- Travel visa40
- Utility statement
For kind=corporate
entities the accepted values are:
1
- Articles of association2
- Certificate of corporate status3
- Certificate of incorporation4
- Letter/Notice of assessment5
- Partnership agreement6
- Annual report7
- Other
List of Nature of Relationship Type Codes accepted by the API
This is an integer type.
1
- Accountant2
- Agent3
- Borrower4
- Broker5
- Customer6
- Employee7
- Friend8
- Relative9
- Other10
- Legal counsel11
- Employer12
- Joint/Secondary owner13
- Power of attorney
List of Device Type Codes accepted by the API
This is an integer type.
1
- Computer/Laptop2
- Mobile phone3
- Tablet4
- Other
Sample API Requests / Responses
Keep in mind that headers (including authentication headers) are not included in these examples to keep them brief.
Create Wallet with Default Originator Entity
(Full API Call Documentation: POST /api/v1/wallets
)
Request:
Response:
Set Default Originator Entity for Wallet
(Full API Call Documentation: PUT /api/v1/wallets/:id
)
Note that if you attempt to set a default originator entity for a wallet that already has one set - the API will return a 400 error with the following body: {"error": "Default originator already set for this wallet."}
.
Request:
Response:
Same as Create Wallet with Default Originator Entity
Read Default Originator Entity for a Wallet
(Full API Call Documentation: GET /api/v1/wallets/:id
)
Note that default_originator_entity
field is only returned for the GET /api/v1/wallets/:id
API call, and is NOT returned for the GET /api/v1/wallets
API call.
Request:
Response:
Same as Create Wallet with Default Originator Entity
Get a List of Eligible Deposits Pending Regulatory Info
(Full API Call Documentation: GET /api/v1/transactions
)
Request:
Response:
Same as GET /api/v1/transactions
.
Set an Originator Entity for an Eligible Deposit
(Full API Call Documentation: PUT /api/v1/transactions/:id
)
Request:
Response:
Same as GET /api/v1/transactions/:id
Create an Eligible Withdrawal with Beneficiary Entity
(Full API Call Documentation: POST /api/v1/wallets/:wallet_id/transactions
)
Request:
Response:
Last updated