PearPear
API IntegrationTrade Activity

Rebalance Activity

Read what auto-rebalance did to a position, and the events to track live.

Every auto-rebalance decision leaves a record, whether it traded or failed. Read the history per position, and the live state per config.

ReadEndpoint
What rebalancing did to a positionGET /rebalance/{positionId}/events
The configs and their current driftGET /rebalance/auto

To set one up, see Auto-Rebalance.

Rebalance events

curl "https://pro-gateway.pearprotocol.io/rebalance/$POSITION_ID/events?limit=50" \
  -H "x-api-key: $PEAR_API_KEY" \
  -H "x-trade-account-id: $TRADE_ACCOUNT_ID"
{
  "limit": 50,
  "items": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "autoRebalanceConfigId": "9c1b2d3e-4f56-4789-a0b1-c2d3e4f56789",
      "positionId": "7d8e9f01-2345-4678-9abc-def012345678",
      "weightSource": "INITIAL_WEIGHT",
      "driftPct": "0.0563",
      "currentWeights": { "0": 0.5563, "1": 0.4437 },
      "targetWeights":  { "0": 0.5,    "1": 0.5 },
      "status": "SUCCESS",
      "createdAt": "2026-01-01T08:00:00.000Z"
    }
  ]
}
FieldMeaning
driftPctThe drift that tripped the threshold, measured the way that weightSource measures it.
currentWeightsWhat the basket held when the decision was made. Keyed by instrument ID.
targetWeightsWhat it traded towards.
statusSUCCESS or FAILED.
errorPresent on FAILED, with the reason.

Comparing currentWeights against targetWeights shows exactly how far the basket had drifted and what the rebalance aimed at. On a LIVE_BETA config the targets come from the live beta, so they move between events; on INITIAL_WEIGHT they are constant.

Page with limit and cursor, as with the other list endpoints.

Watch for failures

FAILED events are the ones to alert on. Three consecutive failures pause the config, so a burst of them means rebalancing is about to stop:

GET /rebalance/{positionId}/events?limit=3

Three FAILED in a row and the config is paused, or about to be. A single SUCCESS resets the streak. See Auto-Rebalance.

Config state

GET /rebalance/auto returns the configs themselves, filtered by status, weightSource, or positionId, and paged with limit and cursor:

GET /rebalance/auto?status=PAUSED

That is the query worth running on a schedule: it lists every config that has stopped working and why, in one call. pausedReason is USER, POSITION_CHANGED, REPEATED_FAILURES, or INVALID_LIVE_BETA_EXPOSURE.

A LIVE_BETA config also carries its timeframe1h, 4h, or 1d, the candle feed driving the comparison — and its live drift, so you can show a user how close the position is to its next rebalance without waiting for an event:

{
  "limit": 20,
  "items": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "positionId": "7d8e9f01-2345-4678-9abc-def012345678",
      "status": "ACTIVE",
      "minimumDriftPct": "0.05",
      "weightSource": "LIVE_BETA",
      "timeframe": "4h",
      "beta": {
        "state": "TRACKING",
        "impliedEntryBeta": "0.9120",
        "lastDerivedBeta": "0.9642",
        "lastProcessedBetaTime": "2026-01-01T08:00:00.000Z",
        "driftPct": "0.0572"
      },
      "createdAt": "2026-01-01T00:00:00.000Z",
      "updatedAt": "2026-01-01T08:00:00.000Z"
    }
  ]
}

beta.state runs PENDINGBASELINEDTRACKING. Only TRACKING carries both sides of the comparison, so lastDerivedBeta, lastProcessedBetaTime, and driftPct exist only there. impliedEntryBeta appears from BASELINED on.

Compare driftPct against the config's minimumDriftPct. It can also be absent inside TRACKING, when the baseline is zero and no fraction can be derived.

Live events

Subscribe to user_events on the WebSocket and read five topics:

TopicFires when
rebalance.createdA config is created.
rebalance.updatedA config changes: threshold, timeframe, or status.
rebalance.executedA rebalance ran. Read the matching event for whether it succeeded.
rebalance.pausedA config stopped. Read pausedReason for why.
rebalance.cancelledA config is cancelled.

rebalance.paused is the one that needs handling: it fires for a closed position, an invalid LIVE_BETA shape, and the repeated-failure circuit breaker alike, and until you resume it the position is no longer being kept on target.

An automatic pause also files a notification, so it survives the user not being on the page. Read those with GET /notifications.

The trades themselves

A rebalance places real orders, so it also appears in the ordinary trade record: an execution with the venue orders it sent, the fills those produced, and a position.updated event. The rebalance event tells you why it traded; the execution tells you what happened at the venue.

On this page