Webhooks
Receive signed position lifecycle notifications and process retries safely.
Use webhooks to start and stop event-driven workflows in your organization’s backend. Your application owns its trading rules and decides what to do with each event.
Available events
Section titled “Available events”| Event | When it is sent |
|---|---|
position.opened |
A market or pending order creates an open position. |
position.closed |
A position is fully closed. |
position.reduced |
A position is partially closed, including the remaining volume and closed volume. |
finance.transaction.completed |
A deposit or withdrawal is committed to the account ledger. |
account.metrics.updated |
An account metric batch is accepted for a subscribed account. |
Register an HTTPS receiver in Koneth Console → Webhooks, select the events, and store the signing secret securely. Follow Verify webhook signatures.
Activate your endpoint
Section titled “Activate your endpoint”A new endpoint is created pending and receives no events until it answers Koneth’s verification challenge. In Console → Webhooks, click Verify on the endpoint row. Koneth then POSTs this body to your URL:
{ "type": "koneth.endpoint.verify", "challenge": "9f2c4d1e7a8b3c5d6e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d"}Your receiver must reply with a 2xx status and a JSON body that echoes the same value:
{ "challenge": "9f2c4d1e7a8b3c5d6e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d" }The challenge is 64 hexadecimal characters, and a new one is issued on every attempt.
| Response | Result |
|---|---|
2xx with the matching challenge |
The endpoint becomes active and starts receiving deliveries. |
Any non-2xx status |
Verification fails with the status Koneth received. |
2xx without a matching challenge |
Verification fails with “Endpoint challenge did not match”. |
The verification request is not signed — it carries no X-Koneth-Signature header — because the signing secret is not in use yet. Verify only that the challenge matches the value in the body. Koneth waits up to eight seconds for the response.
An endpoint that is never verified stays pending and is skipped by delivery, so a receiver that returns 200 for everything but ignores the body will never activate.
Choose which servers deliver
Section titled “Choose which servers deliver”Applies to on the endpoint controls its scope:
| Selection | What it receives |
|---|---|
| All servers (default) | Events from every server in the organization. |
| A single server | Events from that server only. |
The scope applies until the endpoint is changed. Every delivery still names its source server in data.serverId, so an organization-wide endpoint can route on that field. If a server is deleted, its server-scoped endpoints are disabled instead of silently widening to the organization.
Change or remove an endpoint
Section titled “Change or remove an endpoint”Edit on an endpoint row changes its URL, the events it listens for, or its scope. Changing the events or the scope takes effect immediately and does not interrupt delivery.
Moving the URL is different. The verification on file was answered by the address that was there before, so a moved endpoint goes back to pending with a fresh challenge and receives nothing until it is verified again. The API reports this as verificationRequired on the update response, and the dialog warns before you save.
Delete removes the endpoint and the log of what was delivered to it, and deliveries stop at once. It cannot be undone. If the receiver is only being rebuilt, disable the endpoint instead and enable it when it is ready.
Payload
Section titled “Payload”{ "version": 1, "id": "d6b3ef8d-95a8-462d-90a5-3ef8fc3a6533", "type": "position.opened", "occurredAt": "2026-08-30T14:25:39.804Z", "data": { "serverId": "srv_123", "accountNumber": "100042", "positionId": "pos_456", "symbol": "EURUSD", "side": "BUY", "volume": 1, "executionPrice": 1.16542 }}Every payload carries version, a stable id, the type, the source occurredAt, and data with serverId and accountNumber. The rest of data depends on the event:
| Event | Additional data fields |
|---|---|
position.opened |
orderId, positionId, dealId, clientOrderId, status, executionPrice, commission, balance, executionVersion, executedAt |
position.closed |
positionId, symbol, side, closedVolume, remainingVolume, status, executionPrice, realizedPnl, commission, reason, closedAt |
position.reduced |
Same fields as position.closed, with the still-open remainingVolume and a null closedAt |
finance.transaction.completed |
referenceId, type (deposit or withdrawal, with amount signed accordingly), amount, balanceAfter |
account.metrics.updated |
eventId, sequence, measuredAt, balance, equity, usedMargin, freeMargin, marginLevel, unrealizedProfit, dailyDrawdown, totalDrawdown, accountStatus |
occurredAt is the source event time. Trade, deal, and transaction records expose their own timestamps through the paginated account endpoints. The delivery timestamp header records the HTTP attempt and is not the trade time.
Process safely
Section titled “Process safely”Verify the signature over the raw body before parsing it. Store id with a uniqueness constraint, return 2xx after durable acceptance, and run business rules asynchronously. Retries are at least once and can arrive out of order.
Delivery attempts use the configured webhook.delivery credit price. A failed receiver, exhausted credits, or a network problem can delay delivery, so silence is not proof that an account has no activity.
Use webhooks with live metrics
Section titled “Use webhooks with live metrics”- Receive
position.openedand subscribe that account to Live account metrics. - Evaluate every consecutive live valuation using your organization’s rules.
- Receive
position.closedand query positions withstatus=open&limit=1. - Unsubscribe when
pagination.totalis0and the account no longer needs live monitoring.
This keeps lifecycle notifications separate from continuous valuations and avoids polling the Management API for every price change.