Skip to main content
Developers

Quickstart

Create a key, read a price, then open and close a demo position. About five minutes.

Before you start

  • A JAFX demo account you can log into at https://terminal.jafx.com (if you have none, open one in the JAFX client area, under Accounts).
  • curl, Python 3.9 or later (with httpx), or Node.js 20 or later.

1. Create an API key

  1. Log into the web terminal with your demo account, choosing Demo Server at sign-in.
  2. Open Developers in the side menu and choose Create API key.
  3. Pick the Trading preset, give the key a name and review its limits.
  4. Under Only allow these IP addresses, enter the address your program calls from (recommended: a locked key can't be used anywhere else, even if it leaks). To try it from a laptop on a changing address, tick Let this key be used from any IP address instead.
  5. For a bot that runs for days, tick Keep my bots trading around the clock (see Around the clock). Without it, your keys trade for 24 hours after each sign-in.
  6. Confirm with your account's master password. This fresh login proves the request comes from you; your terminal session stays as it is.
  7. Copy the key now. It is shown once and looks like jafx_demo_….

Keep the key out of your source code. An environment variable is the simplest place:

Shell
export JAFX_API_KEY='jafx_demo_…'

2. Check the key

GET /me returns the key's account and its server, scopes, limits and whether trading is currently allowed.

curl
curl https://terminal.jafx.com/trading-api/v1/me -H "Authorization: Bearer $JAFX_API_KEY"
Response (abridged)
{
  "key_id": "k7mx2v9qr4tz8w1b6nfa",
  "name": "my first bot",
  "account": 123456,
  "server": "demo",
  "mode": "demo",
  "scopes": ["market:read", "account:read", "trade"],
  "constraints": {
    "max_volume_per_order": "1.00",
    "max_open_positions": 20,
    "orders_per_minute": 30,
    "daily_loss_limit": { "type": "percent", "value": "10" }
  },
  "trading": { "mode": "on", "level": "env", "reason": null }
}

Note the account number: the account and order endpoints use it.

3. Read a price

curl
curl "https://terminal.jafx.com/trading-api/v1/quotes?symbols=EURUSD,XAUUSD" -H "Authorization: Bearer $JAFX_API_KEY"
Response
{
  "data": [
    { "symbol": "EURUSD", "bid": 1.11554, "ask": 1.11555, "time": "2026-10-13T09:30:01.242Z", "price_basis": "raw" },
    { "symbol": "XAUUSD", "bid": 4170.05, "ask": 4170.72, "time": "2026-10-13T09:30:01.834Z", "price_basis": "raw" }
  ],
  "missing": []
}

4. Place a demo order

Buy 0.01 lot of EURUSD at market. Every write needs an Idempotency-Key header: a unique value for this order, such as a UUID. If the connection drops, send the same request with the same key again and you will get the original answer instead of a second trade.

curl
export ACCOUNT=123456   # from GET /me

curl -X POST https://terminal.jafx.com/trading-api/v1/accounts/$ACCOUNT/orders \
  -H "Authorization: Bearer $JAFX_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"symbol":"EURUSD","side":"buy","type":"market","volume":"0.01","client_tag":"quickstart"}'
Response 201
{
  "request_id": "01JQ8Z6M3S4X7T2N9CKV5W0HRB",
  "kind": "market",
  "status": "filled",
  "ticket": 5001,
  "client_tag": "quickstart",
  "position": { "ticket": 5001, "symbol": "EURUSD", "side": "buy", "volume": "0.01", "open_price": 1.11555, "profit": "-0.01" }
}
Got a 202?

The broker is still deciding, for example while it covers the trade with a liquidity provider. The body says "status": "pending". Poll GET /accounts/{account}/requests/{request_id} or watch the orders stream; do not send the order again under a new key. See what each answer means.

No uuidgen? Use python3 -c 'import uuid; print(uuid.uuid4())' or any other unique string of up to 64 characters from A–Z a–z 0–9 . _ : -.

5. See the position

curl
curl "https://terminal.jafx.com/trading-api/v1/accounts/$ACCOUNT/positions?client_tag=quickstart" -H "Authorization: Bearer $JAFX_API_KEY"

6. Close it

Close the whole position with an empty body, or part of it with {"volume": "0.01"}.

curl
curl -X POST https://terminal.jafx.com/trading-api/v1/accounts/$ACCOUNT/positions/5001/close \
  -H "Authorization: Bearer $JAFX_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" -d '{}'

7. Watch it live

The WebSocket stream pushes quotes, candles, account changes and order events. A minimal Python listener (pip install websockets):

Python
import asyncio, json, os
import websockets

async def main():
    headers = {"Authorization": f"Bearer {os.environ['JAFX_API_KEY']}"}
    async with websockets.connect("wss://terminal.jafx.com/trading-api/v1/stream", additional_headers=headers) as ws:
        await ws.send(json.dumps({"op": "subscribe", "channels": ["quotes:EURUSD", "orders"]}))
        async for raw in ws:
            print(json.loads(raw))

asyncio.run(main())

Next steps

  • Orders & positions: pending orders, stops, partial closes, tags and every possible answer.
  • Streaming: channels, reconnecting without missing events, and limits.
  • Example bots: complete Python and TypeScript bots to start from.
  • AI agents (MCP): let Cursor, Claude or your own agent use your account.

Automated and AI-driven trading can lose money quickly; nothing in these docs is investment advice.

JAFX (PTY) LTD · FSCA FSP No. 52058 · Trading leveraged derivatives with JAFX carries a high risk of losing money rapidly. It is not suitable for everyone.