Regulatory Compliance
This document details the Balance Custody Regulatory Compliance API, offering endpoints for transaction monitoring, reporting, and compliance verification to meet regulatory requirements.
Last updated
This document details the Balance Custody Regulatory Compliance API, offering endpoints for transaction monitoring, reporting, and compliance verification to meet regulatory requirements.
Last updated
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 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.
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.
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.
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.
You will see Eligible Deposits reflected in the "Alerts" page, where you will be able to submit this information.
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:
Common Fields:
kind
- string; required; one of: individual
, corporate
address1
- string; required for both missing_travel_rule_info
and missing_lvctr_info
address2
- string; optional; accepted for both missing_travel_rule_info
and missing_lvctr_info
city
- string; required for both missing_travel_rule_info
and missing_lvctr_info
state
- string; required for both missing_travel_rule_info
and missing_lvctr_info
; must be one of the values in List of states/provinces accepted by the API
postcode
- string; required for both missing_travel_rule_info
and missing_lvctr_info
client_number
- string; optional; accepted for both missing_travel_rule_info
and missing_lvctr_info
id_doc_type_code
- integer; required for missing_lvctr_info
; signifies an "Identification Document Type Code"; please see List of Identification Type Codes accepted by the API
id_doc_type_code_other
- string; optional; accepted for missing_lvctr_info
; signifies another "Identification Document Type" only if id_doc_type_code
is selected as 3
for individual or 7
for corporate entity type
id_doc_number
- string; required for missing_lvctr_info
; signifies an Identification Document Number
id_doc_jurisdiction_country
- string; required for missing_lvctr_info
; signifies an Identification Document Jurisdiction Country; must be one of the values in List of countries accepted by the API
id_doc_jurisdiction_state
- string; required for missing_lvctr_info
; signifies an Identification Document Jurisdiction State/Province; must be one of the values in List of states/provinces accepted by the API
device_type_code
- integer; optional; signifies a "Device Type Code"; please see List of Device Type Codes accepted by the API
device_type_code_other
- string; optional; signifies another "Device Type Code"; required only if device_type_code
is selected as 4
device_identification_number
- string; optional; signifies Device Identification Number
device_ip_address
- string; optional; signifies an IPv4 or IPv6 string
requested_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 both missing_travel_rule_info
and missing_lvctr_info
lastname
- string; required for both missing_travel_rule_info
and missing_lvctr_info
occupation
- string; required for missing_lvctr_info
dob
- string; required for missing_lvctr_info
; must be specified in YYYY-MM-DD
format
email
- string; optional; accepted for missing_lvctr_info
Fields for kind=corporate
:
corporate_name
- string; required for both missing_travel_rule_info
and missing_lvctr_info
authorized_person_first_name
- string; required for missing_lvctr_info
; signifies first name of the person authorized to bind the entity or act with respect to the account
authorized_person_last_name
- string; required for missing_lvctr_info
authorized_person_other
- string; optional; accepted for missing_lvctr_info
; e.g., Sr., Jr., Esq.
incorporation_number
- string; optional only if entity is not registered/incorporated; accepted for missing_lvctr_info
; registration number or similar, if the entity is incorporated/registered
registration_country
- string; optional only if entity is not registered/incorporated; accepted for missing_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 API
registration_state
- string; optional only if entity is not registered/incorporated; accepted for missing_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 API
nature_of_business
- string; required for missing_lvctr_info
Common Fields:
kind
- one of: individual
, corporate
address1
- string
address2
- string
city
- string
state
- string; must be one of the values in List of states/provinces accepted by the API
postcode
- string
country
- string; must be one of the values in List of states/provinces accepted by the API
nature_of_relationship_code
- integer; signifies an "Nature of Relationship Type Code"; please see List of Nature of Relationship Type Codes accepted by the API
nature_of_relationship_code_other
- string; signifies another "Nature of Relationship Code" if nature_of_relationship_code
is selected as 9
Fields for kind=individual
:
firstname
- string
lastname
- string
occupation
- string
dob
- must be specified in YYYY-MM-DD
format
Fields for kind=corporate
:
corporate_name
- string
nature_of_business
- string
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.
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.
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.
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 simultaneously.
As of the 27th of July 2023 the beneficiary entity would require the email field to be present.
Common Fields:
kind
- required; can be one of: individual
, corporate
email
- required; string; must be of a valid email format
address1
- required; string
address2
- optional; string
city
- required; string
state
- required; string; can be state, province, etc; must be one of the values in List of states/provinces accepted by the API
postcode
- 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 API
client_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, or Wealthsimple.
service_provider_name
- name of the service provider; string
service_provider_email
- email address for compliance or legal inquiries used by the service provider; string
Fields for kind=individual
:
firstname
- required for individual
kind; string
lastname
- required for individual
kind; string
Fields for kind=corporate
:
corporate_name
- required for corporate
kind; string
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:
This is an integer type.
For kind=individual
entities the accepted values are:
1
- Birth certificate
2
- Passport
3
- Other
4
- Driver's licence
5
- Provincial health card
14
- Citizenship card
15
- Certificate of Indian Status
32
- Permanent resident card
33
- Record of landing
34
- Credit file
35
- Government issued identification
36
- Insurance documents
37
- Provincial or territorial identity card
38
- Record of employment
39
- Travel visa
40
- Utility statement
For kind=corporate
entities the accepted values are:
1
- Articles of association
2
- Certificate of corporate status
3
- Certificate of incorporation
4
- Letter/Notice of assessment
5
- Partnership agreement
6
- Annual report
7
- Other
This is an integer type.
1
- Accountant
2
- Agent
3
- Borrower
4
- Broker
5
- Customer
6
- Employee
7
- Friend
8
- Relative
9
- Other
10
- Legal counsel
11
- Employer
12
- Joint/Secondary owner
13
- Power of attorney
This is an integer type.
1
- Computer/Laptop
2
- Mobile phone
3
- Tablet
4
- Other
Keep in mind that headers (including authentication headers) are not included in these examples to keep them brief.
(Full API Call Documentation: POST /api/v1/wallets
)
Request:
Response:
(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:
(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
(Full API Call Documentation: GET /api/v1/transactions
)
Request:
Response:
Same as GET /api/v1/transactions
.
(Full API Call Documentation: PUT /api/v1/transactions/:id
)
Request:
Response:
Same as GET /api/v1/transactions/:id
(Full API Call Documentation: POST /api/v1/wallets/:wallet_id/transactions
)
Request:
Response:
Same as POST /api/v1/wallets/:wallet_id/transactions
country
- string; required for both missing_travel_rule_info
and missing_lvctr_info
; must be one of the values in
Same as