> ## Documentation Index
> Fetch the complete documentation index at: https://docs.derive.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Changelog

> Release notes for the Derive API.

Release notes for the Derive v3 API, newest first. Subscribe to the [RSS feed](/changelog/rss.xml)
to be notified of new entries.

<Note>
  Migrating from v2? See [Migrating from V2](/migrating/v3-improvements).
</Note>

<Update label="July 31, 2026" tags={["Breaking"]}>
  ## `private/create_session_key` renamed to `private/set_session_key`

  The route now matches what the action does (register, refresh, **or** retire a key by writing a
  nearer expiry) and its L1 counterpart, the `SetSessionKey` onchain action. Everything about the
  rename is mechanical:

  * Route: `private/create_session_key` → **`private/set_session_key`** (and the debug variant
    `private/create_session_key_debug` → `private/set_session_key_debug`). The old route names
    are gone.
  * Protocol scope: `create_session_key` → **`set_session_key`** in `protocol_scopes` on
    registration requests and in `private/session_keys` responses.
  * TypeScript SDK: `client.sessionKeys.create(...)` → **`client.sessionKeys.set(...)`**;
    `ProtocolScopeCode.CreateSessionKey` → `ProtocolScopeCode.SetSessionKey`.

  ## Signed action payloads now use canonical Solidity ABI encoding

  Every signed action's `data` bytes are now exactly what Solidity `abi.encode` produces — if you
  sign with a standard ABI coder (ethers `AbiCoder`, viem `encodeAbiParameters`, `abi.encode` in a
  contract), nothing changes for you. Hand-rolled encoders must drop the previous non-standard
  layouts, which are **no longer accepted**:

  **`private/set_session_key` and the L1 `SetSessionKey` action (type 51)**

  The payload is canonical `abi.encode(address sessionKey, uint256 expirySec, uint256[] scopes,
    uint256[] subaccountIds)` — dynamic arrays sit behind standard offset words, each prefixed by its
  length word. The old hand-packed layout (`[key][expiry][scopeCount][subaccountCount][scopes…] [subaccounts…]`, no offsets) is rejected. In Solidity, build the L1 payload with a plain
  `abi.encode` call instead of packing words manually.

  **`private/update_whitelisted_recipients`**

  The payload is canonical `abi.encode(address[] add, address[] remove)`. The old hand-packed
  layout (`[addCount][removeCount][adds…][removes…]`, no offsets) is rejected.

  **Orders (`private/order`) and liquidations (`private/liquidate`)**

  Negative `int256` values (`limit_price`, `amount`, `price_limit`) are now full 32-byte
  two's-complement words, sign-extended through the high 16 bytes — standard ABI coder output.
  Previously the server produced and expected a non-standard form with the value packed into the
  low 16 bytes only, which broke standard-signing clients on negative liquidation price limits.
  Non-negative values encode identically, so most existing signatures are unaffected.

  Decoding is also strict across these payloads: offset words must point at their canonical
  positions, lengths must match the byte count, and value words must fit their field's range —
  dirty high bytes are rejected instead of silently truncated, matching Solidity `abi.decode`.

  See [Action signing](/authentication/action-signing) for the per-module payload layouts.
</Update>

<Update label="July 22, 2026" tags={["Breaking"]}>
  ## Settlement status unified under `batch_status`

  The `tx_status` field and the `TxStatus` type are removed. Every route and channel that reported
  settlement status now uses **`batch_status`**, typed as the shared `BatchStatus` enum — `Batching`,
  `Executing`, `Proving`, `Settling`, `Settled` and their `…Error` counterparts — and `null` until
  the operation is picked up into a batch.

  This replaces the old granular transaction states (`applied`, `in_batch`, `proving`, `submitted`)
  **and** the lowercase matching-engine values (`requested`, `pending`, `settled`, `reverted`,
  `ignored`, `timed_out`), which are all **gone** across the entire API. There is now one status
  field, one set of values.

  **REST methods**

  * `public/get_trade_history` — optional `batch_status` request filter (unset returns trades in every
    batch state) and on each trade
  * `private/get_trade_history` — `batch_status` on each trade
  * `private/order`, `private/replace` — `batch_status` on each `trades[]` entry (always `null` at placement)
  * `private/send_quote`, `private/cancel_quote`, `private/replace_quote`, `private/get_quotes`,
    `private/transfer_positions` — `batch_status` on each quote (present only for executed quotes)
  * `private/get_deposit_history`, `private/get_withdrawal_history`,
    `private/get_erc20_transfer_history`, `private/get_funding_history` — `batch_status` on each row
  * `public/get_transaction` — `status` uses the same `BatchStatus` values

  **WebSocket channels**

  * `trades.{instrument_type}.{currency}.{tx_status}` and `{subaccount_id}.trades.{tx_status}` — removed;
    settlement is no longer streamed. Poll `public/get_trade_history` for `batch_status` / `tx_hash` instead
  * `trades.{instrument_name}`, `trades.{instrument_type}.{currency}` — each event now carries the full
    trade detail (`wallet`, `subaccount_id`, `liquidity_role`, fees, realized PnL)
  * `{subaccount_id}.trades`, `{subaccount_id}.quotes` — `batch_status` on each payload item

  ## `instrument_type` is now a typed enum

  On the trade-history schemas, `instrument_type` is typed as the `AssetType` enum
  (`erc20` / `option` / `perp`) instead of a free-form string.

  See [Breaking changes → Settlement status](/migrating/breaking-changes) for the full route table
  and value reference.
</Update>


## Related topics

- [Programmatic Onboarding](/getting-started/depositing.md)
