PearPear
API IntegrationTrade Activity

Monitor TWAP

Track a running TWAP schedule.

A TWAP order is a schedule. List your schedules with GET /schedules (SDK: sdk.core.schedules.list) to see progress:

curl "https://pro-gateway.pearprotocol.io/schedules?status=ACTIVE" \
  -H "x-api-key: $PEAR_API_KEY" \
  -H "x-trade-account-id: $TRADE_ACCOUNT_ID"
{
  "limit": 50,
  "schedules": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "connector": "hyperliquid",
      "strategy": "TWAP",
      "status": "ACTIVE",
      "intent": "OPEN",
      "executionType": "MARKET",
      "positionKey": "9f2c4a7e10b3486d5c8e1a04b7d92f63c05e8a1b7d34f62089ac5e1f30b74d28",
      "startAt": "2026-01-01T00:00:00.000Z",
      "endAt": "2026-01-01T01:00:00.000Z",
      "sliceIntervalSec": 300,
      "sliceCount": 12,
      "lastSliceAt": "2026-01-01T00:25:00.000Z",
      "targetNotional": "1000",
      "remainingNotional": "583.33",
      "legs": [
        { "symbol": "0", "side": "BUY",  "weight": 0.5 },
        { "symbol": "1", "side": "SELL", "weight": 0.5 }
      ],
      "randomization": { "timingJitterBps": 0, "sizeJitterBps": 0 },
      "fills": [],
      "createdAt": "2026-01-01T00:00:00.000Z",
      "updatedAt": "2026-01-01T00:25:00.000Z"
    }
  ]
}

Reading progress

targetNotional and remainingNotional are the progress fields. How far along the schedule is:

progress = (targetNotional - remainingNotional) / targetNotional
FieldTells you
targetNotionalThe total USD the schedule set out to trade.
remainingNotionalThe USD it has left. It falls as slices fill.
statusWhether the schedule is still working.
sliceCountHow many slices the window is divided into. This is the planned count, recomputed from startAt, endAt, and sliceIntervalSec on every request. It is not a count of slices done.
lastSliceAtWhen the most recent slice went out. Compare it with sliceIntervalSec to see if the next one is due.
positionKeyThe basket the schedule works on. It matches the positionKey on GET /positions/lite.
fillsThe fills the schedule has produced so far, each with quantity, price, usd, and fees.
cancelledAt, cancelledReasonWhy it stopped, such as POSITION_CLOSED.

There is no slices-done counter and no average-price field. Derive both from fills, with the caveat below.

fills is unfiltered, and summing it double-counts. Unlike GET /fills, a schedule's fills array includes superseded RECONCILED rows alongside the CONFIRMED rows that replaced them. Drop every fill whose status is RECONCILED before you aggregate quantity, notional, or fees. See Fills.

The exposure a running open TWAP has already built shows up in GET /positions as it fills, not only at the end.

A close TWAP is a different shape

intent: "CLOSE" returns positionId and initialExposure — the position it is unwinding and the exposure it started from. It carries no legs, targetNotional, or remainingNotional, so the progress formula above does not apply. Track a close TWAP through the position's shrinking exposure instead.

Query parameters

ParameterValues
statusACTIVE, COMPLETED, or CANCELLED, as a comma-separated list. Omitting it returns every state.
limitDefault 20, maximum 2000.
cursorThe nextCursor of the previous page.
connectorAccepted and ignored. The venue comes from the trade account.

Querying status=COMPLETED also returns schedules that failed; the response tells them apart with COMPLETED or FAILED. See Open Order.

Live updates

Subscribe to user_events on the WebSocket for schedule.created, the per-slice executions, schedule.completed, schedule.failed, and schedule.cancelled. Cancel a schedule from Managing Open Order.

On this page