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 durable callback delivery reconstructs data at send time for aggregate_type = mini_app_order. That means trade callback data is operator-actionable even if the stored outbox payload is minimal.
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.
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 when trade fails and no successful final execution exists.
{
"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
