The following section describes the API that an exchange must implement in order to integrate with the Nomics platform. From the root of your API, you must implement the following endpoints.
There are many endpoints in this spec, and not all of them are required. They are marked with one of the following:
- Required: This endpoint must be implemented in order for Nomics to integrate.
- Preferred: This endpoint is the simplest and provides the highest quality data to Nomics.
- Optional: While not required, this endpoint adds extra information or reduces load or latency.
- Discouraged: This endpoint is present for maximum compatibility, but Preferred endpoints should be implemented whenever possible.
To test your integration prior to submission, run the following auditing tool (requires NodeJS and NPM to be installed):
npx nomics-platform@latest audit https://path-to-your-api-root
If data functionality needs to be audited prior to all metadata being available,
you can use the NOMICS_PLATFORM_RELAX
environment variable to temporarily relax
requirements for description length, logo URL, and location. This flag will also
skip checks for markets type
and active
flags.
NOMICS_PLATFORM_RELAX=1 npx nomics-platform@latest audit https://path-to-your-api-root
Fill out the Nomics Exchange Listing Form in its entirety.
The /info
endpoint returns information about the exchange as a whole, and is used by Nomics to display information about your exchange to users.
None
JSON object containing the following properties:
Required:
name
: The name of the exchangedescription
: An exchange description of at least 1000 characters in plain text (no html)location
: The primary country the exchange operates fromlogo
: A HTTPS URL to your exchange's logo. It should be an SVG with a square aspect ratio or a 500x500 PNGwebsite
: A URL to your exchangetwitter
: Twitter username to your exchange (without @)version
: The Nomics Platform Specification versioncapability
: An object describing the endpoints this integration implements. If not provided, false is assumed for all capabilities. It a capability is ommitted, it is assumed false.markets
: boolean indicating markets endpoint is implementedtrades
: boolean indicating trades endpoint is implementedtradesByTimestamp
: boolean indicating trades by timestamp endpoint is implementedtradesSocket
: boolean indicating trades socket endpoint is implementedorders
: boolean indicating orders endpoint is implementedordersSocket
: boolean indicating orders socket endpoint is implementedordersSnapshot
: boolean indicating orders snapshot endpoint is implementedcandles
: boolean indicating candles endpoint is implemented
Example:
{
"name": "Exchange Name",
"description": "An exchange description of at least 1000 characters in plain text (no html)",
"location": "Country Name",
"logo": "https://example.com/exchange-logo.png",
"website": "https://example.com",
"twitter": "example",
"version": "1.0",
"capability": {
"markets": true,
"trades": true,
"ordersSnapshot": true,
"candles": false,
"ticker": false
}
}
The /markets
endpoint returns a list of all available markets on your exchange and is used to query other endpoints on your API.
None
JSON array of objects (one for each market) containing the following properties:
Required:
id
: Your exchange's unique ID of the market as a string.type
: The type of the market:spot
: If the asset actually being traded is for immediate delivery. This is the most common type of cryptocurrency market.derivative
: If the market represents trading activity on any kind of contract or underlying asset. Examples of a derivative market are futures, options, and perpetual markets.index
: If the market represents the price of an index directly from its methodology, and it has no order book, or trading activity. This should only be used to price the underlying index and not for markets on that index. Volume for indexes should always be1
.
base
: The base asset of the marketquote
: The quote asset of the market
Optional:
active
: Boolean representing if the market is currently active. Defaults totrue
.subtypes
: An array representing additional context based on the market'stype
. Multiple subtypes are allowed.type
:spot
: No subtypes at this timetype
:derivative
:perpetual
: If the market is a perpetual futures market regardless of underlying assetsfuture
: If the market is a futures market regardless of underlying assetsoption
: If the market represents an option regardless of underlying assets
type
:index
: No subtypes at this time
settlement
: The settlement asset of the market. Used for derivative markets where the settlement currency may or may not differ from the base or quote currencies.underlying
: The underlying asset of the market upon which a derivative’s price is based. Used for derivative markets and is typically an index.market_url
: The full exchange URL for the marketdescription
: A description of the market
Example:
[
{
"id": "ETH_BTC",
"type": "spot",
"base": "ETH",
"quote": "BTC"
},
{
"id": "BTC_USDT",
"type": "derivative",
"base": "BTC",
"quote": "USDT",
"active": true,
"subtypes": ["perpetual", "future"],
"settlement": "USDT",
"market_url": "https://www.binance.com/en/futures/BTCUSDT",
"description": "Binance perpetual futures market for BTC quoted in USDT"
},
{
"id": "in_xrpxbt",
"type": "index",
"base": "XRP",
"quote": "XBT",
"active": true,
"market_url": "https://www.cfbenchmarks.com/indices/XRP/XBT/RTI/seconds"
}
]
The /trades
endpoint returns executed trades historically for a given market (provided via parameters). It allows Nomics to ingest all trades from your exchange for all time.
market
Required Your exchange's market ID from the/markets
endpointsince
A trade ID from a previous/trades
response. If none is provided, the oldest trades should be returned
JSON array of trade object for the given market after (and not including) the trade ID provided, with the following properties:
Required:
id
: A string ID for the trade that is unique within the scope of the markettimestamp
: Timestamp of the trade in RFC3339 in UTCprice
: The price for one unit of the base currency expressed in the quote currency as a string that is parseable to a positive number.
One of the following are required:
amount
: The amount of the base currency that was traded as a string that is parseable to a positive number. Only one ofamount
andamount_quote
are required but both are encouraged.amount_quote
: The amount of the quote currency that was traded as a string that is parseable to a positive number. Only one ofamount
andamount_quote
are required but both are encouraged.
Optional:
order
The ID of the order that was executed to produce this tradetype
The type of order that resulted in the trade: [market
,limit
]side
The direction of the trade [buy
,sell
]raw
The raw data of the trade as represented by the exchange. This can be any JSON encodable data.
Example:
[
{
"id": "123456789",
"timestamp": "2006-01-02T15:04:05.999Z",
"price": "123.45678",
"amount": "48.75",
"amount_quote": "0.02051282051",
"order": "8afe76fabe8befa",
"type": "market",
"side": "buy",
"raw": [123456789, 1136214245, 123.45678, 48.75, "8afe76fabe8befa", "m"]
}
]
Notes:
- The number of trades returned is up to the exchange's implementation.
- Returning an empty array signifies there are no newer trades than the given
since
ID.
If you implement /trades
you do not need to implement /trades-by-timestamp
.
The /trades-by-timestamp
endpoint is nearly identical to the /trades
endpoint. The core difference is that the since
parameter is an RFC3339 timestamp instead of an ID. Otherwise, the parameters and response are the same.
This endpoint is provided to maximum compatibility with exchanges that can't paginate trades based on ID. It is inferior to paging by ID because in extremely high volume instances there may be more trades executed at the same timestamp than fit on a single page, causing a gap in trade data. If possible, /trades
should be used instead.
market
Required Your exchange's market ID from the/markets
endpointsince
A timestamp from a previous/trades-by-timestamp
response in RFC3339 format. If none is provided, the oldest trades should be returned
Same as /trades
.
The /orders/snapshot
endpoint returns the current order book for a given market. It allows Nomics to get a simple snapshot of open orders.
market
Required Your exchange's market ID from the/markets
endpoint
JSON object of all bids and asks that are currently open for the provided market, with the following properties:
Required:
bids
: a list of all open bid ordersasks
: as list of all open ask orderstimestamp
: the timestamp this snapshot was created in RFC3339 in UTC
Each order is a tuple with the following entries:
Required:
price
: the price for one unit of the base currency expressed in the quote currency as a JSON number or numeric stringamount
: the amount of the base currency available at this price point as a JSON number or numeric string
Example:
{
"bids": [[8123.45678, 10.0]],
"asks": [[8120.0, 5.0]],
"timestamp": "2006-01-02T15:04:05.999Z"
}
Bids must be sorted in descending order and asks must be sorted in ascending order. This means the first bid is the best bid and the first ask is the best ask.
When returning orders, perform as little aggregation as possible (ideally none) and include as many orders as possible (ideally all).
If you implement /trades
you do not need to implement /candles
.
The /candles
endpoint returns open, high, low, close, and volume data for a given market in 24 hour, 1 hour, and 1 minute periods. It allows Nomics to get at least a 24 hour picture of a market, as well as a high level historical view when available. Implementing this endpoint requires 1d
, 1h
, and 1m
candle intervals.
We highly recommend implementing the /trades
endpoint instead of the /candles
endpoint. The /candles
endpoint should be used as a last resort if implementing /trades
is not possible.
market
Required Your exchange's market ID from the/markets
endpointinterval
Required The interval of the OHLCV candles. Valid values are1d
,1h
, and1m
.
JSON array of OHLCV Candles for the given market and interval. If daily candles are available, as many as possible should be returned (preferably to inception). Otherwise, candles should be returned fixed 24 hour, 1 hour, or 1 minute intervals. Timestamps should be aligned to candle size. IE: Midnight UTC (2018-01-01T:00:00:00.000Z
) for 1d
, to the hour (2018-01-01T03:00:00.000Z
) for 1h
, and to the minute (2018-01-01T03:03:00.000Z
) for 1m
. Candles should be sorted by timestamp ascending. Candles have the following properties:
Required:
timestamp
: timestamp of the start of the candle in RFC3339 aligned to candle size in UTCclose
: close price of the asset in the quote currency as a string parseable to a positive numberopen
: open price of the asset in the quote currency as a string parseable to a positive numberhigh
: highest price of the asset in the quote currency as a string parseable to a positive numberlow
: lowest price of the asset in the quote currency as a string parseable to a positive number
One of the following are required:
volume
: volume of the asset in the base currency as a string parseable to a positive number. Only one ofvolume
andvolume_quote
are required but both are encouraged.volume_quote
: volume of the asset in the quote currency as a string parseable to a positive number. Only one ofvolume
andvolume_quote
are required but both are encouraged.
Candles are expected to include a minimum number of records for a given interval and to include the "last candle" within the given timeframe:
1d
: 7 candles with last candle occuring within a rolling 48 hours1h
: 24 candles with last candle occuring within a rolling 2 hours1m
: 60 candles with last candle occurring within a rolling 10 minutes
If you implement /trades
you do not need to implement /ticker
.
The /ticker
endpoint returns last prices (close) and 24h volume data for a given market. It allows Nomics to get a current snapshot of a given market. Implementing this endpoint requires the attributes above in addition to a market symbol and timestamp. Optional attributes include open, high, low, bid, and ask prices.
We highly recommend implementing the /trades
endpoint instead of the /ticker
endpoint. The /ticker
endpoint should be used as a last resort if implementing /trades
is not possible.
market
Required Your exchange's market ID from the/markets
endpoint
JSON object of the current ticker values for the given market. Tickers have the following properties:
Required:
close
: the current price of the asset in the quote currency as a string parseable to a positive numbertimestamp
: timestamp of the current ticker values in RFC3339 in UTCraw
: the raw ticker values as a JSON object
One of the following are required:
volume
: volume of the asset in the base currency as a string parseable to a positive number. Only one ofvolume
andvolume_quote
are required but both are encouraged.volume_quote
: volume of the asset in the quote currency as a string parseable to a positive number. Only one ofvolume
andvolume_quote
are required but both are encouraged.
Optional:
high
: highest price of the asset in the quote currency as a string parseable to a positive numberlow
: lowest price of the asset in the quote currency as a string parseable to a positive numberask
: open price of the asset in the quote currency as a string parseable to a positive numberbid
: open price of the asset in the quote currency as a string parseable to a positive number
Tickers are expected to include the most current data for a given market.