Direct Parties

This document outlines the process for onboarding counterparties, known as "Direct Parties", as wallet owners within the Balance Custody platform.

Onboarding a Direct Party involves provisioning warm or offline wallet(s) on the Client’s instance. Full ownership of these wallets is assigned to the Direct Party, while the Client is authorized to access them through the Balance Custody platform. This API is only available for environments where Balance Settlements has been enabled.

Process Overview

The Client will facilitate the onboarding of a Direct Party by providing Balance with the required information and identity verification data via the API to meet the Reliance Method of KYC/AML requirements. Additionally, the Client must provide a Balance Custody Agreement signed by the Direct Party and an Appointment of Authorized Person Agreement, authorizing the Client to access the Direct Party’s wallet. This information and required documents are transmitted to Balance via API. The integration process follows these steps:

  1. Authentication Requirement: The user making API requests must have an Administrator role to authenticate and perform these actions.

  2. The Client makes a POST call to the /direct_parties API, providing the necessary information to create the entity record.

  3. The Client sends further POST requests to the API to submit the Balance Custody Agreement, the Appointment of Authorized Person Agreement, and, optionally, proof of identity verification (e.g., a scan of identity documents).

  4. Once Balance receives the required information, it validates the data and approves the entity, triggering a Webhook notification to the Client.

  5. The Direct Party is notified via email, welcoming them to Balance. The email includes the executed Balance Custody Agreement and a copy of the executed Appointment of Authorized Person Agreement in PDF format.

  6. The Client then creates a new wallet and associates it with the approved Direct Party ID using the wallets API and specifying the owner_entity_id with the Direct Party id value.

API Endpoints

POST /api/v1/direct_parties

Creates a new direct party.

Include the following JSON structure in the body:

For an Individual Direct Party

  • kind - string; required; specify the type of direct party; must be either individual or corporate

  • firstname - string; required only when kind = individual; individual’s first name

  • lastname - string; required only when kind = individual; individual’s last name

  • dob - string; required only when kind = individual; individual’s date of birth; must be in the YYYY-MM-DD format

  • occupation - string; required only when kind = individual; individual’s occupation

  • email - string; required; contact email of the individual or entity

  • secondary_email - string; optional; alternative contact email of the individual.

  • client_number - string; optional; can be used to identify this object using the Client’s internal ID scheme.

  • address1 - string; required; mailing address of the individual or entity

  • address2 - string; optional; for mailing address

  • city - string; required; for mailing address

  • state - string; required; can be state, province, or equivalent for mailing address; see Regulatory Compliance for accepted values

  • postcode - string; required; can be postal code, zip code, or equivalent for mailing address

  • country - string; required; for mailing address; see Regulatory Compliance for accepted values

  • id_doc_type_code - integer; required; type of identification document used

  • id_doc_type_code_other - string; required if id_type_code is 3

  • id_doc_number - string; required; reference ID or number for the given document or record (e.g. Hydro Canada account number)

  • id_doc_jurisdiction_country - string; required; the jurisdiction country for the identification document or record

  • id_doc_jurisdiction_state - string; required; the jurisdiction state or province for the identify document or record

  • id_doc_expiry_date - string; required only when kind = individual; expiration date of the identification document or record; must be in YYYY-MM-DD format

  • id_doc_verification_date - string; required; date the identification document or record was verified by the Client; must be in the YYYY-MM-DD format

  • id_doc_source - string; required; the source of the identification document or record (e.g. “Government of Canada” for a Canadian passport)

Example Request Body

{
  "direct_party": {
	"kind": "individual",
	"firstname": "Satoshi",
	"lastname": "Nakamoto",
	"dob": "2009-01-03",
	"occupation": "Software Developer",
	"email": "satoshi@example.com",
	"client_number": "1A",
	"address1": "101 Genesis Avenue",
	"city": "Vancouver",
	"state": "British Columbia",
	"postcode": "V1V 1V1",
	"country": "Canada",
	"id_doc_type_code": 34,
	"id_doc_number": "123456789BTC",
	"id_doc_jurisdiction_country": "Canada",
	"id_doc_jurisdiction_state": "Ontario",
	"id_doc_expiry_date": "2028-10-17",
	"id_doc_verification_date": "2024-10-17",
	"id_doc_source": "TransUnion"
  }
}

Example Response Body

{
  "data": {
    "id": 1,
    "status": "pending_review",
    "kind": "individual",
    "fullname": "Satoshi Nakamoto",
    "created_at": "2024-10-25T20:03:34.000Z",
    "updated_at": "2024-10-25T20:03:34.000Z",
    "address1": "101 Genesis Avenue",
    "city": "Vancouver",
    "state": "British Columbia",
    "postcode": "V1V 1V1",
    "country": "Canada",
    "email": "satoshi@example.com",
    "address": {
      "address1": "101 Genesis Avenue",
      "address2": null,
      "city": "Vancouver",
      "state": "British Columbia",
      "postcode": "V1V 1V1",
      "country": "Canada"
    },
    "client_number": "1A",
    "self_custodied": false,
    "id_doc_expiry_date": "2028-10-17",
    "id_doc_verification_date": "2024-10-17",
    "id_doc_source": "TransUnion",
    "dob": "2009-01-03",
    "firstname": "Satoshi",
    "lastname": "Nakamoto",
    "occupation": "Software Developer",
    "id_doc_type_code": 34,
    "id_doc_number": "123456789BTC",
    "id_doc_jurisdiction_country": "Canada",
    "id_doc_jurisdiction_state": "Ontario"
  }
}

For a Corporate Direct Party

  • kind - string; required; specify the type of direct party; must be either individual or corporate

  • corporate_name - string; required only when kind = corporate; the entity's legal name

  • email - string; required; contact email of the entity

  • client_number - string; optional; can be used to identify this object using the Client’s internal ID scheme.

  • address1 - string; required; registered address of the entity

  • address2 - string; optional; second line for the registered address of the entity

  • city - string; required; for registered address

  • state - string; required; can be state, province, or equivalent for registered address; see Regulatory Compliance for accepted values

  • postcode - string; required; can be postal code, zip code, or equivalent for registered address

  • country - string; required; for registered address; see Regulatory Compliance for accepted values

  • nature_of_business - string; required only when kind = corporate; the nature of the entity business in a concise sentence (e.g. Software development and consulting company)

  • incorporation_number - string; required only when kind = corporate; the registration or incorporation number of the entity

  • tax_identification_number - string; optional; the entity's primary tax identifier as issued by the country of incorporation (e.g., EIN in the U.S., BN in Canada).

  • registration_country - string; required only when kind = corporate; the country of incorporation or registration; see Regulatory Compliance for accepted values

  • registration_state - string; required only when kind = corporate; the state or province of incorporation or registration; see Regulatory Compliance for accepted values

  • id_doc_type_code - integer; required; type of document used to confirm corporate identity; see Regulatory Compliance for accepted values

  • id_doc_type_code_other - string; required if id_type_code is 7

  • id_doc_number - string; required; reference ID or number for the given corporate identity document or record (e.g. Certificate of Incorporation)

  • id_doc_jurisdiction_country - string; required; the jurisdiction country for the corporate identity document or record

  • id_doc_jurisdiction_state - string; required; the jurisdiction state or province for the corporate identity document or record

  • id_doc_verification_date - string; required; date of when the corporate identity document or records were verified by the Client; must be in the YYYY-MM-DD format

  • id_doc_source - string; required; the source of the corporate identity document or record (e.g. "Government of Canada": For federal incorporation documents in Canada)

  • authorized_persons - array of objects; required only when kind = corporate; list of persons authorized to bind the entity or act as an Administrator (as defined in the Custody Agreement), with at least one entry. Each object must include:

    • firstname - string; required; the authorized user's first name

    • lastname - string; required; the authorized user's last name

    • email - string; required; the authorized user's email address

    • secondary_email - string; optional; an alternative contact email for the authorized person

    • occupation - string; required; the authorized user's occupation

    • dob - string; required; the authorized user's date of birth; must be in the YYYY-MM-DD format

    • address1 - string; required; registered address of the authorized user

    • address2 - string; optional; second line for the registered address of the authorized user

    • city - string; required; for address of the authorized user

    • state - string; required; can be state, province, or equivalent for authorized user address; see Regulatory Compliance for accepted values

    • postcode - string; required; can be postal code, zip code, or equivalent for authorized user address

    • country - string; required; for authorized user address; see Regulatory Compliance for accepted values

  • directors - array of objects; required only when kind = corporate; list of entity directors with at least one entry. Each object must include:

    • firstname - string; required; director's first name

    • lastname - string; required; director's last name

  • beneficial_owners – array of objects; required only when kind = corporate; list of beneficial owners, which may include both individual and corporate entities. At least one entry is required. Each object must include:

    • For Individual Beneficial Owners:

      • kind – string; required; specify the type of direct party; must be individual or corporate.

      • firstname – string; required; the individual beneficial owner’s first name

      • lastname – string; required; the individual beneficial owner’s last name

      • address1 – string; required; first line of the beneficial owner’s mailing address

      • address2 – string; optional; second line of the beneficial owner’s mailing address, if applicable

      • city – string; required; city for the beneficial owner’s mailing address.

      • state – string; required; state, province, or equivalent region for the mailing address; see Regulatory Compliance for accepted values

      • postcode – string; required; postal code, zip code, or equivalent for the mailing address

      • country – string; required; country for the mailing address; see Regulatory Compliance for accepted values

      • additional_info – string; optional; any relevant information, such as percentage ownership or contextual notes

    • For Corporate Beneficial Owners:

      • kind – string; required; specify the type of direct party; must be individual or corporate.

      • corporate_name – string; required; the corporate beneficial owner’s legal name

      • address1 – string; required; first line of the corporate entity’s mailing address

      • address2 – string; optional; second line of the corporate entity’s mailing address

      • city – string; required; city for the corporate entity’s mailing address

      • state – string; required; state, province, or equivalent region for the mailing address; see Regulatory Compliance for accepted values

      • postcode – string; required; postal code, zip code, or equivalent for the mailing address.

      • country – string; required; country for the mailing address; see Regulatory Compliance for accepted values

      • beneficial_owners – array of objects; optional; nested list of individual beneficial owners within the corporate entity. Follows the same structure as For Individual Beneficial Owners

      • additional_info – string; optional; any relevant information, such as percentage ownership or contextual notes

Example Request Body

{
  "direct_party": {
    "kind": "corporate", // Specify "corporate" for corporate direct parties
    "corporate_name": "Tech Innovations Ltd.", 
    "email": "contact@techinnovations.com",
    "client_number": "TI-12345",
    "address1": "100 Innovation Drive",
    "address2": "Suite 200",
    "city": "Toronto",
    "state": "Ontario",
    "postcode": "M5J 2N8",
    "country": "Canada",
    "nature_of_business": "Software development and consulting company",
    "incorporation_number": "INC123456789",
    "tax_identification_number": "TIN123456",
    "registration_country": "Canada",
    "registration_state": "Ontario",
    "id_doc_type_code": 1, 
    "id_doc_type_code_other": null, 
    "id_doc_number": "987654321", 
    "id_doc_jurisdiction_country": "Canada", 
    "id_doc_jurisdiction_state": "Ontario", 
    "id_doc_verification_date": "2023-03-15", 
    "id_doc_source": "Government of Canada",
    "authorized_persons": [
      {
        "firstname": "Emily",
        "lastname": "Chen",
        "email": "emily.chen@techinnovations.com",
        "occupation": "Chief Technology Officer",
        "dob": "1982-05-16",
        "address1": "789 Corporate Blvd",
        "address2": "Apt 12",
        "city": "Mississauga",
        "state": "Ontario",
        "postcode": "L4W 1E4",
        "country": "Canada"
      }
    ],
    "directors": [
      {
        "firstname": "John",
        "lastname": "Doe"
      },
      {
        "firstname": "Jane",
        "lastname": "Smith"
      }
    ],
    "beneficial_owners": [
      {
        "kind": "individual",
        "firstname": "Robert",
        "lastname": "Brown",
        "address1": "456 Maple Street",
        "address2": "Unit 8",
        "city": "Vancouver",
        "state": "British Columbia",
        "postcode": "V6B 2Y1",
        "country": "Canada",
        "additional_info": "28% ownership" // Optional: Ownership percentage or notes for this individual beneficial owner
      },
      {
        "kind": "corporate",
        "corporate_name": "Venture Star Holdings", // Corporate beneficial owner
        "address1": "123 Innovation Drive",
        "city": "San Francisco",
        "state": "California",
        "postcode": "94105",
        "country": "United States",
        "additional_info": "32% ownership", // Optional: Ownership percentage or notes for this corporate beneficial owner
        "beneficial_owners": [
          {
            "kind": "individual",
            "firstname": "Jane",
            "lastname": "Doe",
            "address1": "789 Venture Lane",
            "city": "San Francisco",
            "state": "California",
            "postcode": "94107",
            "country": "United States",
            "additional_info": "50% beneficial owner of Venture Star Holdings"
          },
          {
            "kind": "individual",
            "firstname": "Jim",
            "lastname": "Bean",
            "address1": "321 Business Road",
            "city": "San Francisco",
            "state": "California",
            "postcode": "94110",
            "country": "United States",
            "additional_info": "45% beneficial owner of Venture Star Holdings"
          }
        ]
      }
    ]
  }
}

GET /api/v1/direct_parties/

Retrieve all direct parties.

Example Response

{
  "page_info": {
    "has_previous_page": false,
    "has_next_page": true,
    "start_cursor": "ODQ1NQ==",
    "end_cursor": "ODQzMg=="
  },
  "page": [
    {
      "cursor": "ODQ1NQ==",
      "data": {
        "id": 8455,
        "status": "pending_review",
        "kind": "individual",
        "fullname": "Vlad Test",
        "created_at": "2024-11-22T15:02:40.000Z",
        "updated_at": "2024-11-22T15:02:40.000Z",
        "address1": "123 Example Street",
        "city": "Toronto",
        "state": "Ontario",
        "postcode": "M5H 2N2",
        "country": "Canada",
        "email": "vlad.test@example.com",
        "id_doc_source": "Equifax",
        "dob": "1985-09-15",
        "firstname": "Vlad",
        "lastname": "Test"
      }
    },
    {
      "cursor": "ODQzMg==",
      "data": {
        "id": 8432,
        "status": "active",
        "kind": "corporate",
        "entity_name": "Tech Innovations Ltd.",
        "created_at": "2024-11-20T15:25:10.000Z",
        "updated_at": "2024-11-20T15:25:10.000Z",
        "address1": "789 Innovation Drive",
        "city": "San Francisco",
        "state": "California",
        "postcode": "94105",
        "country": "United States",
        "email": "contact@techinnovations.com",
        "nature_of_business": "Technology Consulting",
        "incorporation_number": "US987654321",
        "id_doc_source": "California Secretary of State"
      }
    }
    // [... additional entries truncated ...]
  ]
}

Pagination

To request more results, provide either a before or after parameter containing the cursor of the Direct Party whose data you want to retrieve prior to or after. For example, to request data after the result in the example above: GET /api/v1/direct_parties?after=MTI=

GET /api/v1/direct_parties/:id

Retrieve a single direct party.

Example Response

{
  "data": {
    "id": 10,
    "status": "active",
    "kind": "individual",
    "fullname": "Karma Boyer",
    "created_at": "2024-10-26T02:07:05.000Z",
    "updated_at": "2024-10-26T02:07:05.000Z",
    "address1": "859 Alexis Run",
    "address2": "Suite 478",
    "city": "Floriabury",
    "state": "Alberta",
    "postcode": "20848",
    "country": "Canada",
    "email": "hai_kohler@hessel-steuber.example",
    "address": {
      "address1": "859 Alexis Run",
      "address2": "Suite 478",
      "city": "Floriabury",
      "state": "Alberta",
      "postcode": "20848",
      "country": "Canada"
    },
    "client_number": "123",
    "self_custodied": true,
    "client_instructed": false,
    "id_doc_expiry_date": "2028-10-26",
    "id_doc_verification_date": "2024-10-24",
    "id_doc_source": "Equifax",
    "dob": "1968-12-19",
    "firstname": "Karma",
    "lastname": "Boyer",
    "occupation": "Government Officer",
    "id_doc_type_code": 4,
    "id_doc_number": "123123",
    "id_doc_jurisdiction_country": "Canada",
    "id_doc_jurisdiction_state": "Alberta"
  }
}

Uploading Documents

Authentication for document uploads differs from the usual Balance API authentication. To perform this authentication you may use the ApiAuth Ruby gem.

To perform this authentication first a canonical string based on some of the headers in the request and a hash of the body of the request is generated. This is formed as:

<HTTP method>,<content type>,<SHA256 hash of request body>,<request URI>,<timestamp>

A signature is calculated by base-64 encoding the SHA1 HMAC of the canonical string using your secret key.

Finally the signature is added to the request as a new header Authorization formed as:

APIAuth <access key>:<signature>

All document uploads must be submitted with a content type of multipart/form-data.

POST /api/v1/direct_parties/:id/custody_agreement

Purpose

This endpoint allows the submission of Custody Agreement signed by the Direct Party.

File Requirements

  • Supported file types: PDF

  • The document's field name must be document.

Example Request with Relevant Headers

X-Authorization-Content-SHA256: f27n20w/uQ8YRDJ8O/42ePJPHmyGLRxPAPW/fxEeh0c=
DATE: Sat, 26 Oct 2024 02:37:32 GMT
Authorization: APIAuth fqYumKdQD3KCqo2P1:mYR+BaZhUWahbmvnSjmaGyhYltY=

------RubyFormBoundary7P5EcdOzKDVHWwyD
Content-Disposition: form-data; name="document"; filename="sample.pdf"
Content-Type: application/pdf

%PDF-1.2
9 0 obj
%%EOF

------RubyFormBoundary7P5EcdOzKDVHWwyD--

POST /api/v1/direct_parties/:id/appointment_of_authorized_person_agreement

Purpose

This endpoint allows the submission of an Appointment of Authorized Person Agreement signed by the Direct Party and client.

File Requirements

  • Supported file types: PDF

  • The document's field name must be document.

Example Request with Relevant Headers

X-Authorization-Content-SHA256: f27n20w/uQ8YRDJ8O/42ePJPHmyGLRxPAPW/fxEeh0c=
DATE: Sat, 26 Oct 2024 02:37:32 GMT
Authorization: APIAuth fqYumKdQD3KCqo2P1:mYR+BaZhUWahbmvnSjmaGyhYltY=

------RubyFormBoundary7P5EcdOzKDVHWwyD
Content-Disposition: form-data; name="document"; filename="sample.pdf"
Content-Type: application/pdf

%PDF-1.2
9 0 obj
%%EOF

------RubyFormBoundary7P5EcdOzKDVHWwyD--

POST /api/v1/direct_parties/:id/supporting_documents

Purpose

The endpoint allows clients to upload additional documentation for onboarding or compliance purposes. These documents may include proof of identity, proof of address, or other relevant materials needed to verify the Direct Party’s information.

File Requirements

  • Supported file types: PDF, PNG, and JPEG

  • The document's field name must be document

  • A document_type field is required to specify the type of document being submitted using one of the supporting document type codes.

Example Request with Relevant Headers

X-Authorization-Content-SHA256: f27n20w/uQ8YRDJ8O/42ePJPHmyGLRxPAPW/fxEeh0c=
DATE: Sat, 26 Oct 2024 02:37:32 GMT
Authorization: APIAuth fqYumKdQD3KCqo2P1:mYR+BaZhUWahbmvnSjmaGyhYltY=

------RubyFormBoundaryuNL93g95URZcmncV
Content-Disposition: form-data; name="document"; filename="sample.pdf"
Content-Type: application/pdf

%PDF-1.2
9 0 obj
[...]
%%EOF

------RubyFormBoundaryuNL93g95URZcmncV
Content-Disposition: form-data; name="document_type"

40
------RubyFormBoundaryuNL93g95URZcmncV--

Last updated