Skip to main content

Raw Signed Actions

The low-level wallet flow is a two-step hash-and-submit round trip:

  1. POST /api/v1/trading/actions/hash with an unsigned payload.
  2. Sign the returned hash with the wallet.
  3. POST /api/v1/trading/actions with the returned canonical payload and the wallet signature.

Always sign the canonical payload returned by /actions/hash, not a locally reserialized copy.

Envelope

{
"account": "0x1111111111111111111111111111111111111111",
"nonce": 0,
"nonceReservationId": null,
"ts": 1781190000000,
"action": {
"SpotPlaceOrder": {
"marketId": 1,
"side": "Bid",
"price": 1000000,
"qty": 100000,
"timeInForce": "post_only",
"isMarket": false,
"reduceOnly": false
}
}
}

nonce: 0 asks the server to use the current account nonce in the canonical response. If you reserved a nonce range, send the explicit nonce and nonceReservationId.

Submit the signed response payload:

{
"payload": {
"account": "0x1111111111111111111111111111111111111111",
"nonce": 42,
"nonceReservationId": null,
"ts": 1781190000000,
"action": {
"SpotPlaceOrder": {
"marketId": 1,
"side": "Bid",
"price": 1000000,
"qty": 100000,
"timeInForce": "post_only",
"isMarket": false,
"reduceOnly": false,
"expiresAt": null
}
}
},
"signature": {
"scheme": "EcdsaSecp256k1",
"bytes": [1, 2, 3]
}
}

Use Idempotency-Key on submit requests that may be retried.

Field casing

0.1.2 has two canonical action families:

FamilyCanonical fields
Public place-order envelopes: SpotPlaceOrder, OutcomePlaceOrdermarketId, timeInForce, isMarket, reduceOnly, expiresAt
Raw advanced envelopes: Cancel, AmendOrder, QuoteReplace, SpotQuoteReplace, PlaceAlgoOrder, PlaceConditionalOrdermarket, order_id, new_qty, time_in_force, is_market, reduce_only, expires_at

The server accepts documented camelCase aliases for advanced fields in 0.1.2 and canonicalizes them back to snake_case. For deterministic client code, prefer the canonical fields shown below.

Spot Place Order

{
"account": "0x1111111111111111111111111111111111111111",
"nonce": 0,
"ts": 1781190000000,
"action": {
"SpotPlaceOrder": {
"marketId": 1,
"side": "Bid",
"price": 1000000,
"qty": 100000,
"stpMode": "cancel_maker",
"timeInForce": "post_only",
"isMarket": false,
"reduceOnly": false,
"expiresAt": null
}
}
}

Spot orders do not carry book or outcome.

Prediction Place Order

{
"account": "0x1111111111111111111111111111111111111111",
"nonce": 0,
"ts": 1781190000000,
"action": {
"OutcomePlaceOrder": {
"marketId": 10,
"outcome": "YES",
"side": "Bid",
"price": 520000,
"qty": 100000,
"timeInForce": "gtc"
}
}
}

book is still accepted as a deprecated alias for outcome on prediction place orders.

Cancel

{
"account": "0x1111111111111111111111111111111111111111",
"nonce": 0,
"ts": 1781190000000,
"action": {
"Cancel": {
"order_id": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}
}
}

orderId is accepted as an alias.

Amend Quantity

{
"account": "0x1111111111111111111111111111111111111111",
"nonce": 0,
"ts": 1781190000000,
"action": {
"AmendOrder": {
"order_id": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"new_qty": 50000
}
}
}

Current amend semantics only allow quantity reduction while keeping priority. Do not send new_price; use quote replace for repricing.

Spot Quote Replace

{
"account": "0x1111111111111111111111111111111111111111",
"nonce": 0,
"ts": 1781190000000,
"action": {
"SpotQuoteReplace": {
"market": 1,
"legs": [
{
"cancel_order_id": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"side": "Bid",
"price": 999900,
"qty": 100000,
"time_in_force": "post_only",
"is_market": false,
"reduce_only": false
},
{
"side": "Ask",
"price": 1000100,
"qty": 100000,
"time_in_force": "post_only"
}
]
}
}
}

Spot quote legs do not carry book. A leg with cancel_order_id and qty: 0 is cancel-only. A leg without cancel_order_id is place-only.

Prediction Quote Replace

{
"account": "0x1111111111111111111111111111111111111111",
"nonce": 0,
"ts": 1781190000000,
"action": {
"QuoteReplace": {
"market": 10,
"legs": [
{
"cancel_order_id": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"book": "YES",
"side": "Bid",
"price": 510000,
"qty": 100000,
"time_in_force": "post_only"
},
{
"book": "NO",
"side": "Ask",
"price": 480000,
"qty": 100000,
"time_in_force": "post_only"
}
]
}
}
}

Quote replace is atomic at engine level. If any leg is rejected, the engine rolls back the full group. New child orders are derived from the parent action and leg index; replacing an order creates a new child order and does not preserve the canceled order's queue priority.

Algo Order

{
"account": "0x1111111111111111111111111111111111111111",
"nonce": 0,
"ts": 1781190000000,
"action": {
"PlaceAlgoOrder": {
"market": 10,
"book": "YES",
"side": "Bid",
"total_qty": 1000000,
"limit_price": 510000,
"time_in_force": "gtc",
"strategy": {
"kind": "twap",
"slice_qty": 100000,
"interval_ms": 5000
}
}
}
}

Supported strategies are iceberg, twap, and vwap.

Conditional Order

{
"account": "0x1111111111111111111111111111111111111111",
"nonce": 0,
"ts": 1781190000000,
"action": {
"PlaceConditionalOrder": {
"market": 10,
"book": "YES",
"side": "Ask",
"qty": 100000,
"limit_price": 700000,
"trigger_price": 690000,
"trigger_direction": "at_or_above",
"conditional_kind": "take_profit",
"reduce_only": true,
"signed_trigger_order": {
"payload": {
"account": "0x1111111111111111111111111111111111111111",
"nonce": 43,
"ts": 1781190000000,
"action": {
"OutcomePlaceOrder": {
"marketId": 10,
"outcome": "YES",
"side": "Ask",
"price": 700000,
"qty": 100000,
"reduceOnly": true
}
}
},
"signature": {
"scheme": "EcdsaSecp256k1",
"bytes": [1, 2, 3]
}
}
}
}
}

The nested signed_trigger_order must already be signed. The outer conditional action controls storage and trigger conditions.