Event types
Event types
Current event list comes from packages/mini-app/src/types.ts.
Source-of-truth list
mini_app.login.succeededmini_app.trade.submittedmini_app.trade.processedmini_app.trade.failedmini_app.trade.compensation_requiredmini_app.redemption.processedmini_app.redemption.failedmini_app.payout.pendingmini_app.logout.requestedmini_app.session.expiredmini_app.polyflight.purchase.processedmini_app.polyflight.purchase.failedmini_app.polyflight.ticket.resolvedmini_app.polyflight.payout.pendingmini_app.polyflight.payout.processedmini_app.polyflight.refund.pendingmini_app.polyflight.refund.processedmini_app.polyflight.purchase.compensated
Payload reference
Current callback delivery reconstructs data at send time for aggregate_type = mini_app_order. This includes current durable status, failure reason and execution linkage; it is not a frozen event-time order snapshot. Preserve event_id deduplication even if a replay's reconstructed data differs. The Polyflight snapshot boundary is described separately below.
Trade order data fields
Trade events with aggregate_type = mini_app_order use this data family:
order_idtrade_idexecuted_trade_idoperator_idoperator_user_idpolynion_user_idexternal_user_idmarket_idside:buyorselloutcome:yesornostatusrequested_external_amount_minorrequested_shares_microquoted_credits_equivalentquoted_external_amount_minorshares_microbalance_spenttrade_feetrade_fee_creditscurrency_codefx_rate_snapshot_idfailure_reason
Do not expect legacy credits_delta or external_amount_minor in trade callback data.
trade_fee is historical fee in integer minor units of currency_code, matching Operator Trade Fees view. trade_fee_credits is same fee denominated in Credits.
balance_spent is a shared historical field name, not a debit confirmation. For a buy it can contain the requested amount even on failure; for a sell it can describe the quoted/executed return. Interpret it with side, status and wallet evidence. shares_micro similarly does not by itself prove an executed trade.
mini_app.login.succeeded
Allowlisted event name for launch/session lifecycle. Current durable processor paths do not define an operator-actionable payload beyond the common envelope.
mini_app.trade.submitted
Allowlisted event name for order submission. Current durable trade processor callbacks use the processed, failed, or compensation-required terminal events below.
mini_app.trade.processed
Sent when trade completed successfully.
{
"order_id": 123,
"trade_id": 456,
"executed_trade_id": 456,
"operator_id": 12,
"operator_user_id": 34,
"polynion_user_id": 789,
"external_user_id": "operator-user-123",
"market_id": 51,
"side": "buy",
"outcome": "yes",
"status": "processed",
"requested_external_amount_minor": 10000,
"requested_shares_micro": null,
"quoted_credits_equivalent": 6340,
"quoted_external_amount_minor": 10000,
"shares_micro": 1234500,
"balance_spent": 10000,
"trade_fee": 39,
"trade_fee_credits": 25,
"currency_code": "IDR",
"fx_rate_snapshot_id": 88,
"failure_reason": null
}
mini_app.trade.failed
Sent for trade failure or a wallet/evidence hold such as manual_review. A rejected buy may have no trade, as below; an executed sell can retain a non-null executed_trade_id while its credit needs review. Do not infer “no trade executed” or “no wallet money moved” from the event name. Inspect side, source status, execution linkage and original wallet operation evidence.
{
"order_id": 123,
"trade_id": null,
"executed_trade_id": null,
"operator_id": 12,
"operator_user_id": 34,
"polynion_user_id": 789,
"external_user_id": "operator-user-123",
"market_id": 51,
"side": "buy",
"outcome": "yes",
"status": "failed",
"requested_external_amount_minor": 10000,
"requested_shares_micro": null,
"quoted_credits_equivalent": 6340,
"quoted_external_amount_minor": 10000,
"shares_micro": null,
"balance_spent": 10000,
"trade_fee": null,
"trade_fee_credits": null,
"currency_code": "IDR",
"fx_rate_snapshot_id": null,
"failure_reason": "OPERATOR_DEBIT_FAILED"
}
mini_app.trade.compensation_required
Sent when wallet debit happened but downstream completion needed manual or compensating handling.
{
"order_id": 123,
"trade_id": null,
"executed_trade_id": null,
"operator_id": 12,
"operator_user_id": 34,
"polynion_user_id": 789,
"external_user_id": "operator-user-123",
"market_id": 51,
"side": "buy",
"outcome": "yes",
"status": "compensation_pending",
"requested_external_amount_minor": 10000,
"requested_shares_micro": null,
"quoted_credits_equivalent": 6340,
"quoted_external_amount_minor": 10000,
"shares_micro": null,
"balance_spent": 10000,
"trade_fee": null,
"trade_fee_credits": null,
"currency_code": "IDR",
"fx_rate_snapshot_id": null,
"failure_reason": "DB_EXECUTION_FAILED_AFTER_DEBIT"
}
mini_app.redemption.processed
Sent when redemption or payout completed successfully.
{
"redemption_item_id": 77,
"run_id": 9,
"redeem_request_id": 88,
"operator_id": 12,
"operator_user_id": 34,
"external_amount_minor": 15000,
"fx_rate_snapshot_id": 91
}
mini_app.redemption.failed
Sent when redemption flow failed before successful credit completion.
{
"redemption_item_id": 77,
"run_id": 9,
"operator_id": 12,
"operator_user_id": 34,
"status": "manual_review",
"failure_reason": "OPERATOR_CREDIT_FAILED"
}
mini_app.payout.pending
Allowlisted event name for payout follow-up. Current Mini App redemption processor emits mini_app.redemption.failed with status = manual_review for unresolved payout-side failures.
mini_app.logout.requested
Allowlisted event name for operator-side session cleanup. Current durable processor paths do not define an operator-actionable payload beyond the common envelope.
mini_app.session.expired
Allowlisted event name for launched Mini App session expiry. Current durable processor paths do not define an operator-actionable payload beyond the common envelope.
Polyflight event semantics
| Event | Contract |
|---|---|
mini_app.polyflight.purchase.processed | Native debit and ticket admission completed. Do not debit from the webhook. |
mini_app.polyflight.purchase.failed | No ticket was admitted. status can be failed, manual_review, or compensation_pending; reconcile the purchase debit instead of assuming whether money moved. |
mini_app.polyflight.ticket.resolved | Ticket outcome and payout amount are final; this does not assert wallet delivery. Newly settled losses have payoutMinor: 0 and a non-null delivery obligationId, not money owed. |
mini_app.polyflight.payout.pending | A winning payout is owed, or its wallet credit is in manual_review. |
mini_app.polyflight.payout.processed | Winning wallet credit is confirmed. |
mini_app.polyflight.refund.pending | A cancelled-ticket full refund is owed, or its wallet credit is in manual_review. |
mini_app.polyflight.refund.processed | Cancelled-ticket wallet credit is confirmed. |
mini_app.polyflight.purchase.compensated | An applied debit with no admitted ticket was reversed. |
The signed envelope stays snake_case; Polyflight data keys are camelCase. Initial pending events use status = "owed" and do not signal a failed credit. A later pending event with status = "manual_review" includes failureReason. Processed events confirmed from operator evidence add manualResolution: true.
New Polyflight event snapshots include operatorUserId, externalUserId, currencyCode, stakeMinor (gross debit or purchase quote), feeMinor (ticket fee or quote), netStakeMinor, and potentialPayoutMinor. Purchase failures without a ticket report quoted economics only; they do not claim a debit or earned fee. Admitted-ticket events additionally include feeBps, payoutMultiplier, commercialTermsVersionId, ticketFeeShareBps, and positionShareBps; the last two describe the captured operator commercial allocation, not extra fees charged to the user. A cancelled-ticket refund reverses the full gross stake, including its fee. A no-ticket compensation reverses the full applied debit, with no earned ticket fee.
amountMinor on a pending payout/refund or compensation failure is owed, not yet confirmed cash; on a processed payout/refund or compensated purchase it is confirmed wallet credit/reversal. payoutMinor on ticket resolution is the result (0 for a loss), not proof of credit. status belongs to the event-time snapshot: later payment or manual resolution does not change it on webhook replay. Event omissions on older deliveries mean unknown, never zero; read API, events, and proof for precise fields.
The eight Polyflight events are unchanged. A new loss's zero-amount /credit acknowledgement is tracked by the ticket/payment lifecycle and loss_credit wallet operation; no loss payout pending/processed callback exists. ticket.resolved remains authoritative regardless of acknowledgement status. Historical loss payloads can retain obligationId: null; webhook replay does not backfill a loss delivery or rewrite planned/dispatched wallet evidence.
Use event_id to deduplicate delivery. Wallet debit, credit, and reversal requests have separate financial idempotency keys; a webhook must never trigger a second money movement. See API, events, and proof for the source-backed payload families, full envelope example, and handling table.
Guidance
- keep receiver tolerant to additive fields
- branch only on known
event_type - use
event_idfor dedupe - for current trade callbacks, prefer
order_id,trade_id/executed_trade_id,operator_user_id,external_user_id, andmarket_idfor support correlation - for current redemption callbacks, prefer
redemption_item_id,run_id,redeem_request_id,operator_user_id, andexternal_amount_minorwhen present - treat
failure_reasonas operator-facing diagnostic string, not enum guaranteed forever - examples above are source-backed where current contract already defines fields explicitly
