Balance SSE event stream
https://api.triport.io/v1/balance/eventsA Server-Sent Events stream that pushes your account's authoritative balance on connect and on every credit or debit.
GET /v1/balance/events is a long-lived Server-Sent Events stream (Content-Type: text/event-stream) that delivers your live account balance. It is scoped to the authenticated session: the server only emits events for your own user, so there is no per-user filter to pass.
The stream is authoritative — all amounts are in micro-USD (1 USD = 1,000,000 micro). Never do client-side balance arithmetic from deltas alone: every credit and debit frame also carries the post-event new_balance, and the snapshot frame carries the full current balance. Treat the server's values as the source of truth.
On every connect (and every reconnect), the server first sends a snapshot frame describing the current balance, then streams balance_credit / balance_debit frames as they occur. A keep-alive comment frame is sent every 15 seconds so that intermediary proxies do not close the idle connection.
Use this stream to keep a balance widget live without polling. For one-off reads or for re-establishing a baseline after a disconnect, use GET /v1/balance; for historical ledger rows, use GET /v1/balance/entries.
Parameters
This endpoint takes no path, query, or body parameters. Identity is resolved from the session cookie.
Response
The response is an open text/event-stream. Each frame is a named SSE event (event: <name>) followed by a JSON data: line. The very first frame is always snapshot; subsequent frames are balance_credit or balance_debit. Comment lines beginning with : are keep-alives and carry no data.
Event types
| Event name | When it fires | Payload shape |
|---|---|---|
snapshot | On every connect and reconnect, as the first frame. The authoritative baseline — overwrite your cached balance with it, do not merge. | Snapshot payload |
balance_credit | When your balance increases (e.g. a payment is credited). | Delta payload |
balance_debit | When your balance decreases (e.g. an invoice is paid from balance). delta_micro is negative. | Delta payload |
snapshot payload fields
| Field | Type | Description |
|---|---|---|
amount_micro | integer | Current balance in micro-USD. 0 for a brand-new account. |
locked | boolean | Whether the balance is currently locked. |
updated_at | integer | Unix seconds the balance was last updated. Multiply by 1000 for new Date(...). |
locked_at | integer | Unix seconds the balance was locked. Present only when locked is true. |
balance_credit / balance_debit payload fields
| Field | Type | Description |
|---|---|---|
kind | string | The event kind — equals the event name (balance_credit or balance_debit). Redundant discriminator alongside the SSE event name. |
user_id | string | Your user id. |
delta_micro | integer | Signed change in micro-USD. Positive for credits, negative for debits. |
new_balance | integer | Authoritative balance in micro-USD after applying this event. Use this rather than summing deltas. |
ref_invoice_id | string | Invoice this movement references. Present only when applicable. |
ref_payment_id | integer | Payment this movement references. Present only when applicable. |
at | integer | Unix seconds the event occurred. Note the field is at, not created_at. |
Errors
SSE errors surface as the HTTP status of the initial response (before the stream opens) or as a connection drop afterwards.
| Code | Meaning | When it happens |
|---|---|---|
401 | Unauthorized | No valid session cookie was sent. Sign in and retry. |
500 | Streaming unsupported | The serving environment cannot flush a stream. Not retryable by the client. |
See the shared error envelope reference for the full JSON error format returned by non-streaming endpoints such as GET /v1/balance.
Examples
JavaScript (fetch)
EventSource is the right primitive for SSE in the browser — it auto-reconnects on network errors and lets you bind per-event listeners. Pass withCredentials: true so the session cookie is sent.
const es = new EventSource("https://api.triport.io/v1/balance/events", {
withCredentials: true,
});
// snapshot = authoritative baseline; overwrite, don't merge.
es.addEventListener("snapshot", (e) => {
const snap = JSON.parse(e.data);
console.log("baseline balance:", snap.amount_micro, "locked:", snap.locked);
});
const onDelta = (e) => {
const ev = JSON.parse(e.data);
console.log(ev.kind, ev.delta_micro, "->", ev.new_balance);
};
es.addEventListener("balance_credit", onDelta);
es.addEventListener("balance_debit", onDelta);
es.onerror = () => {
// EventSource reconnects automatically; the server re-sends a fresh
// snapshot on reconnect, so any frames missed while offline are recovered.
};
// later: es.close();TypeScript SDK (@triport/sdk)
import { subscribeBalance, getBalance } from "@triport/sdk";
const stop = subscribeBalance((ev) => {
if (ev.type === "snapshot") {
// authoritative baseline — replace local state
setBalance(ev.amount_micro);
} else {
// balance_credit | balance_debit — trust new_balance
setBalance(ev.new_balance);
}
});
// On a hard disconnect, re-fetch the snapshot before resubscribing:
// const fresh = await getBalance();
// teardown:
stop();Python (triport-sdk)
from triport import Client
client = Client(session="$TRIPORT_SESSION")
for event in client.balance.events():
if event.type == "snapshot":
print("baseline:", event.amount_micro, "locked:", event.locked)
else: # balance_credit | balance_debit
print(event.kind, event.delta_micro, "->", event.new_balance)Notes
- Snapshot semantics. The
snapshotframe is a full replacement of your cached balance, includinglocked/locked_attransitions — never merge it with prior state. - Reconnect strategy. If the connection drops, re-fetch
GET /v1/balanceto re-establish a baseline, then reconnect to/v1/balance/events. Events dropped while you were offline (e.g. a slow subscriber) are recovered as part of the newsnapshot. BrowserEventSourcehandles reconnection automatically. - Keep-alives. A
: keep-alivecomment frame is sent every 15 seconds. It carries no data — ignore it. It exists only to keep proxies from closing an idle connection. - No default
messagechannel. The server only emits the three named events (snapshot,balance_credit,balance_debit); the unnamedmessagechannel is never used, so anonmessagehandler will never fire. - Units. All amounts are integer micro-USD (1 USD = 1,000,000 micro). Timestamps (
updated_at,locked_at,at) are Unix seconds — multiply by 1000 for a JavaScriptDate. - Related:
GET /v1/balance(snapshot),GET /v1/balance/entries(paginated ledger history).