# Implementing instruments

The Upvest Investment API offers the endpoints `/instruments` and `instruments/:id` through which you can fetch the information about instruments available for trading or fractional trading. But you can also request information about prices of venues, etc.

All these endpoints are purely informative. There is nothing that a client can change.

This chapter guides you through the necessary steps to get you ready to work with the `/instruments` endpoint.

Important for your Implementation: As our API is asynchronous, using webhooks must be the foundation for your integration. You should leverage webhooks to drive all real-time, user-facing functionality. GET endpoints are fallbacks (e.g., for reconciliation purposes) and should not be used as the primary mechanism for retrieving data in your product. Building on polling-based GET calls instead of webhooks results in architectural limitations as your implementation scales.

## Prerequisites

Clients who wish to access the price data require a separate contract with an external data providing service partner, such as [*Infront*](https://www.infront.co/global/en.html). Clients who do not have this contract do not receive real-time prices.

Please note that our external partners may reserve time slots for their maintenance and minor service interruptions may therefore occur occasionally.

However, this contract is not required to retrieve the instruments or venues information.

- **Authentication scopes** — `instruments:read`
For more information, refer to [Authentication scopes](/products/omnibus/concepts/api_concepts/authentication/authentication_oauth#list-of-authentication-scopes).
- **Webhook handler ready** — Set up a webhook endpoint to receive instrument status change notifications.
  - Subscribe to [`INSTRUMENT.*`](/products/omnibus/guides/instruments/instruments_webhooks) events.
For more information, refer to [Implementing webhooks](/products/omnibus/getting_started/implementing_webhooks).
- **Setup caching to support price data** - Prepare a cache for price data responses on a per-instrument basis. You can provide faster response times and reduce potential latency by implementing a caching solution for the `/latest` and `/ohlc` price data endpoints. This approach also helps preserve a historical views for charting.


## 1. Listing instruments

To retrieve the list of available instruments, submit this request:

**GET** [`/instruments`](/api/instruments/list_instruments)

**Example response**

```json
{
  "meta": {
    "offset": 0,
    "limit": 100,
    "count": 1,
    "total_count": 10,
    "sort": "created_at",
    "order": "ASC"
  },
  "data": [
    {
      "id": "123e4567-e89b-12d3-a456-426614174000",
      "created_at": "2022-08-31T17:28:00.00Z",
      "updated_at": "2022-08-31T17:28:00.00Z",
      "isin": "DE0007664005",
      "wkn": "766400",
      "name": "Volkswagen (VW) St. Aktie.",
      "fractional_trading": true,
      "trading_status": "ACTIVE"
    }
  ]
}
```

| Parameter | Description | Example |
|  --- | --- | --- |
| `id` | The instrument's unique identifier. | 123e4567-e89b-12d3-a456-426614174000 |
| `created_at` | The date the instrument was created. | 2022-08-31T17:28:00.00Z |
| `updated_at` | The date the instrument was last updated. | 2022-08-31T17:28:00.00Z |
| `ìsin` | The instrument ISIN. | DE0007664005 |
| `wkn` | The instrument *Wertpapierkennnummer* | 766400 |
| `name` | The instrument name. | Volkswagen (VW) St. Aktie |
| `fractional_trading` | Is fractional trading is allowed? This data can also be changed during a trading day. | `TRUE` |
| `trading_status` | **Possible values**:  * `ACTIVE` - The instrument can be traded.  * `INACTIVE` - The instrument cannot be traded.**NOTE**An instrument can be set to `ACTIVE` again after it has been set to `INACTIVE`. | `ACTIVE` |


Upvest plans to extend the list of available trading statuses at instrument level to support corporate actions such as rights issues, tender offers and the delisting case described above. The following two additional statuses will be available soon:

* `BUY_ONLY`
* `SELL_ONLY`


If you want to retrieve a single instrument, you can specify its ID:

**GET** [`/instruments/{instrument_id}`](/api/instruments/retrieve_instrument)

**Example response**

```json
{
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "created_at": "2022-08-31T17:28:00.00Z",
  "updated_at": "2022-08-31T17:28:00.00Z",
  "isin": "DE0007664005",
  "wkn": "766400",
  "name": "Volkswagen (VW) St. Aktie.",
  "fractional_trading": true,
  "trading_status": "ACTIVE"
}
```

## 2. Get instrument venues

As the prices are linked to an exchange, a user must first be able to see at which venues prices are available and in which quality.

To retrieve the trading venues on which the instrument is traded and for which price data is available, proceed as follows:

**GET** [`/instruments/{instrument_id}/venues`](/api/price-data/retrieve_instrument_venues)

**Example response**

```json
{
  "data": [
    {
      "id": "20d6024b-2df4-41ae-8d42-62e4744e455b",
      "name": "Tradegate",
      "price_qualities": [
        "EOD",
        "REALTIME"
      ]
    }
  ]
}
```

## 3. Retrieving instruments prices

Once you have opted for a trading venue (how to find venues is described in the ['Get instruments venues'](/products/omnibus/guides/instruments/implementing_instruments#get-instrument-venues) step above), you can either retrieve

* [latest prices](/products/omnibus/guides/instruments/implementing_instruments#get-instrument-latest-prices) or
* [OHLC (Open-High-Low-Close) data](/products/omnibus/guides/instruments/implementing_instruments#get-instrument-OHLC-prices).


Please note that our external partners may reserve time slots for their maintenance and minor service interruptions may therefore occur occasionally.

### Get instrument latest prices

**GET** [`/instruments/{instrument_id}/venues/{venue_id}/prices/latest`](/api/price-data/retrieve_instrument_latest_price)

**Example response**

```json
{
  "price_quality": "REALTIME",
  "currency": "EUR",
  "bids": [
    {
      "time": "2023-01-09T13:02:15Z",
      "price": "210.01",
      "size": "100"
    }
  ],
  "asks": [
    {
      "time": "2023-01-09T13:02:15Z",
      "price": "212.32",
      "size": "50"
    }
  ],
  "last_trade": {
    "time": "2023-01-09T12:59:04Z",
    "price": "211.32",
    "size": "40"
  }
}
```

Cache responses to provide the best performance for end users and to help provide historical views for charting.

### Get instrument OHLC prices

**GET** [`/instruments/{instrument_id}/venues/{venue_id}/prices/ohlc`](/api/price-data/retrieve_instrument_prices_ohlc)

Price data requests are limited to 5,000 data points per each request. We recommend using multiple requests when calling the [Open/High/Low/Close (OHLC)](/api/price-data/retrieve_instrument_prices_ohlc) endpoint with a request that may exceed this limit.

You can use the following query parameters to narrow down the result:

| Query parameter | Description |
|  --- | --- |
| `start_date` | Returns OHLC prices from and including this date (UTC).If not specified, OHLC prices are returned from 30 days before the specified end date.  **Example**: `2020-08-21` |
| `end_date` | Returns OHLC prices from and including this date (UTC). If not specified, OHLC prices are returned up to yesterday.**Example**: `2020-08-21` |
| `adjusted_for` | Indication of the desired data adjustment. Prices are adjusted for corporate actions such as cash dividends and stock splits.**Possible values**:  - `NONE`  - `ALL` (default). |
| `interval` | Specification of the maximum length of the interval that each OHLC price tuple covers.  If a price did not change subsequent price tuples are omitted. **Possible values**:  - `1d` for daily prices (default)  - any positive integer followed by `h` (for hour) or `m` (for minute) respectively. Requests are limited to a maximum of 5000 data points. |


**Example response**

```json
{
  "data": [
    {
      "currency": "EUR",
      "time": "2023-01-09T00:00:00Z",
      "open": "213.32",
      "high": "215.32",
      "low": "210.32",
      "close": "213.22",
      "volume": "277973"
    },
    {
      "currency": "EUR",
      "time": "2023-01-10T00:00:00Z",
      "open": "214.42",
      "high": "214.42",
      "low": "213.22",
      "close": "213.22",
      "volume": "260335"
    }
  ],
  "meta": {
    "count": 2
  }
}
```

Cache responses to provide the best performance for end users and to help provide historical views for charting.

## Instruments status

The individual instrument status and configuration is the single source of truth for each instrument, which affects the following cases:

| Status | Description |
|  --- | --- |
| `FRACTIONAL_TRADING` | Only instruments with the attribute `fractional_trading=TRUE` can be executed as nominal orders. |
| `INACTIVE` | Orders that include instruments with an `INACTIVE` status will be rejected. It is possible to retrieve a list of inactive instruments by using this attribute (by default,  only  the currently activated instruments are listed when retrieving instruments). |


## Webhooks

Subscribe to [`INSTRUMENT.*`](/products/omnibus/guides/instruments/instruments_webhooks) events to receive real-time updates when instruments are onboarded, change trading status, or have their data updated. This removes the need to poll the API for instrument state changes.

For a full reference of instrument webhook events, refer to [Instrument webhook events](/products/omnibus/guides/instruments/instruments_webhooks).