Agara

Portfolio stream

Keep complete position rows and portfolio summary up to date.

Open GET /trade/v1/portfolio/stream with an Authorization: Bearer … header. Personal access tokens need portfolio:read. The response uses text/event-stream and covers your complete AGARA portfolio.

This endpoint allows 300 connection attempts per IP per 60 seconds, including reconnects. See stream connection limits.

You can use the existing positions and summary REST endpoints for initial display. Once the stream's synchronization arrives, replace that initial data and apply subsequent stream updates. Ignore REST responses that arrive after synchronization.

Synchronization

The first message on every connection has type: "portfolio.sync", a stream_id, a decimal-string seq, and two objects:

  • positions: an object containing positions, unavailable_exchanges, and as_of. Each position contains its complete numerical fields, a market object, and an event object or null.
  • summary: the complete summary response, containing summaries.

Replace your local portfolio with this snapshot. Position identity is the pair (exchange, token_id).

Updates

Messages with type: "portfolio.update" contain stream_id, seq, changes, and as_of. Apply all changes in a message together:

Change typePayloadAction
position.upsertposition containing every position field, market, and nullable eventReplace the matching row and its metadata, or prepend a new row.
position.removeexchange and token_idRemove the matching row.
summary.replacesummary containing summariesReplace your summary.

Read each row's title, outcome, logo, event link, and lifecycle state from its market object. Its optional event object provides event display information. Stream packets do not include separate markets or events maps; the REST endpoints still do. Removal and summary changes do not replace the metadata of other positions. Monetary amounts remain decimal integer strings in micro units, as in REST. Keep nullable accounting fields nullable.

Current price uses the best bid, then the best ask, then the average acquisition price. If none is available, current price and current value are null. P&L is null whenever the price or acquisition cost is unavailable. Summary valuation totals are also null when a position has no current value.

For proposed or resolved outcomes, use the returned valuation: each outcome is priced at what one share pays. With a single winner, the winning outcome is priced at 100¢ and the losing outcome at 0¢. On a split, each outcome carries its own price, such as 37¢ and 63¢, and to_win_micro is the shares times that price, rounded down. Zero is a valid price. Do not overwrite these values with order-book quotes or infer the result yourself.

Held shares and available shares update promptly. Acquisition cost and P&L can update later. An AVAILABLE accounting status means a cost estimate is available; it does not promise that every recent trade is already reflected in that estimate.

Use the portfolio row's lifecycle fields to render portfolio actions. A market_status notification can arrive earlier; wait for the updated portfolio row before changing those fields. The portfolio stream and REST endpoints use the same lifecycle state.

Ordering and reconnecting

Parse seq as an integer with sufficient precision, such as JavaScript BigInt. After accepting a synchronization snapshot:

  • Ignore messages with a sequence less than or equal to the last applied sequence.
  • Apply an update only when its sequence is exactly one greater and its stream_id matches.
  • Reconnect if a sequence is missing or the stream identifier changes unexpectedly. Wait for the new synchronization before applying updates.

Reconnect when the response ends. Connections also end periodically so credentials can be checked again. Use retry backoff; REST remains available while reconnecting. Historical replay through Last-Event-ID is not supported.

Use a fetch-based SSE reader when you need to set the authorization header. Native browser EventSource does not accept custom authorization headers. Heartbeat comments can be ignored.

The web app shows the first synchronization immediately, then updates the display once per second. It processes every message in order between display updates.

Open orders continue to use the account stream.