Autopilot-Managed

Overview

Use this quick start guide to learn how to use DriveWealth’s API’s to prepare an Autopilot-managed investor portfolio which consists of two flows:

Flow 1: Registered Investment Advisor Developer Flow

  • Set up a portfolio of funds on behalf of a registered investment advisor (RIA) for an
    Investor.

Flow 2: Investor Developer Flow:

  • Create a deposit that is auto-invested by Autopilot into their portfolio.

Registered Investment Advisor Developer Flow
This section describes the APIs to use on behalf of a registered investment advisor (RIA). It creates two funds and then a portfolio that includes those funds, as the basis for an Autopilot-managed investor portfolio. The portfolio can then be selected by an investor or assigned by the RIA, after which the investor can deposit funds for auto-investment.


Prerequisites
Before you begin, ensure you have the following:

  • RIA user ID provided by DriveWealth when the environment is set up.
  • RIA product ID.
  • DriveWealth client app key.


Generate an Authentication Token

An authentication token is required for your client app to make requests with our API on behalf of the RIA.

Auth Request

Invoke POST '/back-office/auth' and pass in the following:
For the Header:

  • (Optional) Idempotency-Key: Idempotency key.
  • dw-client-app-key: Client app ID.

Body Parameters:

  • clientID as the value retrieved when generating Sandbox keys
  • clientSecret as the value retrieved when generating Sandbox keys
curl --request POST \
     --url https://bo-api.drivewealth.io/back-office/auth/tokens \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --header 'dw-client-app-key: 69204e73-561d-4...' \
     --data '{"clientID": "0oa5rc70..","clientSecret": "fr2k5wntp..."}'

Auth Response

The authToken field in the response contains the generated authentication token:

{
    "token_type": "Bearer",
    "expires_in": "3600",
    "access_token": "eyJraWQiOiJjY1lyLVRDUTZBR0w5OWl3TTFyMjAwWlNSdnI0dVBCZ3QxZU42eDhyRVVrIiwiYWxnIjoiUlMyNTYifQ.eyJ2ZXIiOjEsImp0aSI6IkFULmkwRmJtbzJkdU5Ya3EzREtyU3NkVTN4M3V3MnljSjhTdkctel9hMFM0VWMiLCJpc3MiOiJodHRwczovL2FwMS1kcml2ZXdlYWx0aC5va3RhcHJldmlldy5jb20vb2F1dGgyL2F1czJ6bWJsNnBOcE4zelZEMWQ3IiwiYXVkIjoiRFdBdXRoU2VydmVyREVWIiwiaWF0IjoxNjY0OTA4OTA2LCJleHAiOjE2NjQ5MTI1MDYsImNpZCI6IjBvYTVubnk0bzlCZU1zQVlRMWQ3Iiwic2NwIjpbImFsbF90cmFkZXIiXSwic3ViIjoiMG9hNW5ueTRvOUJlTXNBWVExZDciLCJwcm9maWxlIjp7InBlcm1pc3Npb25JRCI6IjY5NTQ3OWFhLTVmN2ItNDRhOC1hMTE4LWFhOWU2N2M3YmUyZSIsInJvbGUiOiJBTExfVFJBREVSIiwicGFydG5lcklEIjoiMThkNTk3NjctNzNiOC00YTM0LWE1NDItMWNjZDIyYmEzNjAyIiwidXNlcklEIjoiNzA1YzFiMDMtM2Y2YS00MmFhLTgwN2EtMWY0NGMwNjc0ZDhmIn19.p3fspVtifQ_Gr4K3pi5fTorCBrcuVkRxk-yNLANgiKvl3t0BKraMT7_Y8c8opsKmNUwLS2K3YlBA0vrskzxeacWtEDx_JGtz_zKS_GXWTPDNNd77Zy0P6vfNfDjc_Hbzpp90dAICrTwvrcihNbyLeL3Zq7LisGpDkYtdxwB73AHtU6qIQvPY-iYaWBLfJ9IZrTTNWd5Qqy8ICJNunrS5riD2O3o4idyzMoUnFimUAoiAwgqtSOh4Loe57kPQsCgNRoba0zbnXKNd0eyMHCCdM0BXW_uhyJIfdGUXVzCcg9k_G80sWnefTeitwdX0S657vKHTjyLsGJSc06ZggGdlag",
    "scope": "all_trader"
}

You will use the generated authToken in the sections below to make requests on behalf of the RIA in your client app.

Create Two Funds

Multiple funds can be created and included in a portfolio. In this step you will create two funds.

Fund Request

Follow the steps below to create these funds:

Invoke POST /managed/funds and pass in the following to create a fund:
Body Parameters:

  • userID: RIA ID.
  • clientFundID: Unique ID for the fund generated by your institution.
  • holdings: One or more instruments to include in the fund.
  • triggers: Specifies how much a security can drift from its target weights before an allocation is triggered.

Note: You can get a list of all instruments and their IDs by invoking GET /back-office/instruments.

Each target value must be greater than 0.0 and less than or equal to 1.0. The values for all holdings must add up to 1.0 (100%).

Repeat Step 1 to create a second fund. Pass in the same userID, but a unique clientFundID value and the desired instrument(s).

The following shows an example request in cURL:

curl --location --request POST 'https://bo-api.drivewealth.io/back-office/managed/funds' \
--header 'Authorization: Bearer :authToken' \
--header 'dw-client-app-key: f988b...' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data-raw '{
     "userID": "2843...",
     "name": "Tech Fund",
     "clientFundID": "1538773354123",
     "description": "Top Technology Companies",
     "holdings": [
          {
               "instrumentID": "920a6...",
               "target": 1.0
          }
     ],
     "triggers": [
          {
               "type": "TOTAL_DRIFT",
               "maxAllowed": 0.05
          }
     ]          
}'

Fund Response
The id field in the response contains the ID of the newly-created fund. You will use this later when creating a portfolio of funds:

{
  "id": "fund_dff7a...",
  "userID": "2843...",
  "name": "Tech Fund",
  "clientFundID": "1538773354123",
  "description": "Top Technology Companies",
  "holdings": [
    {
      "instrumentID": "a67422af-8504-43df-9e63-7361eb0bd99e",
      "target": 0.8
    },
    {
      "instrumentID": "a74c5ebd-c534-4e6f-804a-5e3d4044c7a9",
      "target": 0.2
    }
  ],
  "triggers": [
    {
      "child": null,
      "maxAllowed": 0.05,
      "lowerBound": null,
      "upperBound": null,
      "type": "TOTAL_DRIFT"
    }
  ]
}

Create a Portfolio

A portfolio is a type of fund that contains a collection of funds, rather than securities.

This step shows how to create a portfolio that includes the two funds created above.

Portfolio Request

Invoke POST /managed/portfolios and pass in the following:

Body Parameters:

  • userID: Same RIA ID that was used to create the funds above.
  • clientPortfolioID: Unique ID for the portfolio generated by your institution.
  • holdings: One or more funds to include in the portfolio. For each fund set the type to FUND and the id to one of the IDs of the funds created above.
  • triggers: Specifies how much a security can drift from its target weights before an allocation is triggered.

Note: You can get a list of all funds and their IDs by invoking GET /list-individual-advisor-funds.
Each target value must be greater than 0.0 and less than or equal to 1.0. The values for all holdings must add up to 1.0 (100%).

The following shows an example request in cURL:

curl --location --request POST 'https://bo-api.drivewealth.io/back-office/managed/portfolios' \
--header 'Authorization: Bearer :authToken' \
--header 'dw-client-app-key: f988...' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data-raw '{
     "userID": "2843...",
     "name": "Aggressive Portfolio",
     "clientPortfolioID": "998877",
     "description": "This is a portfolio for aggressive investors",
     "holdings": [
          {
               "type": "FUND",
               "id": "fund_dff7a...",
               "target": 0.3
          },
          {
               "type": "FUND",
               "id": "fund_dff7b...",
               "target": 0.7
          }          
     ],
     "triggers": [
          {
               "type": "TOTAL_DRIFT",
               "maxAllowed": 0.05
          }
     ]          
}'

Portfolio Response

The id field in the response contains the ID of the newly created portfolio:

{
    "id": "portfolio_548e23",
    "name": "Aggressive Portfolio",
    "description": "This is a portfolio for aggressive investors",
    "clientPortfolioID": "998877",
    "holdings": [
        {
            "id": "fund_dff7a...",
            "name": "Tech Fund",
            "type": "FUND",
            "clientFundID": "1538773354125",
            "description": "Top Technology Companies",
            "target": 0.3,
            "holdings": [
                {
                    "instrumentID": "920a622a...",
                    "target": 1
                }
            ],
            "triggers": [
                {
                    "child": null,
                    "maxAllowed": 0.05,
                    "lowerBound": null,
                    "upperBound": null,
                    "type": "TOTAL_DRIFT"
                }
            ]
        },
        {
            "id": "fund_dff7b",
            "name": "Tech Fund",
            "type": "FUND",
            "clientFundID": "1538773354126",
            "description": "Top Other Companies",
            "target": 0.7,
            "holdings": [
                {
                    "instrumentID": "920a6...",
                    "target": 1
                }
            ],
            "triggers": [
                {
                    "child": null,
                    "maxAllowed": 0.05,
                    "lowerBound": null,
                    "upperBound": null,
                    "type": "TOTAL_DRIFT"
                }
            ]
        }
    ],
    "userID": "4f49e6d9-5929-4197-8123-537f29822b6a",
    "triggers": [
        {
            "child": null,
            "maxAllowed": 0.05,
            "lowerBound": null,
            "upperBound": null,
            "type": "TOTAL_DRIFT"
        }
    ],
    "isFundTargetsChanged": false,
    "fundTargetsChanged": false
}

Investor Developer Flow

Once the portfolio is created, it can be assigned to the investor via the partner (e.g. via the partner's UI or other partner-level logic). The client can then create a deposit which is auto-invested in the portfolio.

This section shows how to create a deposit on behalf of the investor that becomes auto-invested into their portfolio.

Prerequisites
Before you begin, ensure you have the following:

  • ID of the RIA.
  • ID of a portfolio generated by an RIA. This ID is available after completing the RIA flow above.
  • Generate an Authentication Token
  • An authentication token is required for your client app to make requests with our API on behalf of the investor.

Invoke POST /back-office/auth and pass in the following:
For the Headers:

  • (Optional) Idempotency-Key: Idempotency key.
  • dw-client-app-key: Client app ID.

Body Parameters:

  • username: Investor's name.
  • password: Investor's password.
  • appTypeID: Set to 4.

Create an Investor User

The next step is to create a User entity in DriveWealth that represents the investor.

Create User Request

Invoke POST /back-office/users and pass in the following:
For the Header:

  • Authentication token (generated in the previous section)
  • Client app ID

Body Parameters:
The user's information in the body of the request.

curl --location --request POST 'https://bo-api.drivewealth.io/back-office/users' \
--header 'Authorization: Bearer :authToken' \
--header 'dw-client-app-key: f988...' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data-raw '{
  "userType":"INDIVIDUAL_TRADER",
  "wlpID":"DWTT",
  "documents": [
       {
            "type": "BASIC_INFO",
            "data": {
                "firstName": "Daryl",
                "lastName": "Hall",
                "username": "DHall",
                "country": "USA", 
                "phone": "291...",
                "emailAddress": "[email protected]",
                "language": "en_US"
            }
        },
        {
            "type": "IDENTIFICATION_INFO",
            "data": {
                "value": "123456789",
                "type": "SSN",
                "citizenship": "USA"
            }
        },
        {
            "type": "PERSONAL_INFO",
            "data": {
                "birthDay": 3,
                "birthMonth": 12,
                "birthYear": 1990,
                "politicallyExposedNames": null
            }
        },
        {
            "type": "ADDRESS_INFO",
            "data": {
                "street1": "123 Main St",
                "city": "Chatham",
                "province": "NJ",
                "postalCode": "09812"
            }
        },
        {
            "type": "EMPLOYMENT_INFO",
            "data": {
                "status": "Employed",
                "broker": false,
                "type": "PROFESSIONAL",
                "position": "Police"
            }
        },
        {
            "type": "INVESTOR_PROFILE_INFO",
            "data": {
                "investmentObjectives": "Active_DAIly",
                "investmentExperience": "None",
                "annualIncome": 75000, 
                "networthLiquid": 58932,
                "networthTotal": 485003,
                "riskTolerance": "Low"
            }
        },
        {
            "type": "DISCLOSURES",
            "data": {
                "termsOfUse": true,
                "customerAgreement": true,
                "marketDataAgreement": true,
                "rule14b": true,
                "findersFee": false,
                "privacyPolicy": true,
                "dataSharing": true,
                "signedBy": "Chris Turkelton"
            }
        }        
  ],
  "parentIBID":"acb33c..."
}'

Create User Response

The id field in the response contains the ID for the newly-created user:

{
    "id": "261fb...",
    "userType": {
        "name": "INDIVIDUAL_TRADER",
        "description": "Individual Trader"
    },
    "status": {
        "name": "APPROVED",
        "description": "User approved."
    },
    "parentIB": {
        "id": "acb33c...",
        "name": "DriveWealth"
    },
    "documents": [
        {
            "type": "ADDRESS_INFO",
            "data": {
                "street1": "123 Main St",
                "city": "Chatham",
                "province": "NJ",
                "postalCode": "09812",
                "country": "USA"
            },
            "description": "Physical address information"
        },

        ...

    ],
    "wlpID": "DWTT",
    "referralCode": "CEB...",
    "createdWhen": "2022-04-20T21:49:34.452Z",
    "updatedWhen": "2022-04-20T21:49:34.452Z"
}

The ID generated for the user will be used in subsequent requests below to perform actions on behalf of the user.

Create an Account

Create an account for an existing DriveWealth investor user that is linked to the RIA user and the portfolio created above.

Create Account Request

Invoke POST /back-office/accounts and pass in the following:

Body Parameters:

  • userID: ID of the investor user.
  • riaUserID: ID of the RIA who created the portfolio.
  • riaPortfolioID: ID of the portfolio created above.
curl --location --request POST 'https://bo-api.drivewealth.io/back-office/accounts' \
--header 'Authorization: Bearer :authToken' \
--header 'dw-client-app-key: f988...' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data-raw '{
  "userID":"261fb...",
  "accountType": "LIVE",
  "accountManagementType": "RIA_MANAGED",
  "tradingType": "CASH",
  "riaUserID": "2843...",
  "riaProductID": "product_123...",
  "riaPortfolioID":"portfolio_548e23..."
}'

Response

The id and accountNo fields in the response uniquely identify the newly created account:

{
    "id": "2f977...",
    "accountNo": "ZBG...",
    "accountType": {
        "name": "LIVE",
        "description": "Live Account"
    },
    "accountMgmtType": {
        "name": "SELF",
        "description": "Self Directed Account"
    },
    "status": {
        "name": "OPEN",
        "description": "Open"
    },
    "tradingType": {
        "name": "CASH",
        "description": "Cash account"
    },
    "leverage": 1.00,
    "nickname": "Daryltwo's Self Directed Account",
    "parentIB": {
        "id": "0067..",
        "name": "DWPSGTest"
    },
    "commissionID": "164..",
    "beneficiaries": false,
    "userID": "261fb...",
    "restricted": false,
    "goodFaithViolations": 0,
    "patternDayTrades": 0,
    "freeTradeBalance": 0,
    "gfvPdtExempt": false,
    "buyingPowerOverride": true,
    "bod": {},
    "sweepInd": true,
    "interestFree": false,
    "openedWhen": "2022-05-13T18:46:12Z",
    "ignoreMarketHoursForTest": false,
    "flaggedForACATS": false
}

Create a Deposit Request

Now create a deposit request on behalf of the investor.

Deposit Request

Invoke POST /back-office/funding/deposits and pass in the following:
For the Headers:

  • dw-auth-token: Authentication token generated above for the investor
  • Idempotency-Key: Idempotency key (optional)
  • dw-client-app-key: Client app ID

Body Parameters:

  • accountNo: Account number for the investor's DriveWealth brokerage account created in the previous step.
  • amount: Amount of fund.
  • currency: Currency for the fund.
  • type: Type of fund.
curl --location --request POST 'https://bo-api.drivewealth.io/back-office/funding/deposits' \
--header 'Authorization: Bearer :authToken' \
--header 'dw-client-app-key: f988...' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data-raw '{
  "accountNo": "ZBG...",
  "amount": 500,
  "currency": "USD",  
  "type": "INSTANT_FUNDING", 
  "note": "Some money for funding" 
}'

Response

The id field in the response identifies the funding request:

{
    "id": "ZBCB000...",
    "accountNo": "ZBC...",
    "category": "DEPOSIT",
    "currency": "USD",
    "amount": 500,
    "status": {
        "id": 1,
        "message": "Pending",
        "updated": "2022-04-26T17:56:25.295Z"
    },
    "source": {
        "id": "INSTANT_FUNDING",
        "brand": "Instant funding",
        "meta_info": "Some money for funding"
    },
    "created": "2022-04-26T17:56:25.295Z",
    "accountID": "261fb...",
    "userID": "261fb...",
    "transactionCode": "JOURNAL",
    "wlpFinTranTypeID": "f197...",
    "batch": true,
    "account_number": "ZBG..."
}

Force a Rebalance

Since Autopilot is responsible for the creation of orders, we'll simulate a forced rebalance which is outside of normal operations but provides a real-time feel for this quickstart.

Follow the steps below to force a rebalance:

Invoke POST /managed/autopilot/{riaID} and pass in the following to force the investment into the portfolio assigned to an investor:

Body Parameters:

  • riaID: RIA's user ID.
  • forceRebalance: Set to true.

*Rebalance Request

curl --location --request POST 'https://bo-api.drivewealth.io/back-office/managed/autopilot/2843...' \
--header 'Authorization: Bearer :authToken' \
--header 'dw-client-app-key: f988b...' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data-raw '{
  "reviewOnly": false,
  "forceRebalance": true
}'

Response

The status field in the response indicates the result of the request:

"id": "ria_rebalance_af027...",
    "created": "2022-05-10T20:07:09.254Z",
    "status": "REBALANCE_NOT_STARTED",
    "riaID": "2843..."
}

Note: Rebalance is a multi-step process that could take a few seconds to complete, depending on the load of DriveWealth's internal systems. In the example above, the status value: REBALANCE_NOT_STARTED indicates that rebalancing has yet to start. Step 2 below shows how to re-check the balance.

Invoke GET /managed/autopilot/{rebalanceRunID} and pass in the following

Path parameters:
id: The rebalance ID returned in the previous step.

Request

curl --location --request GET 'https://bo-api.drivewealth.io/back-office/managed/autopilot/ria_rebalance_076d4d2b-47d6-46f9-8b05-dccbe122ad4a' \
--header 'Authorization: Bearer :authToken' \
--header 'dw-client-app-key: f988b...' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json'

Response
The status field in the response shows the current status:

{
    "id": "ria_rebalance_af027...",
    "riaID": "4f49e6d9-5929-4197-8123-537f29822b6a",
    "status": "SUCCESS",
    "updated": "2022-05-16T13:56:05.057Z",
    "created": "2022-05-16T13:55:57.375Z",
    "moneyMovement": false,
    "regularRebalance": false,
    "reviewOnly": false,
    "orders": {
        "total": 1,
        "submitted": "https://uat.drivewealth.autopilot.s3.amazonaws.com/4f49...",
        "outcome": "https://uat.drivewealth.autopilot.s3.amazonaws.com/4f49...",
        "amountBuys": -0.35,
        "amountSells": 0,
        "cleanedUp": null
    },
    "allocations": {
        "submitted": "https://uat.drivewealth.autopilot.s3.amazonaws.com/4f4...",
        "outcome": "https://uat.drivewealth.autopilot.s3.amazonaws.com/4f49..."
    },
    "subAccounts": {
        "total": 1,
        "rebalanced": 1,
        "error": 0,
        "outcome": "https://uat.drivewealth.autopilot.s3.amazonaws.com/4f4..."
    }
}

Generate a Report of Holdings

You can check the status of the investor's portfolio holdings and positions at any time.

Request

Invoke GET /accounts/{accountID}/summary and pass in the following:

Path parameters:
accountID: Investor's account ID.

curl --location --request GET 'https://bo-api.drivewealth.io/back-office/accounts/2f977.../summary' \
--header 'Authorization: Bearer :authToken' \
--header 'dw-client-app-key: f988b...' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json'

Response

The response contains a summary of the account:

{
    "accountSummary": {
        "accountID": "2f977...",
        "accountNo": "ZBJC...",
        "tradingType": "CASH",
        "lastUpdated": "2022-05-09T19:48:25.154Z",
        "cash": {
            "cashAvailableForTrade": 0,
            "cashAvailableForWithdrawal": 0,
            "cashBalance": 0,
            "noBuyingPowerReason": null,
            "cashSettlement": [
                {
                    "utcTime": "2022-05-10T13:30:00.001Z",
                    "cash": 0
                },
                {
                    "utcTime": "2022-05-11T13:30:00.001Z",
                    "cash": 0
                }
            ],
            "pendingPaymentsAmount": 0
        },
        "margin": null,
        "violations": {
            "goodFaithViolations": {
                "count": 0
            },
            "patternDayTrades": null,
            "details": null
        },
        "equity": {
            "equityValue": 0,
            "equityPositions": []
        },
        "orders": [],
        "transactions": []
    }
}

This completes the Autopilot-managed quickstart.