NAV Navbar
DOCS
shell python
  • Introduction
  • General
  • OAuth
  • Products
  • Companies
  • Customer Profiles
  • User Onboarding
  • Accounts and Portfolio
  • Robowise
  • Reporting
  • Market
  • Events and Webhooks
  • Introduction

    Here at WiseAlpha we are leading the digital revolution in the multi-trillion corporate bond market with a mission to create fair access for all. We are delighted to partner with you.

    The WiseAlpha API provides access to the WiseAlpha Fractional Bond Market where customers can trade corporate bonds.

    We provide two types of API access, Super accounts and Individual accounts. Super accounts (typically Fintechs, Banks and Online investment platforms) can onboard customers and route orders directly to the WiseAlpha market from their Customers on a real time execution basis. Individual accounts can access information and execute trades on behalf of their own account.

    When a Customer is on-boarded by a Super account, a series of steps must be taken including KYC/AML so that WiseAlpha can comply with its regulatory requirements. If you think that these steps can be simplified because of your own regulatory permissions and putting in place a suitable KYC/AML reliance agreement with us then please contact us.

    The WiseAlpha API is REST-based and returns responses in JSON.

    Our API is currently in beta, but please contact us if you're interested in learning more and getting early access to an API key. Until V1 is released we will be adding functionality with potentially breaking changes. All changes will be documented in the versioning section.

    We have usage examples in cURL and Python. You can view code examples in the area to the right, and you can switch between shell (i.e., using bash, cURL and jq) and Python.

    The root URL for all requests to the WiseAlpha production system is https://api.wisealpha.com/v1/. The production system will not be available until V1 is fully released, but a sandbox version is available at https://api-sandbox.wisealpha.com/v1/.

    General

    We publish a Corporate Bond Investment Glossary which is useful if you're unfamiliar with some of the terms used in this documentation.

    Authentication

    Token based authentication

    To authorize, use this code:

    import requests
    
    headers = {'Authorization': 'Token $API_KEY'}
    
    api = requests.get('$API_ROOT_URL/api_endpoint_here', headers=headers)
    
    # With shell, you can just pass the correct header with each request
    curl "$API_ROOT_URL/api_endpoint_here"
      -H "Authorization: Token $API_KEY"
    

    Make sure to replace $API_KEY with your API key.

    WiseAlpha uses API keys to allow access to the API. Access is limited to accounts that have been created by the account accessing the API. If you want to make API calls on behalf of another user see OAuth.

    WiseAlpha expects for the API key to be included in all API requests to the server in a header that looks like the following:

    Authorization: Token $API_KEY

    In the code examples, we use the string $API_KEY as a substitute for your API key.

    OAuth 2.0

    WiseAlpha also supports an OAuth 2.0 flow in order to make calls on behalf of a user. In order to do this you will need to set-up an application in the developer portal. Refer to the OAuth section for more information.

    Expansion

    Some endpoints will detail an Available Expansions section. This will detail what items maybe be optionally returned by the endpoint. To use an expansion include expand=expansion_name in the query string you send to the endpoint. Some endpoints may include multi-level expansions. Nest expansions are of the form expand=parent__child

    Field Exclusion

    Some endpoints allow field exclusion, this is done through providing the query string exclude=field_name. Nested exclusions are also supported and can be used like exclude=field__child_field

    Field Inclusion

    Some endpoints allow field inclusion, this is done through providing the query string only=field_name. Nested inclusions are also supported and can be used like only=field__child_field. All non-included fields will be excluded.

    Pagination

    api = requests.get('$API_ROOT_URL/customers/',
                       params={'offset': 5, 'limit': 5},
                       headers=headers)
    
    curl -s "$API_ROOT_URL/customers/?offset=5&limit=5" \
         -H 'Authorization: Token $API_KEY' | jq .
    

    Returns the following JSON pagination object:

    {
      "count":20,
      "next":"$API_ROOT_URL/customers/?limit=5&offset=10",
      "previous":"$API_ROOT_URL/customers/?limit=5",
      "results":[
        {
          "customer_id":"10000001",
          "email":"user5@wisealpha.com",
          ...
        }
        ...
      ]
    }
    

    For most lists of objects, you can limit the number of results returned via parameters to the GET request.

    So a request to $API_ROOT_URL/customers/?offset=5&limit=5 will return the second page of five senior secured bonds.

    Any request to a list resource returns a pagination object with the following fields:

    Name Description Type
    count Total number of results available Integer
    next Resource URL for the subsequent page of results String
    previous Resource URL for the previous page of results String
    results Results array Array

    If no limit is supplied, then the limit defaults to 100.

    Data types

    Throughout the API, in requests and responses, the WiseAlpha API uses the following basic data types.

    Data Type Description
    Integer An integer number, represented by the native JSON number type.
    Decimal A decimal number represented as a JSON string, e.g. "100.55". All money amounts are represented in this way.
    Float A decimal number represented as a JSON number, e.g. 1.123456789. This type is used when precision is important.
    Boolean A value of true/false represented by the native JSON Boolean type.
    String A text string
    DateTime An ISO 8601 DateTime string, e.g. "2015-01-01T00:00:00+00:00"
    Date An ISO 8601 calendar date, e.g., "2015-01-01"
    Array A collection of items
    Currency A string containing an ISO 4217 currency code
    Customer ID User accounts are identified using 8-digit integers, zero padded and encoded in a String. E.g., 10000001.
    In requests, you can use the special value me to target the user account associated with the API key.
    Reference ID Other objects are identified by a reference string, consisting of a type tag, and a zero-padded ID number. E.g., EVENT00000099
    Country Code An ISO 3166-1 alpha-2 country code e.g. 'gb'
    Limited Html String For some product descriptions we return a limited set of HTML. The HTML returned will be valid XHTML and be limited to the tags ['a', 'ul', 'li', 'p', 'div'] and the attributes ['href', 'alt'].
    Markdown String Markdown string

    Pricing

    The products on WiseAlpha are bought and sold at a price that's a percentage of par. So a price of 100 indicates that a £1 investment will buy £1 of the product. A price of 90 indicates that a £1 investment will buy £1.11 of the product. A price of 110 indicates that a £1 investment will buy £0.90 of the product.

    Rate limiting

    Currently the only active rate limiting is triggered by failed authentication requests. All other endpoints do not have a rate limit. WiseAlpha reserves the right to impose a rate limit on requests at a later date.

    Testing

    We provide a sandbox server that you can use to test out creating users, purchasing investments and responding to events. Updates to this server do not have real world effects, (and WiseAlpha may occasionally clear out any data contained in this server when re-syncing with the production system). To access the sandbox server, use the URL root https://api-sandbox.wisealpha.com/v1/.

    Versioning

    Non-breaking API changes may be made at any time by the WiseAlpha team. An example of a non-breaking change would be the addition of a field returned by an endpoint, addition of a new endpoint or additional of an optional parameter to an existing endpoint. Non-breaking changes will appear in the API Version log as a minor version number increase and will be documented and dated.

    Breaking API changes will be rolled out under a major version number, will have a new endpoint and will run in parallel with previous versions. In the event of the WiseAlpha team deprecating a previous API release there will be plenty of notice and help to move onto the new endpoints.

    API Version 1.0

    Release 2020-01-15

    Release 2019-10-03:

    Still in beta.

    Responses

    On success we return a suitable HTTP success code

    Success Code Meaning
    200 OK -- The request was successfully processed and/or the requested data returned.
    201 Created -- We created the object as you requested.
    202 Accepted -- The request has been accepted for processing, but the processing has not been completed. The request may still fail during offline processing. You will be notified of success/failure via a webhook..

    We spell out the response code for each request in the examples below. If no response code is given, 200 - OK will be returned.

    Errors

    {
        "email": ["Customer with this Email already exists."]
    }
    

    On error, we return a suitable HTTP error code. For many errors, we also return the nature of the error as a JSON fragment as illustrated.

    Error Code Meaning
    400 Bad Request -- The request could not be processed due a client error
    401 Unauthorized -- Your API key could not be validated.
    403 Forbidden -- You tried to execute a request that you do not have rights to, i.e. make a trade on an account you do not have permission to trade on.
    404 Not Found -- The specified resource could not be found.
    405 Method Not Allowed -- You tried to access an endpoint with a method that it does not accept
    406 Not Acceptable -- You requested a format that isn't JSON.
    422 Unprocessable Entity - The request was understood but could not be processed. E.g. there where not sufficient funds available to complete a market order.
    500 Internal Server Error -- There was an unexpected server side problem.
    503 Service Unavailable -- We're temporarily offline for maintenance. Please try again later.

    OAuth

    In order to create and configure an OAuth application you will need a WiseAlpha account configured with access to the developer portal, contact our partners team if you're interested.

    The root URL for all OAuth requests to the WiseAlpha production system is https://www.wisealpha.com/o/. The production system will not be available until V1 is fully released, but a sandbox version is available at https://sandbox.wisealpha.com/o/. This URL might change before the production system is launched.

    Creating an app

    Once you can access the developer portal you will be able to create a new application. When creating the application you will need to provide:

    You will be provided with a client_id and client_secret which can be modified at creation time. Apps created on the sandbox environment cannot be moved to the production environment so you'll need to create a production app when you're ready to go live.

    When creating or editing your application you will see the below fields.

    Name Description
    Name The application name - users will see this when authorizing your application.
    client_id This publically identifies your application.
    client_secret This is your application's secret.
    client_type Either public or confidential depending on if the credentials retrieved can be stored in a secure way.
    authorization_grant_type Either authorization_code or implicit. Only authorization_code should be used for production applications - see the aside below
    redirect_uris The set of URIs that the server will return the browser to after the user grants or denies the application's request for access.

    Scopes

    In order to request a specific set of scopes when redirecting to the authorization URL, include the scope parameter with a space separated list of the below scopes. If this is not included, all scopes will be requested.

    Name Description
    read_investments Grants read access to the user's investment portfolio
    read_profile Grants read access to the user's profile
    write_profile Grants write access to the user's profile
    trade Grants access to trade
    fund Grants access to issue deposit and withdrawal requests
    create_account Grants access to create new investment accounts

    OAuth 2.0 Authorization code flow

    WiseAlpha supports a standard OAuth 2.0 Authorization code grant flow, at it's heart it's very simple:

    /authorize/

    api = requests.get('$OAUTH_ROOT_URL/authorize/?response_type=code&client_id=ZOknOs0kO02ZyUA8Z6eBUL3cJNip2pRUE0Oi6P71&redirect_uri=https%3A%2F%2Fwww.example.com%2Fauthorize&state=zxx5LbYXdbkbRhfUXCHz2SISHkUgMR&scope=read')
    
    curl -s "$OAUTH_ROOT_URL/authorize/?response_type=code&client_id=ZOknOs0kO02ZyUA8Z6eBUL3cJNip2pRUE0Oi6P71&redirect_uri=https%3A%2F%2Fwww.example.com%2Fauthorize&state=zxx5LbYXdbkbRhfUXCHz2SISHkUgMR&scope=read" \
         | jq .
    

    Will return the user to the redirect URL indicating if they have or have not accepted the request for access

    The user will see a screen like this:

    The page displayed to grant access to an application

    Once the user has granted or denied access to your application their browser will be redirected back to the provided redirect URI.

    /token/

    The token endpoint can be used to swap an authorization code for an access/refresh token as well as to using a refresh token to get a new access token.

    Exchange Authorization Code

    Available Methods:

    Name Description Data Type
    grant_type authorization_code String
    code An authorization code returned by the authorize endpoint. String
    client_id Your application's client_id. String
    client_secret Your application's client_secrent. String

    Response:

    Name Description Data Type
    access_token An access token. String
    token_type Bearer String
    expires_in The seconds until token expiry. Integer
    refresh_token A refresh token. String
    scope The scopes the access token gives access to. String

    Refresh Token

    Available Methods:

    Name Description Data Type
    grant_type refresh_token String
    refresh_token A refresh token. String
    client_id Your application's client_id. String
    client_secret Your application's client_secrent. String

    Response:

    Name Description Data Type
    access_token An access token. String
    token_type Bearer String
    expires_in The seconds until token expiry. Integer
    refresh_token A refresh token. String
    scope The scopes the access token gives access to. String

    Products

    Displaying WiseAlpha market products

    The product endpoints contain all the information needed to create a marketplace for WiseAlpha products. WiseAlpha products fit into a number of marketplaces:

    Product Data Types

    We use the following data types in the product endpoints:

    Product object

    Name Description Data Type
    product_id Product id String
    state The state of the product, valid states are open, closed, suspended, repaid, defaulted or exchanged String-Enum
    market_type The WiseAlpha marketplace that the product appears in main_market, high_yield, perpetuals, special_situations String-Enum
    investment_type bond String-Enum
    asset_security One of not_specified, senior_secured, senior_unsecured, unsecured, unsecured_lt2 or at1 String-Enum
    asset_security_label A human readable form of the asset security field. String
    isin_code International Securities Identification Number String
    currency Currency String
    buy_price The current market buy price Decimal
    sell_price The current market sell price Decimal
    maturity The maturity of the bond Date
    sell_liquidity The amount of current liquidity in the WiseAlpha marketplace for this product Decimal
    pending_liquidity The amount of liquidity that will soon be injected in the WiseAlpha marketplace for this product Array of Pending Liquidity objects
    interest_period The interest period String
    next_interest_payment The next interest payment date Date
    coupon The annual interest rate paid Decimal
    coupon_string A human readable description of the coupon. (Libor/fixed/etc) String
    call_schedule The products call schedule, e.g.: [{"date": "2019-09-15", "price": "102.75"}, {"date": "2020-09-15", "price": "101.375"}, {"date": "2021-09-15", "price": "100.00"}] Array of Call Option objects
    yield_to_maturity The current yield if bought at the market price and held to maturity. Decimal
    current_yield The current yield, ignoring buy price. Decimal
    rating_moodys The Moody's rating String or null, e.g. B3
    rating_fitch The Fitch rating String or null, e.g. BBB
    rating_sandp The S&P rating String or null, e.g. B+
    accrued_interest_rate The amount of interest accrued per unit invested, e.g. 1p interest accrued for every £1 invested Float
    company Company details Company object
    cashflows Cashflow details, optionally returned with the cashflows expansion Cashflow object
    zero_interest_fees Is this product a zero fee product? Boolean
    product_url The URL for this product on the WiseAlpha website String
    total_invested Returns the total invested in this product. Decimal
    user_invested Not included unless specified in an expand, this will return the aggregate amount the calling user holds in the product across all their investment accounts. Decimal

    Company object

    Name Description Data Type
    company_id Company id String
    company_name The name of the company String
    industry The industry that the company operates in Industry object
    stock_symbol A unique reference to a companies stock. Available for publicly listed companies only String
    description A description of the company's undertakings Limited Html String
    borrower_status One of performing or non-performing String-Enum
    website The company's website String
    formation_date The company's formation date String
    country_of_origin The country of origin of the company String
    ownership_status A description of the current ownership status - e.g. private held, publicly traded, etc String
    senior_debt The percentage of the companies capital structure as senior debt String
    junior_debt The percentage of the companies capital structure as junior debt String
    equity The percentage of the companies capital structure as equity String
    tile_description A short description of the company String
    tile_image An image that can be used in a product list String
    logo A logo that can be used in a product list String
    capital_structure A breakdown of the company's capital structure, optionally returned with the company__captital_structure expansion Array of Capital Structure objects
    important_updates Important updates on the company, optionally returned with the company__important_updates expansion Array of Note objects

    Industry object

    Name Description Data Type
    key Identifier for the industry String
    name The name of the industry String

    Capital Structure object

    Name Description Data Type
    capital_type String
    amount Decimal
    currency String
    ebitda Decimal
    ebitda_interest Decimal
    capitalisation Decimal
    maturity Date
    margin String
    footnote String
    is_important Boolean
    is_total Boolean

    Note object

    Name Description Data Type
    datestamp DateTime
    note_html String

    Cashflow object

    Name Description Data Type
    date The date the cashflow occurs on. Date
    coupon_rate The coupon rate of the cashflow. Decimal
    coupon_amount The amount to multiple held principal by to get the predicted coupon payment for a fractional bond. Decimal
    principal_amount The amount to multiple held principal by to get the predicted principal payment for a fractional bond. Decimal
    total_amount The amount to multiple held principal by to get the predicted total cashflow payment for a fractional bond. Decimal

    Call Option object

    Name Description Data Type
    date The date the call option begins. If set to 'any', the product can be called at any time Date or String
    price The price at which the borrower can call at. Decimal

    Pending Liquidity object

    Name Description Data Type
    settlement_date The date on which the liquidity will be injected into the marketplace Date
    pending_amount The amount of liquidity that will be injected into the marketplace Decimal

    /products/

    import requests
    
    headers = {'Authorization': 'Token $API_KEY'}
    
    api = requests.get('$API_ROOT_URL/products/?expand=cashflows', headers=headers)
    
    curl "$API_ROOT_URL/products/?expand=cashflows"
      -H "Authorization: Token $API_KEY" | jq .
    

    The above command returns pagination object containing a list of product objects:

    {
        "count": 1,
        "next": null,
        "previous": null,
        "results": [
            {
                "product_id": "INVMKT00000001",
                "state": "open",
                "market_type": "main_market",
                "investment_type": "bond",
                "asset_security": "Senior Secured",
                "isin_code": "XS1577956516",
                "currency": "GBP",
                "buy_price": "101.5000",
                "sell_price": "101.5000",
                "maturity": "2022-08-01",
                "sell_liquidity": "0.00",
                "pending_liquidity": [
                    {
                      "settlement_date": "2018-01-01",
                      "pending_amount": "100000.00"
                    }
                ],
                "interest_period": "6m",
                "next_interest_payment": "2018-02-01",
                "coupon": "5.0000",
                "call_schedule": [
                    {
                        "date": "2019-09-01",
                        "price": "102.50"
                    },
                    {
                        "date": "2020-09-01",
                        "price": "101.25"
                    },
                    {
                        "date": "2021-09-01",
                        "price": "100.00"
                    }
                ],
                "yield_to_maturity": "4.7",
                "current_yield": "4.9",
                "rating_moodys": "B+",
                "rating_fitch": "A-",
                "rating_sandp": null,
                "company": {
                    "company_id": "CO00000001",
                    "company_name": "McLaren",
                    "stock_symbol": "",
                    "description": "McLaren Technology Group is globally renowned as one of the world’s most illustrious high-technology brands. Since its foundation in 1963, McLaren has been pioneering and innovating in the competitive world of Formula 1, forging a formidable reputation which has seen the racing team win 20 World Championships and over 180 races.\r\n\r\nThe Group has built on its successful racing expertise and diversified to include a global, high-performance sports car business, McLaren Automotive, and a game-changing technology and innovation business, McLaren Applied Technologies.",
                    "website": "http://www.mclaren.com/",
                    "formation_date": "1963",
                    "country_of_origin": "UK",
                    "ownership_status": "Private",
                    "image": "https://d1x9604lsph6r7.cloudfront.net/media/cache/cd/24/cd243f12c0c6f5e7c999b46559d63af4.png",
                    "senior_debt": 19,
                    "junior_debt": 0,
                    "equity": 81,
                    "tile_description": "McLaren Technology Group is globally renowned as one of the world’s most illustrious high-technology brands.",
                    "tile_image": "https://d1x9604lsph6r7.cloudfront.net/media/cache/cd/24/cd243f12c0c6f5e7c999b46559d63af4.png",
                    "logo": "https://d1x9604lsph6r7.cloudfront.net/media/cache/25/71/25716d08c1c625febfae715e952258a8.png",
                    "industry": {
                        "key": "automotive",
                        "name": "Automotive"
                    }
                },
                "cashflows": {
                    {
                        "date": "2018-02-01",
                        "coupon_rate": "0.0500",
                        "coupon_amount": "0.0265",
                        "principal_amount": "0.0000",
                        "total_amount": "0.0265"
                    },
                    ...
                    {
                        "date": "2022-08-01",
                        "coupon_rate": "0.0500",
                        "coupon_amount": "0.0250",
                        "principal_amount": "1.0000",
                        "total_amount": "1.0250"
                    }
                }
            }
        ]
    }
    

    This endpoint retrieves a list of the products available through the WiseAlpha market place. This endpoint supports inclusions and exclusions.

    Available Methods

    Optional Query Strings for GET

    Name Description Data Type
    market_type Filter to return only products of a certain type. Valid values are main_market, high_yield, perpetuals and special_situations String-Enum
    isin Search the endpoint based on the ISIN code. Matches will be returned based on the the product ISIN code starting with the provided filter value. String

    Available Expansions

    Name Description
    cashflows Return the cashflows for the product.
    company__important_updates Return important updates for the product's company.
    company__capital_structure _Return the company capital structure.

    /products/{product_id}/

    import requests
    
    headers = {'Authorization': 'Token $API_KEY'}
    
    api = requests.get('$API_ROOT_URL/products/1/', headers=headers)
    
    curl "$API_ROOT_URL/products/1/"
      -H "Authorization: Token $API_KEY" | jq .
    

    The above command returns JSON structured like this:

    {
        "product_id": "INVMKT00000001",
        "state": "open",
        "market_type": "main_market",
        "investment_type": "bond",
        "asset_security": "Senior Secured",
        "isin_code": "XS1577956516",
        "currency": "GBP",
        "buy_price": "101.5000",
        "sell_price": "101.5000",
        "maturity": "2022-08-01",
        "sell_liquidity": "0.00",
        "pending_liquidity": [
            {
              "settlement_date": "2018-01-01",
              "pending_amount": "100000.00"
            }
        ],
        "interest_period": "6m",
        "next_interest_payment": "2018-02-01",
        "coupon": "5.0000",
        "call_schedule": [
            {
                "date": "2019-09-01",
                "price": "102.50"
            },
            {
                "date": "2020-09-01",
                "price": "101.25"
            },
            {
                "date": "2021-09-01",
                "price": "100.00"
            }
        ],
        "yield_to_maturity": "4.7",
        "current_yield": "4.9",
        "rating_moodys": "B+",
        "rating_fitch": "A-",
        "rating_sandp": null,
        "company": {
            "company_id": "CO00000001",
            "company_name": "McLaren",
            "stock_symbol": "",
            "description": "McLaren Technology Group is globally renowned as one of the world’s most illustrious high-technology brands. Since its foundation in 1963, McLaren has been pioneering and innovating in the competitive world of Formula 1, forging a formidable reputation which has seen the racing team win 20 World Championships and over 180 races.\r\n\r\nThe Group has built on its successful racing expertise and diversified to include a global, high-performance sports car business, McLaren Automotive, and a game-changing technology and innovation business, McLaren Applied Technologies.",
            "website": "http://www.mclaren.com/",
            "formation_date": "1963",
            "country_of_origin": "UK",
            "ownership_status": "Private",
            "image": "https://d1x9604lsph6r7.cloudfront.net/media/cache/cd/24/cd243f12c0c6f5e7c999b46559d63af4.png",
            "senior_debt": 19,
            "junior_debt": 0,
            "equity": 81,
            "tile_description": "McLaren Technology Group is globally renowned as one of the world’s most illustrious high-technology brands.",
            "tile_image": "https://d1x9604lsph6r7.cloudfront.net/media/cache/cd/24/cd243f12c0c6f5e7c999b46559d63af4.png",
            "logo": "https://d1x9604lsph6r7.cloudfront.net/media/cache/25/71/25716d08c1c625febfae715e952258a8.png",
            "industry": {
                "key": "automotive",
                "name": "Automotive"
            }
            "
        }
    }
    

    This endpoint retrieves detailed information about a market product in WiseAlpha. While the list endpoint will only return products currently investible in the WiseAlpha marketplace, the detail endpoint will return products that have since closed (e.g. a bond which has been repaid).

    Available Methods

    Available Expansions

    Name Description
    cashflows Return the cashflows for the product.
    company__important_updates Return important updates for the product's company.
    company__capital_structure _Return the company capital structure.

    /products/describe_types/

    import requests
    
    headers = {'Authorization': 'Token $API_KEY'}
    
    api = requests.get('$API_ROOT_URL/products/describe_types/', headers=headers)
    
    curl "$API_ROOT_URL/products/describe_types/"
      -H "Authorization: Token $API_KEY" | jq .
    

    The above command returns a pagination object containing a list of investment type objects:

    {
      "count": 6,
      "next": null,
      "previous": null,
      "results": [
        {
            "market_type": "main_market",
            "name": "Senior Secured",
            "category": "investment",
            "description": "A corporate takes out a bond from a bank and this bond is then syndicated amongst a group of lenders.",
            "resource_url": "https://api.wisealpha.com/v1/products/?market_type=main_market"
        },
        {
            "market_type": "high_yield",
            "name": "High Yield",
            "category": "investment",
            "description": "High yield bonds ...",
            "resource_url": "https://api.wisealpha.com/v1/products/?market_type=high_yield"
        },
        ...
      ]
    }
    

    This endpoint retrieves all product types currently available through WiseAlpha.

    Available Methods

    Product Type Description Resource

    Name Description Data Type
    results[ ].market_type Product identifier String
    results[ ].name Product display name String
    results[ ].category Product category String
    results[ ].description A plain English description of the product String
    results[ ].resource_url Product resource URL String

    Companies

    Company Update Data Types

    We use the following data types in the company update endpoints:

    Company Update Source

    {
        "id": 1136,
        "name": "lse-gb",
        "description": "London Stock Exchange",
        "url": "https://www.londonstockexchange.com/",
        "image": "https://docs.londonstockexchange.com/sites/default/files/logo.svg"
    }
    
    Name Description Data Type
    id Company Update Source ID Reference ID
    name Source name String
    description short description about the source String
    url URL String
    image Image URL String

    Company Update Object

    {
        "id": 25079,
        "source": {
            "id": 1136,
            "name": "lse-gb",
            "description": "London Stock Exchange",
            "url": "https://www.londonstockexchange.com/",
            "image": "https://docs.londonstockexchange.com/sites/default/files/logo.svg"
        },
        "title": "AA 2021Q2 financials updated",
        "description": "Please find the newest AA financials here: [https://aggredium.com/company/AABOND/standardized/?data\\_view=ltm'](https://aggredium.com/company/AABOND/standardized/?data_view=ltm')\n\n      ",
        "published_time": "2020-09-29T11:15:44Z",
        "url": "https://aggredium.com/company/AABOND/standardized/?data_view=ltm'",
        "provider": "AGGREDIUM",
        "type": "COMPANY_NEWS",
        "image": null,
        "category": "financials update",
        "priority": "LOW"
    }
    
    Name Description Data Type
    id Company Update ID Reference ID
    source Update source Company Update Source
    title Title of the update String
    description Description of the update Markdown String
    published_time Datetime when the update was published. DateTime
    url URL to the original update String
    provider Name of the (meta data) provider (e.g. CITY_FALCON, AGGREDIUM, WISEALPHA) String-Enum
    type Type of update (e.g. COMPANY_NEWS, PRESS) String-Enum
    image Image URL String
    category Category of the update String
    priority Priority level assigned to the update (e.g. LOW, MEDIUM, HIGH) String-Enum

    Get list of company updates

    URL: GET /companies/{}/company-updates/

    Example GET request

    api = requests.get('$API_ROOT_URL/companies/CO00000001/company-updates/limit=2&offset=10', headers=headers)
    
    curl -s "$API_ROOT_URL/companies/CO00000001/company-updates/limit=2&offset=10" \
    -H 'Authorization: Token $API_KEY' | jq .
    

    The above command returns JSON structured like this:

    {
        "count": 20,
        "next": "https://api.wisealpha.com/pubapi/v1/companies/CO00000019/company-updates/?limit=2&offset=12",
        "previous": "https://api.wisealpha.com/pubapi/v1/companies/CO00000019/company-updates/?limit=2&offset=8",
        "results": [
            {
                "id": 23766,
                "source": {
                    "id": 1136,
                    "name": "lse-gb",
                    "description": "London Stock Exchange",
                    "url": "https://www.londonstockexchange.com/",
                    "image": "https://docs.londonstockexchange.com/sites/default/files/logo.svg"
                },
                "title": "Albert Bridge Cap Form 8.3 AA Plc",
                "description": "RNS Number : 9332Y Albert Bridge Capital LLP 14 September 2020 FORM 8.3 PUBLIC OPENING POSITION DISCLOSURE/DEALING DISCLOSURE BY A PERSON WITH INTERESTS IN RELEVANT SECURITIES REPRESENTING 1% OR MORE Rule 8.3 of the Takeover Code (the \"Code\") 1. ...",
                "published_time": "2020-09-14T13:04:00Z",
                "url": "https://cityfalcon.com/directory/filings/GB/lse-gb/121999940-aa-plc-albert-bridge-cap-form-83-aa-plc",
                "provider": "CITY_FALCON",
                "type": "COMPANY_NEWS",
                "image": "https://cityfalconproduction.blob.core.windows.net/autotweetmedia/domains/logos/79/small.png",
                "category": "major_publication",
                "priority":  "LOW"
            },
            ...
        ]
    }
    

    This endpoint retrieves a list of company updates linked to the current company. Results are arranged in reverse chronological order.

    Optional Query Strings for GET

    Name Description Data Type
    limit limit the number of results Integer
    offset offset Integer
    provider Name of the (meta data) provider (e.g. CITY_FALCON, AGGREDIUM, WISEALPHA) String-Enum
    type Type of update (e.g. COMPANY_NEWS, PRESS) String-Enum
    priority Priority level assigned to the update (e.g. LOW, MEDIUM, HIGH) String-Enum

    Customer Profiles

    These endpoints are used to fetch and update the personal information for WiseAlpha users.

    If you have a super account, you can use these endpoints to create managed WiseAlpha users, and progress them through the account onboarding process.

    You can also use these endpoints if you are not a super account. In this case, setting customer_id to me in the endpoints targets the user account associated with the API key. The list and create endpoints are only available to super accounts.

    You can find more details of the information we gather and how it is used in the onboarding section of this document.

    Customer Profile Data Types

    We use the following data types in the profile endpoints:

    Profile object

    We return this object when details of a WiseAlpha user are requested. It is also used when creating and updating user information, and subsets of this object are used in the PATCH method of the /customers/{customer_id}/ endpoint.

    {
       "customer_id":"10000001",
       "email":"user1@example.com",
       "title":"mr",
       "first_name":"FirstName",
       "last_name":"LastName",
       "contact_number":null,
       "nationality":"GB",
       "date_of_birth":null,
       "date_joined":"2017-11-23T11:17:05.488037Z",
       "address":null,
       "previous_addresses":[],
       "bank_details":{
          "GBP":{
             "provided":false,
             "last_error":""
          },
          "EUR":{
             "provided":false,
             "last_error":""
          }
       },
       "investor_type":null,
       "user_agreement": {
          "client-account-migration": {
             "reference": "client-account-migration",
             "agreement": "$API_ROOT_URL/customers/me/user-agreements/client-account-migration/",
             "choices": [
                {
                  "reference": "move_funds",
                  "text": "Move Funds To Client Account"
                },
                {
                  "reference": "withdraw_funds",
                  "text": "Withdraw Funds"
                }
             ],
             "decision": ""
          }
       },
       "tos_acceptance":{},
       "ifisa_agreement_acceptance": null,
       "validation":{
          "status":"onboarding",
          "can_withdraw":false,
          "can_invest_high_yield":false,
          "can_invest_perpetuals":false,
          "can_invest_special_situations":false,
          "next_actions":[
             "provide-missing-fields",
             "select-investor-type"
          ],
          "can_invest":false,
          "aml_check":{
             "status":"No Check Performed",
             "passed":false
          },
          "fields_needed":[
             "nationality",
             "date_of_birth",
             "contact_number",
             "address",
             "bank_details",
             "tos_acceptance",
             "tax_residencies",
             "user_agreement:client-account-migration"
          ],
          "documents":{
             "proof_of_address":"not-yet-needed",
             "photo_id":"not-yet-needed"
          },
          "document_info": {},
          "questionnaire":{
             "high-yield": "not-attempted",
             "perpetual": "not-attempted",
             "signup": "not-attempted",
             "smart-interest": "not-attempted",
             "special-situation": "not-attempted"
          }
       }
    }
    
    Name Description Data Type
    customer_id The ID of the account. Customer ID
    email Email of the user associated with the account. String
    title Title of the user associated with the account. String
    first_name First name of the user associated with the account. String
    last_name Last name of the user associated with the account. String
    contact_number User's telephone number - we occasionally need to contact the user for compliance purposes String
    nationality Country code for user's nationality Country Code
    date_of_birth Date of birth of the user Date
    date_joined The date the user joined wisealpha DateTime
    address Current address of the user. Address object
    previous_addresses Previous addresses of the user. You should provide addresses to cover the last 3 years. List of Address objects
    bank_details The user's bank-account details. Payouts are transferred to this account. Bank account object
    tax_residencies The user's current tax residencies. List of Tax residency objects
    investor_type The type of this investor Investor type object (Read Only)
    user_agreements All the legal agreements relating to the user User agreements object
    tos_acceptance Details of when the user accepted the WiseAlpha Terms Of Service TOS object
    ifisa_agreement_acceptance Details of when the user accepted the WiseAlpha IF ISA Agreement TOS object
    validation Details of the user's progress through the Onboarding process Validation object (Read Only)

    The email address field must be unique across the WiseAlpha platform. If you try to create an account with a pre-existing email address, or update the email address to match another account, then the API will return an error.

    customer_id, date_joined, investor_type, and validation are read-only fields, and cannot be updated by users. Investor type is set/updated using the /customers/{customer_id}/change_investor_type/ endpoint.

    bank_details is a special object - you can set its value, but when read it just returns whether the value has been set or not. See the bank account object for details.

    Address object

    This is the data type used for user addresses in the profile object.

    {
        "flat_or_apartment_number":null,
        "house_name":null,
        "house_number":"1",
        "address1":"John Street",
        "address2":null,
        "address3":"London",
        "address4":null,
        "post_code":"N1 1XX",
        "country": "gb",
        "from_date":"2016-01-01",
        "to_date": null
    }
    
    Name Description Data Type
    flat_or_apartment_number Flat number, if residence is a flat See note below
    house_name Name of the house, if it has one See note below
    house_number Number of the house, if it has one See note below
    address1 e.g., Street name String
    address2 Optional String
    address3 Town/City name String
    address4 Optional String
    post_code Post Code/Zip Code String
    country Country Country Code
    from_date The date the user moved to this address Date
    to_date The date the user moved to this address Optional Date

    Note: You must specify at least one of flat_or_apartment_number, house_number, house_name.

    For the address field in the profile object (i.e., the user's current address), the to_date is assumed to be unset, and is ignored.

    Bank account object

    This object contains the user's bank-account details.

    {
        "account_name": "FirstName LastName",
        "sort_code":"00-00-00",
        "account_number":"88668866",
        "country_code": "gb"
    }
    
    Name Description Data Type
    account_name The name of the account owner String
    sort_code The sort code of the bank holding the account String
    account_number The account number String
    country_code The country code Country Code

    When read, the above information is not returned. Instead we return a simplified object

    {
        "provided":true,
        "last_error":""
    }
    
    Name Description Data Type
    provided Whether bank account details have been provided Boolean
    last_error The error returned when you last set the user's bank account String

    Tax residency object

    This object contains details of a tax residency.

    {
       "country": "gb",
       "tax_indentification_number": "QQ123456C"
    }
    
    Name Description Data Type
    country The country of the tax residency Country Code
    tax_identification_number The tax identification number String

    Change investor type object

    Not all fields are mandatory for all investor type - see below for more information.

    Mandatory fields for all investor types

    Name Description Data Type
    investor_type_id The user's investor type id. Integer
    annual_income The user's declared annual income. Decimal
    annual_income_currency The currency of the user's declared annual income. Currency
    net_investible_assets The user's declared net investible assets. Decimal
    net_investible_assets_currency The currency of the user's declared net investible assets Currency

    Certified High Net Worth Investor type validation

    There are no additional fields required for the Certified High Net Worth Investor type, but either the annual_income submitted must be at least GBP100,000 or the net_investible_assets submitted must be at least GBP250,000.

    Professional Investor type validation

    The additional below fields are required for the Professional Investor type.

    Name Description Data Type
    professional_investment_experience A description of the customer's professional investment experience. String

    Advised Investor type validation

    The additional below fields are required for the Advised Investor type.

    Name Description Data Type
    advisor_name The customer's advisors name. String
    advisor_fca_reference_number The customer's advisors FCA reference number. String
    advisor_is_fca_authorised A confirmation that the customers advisor is FCA authorised - this must be true. Boolean

    Sophisticated Investor type validation

    The additional below fields are required for the Self-Certified Sophisticated Investor type and at least one of them must be set to true. They all refer to activities that must have taken part in the prior 6 months.

    Name Description Data Type
    angel The customer has been a member of a business angel network. Boolean
    unlisted The customer has invested in a WiseAlpha product, an unlisted company, P2P, Crowdfunding or a Venture Capital firm. Boolean
    professional The customer has worked professionally in the private equity sector, or the provision of finance for small and medium enterprises. Boolean
    director The customer has been a directory of a company with £1m+ in turnover. Boolean

    Investor type summary object

    This object is read-only. To set the customer's investor type, you need to use the set-investor-type

    {
        "investor_type_id": 1,
        "investor_type_identifier": "Certified High Net Worth Investor",
        "investor_type": "High Net Worth Investor",
        "is_retail_restricted": false,
        "annual_income": "105000",
        "annual_income_currency": "GBP",
        "net_investible_assets": "350000",
        "net_investible_assets_currency": "GBP",
        "professional_investment_experience": null,
        "occupation": "CEO",
        "date_selected": "2017-11-23T14:08:19.107968Z",
    }
    
    Name Description Data Type
    investor_type_id The customer's investor type id Integer
    investor_type_identifier The customer's investor type identifier String
    investor_type The text label describing this user's investor type String
    is_retail_restricted Set true if the user is a retail investor. Retail investors cannot invest in some of the more sophisticated investments Boolean
    annual_income The customer's declared annual income. Decimal
    annual_income_currency The currency of the customer's declared annual income. Currency
    net_investible_assets The customer's declared net investible assets. Decimal
    net_investible_assets_currency The currency of the user's declared net investible assets Currency
    professional_investment_experience The customer's professional investment experience String
    advisor_name The customer's advisors name. String
    advisor_fca_reference_number The customer's advisors FCA reference number. String
    advisor_is_fca_authorised A confirmation that the customers advisor is FCA authorised - this must be true. Boolean
    angel The customer has been a member of a business angel network. Boolean
    unlisted The customer has invested in a WiseAlpha product, an unlisted company, P2P, Crowdfunding or a Venture Capital firm. Boolean
    professional The customer has worked professionally in the private equity sector, or the provision of finance for small and medium enterprises. Boolean
    director The customer has been a directory of a company with £1m+ in turnover. Boolean
    date_selected The date the customer selected their investor type DateTime

    User agreements object

    This object should be written when the customer has accepted the WiseAlpha Terms Of Service. It should consist of a dictionary with the following fields:

    {
       "client-account-migration": {
          "reference": "client-account-migration",
          "agreement": "$API_ROOT_URL/customers/me/user-agreements/client-account-migration/",
          "choices": [
            {
              "reference": "move_funds",
              "text": "Move Funds To Client Account"
            },
            {
              "reference": "withdraw_funds",
              "text": "Withdraw Funds"
            }
          ],
          "decision": ""
       }
    }
    
    Name Description Data Type
    client-account-migration The client account migration agreement User agreement object

    User agreement object

    This is a general form of all user agreements:

    {
      "reference": "agreement-reference-identifier",
      "agreement": "$API_ROOT_URL/customers/me/user-agreements/agreement-markdown-text/",
      "choices": [
        {
          "reference": "choice_1",
          "text": "This is choice #1"
        },
        {
          "reference": "choice_2",
          "text": "This is choice #2"
        }
      ],
      "decision": ""
    }
    
    Name Description Data Type
    reference An identifier used to reference the agreement String
    agreement The URL of the agreement text String
    choices The choices available to the user User agreement choice object
    decision The record of the user's decision String

    User agreement choice object

    This is the general form for choices in user agreements:

    {
      "reference": "choice_1",
      "text": "This is choice #1"
    }
    
    Name Description Data Type
    reference The identifier of the choice. This value must be submitted as the "decision". String
    text Text to display to the user User agreement object

    TOS object

    This object should be written when the customer has accepted the WiseAlpha Terms Of Service. It should consist of a dictionary with the following fields:

    {
       "date":"2017-11-23T11:17:05.488037Z",
       "ip_address": "1.2.3.4"
    }
    
    Name Description Data Type
    date Date the customer accepted the Terms Of Service DateTime
    ip_address IP address of the customer's computer when he accepted the Terms Of Service String

    Validation object

    This records the customer's progress through the onboarding process.

    {
        "status":"onboarding",
        "can_invest": false,
        "can_invest_high_yield": false,
        "can_invest_perpetuals": false,
        "can_invest_special_situations": false,
        "can_withdraw": false,
        "next_actions":[
           "provide-missing-fields",
           "select-investor-type"
        ],
        "fields_needed":[
           "date_of_birth",
           "contact_number",
           "address",
           "bank_details",
           "tos_acceptance"
        ],
        "aml_check":{
           "status":"No Check Performed",
           "passed":false
        },
        "documents":{
           "proof_of_address":"not-yet-needed",
           "photo_id":"not-yet-needed"
        },
        "document_info":{},
        "questionnaire":{
           "high-yield": "not-attempted",
           "perpetual": "not-attempted",
           "signup": "not-attempted",
           "smart-interest": "not-attempted",
           "special-situation": "not-attempted"
        }
    }
    
    Name Description Data Type
    status The status of the onboarding process String
    can_invest Can this user deposit money and buy fractional bonds? Boolean
    can_invest_high_yield Can this user invest in the high yield bonds market? Boolean
    can_invest_perpetuals Can this user invest in the perpetual market? Boolean
    can_invest_special_situations Can this user invest in the special situation market? Boolean
    can_withdraw Can this user withdraw funds Boolean
    next_actions What actions should the user do next List of Strings
    fields_needed If next_actions contains "provide-missing-fields" this list identifies which fields should be provided List of Strings
    aml_check The AML check object
    aml_check.status The status of the AML check. See [onboarding] for details String
    aml_check.passed Whether the AML check has been passed Boolean
    documents List of required documents and their current upload status Map of key-value pairs.
    document_info Extra information (such as reason document was rejected) to help with uploading the correct document Map of key-value pairs.

    The keys for the documents and document_info maps will be one of the known document types: photo_id, proof_of_address, bank_statement:<currency>. For documents other than photo_id and proof_of_address, we will not add an entry in documents unless that document is required.

    The values for the documents map will be one of: not-yet-needed, required, provided, approved, rejected.

    If a document is in the rejected state, then document_info.rejection_reason will contain a description of the rejection reason.

    More details of the meaning of each of these fields can be found in the onboarding section of this document.

    Investor type object

    We return a list of these objects from the investor_types endpoint.

    This information should be displayed to the user when he is selecting his investor type. The title field should be used in the toggle used to select the investor type.

    The intro_title and intro_content fields give a brief overview of what each investor type entails.

    The main_title and main_content outline the terms the user is agreeing to by selecting that investor type.

    Once a user has selected an investor type, the id and title fields are returned in the user's investor type summary object. The indentifier field can be used to map the investor type to it's required fields on submission of a change investor type request.

    More details on the investor-type-selection process can be found in the onboarding section of this document.

    {
       "id":1,
       "identifier": "Certified High Net Worth Investor",
       "title":"High Net Worth Investor",
       "intro_title":" What is a Certified High Net Worth Investor?",
       "intro_content":"<p>Description of this investor type.</p>\r\n",
       "main_title":"Certified High Net Worth Investor Statement",
       "main_content":"<p>What the investor is agreeing to.....</p>"
    }
    
    Name Description Data Type
    id ID of this investor type Integer
    identifier A string identifying this investor type, one of Standard Investor, Self-Certified Sophisticated Investor, Professional Investor, Certified High Net Worth Investor or Advised Investor String-Enum
    title Title/identifying string for this investor type String
    intro_title Page title to use when presenting this investor type String
    intro_content Description of this investor type HTML String
    main_title Header for the investor agreement for this investor type String
    main_content Investor agreement HTML String

    Questionnaire object

    We return this object via the questionnaire endpoint.

    Each question in the questions array represents a single multiple-choice question.

    {
       "type":"signup",
       "help": "help text",
       "questions":[
          {
             "id":1,
             "question":"Question 1?",
             "answers":[
                {
                   "id":3,
                   "answer_text":"Answer 1."
                },
                {
                   "id":1,
                   "answer_text":"Answer 2."
                }
             ],
             "mimetype": "text/plain",
             "question_type": "radio"
          },
          ...
       ],
      "faqs": [
        {
          "title": "What are Senior Secured bonds ?",
          "link": "https://support.wisealpha.com/glossary/senior-secured"
        },
        {
          "title": "What happens when a corporate borrower defaults ?",
          "link": "https://support.wisealpha.com/about-wisealpha/what-happens-if-a-borrower-defaults"
        },
        {
          "title": "How does our secondary market operate ?",
          "link": "https://support.wisealpha.com/glossary/secondary-market"
        },
        {
          "title": "When will I receive Interest Payments ?",
          "link": "https://support.wisealpha.com/payments-and-fees/when-will-i-receive-interest-payments"
        },
        {
          "title": "What is Yield To Maturity ?",
          "link": "https://support.wisealpha.com/glossary/yield-to-maturity"
        },
        {
          "title": "What is Current Yield ?",
          "link": "https://support.wisealpha.com/glossary/current-yield"
        }
      ],
      "user_status": {
        "blocked_message": null,
        "num_failed_attempts": 0,
        "max_num_failed_attempts": 3,
        "num_attempts_remaining": 3,
        "passed": false
      },
      "hash": "680b7d32e5f5b39528b46dd0e4051c41"
    }
    
    Name Description Data Type
    type Questionnaire type String, either signup, high-yield, special-situation or perpetual
    help Help text to display if the user fails to pass the questionnaire. String
    questions Questions to ask List of question objects
    faqs Frequently asked questions relating to this questionnaire List of FAQ objects
    user_status If this questionnaire is being retrieved in the context of a user then returned will be the user's current questionnaire status, null otherwise. A questionnaire user status object.

    Question object

    Name Description Data Type
    id ID of this question Integer
    question The question text String
    mimetype The mimetype of the question text. Can be one of text/plain, text/markdown
    question_type The type of question Can be one of radio, free_text
    answers Answers for this question List of answer objects

    Answer object

    Name Description Data Type
    id ID of this answer Integer
    answer_text Text for this answer String

    FAQ object

    Name Description Data Type
    title FAQ title String
    link FAQ link String

    Questionnaire user status object

    Name Description Data Type
    blocked_message If set, the user has been blocked on the questionnaire. This can be due to an answer having been submitted that needs a compliance action before continuing. String
    num_failed_attempts The number of times the user has attempted and failed this questionnaire. Integer
    max_num_failed_attempts The maximum number of times the user can fail this questionnaire before being blocked, can be null. Integer
    num_attempts_remaining The number of attempts the user had remaining to pass this questionnaire, can be null. Integer
    passed Have they passed this questionnaire? Boolean

    List customers

    URL: POST /customers/

    Example GET request

    api = requests.get('$API_ROOT_URL/customers/', headers=headers)
    
    curl -s "$API_ROOT_URL/customers/" \
         -H 'Authorization: Token $API_KEY' | jq .
    

    The above command returns pagination object containing a list of managed user accounts associated with the current API key. The resulting JSON is structured like this:

    {
      "count": 6,
      "next": null,
      "previous": null,
      "results": [
         {
            "customer_id":"10000001",
            "email":"user1@example.com",
            "title":"mr",
            "first_name":"FirstName",
            "last_name":"LastName",
            "contact_number":"07777777777",
            "nationality":"GB",
            "date_of_birth":"2000-01-01",
            "date_joined":"2017-11-23T11:17:05.488037Z",
            "address":{ address... },
            "previous_addresses":[],
            "bank_details":{
               "provided":true,
               "last_error":""
            },
            "investor_type":null,
            "user_agreement": {},
            "tos_acceptance":{ },
            "ifisa_agreement_acceptance": null,
            "validation":{ validation... }
         }
         ...
      ]
    }
    

    Example POST request

    data = {
        "email": "user@example.com",
        "first_name": "FirstName",
        "last_name": "LastName"
    }
    
    api = requests.post('$API_ROOT_URL/customers/', data=data, headers=headers)
    
    curl -s -X POST $API_ROOT_URL/customers/ \
         -H 'Authorization: Token $API_KEY' \
         -H 'Content-Type: application/json' \
         -d '{"email": "user1@example.com","first_name": "FirstName", "last_name": "LastName"}' | jq .
    

    The above command creates a managed user account and associates it with the current API key. On success, it returns the profile object for the resulting user.

    {
       "customer_id":"10000001",
       "email":"user1@example.com",
       "title":"mr",
       "first_name":"FirstName",
       "last_name":"LastName",
       "contact_number":null,
       "nationality":"GB",
       "date_of_birth":null,
       "date_joined":"2017-11-23T11:17:05.488037Z",
       "address":null,
       "previous_addresses":[],
       "bank_details":{
          "provided":false,
          "last_error":""
       },
       "investor_type":null,
       "user_agreement": {},
       "tos_acceptance":{},
       "ifisa_agreement_acceptance": null,
       "validation":{
          "status":"onboarding",
          "can_withdraw":false,
          "can_invest_high_yield":false,
          "can_invest_perpetuals":false,
          "can_invest_special_situations":false,
          "next_actions":[
             "provide-missing-fields",
             "select-investor-type"
          ],
          "can_invest":false,
          "aml_check":{
             "status":"No Check Performed",
             "passed":false
          },
          "fields_needed":[
             "nationality",
             "date_of_birth",
             "contact_number",
             "address",
             "bank_details",
             "tos_acceptance"
          ],
          "documents":{
             "proof_of_address":"not-yet-needed",
             "photo_id":"not-yet-needed"
          },
          "document_info":{},
          "questionnaire":{
             "high-yield": "not-attempted",
             "perpetual": "not-attempted",
             "signup": "not-attempted",
             "smart-interest": "not-attempted",
             "special-situation": "not-attempted"
          }
       }
    }
    

    This endpoint is used to list and create accounts that have been associated with the API key in use (i.e., "super accounts")

    This endpoint is only available to accounts that have been configured as a Super Account. If ordinary users try to use this method, it will return 403 - Permission Denied.

    Available Methods:

    GET Request

    This endpoint returns a list of all managed users associated with the API key in use. The data is returned as a list of profile object.

    POST Request

    This endpoint creates a new managed user account and associates it with the current API key.

    The email field must be set at this point, but other fields can be set in subsequent PUT or PATCH requests. But note that a user cannot invest until all fields are set and the onboarding process is complete.

    Once an account is created, it is associated with the API key used to create the account. The same key will have the rights to make investment requests on behalf of the account. On initial creation, an account is in an unverified state, there is an onboarding process that must be followed to get an account through to the state where it can be used to make investments.

    Customer profile

    URL: POST /customers/{customer_id}/

    ## GET request
    api = requests.get('$API_ROOT_URL/customers/$CUSTOMER_ID/', headers=headers)
    
    ## PUT request
    data = {
       "customer_id":"10000001",
       "email":"user1@example.com",
       "title":"mr",
       "first_name":"FirstName",
       "last_name":"LastName",
       "contact_number":"07777777777",
       "nationality":"GB",
       "date_of_birth":"2000-01-01",
       "date_joined":"2017-11-23T11:17:05.488037Z",
       "address":{
         "house_number": "1",
         "address1": "Some Street.",
         "address3": "London",
         "post_code": "N1 1XX",
         "from_date":"2016-01-01"
       },
       "previous_addresses":[],
       "bank_details":{
          "GBP": {
             "account_name": "FirstName LastName",
             "sort_code":123456,
             "account_number":12345678,
             "country_code": "gb"
          }
       }
    }
    
    api = requests.put('$API_ROOT_URL/customers/10003074/', data=data, headers=headers)
    
    ## PATCH request
    data = {
       "contact_number":"07777777778",
       "previous_addresses":[
          {
            "house_number": "2",
            "address1": "Some Street.",
            "address3": "London",
            "post_code": "N1 1XX",
            "from_date":"2014-01-01",
            "to_date":"2016-01-01"
          }
       ],
       "tos_acceptance": {
         "date":"2017-11-23T11:17:05.488037Z",
         "ip_address": "1.2.3.4"
       }
    }
    
    api = requests.patch('$API_ROOT_URL/customers/10003074/', data=data, headers=headers)
    
    ## GET request
    
    curl -s "$API_ROOT_URL/customers/$CUSTOMER_ID/" \
         -H "Authorization: Token $API_KEY" | jq .
    
    ## PUT request
    
    read -r -d '' DATA << EOM
    {
       "customer_id":"10000001",
       "email":"user1@example.com",
       "title":"mr",
       "first_name":"FirstName",
       "last_name":"LastName",
       "contact_number":"07777777777",
       "nationality":"GB",
       "date_of_birth":"2000-01-01",
       "date_joined":"2017-11-23T11:17:05.488037Z",
       "address":{
         "house_number": "1",
         "address1": "Some Street.",
         "address3": "London",
         "post_code": "N1 1XX",
         "from_date":"2016-01-01"
       },
       "previous_addresses":[],
       "bank_details":{
          "GBP": {
             "account_name": "FirstName LastName",
             "sort_code":123456,
             "account_number":12345678,
             "country_code": "gb"
          }
       }
    }
    EOM
    
    curl -s -X PUT "$API_ROOT_URL/customers/10003074/" \
         -H "Authorization: Token $API_KEY" \
         -H "Content-Type: application/json" \
         -d "$DATA" | jq .
    
    ## PATCH request
    
    read -r -d '' DATA << EOM
    {
       "contact_number":"07777777778",
       "previous_addresses":[
          {
            "house_number": "2",
            "address1": "Some Street.",
            "address3": "London",
            "post_code": "N1 1XX",
            "from_date":"2014-01-01",
            "to_date":"2016-01-01"
          }
       ],
       "tos_acceptance": {
         "date":"2017-11-23T11:17:05.488037Z",
         "ip_address": "1.2.3.4"
       }
    }
    EOM
    
    curl -s -X PATCH "$API_ROOT_URL/customers/10003074/" \
         -H "Authorization: Token $API_KEY" \
         -H "Content-Type: application/json" \
         -d "$DATA" | jq .
    

    On success, the above commands return the profile object:

    {
      "customer_id": "10000001",
      "email": "user1@example.com",
      "title":"mr",
      "first_name": "FirstName",
      "last_name": "LastName",
      "contact_number": "07777777778",
      "nationality": "GB",
      "date_of_birth": "2000-01-01",
      "date_joined": "2017-11-23T11:17:05.488037Z",
      "address": {
        "flat_or_apartment_number": null,
        "house_name": null,
        "house_number": "1",
        "address1": "Some Street.",
        "address2": null,
        "address3": "London",
        "address4": null,
        "post_code": "N1 1XX",
        "from_date": "2016-01-01"
      },
      "previous_addresses": [
        {
          "house_number": "2",
          "address1": "Some Street.",
          "address3": "London",
          "from_date": "2014-01-01",
          "post_code": "N1 1XX",
          "to_date": "2016-01-01"
        }
      ],
      "bank_details": {
        "provided": true,
        "last_error": ""
      },
      "investor_type": {
        "date_selected": "2017-11-23T14:08:19.107968Z",
        "investor_type_id": 1,
        "investor_type": "High Net Worth Investor",
        "net_investible_assets": "500000",
        "net_investible_assets_currency": "GBP",
        "annual_income": "100000",
        "annual_income_currency": "GBP",
        "occupation": "CEO"
      },
      "user_agreement": {},
      "tos_acceptance": {
        "date": "2017-11-23T11:17:05.488037Z",
        "ip_address": "1.2.3.4"
      },
      "ifisa_agreement_acceptance": null,
      "validation": {
        "status": "onboarding",
        "can_withdraw": false,
        "can_invest_high_yield": false,
        "can_invest_perpetuals": false,
        "can_invest_special_situations": false,
        "next_actions": [
          "answer-investor-questionnaire"
        ],
        "can_invest": false,
        "aml_check": {
          "status": "AML Check Pending",
          "passed": false
        },
        "fields_needed": [],
        "documents": {
          "proof_of_address": "not-yet-needed",
          "photo_id": "not-yet-needed"
        },
        "document_info":{},
        "questionnaire":{
          "high-yield": "not-attempted",
          "perpetual": "not-attempted",
          "signup": "not-attempted",
          "smart-interest": "not-attempted",
          "special-situation": "not-attempted"
        }
      }
    }
    

    This endpoint is used to retrieve or update data for the specific account. On success, we return the profile object for that user.

    Trying to access an account that is not associated with this API key will result in a 403 - Permission Denied.

    Available Methods:

    GET requests

    This endpoint retrieves detailed information about an account. Data is returned as a profile object.

    PUT requests

    This method updates the user's details in their entirety.

    PATCH requests

    This method updates specific fields in the user's profile.

    List investor types

    URL: POST /customers/investor_types/

    api = requests.get('$API_ROOT_URL/customers/investor_types/', headers=headers)
    
    curl -s "$API_ROOT_URL/customers/investor_types/" \
         -H "Authorization: Token $API_KEY" | jq .
    

    Returns a list of investor types as the following JSON:

    {
       "investor_types":[
          {
             "id":3,
             "identifier": "Sophisticated Investor",
             "title":"Sophisticated Investor",
             "intro_title":"What is a Sophisticated Investor?",
             "intro_content":"<p>Description of this investor type.</p>\r\n",
             "main_title":"Sophisticated Investor Statement",
             "main_content":"<p>What the investor is agreeing to ...</p>"
          },
          {
             "id":4,
             "identifier": "Certified High Net Worth Investor",
             "title":"High Net Worth Individual",
             "intro_title":"What is a High Net Worth Individual?",
             "intro_content":"<p>Description of this investor type.</p>\r\n",
             "main_title":"High Net Worth Individual Statement",
             "main_content":"<p>What the investor is agreeing to ...</p>"
          },
          {
             "id":5,
             "identifier": "Professional Investor",
             "title":"Investment Professional",
             "intro_title":"What is an Investment Professional?",
             "intro_content":"<p>Description of this investor type.</p>\r\n",
             "main_title":"Investment Professional Statement",
             "main_content":"<p>What the investor is agreeing to ...</p>"
          }
       ]
    }
    

    Available Methods:

    GET request

    This endpoint fetches details of the investor categories

    The investor_types contains a list of investor types. Certain types have more privileges than others, and each type has an associated investor agreement.

    Users must select an investor type, provide the appropriate information for that investor type, and agree to the associated investor agreement. See the onboarding section of this document for details.

    WiseAlpha reserve the right to contact the client to check that the investor type and band are set correctly.

    Change investor type

    URL: POST /customers/{}/change_investor_type/

    data = {
        "investor_type_id": 1,
        "net_investible_assets": "500000",
        "net_investible_assets_currency": "GBP",
        "annual_income": "100000",
        "annual_income_currency": "GBP",
        "occupation": "CEO",
    }
    
    api = requests.post('$API_ROOT_URL/customers/$CUSTOMER_ID/change_investor_type/',
                        data=data, headers=headers)
    
    read -r -d '' DATA << EOM
    {
        "investor_type_id": 1,
        "net_investible_assets": "500000",
        "net_investible_assets_currency": "GBP",
        "annual_income": "100000",
        "annual_income_currency": "GBP",
        "occupation": "CEO"
    }
    EOM
    
    curl -s -X POST "$API_ROOT_URL/customers/$CUSTOMER_ID/change_investor_type/" \
         -H "Authorization: Token $API_KEY" \
         -H "Content-Type: application/json" \
         -d "$DATA" | jq .
    

    If the investor type change request is accepted, we return a 200 or 202 return code with a simple status body:

    {
      "status": "ok"
    }
    

    This endpoint is used to set the user's investor type via submitting a Change investor type object. Setting an investor type also implies the user has read and accepted the investor agreement for this investor type. As such, you should have shown the relevant document to the investor before calling this endpoint.

    WiseAlpha reserves the right to contact the user to discuss whether the selected investor type is appropriate for their circumstances.

    See the Change investor type object documentation for a description of what fields are required for each investor type.

    Get questionnaire

    URL: GET /customers/{customer_id}/questionnaire/

    api = requests.get('$API_ROOT_URL/customers/{customer_id}/questionnaire/',
                       params={'type': '{questionnaire_type}'}, headers=headers)
    
    curl -s "$API_ROOT_URL/customers/{customer_id}/questionnaire/?type={questionnaire_type}" \
         -H "Authorization: Token $API_KEY" | jq .
    

    Returns a questionnaire as the following JSON:

    {
       "type":"signup",
       "help": "help text",
       "questions":[
          {
             "id":1,
             "question":"Question 1?",
             "answers":[
                {
                   "id":3,
                   "answer_text":"Answer 1."
                },
                {
                   "id":1,
                   "answer_text":"Answer 2."
                }
             ],
             "mimetype": "text/plain",
             "question_type": "radio"
          },
          ...
       ],
      "faqs": [
        {
          "title": "What are Senior Secured bonds ?",
          "link": "https://support.wisealpha.com/glossary/senior-secured"
        },
        {
          "title": "What happens when a corporate borrower defaults ?",
          "link": "https://support.wisealpha.com/about-wisealpha/what-happens-if-a-borrower-defaults"
        },
        {
          "title": "How does our secondary market operate ?",
          "link": "https://support.wisealpha.com/glossary/secondary-market"
        },
        {
          "title": "When will I receive Interest Payments ?",
          "link": "https://support.wisealpha.com/payments-and-fees/when-will-i-receive-interest-payments"
        },
        {
          "title": "What is Yield To Maturity ?",
          "link": "https://support.wisealpha.com/glossary/yield-to-maturity"
        },
        {
          "title": "What is Current Yield ?",
          "link": "https://support.wisealpha.com/glossary/current-yield"
        }
      ],
      "user_status": {
        "blocked_message": null,
        "num_failed_attempts": 0,
        "max_num_failed_attempts": 3,
        "num_attempts_remaining": 3,
        "passed": false
      },
      "hash": "680b7d32e5f5b39528b46dd0e4051c41"
    }
    

    This endpoint fetches details of the questionnaires users must answer before accessing WiseAlpha investments. This is used to make sure the investor understands the nature of the investments and the risks involved.

    This endpoint requires a single type parameter that should be set to one of signup, high-yield, special-situation or perpetual. The signup questionnaire must be answered before the user can invest in the platform. The other questionnaires are for access to specific WiseAlpha markets and are explained elsewhere.

    Additionally the user's status for the questionnaire will be returned.

    Returned is a Questionnaire Object

    Submit questionnaire results

    URL: POST /customers/{customer_id}/upload_questionnaire_results/

    data = {
      "type": "signup",
      "questions_answered": [
          {"question_id": 1, "answer_id": 1},
          {"question_id": 2, "answer_id": 6},
          {"question_id": 3, "answer_id": 7},
          {"question_id": 4, "answer_id": 10},
          {"question_id": 5, "answer_id": 15},
          {"question_id": 7, "answer_text": "This is a free text response"}
      ]
    }
    
    api = requests.post('$API_ROOT_URL/customers/$CUSTOMER_ID/upload_questionnaire_results/',
                        data=data, headers=headers)
    
    read -r -d '' DATA << EOM
    {
      "type": "signup",
      "questions_answered": [
          {"question_id": 1, "answer_id": 1},
          {"question_id": 2, "answer_id": 6},
          {"question_id": 3, "answer_id": 7},
          {"question_id": 4, "answer_id": 10},
          {"question_id": 5, "answer_id": 15},
          {"question_id": 7, "answer_text": "This is a free text response"}
      ]
    }
    EOM
    
    curl -s -X POST "$API_ROOT_URL/$CUSTOMER_ID/upload_questionnaire_results/" \
         -H "Authorization: Token $API_KEY" \
         -H "Content-Type: application/json" \
         -d "$DATA" | jq .
    
    

    The questionnaire is returned along with the user status which will indicate pass/fail.

    {
      "type": "signup",
      ...
      "user_status": {
        "blocked_message": null,
        "num_failed_attempts": 0,
        "max_num_failed_attempts": 3,
        "num_attempts_remaining": 3,
        "passed": true
      }
    }
    

    This method is used to upload the user's answers to one of our questionnaires, and check whether the answers are correct. It is not sufficient for the user to answer the questionnaire, they must also answer it correctly. In all cases, the endpoint returns a 200 response, and you should check the response data to see if the questionnaire was answered correctly.

    A Quesitonnaire Object is returned which will include the Questionnaire User Status object indicating pass or fail.

    Document upload

    import requests
    import os
    import mimetypes
    
    photo_id = os.path.join('/../path_to_docs', 'photo_id.jpg')
    with open(photo_id, 'rb') as f:
        headers = {'Authorization': 'Token ' + api_token}
        headers['Content-Type'] = mimetypes.guess_type(photo_id)[0]
        headers['Content-Disposition'] = 'attachment; filename={0}'.format(photo_id)
        result = requests.post('$API_ROOT_URL/customers/$CUSTOMER_ID/upload_photo_id/',
                               data=f, headers=headers)
    
    address_id = os.path.join('/../path_to_docs', 'address_id.jpg')
    with open(address_id, 'rb') as f:
        headers = {'Authorization': 'Token ' + api_token}
        headers['Content-Type'] = mimetypes.guess_type(address_id)[0]
        headers['Content-Disposition'] = 'attachment; filename={0}'.format(address_id)
        result = requests.post('$API_ROOT_URL/customers/$CUSTOMER_ID/upload_proof_of_address/',
                               data=f, headers=headers)
    
    
    # Upload photo ID in file $PHOTO_ID
    curl -s -X POST "$API_ROOT_URL/customers/$CUSTOMER_ID/upload_photo_id/" \
         -H "Authorization: Token $API_KEY" \
         -H "Content-Type: $(file --mime-type -b $PHOTO_ID)" \
         -H "Content-Disposition: attachment; filename=$(basename $PHOTO_ID)" \
         -d $PHOTO_ID | jq .
    
    # Upload proof of address in file $PROOF_OF_ADDRESS using multipart/form-data
    curl -s -X POST "$API_ROOT_URL/customers/$CUSTOMER_ID/upload_proof_of_address/" \
         -H "Authorization: Token $API_KEY" \
         -F "document=@$PROOF_OF_ADDRESS" | jq .
    

    A successful upload returns the following JSON:

    {
      "status": "ok"
    }
    

    When the AML check fails the user will be asked to upload ID documents to confirm their identity. They will not have full access to their account and the WiseAlpha investments until this formality is completed.

    We require 2 proofs of identity:

    Once submitted, these documents are manually verified by the WiseAlpha team, and, if acceptable, the account will be fully enabled. We will issue a webhook event to inform you when the check is complete. If a document is deemed unacceptable, the event will contain a reason for the rejection, the document status will be set to rejected and the reason for the rejection will be added to the document_info section of the validation object. In this case, you should provide a mechanism for the user to upload a replacement for the deficient document.

    From time to time, we may require that the user upload additional documents, e.g., to prove the user owns the destination bank account when making withdrawals. In these circumstances, the ID of the required document will be added to the documents section of the validation object. You can use this endpoint to upload the requested document.

    Available Methods:

    You can upload the document either by posting it directly to the HTTP endpoint with an appropriate Content-Type and Content-Disposition, or by embedding it in a multipart/form-data body type, containing a single part with name document and appropriate Content-Type and Content-Disposition section headers.

    POST requests

    There is one endpoint for each document type we require:

    where <document_type> is one of the known document types: photo_id, proof_of_address, etc.

    Uploaded documents must be in one of the following formats: JPEG, GIF, PNG, PDF or bitmap (BMP).

    /customers/{customer_id}/push-notifications-configuration/

    ## GET request
    api = requests.get('$API_ROOT_URL/customers/{customer_id}/push-notifications-configuration/',
                       params={'type': '{questionnaire_type}'}, headers=headers)
    
    ## PUT request
    data = {
        "configuration": {
            "BOND_LISTINGS:NEW_BOND_AVAILABLE": {
                "ENABLED": "ON",
                "PERIOD": "DAILY"
            }
        }
    }
    api = requests.put('$API_ROOT_URL/customers/{customer_id}/push-notifications-configuration/',
                       data=data, headers=headers)
    
    ## GET request
    curl -s "$API_ROOT_URL/customers/{customer_id}/push-notifications-configuration/" \
         -H "Authorization: Token $API_KEY" | jq .
    
    ## PUT request
    read -r -d '' DATA << EOM
    {
        "configuration": {
            "BOND_LISTINGS:NEW_BOND_AVAILABLE": {
                "ENABLED": "ON",
                "PERIOD": "DAILY"
            }
        }
    }
    EOM
    
    curl -s -X PUT "$API_ROOT_URL/customers/{customer_id}/push-notifications-configuration/" \
         -H "Authorization: Token $API_KEY" \
         -H "Content-Type: application/json" \
         -d "$DATA" | jq .
    

    Returns the customer's push notifications configuration:

    {
        "configuration": {
            "BOND_LISTINGS:NEW_BOND_AVAILABLE": { "ENABLED": "ON" }
        },
        "net_configuration": {
            "BOND_LISTINGS:MORE_OF_BOND_AVAILABLE": { "ENABLED": "OFF" },
            "BOND_LISTINGS:NEW_BOND_AVAILABLE": { "ENABLED": "ON" },
            "TRANSACTIONS_AND_PAYMENTS:BOND_PAYMENTS": { "ENABLED": "OFF" },
            "OTHER:NEWS_AND_UPDATES": { "ENABLED": "OFF", "PERIOD": "WEEKLY" }
        }
    }
    

    Available Methods:

    GET requests

    This endpoint fetches the user's push notifications configuration. Push notifications will be scheduled based on this configuration.

    PUT requests

    This endpoint allows users to edit the push notifications configuration.

    /customers/{customer_id}/email-notifications-configuration/

    ## GET request
    api = requests.get('$API_ROOT_URL/customers/{customer_id}/email-notifications-configuration/',
                       params={'type': '{questionnaire_type}'}, headers=headers)
    
    ## PUT request
    data = {
        "configuration": {
            "BOND_LISTINGS:NEW_BOND_AVAILABLE": {
                "ENABLED": "ON",
                "PERIOD": "DAILY"
            }
        }
    }
    api = requests.put('$API_ROOT_URL/customers/{customer_id}/email-notifications-configuration/',
                       data=data, headers=headers)
    
    ## GET request
    curl -s "$API_ROOT_URL/customers/{customer_id}/email-notifications-configuration/" \
         -H "Authorization: Token $API_KEY" | jq .
    
    ## PUT request
    read -r -d '' DATA << EOM
    {
        "configuration": {
            "BOND_LISTINGS:NEW_BOND_AVAILABLE": {
                "ENABLED": "ON",
                "PERIOD": "DAILY"
            }
        }
    }
    EOM
    
    curl -s -X PUT "$API_ROOT_URL/customers/{customer_id}/email-notifications-configuration/" \
         -H "Authorization: Token $API_KEY" \
         -H "Content-Type: application/json" \
         -d "$DATA" | jq .
    

    Returns the customer's email notifications configuration:

    {
        "configuration": {
            "BOND_LISTINGS:NEW_BOND_AVAILABLE": { "ENABLED": "OFF" }
        },
        "net_configuration": {
            "BOND_LISTINGS:MORE_OF_BOND_AVAILABLE": { "ENABLED": "ON" },
            "BOND_LISTINGS:NEW_BOND_AVAILABLE": { "ENABLED": "OFF" },
            "TRANSACTIONS_AND_PAYMENTS:BOND_PAYMENTS": { "ENABLED": "ON" },
            "OTHER:NEWS_AND_UPDATES": { "ENABLED": "ON", "PERIOD": "WEEKLY" }
        }
    }
    

    Available Methods:

    GET requests

    This endpoint fetches the user's email notifications configuration. email notifications will be scheduled based on this configuration.

    PUT requests

    This endpoint allows users to edit the email notifications configuration.

    Push notification device registration

    URL: POST /customers/{customer_id}/push-notifications/device/

    ## POST request
    data = {
      "deviceId": "DEVICE_ID",
      "name": "Friendly name",
      "registrationId": "..."
    }
    api = requests.post('$API_ROOT_URL/customers/{customer_id}/push-notifications/device/',
                       data=data, headers=headers)
    
    ## POST request
    read -r -d '' DATA << EOM
    {
      "deviceId": "DEVICE_ID",
      "name": "Friendly name",
      "registrationId": "REGIRATION_ID"
    }
    EOM
    
    curl -s -X POST "$API_ROOT_URL/customers/{customer_id}/push-notifications/device/" \
         -H "Authorization: Token $API_KEY" \
         -H "Content-Type: application/json" \
         -d "$DATA" | jq .
    

    Returns:

    HTTP 204 - No Response

    Available Methods:

    Enable/Disable a Push notification device

    URL: PATCH /customers/{customer_id}/push-notifications/device/DEVICE_ID/

    ## PATCH request
    data = {
      "enabled": false,
    }
    api = requests.patch('$API_ROOT_URL/customers/{customer_id}/push-notifications/device/DEVICE_ID/',
                       data=data, headers=headers)
    
    ## PATCH request
    read -r -d '' DATA << EOM
    {
      "enabled": false
    }
    EOM
    
    curl -s -X PATCH "$API_ROOT_URL/customers/{customer_id}/push-notifications/device/DEVICE_ID/" \
         -H "Authorization: Token $API_KEY" \
         -H "Content-Type: application/json" \
         -d "$DATA" | jq .
    

    Returns:

    HTTP 204 - No Response

    Available Methods:

    Get list of company updates for a user

    URL: GET /customers/{customer_id}/company-updates/

    Example GET request

    api = requests.get('$API_ROOT_URL/customers/{customer_id}/company-updates/limit=2&offset=10', headers=headers)
    
    curl -s "$API_ROOT_URL/customers/{customer_id}/company-updates/limit=2&offset=10" \
    -H 'Authorization: Token $API_KEY' | jq .
    

    The above command returns JSON structured like this:

    {
        "count": 31,
        "next": "$API_ROOT_URL/customers/{customer_id}/company-updates/?limit=1&offset=1",
        "previous": null,
        "results": [
            {
                "id": 25079,
                "source": {
                    "id": 1137,
                    "name": "Aggredium",
                    "description": "London Stock Exchange",
                    "url": "https://www.londonstockexchange.com/",
                    "image": "https://docs.londonstockexchange.com/sites/default/files/logo.svg"
                },
                "title": "AA 2021Q2 financials updated",
                "description": "Please find the newest AA financials here: [https://aggredium.com/company/AABOND/standardized/?data\\_view=ltm'](https://aggredium.com/company/AABOND/standardized/?data_view=ltm')\n\n      ",
                "published_time": "2020-09-29T11:15:44Z",
                "url": "https://aggredium.com/company/AABOND/standardized/?data_view=ltm'",
                "provider": "AGGREDIUM",
                "type": "COMPANY_NEWS",
                "image": "https://cityfalconproduction.blob.core.windows.net/autotweetmedia/domains/logos/79/small.png",
                "category": "financials update",
                "priority": "LOW",
                "companies": [
                    {
                        "company_id": "CO00000019",
                        "company_name": "The AA",
                        "industry": "services",
                        "logo": "/media/company/ab55ba40-dd9c-4ecc-8b2a-23ce05c8b124.png"
                    }
                ]
            },
            ...
        ]
    }
    

    This endpoint retrieves a list of company updates linked to the current company. Results are arranged in reverse chronological order.

    Optional Query Strings for GET

    Name Description Data Type
    limit limit the number of results Integer
    offset offset Integer
    provider Name of the (meta data) provider (e.g. CITY_FALCON, AGGREDIUM, WISEALPHA) String-Enum
    type Type of update (e.g. COMPANY_NEWS, PRESS) String-Enum
    priority Priority level assigned to the update (e.g. LOW, MEDIUM, HIGH) String-Enum
    companies Comma separated list of company references String

    Company Updates Subscription

    Get list of user's company updates subscription

    This endpoint fetches the user's company updates subscription. The user will be notified of new company updates based on these subscriptions.

    URL: GET /customers/{customer_id}/company-updates-subscription/

    Example GET request

    api = requests.get('$API_ROOT_URL/customers/{customer_id}/company-updates-subscription/',
                       headers=headers)
    
    curl -s "$API_ROOT_URL/customers/{customer_id}/company-updates-subscription/" \
         -H "Authorization: Token $API_KEY" | jq .
    

    The above command returns JSON structured like this:

    {
        "CO00000099": "unsubscribed",
        "CO00000109": "subscribed",
        "CO00000019": "subscribed"
    }
    

    Update user's company updates subscription

    This endpoint allows users to edit their company updates subscription.

    URL: PATCH /customers/{customer_id}/company-updates-subscription/

    Example PATCH request

    data = {
        "companies": {
            "CO00000001": "subscribed",
            "CO00000002": "unsubscribed",
            "CO00000003": "unsubscribed",
            ...
        }
    }
    
    api = requests.put('$API_ROOT_URL/customers/{customer_id}/company-updates-subscription/', data=data, headers=headers)
    
    read -r -d '' DATA << EOM
    {
        "companies": {
            "CO00000001": "subscribed",
            "CO00000002": "unsubscribed",
            "CO00000003": "unsubscribed",
            ...
        }
    }
    EOM
    
    curl -s -X PATCH "$API_ROOT_URL/customers/{customer_id}/company-updates-subscription/" \
         -H "Authorization: Token $API_KEY" \
         -H "Content-Type: application/json" \
         -d "$DATA" | jq .
    
    

    The above command returns JSON structured like this:

    {
        "CO00000099": "unsubscribed",
        "CO00000109": "subscribed",
        "CO00000019": "subscribed"
    }
    

    Accept/Decline user agreement

    URL: PUT /customers/{}/

    data = {
      "user_agreements": {
        "client-account-migration": {
          "decision": "move_funds"
        }
      }
    }
    api = requests.put('$API_ROOT_URL/customers/{customer_id}/', data=data, headers=headers)
    
    read -r -d '' DATA << EOM
    {
      "user_agreements": {
        "client-account-migration": {
          "decision": "move_funds"
        }
      }
    }
    EOM
    
    curl -s -X PUT "$API_ROOT_URL/customers/{customer_id}/" \
         -H "Authorization: Token $API_KEY" \
         -H "Content-Type: application/json" \
         -d "$DATA" | jq .
    

    Returns the customer profile with decision recorded:

    HTTP 200 - Profile object

    Available Methods:

    User Onboarding

    User's cannot invest in the WiseAlpha platform until they have completed initial validation. The user must:

    Some of this process involves manual review by the WiseAlpha team, or are otherwise done offline. In order to be notified when these offline processes are completed, make sure to register a webhook to be notified when the account status changes.

    The Validation Object

    "validation":{
        "status":"onboarding",
        "can_invest":false,
        "can_invest_high_yield":false,
        "can_invest_perpetuals":false,
        "can_invest_special_situations":false,
        "can_withdraw":false,
        "next_actions":[
           "provide-missing-fields",
           "select-investor-type"
        ],
        "fields_needed":[
           "date_of_birth",
           "contact_number",
           "address",
           "bank_details",
           "tos_acceptance",
           "tax_residencies"
        ],
        "aml_check":{
           "status":"No Check Performed",
           "passed":false
        },
        "documents":{
           "proof_of_address":"not-yet-needed",
           "photo_id":"not-yet-needed"
        },
        "document_info":{},
        "questionnaire":{
          "high-yield": "not-attempted",
          "perpetual": "not-attempted",
          "signup": "not-attempted",
          "smart-interest": "not-attempted",
          "special-situation": "not-attempted"
        }
    }
    

    Whenever you fetch a user's profile object, we return an accompanying validation object.

    Details of the validation object can be found in the validation section. Here, we describe the most important fields in this object, and explain how they can be used to shepherd a user through the Onboarding and AML processes.

    The validation status

    This field indicates the user's progress through the process. It can have one of the following values:

    Name Description
    onboarding We are still waiting for the user to provide personal information
    invest The user has completed the AML process and can invest and withdraw. The ability to invest in specific products may still be limited by specific market access.

    The validation can_xxx fields

    These indicate what actions the user is currently capable of doing.

    If can_invest is true, the user can deposit money in WiseAlpha and purchase fractional bonds.

    If can_invest_high_yield is true, the user can purchase higher-risk fractional bonds on the high-yield marketplace. To enable this, the user must complete the high yield questionnaire.

    If can_invest_perpetuals is true, the user can purchase perpetuals on the perpetual marketplace. To enable this, the user must complete the perpetuals questionnaire and be cleared by a member of the WiseAlpha compliance team.

    If can_invest_special_situations is true, the user can purchase higher-risk fractional bonds on the special situations marketplace. To enable this, the user must complete the special situations questionnaire and be cleared by a member of the WiseAlpha compliance team.

    If can_withdraw is true, the user can withdraw money from his WiseAlpha account. This is sometimes set false even though can_invest is true. There can be a compliance block on the user's account preventing withdrawals.

    The next_actions field

    This field contains a list of next steps you should take to progress the user through the onboarding process. It will contain one or more of the following values:

    Name Description
    provide-missing-fields We are waiting for basic profile information for this user. We list the fields we are still waiting for in the fields_needed field described below.
    select-investor-type The user hasn't selected an investor type.
    answer-signup-questionnaire The user hasn't answered the signup questionnaire.
    upload-id-documents The user needs to upload ID documents before we can progress.
    answer-high-yield-questionnaire The user hasn't answered the high-yield questionnaire. (Note that this isn't a blocking issue - the user may be able to invest in other investments.)
    upload-supporting-document The user needs to upload additional documents (e.g., a bank statement)

    The fields_needed field

    This field contains a list of user attributes that still need to be provided. Each entry in this list should correspond to one of the top-level fields in the user's profile object.

    The aml_check field

    {
       "status":"No Check Performed",
       "passed":false
    }
    

    This field provides the status and result from the automated AML check. The status field contains one of the following values:

    Value Description
    No Check Performed We haven't yet done an automated check.
    AML Check Pending An automated AML check is pending. We'll issue a webhook event when the result is available.
    Auto Check Failed We've done the automated check, and it failed. The user will have to upload ID documents to complete the AML process.
    Auto Check Passed We've done the automated check, and it passed. The AML process is completed and the user is free to invest.
    AML Documents Provided The user has uploaded ID documents and is waiting for WiseAlpha staff to verify them.
    AML Documents Verified The user has uploaded ID documents and they've been verified by WiseAlpha. The AML process is complete and the user is free to invest.

    The passed field indicates whether the user has successfully completed the AML process.

    The documents field

    {
       "proof_of_address":"not-yet-needed",
       "photo_id":"not-yet-needed"
    }
    

    This field is a dictionary whose keys list the documents we require. The documents required for the AML process, namely photo_id and proof_of_address, are always included in this list. From time to time, additional document types may be added, e.g., we may request a bank statement if we cannot automatically associate the user's bank account details with the user's identity.

    For each document, the value in the dictionary indicates whether the document is needed, and if so, whether it has been provided, and accepted. If a document does not appear in the documents list, then it is not yet needed.

    You can upload AML documents at any time, even if they are not currently required. Other documents can only be uploaded when they are required.

    Document state Description
    not-yet-needed We don't need these documents yet.
    required The AML process is blocked until this document is uploaded.
    provided The user has provided API documents, though they may still be awaiting review by WiseAlpha.
    accepted The user's documents have been accepted.
    rejected The user's documents have been rejected, and the rejection reason has been added to the document_info.

    The document_info field

    {
       "proof_of_address": { rejection_reason: "Provided document was too old." }
    }
    

    This field provides some extra information to help the user upload the correct documents, e.g., - The reason the document was requested - What specific documents are required - The reason an uploaded document was rejected

    The field is a dictionary whose keys list the documents where additional information is available. For each key in the list, the value contains a dictionary with one or more of the following subfields:

    subfield Description
    request_reason Any additional information on why this document was requested. For bank statements this will include details of the bank account being verified.
    rejection_reason If the document status is 'rejected', the reason for the rejection will be included here.

    The questionnaire field

    {
      "high-yield": "not-attempted",
      "perpetual": "not-attempted",
      "signup": "not-attempted",
      "smart-interest": "not-attempted",
      "special-situation": "not-attempted"
    }
    

    This field lists the questionnaires that are available on the platform. In order to gain access to a given market, the user must pass the relevant questionnaire. There may be other requirements to access a market so please use the can_xxx fields as the authoritative flags for access to markets.

    Questionnaire state Description
    not-attempted The questionnaire has never been submitted by the user.[^reset-questionnaire-attempts]
    passed The user has attempted the questionnaire and passed it.
    failed The user has attempted the questionnaire and failed it too many times.
    attempted-N-times The user has attempted the questionnaire but failed it N times. They haven't yet exceeded the maximum number of failures.

    [^reset-questionnaire-attempts]: Under some circumstances we may reset the user's attempts.

    In these cases, the questionnaire state will show not-attempted as though they never attempted the questionnaire.

    Providing Information For The Automated AML Check

    ## Get investor types and signup questionnaire
    curl -s $API_ROOT_URL/investor_types/ \
         -H "Authorization: Token $API_KEY" | jq .
    curl -s $API_ROOT_URL/questionnaires/?type=signup \
         -H "Authorization: Token $API_KEY" | jq .
    
    ## Create a user
    read -r -d '' DATA << EOM
    {
       "email": "username@example.com",
       "first_name": "FirstName",
       "last_name": "LastName"
    }
    EOM
    curl -s -X POST "$API_ROOT_URL/customers/" \
         -H "Authorization: Token $API_KEY" \
         -H "Content-Type: application/json" \
         -d "$DATA" > create_result.json
    jq . create_result.json
    
    CUSTOMER_ID=`jq -r .customer_id create_result.json`
    
    ## Add user's personal details using PUT
    read -r -d '' DATA << EOM
    {
       "customer_id":"$CUSTOMER_ID",
       "email":"$USERNAME@example.com",
       "first_name":"FirstName",
       "last_name":"LastName",
       "contact_number":"07777777777",
       "nationality":"GB",
       "date_of_birth":"2000-01-01",
       "date_joined":"2017-11-23T11:17:05.488037Z",
       "address":{
         "house_number": "1",
         "address1": "Some Street.",
         "address3": "London",
         "post_code": "N1 1XX",
         "from_date":"2016-01-01"
       },
       tax_residencies: [{
          "country": "gb",
          "tax_identification_number": "QQ123456C",
       }],
       "previous_addresses":[],
       "bank_details":{
          "GBP": {
             "account_name": "FirstName LastName",
             "sort_code":123456,
             "account_number":12345678,
             "country_code": "gb"
          }
       }
    }
    EOM
    
    curl -s -X PUT "$API_ROOT_URL/customers/$CUSTOMER_ID/" \
         -H "Authorization: Token $API_KEY" \
         -H "Content-Type: application/json" \
         -d "$DATA"  | jq .
    
    ## Set the user's previous_addresses and tos_acceptance using PATCH
    read -r -d '' DATA << EOM
    {
       "previous_addresses":[
          {
            "house_number": "2",
            "address1": "Some Street.",
            "address3": "London",
            "post_code": "N1 1XX",
            "from_date":"2014-01-01",
            "to_date":"2016-01-01"
          }
       ],
       "tos_acceptance": {
         "date":"2017-11-23T11:17:05.488037Z",
         "ip_address": "1.2.3.4"
       }
    }
    EOM
    
    curl -s -X PATCH "$API_ROOT_URL/customers/$CUSTOMER_ID/" \
         -H "Authorization: Token $API_KEY" \
         -H "Content-Type: application/json" \
         -d "$DATA"  | jq .
    
    ## Set investor type
    read -r -d '' DATA << EOM
    {
        "investor_type_id": 1,
        "net_investible_assets": "500000",
        "net_investible_assets_currency": "GBP",
        "annual_income": "100000",
        "annual_income_currency": "GBP",
        "occupation": "CEO"
    }
    EOM
    
    curl -s -X POST "$API_ROOT_URL/customers/$CUSTOMER_ID/change_investor_type/" \
         -H "Authorization: Token $API_KEY" \
         -H "Content-Type: application/json" \
         -d "$DATA"  | jq .
    
    ## Upload signup questionnaire
    read -r -d '' DATA << EOM
    {
      "type": "signup",
      "questions_answered": [
          {"question_id": 1, "answer_id": 1},
          {"question_id": 2, "answer_id": 6},
          {"question_id": 3, "answer_id": 7},
          {"question_id": 4, "answer_id": 10},
          {"question_id": 5, "answer_id": 15},
          {"question_id": 7, "answer_id": 20}
      ]
    }
    EOM
    
    curl -s -X POST "$API_ROOT_URL/customers/$CUSTOMER_ID/upload_questionnaire_results/" \
         -H "Authorization: Token $API_KEY" \
         -H "Content-Type: application/json" \
         -d "$DATA" | jq .
    
    ## Fetch details to check status and next-actions
    curl -s "$API_ROOT_URL/customers/$CUSTOMER_ID/" -H "Authorization: Token $API_KEY" | jq .
    

    Attached is a script that creates a user and provides enough information to initiate the automated AML check process.

    Most of the script is devoted to setting the user's personal details - name, email address, telephone number etc. This should be self-explanatory.

    Selecting an investor type

    Before a customer can invest, it is a regulatory requirement for them to select an investor type and by doing so agree to the investor type agreement. At the same time, the user must give an indication of their net investible assets.

    You can fetch a list of investor types and investible assets bands via the /customers/investor_types/ endpoint.

    Investor types should be presented and agreed to by the customer. Here is a example of how this might look:

    Presenting Investor Types

    Each panel on this page comes from one investor type object. The title field of the object is used to select the investor type, in this case using a 'tabs' interface. Within each panel, the intro_title and intro_content fields contain the title and HTML-encoded text used in the top part of the panel to present a friendly description of the investor type. Similarly, the main_title and main_content contain the actual agreement to be presented in the bottom part of the panel. The investor type content contains dates etc., so should be fetched every time the text is displayed to the user.

    Once the user has selected an investor type and provided any required additional information, and clicked an 'I agree' button, you should submit this information via the change_investor_type endpoint, passing the ID of the investor type and any additional information required.

    After the user has selected an investor type, the value becomes fixed. Subsequent attempts to change the value results in an investor-type change request that is manually processed by WiseAlpha staff. WiseAlpha reserve the right to contact investors to check that their investor type is correct and that their investment strategy is appropriate with consideration of their experience and available assets.

    Answering the questionnaires

    Before the user can invest, they must answer a signup questionnaire to show that they understand the nature of the investments on WiseAlpha, and the risks involved.

    If the investor wants to invest in high yield bonds, then they must answer a second high-yield questionnaire.

    If the investor wants to invest in the perpetual or special situations markets they must answer the special-situation or perpetual respectively. In addition to answering the questionnaire a member of our compliance team will review the market access request and access will only be granted if the application passes compliance.

    You fetch the questionnaire data to display via the questionnaires endpoint. This returns a list of questions and, for each question, a set of possible answers. Each question and answer has a unique ID that is used when submitting the questionnaire responses.

    To display the questionnaire to the user, you can present it as illustrated in the attached screenshot.

    Presenting A Questionnaire

    The questionnaire is fairly short and self-explanatory. The user is free to retry the questionnaire until he answers all questions correctly, however multiple failed attempts will raise a flag and may be investigated by the WiseAlpha team.

    To submit a questionnaire response, use the submit questionnaire endpoint, passing the IDs of each question asked and ID of each answer selected as described. We return a list of questions the user answered correctly. The questionnaire is completed when all questions are correct, if a user fails their questionnaire three times. Speak to the WiseAlpha team if you want to include links to the FAQs in your page.

    Completing The AML Process and Investing In High-Yield Bonds

    ## Upload identity documents
    curl -s -X POST "$API_ROOT_URL/customers/$CUSTOMER_ID/upload_photo_id/" \
         -H "Authorization: Token $API_KEY" \
         -H "Content-Type: $(file --mime-type -b $PHOTO_ID)" \
         -H "Content-Disposition: attachment; filename=$(basename $PHOTO_ID)" \
         -d $PHOTO_ID | jq .
    
    curl -s -X POST "$API_ROOT_URL/customers/$CUSTOMER_ID/upload_proof_of_address/" \
         -H "Authorization: Token $API_KEY" \
         -H "Content-Type: $(file --mime-type -b $PROOF_OF_ADDRESS)" \
         -H "Content-Disposition: attachment; filename=$(basename $PROOF_OF_ADDRESS)" \
         -d $PROOF_OF_ADDRESS | jq .
    
    ## Upload high-yield questionnaire
    read -r -d '' DATA << EOM
    {
      "type": "high-yield",
      "questions_answered": [
          {"question_id": 15, "answer_id": 36},
          {"question_id": 16, "answer_id": 38},
          {"question_id": 17, "answer_id": 40},
          {"question_id": 18, "answer_id": 41},
          {"question_id": 19, "answer_id": 43},
          {"question_id": 20, "answer_id": 45},
          {"question_id": 21, "answer_id": 48}
      ]
    }
    EOM
    
    curl -s -X POST "$API_ROOT_URL/customers/$CUSTOMER_ID/upload_questionnaire_results/" \
         -H "Authorization: Token $API_KEY" \
         -H "Content-Type: application/json" \
         -d "$DATA" | jq .
    
    ## Fetch details to check status and next-actions
    curl -s "$API_ROOT_URL/customers/$CUSTOMER_ID/" -H "Authorization: Token $API_KEY" | jq .
    

    Once the user has completed the onboarding process, this information is checked by an external reference agency. This check will have one of two outcomes:

    Once ID documents are uploaded, the AML check status becomes "AML Documents Provided", and the documents are queued for manual verification. If this succeeds the AML check status is set to "AML Documents Verified", the user's status is set to invest, and the user is free to invest without further restrictions.

    Accounts and Portfolio

    These endpoints return details of the user's balances, owned investments, and historical transactions on the user's account. This information can be used to generate statements, tax and other reports for the user.

    A customer has one of more InvestmentAccounts, all balances and investments belong to one of the customers InvestmentAccounts.

    Account Data Types

    Performance Summary

    Name Description Data Type
    principal The total amount of principal currently held. Decimal
    portfolio_value The estimated value of the products held if sold on the secondary market. This estimate does not include Sale or Cash-out Fees. Decimal
    gains This is the difference between the Portfolio Value and Cost of investments, inclusive of any cash payments and paid fees. Decimal
    sales_fees The total sales fees paid. Decimal
    service_fees The total service fees paid. Decimal
    cash_bonus The total cash bonus earned in the account (e.g. earned through our referral scheme or other promotional offers). Decimal
    interest_accrued The amount of interest that has been earned but not yet paid out. Decimal
    interest_paid The amount of interest that has been paid. This figure is net of paid Service Fees. Decimal
    interest_earned The total amount of interest that has been earned, paid and unpaid. This figure is net of paid Service Fees. Decimal
    interest_paid_gross The amount of interest that has been paid. This figure is prior to paying Service Fees. Decimal
    interest_earned_gross The total amount of interest that has been earned, paid and unpaid. This figure is prior to paying Service Fees. Decimal
    projected_interest The interest expected over the next year. Decimal
    current_yield The current yield averaged across all investments. Decimal
    yield_to_maturity The current yield to maturity averaged across all investments Decimal
    interest_earned_pending_payment Total of interest payments past due, but not yet credited to the account. Decimal
    count_of_positions The total number of positions represented in the data, this field is not included when the data represents an individual position. Integer

    Smart Interest

    Name Description Data Type
    reference Smart interest product reference. Reference ID
    holding_name The holding name for the product. String
    series_no The series number for the product. String
    maturity The maturity date for the product. Date
    currency The currency of the holding. Currency
    amount The amount of principal held. Decimal
    cash_rate The rate paid on the principal. Decimal
    sales_fee_rate The fee if sold. Decimal
    total_interest_paid The total interest paid so far. Decimal

    Investment Product

    Name Description Data Type
    reference Product reference. Reference ID
    currency The currency of the product. Currency
    product_type The product type (e.g. fractional_bond, robowise or smart_interest) String-Enum
    detail Detailed product information. Product object for fractional_bond products, Smart Interest object for smart_interest products and Robowise account object for robowise.

    Account Balance

    Name Description Data Type
    amount Balance amount. Decimal
    currency The currency of the balance. Currency

    Payment Method

    Name Description Data Type
    method One of bank_transfer, open_banking, debit_card or account_transfer. String-Enum
    details Transfer details, vary by method. Method dependent

    Investment Accounts

    URL: /customers/{}/investment-accounts/

    To retrieve a list of all investment accounts for a user

    api = requests.get('$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/', headers=headers)
    
    curl -s "$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/" \
         -H "Authorization: Token $API_KEY" | jq .
    

    Or to read details of a specific investment account

    api = requests.get('$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID',
                       headers=headers)
    
    curl -s "$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID" \
         -H "Authorization: Token $API_KEY" | jq .
    

    The request returns a list of investment accounts as the following JSON:

    {
      "count": 1,
      "next": null,
      "previous": null,
      "results": [
        {
          "id": "INVACC00000001",
          "account_type": "individual",
          "currencies": ["GBP"]
        }
      ]
    }
    

    If you request details for a single investment account, then we return a single object, rather than a list.

    Available Methods:

    This endpoint returns the customer's investment accounts, i.e. a container to hold account balances and investments.

    You can request details on a specific investment account by specifying the investment account id in the URL.

    The summary contains the following information:

    Field Description Type
    id The currency used for this account. Reference ID
    account_type The type of this investment account. String (see below)
    currencies The currencies currently active for this investment account Array of Strings

    Investment accounts can be of the following account types:

    Account Type Description
    individual A standard individual account with no specific restrictions.
    ifisa An account holding IF ISA investments. Only current UK Tax Residents can open and fund IF ISA accounts, and there is a yearly funding limit of £20,000.
    corporate An account holding investments on behalf of a corporate entity.
    sipp An account SIPP investments.

    Creating an Account - Availability

    URL: GET /customers/{}/investment-accounts/available/

    To retrieve a list of all investment accounts available for creation

    api = requests.get('$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/available/', headers=headers)
    
    curl -s "$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/available/" \
         -H "Authorization: Token $API_KEY" | jq .
    
    {
      "count": 2,
      "next": null,
      "previous": null,
      "results": [
        {
          "account_type": "individual",
          "title": "Euro general investment account",
          "description": "Open an individual investment account for access to Euro products",
          "currency": "EUR",
          "is_transfer": false,
          "validation": []
        },
        {
          "account_type": "ifisa",
          "title": "IF ISA",
          "description": "Open a WiseAlpha Innovative Finance ISA (IF ISA) account",
          "currency": "GBP",
          "is_transfer": false,
          "validation": [
            "submit_nino",
            "agree_to_ifisa_terms"
          ]
        }
      ]
    }
    

    This endpoint will return an array of the possible accounts that can be created. This might also include adding an additional currency to an existing account.

    An array of account availability objects will be returned of the form:

    Field Description Type
    account_type The type of investment account individual or ifisa. String-Enum
    title A title that can be displayed to a user explaining the account. String
    description A longer description that can be displayed to the user explaining the account. String
    currency The currency that the account will be opened with. If this is not GBP then the account may additionally open with a GBP account. String
    is_transfer Is this a transfer of an account from another provider rather than a fresh opening of an account. Currently initiating account transfers via the API is not supported. Boolean
    validation Any pre-requisites that are not yet met before the account creation can take place - see below. Array of Strings

    The possible entries in the validation list are as follows:

    Value Description
    submit_nino In order to create an IF ISA account, WiseAlpha must have a record of the user's national insurance number. This can be submitted via the tax residencies field on the customer endpoint.
    agree_to_ifisa_terms The use must have agreed to WiseAlpha's IF ISA terms. This can be done through a PATCH or POST to the customer endpoint.

    Creating an Account

    URL: POST /customers/{}/investment-accounts/available/action/

    api = requests.post('$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/available/action/',
                        data={'account_type': 'individual', 'is_transfer': false, 'currency': 'EUR'}, headers=headers)
    
    curl -s -X POST "$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/available/action/"
         -H "Authorization: Token $API_KEY"
         -H "Content-Type: application/json"
         -d '{"account_type": "individual", "is_transfer": false, "currency": "EUR" }' | jq .
    

    On success, this endpoint returns the new or updated investment account.

    {
      "reference": "INVACC00004182",
      "account_type": "individual",
      "created": "2019-10-29T21:32:24.998451Z",
      "currencies": [
        "EUR",
        "GBP"
      ]
    }
    

    To action an availability, post the availability back to this endpoint. If successful the investment account will be sent back.

    Investment Account Balance

    URL: /customers/{}/investment-accounts/{}/balances/

    To read details of the uninvested capital balance for all currencies

    api = requests.get('$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/balances/', headers=headers)
    
    curl -s "$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/balances/" \
         -H "Authorization: Token $API_KEY" | jq .
    

    Or to read details of the uninvested capital balance for a single currency (GBP in this case)

    api = requests.get('$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/balances/GBP/', headers=headers)
    
    curl -s "$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/balances/GBP/" \
         -H "Authorization: Token $API_KEY" | jq .
    

    The request returns a list of balance summaries as the following JSON:

    [
      {
        "currency": "GBP",
        "amount": "1681.94"
      }
      ...
    ]
    

    If you request details for a single currency, then we return a single summary, rather than a list.

    Available Methods:

    This endpoint returns an investment account's uninvested capital balance, i.e. the amount of money the investment account has available for purchasing investments. There will be one balance for each currency the investment account supports.

    Note that this list is never paginated and the result is always a simple array of JSON objects.

    You can request details on a specific account by specifying the currency in the URL.

    This endpoint returns Account Balance objects.

    Query Available Payment Methods

    URL: /customers/{}/investment-accounts/{}/balances/{}/available-payment-methods/

    api = requests.get('$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/balances/$CURRENCY/available-payment-methods/',
                       headers=headers)
    
    curl -s "$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/balances/$CURRENCY/available-payment-methods/" \
         -H "Authorization: Token $API_KEY" | jq .
    

    A list of available payment methods for the account and currency will be returned.

    Fund Account

    URL: /customers/{}/investment-accounts/{}/balances/{}/fund/

    api = requests.post('$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/balances/GBP/fund/',
                        data={'amount': 1000, 'method': 'bank_transfer'}, headers=headers)
    
    curl -s -X POST "$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/balances/GBP/fund/"
         -H "Authorization: Token $API_KEY"
         -H "Content-Type: application/json"
         -d '{"amount": 1000, "method", "bank_transfer" }' | jq .
    

    On success, this method returns bank details to be used to complete the transaction

    {
      "status": "ok",
      "transfer_details": {
        "amount": "1000.00",
        "currency": "GBP",
        "wisealpha_reference": "BNKXFR00000007",
        "account_name": "DEVELOPER MODE",
        "sort_code": "12-34-56",
        "account_number": "123456789",
        "bank_name": "Test Bank",
        "swift_code": "BARCGB22XXX",
        "iban": "GB29RBOS60161331926819",
        "bank_reference": "000-000-101",
      }
    }
    

    Available Methods:

    Field Description Type
    amount The uninvested funds remaining in this account. Decimal
    method The method use to fund the account. Either bank_transfer, open_banking, paysafe_js or debit_card. String
    route_to On completion of the payment route the funds to the given child account, this must refer to a child account or be set to null or omitted. Reference ID
    card_type Only required when using method debit_card, must be one of visa_debit, maestro_debit, mastercard_debit or visa_electron_debit. Reference ID
    token Only required when using method paysafe_js, must be a one-time chargeable token retreieved through paysafe.js. String
    success_url Only required when using method open_banking, this will be the url the client is redirected to by the open banking provider on success. String
    error_url Only required when using method open_banking, this will be the url the client is redirected to by the open banking provider on error. String

    Funding via Bank Transfer

    This method initiates a bank transfer. The bank transfer is completed when the funds in question have been transferred to the given WiseAlpha account using the given bank reference.

    The transfer_details object contains details of the requested transfer. The wisealpha_reference is WiseAlpha's reference for this transfer, and will be included in all subsequent updates on this transfer, in particular in the event we generate to notify you when the funds have arrived in our system and been credited to your account. The remaining fields spell out the bank details to use. The meaning of each field should be obvious from the field name. Note particularly the bank_reference. Users must be sure to include this field when creating the payment/transfer request with their bank. Getting the bank reference wrong causes delay as WiseAlpha have to manually reconcile the transaction.

    Funding via Open Banking

    Calling this method will initial an open banking payment session. The returned object will contain a payment_url that the client should be redirected to.

    Funding via Debit Card

    This method intitiates a debit card transaction. A URL to navigate the user to in order to complete the transaction will be returned.

    Withdrawing funds from an account

    URL: POST /customers/{}/investment-accounts/{}/balances/{}/withdraw/

    api = requests.post('$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/balances/GBP/withdraw/',
                        data={'amount': 1000}, headers=headers)
    
    curl -s -X POST "$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/balances/GBP/withdraw/"
         -H "Authorization: Token $API_KEY"
         -H "Content-Type: application/json"
         -d '{"amount": 1000 }' | jq .
    

    On success, this method returns the account balance after the withdrawal.

    {
      "amount": "1000.00",
      "currency": "GBP",
    }
    

    This endpoint withdraws funds from the given account to the bank account associated with the account. On success the funds will be debited from the account. This endpoint returns an Account Balance object.

    Account Transaction

    URL: /customers/{}/investment-accounts/{}/balances/{}/transactions/

    To get a list of all transactions of a particular currency for a customer's investment account:

    api = requests.get('$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/balances/GBP/transactions/',
                       headers=headers)
    
    curl -s "$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/balances/GBP/transactions/" \
         -H "Authorization: Token $API_KEY" | jq .
    

    This returns a pagination object containing a list of transactions.

    {
      "count": 6,
      "next": null,
      "previous": null,
      "results": [
        {
          "created": "2019-05-10T01:55:36Z",
          "reference": "TRANS00999844",
          "balance": "100.00",
          "amount": "100.00",
          "currency": "GBP",
          "description": "Deposit",
          "type": "Deposit via debit card"
        },
        {
          "created": "2019-05-10T04:11:07Z",
          "reference": "TRANS00999847",
          "balance": "80.00",
          "amount": "-20.00",
          "currency": "GBP",
          "description": "Withdrawal to registered bank account",
          "type": "Withdrawal"
        },
        ...
      ]
    }
    

    The transaction endpoint does not support fetching a single transaction.

    Available Methods:

    This method returns a list of all the transactions on the given user's investment account.

    The fields in the transaction object are:

    Field Description Type
    created The date and time that the transaction occurred. DateTime
    reference A unique reference for this transaction. Reference ID
    balance The uninvested funds remaining in this account after the transaction. Decimal
    amount The amount the transaction changes the account balance. Negative values correspond to withdrawals, investment purchases etc. Decimal
    currency The currency this transaction used. Currency
    description A description of the transaction. String
    type The transaction type. String-Enum

    Common transaction types:

    Type Description
    Deposit via debit card User has deposited money in his account via debit card.
    Deposit via bank transfer User has deposited money in his account via bank transfer.
    Withdrawal User has withdrawn money from his account.

    Account Products

    URL: GET /customers/{}/investment-accounts/{}/products/

    To read details of all the investments the customer has purchased in a given investment account:

    api = requests.get('$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/products/', headers=headers)
    
    curl -s "$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/products/" \
         -H "Authorization: Token $API_KEY" | jq .
    

    Or to read details of a specific investment:

    api = requests.get('$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/products/INVMKT00000001/', headers=headers)
    
    curl -s "$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/products/INVMKT00000001/" \
         -H "Authorization: Token $API_KEY" | jq .
    

    The request returns a list of investments as the following JSON: json [ ... ]

    This method returns a list of all the investments the user owns in a given investment account, or has owned in the past.

    The fields returned in each investment object are:

    Field Description Type
    reference The product identifier for the underlying investment Reference ID
    product Investment product data Investment Product object
    open The open position data if applicable. Performance Summary object
    closed The closed position data if applicable. Performance Summary object

    A closed holding represents a position that the account held in the past. I.e. if an account owns 1000 of a product, then sells half of the product, the gain/loss from the sold half will appear in the closed position.

    This endpoint supports inclusions and exclusions.

    Available Expansions

    Name Description
    product Expand the product information
    product__detail Expand the product detail information
    product__detail__* All normal product expansions can be used from here, e.g. product__detail__cashflows

    Optional Query Strings for GET

    Name Description Data Type
    currencies Filter to return only products in certain currencies. E.g. ?currencies=GBP,EUR String
    exclude_fractional_bond_product_detail If expanding with product__detail, use this to exclude fractional_bond products from returning detail if you have already retrieved that data from a different source. String

    Account Product Transfer

    URL: POST /customers/{}/investment-accounts/{}/products/{}/transfer/

    To transfer a bond into a sub-account:

    api = requests.post('$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/products/INVMKT00000001/transfer/',
                        headers=headers,
                        data={"account": "$SUB_ACCOUNT_ID"})
    
    curl -s "$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/products/INVMKT00000001/transfer/" \
         -H "Authorization: Token $API_KEY" \
         -d '{"account": "$SUB_ACCOUNT_ID"}'| jq .
    

    Investments from a parent account can be transferred into child accounts. It's important to remember that child have specific purposes like robowise, so after transferring the bond may be sold in part or in whole depending on the paramters of the child account.

    Field Description Type
    account The account reference to transfer ownership to. Reference ID

    Account Portfolio Summary

    URL: /customers/{}/investment-accounts/{}/products/summary/

    To fetch a summary of an investment account's investments for all currencies

    api = requests.get('$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/products/summary/', headers=headers)
    
    curl -s "$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/products/summary/" \
         -H "Authorization: Token $API_KEY" | jq .
    

    To fetch a summary of an investment account's investments for a single currency (GBP in this case)

    api = requests.get('$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/products/summary/GBP/', headers=headers)
    
    curl -s "$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/products/summary/GBP/" \
         -H "Authorization: Token $API_KEY" | jq .
    

    The request returns a list of account summaries as the following JSON:

    [
      {
        "currency": "GBP",
        "summaries": {
          "all": {
            ...
          },
          "open": {
            ...
          }
        }
      }
      ...
    ]
    

    If you request details for a single currency, then we return a single summary, rather than a list.

    Available Methods:

    This endpoint produces a summary of the investment account's investments. The investment account will have one summary for each currency WiseAlpha supports.

    Note that this list is never paginated and the result is always a simple array of JSON objects.

    You can request details for a specific currency by specifying the currency in the URL.

    The account object is created the first time the account is funded, and these summaries are unavailable until that time.

    The summary contains the following information:

    Field Description Type
    currency The currency used for this account. Currency
    summaries The number of investments the investment account holds. Object
    summaries.all The performance summary across the lifetime of the investment account. Performance Summary
    summaries.open The performance summary for the Performance Summary

    Account Activity

    URL: /customers/{}/investment-accounts/{}/activity/{}/

    To fetch an investment account's activity feed

    api = requests.get('$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/activity/$CURRENCY/', headers=headers)
    
    curl -s "$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/activity/$CURRENCY/" \
         -H "Authorization: Token $API_KEY" | jq .
    

    The request returns a list of account summaries as the following JSON:

    [
      {
        "group": "August 2016",
        "amount": "105.8500",
        "currency": "GBP",
        "date_description": "07 Aug 2016",
        "created": "2016-08-07T05:21:40.325885Z",
        "description": "Bought <a href='https://www.wisealpha.com/market/corporate-bond/vue-entertainment/12/XS0953085114'>Vue Entertainment</a>",
        "item_logo": "https://d1x9604lsph6r7.cloudfront.net/media/cache/56/57/5657119b244045cf49026f07ea5737b2.png",
        "activity_type": "past",
        "transaction_type": "buy"
      },
      {
        "group": "February 2017",
        "amount": "3.9300",
        "currency": "GBP",
        "date_description": "Interest paid on 03 Feb 2017",
        "created": "2017-02-03T13:18:12.534450Z",
        "description": "Payment from <a href='https://www.wisealpha.com/market/corporate-bond/vue-entertainment/12/XS0953085114'>Vue Entertainment</a>",
        "item_logo": "https://d1x9604lsph6r7.cloudfront.net/media/cache/56/57/5657119b244045cf49026f07ea5737b2.png",
        "activity_type": "past",
        "transaction_type": "payment"
      },
      ...
      {
        "group": "August 2055",
        "amount": "8.29",
        "currency": "GBP",
        "date_description": "Interest due on 12 Aug 2055",
        "created": "2055-08-12T00:00:00Z",
        "description": "Payment from <a href=\"https://www.wisealpha.com/market/corporate-bond/vodafone/84/XS1472483772\">Vodafone</a>",
        "item_logo": "https://d1x9604lsph6r7.cloudfront.net/media/cache/e9/db/e9db7946013f482691387202a5cdd924.png",
        "activity_type": "future",
        "transaction_type": "payment"
      },
      {
        "group": "August 2056",
        "amount": "284.65",
        "currency": "GBP",
        "date_description": "Principal and Interest due on 12 Aug 2056",
        "created": "2056-08-12T00:00:00Z",
        "description": "Payment from <a href=\"https://www.wisealpha.com/market/corporate-bond/vodafone/84/XS1472483772\">Vodafone</a>",
        "item_logo": "https://d1x9604lsph6r7.cloudfront.net/media/cache/e9/db/e9db7946013f482691387202a5cdd924.png",
        "activity_type": "future",
        "transaction_type": "payment"
      }
    ]
    

    Available Methods:

    This endpoint gives historical and future activity for a given investment account and currency. The activity includes interest and principal repayments, completed buys and completed sells. To see how this might like see the below example from the WiseAlpha web app with the data based around early November 2019.

    WiseAlpha Activity Feed

    This endpoint returns an unpaged array of activity feed items as per below:

    Name Description Data Type
    group The month and year of the activity, e.g. February 1981. String
    amount The amount of the activity transaction. Decimal
    currency The currency of the activity transaction. String
    date_description A should description of the date of the activity. String
    created The datetime when the activity was created. DateTime
    description A short description of the activity. The description may include a link to the product details page on https://www.wisealpha.com if one is available. String
    item_logo When the activity relates to a bond it will be the logo of the company that the activity relates to, or an icon representing the activity. It may also be one the value smart_interest in which case no logo is provided. String
    activity_type Either future or past. String-Enum
    transaction_type One of payment, buy, sell or cash-movement. String-Enum

    Investment Transactions

    URL: /customers/{}/investment-accounts/{}/products/{}/transactions/

    To read details of all the transactions made for a given investment:

    api = requests.get('$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/products/INVMKT00000001/transactions/',
                       headers=headers)
    
    curl -s "$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/products/INVMKT00000001/transactions/" \
         -H "Authorization: Token $API_KEY" | jq .
    

    Or to read details of a specific transaction:

    api = requests.get('$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/products/INVMKT00000001/transactions/INVTR00000001/',
                       headers=headers)
    
    curl -s "$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/products/INVMKT00000001/transactions/INVTR00000001/" \
         -H "Authorization: Token $API_KEY" | jq .
    

    The request returns a list of investments as the following JSON: json [ ... ]

    Available Methods:

    This method returns a list of all the investment account's transactions - purchases, payouts, reinvestments etc. - on this investment.

    Buy Orders

    URL: /customers/{}/investment-accounts/{}/buy-orders/

    To get a list of all open buy orders for the given investment account.

    api = requests.get('$API_ROOT_URL/customers/investment-accounts/$INVESTMENT_ACCOUNT_ID/$CUSTOMER_ID/buy-orders/',
                       headers=headers)
    
    curl -s "$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/buy-orders/" \
         -H "Authorization: Token $API_KEY" | jq .
    

    Or to read details of a specific buy order:

    api = requests.get('$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/buy-orders/MKTBUY00000001/',
                       headers=headers)
    
    curl -s "$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/buy-orders/MKTBUY00000001/" \
         -H "Authorization: Token $API_KEY" | jq .
    

    The list request returns a list of buy orders as the following JSON:

    {
       "count":2,
       "next":null,
       "previous":null,
       "results":[
          {
             "id":"MKTBUY00000001",
             "original_id":"MKTBUY00000001",
             "product_id":"INVMKT00000001",
             "type":"gross",
             "state":"open",
             "currency":"GBP",
             "amount":"100.00",
             "principal":null,
             "price":"100.0000",
             "created":"2017-12-20T12:35:31.390342Z"
          },
          {
             "id":"MKTBUY00000002",
             "original_id":"MKTBUY00000002",
             "product_id":"INVMKT00000002",
             "type":"principal",
             "state":"open",
             "currency":"GBP",
             "amount":"120.02",
             "principal":"200.00",
             "price":"50.0125",
             "created":"2017-12-20T12:35:31.403366Z"
          }
       ]
    }
    

    This method returns a list of all buy orders that the customer has placed through a given investment account on the market that haven't yet been completed.

    You can also get details of a specific buy order by appending the order ID as shown.

    Each buy order object contains the following fields:

    Name Description Data Type
    id The ID of the buy order. This can be used in subsequent cancel and confirm requests Reference ID
    original_id The ID of the buy order when the buy was first issued. Reference ID
    product_id The ID of the investment being purchased Reference ID
    type The order type: 'gross' or 'principal' as described in the market section String
    state The state of the order - see below String
    currency The currency used to complete the order String
    amount The amount this investment will cost Decimal
    principal For type = principal orders, this is the amount of principal being purchased. Decimal
    price The price per unit of principal to use for this purchase Decimal
    created When this order was created DateTime

    Open orders can be in one of the following states:

    State Description
    open The order is waiting to be matched against a sell
    confirm Prices have changed since the order was made. It will need to be confirmed (see below)

    Sell Orders

    URL: /customers/{}/investment-accounts/{}/sell-orders/

    To get a list of all open sell orders for the given investment account.

    api = requests.get('$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/sell-orders/',
                       headers=headers)
    
    curl -s "$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/sell-orders/" \
         -H "Authorization: Token $API_KEY" | jq .
    

    Or to read details of a specific sell order:

    api = requests.get('$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/sell-orders/MKTSELL00000001/',
                       headers=headers)
    
    curl -s "$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/sell-orders/MKTSELL00000001/" \
         -H "Authorization: Token $API_KEY" | jq .
    

    The list request returns a list of sell orders as the following JSON:

    {
       "count":1,
       "next":null,
       "previous":null,
       "results":[
          {
             "id":"MKTSELL00000001",
             "original_id":"MKTSELL00000001",
             "product_id":"INVMKT00000004",
             "state":"open",
             "currency":"GBP",
             "amount":"100.00",
             "price":"50.0000",
             "created":"2017-12-20T13:50:19.839640Z"
          }
       ]
    }
    

    This method returns a list of all sell orders that the customer has placed through a given investment account on the market that haven't yet been completed.

    You can also get details of a specific sell order by appending the order ID as shown.

    Each sell order object contains the following fields:

    Name Description Data Type
    id The ID of the sell order. This can be used in subsequent cancel and confirm requests Reference ID
    original_id The ID of the sell order when the sell was first issued. Reference ID
    product_id The ID of the investment being sold Reference ID
    state The state of the order - see below String
    currency The currency used to complete the order String
    amount The amount this investment will cost Decimal
    price The price per unit of principal to use for this sale Decimal
    created When this order was created DateTime

    Open orders can be in one of the following states:

    State Description
    open The order is waiting to be matched against a sell
    confirm Prices have changed since the order was made. It will need to be confirmed (see below)

    This method returns a list of all sell orders that the customer has placed on the market that haven't yet been completed.

    You can also get details of a specific sell order by appending the order ID as shown.

    'id' vs 'original_id'

    When an order is partially filled - which may happen if there is only a limited amount of the product on the market, or if the next matched counterparty only has/wants a small amount of the product - we create a new order for the remainder.

    Similarly, when an order is confirmed, we create a new order at the new price, and archive the original.

    The id field is the ID of the current open order for that user and product. This ID is useful if you need to discuss the order with the WiseAlpha team.

    The original_id is the ID of the order when the buy or sell request was first issued. If you want to correlate orders with the original request, for example, to keep the customer informed of its progress, then you should use the original_id to do so.

    Order Actions

    URL: /customers/{}/investment-accounts/{}/buy-orders/{}/action/ URL: /customers/{}/investment-accounts/{}/sell-orders/{}/action/

    To confirm an order:

    api = requests.post('$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/sell-orders/MKTSELL00000001/action/',
                       headers=headers,
                       data={"action": "confirm"})
    
    curl -s "$API_ROOT_URL/customers/$CUSTOMER_ID/sell-orders/investment-accounts/$INVESTMENT_ACCOUNT_ID/sell-orders/MKTSELL00000001/action/" \
         -H "Authorization: Token $API_KEY" \
         -d '{"action": "confirm"}'| jq .
    

    To cancel an order

    api = requests.post('$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/sell-orders/MKTSELL00000001/action/',
                       headers=headers,
                       data={"action": "cancel"})
    
    curl -s "$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/sell-orders/MKTSELL00000001/action/" \
         -H "Authorization: Token $API_KEY" \
         -d '{"action": "cancel"}'| jq .
    

    In both cases, action returns HTTP return code 200 on success.

    The user can use this entrypoint to manage his open orders.

    If the price of an investment changes substantially before the order is completed, then the WiseAlpha platform raises an -order.price-change event and puts the order into the confirm state. In this state, the order will not be filled until the customer has confirmed that they want to continue.

    If the customer decides to continue, they should issue a confirm action as shown. This will create a new order based on the old order, but using the new price.

    Alternatively, if the customer does not want to continue, (or if the user has changed his mind about orders in the open state), they should issue a cancel action as shown. This will remove the order from the market.

    Robowise

    Robowise is an automatic portfolio management tool where users can configure a robowise account to target their investments based on a number of parameters and have robowise diversify their portfolio under the configured constraints. For a marketing page explaining the feature to users see here. Robowise trades made to diversify the porfolio will always be 0% fee trades.

    Each investment account that supports robowise can have multiple robowise sub-accounts configured that live within the parent account. Currently robowise is only supported for GBP investment accounts.

    Robowise Types

    Robowise Risk Categories

    Name Description
    medium Medium risk bond
    high High risk bond
    not candidate This bond is not a candidate for inclusion in a robowise portfolio
    hold This bond is not a candidate for inclusion in a robowise portfolio, but if currently held keep it.

    Robowise Risk Profile

    A robowise risk profile maps the broad split of investments that robowise will make with regard to the risk of investments.

    Field Description Type
    reference Profile ID Reference ID
    label The name of the profile, e.g. balanced. String
    projected_return The projected return for portfolios using this profile with the default inclusions and exclusions. Decimal
    weightings The split between various risk categories. Robowise Weighting object
    attributes The base attributes for this risk profile Robowise Attributes object
    description A description of the profile. String
    legacy True if this is a legacy (deprecated) profile and shouldn't be used in new or updated profiles. Boolean

    Robowise Weighting

    The sum of all fields in the weighting object should add up to 1. A fields particular value indicates how much out of a given risk category robowise will try to hold. So a weighting of .5 indicates robowise will aim to hold 50% of it's holidings in a given risk category.

    Field Description Type
    medium The weighting for medium risk bonds Float
    high The weighting for high risk bonds Float

    Robowise Attributes

    Robowise attributes is a summary of the yield, available bonds and calculated yield for a given combination of a Robowise Profile with a set of industry and company exclusions. If run on the base profile then calculated_yield will equal projected_return.

    Field Description Type
    bond_count The number of bonds that are candidates for inclusion Integer
    calculated_yield The calcualted yield for the returned bonds Decimal
    candidate_bonds All the bonds that can be considered for inclusion. Robowise Bond Summary object Array

    Robowise Bond Summary

    Field Description Type
    product_id The bond's product id. Reference ID
    company_id The company for the bond. Reference ID
    risk_category The bond's risk category Robowise Risk Category
    coupon The bond's coupon Decimal
    yield The bond's current yield Decimal
    weight The amount of this bond that robowise will attempt to hold as part of this portfolio. Decimal

    Robowise Company Summary

    Field Description Type
    company_id Company ID. Reference ID
    company_name The name of the company. String
    industry The key for the primary industry for the company. String

    Robowise Industry Summary

    Field Description Type
    key The industry key. String
    name A descriptive label for the industry. String

    Robowise Profile Modifiers

    Field Description Type
    excluded_industries An array of industry keys to exclude from the robowise profile. String Array
    excluded_companies An array of companies to exclude from the robowise profile. Reference ID Array

    Robowise Parameters

    Field Description Type
    currency The currency for the portfolio Currency
    risk_profile The risk profile the account is running under. Robowise risk profile object - ignored on PUT/POST
    risk_profile_id The risk profile id the account is running under. Reference ID
    profile_modifiers Modifiers for the selected risk profile. Robowise profile modifiers object
    reinvest_payments Whether payments from the profile holdings should be kept and reinvested or paid out into the parent account's wallet. Boolean

    Robowise Withdrawal Behaviour

    Field Description Type
    type Either all, some or none. String-Enum
    amount The amount of money to withdraw back into the parent account. Decimal

    Robowise Account Metadata

    Field Description Type
    industry_count The number of industries the profile currently has investments in. Integer

    Robowise Ideal Holding

    Field Description Type
    product_id ID of the investment product robowise is considering. String
    company_id ID of the company for this investment. String
    industry The industry that the company operates in. String
    ideal The amount of this investment Robowise would like to hold. Decimal
    wanted The amount robowise aims to hold after applying real-world constraints (such as minimum investment size.) Decimal
    held The amount robowise is currently holding. Decimal
    to_acquire The amount robowise is plannint to buy (or sell if this value is negative.) Decimal
    reason A hint as to the reason behind Robowise's decision String
    performance The performance of this product in the portfolio. Account product object

    Robowise Status

    Field Description Type
    state A Robowise Account State. String-Enum
    description A short human description of the status. String

    Robowise Account State

    State Description
    opening The account has been created, but does not have enough funds to start invested (min GBP/EUR 90)
    open The account is open and is being actively managed by robowise
    closing The account is in the process of being closed, it will not make any new purchases.
    closed The account has been closed and no longer has any holdings. It can still be accessed for reporting purpose.

    Robowise Closure Request

    Field Description Type
    closure_type A Robowise Closure Type. String-Enum

    Robowise Closure Type

    Type Description
    transfer_to_parent Close the account by transferring all holdings to the parent account.
    liquidate Close the account by liquidating all holdings and transferring the cash to the parent account.

    Robowise Account

    Field Description Type
    name A name for the account. String
    reference The reference for the robowise profile. Reference ID
    created When the account was created Datetime
    parameters The parameters controlling the behaviour of this robowise profile. Robowise parameters object
    status The current status of this account Robowise status object
    withdrawal_behavior Returns the current withdrawal behaviour set for the account. This field is ignored on update, see Withdraw cash from a Robowise Portfolio for information on how to withdraw cash from a robowise portfolio back into the parent account. Robowise Withdrawal Behaviour object
    metadata Additional account metadata Robowise Account Metadata
    performance Returns the current and historical performance of the portfolio, not included by default, but is available as an expansion. Performance Summary object
    balance Returns the cash balance available to the robowise account, not included by default, but is available as an expansion. Account Balance object
    ideals Robowise's investment strategy for each investment, not included by default, but is available as an expansion. Array of Robowise Ideal Holding objects

    Get Robowise Configuration Data

    URL: /robowise/{currency}/configuration-data/

    Available Methods:

    Parameters:

    Field Description Type
    risk_profile_id The current risk profile in use, providing this will make sure it's returned even if the profile itself has since been marked as inactive. Reference ID

    The fields returned are:

    Field Description Type
    companies An array of the companies whose bond's are available to invest in under robowise. Robowise company summary object
    industries An array of industries available to invest in. Robowise industry summary object
    risk_profiles An array of robowise risk profiles Robowise risk profile object
    suggested_names An array of suggested portfolio names, this will be filtered by removing any names already used by the calling user. String Array

    The request returns the data needed to create and update robowise profiles:

    {
      "companies": [
        {
          "company_id": "CO00000034",
          "company_name": "AMC ",
          "industry": "entertainment_media_broadcasting"
        },
        ...
        {
          "company_id": "CO00000057",
          "company_name": "Yell",
          "industry": "entertainment_media_broadcasting"
        }
      ],
      "industries": [
        {
          "key": "entertainment_media_broadcasting",
          "label": "Entertainment, Media & Broadcasting"
        },
        ...
        {
          "key": "travel",
          "label": "Travel"
        }
      ],
      "risk_profiles": [
        {
          "reference": "RWRP00000002",
          "label": "Balanced",
          "projected_return": "5.79",
          "weightings": {
            "high": 0,
            "medium": 1.0,
          },
          "attributes": {
            "candidate_loans": [
              {
                "product_id": "INVMKT00000011",
                "company_id": "CO00000011",
                "risk_category": "medium",
                "coupon": "6.0000",
                "weight": "0.02631579",
                "yield": "3.7000"
              },
              ...
              {
                "product_id": "INVMPE00000088",
                "company_id": "CO00000067",
                "risk_category": "medium",
                "coupon": "5.1250",
                "weight": "0.02631579",
                "yield": "6.8000"
              }
            ],
            "calculated_yield": 5.79,
            "bond_count": 38
          },
          "description": "100% weighting to investments on the Main Market (Senior Secured and Senior Unsecured) with no high yield market exposure."
        },
        {
          "reference": "RWRP00000003",
          "label": "Adventurous",
          "projected_return": "7.85",
          "weightings": {
            "high": 0.5,
            "medium": 0.5,
          },
          "attributes": {
            "candidate_loans": [
              {
                "product_id": "INVMKT00000011",
                "company_id": "CO00000011",
                "risk_category": "medium",
                "coupon": "6.0000",
                "weight": "0.01315789",
                "yield": "3.7000"
              },
              ...
              {
                "product_id": "INVMHY00000090",
                "company_id": "CO00000069",
                "risk_category": "high",
                "coupon": "7.7500",
                "weight": "0.02173913",
                "yield": "7.2000"
              }
            ],
            "calculated_yield": 7.85,
            "bond_count": 61
          },
          "description": "The portfolio has a 50% target weighting to investments on the main market (Senior secured and Senior Unsecured bonds) and a 50% weighting to investments on the high yield market (subordinated bonds and Perpetuals. As well as a potentially higher return there is greater risk in this portfolio versus the Balanced portfolio."
        },
        {
          "reference": "RWRP00000004",
          "label": "Adventurous2",
          "projected_return": "7.83",
          "weightings": {
            "high": 0.5,
            "medium": 0.5,
          },
          "attributes": {
            "candidate_loans": [
              {
                "product_id": "INVMKT00000011",
                "company_id": "CO00000011",
                "risk_category": "medium",
                "coupon": "6.0000",
                "weight": "0.01351351",
                "yield": "3.7000"
              },
              ...
              {
                "product_id": "INVMHY00000090",
                "company_id": "CO00000069",
                "risk_category": "high",
                "coupon": "7.7500",
                "weight": "0.02173913",
                "yield": "7.2000"
              }
            ],
            "calculated_yield": 7.84,
            "bond_count": 60
          },
          "description": "The portfolio has a 50% target weighting to investments on the main market (Senior secured and Senior Unsecured bonds) and a 50% weighting to investments on the high yield market. As well as a potentially higher return there is greater risk in this portfolio versus the Balanced portfolio."
        }
      ]
    }
    

    Check a robowise configuration

    URL: /robowise/{currency}/risk-profile-attributes/

    Available Methods:

    Parameters:

    Field Description Type
    risk_profile_id The ID of the risk profile to be considered. Reference ID
    excluded_industries An array of industry keys to exclude from the robowise profile. String Array
    excluded_companies An array of companies to exclude from the robowise profile. Reference ID Array

    The fields returned are:

    Field Description Type
    candidate_bonds The bonds that will be considered for inclusion. Robowise Bond Summary object Array
    bond_count The number of bonds to be considered Decimal
    weighted_ytm The weighted average yield to maturity of the resulting portfolio, assuming Robowise achieves an ideal spread of investments. Integer
    issues A list of issues that must be fixed before this profile can be used. String Array

    Possible values in the issues field include:

    List Robowise Portfolios

    URL: GET /customers/{}/investment-accounts/{}/robowise/

    To retrieve a list of all robowise portfolios for a given investment account.

    api = requests.get('$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/robowise/', headers=headers)
    
    curl -s "$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/robowise/" \
         -H "Authorization: Token $API_KEY" | jq .
    

    Returned is a list of Robowise account objects

    Available Expansions

    Name Description
    performance Return the portfolio performance
    balance Return the portfolio cash balance
    ideals Return a breakdown of Robowise's current investment strategy

    Get Robowise Portfolio

    URL: GET /customers/{}/investment-accounts/{}/robowise/{}/

    Return details of a single robowise portfolio

    As per the List call but returning a single Robowise account object rather than a list.

    Available Expansions

    Name Description
    performance Return the portfolio performance
    balance Return the portfolio cash balance
    ideals Return a breakdown of Robowise's current investment strategy

    Create Robowise Portfolio

    URL: POST /customers/{}/investment-accounts/{}/robowise/

    data = {
        "parameters": {
            "risk_profile_id": "RWRP00000002",
            'reinvest_payments': False,
            "profile_modifiers": {
                "excluded_companies": ["CO00000001"],
                "excluded_industries": ["space_mining"],
            }
        }
    }
    api = requests.post('$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/robowise/',
                        data=data, headers=headers)
    
    curl -s -X POST "$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/robowise/"
         -H "Authorization: Token $API_KEY"
         -H "Content-Type: application/json"
         -d '{"parameters": {"risk_profile_id": "RWRP00000002", "profile_modifiers": {}}}' | jq .
    

    On success, this endpoint returns the new Robowise account object

    To create a robowise profile post a Robowise account object to this endpoint. Only the risk_profile_id member is needed in the parameters object, the fully serialized risk_profile is ignored.

    If no name is provided one will be selected from a default set of names managed by WiseAlpha.

    Update Robowise Portfolio

    URL: PUT /customers/{}/investment-accounts/{}/robowise/{}/

    data = {
        "parameters": {
            "risk_profile_id": "RWRP00000002",
            'reinvest_payments': False,
            "profile_modifiers": {
                "excluded_companies": ["CO00000001"],
                "excluded_industries": ["space_mining"],
            }
        }
    }
    api = requests.put('$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/robowise/$ROBOWISE_ACCOUNT_ID/',
                        data=data, headers=headers)
    
    curl -s -X POST "$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/robowise/$ROBOWISE_ACCOUNT_ID/"
         -H "Authorization: Token $API_KEY"
         -H "Content-Type: application/json"
         -d '{"parameters": {"risk_profile_id": "RWRP00000002", "profile_modifiers": {}}}' | jq .
    

    On success, this endpoint returns the updated Robowise account object

    To update update and PUT a Robowise account object. Only the risk_profile_id member is needed in the parameters object, the fully serialized risk_profile is ignored.

    Fund a Robowise Portfolio

    URL: POST /customers/{}/investment-accounts/{}/robowise/{}/fund/

    data = {
        "amount": "1000.00"
    }
    api = requests.post('$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/robowise/$ROBOWISE_ACCOUNT_ID/fund/',
                        data=data, headers=headers)
    
    curl -s -X POST "$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/robowise/$ROBOWISE_ACCOUNT_ID/fund/"
         -H "Authorization: Token $API_KEY"
         -H "Content-Type: application/json"
         -d '{"amount": 1000.00}' | jq .
    

    Funds cannot be deposited directly into a robowise portfolio, but must rather be transferred from the parent account.

    Field Description Type
    amount The amount to transfer from the parent account to the robowise account. Decimal

    No currency is provided as each robowise account operates only in a single currency.

    On success an Account Balance object is returned with the available cash balance for the account. As robowise is designed to invest any available cash, this is typically the amound just funded.

    Withdraw cash from a Robowise Portfolio

    URL: POST /customers/{}/investment-accounts/{}/robowise/{}/withdraw/

    data = {
        "type": "some",
        "amount": "1000.00",
    }
    api = requests.post('$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/robowise/$ROBOWISE_ACCOUNT_ID/withdraw/',
                        data=data, headers=headers)
    
    curl -s -X POST "$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/robowise/$ROBOWISE_ACCOUNT_ID/withdraw/"
         -H "Authorization: Token $API_KEY"
         -H "Content-Type: application/json"
         -d '{"amount": 1000.00, "type": "some"}' | jq .
    

    For each robowise portfolio a target cash amount to withdraw can be set, or the portfolio can be marked to be cashed out completely. When a target amount is set, robowise will sell off enough of it's managed portfolio in order to reach the target. Funds will be move from the robowise account to the parent account as they become available.

    The endpoint accepts a Robowise Withdrawal Behaviour object.

    The current withdrawal behaviour can be checked via checking the Robowise account object and inspecting the withdrawal_behavior field. There can be only one withdrawal behaviour set at a time, if a second call is made it will supercede the current behaviour. If a target is set to withdraw 1000, funds will be moved as they become available and the amount returned in the withdrawal_behaviour field will update to reflect this.

    Transferring a Fractional Bond into a Robowise Portfolio

    Fractional bond investments can be transferred from the parent account into robowise child accounts. This allows a customer to diversify their current holdings without incurring sales fees.

    See Account Product Transfer for details on how to issue the transfer.

    Close a Robowise Portfolio

    URL: POST /customers/{}/investment-accounts/{}/robowise/{}/close/

    data = {
        "type": "transfer_to_parent",
    }
    api = requests.post('$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/robowise/$ROBOWISE_ACCOUNT_ID/close/',
                        data=data, headers=headers)
    
    curl -s -X POST "$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/robowise/$ROBOWISE_ACCOUNT_ID/close/"
         -H "Authorization: Token $API_KEY"
         -H "Content-Type: application/json"
         -d '{"type": "transfer_to_parent"}' | jq .
    

    In order to close a robowise portfolio you need to issue a closure request and specify what how you want WiseAlpha to handle any remaining holdings in the account.

    The endpoint accepts a Robowise Closure Request object. On acceptance of the request the account will be put into the closing state and the process to close the account started. The robowise.closed event will be generated when the closure is complete.

    Reporting

    Report Types

    The following reports are offered over the API

    Name Tag Description
    Portfolio Value portfolio_value A report showing the Portfolio Value for each of the current investments in the chosen account as well as its characteristic information including Coupon, Next Payment Date, Maturity Date, and Rating. Available as csv.
    Gain/Loss gain_loss A report showing the Portfolio Value, Gain/Loss, Interest Earned and other measures for all of your current and closed investments since the account was opened. Available as csv.
    Account Statement account_statement A statement detailing all the cash movements on your account. Available as csv and pdf.
    Tax Report tax_report A report with the necessary information for filling out tax forms. Available as pdf.

    Report Formats

    Depending on the report, a combination of the available formats is available for downoload.

    Name Format Description
    CSV csv Comma seperated values text/csv
    PDF pdf Portable Document Format (PDF) application/pdf

    List Available Reports

    URL: /customers/{}/investment-accounts/{}/reports/

    Request a Report

    URL: /customers/{}/investment-accounts/{}/reports/generate/

    Market

    Market Data Types

    We use the following data types in the market endpoints:

    Buy Request object

    Name Description Data Type
    product_id The product ID to create a buy order for. Reference ID
    type One of either principal or gross. If the buy is of type principal then the order will be create to acquire the specific amount of principal regardless of current price or accrued interest on the product. A buy of type gross will create an order of the specified amount and will buy the appropriate amount of principal to achieve that. String-Enum
    amount Either the amount of principal to acquire or the amount of money to invest depending on the type. Decimal
    currency Currency to invest with, currently this must match the currency that the product is listed in. Currency
    price The price to buy the product at. For an explanation of product prices see the pricing under general section. Decimal

    Buy Quote object

    This object has the same fields as the Buy Request object with the additional fields below added.

    Name Description Data Type
    principal The amount of principal that will be purchased. Decimal
    interest The amount of accrued interest that will be purchased. Decimal
    total The total amount the user needs to spend to complete this purchase. Decimal
    warnings Any reasons that this request might fail, e.g., price does not match bond, or the customer is attempting to buy more than is

    Sell Request object

    Name Description Data Type
    product_id The product ID to create a sell order for. Reference ID
    amount The amount of principal to sell. Decimal
    currency Currency to invest with, currently this must match the currency that the product is listed in. Currency
    price The price to sell the product at. For an explanation of product prices see pricing under the general section. Decimal

    Sell Quote object

    This object has the same fields as the Sell Request object with the additional fields below added.

    Name Description Data Type
    principal The amount of principal that will be sold. Decimal
    interest The amount of accrued interest that will be sold. Decimal
    service_fee The service fee that will be taken (As per the T&C, this is the service fee the customer has accumulated while holding this asset.) Decimal
    sale_fee The sale fee that will be taken (As per the T&C, selling an investment early is subject to a small fee.) Decimal
    total This is the total, including interest and all fees, the user will receive when selling the asset. Decimal
    warnings Any reasons that this request might fail, e.g., price does not match bond, or the customer is attempting to sell more than they own. Array of Strings

    /market/

    import json
    import requests
    
    headers = {
      'Authorization': 'Token $API_KEY',
      'Content-Type': 'application/json',
    }
    
    market_request = {
        "customer_id": "10000001",
        "investment_account_id": "INVACC00000001",
        "buys": [{
            "product_id": "INVMKT00000001",
            "type": "principal",
            "amount": "500.00",
            "currency": "GBP",
            "price": "100"
        }, {
            "product_id": "INVMKT00000002",
            "type": "gross",
            "amount": "500.00",
            "currency": "GBP",
            "price": "100"
        }],
        "sells": [{
            "product_id": "INVMKT00000003",
            "amount": "500.00",
            "currency": "GBP",
            "price": "100"
        }]
    }
    
    
    api = requests.post('$API_ROOT_URL/market/', headers=headers, data=json.dumps(market_request))
    
    read -r -d '' DATA << EOM
    {
      "customer_id": "10000001",
      "investment_account_id": "INVACC00000001",
      "buys": [
        {
          "product_id": "INVMKT00000001",
          "type": "principal",
          "amount": "500.00",
          "currency": "GBP",
          "price": "100"
        },
        {
          "product_id": "INVMKT00000002",
          "type": "gross",
          "amount": "500.00",
          "currency": "GBP",
          "price": "100"
        }
      ],
      "sells": [
        {
          "product_id": "INVMKT00000003",
          "amount": "500.00",
          "currency": "GBP",
          "price": "100"
        }
      ]
    }
    EOM
    
    curl -s -X POST $API_ROOT_URL/market/ \
         -H "Authorization: Token $API_KEY" \
         -H "Content-Type: application/json" \
         -d "$DATA" | jq .
    

    The above command returns JSON structured like this:

    {
        "balances": [{
            "currency": "GBP",
            "amount": "1681.94"
        }],
        "buys_orders": [{
            "id":"MKTBUY00000001",
            "original_id":"MKTBUY00000001",
            "product_id":"INVMKT00000001",
            "type":"principal",
            "state":"open",
            "currency":"GBP",
            "amount":"520.00",
            "principal":"500.00",
            "price":"100.0000",
            "created":"2017-12-20T12:35:31.403366Z"
        },{
            "id":"MKTBUY00000002",
            "original_id":"MKTBUY00000002",
            "product_id":"INVMKT00000002",
            "type":"gross",
            "state":"open",
            "currency":"GBP",
            "amount":"500.00",
            "principal":null,
            "price":"100.0000",
            "created":"2017-12-20T12:35:31.390342Z"
          }
        ],
        "sell_orders": [{
             "id":"MKTSELL00000001",
             "original_id":"MKTSELL00000001",
             "product_id":"INVMKT00000003",
             "state":"open",
             "currency":"GBP",
             "amount":"500.00",
             "price":"100.0000",
             "created":"2017-12-20T13:50:19.839640Z"
        }]
    }
    

    Use the market endpoint to create buy and sell orders on the WiseAlpha market. A successful market request will return the new account balance after the orders have been placed along with details of the orders created. Details of unfulfilled orders can also be retrieved via the buy_orders and sell_orders entrypoints. On success, all of the buys and sells have been placed on the market, though they will not have been fulfilled. In particular, sell orders (and buy orders with no liquidity) will likely remain unfulfilled until another customer creates a matching order. For this reason, we recommend that you only allow the customer to generate buy orders when the bond sell_liquidity is non-zero. Sell orders may take a few days to complete.

    The customer will be notified of success or failure of the order via buy-order and sell-order events as documented in the events section.

    If the market request fails, none of the buys and sells will have been placed on the market, The request cannot partially succeed.

    Available Methods:

    POST request:

    The market request takes the following arguments.

    Name Description Data Type
    customer_id User account making the trade, if not present the account is assumed to be the account associated with the API key in use. Customer ID
    investment_account_id Investment account to make the trade on. Reference ID
    buys An array of buy requests. Array of Buy Requests
    sells An array of sell requests. Array of Sell Requests

    It returns a JSON object containing the following fields:

    Name Description Data Type
    balances The funds remaining uninvested in the customer's account. See balances for details. Array of balance objects
    buy_orders A list of buy orders created by the request. See buy_orders for details. Array of Buy orders
    sell_orders A list of sell orders created by the request. See sell_orders for details. Array of Sell orders

    /market/quote/

    import json
    import requests
    
    headers = {
      'Authorization': 'Token $API_KEY',
      'Content-Type': 'application/json',
    }
    
    market_request = {
        "customer_id": "1000001",
        "investment_account_id": "INVACC00000001",
        "buys": [{
            "product_id": "INVMKT00000001",
            "type": "principal",
            "amount": "500.00",
            "currency": "GBP",
            "price": "100"
        }, {
            "product_id": "INVMKT00000002",
            "type": "gross",
            "amount": "500.00",
            "currency": "GBP",
            "price": "100"
        }],
        "sells": [{
            "product_id": "INVMKT00000003",
            "amount": "500.00",
            "currency": "GBP",
            "price": "100"
        }]
    }
    
    
    api = requests.post('$API_ROOT_URL/market/quote/', headers=headers, data=json.dumps(market_request))
    
    read -r -d '' DATA << EOM
    {
      "customer_id": "10000001",
      "investment_account_id": "INVACC00000001",
      "buys": [
        {
          "product_id": "INVMKT00000001",
          "type": "principal",
          "amount": "500.00",
          "currency": "GBP",
          "price": "100"
        },
        {
          "product_id": "INVMKT00000002",
          "type": "gross",
          "amount": "500.00",
          "currency": "GBP",
          "price": "100"
        }
      ],
      "sells": [
        {
          "product_id": "INVMKT00000003",
          "principal": "500.00",
          "principal_currency": "GBP",
          "price": "100"
        }
      ]
    }
    EOM
    
    curl -s -X POST $API_ROOT_URL/market/quote/ \
         -H "Authorization: Token $API_KEY" \
         -H "Content-Type: application/json" \
         -d "$DATA" | jq .
    
    

    The above command returns JSON structured like this:

    {
        "customer_id": "10000001",
        "investment_account_id": "INVACC00000001",
        "buys": [{
            "product_id": "INVMKT00000001",
            "type": "principal",
            "amount": "500.00",
            "currency": "GBP",
            "price": "100",
            "principal": "500.00",
            "interest": "1.50",
            "total": "501.50",
            "warnings": []
        }, {
            "product_id": "INVMKT00000002",
            "type": "gross",
            "amount": "500.00",
            "currency": "GBP",
            "price": "100",
            "principal": "499.00",
            "interest": "1.00",
            "total": "500.00",
            "warnings": []
        }],
        "sells": [{
            "product_id": "INVMKT00000003",
            "amount": "500.00",
            "currency": "GBP",
            "price": "100",
            "principal": "500.00",
            "interest": "2.50",
            "service_fee": ".25",
            "sale_fee": "1.25",
            "total": "501.00",
            "warnings": []
        }]
    }
    

    Use the /market/quote/ endpoint to get a preview of what will happen during a market buy or sale.

    When buying an investment, this endpoint returns the amount of principal and interest that will be purchased, and the total amount that the user will need to invest to fulfill the order. These amounts are related via the following formula:

    total = principal * price + interest

    For "type": "gross" orders, the amount corresponds to the total amount the customer wants to spend on the investment. In this case, amount == total and the amount of principal the customer will receive is given by principal.

    For "type": "principal" orders, the amount corresponds to the amount of principal the customer wants to purchase. In this case, amount == principal and the total gives the amount the user will have to pay for the investment.

    When selling an investment, the amount always specifies the amount of principal the customer intends to sell. In this case, the endpoint returns the amount of accrued interest they will receive, and the fees taken during the sale. The total field gives total cash that will be returned to the user.

    As when you're buying from the marketplace you're also buying accrued interest. and the market price can fluctuate these calculations can vary.

    The results of a successful call to /market/quote/ may be posted to /market/ directly, although a successful call to /market/quote/ is no guarantee of the trade going through successfully as the /market/ endpoint runs additional validation that the /market/quote/ endpoint does not.

    Available Methods:

    Request body arguments for POST

    As per /market/

    Name Description Data Type
    buys Quotes for the buy requests passed in. Array of Buy quotes
    sells Quotes for the sell requests passed in. Array of Sell quotes

    Events and Webhooks

    As part of your API integration you can configure webhooks to receive callbacks when certain events happen in WiseAlpha. The endpoint receiving these webhooks must return a success response to the WiseAlpha server. WiseAlpha will attempt to deliver an event to a webhook URL 5 times, with an increasing delay between attempts until a success response is returned. After 5 delivery attempts the event will no longer be delivered.

    Alternatively, you can always fetch the event via the /events/ endpoint below.

    Events

    Every event contains the following fields:

    Field Description Type
    id The unique event identifier Reference ID
    created The timestamp for when the event was created DateTime
    event_type The type of the event String - one of the Event Type values listed below
    customer_id The customer the event applies to Customer ID
    data Additional information specific to the event A dictionary containing additional information specific to the event

    The WiseAlpha platform produces the following events.

    Event Type Description
    account.aml-check-passed The AML check is complete and passed. The user can now invest.
    account.aml-check-failed The AML check is complete and failed. The user will need to upload ID documents before they can invest.
    account.identity-documents-verified The WiseAlpha team have verified and approved the user's identity documents.
    account.document-rejected The WiseAlpha team have rejected a document that you uploaded. You will need to upload the document in question again.
    account.additional-document-required We require that you upload an additional document to further verify your account. (E.g., a bank statement to verify account ownership.)
    account.bank-details-rejected The user's bank details are invalid. The user will need to upload new bank details before transfer can be processed.
    account.bank-transfer-credited The user's bank transfer has been completed and the amount credited to his WiseAlpha account.
    account.investor-type-approved The user's investor type has been approved.
    buy-order.price-change The prices of the assets in the user's buy order has changed before it could be completed. The buy order will need to be reconfirmed.
    buy-order.filled The buy order has been filled.
    buy-order.cancelled The buy order has been cancelled. This usually occurs because none of the requisite asset is available to fill the order.
    sell-order.price-change The prices of the assets in the user's sell order has changed before it could be completed. The sell order will need to be reconfirmed.
    sell-order.filled The sell order has been filled.
    sell-order.cancelled The sell order has been cancelled. This is a very rare eventuality - usually, sell orders remain until the asset is sold.
    investment.payment An investment has made a payment.
    investment.repayment An investment has been repaid.
    investment.partial_repayment An investment has been partially repaid.
    robowise.closed A robowise account has been closed.

    The account events

    These events are generated when the WiseAlpha platform changes the state of a user's account, e.g. when the WiseAlpha platform completes an AML check.

    The event contains the following additional information in the data field:

    Field Description Type
    user_profile User's profile object after the update Profile object

    Details of the next steps required - if any - are contained in the validation object in the user data.

    The aml-check-passed and aml-check-failed events

    These events are generated when the WiseAlpha platform completes the AML check for a user.

    If the AML check returns "pass" we generate the aml-check-passed event. The user can start investing up to the AML investment threshold - currently £5,000 - without restriction.

    If the AML check returns "fail" we generate the aml-check-failed event. In this case, the user will not be able to transfer funds or invest until they have uploaded identity documents.

    The identity-documents-verified event

    This event is generated when the WiseAlpha team has reviewed and verified the ID documents provided by the user and the AML process is now complete. The user is in the invest state and can invest and withdraw funds as he sees fit.

    The document-rejected event

    This event is generated when the WiseAlpha team has reviewed a document, but found it to be not acceptable. The event contains the following additional fields.

    Field Description Type
    document.type The ID of the document that was rejected. See Onboarding for details of valid document types. String
    document.type_display A human-readable string describing the document type. String
    document.original_file_name The name provided when the document was uploaded. String
    document.rejection_reason The reason the wisealpha team rejected this document. String

    The user's verification object will also be updated to indicate which documents need updating.

    The additional-document-required event

    From time to time, we may require additional documentation. E.g., we may require that you upload a bank statement if we are unable to automatically verify that the user owns/controls the linked bank account.

    Field Description Type
    document.type The ID of the document that was rejected. See Onboarding for details of valid document types. String
    document.type_display A human-readable string describing the document type. String

    The user's verification object will also be updated to indicate that an additional document is now required.

    The bank-details-rejected event

    Before we can transfer money to an external bank account, we check the user's configured bank-details. If the bank details are deemed to be invalid, e.g., if the sort code does not identify a real bank, then we issue an account.bank-details-rejected event. In this case the user should upload new bank details.

    Field Description Type
    rejection_reason The reason the Wisealpha team rejected the bank details. String

    Note that if the bank details are valid, but can't be confirmed as belonging to the user, then we will send an appropriate account.additional-document-required event instead.

    The bank-transfer-credited event

    This event is generated when the fund transfer process is complete, i.e. when funds have arrived in our system and been credited to your account. In addition to the user_profile object, the event contains the following additional items:

    Field Description Type
    wisealpha_reference WiseAlpha's reference for this transfer. String
    amount_allocated The amount allocated to your account for this transfer Decimal
    currency The currency of the amount allocated in this transfer Currency

    The wisealpha_reference matches the reference returned by the initial fund request. You can use this to correlate this event with the fund request that initiated the process.

    The amount_allocated gives the amount credited to your account.

    The buy-order and sell-order events

    Buys and sells of marketplace investments are completed offline. The WiseAlpha platform sends events to notify the user when the order for each investment completes.

    All buy-order and sell-order events include the following fields:

    Field Description Type
    order_id The order ID Reference ID
    original_id The ID of the order originally submitted Reference ID
    investment Details of the investment being bought or sold Investment Object
    currency The currency of this order Currency
    trade_type (Buys only) The type of this trade: gross, principal or auto_reinvest_trade String

    WiseAlpha fulfils orders by matching buys with sells in the marketplace. This means that any given order can be filled over a number of transactions.

    The investment object contains the following fields:

    Field Description Type
    product_id Product id Reference ID
    company_name The name of the company String

    The -order.filled events

    We raise this event when the order has been completely filled, or partially filled then the remainder cancelled.

    Field Description Type
    amount_requested The amount originally requested Decimal
    amount_filled The amount we were able to fulfil Decimal

    For buy orders, even principal orders, the above amounts are the total amount requested/spent, including accrued interest. For sell orders, the above amounts refer to the amount of principal.

    For sell orders, we also include the following fields:

    Field Description Type
    cash_received The amount of cash returned to the user, including accrued interest and fees taken. Decimal

    The -order.cancelled events

    We raise this event when the order is cancelled. The event contains the following additional fields:

    Field Description Type
    reason The reason the order was cancelled String
    amount_remaining The amount remaining unfulfilled in this order Decimal
    currency The currency of the order Currency

    If the order has been partially filled before being cancelled, you'll also get an -order.filled event telling you this.

    The -order.price_change events

    We raise this event when the asset underlying the order changes in price. It indicates that the order has been suspended. The user will need to confirm that they want to continue with this order via the /orders/confirm entrypoint. Alternatively, they can cancel the order. For buy orders, this returns the order funds to the user's wallet.

    Field Description Type
    old_price The old price of the asset Decimal
    new_price The new price of the asset Decimal
    amount_remaining The amount remaining unfulfilled in this order Decimal
    currency The currency of the order Currency

    The investment events

    These events are generated when an investment makes a payment.

    All the events include the following fields:

    Field Description Type
    investment Details of the investment being paid out. Investment object
    currency The currency of the payout Currency
    interest_payment The interest paid out Decimal
    reinvesting_proceeds Whether we are going to reinvest the proceeds Boolean

    For marketplace investments, the investment field contains details of the bond, e.g., the wise ticker and company name.

    The reinvesting_proceeds flag is set to true if you have selected to reinvest the proceeds of this investment, and if there is some of this investment available on the marketplace. In this case the proceeds of the investment are used to purchase more of the investment. Otherwise, the proceeds are added to the user's uninvested funds. They'll need to either withdraw the funds or manually reinvest them as they see fit.

    (For repayment and partial_repayment events, reinvesting_proceeds is currently always False. At some future time, WiseAlpha plan to offer an automated reinvestment tool. When the user selects to use such a tool, this flag will be true and the proceeds will automatically be used to purchase other investments.)

    We issue the investment.payment event when an investment makes an interest payment. The proceeds are your share of the interest accrued on this investment since it last made a payment, or since it was issued if this is the first payment.

    We issue the investment.repayment event when an investment repays, either because it has matured or because the company issuing the bond has decided to repay early. The proceeds include both the interest accrued since the last payment and repayment of the capital. Repayment events contain the following additional fields:

    Field Description Type
    call_price The price at which the bond issuer is buying back the principal Decimal
    principal_payment The principal paid out Decimal

    The call_price is the price at which the principal is being repaid. A call price of 100 means the principal is being bought back at parity. In some cases, particularly if the bond is being paid back early, the call price may be greater than 100, in which case the user is making a capital gain on the investment. The principal_payment field gives the amount of capital being paid back to the user. It's value equals the principal invested multiplied by the call price.

    The investment.partial_repayment event is raised when the investment in question partially pays back early.

    Delivering events via the Webhook API

    Use webhooks to be notified about events that happen to a WiseAlpha account.

    To configure your webhook settings, you'll need to contact Contact Support and provide them with an endpoint or endpoints that webhook events should be sent to. We'll then provide you with a private key that should be used to validate that a given webhook delivery was made by WiseAlpha.

    For more information on this have a look at "Validate the Signature" section.

    /events/: Fetching events directly

    api = requests.get('$API_ROOT_URL/events/',
                       headers=headers)
    
    curl -s "$API_ROOT_URL/events/" \
         -H "Authorization: Token $API_KEY" | jq .
    

    Returns pagination object containing a list of events.

    {
      "count": 6,
      "next": null,
      "previous": null,
      "results": [
        {
          "id": "EVENT00000099",
          "created": "2017-11-29T17:48:59.786838Z",
          "event_type": "account.aml-check-passed",
          "data": {
              "user_profile": { ... }
            }
          }
        }
        ...
      ]
    }
    

    Available Methods:

    You can also fetch events directly by making a GET web request to the /events/ endpoint as shown.

    Validate the signature of an event

    When you register your endpoint you will be provided a private key, $WEBHOOK_KEY, that you can use to validate that a given webhook delivery was made by WiseAlpha. The signature will be present in the x-wisealpha-signature header.

    To calculate the expected signature, generated an HMAC SHA-256 digest on the request body using your private key and check it against the expected header.

    
    import json
    import binascii
    import hashlib
    import hmac
    import base64
    
    from sanic import Sanic
    from sanic.response import json
    
    app = Sanic()
    
    
    @app.route("/")
    async def home(request):
        return json({"hello": "world"})
    
    
    @app.route("/webhooks", methods=['POST', 'GET'])
    async def webhooks(request):
        try:
            signature = request.headers.get('x-wisealpha-signature', '')
            key_bytes = base64.b64decode('$WEBHOOK_KEY')
            calculated = base64.b64encode(hmac.new(key_bytes, request.body, digestmod=hashlib.sha256).digest()).decode(encoding='ascii')
            if signature == calculated:
                # Process request
                pass
        except Exception as ex:
            # Log exception, but swallow it and return 200 so the endpoint does not get disabled
            pass
        return json({"valid": signature == calculated})
    
    
    if __name__ == "__main__":
        app.run(host="0.0.0.0", port=9999)
    
    
    
    # No shell example - see the python example