OpenPoly logo
Polyflight

API, events, and proof

Polyflight operator resources, webhook catalogue, and public v5 mixed-money verification.

API, events, and proof

Polyflight adds operator-scoped read resources and webhook events without changing the REST v1 wallet response contract. Private endpoints derive operator ownership from the authenticated API key or staff session; never send an operatorId to widen access.

Scopes

ScopePurpose
polyflight:readPolyflight overview, participating flights, tickets, and product activity.
polyflight_terms:readCurrent, scheduled, and historical commercial terms.
polyflight_settlements:readProvisional/final statements, statement exports, liabilities, and payment history.
balance_operations:readWallet request/response evidence, including Polyflight source links.
webhooks:readEndpoint and delivery evidence for Polyflight events.

These scopes are assignable but are not silently added to existing restricted keys or staff memberships. * can read operator-owned resources but does not create an operator terms-write, statement-finalize, payment-record, or manual-resolution endpoint.

Operator endpoint inventory

All routes are GET-only for operator reporting:

ResourceGET pathsRequired scope
Overview/api/operator/polyflight/overviewpolyflight:read
Participating flights/api/operator/polyflight/flights, /flights/{flightIdOrCode}, /flights/exportpolyflight:read
Tickets/api/operator/polyflight/tickets, /tickets/{ticketId}, /tickets/exportpolyflight:read and polyflight_terms:read
Wallet operations/api/operator/polyflight/balance-operations, /balance-operations/{operationId}, /balance-operations/exportpolyflight:read and balance_operations:read
Terms and history/api/operator/polyflight/termspolyflight_terms:read
Statements/api/operator/polyflight/settlement-reports, /settlement-reports/{id}, /settlement-reports/export, /settlement-reports/{id}/exportpolyflight_settlements:read
Payment history/api/operator/polyflight/settlement-reports/payments, /settlement-reports/{id}/paymentspolyflight_settlements:read
Webhook evidence/api/operator/webhooks/deliveries?product=polyflightwebhooks:read and polyflight:read

List filters are date_from, date_to, comma-separated status, search, page, and page_size; statement lists use pagination. Export returns CSV by default and canonical JSON with format=json; CSV uses spreadsheet-formula protection. All DTOs use camelCase and native aggregate amounts are decimal strings. Every response is tenant-derived and private, no-store.

Use Operator Dashboard → API Playground → Polyflight (/api-playground/polyflight) for source-backed examples. The Playground inherits the staff session and does not expose its bearer token. External integrations must call the same routes from their backend with an appropriately scoped API key.

The dashboard mirrors these resources at /polyflight, /polyflight/flights, /polyflight/tickets, /polyflight/balance-operations, /polyflight/settlement-reports, and /polyflight/terms.

Opinion metrics continue to exclude Polyflight native money unless an explicitly labelled all-products wallet audit is selected. Never add IDR amounts to Credits totals.

Webhook catalogue

Polyflight events use the existing signed envelope, signature verification, retry schedule, and event_id deduplication rules.

Event typeMeaning
mini_app.polyflight.purchase.processedDebit and ticket admission completed; the immutable ticket exists.
mini_app.polyflight.purchase.failedPurchase reached a terminal failure without an admitted ticket; inspect compensation state when a debit may have applied.
mini_app.polyflight.ticket.resolvedThe global result classified the ticket and records the amount owed, if any. It does not assert wallet delivery.
mini_app.polyflight.payout.pendingA winning payout is owed or requires follow-up.
mini_app.polyflight.payout.processedWinning wallet credit is confirmed.
mini_app.polyflight.refund.pendingA cancelled-ticket full refund is owed or requires follow-up.
mini_app.polyflight.refund.processedCancelled-ticket wallet credit is confirmed.
mini_app.polyflight.purchase.compensatedAn applied purchase debit with no admitted ticket was reversed.

The signed envelope remains snake_case: event_id, event_type, operator_id, occurred_at, aggregate_type, aggregate_id, idempotency_key, and data. Polyflight data keys are camelCase:

FamilyExact data fields
purchase.processedpurchaseRequestId, ticketId, flightId, flightCode, status, currencyCode, stakeMinor, feeMinor, netStakeMinor, potentialPayoutMinor, choiceKind, choiceIndex, predictedSequence, economyVersion
purchase.failedpurchaseRequestId, operatorId, operatorUserId, flightId, flightCode, status, failureReason
ticket.resolvedticketId, purchaseRequestId, flightId, flightCode, status, currencyCode, payoutMinor, obligationId
Payout/refund pending or processed; purchase compensatedobligationId, effect, purchaseRequestId, ticketId, flightId, flightCode, amountMinor, currencyCode, status

ticketId and obligationId are nullable when the outcome/effect permits. Pending/manual-review payment events add failureReason; an admin-resolved processed event adds manualResolution; engine-created refund.pending adds voidCode.

Payload data is reconstructed from immutable native ticket, operation, obligation, and captured-terms rows. It does not revalue an amount with current FX or current terms.

Receivers must tolerate additive fields, branch only on known event_type, and deduplicate by event_id. Delivery replay may repeat an event; it never repeats or authorizes the underlying wallet mutation.

Comparison-only FX

A polyflight-v5 flight freezes one Indodax USDT_IDR observation before boarding. The committed valuation contains:

  • policy indodax-usdt-idr-v1;
  • source indodax and pair USDT_IDR;
  • positive canonical rate with exactly 8 fractional digits and either 0 or 1–12 integer digits (maximum serialized length 21);
  • source timestamp and observation correlation ID;
  • observation age and fallbackUsed disclosure.

A refresh targets five-minute freshness, but refresh failure may use the latest persisted valid observation. That cached fallback is frozen and disclosed; it is not refreshed at purchase, lock, result, payout, or replay. If no valid observation has ever existed, that flight remains Credits-capable but IDR entry is unavailable.

For one option, the verifier compares exact integer weight:

C = gross first-party Credits stake
I = gross IDR stake across all operators
R = canonical rate × 10^8
K = 10^8
comparisonWeight = C × R + I × 10,000 × K

Every option uses the same denominator, so ranking compares the integer weights directly. Commercial shares, ticket-fee earnings, and wallet-delivery status do not affect ranking. The rate is comparison evidence only: users are debited and credited directly in their original currency.

v5 mixed-money proof

New mixed-money-capable flights use:

  • rules/protocol polyflight-v5;
  • public package codec 4, domain polyflight-public-package-v5;
  • snapshot codec 3, domain polyflight-snapshot-v5;
  • lock package codec 4, domain polyflight-lock-package-v5;
  • unchanged grouped abcdOptions / efghOptions and count-v2 strategy behavior.

The public package declares currencyCodes as exactly ['CREDITS'] or ['CREDITS', 'IDR'], stakeUnit: 'minor', and either the frozen valuation or null. null means Credits-only entry for that flight.

After landing, the anonymous v5 snapshot discloses each ticket's anonymous UUID, choice group/index, CREDITS or IDR, gross stake, fee, and potential payout. Per-option ranking totals publish totalStakeCredits and totalStakeIdr as decimal strings, plus ticket count and rank.

The public proof never contains operator ID, external user ID, linked Polynion user ID, wallet reference, balance, commercial terms, or settlement allocation. Native amounts are intentionally disclosed after landing so independent verifiers can recompute the committed mixed-money ranking and result.

Private operator ticket reports expose proofTicketId to correlate an owned v5 ticket with that anonymous UUID; it is null for legacy v4. The mapping remains private and is not itself added to the public proof.

The verifier checks native ticket economics, snapshot/public/lock digests, exact ranking, fallback ranks, unchanged strategy candidate, draw, selected branch, result, approach tracks, and owned-ticket classification. v1–v4 codecs and verifiers remain supported for their historical flights; v5 support is additive and does not rewrite old commitments or apply today's economy to an older proof.

Copyright © 2026