Place Order
Submit a hidden, fully-collateralized order, covering the request body, the cryptographic fields the SDK builds for you, and the response lifecycle.
POST /orders submits a new order. The body carries the usual economic fields
(symbol, side, type, amount, price) plus the cryptographic backing that makes
the order private and self-custodial: the collateral-note commitment, a zero-knowledge
input proof, a note opening, a signed contributory viewing key, the current boot
session, and a trading-key signature over the canonical order intent. The
opening is pinned indirectly through the signed note commitment. The SDK builds and signs
all of this from your keys and a deposited note.Authorization: Bearer <token> and a trading-key signature in the body.
How a Darknyx order differs
On a transparent venue, placing an order is just sending its economic fields. On Darknyx an order is fully collateralized by a specific note you already deposited, and it is private, so the request also carries:- the commitment of the collateral note, and a secret opening of that note the in-enclave prover needs;
- a zero-knowledge input proof that the note exists in the on-chain tree and is yours to spend;
- a signed X25519 viewing key for private recovery data;
- the current 32-byte boot session id, so a signed order cannot be replayed into a restarted engine;
- an Ed25519 signature from your trading key over the canonical body, so the engine can attribute, and ultimately settle, the order to you without any per-order on-chain transaction;
- deterministic partial-fill continuation: the settlement circuit derives each change inner from the consumed input inner, so no pre-supplied pool is needed.
Request body
Economic fields
Collateral, opening, and proof
Recovery and replay binding
Signature
Example
Success response
202 Accepted.
202 means the order passed signature and collateral verification and entered
the book, not that it has filled. Track fills via
GET /orders/{order_id} or the
Orders Channel.Order status lifecycle
Idempotency
order_id is your idempotency key. A retry that re-sends the byte-identical
signed order returns the original acceptance (202, same order_id) instead of
a conflict, so a network blip is safe to retry. Reusing an order_id for a
different order (any economic field changed) is a real conflict and returns
409 (code 1201). Because order ids are client-chosen, pick a fresh one per
distinct order.
Verification at intake
Every order is verified before it enters the book. A non-202 response carries a
structured error code; the conditions:
429 includes a Retry-After header. For
high-frequency management prefer the shared
/v1/stream session.Authorizations
Short-lived (≤ 1h) bearer token from POST /auth/token.
Expiry is EXACT — there is no grace period past expires_in, on REST
or on the streaming transport. Refresh on a margin.
A structurally valid, unexpired token is still refused when it has been revoked (401), when the operator has invalidated the tokens the account was holding (401), or when the account is suspended (403). Suspension also blocks issuing a new one, so re-authenticating does not clear it.
Body
The canonical-order wire schema (darknyx-order-v5 signature domain).
All 32/64/16-byte fields are hex-encoded strings; all numeric fields are
JSON integers (u64).
The trading-key signature covers the canonical encoding of the
economic fields, viewing_pubkey, session_id, and arrival_nonce;
the opening fields (owner_commitment, note_inner_hash) are pinned
indirectly because the matcher re-derives
note_commitment from them and rejects a mismatch.
bid = buy base; ask = sell base.
bid, ask limit, ioc, fok Order size in base units.
Worst acceptable price, in quote units per base. Required for
a bid (must be > 0); an ask may use 0 to accept any clearing
price. Every non-zero value must be an integer multiple of the
instrument's tick_size.
Future Solana slot past which this order auto-expires. It must leave the matcher settlement buffer and is bounded by the protocol maximum (currently 4,500 slots) to prevent an unbounded collateral-lock window. Zero is not a GTC sentinel.
16-byte client-chosen id, hex. Must be unique + non-zero.
32-byte hex — Poseidon6 commitment to the collateral note this order is backed by. The opening and VALID_INPUT proof are checked at intake on a settlement-enabled venue. The commitment can reserve at most one live or settlement-pending order in this venue; the on-chain lock remains the final authority at settlement.
Nonce bound into the signed canonical body. After exact-body idempotency handling, it must be strictly greater than every prior accepted nonce for the same trading key.
32-byte hex — the Ed25519 public key that owns this order.
64-byte hex — Ed25519 signature over sha256(canonical body)
from the trading key. Lets the TEE attribute the order to a
specific key without a per-order on-chain tx.
32-byte hex — the collateral note's owner commitment
Poseidon2(DOMAIN_OWNER_V2=32, spending_key). Part of the
input-note opening the in-TEE VALID_MATCH_BATCH prover needs
(the circuit re-derives note_commitment from the opening).
This is the only NOTE-BOUND owner identity an order carries, and
the one settlement derives output notes back to. Verified against
the signed note_commitment at intake. Held in enclave memory
only.
32-byte hex — the collateral note's amount-independent
inner_hash, which anchors both its commitment and unlinkable
note-use tag.
32-byte hex — the merkle root the valid_input_proof was
generated against. A settlement-enabled venue checks its recent-root
mirror before accepting the order; lock_note checks the
authoritative on-chain window again at settlement.
256-byte hex (pi_a ‖ pi_b ‖ pi_c) — the per-note VALID_INPUT
Groth16 proof that gates lock_note. The TEE cannot generate
it (needs the spending key + merkle witness), so the client
supplies it. A settlement-enabled venue verifies it at intake
against (merkle_root, note_use_tag, collateral mint), deriving
the tag from the supplied commitment + private inner hash;
on-chain lock_note verifies it again. Enqueue-only simulator /
load-test deployments do not settle and may deliberately accept
stub proofs.
Required 32-byte contributory X25519 viewing-encryption public key,
hex (deriveViewingEncKeypair().publicKey). The TEE
encrypts each fill's (trade, change) output amounts to it and
writes the ciphertext on-chain, so exact and partial output notes
remain recoverable after a CVM redeploy. It is signed; low-order
encodings that yield an all-zero shared secret are rejected.
Required 32-byte boot session id from GET /info, hex, bound into
the signature. A stale session is rejected even when every other
field and signature is valid. Programmatic clients confirm that the
value matches the boot session bound by /transport-attestation;
a substituted value causes rejection rather than stale-session
acceptance.
^[0-9a-fA-F]{64}$Optional (default 0). Reject fills smaller than this; set equal
to amount for resting all-or-none.
Optional over-collateralization: the actual value the collateral note carries when it exceeds the order's nominal cost. Lets a large note back a small order; the surplus returns as a change note. Omit for exact collateral.
Merkle-tree shard containing the collateral note. Intake rejects an out-of-range shard and checks the proof root against this shard's recent-root window before booking.