Skip to content
API status
Start here

Trade and position management

Place, modify, and close trades on a trading account through the Management API.

The Management API can trade on behalf of an account, not just create and fund it. Trade and position commands run on the trading server itself, through the same order and position engine the Koneth Terminal uses. Risk checks, margin rules, ledger entries, deals, and webhook events are therefore identical to a trade the trader placed themselves.

Two scopes control access:

Scope Allows
trades:write Open an order, modify a pending order, and cancel a pending order.
positions:write Close or partially close a position, modify protection levels, and close every position on an account.

Every endpoint queues a command and returns 202 with the queued command. The server picks the command up on its next poll and applies it. Poll GET /api/v1/management/commands/{commandId} until the status is succeeded or failed.

{
"command": {
"id": "70d55344-8408-4ccb-b565-0e975cc0168d",
"operation": "position.close",
"status": "queued",
"attempts": 0
},
"duplicate": false
}

A failed command keeps its errorCode and errorMessage. Business rejections, such as an unknown position, an inactive account, or a protection level that is too close to the market, are recorded on the command instead of being returned as an immediate API error.

Every trade request requires an Idempotency-Key header. Reusing the key returns the original command with duplicate: true and 200 instead of queueing a second trade.

The queued command ID is also the idempotency key the server uses for the underlying order or position action. If a delivery is retried, the server returns the original result rather than opening or closing twice. See Idempotency for the general contract.

POST /api/v1/management/servers/{serverId}/accounts/{accountNumber}/trades

Field Notes
symbol Instrument enabled on the server, for example XAUUSD.
side BUY or SELL.
volume Order volume in lots.
orderType MARKET (default), LIMIT, or STOP.
requestedPrice Required for LIMIT and STOP; rejected for MARKET.
stopLoss, takeProfit Optional protection levels, validated against the current quote.
requestId Correlation ID for this action.

A market order fills at the server’s authoritative quote and returns the created position and deal in the command result. A pending order stays PENDING until the price is reached.

Terminal window
curl -X POST "https://api.koneth.com/api/v1/management/servers/$SERVER_ID/accounts/$ACCOUNT_NUMBER/trades" \
-H "Authorization: Bearer $MANAGEMENT_KEY" \
-H "Idempotency-Key: eval-open-1042" \
-H "Content-Type: application/json" \
-d '{
"symbol": "XAUUSD",
"side": "BUY",
"volume": 0.5,
"orderType": "MARKET",
"stopLoss": 4480.5,
"requestId": "eval-open-1042"
}'
Endpoint Purpose
PATCH /api/v1/management/servers/{serverId}/accounts/{accountNumber}/orders/{orderId} Replace the requested price and optionally the stop loss and take profit of a pending order. The new price is validated against current quotes before it is accepted.
POST /api/v1/management/servers/{serverId}/accounts/{accountNumber}/orders/{orderId}/cancel Cancel a pending order. Cancellation is idempotent, so retrying against an already-cancelled order still succeeds.
Endpoint Purpose
POST .../positions/{positionId}/close Close a position. Send volume to close it partially.
PATCH .../positions/{positionId} Set stopLoss and takeProfit. Send null to clear a level.
POST .../positions/close-all Close every open position, or only BUY or SELL when side is set.

close-all closes one position at a time and reports both outcomes:

{
"accountNumber": "7001042",
"requested": 3,
"closedCount": 2,
"closed": [
{ "positionId": "1f4d3c2b-0a19-4c8e-9f21-8b7c6d5e4f30", "status": "CLOSED" }
],
"failedCount": 1,
"failures": [
{ "positionId": "9c1d2e3f-4a5b-6c7d-8e9f-0a1b2c3d4e5f", "error": "POSITION_ALREADY_CLOSED" }
]
}
  1. Confirm the account is trading. Trade commands are accepted only for an active account: a disabled account is paused — its trader stays signed in and can still read, but the server refuses its trades with ACCOUNT_READ_ONLY until it is enabled again — an archived account has been ended, and a pending account is still being provisioned. Main refuses the command up front rather than queueing one the server is going to reject.
  2. Confirm the market is open and the server is connected to the market service. Orders depend on authoritative quotes, so a disconnected server cannot fill them.
  3. Read the account’s positions and orders first if your integration reacts to state it did not create.