A forex API that answers in JSON
Every answer of the API is JSON: candle pages by REST, frames on the live WebSocket, and refusals with a code a program can branch on. Prices travel as strings, so no decimal is ever rounded on the way.
- A page of candles
- GET GET /v1/candles answers an object with the symbol, the timeframe, a list of candles in ascending time, and next_before, the cursor to the page before it, null when there is nothing older for your account. A page holds up to 5 000 candles.
- A candle
- Each candle has time, the bar's open time in UTC as a string in the RFC 3339 format, then open, high, low and close, and volume. Every one of them is a string, exactly as served: parse it into a decimal type, not a float, if the last digit matters to you.
- Why prices are strings
- A binary float cannot hold most decimal prices exactly, and a JSON parser turns a number into one by default. Sending the price as a string leaves the choice of type to you, and a price you store is the price we sent.
- Refusals
- A refusal is a JSON object whose detail starts with a code in capitals, such as CUSTOMER_TRIAL_EXPIRED or SYMBOL_NOT_ALLOWED: branch on the part before the first colon. A validation error adds fields, each with where it sits in your request and why it was refused. The reference lists every code with what a client should do.
- On the WebSocket
- Frames are JSON too: you send a subscribe frame with a request id and a payload naming the channels, and receive quote frames with the bid and ask, and candle frames as bars close. A refused frame is answered by an error frame with a code; a refused connection is closed with code 1008 and the code as its reason.
- The token
- POST /v1/tokens takes a JSON body with your end user's id and answers a JSON object with the access token, its lifetime in seconds and the symbols it may read. The token lives 12 hours.
- A machine-readable contract
- The whole REST contract is an OpenAPI document, so a client can be generated from it in your language; a dated changelog says what changed in it and when.
- What it costs
- Sold by capacity, from CHF 500 a month: the monthly peak of simultaneous connections, and slices of 1 000 bars; an empty page costs nothing. The free trial lasts 7 days, on EURUSD · XAUUSD.
Facts as of 06.10.2026.
First call
# 1. your server exchanges the key for a short-lived token
export ADONA_API_KEY="${ADONA_API_KEY:-adk_live_...}"
RESP=$(curl -s https://api.adona-robot.com/v1/tokens \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $ADONA_API_KEY" \
-d '{"end_user_id":"u-42"}')
TOKEN=$(echo "$RESP" | grep -o '"access_token":"[^"]*' | cut -d'"' -f4)
[ -n "$TOKEN" ] || echo "refused: $RESP"
# 2. the token reads candles
curl -s 'https://api.adona-robot.com/v1/candles?symbol=EURUSD&timeframe=S1&limit=1000' \
-H "Authorization: Bearer $TOKEN"The quickstart: from the key to the live stream, step by step