NAV
DOCS
shell python
  • Introduction
  • General
  • OAuth
  • Products
  • Companies
  • Customer Profiles
  • User Onboarding
  • Accounts and Portfolio
  • Robowise Portfolios
  • Robowise Risk Profiles
  • Reporting
  • Trading on WiseAlpha
  • Markets
  • Request for Quotes (Investor)
  • Market Making
  • Peer to Peer Market
  • Events and Webhooks
  • WiseAlpha Services
  • 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.

    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.

    Ordering

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

    Will order the customer list in descending order of the date_joined field

    List endpoints will provide details on the fields that the returned data can be ordered on. Prefix a field with - to order by the field descending, e.g. -created will return the data by the created field in descending order.

    Filtering

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

    Will filter the customer by customers who's last name starts with bar and who's first name contains foo (both case insensitive)

    List endpoints will detail all the fields that support filtering and the lookups supported. A description of the lookups is given below. The filter string is formed by joining the field name and the lookup name with a __. E.g. filtering the last_name field to find last names beginning with bar (case insensitive) would be done by providing the query string argument last_name__istartswith=bar.

    Text field lookups

    Name Description
    exact Filter by exact matches
    iexact Filter by exact matches (case insensitive)
    contains Filter when the field contains the value
    icontains Filter when the field contains the value (case insensitive)
    startswith Filter when the field starts with the value
    istartswith Filter when the field starts with the value (case insensitive)
    endswith Filter when the field ends with the value
    iendswith Filter when the field ends with the value (case insensitive)

    Datetime field lookups

    Name Description
    gt Filter by records where the datetime is greater than
    gte Filter by records where the datetime is greater than or equal
    lt Filter by records where the datetime is less than
    lte Filter by records where the datetime is less than or equal
    exact Filter when the datetime matches

    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:

    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
    seniority One of not_specified, super_senior_secured, senior_secured, second_lien_secured, unsecured, unsecured_pik or unsecured_at1 String-Enum
    categories List of categories this product falls into. Array of Product Category objects
    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
    borrower The legal entity that issued the bond String
    amount_outstanding The total amount of the bond in issue Decimal
    coupon The annual interest rate paid Decimal
    coupon_string A description of the coupon. (e.g. 4.875, L+12.0, E+5.25) String
    coupon_type A human readable detailed description of the coupon type. (Fixed Rate, Floating Rate, PIK, PIK Toggle) 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? (Deprecated - use discounted_fee_rate instead) Boolean
    discounted_fee_rate The discounted fee rate for the product. Decimal
    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
    num_important_updates Number of important updates for product Integer
    access_restrictions List of access restrictions that apply to this product Access restrictions object
    first_added_to_market The date this product was first added to the WiseAlpha market Date
    last_added_to_market The date this product was last added to the WiseAlpha market Date

    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
    key_financials Key financial information, optionally returned with the company__key_financials expansion Key Financials object
    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

    Key Financials object

    Name Description Data Type
    data Table of key financial information for different years in markdown format String
    source The source of the financial information String

    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
    package_id The ID of this package String
    package_type One of: new-issue, primary-market String
    settlement_date The date on which the liquidity will be injected into the marketplace Date
    pending_amount The amount of principal that will be injected into the marketplace Decimal
    accrued_interest_rate The amount of accrued interest to pay per unit of principal in this package Decimal

    Product Category object

    Name Description Data Type
    category_id A unique ID for the category String
    label Text to display for the category String

    Product Access Restrictions

    This is a list of strings each of which represents a particular permission required to access this investment.

    Access Restriction Meaning
    high_yield You need to have answered the High Yield questionnaire to access this investment.
    perpetuals You need to be of a suitable investor type and have answered the Perpetuals questionnaire to access this investment.
    special_situations You need to be of a suitable investor type and have answered the Special Situations questionnaire to access this investment.

    Access to each of the above markets can be achieved by going through the appropriate authorisation process, setting investor type and answering questionnaires. Each user's current restrictions are detailed in the access_restrictions record in the Profile object.

    Pricing Summary Data

    Pricing summary data is generated with respect to a given pricing date. A pricing_date=YYYY-MM-DD can be passed in via a query string.

    Some products have no available pricing, in which case a single field error will be returned with the message Pricing not enabled for this product.

    Name Description Data Type
    initial_pricing_date The date where the pricing information starts Date
    pricing_date The pricing date the information is generated relative to Date
    at_pricing_date The price at the pricing date Decimal
    one_day_prior The price one day prior to the pricing date Decimal
    seven_days_prior The price seven days prior to the pricing date Decimal
    twentyeight_days_prior The price twenty eight days prior to the pricing date Decimal
    ninety_days_prior The price ninety days prior to the pricing date Decimal
    year_start The price at the year start 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,access_restrictions&for_user=me"
      -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",
                "seniority": "super_senior_secured",
                "categories": ["investment-grade"],
                "access_restrictions": [],
                "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",
                "borrower": "NMG Finco plc",
                "amount_outstanding": "370000000.00",
                "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,
                "num_important_updates": 2,
                "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
    category Filter to return products that fall into the given category. E.g., 'investment-grade'. 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.
    company__key_financials Return key financial information for the product's company.
    access_restrictions Return any market access restrictions that apply to this investment.

    The access_restrictions expansion supports an extra optional request parameter: for_user=<user ID> | 'me'. If for_user is set then the access restrictions returned apply to the given user. If the user has the necessary permission, that access restriction will not be included in the returned list.

    /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",
        "seniority": "super_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",
        "borrower": "NMG Finco plc",
        "amount_outstanding": "370000000.00",
        "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,
        "num_important_updates": 2,
        "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.
    company__key_financials Return key financial information for the product's company.
    access_restrictions Return any market access restrictions that apply to this investment.
    pricing_summary See Pricing Summary Data.

    The access_restrictions expansion supports an extra optional request parameter: for_user=<user ID> | 'me'. If for_user is set then the access restrictions returned apply to the given user. If the user has the necessary permission, that access restriction will not be included in the returned list.

    /products/{product_id}/pricing.{format}

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

    Available Methods

    Data is returned as either JSON:

    [
      {
        "date": "2019-08-06",
        "price": "102.5000"
      },
      {
        "date": "2019-08-07",
        "price": "102.7000"
      },
      {
        "date": "2019-08-07",
        "price": "102.5000"
      }
    ]
    
    

    Or CSV

    2019-08-06,102.5000
    2019-08-07,102.7000
    2019-08-08,102.5000
    

    /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

    Company Document Data Types

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

    Company Document object

    {
        "reference": "CFD00002095",
        "description": "2022 First Six Months Presentation",
        "link": "https://web-assets.wisealpha.com/media/company/files/220727115118/Q1_2022_Presentation.pdf",
        "order": 0,
        "document_type": "Generic"
    }
    
    Name Description Data Type
    reference Company Document reference Reference ID
    description Short description of the document String
    link URL for uploaded document String
    order Number representing display order Integer
    document_type Type of document (e.g. Generic, Prospetus) String-Enum

    List or upload company documents

    URL: /companies/{company_id}/documents/

    This endpoint is used to list and upload documents that are associated with a company. GET is available to ordinary user accounts, but only accounts with operations permissions can POST.

    Available Methods:

    Example GET request

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

    The above command returns JSON structured like this:

    {
        "count": 19,
        "next": null,
        "previous": null,
        "results": [
            {
                "reference": 2095,
                "description": "2022 First Six Months Presentation",
                "link": "https://web-assets.wisealpha.com/media/company/files/220727115118/Q1_2022_Presentation.pdf",
                "order": 0,
                "document_type": "Generic"
            },
            {
                "reference": 2096,
                "description": "2022 First Six Months Results",
                "link": "https://web-assets.wisealpha.com/media/company/files/220727115118/Q1_2022_Results.pdf",
                "order": 1,
                "document_type": "Generic"
            },
            {
                "reference": 1941,
                "description": "2021 Full Year Results",
                "link": "https://s3.eu-west-1.amazonaws.com/aggredium-prod-media/CompanyFiles/123456",
                "order": 2,
                "document_type": "Generic"
            },
            {
                "reference": 1942,
                "description": "Prospectus",
                "link": "https://web-assets.wisealpha.com/media/company/files/211111115902/Prospectus.pdf",
                "order": 3,
                "document_type": "Prospectus"
            },
            ...
        ]
    }
    

    Example POST request

    api = requests.post('$API_ROOT_URL/companies/CO00000001/documents/', 
                        data = {"description": "Test document description", "file_upload": FILE},
                        headers=headers)
    
    curl -s -X POST "$API_ROOT_URL/companies/CO00000001/documents/" \
        -H 'Authorization: Token $API_KEY' \
        -H 'Content-Type: application/json' \
        -d '{"description": "Test document description", "file_upload": FILE}' | jq .
    

    The above command returns a company document object.

    Get or change a company document

    URL: /companies/{company_id}/documents/{document_reference}

    This endpoint is used to retrieve, update or delete an uploaded document that is associated with a company. GET is available to ordinary user accounts, but only accounts with operations permissions can PATCH and DELETE.

    Available Methods:

    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":""
          }
       },
       "tax_residencies": [],
       "investor_type":null,
       "user_agreements": {
          "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,
       "access_restrictions": {
          "high_yield": {
             "investor_type": true,
             "questionnaire": false,
             "access_approved": false,
             "message": "message"
          },
          "perpetuals": {
             "investor_type": false,
             "questionnaire": false,
             "access_approved": false,
             "message": "message"
          },
          "special_situations": {
             "investor_type": false,
             "questionnaire": false,
             "access_approved": false,
             "message": "message"
          }
       },
       "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"
          },
          "sale_fee": "0.2500",
          "role": "investor",
          "account_locked": false
       }
    }
    
    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
    access_restrictions Details of any access restrictions that apply to this account Access restrictions object (Read Only)
    validation Details of the user's progress through the Onboarding process Validation object (Read Only)
    sale_fee The user's sale fee Decimal
    role The user's role String
    account_locked The user's account lock status Boolean

    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, access_restrictions, validation and account_locked are read-only fields, and cannot be updated by users.

    Investor type is set/updated using the /customers/{customer_id}/change_investor_type/ endpoint.

    Accounts can be unlocked using the /customers/{customer_id}/unlock-account/ 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",
    }
    
    Name Description Data Type
    account_name The name of the account owner String
    sort_code The sort code (or BIC) of the bank holding the account String
    account_number The account number (or IBAN) String

    Note that you should specify either sort code and account number or BIC and IBAN. Mixing the two types of bank identifiers is not supported.

    When read, we return a data blob with additional information.

    {
        "provided":true,
        "status":"verified",
        "last_error":"",
        "details": {
            "account_name": "FirstName LastName",
            "sort_code":"00-00-00",
            "account_number":"88668866",
        }
    }
    
    Name Description Data Type
    provided Whether bank account details have been provided Boolean
    status Whether the account details have been approved for use. One of unverified, verified, rejected, 'request-new' String
    last_error The reason the bank details were rejected, or new details requested. String
    details The bank details Object

    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

    Access restrictions object

    This object details the nature of each access restriction that applies to this user.

    For a user to gain access to an investment with a particular restriction, he must satisfy two criteria:

    This object outlines the user's progress in achieving these criteria.

       "access_restrictions": {
          "high_yield": {
             "investor_type": true,
             "questionnaire": false,
             "access_approved": false,
             "message": "message"
          },
          "perpetuals": {
             "investor_type": false,
             "questionnaire": false,
             "access_approved": false,
             "message": "message"
          },
          "special_situations": {
             "investor_type": false,
             "questionnaire": false,
             "access_approved": false,
             "message": "message"
          }
       },
    

    Each access restriction has the following fields:

    Name Description Data Type
    investor_type Is the user's investor type allowed to access these investments? Boolean
    questionnaire Has the user completed the necessary questionnaire for these investments? Boolean
    message A brief message describing what the user needs to do to access these investments String
    access_approved Has the user got access to these investments. Boolean

    Note that access_approved may be false even if the investor_type and questionnaire are true; in this case the user access permission is awaiting approval from a member of the WiseAlpha team.

    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:

    Supported Ordering Fields

    Field Name
    date_joined
    first_name
    last_name
    email

    Supported Filtering

    Field Name Support Lookups
    email All text lookups supported
    first_name All text lookups supported
    last_name All text lookups supported
    search This will filter by email__icontains, first_name__istartswith, last_name__istartswith or customer_id__icontains
    account_locked Valid lookups are account_locked=true and account_locked=false

    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,
          }
       }
    }
    
    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,
          }
       }
    }
    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: GET /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": {
            "MARKETING: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": {
            "MARKETING: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": {
            "MARKETING:NEW_BOND_AVAILABLE": { "ENABLED": "ON" }
        },
        "net_configuration": {
            "TRANSACTIONS_AND_PAYMENTS:BOND_PAYMENTS": { "ENABLED": "OFF" },
            "MARKETING:MARKETING": { "ENABLED": "OFF" },
            "MARKETING:NEW_BOND_AVAILABLE": { "ENABLED": "ON" },
            "MARKETING: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": {
            "MARKETING: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": {
            "MARKETING: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": {
            "MARKETING:NEW_BOND_AVAILABLE": { "ENABLED": "OFF" }
        },
        "net_configuration": {
            "TRANSACTIONS_AND_PAYMENTS:BOND_PAYMENTS": { "ENABLED": "ON" },
            "MARKETING:MARKETING": { "ENABLED": "ON" },
            "MARKETING:NEW_BOND_AVAILABLE": { "ENABLED": "OFF" },
            "MARKETING: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:

    Unlock a user's account

    URL: POST /customers/{customer_id}/unlock-account/

    Example POST request

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

    The above command returns JSON structured like this:

    {
       "detail": "User account successfully unlocked."
    }
    

    This endpoint is only available to accounts with the superuser, account_manager, or customer_service_agent role. Sending a request to this endpoint from any other role will result in a 403 error.

    This endpoint finds the account associated with the provided customer_id and unlocks the account by resetting any failed login attempts. A 404 error will be returned if no account is found.

    User Audit Log

    URL: GET /audit-logs/ URL: GET /audit-logs/{audit_log_record_id}/

    An audit log of user actions is available to be queried. This will contain a detailed list of the user's actions while using the platform, as well as some server side generated events for events like investment payments.

    Suported Formats

    Name Description
    json applicaiton/json, default
    csv text/csv

    Suported Ordering

    Name Description
    created Sort from oldest to newest.
    -created Sort from newest to oldest.

    Supported Filtering

    Name Supported Lookups
    time All datetime lookups supported
    user_id Exact match on user account_no
    event_type Exact match on event_type (multiple supported)
    action Exact match on action (multiple supported)
    platform Exact match on platform

    User Audit Log Object

    Name Description Data Type
    reference Audit Log entry reference Reference
    action Description of action String
    user_id The user the log relates to Customer ID
    time The time of the entry DateTime
    event_type The event_type that triggered the entry String-Enum
    platform The platform generating the user was using String-Enum
    os_name String
    os_version String
    ip IP Address
    language String
    event_properties Varies by event Object

    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.
    confirm-investor-type The user has previously selected an investor type, but needs to confirm that they still belong to that category.
    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
    accrued_service_fees The total service fees accrued but not yet 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
    total_gain The total amount gained from this investment. Decimal

    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
    reinvest_payments Should payments (e.g. coupon payments) be reinvested in the product. Boolean
    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

    FX Quote

    Name Description Data Type
    reference The quote's unique reference. Decimal
    created When the quote was created. DateTime
    sell_currency The currency that is being sold. String
    buy_currency The currency that is being bought. String
    sell_amount The amount of currency that will be sold. Decimal
    buy_amount The amount of currency that will be bought. Decimal
    fee_amount The fee for the trade, in sell_currency. Decimal
    fee_rate The fee rate the trade (in bps). Integer
    total_sell_cost The total cost of the sell, inclusive of the sell_amount and fee_amount. Decimal
    rate The fx rate. String
    state The state of the quote, one of transient, awaiting_confirmation, confirmed, errored or expired. String-Enum
    limits Information regarding personal or system wide FX limits if any. An array of FX Limits objects
    errors A list of errors that will stop the quote from being able to be confirmed. An FX Quote Error object
    suggested_buy_amount In the case of an FX Quote that cannot be filled due to a constraint on the amount able to buy or sell, the API will return a suggested buy_amount that can be used Decimal

    FX Limits

    Name Description Data Type
    user_limit The daily user FX limit, defined in GBP. The limit is shared across a user's investment accounts. Decimal
    user_limit_remaining The amount remaining from user_limit for the calling user. Resets at midnight in the Europe/London timezone. Decimal
    buy_max_liquidity The current maximum amount of liquidity available in the buy currency. Decimal
    sell_account_balance The currency sell account balance (in sell_currency).

    FX Quote Error

    Name Description Data Type
    error_type One of insufficient_sell_balance, insufficient_buy_liquidity, daily_limit_reached or trade_would_exceed_daily_limit. String-Enum

    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": [
        {
          "reference": "INVACC00000001",
          "account_type": "individual",
          "created": "2000-01-01T00:00:00Z",
          "currencies": ["GBP"],
          "is_closed": False
        }
      ]
    }
    

    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
    reference The reference ID for this account. Reference ID
    account_type The type of this investment account. String (see below)
    created When the account was created DateTime
    currencies The currencies currently active for this investment account Array of Strings
    is_closed Is the account open or closed Boolean

    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"
      ],
      "is_closed": False,
    }
    

    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.

    Field Description Type
    amount The date and time that the transaction occurred. Decimal
    customer_reference Optional, the reference to appear on the customers bank statement, this is limited to 12 characters. String

    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/$CURRENCY/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",
          "type_id": "FUNDING_PAYMENT"
        },
        {
          "created": "2019-05-10T04:11:07Z",
          "reference": "TRANS00999847",
          "balance": "80.00",
          "amount": "-20.00",
          "currency": "GBP",
          "description": "Withdrawal to registered bank account",
          "type": "Withdrawal",
          "type_id": "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 A description of the transaction type. String
    type_id The transaction type. String-Enum

    Optional Query Strings for GET

    Name Description Data Type
    from_date Filter to return only transactions dated after from_date, including transactions on from_date. Date string format: YYYY-MM-DD. E.g. ?from_date=2022-02-15 String
    to_date Filter to return only transactions dated before to_date, excluding transactions on to_date. Date string format: YYYY-MM-DD. E.g. ?to_date=2022-07-04 String

    The from_date and to_date query strings can be combined. E.g. ?from_date=2022-02-15&to_date=2022-07-04

    Common transaction types:

    Type ID Type Description
    FUNDING_PAYMENT Deposit via debit card User has deposited money in his account via debit card.
    BANK_TRANSFER_IN Deposit via bank transfer User has deposited money in his account via bank transfer.
    WITHDRAWAL Withdrawal User has withdrawn money from his account.
    BUY_PRINCIPAL Purchase: Principal User has purchased the principal for a bond
    BUY_INTEREST Purchase: Accrued interest User has purchased the accrued interest for a bond
    BUY_SETASIDE Buy setaside User has set aside money for the purchase of a bond
    SALE_PRINCIPAL Sale: Principal User has purchased the principal for a bond
    SALE_INTEREST Sale: Accrued Interest User has sold the accrued interest for a bond
    FEE_SERVICE_PAID Service Fee User has paid the service fee accumulated while holding the bond
    FEE_SALES_PAID Secondary Sales Fee User has paid the sales fee when selling a bond
    MARKETING_FEE_CREDIT_RECEIVED Fees credited Fees have been returned to the user as part of an incentive scheme
    INTEREST_PAYMENT_RECEIVED Payment of interest User has been paid a coupon
    CAPITAL_REPAYMENT_RECEIVED Repayment: Principal User has been paid the bond principal as part of a repayment
    INTEREST_REPAYMENT_RECEIVED Repayment: Interest User has been paid the final coupon as part of a repayment.
    ``

    Account Withdrawals

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

    To get a list of all the withdrawal requests made for 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/withdrawals/',
                       headers=headers)
    
    curl -s "$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/balances/GBP/withdrawals/" \
         -H "Authorization: Token $API_KEY" | jq .
    

    This returns a pagination object containing a list of withdrawal requests.

    {
      "count": 1,
      "next": null,
      "previous": null,
      "results": [
        {
          "created": "2019-05-10T01:55:36Z",
          "reference": "WR00999844",
          "state": "open",
          "amount": "100.00",
          "amount_currency": "GBP",
          "scheduled_on": null,
          "paid_on": null
        }
        ...
      ]
    }
    

    Available Methods:

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

    The fields in the transaction object are:

    Field Description Type
    created The date and time that the withdrawal was requested. DateTime
    reference A unique reference for this withdrawal. Reference ID
    state The state of the withdrawal. Decimal
    amount The amount of the withdrawal. Decimal
    currency The currency of the withdrawal. Currency
    scheduled_on The date and time that the withdrawal was issued from WiseAlpha's client money account. DateTime
    paid_on The date and time the transaction was verified in WiseAlpha's client money account transaction feed. DateTime

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

    An individual withdrawal can be queried by specifiying the withdrawal reference.

    Debit Notes

    GET /customers/{}/investment-accounts/{}/balances/{}/debit-notes/ GET /customers/{}/investment-accounts/{}/balances/{}/debit-notes/{}/

    To get a list of all the debit notes issued for 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/debit-notes/',
                       headers=headers)
    
    curl -s "$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/balances/GBP/debit-notes/" \
         -H "Authorization: Token $API_KEY" | jq .
    

    This returns a pagination object containing a list of debit-notes.

    {
      "count": 1,
      "next": null,
      "previous": null,
      "results": [
        {
          "created": "2019-05-10T01:55:36Z",
          "reference": "WR00999844",
          "state": "open",
          "amount": "100.00",
          "amount_currency": "GBP",
          "scheduled_on": null,
          "paid_on": null
        }
        ...
      ]
    }
    

    Available Methods:

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

    The fields in the transaction object are:

    Field Description Type
    created The date and time that the withdrawal was requested. DateTime
    reference A unique reference for this withdrawal. Reference ID
    state The state of the withdrawal. Decimal
    amount The amount of the withdrawal. Decimal
    currency The currency of the withdrawal. Currency
    scheduled_on The date and time that the withdrawal was issued from WiseAlpha's client money account. DateTime
    paid_on The date and time the transaction was verified in WiseAlpha's client money account transaction feed. DateTime

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

    An individual debit note can be queried by specifiying the debit note reference.

    FX Quotes

    URL: GET /customers/{}/investment-accounts/{}/fx-quotes/

    To return a list of all FX quotes generated for a given investment account:

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

    This method returns a list of all the FX Quotes generated for a given investment account.

    Create an FX Quote

    URL: POST /customers/{}/investment-accounts/{}/fx-quotes/

    To create an FX Quote, the below fields must be provided. The quote can be created in order to sell or buy a specific amount.

    Field Description Type
    sell_currency The currency to sell. Currency
    buy_currency The currency to buy. Currency
    sell_amount The amount to sell, if this field is specified, buy_amount should not be. Decimal
    buy_amount The amount to buy, if this field is specified, sell_amount should not be. Currency
    transient Optional, set to true to create an indicative quote to be used for display purpuses only, the quote will not exist on the server and cannot be confirmed. Boolean

    An FX Quote object will be returned as a result of the call. There are constraints that may prevent an FX Quote from being filled, either the user or the system may have reached a daily limit for trading. Most users will have a limit of GBP10,000 convertable in given day, with the period measured as the amount traded the 24 hours of the UK day.

    When a quote is submitted that can't be filled (e.g. not enough buy currency liquidity) the system will return a suggested_buy_amount that will be able to be traded.

    Confirm FX Quote

    URL: POST /customers/{}/investment-accounts/{}/fx-quotes/{}/confirm

    Confim an FX quote

    Use this method to confirm and executed a quote. If it can be filled it will execute and return the quote with the confirmed state, if not it will be returned with an error message explaining the reason why. E.g. the counterparty account may not currently have sufficient balance to complete the trade.

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

    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"
    

    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.

    Supported Ordering Fields

    Field Name
    created

    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,
             "my_bid":"100.0000",
             "market_price":"100.0000",
             "created":"2017-12-20T12:35:31.390342Z",
             "settlement_date": null
          },
          {
             "id":"MKTBUY00000002",
             "original_id":"MKTBUY00000002",
             "product_id":"INVMKT00000002",
             "type":"principal",
             "state":"pending_settlement",
             "currency":"GBP",
             "amount":"120.02",
             "principal":"200.00",
             "my_bid":"50.0125",
             "market_price":"50.0125",
             "created":"2017-12-20T12:35:31.403366Z",
             "settlement_date":"2017-12-25"
          }
       ]
    }
    

    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
    market_price The price per unit of principal to use for this purchase Decimal
    my_bid The price this order is seeking. If this is different from current_buy_price, the order will need to be confirmed Decimal
    created When this order was created DateTime
    settlement_date When this order settles (null if settlement is unknown) 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)
    pending_settlement The order has executed and will settle on settlement_date

    Optional Query Parameters

    Name Description Data Type
    currencies Filter to return only products in certain currencies. E.g. ?currencies=GBP,EUR String

    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",
             "my_ask":"50.0000",
             "market_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
    market_price The price per unit of principal to use for this purchase Decimal
    my_ask The price this order is seeking. If this is different from current_sell_price, the order will need to be confirmed 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.

    Optional Query Parameters

    Name Description Data Type
    currencies Filter to return only products in certain currencies. E.g. ?currencies=GBP,EUR String

    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 Portfolios

    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.

    The behaviour and description of robowise risk profiles in this section is centered around the risk profiles published and maintained by WiseAlpha. Concepts like robowise risk categories and robowise weightings are generally not used for custom profiles.

    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
    liquidity The current amount of liquidity available on the market for the bond. 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_behaviour 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

    Robowise Withdrawal Request

    Field Description Type
    created The date and time that the robowise withdrawal was requested. DateTime
    closed_on The date and time that the robowise withdrawal was either completed or cancelled. DateTime
    reference A unique reference for this robowise withdrawal request. Reference ID
    state One of queued, processing, completedor cancelled String-Enum
    amount_requested The target for the withdrawal. Decimal
    amount_processed The amount currently processed for the withdrawal. Decimal
    on_complete The action to take on complete if any. Object

    Robowise Rebalance

    Field Description Type
    created_by_schedule The schedule that triggered this rebalance. Reference ID
    created_by_user The use that triggered this rebalance. Minimal User Data Type
    created_on The date and time this rebalance was created. DateTime
    executed_on The date and time this rebalance was executed. DateTime

    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 can be transferred from the parent account, or directly deposited by using the account fund on the parent with the route_to set to the child account id.

    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

    There are two ways to withdraw cash from a robowise portfolio. You can directly set the current withdrawal behaviour to withdraw some or all of the value, or you can issue robowise withdrawal requests. These will executed in sequence and will set the withdrawal behaviour as needed.

    Managing the withdrawal behaviour manually

    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_behaviour 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.

    Issuing a Robowise Withdrawal Request

    A request to withdraw cash from a robowise portfolio can be issued, this is similar to managing the withdrawal behaviour manually, but with a few important differences. You can issue several requests which will be executed in the order in which they are received. Only one request will be active at a given time and will remain active until the cash target for the withdrawal is achieved. An event will be generated when a given withdrawal request completes.

    As an extra convenience you can instruct a withdrawal request to create a regular withdrawal request once it has completed. A robowise withdrawal request will move money from the robowise account to the holding account, and a regular withdrawal request will then move money from the holding account to the customer's registered bank account.

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

    data = {
        "amount": "100.00",
    }
    api = requests.post('$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/robowise/$ROBOWISE_ACCOUNT_ID/withdrawals/',
                        data=data, headers=headers)
    
    Field Description Type
    amount The amount to transfer from the parent account to the robowise account. Decimal
    on_complete Optional field, it provides a mechanism for chaining a cash withdrawal from the top level account to the users registered bank account. Object - see below

    The below is the only currently supported on_complete action

    Field Description Type
    action Currently only withdraw_funds. String-Enum
    customer_reference Only valid when the action is withdraw_funds. String

    Listing Robowise Withdrawal Requests

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

    api = requests.get('$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/robowise/$ROBOWISE_ACCOUNT_ID/withdrawals/',
                       headers=headers)
    

    A paged list of Robowise Withdrawal Request objects will be returned.

    Updating a Robowise Withdrawal Request

    URL: PATCH /customers/{}/investment-accounts/{}/robowise/{}/withdrawals/{}/

    Once a withdrawal request has been issued it can be cancelled if it's not already completed. Only the state field can be updated and only to the cancelled state.

    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.

    Robowise Portfolio Rebalances

    List rebalances: URL: GET /customers/{}/investment-accounts/{}/robowise/{}/rebalances/
    Get rebalance: URL: GET /customers/{}/investment-accounts/{}/robowise/{}/rebalances/{}/
    Issue a rebalance: URL: POST /customers/{}/investment-accounts/{}/robowise/{}/rebalances/

    # Create a manual rebalance
    data = {}
    api = requests.post('$API_ROOT_URL/customers/$CUSTOMER_ID/investment-accounts/$INVESTMENT_ACCOUNT_ID/robowise/$ROBOWISE_ACCOUNT_ID/rebalances/',
                        data=data, headers=headers)
    

    If the portfolio is set to use a risk profile with a rebalance set to schedule or manual then a log all rebalances can be retrieved through these URLs. Continously rebalanced portfolios do not have rebalance logs.

    See the Robowise Rebalance data type.

    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.

    Robowise Risk Profiles

    Customised risk profiles can be configured to create automated portfolios for your investors. Free cash in a portfolio will be invested according to the rules set-up in it's assigned risk-profile. Robowise portfolios can have additional modifiers as explained in Robowise Profile Modifiers.

    Risk profiles can be private to an account manager, or shared within an organization.

    Capital Allocation and Rebalancing

    Robowise has two core concepts - capital allocation and rebalancing. A robowise portfolio will have a set of candidate products that it can invest in based on the risk profile and portfolio profile modifiers. The candidate products will have a weighting assgined. The most straightforward example of this is when a risk profile is set-up with a fixed set of products with fixed weightings per product.

    The weighting corresponds to the percentage porfolio value the robowise portfolio should attempt to hold. It's important to note that this is portfolio value rather than notional, with portfolio value being notional * price + accrued.

    Allocation Types

    A risk profile can have the below values for allocation_type.

    Name Description
    strict Do not overallocate.
    flexible_to_max_holding If some products are not available then re-allocate the funds in other products up to the max_holding limit defined in the risk profile.

    Initial Fund Allocation

    When cash is made available to a portfolio an ideal holding will be created based on the current set and weighting of candidate products.

    In strict allocation mode a buy will be created for each product matching that ideal value. If a product is not tradeable (e.g. it has repaid) then the cash will be held uninvested. It's also possible to hold cash in a porfolio by assigned weightings that sum up to less than 1.

    In flexible allocation mode the portfolio will try and spend all the cash available. If a product is unavailable, whether due to a lack of liquidity in the market or because it's not tradeable, then the cash that would have been invested in that product is allocated to the other products in the portfolio. The total invested in a single product is still governed by the percentage set in the max_holding limit defined in the portfolio.

    Rebalancing

    A risk profile can have the below values for rebalance_method

    Name Description
    continuous The portfolio will be continously rebalanced.
    manual Rebalancing is only triggered manually.
    schedule Reblancing runs on a schedule.

    Product Sets

    A risk profile can have the below values for product_set. This parameter controls how the list of candidate products for a porfolio is generated.

    Name Description
    wisealpha_risk_category Use a weighted porfolio based on WiseAlpha's risk categories. If this is set the weightings must be provided.
    fixed Use a fixed product set.

    Weighting Methods

    A risk profile can have the below values for weighting_method. This parameter controls how a portfolio calculates the ideal holding of the various available candidate products in a given portfolio.

    Name Description
    wisealpha_risk_category Use the weightings parameter to define the percentage of each of WiseAlpha's risk categories to hold.
    flat The weighting is calculated as 1/(number of candidate products).
    set_per_product The weighting is defined per product by the portfolio manager.

    Risk Profile APIs

    e

    An example of creating a new risk profile and the data returned

    # Create a new risk profile
    data = {
        "label": "Example Policy",
        "currency": "GBP",
        "allocation_type": "strict",
        "weighting_method": "set_per_product",
        "product_set": "fixed",
        "fixed_products": [{
            "product_reference":  "INVMKT00000196",
            "weighting":  "0.5"
        }],
        "perpetuals_enabled": true
    }
    api = requests.post('$API_ROOT_URL/robowise/risk-profiles/', data=data, headers=headers)
    
    {
        "reference": "RWRP00000009",
        "label": "Example Policy",
        "projected_return": "3.06",
        "weightings": {},
        "attributes": {
            "candidate_loans": [
                {
                    "product_id": "INVMKT00000196",
                    "company_id": "CO00000138",
                    "risk_category": "medium",
                    "coupon": "3.7400",
                    "weight": "0.50000000",
                    "liquidity": "4088.9800",
                    "yield": "6.1160"
                }
            ],
            "calculated_yield": 3.06,
            "bond_count": 1
        },
        "description": null,
        "account_manager": null,
        "weighting_method": "set_per_product",
        "product_set": "fixed",
        "fixed_product_ids": [
            "INVMKT00000196"
        ],
        "created_by": {
            "email": "andrew@wisealpha.com",
            "first_name": "Andrew",
            "last_name": "Barrett",
            "staff_id": "10006249"
        },
        "created_on": "2024-03-11T03:11:26.069507Z",
        "updated_by": {
            "email": "andrew@wisealpha.com",
            "first_name": "Andrew",
            "last_name": "Barrett",
            "staff_id": "10006249"
        },
        "updated_on": "2024-03-11T03:11:26.069520Z",
        "currency": "GBP",
        "perpetuals_enabled": true,
        "fixed_products": [
            {
                "product_reference": "INVMKT00000196",
                "weighting": "0.5000"
            }
        ],
        "rebalance_method": "continuous",
        "allocation_type": "strict"
    }
    

    List Risk Profiles: URL: GET /robowise/risk-profiles/
    Create Risk Profile: URL: POST /robowise/risk-profiles/
    Retrieve Risk Profile: URL: GET /robowise/risk-profiles/{}/
    Update Risk Profile: URL: PUT/POST /robowise/risk-profiles/{}/
    Delete Risk Profile: URL: DELETE /robowise/risk-profiles/{}/

    Robowise Risk Profile Data Type

    Name Description Data Type
    reference Risk profile reference. Reference ID
    account_manager This will be null if it's a shared profile, or owner if it is not. User Info Type
    description Optional description. String
    label The label displayed in the UX. String
    projected_return The current projected return for a ideally balanced portfolio using this profile. Decimal
    rebalance_method See Rebalancing. String-Enum
    allocation_type See Allocation Types. String-Enum
    product_set See Product Sets. String-Enum
    fixed_product_ids Deprecated - see fixed_products instead. Array of Product IDs
    fixed_products See Fixed Product Data Type. Array of Fixed Product Data Types
    weighting_method See Weighting Methods. String-Enum
    currency The currency of the portfolio. Currency
    perpetuals_enabled True if the portfolio should hold perps - this setting will take precendence over products defined in a fixed product set. Boolean

    Fixed Product Data Type

    Name Description Data Type
    product_reference Product ID. Product ID
    weighting The ideal weighting of this product in a portfolio, based on portfolio value. Decimal

    Rebalance Schedule APIs

    An example of setting a schedule

    # Create a new risk profile
    data = {
        "epoch": "2024-02-11T09:00:00Z",
        "schedule_frequency": "monthly"
    }
    
    api = requests.put('$API_ROOT_URL/robowise/risk-profiles/$RISK_PROFILE_ID/schedule/', data=data, headers=headers)
    
    {
        "epoch": "2024-02-11T09:00:00Z",
        "updated_on": "2024-03-11T03:19:51.430960Z",
        "updated_by": {
            "email": "andrew@wisealpha.com",
            "first_name": "Andrew",
            "last_name": "Barrett",
            "staff_id": "10006249"
        },
        "schedule_frequency": "monthly",
        "should_run_next_at": "2024-03-11T09:00:00Z",
        "weekdays": null
    }
    

    Retrieve Rebalance Schedule: URL: GET /robowise/risk-profiles/{}/schedule/
    Set Rebalance Schedule: URL: PUT /robowise/risk-profiles/{}/schedule/

    Schedules are set relative to an epoch. E.g. setting up a weekly schedule with an epoch of 2024-02-11T09:00:00Z and weekdays of ['mon', 'wed'] will create a portfolio rebalance weekly at 9am UTC every Monday and Wednesday following the epoch date.

    Monthly schedules are set to repeat monthly relative to the date set in the epoch. If the epoch date is set after the 28th and the following month ends before the date set it will occur on the final day of the month.

    If no schedule is set a 404 will be returned.

    Rebalance Schedule Data Type

    Name Description Data Type
    epoch The start date and time for the schedule. Datetime
    updated The date and time of the last schedule update. Datetime
    updated_by The user who last updated the schedule. User Details
    should_run_next_at The next time the schedule should fire. Datetime
    schedule_frequency One of monthly or weekly. String-Enum
    weekdays Only valid for weekly, an array of weekdays, e.g. ['mon', 'wed']. Array of weekday String-Enums

    Manual trigger API

    # Rebalance all associated active profiles
    data = {}
    api = requests.post('$API_ROOT_URL/robowise/risk-profiles/$RISK_PROFILE_ID/rebalance/',
                        data=data, headers=headers)
    

    Trigger a rebalance for all portfolios: URL: POST /robowise/risk-profiles/{}/rebalance/

    This API is used to trigger a manual rebalance of all active portfolios under a risk profile. To rebalance a single portfolio see the Robowise Portfolio Rebalances API documentation.

    Rebalance Log

    List Rebalances: URL: GET /robowise/risk-profiles/{}/rebalances/
    Get Rebalance: URL: GET /robowise/risk-profiles/{}/rebalances/{}/

    Rebalance Log Data Type

    Name Description Data Type
    created_by_schedule The schedule reference if the rebalance was created via a schedule. Reference
    created_by_user If manually created the user who triggered the rebalance. User Details

    Rebalance Results Data Type

    Name Description Data Type
    executed The number of robowise portfolios who have been rebalanced as a result of this rebalance. Integer
    schedule The number of robowise portfolios who are still scheduled to be rebalanced as a result of this rebalance. Integer

    Available Expansions

    Name Description
    results Returns the rebalance results

    Supported Ordering Fields

    Field Name
    created_on

    Reporting

    Report Execution

    Reports by default are generated asynchronously and are available to download for a period of 24 hours after generation. A webhook event will be fired when the report is available for download and the report-runs endpoint can be polled to check for report completion.

    Some reports can be asked to be generated synchronously, in this case the report content will be returned as part of the call and not stored for download later.

    Reporting Data Types

    Report Run object

    Name Description Data Type
    reference A unique reference for the report run. Reference
    created The time the report run was created String-Enum
    status One of pending, completed or failed String-Enum
    report_type See Report Types below String-Enum
    report_generation One of synchronous or asynchronous String-Enum
    report_format See Report Formats below String-Enum
    report_args The arguments for the report, for the supported arguments on a given report type, see the section for the specific report below Dictionary
    content Only included in a response to a synchrous report run creation request, will contain the report data. Object

    Report Types

    The following reports are offered over the API

    Name Tag Description
    Account Statement account_statement A report showing a detailed account statement.
    Bond Investment Detail bond_investment_detail A report that will show all investment transactions for a given bond. Available as csv, json and pdf.
    Portfolio Value Report portfolio_report A report that will show the porfolio value. Available as csv, json and pdf.
    Returns Report returns_report 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
    Income Statement income_statement A report that provides income and capital gains information to assist with tax reporting. Replaces the Tax Report. Available as pdf.
    Tax Report (deprectated) tax_report A report to help tax reporting. Available as pdf.

    Account Statement Report

    {
            "report_type": "account_statement",
            "report_format": "csv",
            "report_generation": "asynchronous",
            "report_args": {
                "investment_account_reference": "INVACC00001786",
                "from_date": "2020-01-01",
                "until_date": "2022-01-01",
                "currency": "GBP"
            }
    }
    

    Available as csv and pdf.

    The report arguments are

    Name Description Data Type
    investment_account_reference The investment account to generate the report for. (required) Reference
    currency The currency to generate the report for. (required) Reference
    from_date The date from which to generated data for (inclusive of date). (optional) Reference
    until_date The date until which to generate data for (exclusive of date). (optional) Reference

    Bond Investment Detail Report

    {
            "report_type": "bond_investment_detail",
            "report_format": "json",
            "report_generation": "synchronous",
            "report_args": {
                "investment_account_reference": "INVACC00001786",
                "from_date": "2020-01-01",
                "until_date": "2022-01-01",
                "product": "INVMKT00000160"
            }
    }
    
    {
            "report_type": "bond_investment_detail",
            "report_format": "csv",
            "report_generation": "asynchronous",
            "report_args": {
                "investment_account_reference": "INVACC00001786",
                "from_date": "2020-01-01",
                "until_date": "2022-01-01",
                "product": "INVMKT00000160"
            }
    }
    

    This report supports synchronous generation for json. Available as json, csv and pdf.

    The report arguments are

    Name Description Data Type
    investment_account_reference The investment account to generate the report for. (required) Reference
    product The product reference to generate the report for. (required) Reference
    from_date The date from which to generated data for (inclusive of date). (optional) Reference
    until_date The date until which to generate data for (exclusive of date). (optional) Reference

    Portfolio Value Report

    {
        "report_type": "portfolio_report",
        "report_format": "csv",
        "report_args": {
            "investment_account_reference": "INVACC00001786",
            "currency": "GBP",
            "pricing_date": "2022-01-01"
        }
    }
    

    The report arguments are

    Name Description Data Type
    investment_account_reference The investment account to generate the report for. (required) Reference
    currency The currency to generate the report for. (required) Currency
    pricing_date The date to generate the report for. (optional) Currency

    Available as csv.

    Returns Report

    {
        "report_type": "returns_report",
        "report_format": "csv",
        "report_args": {
            "investment_account_reference": "INVACC00001786",
            "currency": "GBP"
        }
    }
    

    The report arguments are

    Name Description Data Type
    investment_account_reference The investment account to generate the report for. (required) Reference
    currency The currency to generate the report for. (required) Currency

    Available as csv.

    Income Statement

    {
        "report_type": "income_statement",
        "report_format": "pdf",
        "report_args": {
            "investment_account_reference": "INVACC001786",
            "currency": "GBP",
            "from_date": "2020-01-01",
            "until_date": "2022-01-01",
        }
    }
    

    Available as pdf.

    The report arguments are

    Name Description Data Type
    investment_account_reference The investment account to generate the report for. (required) Reference
    currency The currency to generate the report for. (required) Reference
    from_date The date from which to generate data for (inclusive of date). (optional) Reference
    until_date The date until which to generate data for (exclusive of date). (optional) Reference

    Tax Report (deprecated)

    {
            "report_type": "tax_report",
            "report_format": "pdf",
            "report_generation": "asynchronous",
            "report_args": {
                "investment_account_reference": "INVACC00001786",
                "from_date": "2020-01-01",
                "until_date": "2022-01-01",
                "currency": "GBP"
            }
    }
    

    Available as pdf.

    The report arguments are

    Name Description Data Type
    investment_account_reference The investment account to generate the report for. (required) Reference
    currency The currency to generate the report for. (required) Reference
    from_date The date from which to generate data for (inclusive of date). (optional) Reference
    until_date The date until which to generate data for (exclusive of date). (optional) Reference

    Report Formats

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

    Name Format Description
    CSV csv Comma seperated values text/csv
    PDF pdf Portable Document Format (PDF) application/pdf
    JSON json Javascript Object Notation (JSON) application/json
    XLSX xlsx Excel spreadsheet application/xlsx

    Report Runs

    List Report Runs: URL: GET /reporting/report-runs/
    Get a Report Run: URL: GET /reporting/report-runs/{}/
    Create a Report Run: URL: POST /reporting/report-runs/

    Report generation is scheduled by creating a report run object. Some report_type and report_format combinations support synchronous generation of the report content where the report will be returned as part of the call to create. Asynchronous reports will be generated after the report run is created and an event will be fired when the report is finished, or the report status can be polled waiting for the report_status to turn to completed. Once a report is in the completed state it will be available to download for 24 hours.

    See the Report Type documentation for details on the report arguments required to generate each report type.

    Supported Ordering

    Name Description
    created Sort from oldest to newest.
    -created Sort from newest to oldest.

    Supported Filtering

    Name Description
    report_generation Filter by asynchronous or asynchronous.

    Downloading report runs

    URL: GET /reporting/report-runs/{}/download/

    If the report run status is set to completed it will be available to be downloaded for a period of 24 hours from the download URL.

    Trading on WiseAlpha

    WiseAlpha supports different execution models depending on the underlaying market being traded on. Peer to peer orders are created via the /market/ endpoint and request for quotes (RFQs) from market makers can be created on the /rfq/ endpoint. The /markets/ endpoint will list all made markets that can be traded on by the caller.

    RFQ Flow

    In a RFQ based market, investors (or someone working on their behalf) will issue RFQs to get quotes for purchasing products. Any market makers operating in the market can respond with a quote. The issuer of the RFQ can then confirm any of the return quotes. On confirmation of a quote an order is created. Orders are then executed by the market process. Settlement depends on the market, with near instant settlement supported.

    Market makers can run in auto quote or manual quote mode, or a mixture of both.

    Manual Quote Flow

    If operating with manual quotes, a market maker will be notified when there is a new RFQ available to be quoted on. The market maker can then respond to the RFQ with a Quote if they want to.

    Auto Quote Flow

    If operating with automatic quotes, the system will generate a quote from the market maker in response to an RFQ based on the pricing the market maker has loaded into the system. This can be controlled with further settings including how to respond with limited inventory etc.

    Peer to Peer Flow

    In the peer to peer market, investor buys and sells are matched and executed. Orders are split as needed during the matching process. Trading happens at a fixed market price, with the prices marked daily.

    Markets

    WiseAlpha supports multiple markets where investors issue RFQs and Market Makers respond to them.

    Overview

    Managed markets in WiseAlpha consist of one or more Market Makers responding to Request for Quotes (RFQs) from investors looking to invest in a given product.

    Market Makers can be set-up to auto-respond to a RFQs with a given bid/offer price or can respond with a price via the API in response to a new RFQ being posted. Each new RFQ will trigger an event that can be received via a webhook if set-up, or new RFQs can be polled for.

    Markets

    URL: GET /markets/
    URL: GET /markets/{market-reference}/

    Name Description Data Type
    reference Market reference Reference
    state One of open, suspended String-Enum
    timezone Market timezone String
    name Market name String
    description Market description String

    A market in WiseAlpha is an exchange where listed products can be bought and sold. Each market in WiseAlpha can be configured with open hours and market holidays. A market may also be suspended during trading hours if needed. Fractionalised products bought on one market must be sold back to the same market.

    Market settings

    URL: GET /markets/{market-reference}/settings/
    URL: GET /markets/{market-reference}/settings/{setting-name}/
    URL: PUT /markets/{market-reference}/settings/{setting-name}/

    The following settings are retrievable and updatable depending on permissions. Market settings give a way of controlling various attributes of a market, e.g. min/max order sizes and min holdings.

    Name Description Value Data Type
    opening_hours The market opening days and hours Array of opening hours objects
    minimum_order_sizes The minimum order sizes by currency Currency value dictionary
    maximum_order_sizes The maximum order sizes by currency Currency value dictionary
    minimum_holdings The minimum holding by currency Currency value dictionary
    default_rfq_ttl The default RFQ time to live in seconds Integer
    fixed_fx_rates Any fixed FX rates for the market Array of fixed FX rates

    Opening Hours Data Type

    Name Description Data Type
    day Day of the week, one of mon, tue, wed, thu, fri, sat or sun. String-Enum
    opens The time the market opens. Time
    closes The time the market closes. Time

    Fixed FX Rate Data Type

    Name Description Data Type
    currency_from Currency to convert from. Currency
    currency_to Currency to convert to. Currency
    rate The fixed fx rate. Decimal

    Restricted market settings

    URL: GET /markets/{market-reference}/restricted-settings/
    URL: GET /markets/{market-reference}/restricted-settings/{setting-name}/
    URL: PUT /markets/{market-reference}/restricted-settings/{setting-name}/

    The following settings are retrievable and updatable depending on permissions. The bid/ask fee are built on-top of the price a market maker charges and are payable to the market entity.

    Name Description Value Data Type
    bid_fee The market bid fee Decimal
    ask_fee The market ask fee Decimal

    Market state change requests

    URL: GET /markets/{market-reference}/state-change-requests/
    URL: GET /markets/{market-reference}/state-change-requests/{reference}/
    URL: POST /markets/{market-reference}/state-change-requests/

    {
        "reference": "MKTST00000001",
        "created": "2023-01-16T22:30:15.764267Z",
        "created_by": {
            "email": "andrew@wisealpha.com",
            "first_name": "Andrew",
            "last_name": "Barrett",
            "is_active": true,
            "staff_id": "10000003",
            "date_joined": "2022-11-15T02:56:03.279799Z",
            "role": "superuser"
        },
        "previous_state": "open",
        "requested_state": "suspended"
    }
    

    The state of the market can be updated by creating a new market state change request. Previous requests can be read through the API.

    To create a new state change request, post the requested state.

    Name Description Data Type
    requested_state As per the market state values. String-Enum

    Supported Ordering Fields

    Field Name
    created
    -created

    Holidays

    URL: GET /calendar/CAL00000005/holidays/
    URL: POST /calendar/CAL00000005/holidays/
    URL: PATCH/PUT/DELETE /calendar/CAL00000005/holidays/{}/

    Manage market holidays through the above URLs. A market holiday object is as follows:

    Field Description Type
    date The date of the holiday. Date
    calendar_name The name of the calendar the holiday belongs to. String
    description The description of the holiday. String

    Supported Filtering

    Field Name Support Lookups
    date All date lookups supported

    Supported Ordering Fields

    Field Name
    created
    -created
    date
    -date

    Request for Quotes (Investor)

    RFQ Endpoints

    To return a list of all RFQs generated for a given investment account:

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

    List RFQs URL: GET /customers/{}/investment-accounts/{}/rfqs/
    Retrieve RFQ URL: GET /customers/{}/investment-accounts/{}/rfqs/{}/
    Create an RFQ URL: POST /customers/{}/investment-accounts/{}/rfqs/

    This method returns a list of all the RFQs generated for a given investment account.

    Available Filters

    Name Description
    status One of expired or open
    expires See Datetime field lookups
    created See Datetime field lookups

    Supported Ordering Fields

    Field Name
    created
    expires

    RFQ Object

    Field Description Type
    reference The RFQ reference Reference
    created When the RFQ was created Datetime
    expires When the RFQ expires Datetime
    notional_amount The notional amount to quote on Decimal
    notional_currency The currency of the product Currency
    product_id The product to trade Reference
    market_reference The market to trade in Reference
    investment_account_reference The investment account issuing the RFQ Reference
    quote_type Either buy to indicate the RFQ is to buy a product or sell to indicate the RFQ is to sell a product. String-Enum
    allow_partial_fulfilment Set to true to allow the request to be partially filled, false if the whole quote is to be filled in a single trade. In the case of partial fulfilment the market must also support partial fulfilment. Boolean
    warnings Only present when issuing a transient RFQ, will return an array of any problems with the RFQ data Array of Strings

    Available Expansions

    Name Description
    quotes If called by an investor or account manager it will return all the Quotes available for the RFQ. If called by a market maker it will return only the Quotes issued by the caller
    customer_details Will return information about the investor issuing the RFQ
    related_account_balance Only valid when called by an investor's account manager, it will return the account balance of the investor issuing the RFQ
    bond Will return information about the product the RFQ references.
    inventory Only valid when called by a market maker, it will return the current notional held by the market maker for the product the RFQ calls for

    Quote Object

    Field Description Type
    reference The Quote reference Reference
    rfq_reference The RFQ reference Reference
    market_maker_reference The market maker reference Reference
    created When the Quote was created Datetime
    expires When the Quote expires Datetime
    notional The notional amount of the quote Decimal
    price The price of the quote Decimal
    currency The currency of quote Currency
    cost_of_notional The cost of the notional Decimal
    cost_of_accrued The cost of the accrued Decimal
    total_cost The total cost of the quote Decimal

    Available Expansions

    Name Description
    confirmation A (Quote Confirmation)[#quote-confirmation-objec] object or null if the quote has not been confirmed
    market_maker_name The name of the market maker associated with the quote

    Quote Confirmation Object

    Field Description Type
    reference The Quote Confirmation reference Reference
    confirmed_on The time of confirmation Reference
    order_reference Either a sell order or buy order reference between on the quote type Reference

    Create a RFQ

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

    To create an RFQ, the below fields must be provided.

    Field Description Type
    notional_amount The notional amount Decimal
    notional_currency The product currency Currency
    quote_type Either buy to indicate the RFQ is to buy a product or sell to indicate the RFQ is to sell a product. String-Enum
    product_reference The Product Reference to quote for Reference
    market_reference The market to trade on, if this is left blank the investment account's default market will be used Reference
    allow_partial_fulfilment Set to true to allow the request to be partially filled, false if the whole quote is to be filled in a single trade. In the case of partial fulfilment the market must also support partial fulfilment. Boolean
    transient If true it will return any warnings associated with the creation of the RFQ as well as transient quote if there are market makers with auto-quoting turned on Boolean

    The RFQ will be returned. If there are any market makers set to auto-quote on the product then the quotes field will be expanded and the auto quotes returned.

    List RFQ Quotes

    URL: GET /customers/{}/investment-accounts/{}/rfqs/{}/quotes/

    Returns a page list of Quotes.

    Available Filters

    Name Description
    status One of expired or open
    expires See Datetime field lookups
    created See Datetime field lookups

    Supported Ordering Fields

    Field Name
    created
    expires

    Confirm Quote

    Confirm a Quote URL: POST /customers/{}/investment-accounts/{}/rfqs/{}/quotes/{}/confirm/

    To confirm a quote send a POST request to the quote's confirm endpoint. When a quote is confirmed either a buy or sell order will be created against the investor's investment account. After a quote is confirmed and the order created it will be executed by the market process and settled according to the market set-up.

    Market Making

    URL: GET /market-making/

    To get a list of all market making accounts the caller has permission to act for

    This API will return a list of all the market making accounts the caller has permission for. Each market making account is associated with the market the market making is trading in, and the investment account that holds the fractional bonds within WiseAlpha.

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

    Or to read details of a specific market maker account:

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

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

    {
       "count":1,
       "next":null,
       "previous":null,
       "results":[
          {
             "reference":"MKTM00000001",
             "market_reference":"MKT00000001",
             "investment_account_reference":"INVACC00000001",
             "name":"Market Maker One",
             "quote_expiry_in_seconds": 300,
          }
       ]
    }
    

    The following settings can be configured on a market maker

    Name Description Data Type
    quote_expiry_in_seconds The default quote expiry Integer
    default_execution_type One of auto, manual or not_trading String-Enum
    low_inventory_notification_threshold A threshold to notify about if the market maker's holding drops below Decimal
    rfq_notification_preference One of mute, notify_all or notify_if_price_set String-Enum
    require_fat_finger_check_in_csv_upload Indicates whether to subject CSV price uploads to a fat finger check Boolean
    fat_finger_threshold The threshold to trigger the fat finger check on Decimal

    Market Maker Pricing

    To get a list of all current prices (historical prices will not be returned)

    api = requests.get('$API_ROOT_URL/market-making/$MARKET_MAKER_REFERENCE/products/', headers=headers)
    

    Data return in the form

    {
       "count":1,
       "next":null,
       "previous":null,
       "results":[
          {
             "created": "2000-01-01T00:00:00Z",
             "product_id": "INVMKT00000001",
             "bid": "98.50",
             "ask": "100.50",
             "max_exposure": null,
             "execution_type": "auto"
          }
       ]
    }
    

    To get a specific product price

    api = requests.get('$API_ROOT_URL/market-making/$MARKET_MAKER_REFERENCE/products/$PRODUCT_ID/', headers=headers)
    

    List Prices: URL: GET /market-making/{}/products/
    Retrieve a Product Price: URL: GET /market-making/{}/products/{}/
    Set a price (via POST): URL: POST /market-making/{}/products/
    Set a price (via PATCH): URL: PATCH /market-making/{}/products/{}/

    Market makers can set prices on any product listed on the market.

    To set a new price you can POST to the list endpoint, or directly PATCH the product URL. In not provided the max_exposure will be set to null and the execution type will be the default exection type as configured on the market maker. It is possible to set only the bid or ask price and leave the other null.

    Setting prices via CSV

    Retrieve CSV template: URL: GET /market-making/{}/products/get-csv-template/
    Set prices via CSV: URL: POST /market-making/{}/products/set-prices/

    Prices can be set via CSV upload to the above endpoint as per the table below.

    Name Description Data Type
    price_data The CSV price file File
    unlisted_behavior One of unchanged or remove String-Enum
    confirmations Used if a fat finger check is configured on the market maker Array of Product IDs

    The unlisted_behaviour field controls what to do if a product is not present in the price list. If set to unchanged it will retain it's current pricing. If set to remove then any current pricing will be removed. The confirmations array is used in the case where a fat finger check is configured on the market maker. The fat finger check is an optional threshold set where if the price changes by more than the threshold the API will indicate that confirmation is required to set the price.

    The data returned is a pricing review array as per the table below.

    Name Description Data Type
    product_id The product ID. Product ID
    company_name Company name String
    company_logo A url pointing to a company logo String
    isin_code International Securities Identification Number String
    currency Product currency Currency
    maturity Product maturity Date
    yield_to_maturity YTM Decimal
    coupon_string Coupon Decimal
    previous_bid The bid befor update Decimal
    new_bid The bid after update Decimal
    previous_ask The ask before update Decimal
    new_ask The ask after update Decimal
    requires_confirmation Indicates whether the price update requires confirmation via the confirmations array. Boolean
    has_confirmed Indicaters whether the price update has been confirmed. Boolean

    Market Maker Product Data Type

    Name Description Data Type
    created The time the price was last updated. Datetime
    product_id The relevant product ID. Reference ID
    bid The bid price. Decimal
    ask The ask price. Decimal
    max_exposure Only used in the case of auto execution_type, will limit the notional held. Decimal
    execution_type One of manual, auto or not-trading. String-Enum

    RFQs

    To retrieve a list of all open RFQs available to be quoted

    api = requests.get('$API_ROOT_URL/market-making/$MARKET_MAKER_REFERENCE/rfqs/', headers=headers)
    

    Data return in the form

    {
       "count":1,
       "next":null,
       "previous":null,
       "results":[
          {
                "reference": "RFQ00000001",
                "created": "2022-07-25T09:30:00Z",
                "expires": "2022-07-25T09:33:00Z",
                "notional_amount": "10000.00",
                "notional_currency": "GBP",
                "product_id": "INVMKT00000001",
                "market_reference": "MKT00000001",
                "investment_account_reference": "INVACC00000001",
                "quote_type": "buy",
                "warnings": null,
                "allow_partial_fulfilment": false,
          }
       ]
    }
    

    List RFQs: URL: GET /market-making/{}/rfqs/
    Retrieve RFQ: URL: GET /market-making/{}/rfqs/{}/

    Available Filters

    Name Description
    status One of expired or open
    expires See Datetime field lookups
    created See Datetime field lookups

    Supported Ordering Fields

    Field Name
    created
    expires

    Quoting a RFQ

    URL: POST /market-making/{}/rfqs/{}/quote/

    Name Description Data Type
    notional_amount The notional amount to quote for Decimal
    price The price offered Decimal
    quote_expiry_in_seconds The TTL (time to live) for the quote in seconds Integer

    Quotes

    List Quotes: URL: GET /market-making/{}/quotes/
    Retrieve Quote: URL: GET /market-making/{}/quotes/{}/

    A market maker can retrieve the Quotes they have created.

    Available Filters

    Name Description
    status One of expired or open
    expires See Datetime field lookups
    created See Datetime field lookups

    Supported Ordering Fields

    Field Name
    created
    expires

    Peer to Peer Market

    On the WiseAlpha peer to peer market users directly trade with each other.

    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 secondary 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.
    investment.payment An investment has made a payment.
    investment.repayment An investment has been repaid.
    investment.partial_repayment An investment has been partially repaid.
    market-making.quote-confirmed A quote has been executed.
    market-making.quote-executed A quote has been confirmed.
    market-making.rfq-created An RFQ has been created and is available to be quoted.
    report-run.completed A report run has been completed and is available to be downloaded.
    robowise.closed A robowise account has been closed.
    robowise.withdrawal-complete A withdrawal of funds from a robowise sub-account to it's parent account has completed.
    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.

    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.

    The robowise.closed and robowise.withdrawal-complete events

    Field Description Type
    account-reference The account reference of the robowise account the event pertains to. String

    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.

    Supported Ordering Fields

    Field Name
    created

    Supported Filtering

    Field Name Support Lookups
    created All datetime lookups supported

    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
    

    WiseAlpha Services

    Services information can be viewed via the /services/ endpoint. A superuser can enable or disable services via a PATCH request.

    Displaying WiseAlpha services

    URL: GET /services/

    Returns a list of all service objects.

    URL: GET /services/{service_id}/

    Returns a service object identified by its service_id (e.g. GET /services/market/).

    Service object

    Name Description Data Type
    id Integer
    service_id String
    enabled Boolean
    last_cycle String
    description String
    time_to_alarm Integer
    sleep_time Integer

    Enabling/disabling services

    URL: PATCH /services/{service_id}/

    You must have superuser access to perform this action.

    A service can be enabled or disabled via a PATCH request (e.g. PATCH /services/market/) with a JSON object (e.g. {"enabled": "true"}.

    It is not currently possible to edit other service object fields via the API.