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.
Current endpoints
Section titled “Current endpoints”| 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.
Authenticate
Section titled “Authenticate”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_TOKENAn investor password creates read_only access. The server returns TRADING_ACCESS_REQUIRED if that session calls a trading endpoint.
Read the account
Section titled “Read the account”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.
Read open positions
Section titled “Read open positions”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 a position
Section titled “Open a position”OPEN submits a market order. The server executes against its authoritative quote, not a client-supplied price.
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.
Modify a position
Section titled “Modify a position”Send an absolute stop-loss value, take-profit value, or both. Send null to remove a level.
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.
Close a position
Section titled “Close a position”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:
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}'Stream position events
Section titled “Stream position events”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=1842The 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.
Safety model
Section titled “Safety model”- Keep the session token outside browser code and public repositories.
- Use a unique
client_request_idfor every intendedOPENaction. - Reuse the same identifier when retrying an
OPENrequest after a timeout. - Process stream events by
eventIdand 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.
Copier flow
Section titled “Copier flow”- Connect the source
Sign in with an investor password when the integration only needs to observe the source account.
- Read the snapshot
Fetch the account and current positions before consuming live events.
- Open the event stream
Supply the last processed cursor so reconnects replay missed position events.
- Apply copier rules
Map symbols, calculate destination volume, enforce limits, and reject unsupported trades.
- Execute on the destination
Sign in with the destination trading password and submit an idempotent trade action.
- Reconcile
Regularly compare the destination position snapshot with the copier’s expected state.
Error response
Section titled “Error response”{ "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.