Skip to content

Business Objects


Introduction

This page describes the business objects used by InvestSuite, and the interactions that are possible on them.

The business objects are also referred to as (a collection of) entities.

Concepts

Internal ID

The first letter of the internal ID of an entity is defined by its type, eg. the ID of a Portfolio will always start with a P.

External ID

Middleware

The external_id typically maps to the id in the Client middleware.

Entities have an external_id field. The field is not required, but if it is provided, it must be unique.

Immutability

Objects in the InvestSuite system are immutable. Every change leads to a new version so that a log exists of who performed which change at which moment. The version number is returned alongside other metadata fields. Use the Admin Console to access this log and to view diffs between versions.

Querying business objects

To query a specific business object, send a GET request to the entity root path e.g. GET /users, GET /portfolios, GET /instrument_groups.

Collection endpoints accept the following parameters:

Parameter Description
limit Example: limit=50. Allows you to pass in the number of items to be returned in the results array of the response. The default collection response size is 20 items. The maximum size is 100.
offset Example offset=50. To be used in combination with the limit parameter, the offset defines the number of records that need to be skipped.
embed Example: embed=field_name_1,field_name_2. Optional comma-separated list of field names for which the referenced entity is to be included in the _embedded object of the response. See Embedding.
query Example: query=email+eq+'jane.doe@example.com. See below.
GET /portfolios/
    ?embed=owned_by_user_id
    &limit=2 HTTP/1.1
Host: api.sandbox.investsuite.com
Content-Type: application/json
Authorization: Bearer {string}
{
    "next":"http://api.sandbox.investsuite.com/portfolios/?embed=owned_by_user_id&limit=2",
    "count":204,
    "offset":"10",
    "results":[
    {
        "external_id":"AE820230000000000001918",
        "readable_by":[
            "U01ERYVVSZTKKYEEVX3Y6JECE83"
        ],
        "modifiable_by":[
            "U01ERYVVSZTKKYEEVX3Y6JECE83"
        ],
        "name":"Child's education",
        "owned_by_user_id":"U01ERYVVSZTKKYEEVX3Y6JECE83",
        "base_currency":"USD",
        "money_type":"REAL_MONEY",
        "config":{
            "manager":"ROBO_ADVISOR_DISCRETIONARY",
            "manager_version":1,
            "manager_settings":{
                "policy_id":"Y01F5G34T4FE6T1EH798FA0M170",
                "goal_id":"L01EF46X3JH1QDFPD270BKSDTTX",
                "horizon_id":"H01EF46X564YMWFR8GTNBED16CN",
                "risk_profile_id":"K01EF46X76V5VB4E92FC1D01856",
                "divest_amount":null,
                "start_amount":600.0,
                "recurring_deposit_amount":500.0,
                "end_datetime":null,
                "active":true,
                "proposed_risk_profile_id":"K01EF46X76V5VB4E92FC1D01856",
                "tags":[

                ],
                "risk_profile_score":3,
                "background_image":"https://images.unsplash.com/photo-1526304640581-d334cdbbf45e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1200&q=82",
                "background_color":null
            }
        },
        "brokerage_account":{
            "brokerage_portfolio_id":"BrokerAccountKey",
            "brokerage_user_id":"BrokerAccountId",
            "bank_account_type":"IBAN",
            "bank_account_number":"AE820230000000000001918",
            "bank_id":null
        },
        "owned_by_user_ids":[

        ],
        "portfolio":{

        },
        "snapshot_datetime":null,
        "archived":false,
        "funded_since":null,
        "id":"P01F7KDVY6H718JNV91840DE5V4",
        "creation_datetime":"2021-06-07T00:00:00+00:00",
        "version":2,
        "version_datetime":"2021-06-07T14:26:21.231855+00:00",
        "version_authored_by_user_id":"U01ERYVVSZTKKYEEVX3Y6JECE83",
        "deleted":false,
        "_embedded":{

        },
        "status":"WAITING_FOR_FUNDS"
    }
    ],
    "_embedded":{
    "U01ERYVVSZTKKYEEVX3Y6JECE83":{
        "external_id":null,
        "readable_by":[
            "U01F5XFY0S38KJYVHX0X3GJ4KWM",
            "UXXXXXXXXXXXXXXXXXXXXXXXXXX"
        ],
        "modifiable_by":[
            "U01F5XFY0S38KJYVHX0X3GJ4KWM",
            "UXXXXXXXXXXXXXXXXXXXXXXXXXX"
        ],
        "id":"U01F5XFY0S38KJYVHX0X3GJ4KWM",
        "creation_datetime":"2021-05-17T00:00:00+00:00",
        "version":1,
        "version_datetime":"2021-05-17T15:43:23.427412+00:00",
        "version_authored_by_user_id":"UXXXXXXXXXXXXXXXXXXXXXXXXXX",
        "deleted":false,
        "_embedded":{

        },
        "first_name":"Laurent",
        "last_name":"Sorber",
        "email":"laurent.sorber@gmail.com",
        "phone":null,
        "brokerage_user_id":null,
        "idp_user_id":"a8c8b808-bad9-4acb-babf-aae52488e468",
        "language":"en-US",
        "products":[

        ]
    }
    }
}    

Query syntax

The API provides a structural search and filtering mechanism for all entities. We already opted to work with a query string parameter query=email+eq+'jane.doe@example.com instead of a POST body for more efficient client-side caching and ease of use for testing. The query syntax is a mix of both OData and Apache Lucene Query Parser Syntax.

GET /portfolios
    ?query=lastmodified+in+['20200101'+to+'20240101'] HTTP/1.1
Host: api.sandbox.investsuite.com
Content-Type: application/json
Authorization: Bearer {string}

Info

  • Every entity type can be queried by issuing a GET request e.g. GET users/?query=email+eq+'jane*'.
  • The query string must be URL encoded. This implies that spaces would be transformed to %20, but for improved legibility we recommend using + instead

Operators

Warning

Due to implementation details (eg. amounts are typically stored as strings to preserve precision) the behavior of these operators may vary.

Operator type Operator Example
Number operator Exact match age eq 1
Number operator Less than age lt 18
Number operator Less than or equal age le 18
Number operator Greater than age gt 18
Number operator Greater than or equal age ge 18
String operator Exact match email eq 'jane.doe@example.com'
String operator Prefix search email eq john*
String operator Postfix search email eq '*gmail.com'
String operator LIKE matching email eq '*gmail*'
Date operator Exact match last_modified eq '2020-09-11T09:03:53.721588+00:00'
Date operator Is in range for dates without time lastmodified in ['20200101' to '20210101']
Date operator Is in range for dates with time lastmodified in ['2020-09-11T09:03:53.721588' to '2020-11-11T09:03:53.721588']
Date operator Is in range for dates with timeezone lastmodified in ['2020-09-11T09:03:53.721588+00:00' to '2020-11-11T09:03:53.721588+00:00']
Boolean operator Boolean queries archived eq true
Null comparison Equals null field eq null
NOTE the is null operator is (by design) not supported.
Null comparison Not equal to null field neq null
List operator IN (element of) field in ['value1', 'value2', 'value3']
Logical operator AND, OR email eq kristof and age gt 18

Hint

You can combine operators in all possible compositions e.g. query=email+eq+'*tom*'+and+firstname+in+[’tom',+‘thomas’].

Sorting

The sorting operator always comes as the last term, except when there is a selection term which is always at the very last:

  • orderby {attribute_name}, orderby {attribute_name} asc e.g. orderby+age is always ascending, so the same as orderby+age+asc
  • Order descending: orderby {attribute_name} desc e.g. orderby+age+desc
  • Multiple attributes: orderby {attribute_name} desc, {attribute_name2} asc e.g. orderby+age+desc,+firstname
  • Attributes names can be nested e.g. orderby+manager.bank_account.

Pagination

Business objects can be enumerated by paginating through the entire collection.

Issuing a GET request to the entity root path will return a next cursor:

GET /portfolios HTTP/1.1
Host: api.sandbox.investsuite.com
Content-Type: application/json
Authorization: Bearer {string}
{
    "next": "/portfolios/?limit=20&offset=20",
    "count": "20",
    "offset": "20",
    "results": [
        ...
    ],
    "_embedded": {}
}
{
    "next": null,
    "count": "15",
    "offset": "20",
    "results": [
        ...
    ],
    "_embedded": {}
}

List of business objects

Common:

Robo Advisor only: