Logo Sitagri

Sitagri API: AgriMarket documentation

This guide is designed to help you exploit the data extraction.

The API is RESTful and communicates over HTTP (and websockets). The responses bodies are formatted as JSON.

All examples will require basic knowledge of linux as well as following programs:

On a Debian-based system you can install them with the following commands (for npm install you need to have Node installed, see how):

root@computer:~# apt-get install curl jq
root@computer:~# npm install -g wscat

Please ensure cURL supports gzip too:

user@computer:~$ curl -V | grep libz -o >/dev/null && echo "OK" || echo "FAIL"

Table of Contents

For the authentication documentation please see Sitagri API documentation - Authentication.

Requirements

Please read the login documentation first as it describes all the technical requirements as well as the way to retrieve the session token (that will be used for X-Session-Token) and the market server URL that will be used everywhere further in this documentation.

Keep the application session alive

Like for the login session, your session will expire after a TTL (see below for the exact delay) if you are not making any request for a time.

If you do not send any request through websocket or HTTP request to the /api (being long polling, requesting data on a quote, requesting a price, requesting a news article, etc.), and still need the session to be kept alive (ex: the TTL is 60 seconds and you are making a request every 15 minutes) you'll need to regularly (we suggest 30 seconds before the TTL expiration) send a keep-alive request to https://market.financeagri.com/api/keepAlive with the following headers:

Example:

user@computer:~$ curl "https://market.financeagri.com/api/keepAlive" \
-H "Accept: application/json, text/*;q=0.2" \
-H "Accept-Charset: utf-8" \
-H "Accept-Encoding: gzip, deflate" \
-H "Access-Control-Request-Headers: x-session-token" \
-H "X-Session-Token: 85045E8E-CE68-2956-9E11-96F51837C71B" \
--compressed

This can be done with the websockets too, please refer to the websockets section for more information.

You can check the TTL with a request to https://market.financeagri.com/api/session. This will return a JSON formatted object similar to the one below:

{
    "code": "session",
    "token": "85045E8E-CE68-2956-9E11-96F51837C71B",
    "timeout": 120,
    "ttl": 900,
    "lang": "EN"
}

Fetch the data you need

Whether you want to fetch a specific item or the whole cache, you need to understand the structure of the API's data format. Please read the Agrimarket_Cache_Structure.pdf which will help you to understand how to build a specific request. Any response (if the HTTP code is between 200 and 300) will be a JSON formatted object.

To fetch an item from the API, you will make a HTTP request to the API URL containing a reference describing the item you want to retrieve. This URL is the concatenation of the agrimarket server URL (obtained from the previous section), the /api string and the reference of the item to retrieve. This means all subsequent URLs will be prefixed with with data.services.AgriMarketService.url/api.

The API has three main subsections:

Fetch the whole cache

Often when you need to retrieve a large quantity of data, as opposed to some specific items only, it is more efficient to retrieve the whole cache. Simply send a GET request (with the headers listed in the previous paragraph) to the API's root reference, data.services.AgriMarketService.url/api, to get the whole cache. You will then have to parse the output by yourself to retrieve any wanted item.

Example:

user@computer:~$ curl "https://market.financeagri.com/api" \
-H "Accept: application/json, text/*;q=0.2" \
-H "Accept-Charset: utf-8" \
-H "Accept-Encoding: gzip, deflate" \
-H "Access-Control-Request-Headers: x-session-token" \
-H "X-Session-Token: 85045E8E-CE68-2956-9E11-96F51837C71B" \
--compressed

If you only need some specific items, read the following sections to learn how to fetch them directly saving the bother of searching the whole cache.

Notice:

If you need to retrieve several items but not the whole cache, your best bet is a bi-directionnal connection using the websockets. Read the Establish a permanent connection (using websockets) section to learn more about it.

Fetch a market item

Any API URI describing a market item is prefixed by /market.

Fetch the market sources

The list of market sources is available through the reference /market/sources.

Notice:

The results are not expected to change, unless your access rights do (ex: subscribed to a new source). You probably don't need this request at all, once the development is done.

Example:

We simply append the reference /market/sources to the API's root URL.

user@computer:~$ curl "https://market.financeagri.com/api/market/sources" \
-H "Accept: application/json, text/*;q=0.2" \
-H "Accept-Charset: utf-8" \
-H "Accept-Encoding: gzip, deflate" \
-H "Access-Control-Request-Headers: x-session-token" \
-H "X-Session-Token: 85045E8E-CE68-2956-9E11-96F51837C71B" \
--compressed

This will return a JSON formatted object similar to the one below:

{
  "code": "sources",
  "data": [
    {
      "code": "EURONEX",
      "name": "/l10n/market/EURONEX_SRC",
      "desc": "/l10n/market/EURONEX_SRC_DESC",
      "rights": "REALTIME",
      "autoCurrency": false,
      "orderBook": true,
      "option": [
        "/market/sources/EURONEX/option/OBM",
        "/market/sources/EURONEX/option/OCO",
        "/market/sources/EURONEX/option/OMA",
        "/market/sources/EURONEX/option/OOB"
      ],
      "future": [
        "/market/sources/EURONEX/future/BMS",
        "/market/sources/EURONEX/future/EBM",
        "/market/sources/EURONEX/future/ECO",
        "/market/sources/EURONEX/future/EMA",
        "/market/sources/EURONEX/future/EOB",
        "/market/sources/EURONEX/future/EPL"
      ]
    }
  ]
}

The data property is an array of available market sources. Each item of this array is an object with the following properties:

With the previous request we saw how to get the list of future classes/option classes/single quotes/cash quotes/cross-currencies conversions from a market source. You can however directly fetch the list of any type mentioned in a market source with a direct request using the reference /market/sources/MARKET-CODE/TYPE where MARKET-CODE is the market source's code and TYPE is any of the following (case-sensitive):

Fetch a list of future classes from a market source

Notice:

The deliveries will only change on a maximum daily rate (depending on the contracts). You should not make this request more than once a day.

Example for Euronext:

Supposing we want to retrieve all the future classes from the Euronext stock exchange. The market source's code is EURONEX (as seen in the previous section when requesting all the the market sources) and the type is future, the reference is therefore /market/sources/EURONEX/future.

user@computer:~$ curl "https://market.financeagri.com/api/market/sources/EURONEX/future" \
-H "Accept: application/json, text/*;q=0.2" \
-H "Accept-Charset: utf-8" \
-H "Accept-Encoding: gzip, deflate" \
-H "Access-Control-Request-Headers: x-session-token" \
-H "X-Session-Token: 85045E8E-CE68-2956-9E11-96F51837C71B" \
--compressed

The result should be similar to this:

{
  "code": "future",
  "data": [
    {
      "code": "EMA",
      "marketSource": "/market/sources/EURONEX",
      "name": "/l10n/market/EURONEX_FUTURE_EMA",
      "desc": "/l10n/market/EURONEX_FUTURE_EMA_DESC",
      "product": "/market/prodcats/CORN/products/EUFDCRN",
      "currency": "EUR",
      "contractUnit": "/market/units/TON",
      "contractSize": 50,
      "deliveries": [
        "/market/sources/EURONEX/future/EMA/deliveries/EMAC01",
        "/market/sources/EURONEX/future/EMA/deliveries/EMAC02",
        "/market/sources/EURONEX/future/EMA/deliveries/EMAC03",
        "/market/sources/EURONEX/future/EMA/deliveries/EMAC04",
        "/market/sources/EURONEX/future/EMA/deliveries/EMAH16",
        "/market/sources/EURONEX/future/EMA/deliveries/EMAM16",
        "/market/sources/EURONEX/future/EMA/deliveries/EMAQ16",
        "/market/sources/EURONEX/future/EMA/deliveries/EMAX16",
        "/market/sources/EURONEX/future/EMA/deliveries/EMAF17",
        "/market/sources/EURONEX/future/EMA/deliveries/EMAH17",
        "/market/sources/EURONEX/future/EMA/deliveries/EMAM17",
        "/market/sources/EURONEX/future/EMA/deliveries/EMAQ17",
        "/market/sources/EURONEX/future/EMA/deliveries/EMAX17",
        "/market/sources/EURONEX/future/EMA/deliveries/EMAF18"
      ]
    }
  ]
}

The data property is an array of future classes. Each class has the following properties:

There are two kinds of deliveries codes: the classic and the continuous.

Notice:

A continuous future is a delivery defined by its index in a chronological list of deliveries (first, second, umpteenth…) instead of being defined by a fixed date (ex: March 2016). This is useful for retrieving history prices spanning across several months (therefore several deliveries).

A classic delivery code is an uppercase string built by concatening the future class code, a letter defining the month (see the table below) and the year in the two-digits format.

Month Code
January F
February G
March H
April J
May K
June M
July N
August Q
September U
October V
November X
December Z

A continuous delivery code is an uppercase string built by concatening the future class code, the letter C (for Continuous) and the index.

Fetch a future delivery from a future class

Any future delivery is accessible through the reference /market/sources/MARKET-CODE/future/FUTURE-CLASS-CODE/deliveries/DELIVERY-CODE.

Example for the march 2016 delivery for Euronext corn:

Supposing we want to retrieve the delivery March 2016 for corn on Euronext.

user@computer:~$ curl "https://market.financeagri.com/api/market/sources/EURONEX/future/EMA/deliveries/EMAH16" \
-H "Accept: application/json, text/*;q=0.2" \
-H "Accept-Charset: utf-8" \
-H "Accept-Encoding: gzip, deflate" \
-H "Access-Control-Request-Headers: x-session-token" \
-H "X-Session-Token: 85045E8E-CE68-2956-9E11-96F51837C71B" \
--compressed

The result should be similar to this:

{
  "code": "EMAH16",
  "marketSource": "/market/sources/EURONEX",
  "futureClass": "/market/sources/EURONEX/future/EMA",
  "lastTradingDate": 1457352000,
  "maturityMonth": 3,
  "maturityYear": 2016
}

The returned object has the following properties:

Fetch a list of option classes from a market source

Similar to future references, only that the type field is option instead.

Notice:

The deliveries will only change on a maximum daily rate (depending on the contracts). You should not make this request more than once a day.

Example for Euronext:

user@computer:~$ curl "https://market.financeagri.com/api/market/sources/EURONEX/option" \
-H "Accept: application/json, text/*;q=0.2" \
-H "Accept-Charset: utf-8" \
-H "Accept-Encoding: gzip, deflate" \
-H "Access-Control-Request-Headers: x-session-token" \
-H "X-Session-Token: 85045E8E-CE68-2956-9E11-96F51837C71B" \
--compressed

The result should be similar to this:

{
  "code": "option",
  "data": [
    {
      "code": "OMA",
      "name": "/l10n/market/EURONEX_OPTION_OMA",
      "desc": "/l10n/market/EURONEX_OPTION_OMA_DESC",
      "marketSource": "/market/sources/EURONEX",
      "product": "/market/prodcats/CORN/products/EUFDCRN",
      "currency": "EUR",
      "underlyingFutureClass": "/market/sources/EURONEX/future/EMA",
      "series": [
        "/market/sources/EURONEX/option/OMA/series/OMAH16",
        "/market/sources/EURONEX/option/OMA/series/OMAM16",
        "/market/sources/EURONEX/option/OMA/series/OMAQ16",
        "/market/sources/EURONEX/option/OMA/series/OMAX16",
        "/market/sources/EURONEX/option/OMA/series/OMAF17",
        "/market/sources/EURONEX/option/OMA/series/OMAH17",
        "/market/sources/EURONEX/option/OMA/series/OMAM17",
        "/market/sources/EURONEX/option/OMA/series/OMAQ17",
        "/market/sources/EURONEX/option/OMA/series/OMAX17",
        "/market/sources/EURONEX/option/OMA/series/OMAF18"
      ]
    }
  ]
}

The data property is an array of option classes. Each class has the following properties:

Fetch an option serie

Notice:

The deliveries will only change on a maximum daily rate (depending on the contracts). You should not make this request more than once a day.

Example:

user@computer:~$ curl "https://market.financeagri.com/api/market/sources/EURONEX/option/OMA/series/OMAH16" \
-H "Accept: application/json, text/*;q=0.2" \
-H "Accept-Charset: utf-8" \
-H "Accept-Encoding: gzip, deflate" \
-H "Access-Control-Request-Headers: x-session-token" \
-H "X-Session-Token: 85045E8E-CE68-2956-9E11-96F51837C71B" \
--compressed

The result should be similar to this:

{
  "code": "OMAH16",
  "marketSource": "/market/sources/EURONEX",
  "optionClass": "/market/sources/EURONEX/option/OMA",
  "underlyingFutureQuote": "/market/sources/EURONEX/future/EMA/deliveries/EMAH16",
  "maturityMonth": 3,
  "maturityYear": 2016,
  "lastTradingDate": 1455537600,
  "minStrikePrice": 122,
  "maxStrikePrice": 250,
  "strikes": [
    {
      "code": "OMAH16C250",
      "marketSource": "/market/sources/EURONEX",
      "optionSeries": "/market/sources/EURONEX/option/OMA/series/OMAH16",
      "optionType": "CALL",
      "strike": 250
    },
    {
      "code": "OMAH16P250",
      "marketSource": "/market/sources/EURONEX",
      "optionSeries": "/market/sources/EURONEX/option/OMA/series/OMAH16",
      "optionType": "PUT",
      "strike": 250
    }
  ]
}

We can see that an option serie has some particular properties:

A strike is an object composed of the following properties (plus the customary ones):

Fetch a list of single quotes from a market source

Notice:

By the end of your development period you should have listed each single quote needed, as the symbols are static, and should not need to make this request.

Example for the RATES market source:

user@computer:~$ curl "https://market.financeagri.com/api/market/sources/RATES/single" \
-H "Accept: application/json, text/*;q=0.2" \
-H "Accept-Charset: utf-8" \
-H "Accept-Encoding: gzip, deflate" \
-H "Access-Control-Request-Headers: x-session-token" \
-H "X-Session-Token: 85045E8E-CE68-2956-9E11-96F51837C71B" \
--compressed

The result should be similar to this:

{
  "code":"single",
  "data":[
    {
      "code": "EONIA01M",
      "name": "/l10n/market/RATES_SINGLE_EONIA01M",
      "desc": "/l10n/market/RATES_SINGLE_EONIA01M_DESC",
      "marketSource": "/market/sources/RATES",
      "product": "/market/prodcats/FINANCE/products/EONIA"
    }
  ]
}

The data property is an array of single quotes where which each quote has the following properties:

Fetch a list of cash quotes from a market source

Notice:

By the end of your development period you should have listed each cash quote needed, as the symbols are static, and should not need to make this request.

Examples for the SITCASHFR market source:

curl "https://market.financeagri.com/api/market/sources/SITCASHFR/cash" \
-H "Accept: application/json, text/*;q=0.2" \
-H "Accept-Charset: utf-8" \
-H "Accept-Encoding: gzip, deflate" \
-H "Access-Control-Request-Headers: x-session-token" \
-H "X-Session-Token: 85045E8E-CE68-2956-9E11-96F51837C71B" \
--compressed

The result should be similar to this:

{
  "code": "cash",
  "data": [
    {
      "code": "FRA18EXWAUB",
      "name": "/l10n/market/SITCASHFR_CASH_FRA18EXWAUB",
      "desc": "/l10n/market/SITCASHFR_CASH_FRA18EXWAUB_DESC",
      "marketSource": "/market/sources/SITCASHFR",
      "product": "/market/prodcats/ALFALFA/products/ALFA18",
      "currency": "EUR",
      "contractUnit": "/market/units/TON",
      "contractSize": 1,
      "geoSite": "/market/geoSites/FRAUB",
      "incoterm": "/market/incoterms/EXW"
    }
  ]
}

The data property is an array of cash quotes where which each quote has the following properties:

Fetch a list of index quotes from a market source

Notice:

By the end of your development period you should have listed each cash quote needed, as the symbols are static, and should not need to make this request.

Examples for the SITSISALMONI market source:

curl "https://market.financeagri.com/api/market/sources/SITSISALMONI/index" \
-H "Accept: application/json, text/*;q=0.2" \
-H "Accept-Charset: utf-8" \
-H "Accept-Encoding: gzip, deflate" \
-H "Access-Control-Request-Headers: x-session-token" \
-H "X-Session-Token: 85045E8E-CE68-2956-9E11-96F51837C71B" \
--compressed

The result should be similar to this:

{
  "code": "index",
  "data": [
    {
      "code": "SISALMONI",
      "marketSource": "/market/sources/SITSISALMONI",
      "editable": true,
      "name": "/l10n/market/SITSISALMONI_INDEX_SISALMONI",
      "desc": "/l10n/market/SITSISALMONI_INDEX_SISALMONI_DESC",
      "timezone": "Europe/Paris",
      "product": "/market/prodcats/SALMON/products/INDEXSALMON",
      "currency": "NOK",
      "volumeMin": 0,
      "contractUnit": "/market/units/KILO",
      "contractSize": 1,
      "incoterm": "/market/incoterms/DAP",
      "geoSite": "/market/geoSites/NONO",
      [...]
      "frequency": "weekly"
    }
  ]
}

The data property is an array of index quotes where which each quote has the following properties:

Fetch a currency class

Notice:

Currently only one market source is able to provide cross-currency conversions: the FOREX. It means you can directly use the reference /market/sources/FOREX/currency instead of checking the autoCurrency field of every market source.

To build the resource URI you must append to the reference the cross-currency code, which is the concatenation of two currency codes as in the ISO-4217 norm.

Notice:

By the end of your development period you should have listed each currency pair needed, as the symbols are static, and should not need to make this request.

Example for the Euro/Dollar conversion:

The cross-currency code is the concatenation of EUR and USD which gives EURUSD.

user@computer:~$ curl "https://market.financeagri.com/api/market/sources/FOREX/currency/EURUSD" \
-H "Accept: application/json, text/*;q=0.2" \
-H "Accept-Charset: utf-8" \
-H "Accept-Encoding: gzip, deflate" \
-H "Access-Control-Request-Headers: x-session-token" \
-H "X-Session-Token: 85045E8E-CE68-2956-9E11-96F51837C71B" \
--compressed

The result should be similar to this:

{
  "code": "EURUSD",
  "marketSource": "/market/sources/FOREX",
  "from": "EUR",
  "to": "USD",
  "terms": [
    {
      "code": "EURUSD5Y",
      "marketSource": "/market/sources/FOREX",
      "currencyClass": "/market/sources/FOREX/currency/EURUSD",
      "termType": "SPOT",
      "termDuration": 0
    }
  ]
}

The terms field, if present (see notice below), is an array of objects for which the properties are:

Notice:

The currencies do not have a name property describing its localized name. Just use the codes or have your own map of codes => names.

List of available term types:

Term type Code
SPOT SP
OVERNIGHT ON
SPOTNEXT SN
TOMORROWNEXT TN
FORWARD Built from the term duration

Notice:

Not all currencies can be converted to another. For example, you can not convert Netherlands Antilles Guilder (NAC) to Argentina Peso (ARS). In that case, the terms field is undefined.

The code of a currency quote (or term) is the concatenation of the currency class reference and the term code. If the term type is FORWARD the term code is calculated from the term duration. A week is defined as 7 days, a month as 30 days (always, even for February), and then a multiple of months. For example a year is 12 months, which equals 360 days.

Term duration Step (number of days between two terms) Meaning Code
Between 7 and 29 days 7 the code is expressed in terms of weeks + W (like Week) xW
Between 30 and 359 days 30 the code is expressed in terms of months + M (like Month) xM
Between 360 and 1800 days 360 the code is expressed in terms of years + Y (like Years) Exception: if the number of years is a float (ex: 1.5 year), use months (ex: 18M) instead xY

Examples:

Term duration Code
14 2W
30 1M
60 2M
360 1Y
540 18M
720 2Y

Fetch a currency quote

Using the code of a currency quote (or term) you retrieved earlier (see the previous section), you can fetch a currency quote by appending /terms/CODE to the reference of the currency class, where CODE is the term's code.

Example for the EUR/USD Spot conversion:

For a EUR/USD currency class reference of /market/sources/FOREX/currency/EURUSD the SPOT conversion reference is /market/sources/FOREX/currency/EURUSD/terms/EURUSDSP.

user@computer:~$ curl "https://market.financeagri.com/api/market/sources/FOREX/currency/EURUSD/terms/EURUSDSP" \
-H "Accept: application/json, text/*;q=0.2" \
-H "Accept-Charset: utf-8" \
-H "Accept-Encoding: gzip, deflate" \
-H "Access-Control-Request-Headers: x-session-token" \
-H "X-Session-Token: 85045E8E-CE68-2956-9E11-96F51837C71B" \
--compressed

Notice:

Not all currencies can be converted to another. For example, you can not convert Netherlands Antilles Guilder (NAC) to Argentina Peso (ARS).

Fetch a price

To fetch a price you will first need the precise reference for the quote (not just only class or serie concerning futures or option prices) from which you want to retrieve the price. For further information on how to obtain a quote reference, please refer to the previous sections.

The structure of a price depends on its type, defined in its code field as a string. The available price types are:

Their respective literal structures are described below in their own section.

Fetch the last price

The reference to fetch the last price of a quote is simple: just append /price to the quote's reference.

Example for the price for Euronext corn march 2016:

The reference becomes /market/sources/EURONEX/future/EMA/deliveries/EMAH16/price.

user@computer:~$ curl "https://market.financeagri.com/api/market/sources/EURONEX/future/EMA/deliveries/EMAH16/price" \
-H "Accept: application/json, text/*;q=0.2" \
-H "Accept-Charset: utf-8" \
-H "Accept-Encoding: gzip, deflate" \
-H "Access-Control-Request-Headers: x-session-token" \
-H "X-Session-Token: 85045E8E-CE68-2956-9E11-96F51837C71B" \
--compressed

Fetch an order book

Please ensure beforehand that the market source of the quote you are about to request the order book actually has order books.

Notice:

To ensure the market source allows order books, you can make a request to the market source and look for the orderBook property.

user@computer:~$ curl "https://market.financeagri.com/api/market/sources/EURONEX" \
-H "Accept: application/json, text/*;q=0.2" \
-H "Accept-Charset: utf-8" \
-H "Accept-Encoding: gzip, deflate" \
-H "Access-Control-Request-Headers: x-session-token" \
-H "X-Session-Token: 85045E8E-CE68-2956-9E11-96F51837C71B" \
--compressed | jq ".orderBook"

which should return either true or false

This is basically the same as a price request but you append /orderBook (mind the capital B) to the quote's reference.

Example for the order book for Euronext corn march 2016:

The reference becomes /market/sources/EURONEX/future/EMA/deliveries/EMAH16/orderBook.

user@computer:~$ curl "https://market.financeagri.com/api/market/sources/EURONEX/future/EMA/deliveries/EMAH16/orderBook" \
-H "Accept: application/json, text/*;q=0.2" \
-H "Accept-Charset: utf-8" \
-H "Accept-Encoding: gzip, deflate" \
-H "Access-Control-Request-Headers: x-session-token" \
-H "X-Session-Token: 85045E8E-CE68-2956-9E11-96F51837C71B" \
--compressed

Fetch a history price

Notice:

The number of prices returned for a request is capped at 8192.

To fetch a history price, you'll need:

List of all resolutions available:

  1. TICK (unavailable for currencies)
  2. MINUTE
  3. HOUR
  4. DAY
  5. WEEK
  6. MONTH
  7. A number of of minutes, between 1 and 1440 (only for market prices).

This list is also available through a request to this API resource: /l10n/generic/JSON_HISTORY_RESOLUTIONS.

To build the request append /history/START-TIMESTAMP,END-TIMESTAMP,RESOLUTION to the quote's reference where START-TIMESTAMP is the unix timestamp of the start date, END-TIMESTAMP is the unix timestamp of the end date and RESOLUTION is one of the resolutions above.

Notice: If you switch the start and end timestamps, the result will be returned in descending order. This might be particularly useful for requests expecting a lot of data like EURUSD on Forex. Using the ascending order with a cap of 8092, you might not receive the latest prices if there are more than 8092 prices before even reaching the end timestamp. Using the descending order you might not receive the oldest prices, it all depends of your need.

Example for Euronext corn march 2016 from the 1st of february 2016 at 4PM to the 2nd of february 2016 at 4PM, with a price every half an hour:

First, get the unix timestamp of the start date:

user@computer:~$ date -d "2016-02-01 16:00" +%s
1454338800

Then, the unix timestamp of the end date:

user@computer:~$ date -d "2016-02-02 16:00" +%s
1454425200

Then build the request: /history/1454338800,1454425200,HOUR and append it to the quote's reference ; which gives: /market/sources/EURONEX/future/EMA/deliveries/EMAH16/history/1454338800,1454425200,HOUR.

user@computer:~$ curl \
"https://market.financeagri.com/api/market/sources/EURONEX/future/EMA/deliveries/EMAH16/history/1454338800,1454425200,HOUR" \
-H "Accept: application/json, text/*;q=0.2" \
-H "Accept-Charset: utf-8" \
-H "Accept-Encoding: gzip, deflate" \
-H "Access-Control-Request-Headers: x-session-token" \
-H "X-Session-Token: 85045E8E-CE68-2956-9E11-96F51837C71B" \
--compressed

The result should have the structure of a history market price, as defined in the appropriate section below.

Fetch a history price on an expired future

The request is built from the future class code, the maturity year, maturity month, plus an optional shift for the range: /api/market/sources/SOURCE_CODE/future/FUTURE_CLASS_CODE/expired/YEAR/MONTH/history/START,END,RESOLUTION,SHIFT.

SHIFT is a number of seconds used to shift history entries (can be negative). This number will be added to every timestamp of every history entry.

Ex: /market/sources/EURONEX/future/EMA/expired/2017/11/history/1420098718,1512028318,DAY

Please note that 2017 is expired at the moment of this writing. Previous examples with now expired dates were not updated every year and kept as is.

user@computer:~$ curl \
"https://market.financeagri.com/api/market/sources/EURONEX/future/EMA/2017/11/history/1420098718,1512028318,DAY" \
-H "Accept: application/json, text/*;q=0.2" \
-H "Accept-Charset: utf-8" \
-H "Accept-Encoding: gzip, deflate" \
-H "Access-Control-Request-Headers: x-session-token" \
-H "X-Session-Token: 85045E8E-CE68-2956-9E11-96F51837C71B" \
--compressed

The result should have the structure of a history market price, as defined in the appropriate section below.

Structure of a price

Structure of a market price

A market price is structured as follows:

{
  "code": "marketPrice",
  "quote": "(string) reference of the associated quote",
  "quality": "(string) 'REALTIME' or 'DELAYED'",
  "last":
  {
    "date": "(number) unix timestamp (price reference date)",
    "value": "(number)",
    "volume": "(number)",
    "totalVolume": "(number) cumulated volume of the day",
    "orders": "(number)"
  },
  "stats":
  {
    "perf": "(number) absolute performance",
    "relPerf": "(number) relative performance",
    "perf1Y": "(number) absolute performance over 1 year",
    "relPerf1Y": "(number) relative performance over 1 year"
  },
  "first":
  {
    "date": "(number) unix timestamp",
    "value": "(number)"
  },
  "previousLast":
  {
    "date": "(number) unix timestamp",
    "value": "(number)"
  },
  "settlement":
  {
    "date": "(number) unix timestamp",
    "value": "(number)",
    "openInterest": "(number)"
  },
  "high":
  {
    "date": "(number) unix timestamp",
    "value": "(number)"
  },
  "low":
  {
    "date": "(number) unix timestamp",
    "value": "(number)"
  },
  "high1Y":
  {
    "date": "(number) unix timestamp",
    "value": "(number) value of the high over 1 year"
  },
  "low1Y":
  {
    "date": "(number) unix timestamp",
    "value": "(number) value of the low over 1 year"
  },
  "ask":
  {
    "date": "(number) unix timestamp",
    "value": "(number)",
    "globalVolume": "(number) explicit & implied volume cumulated",
    "volume": "(number) explicit volume (optional)",
    "impliedVolume": "(number) implied volume (optional)",
    "orders": "(number)"
  },
  "bid":
  {
    "date": "(number) unix timestamp",
    "value": "(number)",
    "globalVolume": "(number) explicit & implied volume cumulated",
    "volume": "(number) explicit volume (optional)",
    "impliedVolume": "(number) implied volume (optional)",
    "orders": "(number)"
  }
}
Structure of an order book
{
  "code": "orderBook",
  "quote": "(string) reference of the associated quote",
  "quality": "REALTIME",
  "data": [
    {
      "ask":
      {
        "value": "(number)",
        "volume": "(number)",
        "orders": "(number)",
      },
      "bid":
      {
        "value": "(number)",
        "volume": "(number)",
        "orders": "(number)",
      }
    }
  ]
}
Structure of a cash price
{
  "code": "cashPrice",
  "quote": "(string) reference of the associated quote",
  "quality": "REALTIME",
  "date": "(number) unix timestamp",
  "deliveries": [
    {
      "start": "(number) unix timestamp",
      "end": "(number) unix timestamp",
      "value": "(number)",
      "prime": "(number)"
    }
  ]
}
Structure of an index price
{
  "code": "indexPrice",
  "quote": "(string) reference of the associated quote",
  "quality": "REALTIME",
  "date": "(number) unix timestamp",
  "value": "(number)",
  "volume": "(number)",
  "standardDeviation": "(number)"
}
Structure of a history market price

The reference date for each history entry is the last.date field. The entry date field is automatically computed as the average date between the last.date and first.date fields.

{
  "code": "historyMarketPrice",
  "quote": "(string) reference of the associated quote",
  "quality": "(string) 'REALTIME' or 'DELAYED'",
  "ranges": [
    {
      "start": "(number) unix timestamp",
      "end": "(number) unix timestamp",
      "resolution": "(string) see below for possible value",
      "data": [
        {
          "date": "(number) unix timestamp",
          "first":
          {
            "date": "(number) unix timestamp",
            "value": "(number)"
          },
          "last":
          {
            "date": "(number) unix timestamp",
            "value": "(number)",
            "volume": "(number)",
            "orders": "(number)"
          },
          "high":
          {
            "date": "(number) unix timestamp",
            "value": "(number)"
          },
          "low":
          {
            "date": "(number) unix timestamp",
            "value": "(number)"
          },
          "stats":
          {
            "openInterest": "(number)"
          }
        }
      ]
    }
  ]
}
Structure of a history cash price
{
  "code": "historyCashPrice",
  "quote": "(string) reference of the associated quote",
  "quality": "REALTIME",
  "ranges": [
    {
      "start": "(number) unix timestamp",
      "end": "(number) unix timestamp",
      "resolution": "(string) see below for possible value",
      "data": [
        {
          "date": "(number) unix timestamp",
          "deliveries": [
            {
              "start": "(number) unix timestamp",
              "end": "(number) unix timestamp",
              "value": "(number)",
              "prime": "(number)"
            }
          ]
        }
      ]
    }
  ]
}
Structure of a history index price
{
  "code": "historyIndexPrice",
  "quote": "(string) reference of the associated quote",
  "quality": "REALTIME",
  "ranges": [
    {
      "start": "(number) unix timestamp",
      "end": "(number) unix timestamp",
      "resolution": "(string) see below for possible value",
      "data": [
        {
          "date": "(number) unix timestamp",
          "value": "(number)",
          "volume": "(number)",
          "standardDeviation": "(number)"
        }
      ]
    }
  ]
}

Fetch the list of units

The API reference is /market/units.

Notice:

By the end of your development period you should have listed each unit needed, as the symbols are static, and should not need to make this request.

Example:

user@computer:~$ curl "https://market.financeagri.com/api/market/units" \
-H "Accept: application/json, text/*;q=0.2" \
-H "Accept-Charset: utf-8" \
-H "Accept-Encoding: gzip, deflate" \
-H "Access-Control-Request-Headers: x-session-token" \
-H "X-Session-Token: 85045E8E-CE68-2956-9E11-96F51837C71B" \
--compressed

The result should be similar to this:

{
  "code": "units",
  "data": [
    {
      "code": "USWSBS",
      "name": "/l10n/generic/UNIT_USWSBS",
      "desc": "/l10n/generic/UNIT_USWSBS_DESC",
      "symbol": "bsh",
      "type": "MASS",
      "convertionFactor": 27.2155,
      "convertionOffset": 0
    }
  ]
}

The data field is an array of unit objects. Each unit item has the following structure:

How to convert a unit to another

Using the conversion factor from the units you can convert a unit to another. First, get both conversion factors and offsets. In most of the cases the conversion offset is 0, which means the result is always a multiple of the quantity.

Let's name some variables:

Then apply this calculation (QUANTITY being the quantity of the first unit to convert to the second unit):

((QUANTITY * factorB + offsetB) - offsetA) / factorA.

Example: convert from US wheat and soybeans bushel to metric ton:

First, get the US wheat and soybeans bushel and Metric ton conversion factors and offsets:

For the bushel:

user@computer:~$ curl "https://market.financeagri.com/api/market/units/USWSBS" \
-H "Accept: application/json, text/*;q=0.2" \
-H "Accept-Charset: utf-8" \
-H "Accept-Encoding: gzip, deflate" \
-H "Access-Control-Request-Headers: x-session-token" \
-H "X-Session-Token: 85045E8E-CE68-2956-9E11-96F51837C71B" \
--compressed  | jq "{factor: .convertionFactor, offset: .convertionOffset}"

Result:

{
  "offset": 0,
  "factor": 27.2155
}

For the metric ton:

user@computer:~$ curl "https://market.financeagri.com/api/market/units/TON" \
-H "Accept: application/json, text/*;q=0.2" \
-H "Accept-Charset: utf-8" \
-H "Accept-Encoding: gzip, deflate" \
-H "Access-Control-Request-Headers: x-session-token" \
-H "X-Session-Token: 85045E8E-CE68-2956-9E11-96F51837C71B" \
--compressed  | jq "{factor: .convertionFactor, offset: .convertionOffset}"

Result:

{
  "offset": 0,
  "factor": 1000
}

Then apply the calculation with a quantity of 1: ((1 * 27.2155 + 0) - 0) / 1000 which gives 0.0272155. So, 1 US wheat and soybeans bushel is equal to 0.0272155 metric ton.

Fetch the list of geosites

The list of geosites is available through the reference /market/geoSites (mind the capital S).

Notice:

By the end of your development period you should have listed each geo site needed, as the symbols are static, and should not need to make this request.

Example:

user@computer:~$ curl "https://market.financeagri.com/api/market/geoSites" \
-H "Accept: application/json, text/*;q=0.2" \
-H "Accept-Charset: utf-8" \
-H "Accept-Encoding: gzip, deflate" \
-H "Access-Control-Request-Headers: x-session-token" \
-H "X-Session-Token: 85045E8E-CE68-2956-9E11-96F51837C71B" \
--compressed"

The result should be similar to this:

{
  "code": "geoSites",
  "data": [
    {
      "code": "BEAN",
      "name": "/l10n/generic/GEOSITE_BEAN",
      "desc": "/l10n/generic/GEOSITE_BEAN_DESC",
      "country": "BE",
      "gpsLong": 4.40197,
      "gpsLat": 51.2292
    }
  ]
}

The data field is an array of geosites. Each geosite has the following fields:

Using the GPS coordinates, you can then use a map like Google Maps to have a view at the area: https://maps.google.com/maps?q=51.2292,4.40197.

Fetch the list of incoterms

The list of incoterms is available through the reference /market/incoterms.

Notice:

By the end of your development period you should have listed each incoterm needed, as the symbols are static, and should not need to make this request.

Example:

user@computer:~$ curl "https://market.financeagri.com/api/market/incoterms" \
-H "Accept: application/json, text/*;q=0.2" \
-H "Accept-Charset: utf-8" \
-H "Accept-Encoding: gzip, deflate" \
-H "Access-Control-Request-Headers: x-session-token" \
-H "X-Session-Token: 85045E8E-CE68-2956-9E11-96F51837C71B" \
--compressed

The result should be similar to this:

{
  "code": "incoterms",
  "data": [
    {
      "code": "CFR",
      "name": "/l10n/generic/INCOTERM_CFR",
      "desc": "/l10n/generic/INCOTERM_CFR_DESC"
    }
  ]
}

The data field is an array of incoterms. Each incoterm has the following fields:

Fetch the list of product categories

The list of product categories is available through the reference /market/prodcats.

Notice:

By the end of your development period you should have listed each product category needed, as the symbols are static, and should not need to make this request.

Example:

user@computer:~$ curl "https://market.financeagri.com/api/market/prodcats" \
-H "Accept: application/json, text/*;q=0.2" \
-H "Accept-Charset: utf-8" \
-H "Accept-Encoding: gzip, deflate" \
-H "Access-Control-Request-Headers: x-session-token" \
-H "X-Session-Token: 85045E8E-CE68-2956-9E11-96F51837C71B" \
--compressed

The result should be similar to this:

{
  "code": "prodcats",
    "data": [
    {
      "code": "ALFALFA",
      "name": "/l10n/generic/PRODCAT_ALFALFA",
      "desc": "/l10n/generic/PRODCAT_ALFALFA_DESC",
      "products": [
        "/market/prodcats/ALFALFA/products/ALFA18",
        "/market/prodcats/ALFALFA/products/ALFA23"
      ]
    }
  ]
}

The data field is an array of products categories. Each category has the following fields:

A product is an object with the following properties:

Fetch a news item

Any reference meant to fetch a news item is prefixed by /news.

Fetch the list of news sources

The list of news sources is available through a request with the reference /news/sources.

Notice:

The results are not expected to change, unless your access rights do (ex: subscribed to a new source). You probably don't need this request at all, once the development is done.

Example:

user@computer:~$ curl "https://market.financeagri.com/api/news/sources" \
-H "Accept: application/json, text/*;q=0.2" \
-H "Accept-Charset: utf-8" \
-H "Accept-Encoding: gzip, deflate" \
-H "Access-Control-Request-Headers: x-session-token" \
-H "X-Session-Token: 85045E8E-CE68-2956-9E11-96F51837C71B" \
--compressed

The result should be similar to this:

{
  "code": "sources",
  "data": [
    {
      "code": "SITUSDA",
      "name": "/l10n/news/SITUSDA_SRC",
      "desc": "/l10n/news/SITUSDA_SRC_DESC",
      "bypassFilters": false,
      "rights": "SEARCH",
      "langs": [
        "FR",
        "EN",
        "ES"
      ]
    }
  ]
}

The data field is an array of news sources which have the following properties:

Retrieve the last articles and search for specific articles

Once you have the news source's API reference, you can search articles and retrieve the last articles published. You need to provide a period defined by a beginning date and an end date, both as UNIX timestamp in seconds.

You then build the request with the news source's reference followed by /article/search/START/END where START is the timestamp of the period's beginning and END is the timestamp of the period's end; which gives /news/sources/SOURCE-CODE/article/search/START/END.

Example for the articles from the AFP news source from the 1st of february 2016 at 4PM to the 2nd of february 2016 at 4PM:

First, get the unix timestamp of the start date:

user@computer:~$ date -d "2016-02-01 16:00" +%s
1454338800

Then, the unix timestamp of the end date:

user@computer:~$ date -d "2016-02-02 16:00" +%s
1454425200

Then build the request: /article/search/1454338800/1454425200 and append it to the source's reference; which gives: /news/sources/AFP/article/search/1454338800/1454425200.

user@computer:~$ curl "https://market.financeagri.com/api/news/sources/AFP/article/search/1454338800/1454425200" \
-H "Accept: application/json, text/*;q=0.2" \
-H "Accept-Charset: utf-8" \
-H "Accept-Encoding: gzip, deflate" \
-H "Access-Control-Request-Headers: x-session-token" \
-H "X-Session-Token: 85045E8E-CE68-2956-9E11-96F51837C71B" \
--compressed

The result should be similar to:

{
  "code": "searchNews",
  "source": "/news/sources/AFP",
  "data": []
}

The data field is an array of news articles (described in the next section).

Structure of a news article

Any news article received will follow this format:

{
  "code": "newsArticle",
  "source": "(string) reference of the associated news source",
  "id": "(number|string) unique identifier on the associated source",
  "copyright": "(string) the article's copyright",
  "lang": "(string) the article's language, as in ISO-639-1 norm",
  "publicationDate": "(number) unix timestamp of the date at which the article was first published",
  "modificationDate": "(number) unix timestamp of the date of the last modification",
  "title": "(string) the article's title",
  "snippet": "(string) the article's snipper in HTML",
  "content": "(string, optional) the article's content, in HTML",
  "words": "(number) number of words in the article's content",
  "metadata": "(optional object) the news article metadata when provided. Only some sources have news metadata. For example the properties `dayTendency` and `shortTermTendency` on some sources refer to a trend value (integer) on a scale from 0 (bearish) to 11 (bullish)"
}

The content field might be omitted when listing/searching for news articles. To retrieve the content, fetch the article directly.

Notice:

Please notice that an article's unique identifier is only unique within its associated source and not for all the news sources.

Search for specific articles

You can filter the news articles you want to receive by requesting

Fetch articles written in some languages only

To fetch the articles written in some languages only, append a literal array of languages codes (ISO-639-1 norm) like this: /news/sources/SOURCE-CODE/article/search/START/END/["ISO_CODE_LANG","ISO_CODE_LANG"].

Please note that only double quotes are accepted inside the brackets.

Do not forget to encode the characters in the URL if you use a GET request or to escape the double quotes in a POST request.

Example for articles from the AFP source in english and french only:

The english ISO-639-1 code is EN and the french code is FR.

The API reference will then be /news/sources/AFP/article/search/START/END/["EN","FR"].

user@computer:~$ curl "https://market.financeagri.com/api/news/sources/AFP/article/search/1454338800/1454425200/%5B%22EN%22,%22FR%22%5D" \
-H "Accept: application/json, text/*;q=0.2" \
-H "Accept-Charset: utf-8" \
-H "Accept-Encoding: gzip, deflate" \
-H "Access-Control-Request-Headers: x-session-token" \
-H "X-Session-Token: 85045E8E-CE68-2956-9E11-96F51837C71B" \
--compressed
Fetch articles which contain a keyword

To fetch the articles which contain a given keyword, append the keyword to the search reference: /news/sources/SOURCE-CODE/article/search/START/END/keyword.

Example for articles from the AFP source which content contains wheat:

/news/sources/AFP/article/search/START/END/wheat.

user@computer:~$ curl "https://market.financeagri.com/api/news/sources/AFP/article/search/1454338800/1454425200/wheat" \
-H "Accept: application/json, text/*;q=0.2" \
-H "Accept-Charset: utf-8" \
-H "Accept-Encoding: gzip, deflate" \
-H "Access-Control-Request-Headers: x-session-token" \
-H "X-Session-Token: 85045E8E-CE68-2956-9E11-96F51837C71B" \
--compressed
Fetch articles in some languages which contain a keyword

You can combine both the languages and the keyword filters. In this case just place the keyword after the languages array in the reference instead of after the end timestamp. That gives: /news/sources/SOURCE-CODE/article/search/START/END/["ISO_CODE_LANG","ISO_CODE_LANG"]/keyword.

Please note that only double quotes are accepted inside the brackets.

Do not forget to encode the characters in the URL if you use a GET request or to escape the double quotes in a POST request.

user@computer:~$ curl "https://market.financeagri.com/api/news/sources/AFP/article/search/1454338800/1454425200/%5B%22EN%22,%22FR%22%5D/wheat" \
-H "Accept: application/json, text/*;q=0.2" \
-H "Accept-Charset: utf-8" \
-H "Accept-Encoding: gzip, deflate" \
-H "Access-Control-Request-Headers: x-session-token" \
-H "X-Session-Token: 85045E8E-CE68-2956-9E11-96F51837C71B" \
--compressed

Fetch an article

To fetch a particular news article from a news source you need the source's API reference and the article's unique identifier.

To build the request simply append the identifier to /news/sources/SOURCE-CODE/article to form /news/sources/SOURCE-CODE/article/ID where SOURCE-CODE is the news source's code and ID is the article's unique identifier.

Example for the article with id 57582 from the AFP source:

The API reference is /news/sources/AFP/article/57582.

user@computer:~$ curl "https://market.financeagri.com/api/news/sources/AFP/article/57852" \
-H "Accept: application/json, text/*;q=0.2" \
-H "Accept-Charset: utf-8" \
-H "Accept-Encoding: gzip, deflate" \
-H "Access-Control-Request-Headers: x-session-token" \
-H "X-Session-Token: 85045E8E-CE68-2956-9E11-96F51837C71B" \
--compressed

Fetch a localization item

Any API reference to a localization item is prefixed with /l10n.

Notice:

By the end of your development period you should have listed each localization item needed, as the symbols are static, and should not need to make this request.

Example with the following localization reference retrieved earlier from a request on a cash quote:

user@computer:~$ curl "https://market.financeagri.com/api/l10n/market/SITCASHFR_CASH_FRA18EXWAUB" \
-H "Accept: application/json, text/*;q=0.2" \
-H "Accept-Charset: utf-8" \
-H "Accept-Encoding: gzip, deflate" \
-H "Access-Control-Request-Headers: x-session-token" \
-H "X-Session-Token: 85045E8E-CE68-2956-9E11-96F51837C71B" \
--compressed

The result is always an object with two keys:

{
  "code": "SITCASHFR_CASH_FRA18EXWAUB",
  "text": "Alfalfa (18%) EXW Aube"
}

The text field is either a simple string or a HTML string. When fetching a description you might encounter some patterns like {@:reference,title}.

Example:

60,000 {@:/market/units/LBS,pounds}

Such patterns are used internally for constructing a link that combines the reference and title. In the previous example you can extract the foreign item reference (/market/units/LBS) and build a link to it with pounds as text content.

Fetch several items at once (batch requests)

If you need to retrieve several items at once, you can make a POST request with an array of references.

To do so, make a POST request to the API's root URL (https://market.debug.sitagri:8080/api) with the following extra HTTP header to specify you are sending JSON data: Content-Type: application/json; charset=utf-8. The request's body is a literal array of all the items you want to fetch.

Notice:

The number of references/commands per batch request is capped by default to 250. Based on your contract, this limit can be lower.

Example with all the prices from the EMA (continuous) deliveries:

Supposing that we want to retrieve the last price of each continuous delivery for EMA. The list of references is then:

Which means the array will be constructed as follows:

["/market/sources/EURONEX/future/EMA/deliveries/EMAC01/price",
    "/market/sources/EURONEX/future/EMA/deliveries/EMAC02/price",
    "/market/sources/EURONEX/future/EMA/deliveries/EMAC03/price",
    "/market/sources/EURONEX/future/EMA/deliveries/EMAC04/price"]

So, the following request:

curl -X POST "https://market.financeagri.com/api" \
-H "Accept: application/json, text/*;q=0.2" \
-H "Accept-Charset: utf-8" \
-H "Accept-Encoding: gzip, deflate" \
-H "Access-Control-Request-Headers: x-session-token" \
-H "X-Session-Token: 85045E8E-CE68-2956-9E11-96F51837C71B" \
-H "Content-Type: application/json; charset=utf-8" \
-d '["/market/sources/EURONEX/future/EMA/deliveries/EMAC01/price","/market/sources/EURONEX/future/EMA/deliveries/EMAC02/price", "/market/sources/EURONEX/future/EMA/deliveries/EMAC03/price","/market/sources/EURONEX/future/EMA/deliveries/EMAC04/price"]' \
--compressed

should return a result similar to this:

[
  {
    "code": "marketPrice",
    "quote": "/market/sources/EURONEX/future/EMA/deliveries/EMAC01",
    "quality": "REALTIME",
    "last": {
      "date": 1458323240,
      "value": 152.25,
      "totalVolume": 546,
      "orders": 78
    },
    "stats": {
      "perf": -1.25,
      "relPerf": -0.8143,
      "perf1Y": -11.5,
      "relPerf1Y": -7.0229
    },
    "first": {
      "date": 1458295760,
      "value": 153.25
    },
    "previousLast": {
      "date": 1458235984,
      "value": 153.5
    },
    "settlement": {
      "date": 1458063366,
      "value": 155,
      "openInterest": 14018
    },
    "high": {
      "date": 1458295760,
      "value": 153.25
    },
    "low": {
      "date": 1458320259,
      "value": 152.25
    },
    "high1Y": {
      "date": 1435752000,
      "value": 199.5
    },
    "low1Y": {
      "date": 1457092800,
      "value": 141
    },
    "ask": {
      "date": 1458540240,
      "value": 154.5,
      "volume": 5,
      "orders": 1
    },
    "bid": {
      "date": 1458540240,
      "value": 151.25,
      "volume": 5,
      "orders": 1
    }
  },
  {
    "code": "marketPrice",
    "quote": "/market/sources/EURONEX/future/EMA/deliveries/EMAC02",
    "quality": "REALTIME",
    "last": {
      "date": 1458323240,
      "value": 156.25,
      "totalVolume": 70,
      "orders": 34
    },
    "stats": {
      "perf": -1.25,
      "relPerf": -0.7937,
      "perf1Y": -11.25,
      "relPerf1Y": -6.7164
    },
    "first": {
      "date": 1458297310,
      "value": 157.25
    },
    "previousLast": {
      "date": 1458235984,
      "value": 157.5
    },
    "settlement": {
      "date": 1458063366,
      "value": 159,
      "openInterest": 5368
    },
    "high": {
      "date": 1458297310,
      "value": 157.25
    },
    "low": {
      "date": 1458320225,
      "value": 156
    },
    "high1Y": {
      "date": 1435752000,
      "value": 205
    },
    "low1Y": {
      "date": 1456920000,
      "value": 149.5
    },
    "ask": {
      "date": 1458540240,
      "value": 160.25,
      "volume": 5,
      "orders": 1
    },
    "bid": {
      "date": 1458540240,
      "value": 155.5,
      "volume": 10,
      "orders": 1
    }
  },
  {
    "code": "marketPrice",
    "quote": "/market/sources/EURONEX/future/EMA/deliveries/EMAC03",
    "quality": "REALTIME",
    "last": {
      "date": 1458323240,
      "value": 159.75,
      "totalVolume": 68,
      "orders": 25
    },
    "stats": {
      "perf": -0.25,
      "relPerf": -0.1562,
      "perf1Y": -12.5,
      "relPerf1Y": -7.2569
    },
    "first": {
      "date": 1458295802,
      "value": 160.5
    },
    "previousLast": {
      "date": 1458235984,
      "value": 160
    },
    "settlement": {
      "date": 1458063366,
      "value": 161.75,
      "openInterest": 5917
    },
    "high": {
      "date": 1458295802,
      "value": 160.5
    },
    "low": {
      "date": 1458316976,
      "value": 159.5
    },
    "high1Y": {
      "date": 1435752000,
      "value": 201
    },
    "low1Y": {
      "date": 1456920000,
      "value": 154
    },
    "ask": {
      "date": 1458540240,
      "value": 170,
      "volume": 20,
      "orders": 1
    },
    "bid": {
      "date": 1458540240,
      "value": 157,
      "volume": 5,
      "orders": 1
    }
  },
  {
    "code": "marketPrice",
    "quote": "/market/sources/EURONEX/future/EMA/deliveries/EMAC04",
    "quality": "REALTIME",
    "last": {
      "date": 1458323240,
      "value": 162.5,
      "totalVolume": 9,
      "orders": 14
    },
    "stats": {
      "perf": 0,
      "relPerf": 0,
      "perf1Y": -12.25,
      "relPerf1Y": -7.01
    },
    "first": {
      "date": 1458295802,
      "value": 163.25
    },
    "previousLast": {
      "date": 1458235984,
      "value": 162.5
    },
    "settlement": {
      "date": 1458063366,
      "value": 164.25,
      "openInterest": 764
    },
    "high": {
      "date": 1458295802,
      "value": 163.25
    },
    "low": {
      "date": 1458319742,
      "value": 161.5
    },
    "high1Y": {
      "date": 1435752000,
      "value": 200
    },
    "low1Y": {
      "date": 1456920000,
      "value": 156.25
    },
    "ask": {
      "date": 1458547467,
      "value": 185,
      "volume": 2
    }
  }
]

Publish data

Publish a news article

Publishing a news quite works the same way as fetching some: you need the news source, and of course to have the correct access rights (ie. "write" to be allowed to publish a news). Then the only thing that matters is the endpoint, and the news format.

Once you have the news source's API reference, you can publish an article through a POST request to the following endpoint: /edit/news/sources/NEWS_SOURCE_CODE/article. Please mind that this endpoint begins with /edit and not /api like you might have read earlier. The data expected is a JSON so send the following extra HTTP header to specify you are sending JSON data: Content-Type: application/json; charset=utf-8.

Here is the JSON expected:

{
  "code":"newsArticle",
  "copyright": "(string) a short string defining a copyright",
  "lang": "(string) the language in ISO-639-1 norm",
  "title": "(string) the article's title",
  "snippet": "(string) the article's snippet, a short one-line string describing the content",
  "content": "(string) the article's content. HTML is allowed but please remove any id and class attributes as well as style and script tags.",
  "publicationDate": "(number): the unix timestamp since epoch in seconds of the article's publication date",
  "modificationDate": "(number): the unix timestamp since epoch in seconds of the article's modification date"
}

Example:

We'll use this JSON:

{
  "code": "newsArticle",
  "copyright": "Your company ©",
  "lang": "EN",
  "title": "Your awesome article's title",
  "snippet": "This article will speak about things",
  "content": "Some content about things and stuff and so on.",
  "publicationDate": 1603980548,
  "modificationDate": 1603980548
}

and send it through this request:

user@computer:~$ curl -X POST "https://market.financeagri.com/edit/news/sources/PRIVDEMO/article
" \
-H "Accept: application/json, text/*;q=0.2" \
-H "Accept-Charset: utf-8" \
-H "Accept-Encoding: gzip, deflate" \
-H "Access-Control-Request-Headers: x-session-token" \
-H "X-Session-Token: 85045E8E-CE68-2956-9E11-96F51837C71B" \
-H "Content-Type: application/json; charset=utf-8" \
-d '{"code":"newsArticle","copyright":"Your company ©","lang":"EN","title":"Your awesome article title","snippet":"This article will speak about things","content":"Some content about things and stuff and so on.","publicationDate":1603980548, modificationDate":1603980548}' \
--compressed

The result will be similar to this:

{
    "code": "writeEditableArticle",
    "source": "/news/sources/PRIVDEMO",
    "id": 37,
    "success": true
}

The "source" being the news source on which you published the article, the id being its unique identifier for this source, and success a boolean telling you if the request actually worked.

Establish a permanent connection (using websockets)

Establishing a websocket connection proves useful when you need to quickly retrieve several items or receive realtime updates for the latest prices and news. To receive realtime prices and news, you can register a listener, as described in the subsections below.

To do that, you will need to establish a live connection between our market server and your client thanks to websockets.

To use websockets with our market server, replace the http scheme in the market server URL with ws.

Example:

https://market.financeagri.com becomes ws://market.financeagri.com.

The API endpoint is /api/netbus, which gives a full URL like ws://market.financeagri.com/api/netbus.

The session token must be sent through the sub-protocol option of the websocket.

Warning: When using websockets over SSL/TLS, wscat only works with wss:// whether other apps/frameworks only support ws://.

Example:

user@computer:~$ wscat -c "ws://market.financeagri.com/api/netbus" -s "85045E8E-CE68-2956-9E11-96F51837C71B"
connected (press CTRL+C to quit)
>

Once the connection is open, any API reference described in the Fetch section can be used within this websocket connection. The endpoint expects a JSON formatted request with two parameters: seq and data.

seq is an integer and is used to identify your request. Any request sent with a seq defined as x will receive a response with the same seq field. So, if you send a command with a seq field defined as 1337, the response you will receive will have a seq field with a value of 1337 too.

data is the API reference you want to request or an array of API references (see Fetch several items at once for more information on how to build a JSON array or API references).

So, any command you will send through the websocket channel will look like this:

{"seq":1337,"data":"my-api-reference"}

Example to request the RATES market source localized name:

> {"seq": 1337, "data": "/l10n/market/RATES_SRC"}
  < {"seq":1337,"data":{"code":"RATES_SRC","text":"Interest Rates"}}

This connection must be kept alive by sending a keep-alive request from time to time, unless you are already sending regular messages. To know the connection timeout, send a command with the /session API reference.

Example:

> {"seq": 1337, "data": "/session"}
  < {"seq":1337,"data":{"code":"session","token":"85045E8E-CE68-2956-9E11-96F51837C71B","timeout":120}}

The object returned has a timeout field defining the session timeout, in seconds. In the previous example we can see that a keep-alive request must be sent every 2 minutes. To send a keep-alive request, you can just send anything not empty (not an empty string), "keep-alive" for example.

Warning:

For maintenance reasons our services are rebooted regularly, causing the loss of the websockets connection. If that happens, you need to wait a minute and establish a new websocket connection.

Register a price listener

A price listener is built with the price's reference, as described in the Fetch a price section, on which you append /register.

Example for the EUR/USD Spot:

The price's reference is /market/sources/FOREX/currency/EURUSD/terms/EURUSDSP/price so the full URI is /market/sources/FOREX/currency/EURUSD/terms/EURUSDSP/price/register.

> {"seq": 42, "data": "/market/sources/FOREX/currency/EURUSD/terms/EURUSDSP/price/register"}
  < {"seq":42,"data":{"code":"registerPrice","quote":"/market/sources/FOREX/currency/EURUSD/terms/EURUSDSP","success":true}}

You can check if the listener's registering command was successful by waiting for a message with the seq value equal to the one you sent (42 in the previous example), and data object with a code field equal to registerPrice; the data.success is the definitive field to determine whether the registration request was successful, in the form of a boolean.

Warning:

You might receive prices before the register response !

The prices you will receive are formatted like this:

{
  "seq": -1,
  "data": "(one of the price type as described in *Structure of a price*)"
}

The seq field will always be equal to -1.

Unregister a price listener

Instead of appending /register, append /unregister to the price's reference.

Example for the EUR/USD Spot:

> {"seq": 42, "data": "/market/sources/FOREX/currency/EURUSD/terms/EURUSDSP/price/unregister"}
  < {"seq":42,"data":{"code":"unregisterPrice","quote":"/market/sources/FOREX/currency/EURUSD/terms/EURUSDSP","success":true}}

You can check if the listener's unregistering command was successful by waiting for a message with the seq value equal to the one you sent (42 in the previous example), and data object with a code field equal to unregisterPrice; the data.success field would equal false if anything wrong happened, else true.

Register a news listener

A news listener is built with the news source's reference, as described in the Fetch a news item section, on which you append /article/register.

Example for the AFP market source:

> {"seq": 42, "data": "/news/sources/AFP/article/register"}
  < {"seq":42,"data":{"code":"registerNews","source":"/news/sources/AFP","success":true}}

Warning:

You might receive news before the register response !

The news articles you will receive are formatted like this:

{
  "seq": -1,
  "data": "(a news article as described in *Structure of a news article*)"
}

Unregister a news listener

Instead of appending /register, append /article/unregister to the news source's reference.

Example for the AFP market source:

> {"seq": 42, "data": "/news/sources/AFP/article/unregister"}
  < {"seq":42,"data":{"code":"unregisterNews","source":"/news/sources/AFP","success":true}}

Establish a long polling connection

Should a websocket connection not be possible in your development scenario, this could be due to diverse network limitations, you can still resort to long­ polling.

To do that, you register all the price/news listeners you require and then regularly ask the market server for the things that changed since your last request. To query the server for the latest updates only, do a GET request to the /netbus endpoint.

Example:

Supposing we would like to retrieve the latest prices for the EMA first continuous delivery and the EMA second continuous delivery.

The references:

First, we register all our prices listeners in a single POST request as seen earlier.

user@computer:~$ curl -X POST "https://market.financeagri.com/api" \
-H "Accept: application/json, text/*;q=0.2" \
-H "Accept-Charset: utf-8" \
-H "Accept-Encoding: gzip, deflate" \
-H "Access-Control-Request-Headers: x-session-token" \
-H "X-Session-Token: 85045E8E-CE68-2956-9E11-96F51837C71B" \
-H "Content-Type: application/json; charset=utf-8" \
-d '["/market/sources/EURONEX/future/EMA/deliveries/EMAC01/price/register","/market/sources/EURONEX/future/EMA/deliveries/EMAC02/price/register"]' \
--compressed

Then, we make regular requests for new prices:

user@computer:~$ curl "https://market.financeagri.com/api/netbus" \
-H "Accept: application/json, text/*;q=0.2" \
-H "Accept-Charset: utf-8" \
-H "Accept-Encoding: gzip, deflate" \
-H "Access-Control-Request-Headers: x-session-token" \
-H "X-Session-Token: 85045E8E-CE68-2956-9E11-96F51837C71B" \
-H "Content-Type: application/json; charset=utf-8" \
--compressed

After which, you will be required to repeat the same process in order to obtain further updates. This is a long-poll request meaning that the call will return an array of prices only when these have been updated.