All notable API changes to StreamPay are documented here.
Format follows Keep a Changelog.
API versioning follows the policy in README.md#api-versioning.
- SplashScreen delay reduced: mandatory display time cut from 2 400 ms to 400 ms and fade-out from 600 ms to 300 ms, removing ~2.3 s of forced blocking before the app becomes interactive.
- SplashScreen lazy-loaded: the branded overlay is now loaded via
next/dynamicwithssr: false, removing it from the critical render path entirely. First paint of the actual page content no longer waits for the splash bundle. - Home page converted to React Server Component:
app/page.tsxno longer carries"use client". ThelocalStorage-dependent onboarding state is isolated in a newOnboardingManagerclient component, keeping the bulk of the page as a zero-JS static render. - Unused import removed:
StreamPrimerwas imported but never rendered inapp/page.tsx; the import has been removed to reduce the client bundle. - Image optimisation enabled:
next.config.tsnow specifiesimages.formats: ["image/avif", "image/webp"]so the 339 KB PNG splash icon (and any future images) are served in modern formats to supporting browsers. - HTTP compression enabled:
compress: trueadded tonext.config.ts(gzip/brotli for all responses).
- MRU (most-recently-used) wallet ordering on the connect modal: the
provider a user picked last surfaces at the top of
WalletModal, persisted under thestreampay_mru_walletlocalStoragekey viagetMRUWalletId/setMRUWalletId/getSortedProvidersinapp/state/walletPrefs.ts. Stale ids and SSR are tolerated; the connect flow never breaks because of a missing preference. Backed by focused unit tests inapp/state/walletPrefs.test.tsand documented indocs/mru-wallet-ordering.md. lib/chaos.ts— fault-injection middleware for chaos tests. Lets test suites inject latency, error responses, or request aborts at configurable rates (defaults disabled; opt in viaCHAOS_ENABLED=trueor programmatic override). Activated per-request throughwithChaosMiddleware(request, handler, options?). Honors path-prefix and HTTP-method allowlists, exposes every standard env knob (CHAOS_LATENCY_RATE,CHAOS_ERROR_RATE,CHAOS_ABORT_RATE,CHAOS_MIN_LATENCY_MS,CHAOS_MAX_LATENCY_MS,CHAOS_ERROR_STATUS,CHAOS_ERROR_CODE,CHAOS_ERROR_MESSAGE,CHAOS_PATH_PREFIXES,CHAOS_METHODS,CHAOS_SEED), and emits the standard{ error: { code, message, request_id } }envelope on injected errors withx-chaos-fault/x-chaos-<kind>-msmarkers on the wire (test-only — do not rely on in production).lib/chaos.test.ts— Jest unit suite targeting >=90% line coverage (currently 97.23% lines / 100% funcs / 90.22% branches). Locks the pure decision function, the resolver priority chain, every validation branch, and the middleware dispatch surface.
- Per-user rate limit on
POST /api/exports: 5 requests/min per authenticated wallet, checked after JWT verification so forged tokens cannot spend a victim's budget, returning the standard429envelope withRetry-After. Rate-limit buckets are now keyed per limit tier (read/write/export), so throttling one endpoint class can no longer drain a user's allowance for another. - Wallet auth IP rate limiting on
GET|POST /api/auth/walletnow returns the canonical{ error: { code, message, request_id } }envelope on 429, echoesx-request-id, and emits structuredwallet_ip_rate_limit_exceededlogs with correlation IDs. OpenAPI documents the login (5/min) and challenge (20/min) IP limits. - Boundary validation rejects NaN/Infinity rates, negative latency, 1xx/2xx/
3xx status codes, malformed path prefixes (whitespace or control chars),
empty/whitespace
errorCode/errorMessage, and non-integer seeds. - Disabled by default — every config is validated but no fault is ever injected unless the operator explicitly opts in.
- Centralized accessible toast queue (
ToastProvider,useToast) with severity icons, auto-dismiss, queue limits, androle="status"live region announcements per WCAG 2.1 AA. - A shared keyboard focus-visible layer for interactive controls so focus indicators remain clear in both light and dark themes.
- Request fingerprinting for fraud signals on all
/api/*routes. Edge middleware computes a stable SHA-256 hash from non-volatile request signals (method, path, client IP, User-Agent, Accept-Language, Accept-Encoding) and forwards it via the internalx-request-fingerprintheader. Fingerprint observations are written to the append-only audit log with correlation IDs, and privileged stream audit events now includerequestFingerprintmetadata.
- The streams list now surfaces a distinct filtered-results empty state when the current view has no matches, with clearer guidance to clear filters and return to the broader streams list.
StreamProgressnow emits shared color-blind pattern classes on its fill so stream state remains distinguishable beyond color alone.
GET /api/orgs/:orgId/membersandPOST /api/orgs/:orgId/membersnow return404 ORG_NOT_FOUNDwhen the organization does not exist, instead of an unhandled500caused by accessing an undefined legacy store.
2.0.0 — 2026-04-28
/api/v2/streamsand/api/v2/streams/:id— stream CRUD endpoints with the v2 response shape (see breaking changes below).allowed_actionsarray field replacesnextActionstring, allowing a stream to surface multiple permitted actions simultaneously.- Structured
settlementobject ({ tx_hash, settled_at }) replaces the flatsettlementTxHashstring; always present,nullwhen not yet settled. created_at/updated_atsnake_case date fields aligned with Stellar Horizon conventions (replacescreatedAt/updatedAt)./api/v1/*paths now serveDeprecationandSunsetresponse headers on every response (RFC 9745)./api/v1/*will return410 Gonewith a machine-readable body and migration link after 2026-12-31 (245-day notice from deprecation date).docs/api-v2-migration.md— complete migration guide for wallet partners.docs/deprecation-notice-template.md— comms template for future major deprecations.- CI contract tests (
v1-contract.test.ts) pin the v1 response shape for the full deprecation window.
| Field (v1) | Field (v2) | Notes |
|---|---|---|
nextAction: string |
allowed_actions: string[] |
Always an array; empty when no action is available. |
createdAt: string |
created_at: string |
ISO 8601, same value. |
updatedAt: string |
updated_at: string |
ISO 8601, same value. |
settlementTxHash?: string |
settlement: { tx_hash, settled_at } | null |
Always present; null before settlement. |
partnerId?: string |
partner_id?: string |
snake_case rename; value unchanged. |
/api/streams/*(unversioned paths) — these are the v1 handlers. Continue to work for the deprecation window; migrate to/api/v2/streams/*./api/v1/streams/*— URL alias for the above.- Sunset: 2026-12-31. After this date all
/api/v1/*paths return410 Gone.
1.0.0 — 2026-01-15 (baseline)
Initial stable stream API release.
GET /api/streams— list streams with cursor paginationPOST /api/streams— create a stream (returnsdraft)GET /api/streams/:id— get a single streamDELETE /api/streams/:id— delete a draft/ended/withdrawn streamPOST /api/streams/:id/start— draft → activePOST /api/streams/:id/pause— active → pausedPOST /api/streams/:id/stop— active|paused → endedPOST /api/streams/:id/settle— active|paused → ended (with on-chain settlement)POST /api/streams/:id/withdraw— ended → withdrawn
{
"data": {
"id": "stream-abc123",
"recipient": "GABC...",
"rate": "100 XLM / month",
"schedule": "Pays every 30 days",
"status": "active",
"nextAction": "pause",
"createdAt": "2026-01-15T10:00:00.000Z",
"updatedAt": "2026-01-15T10:00:00.000Z",
"settlementTxHash": "tx-abc..."
},
"links": { "self": "/api/v1/streams/stream-abc123" }
}