Skip to main content

Idempotency

Senticore exposes two separate mechanisms. They are not interchangeable:

MechanismAxisUse
Idempotency-Key headerResponse dedupSafe HTTP retry for signed action submit, delegated batch submit, and replace/cancel flows.
clientOrderId (cloid)Order identityStrategy-level order label carried in the signed payload and echoed back on BSL full results, execution streams, and drop-copy where provisioned.

clientOrderId is not a dedup key. It does not collapse duplicate submissions, and the server keeps no (account, clientOrderId) lookup that returns a prior order. Use Idempotency-Key for retry safety; use clientOrderId to correlate your own order id with engine results.

Idempotency-Key (retry safety)

For signed actions and delegated batches, send an Idempotency-Key header when a network retry may happen. Reuse the same key only for the same intended payload. Re-submitting the same key returns the original response instead of re-applying the action.

clientOrderId (order identity)

clientOrderId is part of the signed ActionPayload. When present it is folded into both the signing hash and the derived OrderId, so two payloads that differ only by clientOrderId sign to different hashes and resolve to different order ids. When absent it is omitted from the canonical bytes (it is not signed as null), which is why existing golden vectors and clients that never set it are unaffected. See Local Action Signing.

On the direct-HTTP/BSL signed-action path and the FIX path, clientOrderId (FIX ClOrdID tag 11) is threaded into the signed payload, echoed in full response-mode actionResults (HotpathOrderResult.clientOrderId), and carried into the private execution stream or drop-copy stream where provisioned.

const order = await client.placeOrder({
market: 'BTC-USDC',
side: 'buy',
price: '60000',
quantity: '0.01',
clientOrderId: 'my-strategy-12345',
});
Agent / delegated path does not carry cloid into the engine

On the agent (delegated) path the signed engine ActionPayload is built with client_order_id = None, so the cloid is not in the signed bytes, the derived OrderId, the engine state, or the state_root. Drop-copy records for agent orders therefore report clientOrderId = null. A clientOrderId you pass on a delegated place-order survives only as off-engine sidecar metadata for a single place-order (not for agent batches); do not rely on it round-tripping through engine results on this path.

Retention

Idempotency-Key dedup state is retained for the reconciliation window below; after it lapses a client may reuse the same key. clientOrderId is not retained as a dedup record - it lives only inside the signed payload and the results that echo it.

StateRetention
Active orderUntil terminal state
Terminal order7 days for reconciliation
Historical fillStandard account history retention

Best practices

  • Generate Idempotency-Key per submitted payload and persist it until a terminal response is known.
  • Never reuse a key for a different intended action or order.
  • Treat an idempotency conflict as "already responded, fetch state".
  • Generate clientOrderId deterministically from your internal order id; use UUID v4 if no deterministic source exists.
  • To correlate engine results back to your order, read clientOrderId from BSL full response-mode actionResults and from the private execution stream or drop-copy (direct-HTTP/BSL and FIX paths only).
  • To cancel or replace, target the engine order_id (the derived OrderId), not the clientOrderId - cloid is a label, not a server-side handle.

Protocol equivalents

clientOrderId is the same signed-payload field across surfaces:

SurfaceField
HTTP (signed action)clientOrderId in the action payload
FIXClOrdID tag 11
BSL compact order entryclient_order_id field in the signed action payload