Skip to content
API status
Automatic trading

Trader API integrations

Plan safe copier and trading integrations with the Koneth Trader API.

The Koneth Trader API connects an external automation service to one trading account on one Koneth trading server. It is separate from the Management API used by organizations.

Endpoint Purpose Investor password Trading password
POST /v1/auth/login Create an account-scoped session Yes Yes
GET /v1/account Read balance, equity, margin, and account details Yes Yes
GET /v1/events Replay execution events after a cursor Yes Yes
GET /api/v1/positions Read open positions and current valuation Yes Yes
POST /v1/trade Open a market position No Yes
POST /api/v1/positions/{positionId}/modify Change protection levels No Yes
POST /api/v1/positions/{positionId}/close Fully or partially close a position No Yes
GET /v1/stream Open a replayable position-event WebSocket Yes Yes

Each request goes to the base URL of the trading account’s server. A session for one server cannot be used on another server.

Terminal window
curl --request POST "https://YOUR-SERVER.example.com/v1/auth/login" \
--header "Content-Type: application/json" \
--data '{
"account": "10002341",
"password": "YOUR_TRADING_OR_INVESTOR_PASSWORD"
}'
{
"access_token": "SESSION_TOKEN",
"token_type": "Bearer",
"expires_in": 604800,
"access_mode": "trade",
"account": "10002341",
"server": "Koneth Demo"
}

Send the session token in the Authorization header:

Authorization: Bearer SESSION_TOKEN

An investor password creates read_only access. The server returns TRADING_ACCESS_REQUIRED if that session calls a trading endpoint.

Terminal window
curl "https://YOUR-SERVER.example.com/v1/account" \
--header "Authorization: Bearer SESSION_TOKEN"
{
"account": "10002341",
"name": "Copier Demo",
"balance": 10000,
"equity": 10125.42,
"margin": 350.1,
"free_margin": 9775.32,
"margin_level": 2892.15,
"floating_profit": 125.42,
"currency": "USD",
"leverage": 100,
"environment": "demo",
"access_mode": "trade"
}

Account values are refreshed from authoritative prices before the response.

Terminal window
curl "https://YOUR-SERVER.example.com/api/v1/positions" \
--header "Authorization: Bearer SESSION_TOKEN"
{
"positions": [
{
"id": "c4cd8f3e-96df-4c15-aa08-6e2a8e43ee92",
"orderId": "5c675e4d-35c1-411b-acd5-5391865d344b",
"symbol": "XAUUSD",
"side": "BUY",
"volume": 0.1,
"openPrice": 3341.2,
"currentPrice": 3346.8,
"stopLoss": 3300,
"takeProfit": 3400,
"status": "OPEN",
"floatingPnl": 56,
"usedMargin": 334.12,
"openedAt": "2026-08-25T12:10:30.120Z",
"closedAt": null,
"providerTimestamp": 1787669462442,
"sequence": "1842",
"source": "market-provider"
}
]
}

OPEN submits a market order. The server executes against its authoritative quote, not a client-supplied price.

Terminal window
curl --request POST "https://YOUR-SERVER.example.com/v1/trade" \
--header "Authorization: Bearer SESSION_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"action": "OPEN",
"client_request_id": "copier-20260825-000001",
"symbol": "XAUUSD",
"side": "BUY",
"volume": 0.10,
"stop_loss": 3300,
"take_profit": 3400
}'
{
"action": "OPEN",
"client_request_id": "copier-20260825-000001",
"order_id": "5c675e4d-35c1-411b-acd5-5391865d344b",
"position_id": "c4cd8f3e-96df-4c15-aa08-6e2a8e43ee92",
"status": "FILLED",
"execution_price": 3341.2,
"executed_at": "2026-08-25T12:10:30.120Z"
}

client_request_id must be unique for each intended open action. Retrying the same request with the same identifier returns the original order. Reusing it with different order parameters returns IDEMPOTENCY_KEY_REUSED.

Send an absolute stop-loss value, take-profit value, or both. Send null to remove a level.

Terminal window
curl --request POST \
"https://YOUR-SERVER.example.com/api/v1/positions/c4cd8f3e-96df-4c15-aa08-6e2a8e43ee92/modify" \
--header "Authorization: Bearer SESSION_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"stopLoss": 3320,
"takeProfit": 3410
}'

Repeating the same absolute modification is safe. The server returns the current protection values without creating another position event when nothing changed. It rejects modifications to a closed position.

Terminal window
curl --request POST \
"https://YOUR-SERVER.example.com/api/v1/positions/c4cd8f3e-96df-4c15-aa08-6e2a8e43ee92/close" \
--header "Authorization: Bearer SESSION_TOKEN" \
--header "Content-Type: application/json" \
--data '{}'

An empty body closes the full position at the server’s authoritative closing price. To close only part of it, send a positive volume and a unique Idempotency-Key header:

Terminal window
curl --request POST \
"https://YOUR-SERVER.example.com/api/v1/positions/c4cd8f3e-96df-4c15-aa08-6e2a8e43ee92/close" \
--header "Authorization: Bearer SESSION_TOKEN" \
--header "Content-Type: application/json" \
--header "Idempotency-Key: copier-close-20260825-000001" \
--data '{"volume": 0.05}'

Open a WebSocket connection to /v1/stream with the bearer token in the handshake’s Authorization header. Add the last processed cursor when reconnecting:

wss://YOUR-SERVER.example.com/v1/stream?cursor=1842

The first frame confirms the connection and contains any missed events after that cursor:

{
"type": "READY",
"cursor": 1844,
"events": [
{
"eventId": "b4ad9d81-2c26-41c0-9200-004e10b608da",
"cursor": 1843,
"type": "ORDER_FILLED",
"orderId": "5c675e4d-35c1-411b-acd5-5391865d344b",
"positionId": null,
"payload": {
"symbol": "XAUUSD",
"side": "BUY",
"volume": 0.1,
"orderType": "MARKET",
"executionPrice": 3341.2
},
"occurredAt": "2026-08-25T12:10:30.120Z"
}
],
"replayTruncated": false
}

Live frames use type: "EVENTS". The event types include POSITION_OPENED, POSITION_MODIFIED, POSITION_REDUCED, POSITION_CLOSED, order lifecycle events, and SWAP_ACCRUED.

Store the highest cursor only after your application has durably processed every earlier event. If replayTruncated is true, reconcile with GET /api/v1/positions before continuing. Send the text frame ping to receive a PONG response.

Browser WebSocket clients cannot add an Authorization header. Connect from a trusted backend or native client instead of exposing the session token in browser code.

  • Keep the session token outside browser code and public repositories.
  • Use a unique client_request_id for every intended OPEN action.
  • Reuse the same identifier when retrying an OPEN request after a timeout.
  • Process stream events by eventId and ignore duplicates.
  • Resume the stream from the last acknowledged cursor after reconnecting.
  • Apply position-size and symbol allowlists in the copier before submitting a trade.
  • Back off with jitter when the server returns an overload or temporary availability error.
  1. Connect the source

    Sign in with an investor password when the integration only needs to observe the source account.

  2. Read the snapshot

    Fetch the account and current positions before consuming live events.

  3. Open the event stream

    Supply the last processed cursor so reconnects replay missed position events.

  4. Apply copier rules

    Map symbols, calculate destination volume, enforce limits, and reject unsupported trades.

  5. Execute on the destination

    Sign in with the destination trading password and submit an idempotent trade action.

  6. Reconcile

    Regularly compare the destination position snapshot with the copier’s expected state.

{
"error": {
"code": "TRADING_ACCESS_REQUIRED",
"message": "Trading password authentication is required for trade actions"
}
}

Validation errors use HTTP 400 and include a stable VALIDATION_ERROR code. Authentication errors use 401, permission errors use 403, state conflicts use 409, and unexpected server failures use 500 with a stable error code.