Batch Transfer

Request:

mutation {
  batchTransfer (
    input: {
      idempotencyId: ""
      transfer: [
        {
          idempotencyId: ""
          investorId: ""
          securityId: ""
          usdPrice: ""
          transferPrice: {
            currency: ""
            amount: ""
          }
          holdings: [
            {
              id: ""
              amount: ""
            }
          ]
          signature: {
            status: ""
            signature: ""
            date: ""
          }
          investorInformation: {
            name: ""
            taxId: ""
            email: ""
            address: [
              {
                lineOne: ""
                lineTwo: ""
                lineThree: ""
                lineFour: ""
                city: ""
                province: ""
                postalCode: ""
                country: ""
              }
            ]
            parties: [
              {
              	firstName: ""
              	lastName: ""
              	taxId: ""
              	email: ""
              	address: [
                  {
                    lineOne: ""
                    lineTwo: ""
                    lineThree: ""
                    lineFour: ""
                    city: ""
                    province: ""
                    postalCode: ""
                    country: ""
                  }
                ]
              }
            ]
            data: {
              field1: ""
              field2: ""
            }
          }
          to: {
            id: ""
            email: ""
            name: ""
            jurisdiction: ""
            accountSetupData: {
              type: ""
              formationDate: ""
              taxId: ""
              addresses: [
                {
                  lineOne: ""
                  lineTwo: ""
                  lineThree: ""
                  lineFour: ""
                  city: ""
                  province: ""
                  postalCode: ""
                  country: ""
                  type: ""
                }
              ]
              parties: [
                {
                  email: ""
                  firstName: ""
                  lastName: ""
                  taxId: ""
                  dateOfBirth: ""
                  usCitizen: true
                  isPrimary: true
                  allowLogin: true
                  addresses: [
                    {
                      lineOne: ""
                      lineTwo: ""
                      lineThree: ""
                      lineFour: ""
                      city: ""
                      province: ""
                      postalCode: ""
                      country: ""
                      type: ""
                    }
                  ]
                }
              ]
            }
          }
          tags: [
            {
              id: ""
              data: {
                field1: ""
                field2: ""
              }
            }
          ]
          data: {
            field1: ""
            field2: ""
          }
          matchedOn: ""
          settledOn: ""
        }
      ]
    }
  ) {
    id
    requestId
    type
    status
    createdOn
    executedOn
    requestByRequestId {
      data
    }
  }
}
Numeric field Usage
transfer.usdPrice The price per share/unit expressed in USD
transfer.transferPrice.currency* The currency used to pay for the shares/units (eg. “BTC”)
transfer.transferPrice.amount* The price per share/unit in the currency used for payment
transfer.holdings.amount The amount of shares/units being transferred for the specific holding

* Optional - may be used if a currency other than USD is used in the transfer; Vertalo is not responsible for any form of conversion between currencies

The example above shows the full extent of the batchTransfer mutation, through which you submit one or more transfer requests as a result of trades occuring on the ATS platform. The transfer field is an array which contains one more transfer requests, each of which provides the required detail of the respective transfer. Each transfer must go through a review process, and once approved, shares are moved between the parties involved and a callback issued to a predetermined endpoint at the ATS. (See the Webhook section below.)

Note: Not all fields in the mutation are required. Please refer to the Documentation Explorer in GraphiQL (described in the Getting Going section of the Introduction) for a detailed description of the mutation, including field types, required fields, etc.

Request:

mutation {
  batchTransfer (
    input: {
      idempotencyId: "15488176-e794-455e-9461-98f96d826b19"
      transfer: [
        {
          idempotencyId: "db97e335-0c1b-43c0-95fd-0facb97e6288"
          investorId: "7eb06212-3abe-48cd-9518-8de536d12fac"
          securityId: "4b0cddfb-9d01-4e2c-84f2-10e6fd504542"
          usdPrice: "5.00"
          holdings: [
            {
              id: "9d4f1a94-e8d0-4002-859f-f0c277cfd5a0"
              amount: "20000"
            }
          ]
          signature: {
            status: "true"
            signature: "Mary Smith"
            date: "2022-09-21T09:00:00.430Z"
          }
          to: {
            email: "barbara.peters@example.com"
            name: "Barbara Peters"
            jurisdiction: "USA"
            accountSetupData: {
              type: "Individual"
              formationDate: "04/19/1973"
              taxId: "123456789"
              addresses: [
                {
                  lineOne: "123 Main St"
                  lineTwo: ""
                  lineThree: ""
                  lineFour: ""
                  city: "Decatur"
                  province: "Georgia"
                  postalCode: "30033"
                  country: "d4dc0fe9-fcdb-4d4d-a2c1-f9a247897362"
                  type: "Primary"
                }
              ]
              parties: [
                {
                  email: "barbara.peters@example.com"
                  firstName: "Barbara"
                  lastName: "Peters"
                  taxId: "123456789"
                  dateOfBirth: "04/19/1973"
                  usCitizen: true
                  isPrimary: true
                  allowLogin: false
                  addresses: [
                    {
                      lineOne: "123 Main St"
                      lineTwo: ""
                      lineThree: ""
                      lineFour: ""
                      city: "Decatur"
                      province: "Georgia"
                      postalCode: "30033"
                      country: "d4dc0fe9-fcdb-4d4d-a2c1-f9a247897362"
                      type: "Primary"
                    }
                  ]
                }
              ]
            }
          }
          matchedOn: "2022-09-20T11:01:04.430Z"
          settledOn: "2022-09-21T09:00:00.430Z"
        }
      ]
    }
  ) {
    id
    requestId
    type
    status
    createdOn
    executedOn
    requestByRequestId {
      data
    }
  }
}

In this (concrete) example, the mutation submits a single transfer request, moving shares from an existing investor on the cap table (identified by the investorId field) to another investor not on the cap table (identified by the to object).

IMPORTANT: At least ONE party must be defined in the mutation for the transfer.to.accountSetupData object. In the case of an individual investor, you may simply duplicate the information from the primary fields as shown above (although this is not enforced). For other investor types (see below), enter the appropriate party information.

Note: In a previous version of this mutation, the transfer.to.investorInformation object was featured. This object is still supported (and visible in the GraphQL schema), though it has been subsumed by the transfer.to.accountSetupData object. The difference is in how the information is stored and how it is subsequently exposed via the API.

Signature

The signature object is a required element of the transfer request. This is simply a field into which your investors (sellers) type their legal name just as they would if they were signing by hand, and must be captured at the point where the investor authorizes the sale of their shares. Failure to include a signature will result in the denial of the transfer request in cases where Vertalo is acting as legal transfer agent.

Response

The response from the batchTransfer mutation is a JSON object which contains an array of the transfer requests submitted through the mutation. The array is ordered based on the ordering of the transfer requests. Each object in the array corresponds to a single transfer and may contain any or all of the following fields (depending on which ones you include in the mutation return payload):

  • id (uuid)
  • accountId (uuid)
  • securityId (uuid)
  • requestId (uuid)
  • type (string)
  • status (string)
  • webhookId (uuid)
  • data (JSON)
  • createdOn (datetime)
  • executedOn (datetime)

You may also include a requestByRequestId field in the mutation response; this allows you to inspect a data field which contains a JSON blob that corresponds to the original transfer request you submitted.

New vs. Existing Investors

It is highly likely that a transfer may involve an investor (the “to” investor in this context) that is not already in the Vertalo system. In this case, the system allows you to create the investor on-the-fly using a combination of required fields in the transfer.to object:

  • email
  • name
  • jurisdiction

If the investor is already in the Vertalo system (for instance, if you created the investor as a separate step using the makeInvestor mutation described in the previous chapter), then all that is required in the transfer.to object is the investor’s ID supplied in the id field.

IMPORTANT: to.id is mutually exclusive of to.email, to.name, and to.jurisdiction. The system will throw an error if to.id is combined with any of these fields.

Idempotency

An idempotency ID is required for the mutation as a whole, as well as for each transfer object in the mutation. These IDs are returned to you using the requestByRequestId field mentioned above.

Webhook

Vertalo will configure a webhook which will issue a callback to an endpoint you provide. The callback will be issued for each transfer contained in the batchTransfer mutation, once the transfer has been reviewed and a disposition assigned. The format of the callback is:

{
  "id": "<UUID of transfer request>",
  "status": "complete | failed"
}

The id field contained in the callback corresponds to an id field in the response returned by the mutation (see above).

Authorization

In order to verify that the callback is coming from Vertalo, we will configure a shared secret to be included in a JWT in the Authorization header of the callback. Vertalo support will coordinate with you to complete this process.

Testing

For testing purposes, you can make use of a feature that let’s you configure a transfer request to be automatically approved or rejected. This will result in a callback to the endpoint we have configured as your webhook for transfer requests. This feature is ONLY available in the Vertalo sandbox environment. To implement this feature you must included the tags field in your transfer request as follows:

tags: [
  {    
    id: "<your UUID>"
    data: {
        _autocomplete_to_status: "complete"
    }
 }
]

-or-

tags: [
  {    
    id: "<your UUID>"
    data: {
        _autocomplete_to_status: "failed"
    }
  }
]