Reference
onTransactionCreated (RAMPS_TRANSACTION_CREATED)
Optional widget callback after validate succeeds (before commit): persist the stable Ramps transaction id, mgiTransactionId for webhook correlation, and reopen view mode if the user leaves mid-flow.
RAMPS_TRANSACTION_CREATED
The widget posts RAMPS_TRANSACTION_CREATED once the Ramps transaction record exists: immediately after validate succeeds and Ramps returns a transactionId. It fires before commit, signing, deposit (cash-out), and completion.
It does not fire before validate. KYC and any required fields must complete first. Validate allocates the stable Ramps id; this event is how the widget surfaces that ID to your app.
Partners use this event to persist the stable Ramps transaction id early, so an interrupted flow still leaves enough state for view mode and support. Because the ID exists after validate but before commit, you can reopen the widget in view mode while the user is still in the flow (for example, after validate but before they finish commit or Sign & Send).
The payload also includes mgiTransactionId when validate bound a MoneyGram quote, so partners can map status webhooks to a pending credit or history row without an extra status call.
For history storage patterns and view mode, see Partner transaction history.
For transaction status and webhooks (all flows), see Transaction status & webhooks.
For custodial cash-in crediting, see Custodial cash-in.
| Stage | RAMPS_TRANSACTION_CREATED |
|---|---|
| Before validate (quote, KYC, required fields) | Does not fire |
Validate succeeds (transactionId allocated) | Fires once |
| EDD / KYC corrections and re-validate (same transaction) | Does not fire again for the same id |
| Commit, Sign & Send, deposit, done screen | Does not fire again |
| View mode (reopen existing transaction) | Does not fire again |
Quote → KYC → Validate succeeds → RAMPS_TRANSACTION_CREATED → Commit / Sign & Send → Done screen → RAMPS_TRANSACTION_COMPLETE │ │ └── id + mgiTransactionId are stable from here onward └── view mode works from here (status may still be validated / pending_kyc)
| Surface | Mechanism |
|---|---|
| Web SDK | onTransactionCreated(transaction) callback on createRamps |
| React Native | postMessage with type: 'RAMPS_TRANSACTION_CREATED' |
| View mode | Does not fire again when reopening an existing transaction |
The event fires at most once per transaction in the widget flow. It is not retried if the host misses it. Partners that require durable capture should also persist the ID at commit or poll status as a fallback.
onTransactionCreated is optional. Integrations that only listen for onComplete / RAMPS_TRANSACTION_COMPLETE continue to work.
Type: TransactionCreatedRecord (@ramps/types)
interface TransactionCreatedRecord { /** Stable Ramps transaction ID. Same value as RAMPS_TRANSACTION_COMPLETE.id */ id: string /** * MoneyGram transaction ID for the quote backing this transaction. * Use to correlate status webhooks. Omitted only if validate ran without an MGI ID. */ mgiTransactionId?: string /** 'cash-in' for on-ramp, 'cash-out' for off-ramp */ type: 'cash-in' | 'cash-out' /** Always 'created' on this event */ status: 'created' chain: 'solana' | 'stellar' | 'ethereum' | /* ... */ asset: 'USDC' | /* ... */ walletType: 'custodial' | 'non-custodial' walletAddress: string amount: number /** ISO 8601 quote expiry. Past this the transaction cannot complete */ quoteExpiresAt?: string /** ISO 8601 timestamp of this event */ createdAt: string // Present when quote economics parsed successfully from the settled quote: fees?: { mgi: number; partner: number; total: number; currency: string } sendPrincipal?: number destinationAmount?: number destinationCurrency?: string exchangeRate?: number}
Field notes
| Field | Cash-in | Cash-out |
|---|---|---|
id | Ramps transaction ID for view mode and GET /status | Same |
mgiTransactionId | MoneyGram ID for webhook correlation | Same |
type | 'cash-in' | 'cash-out' |
walletAddress | Destination wallet (omnibus for custodial cash-in) | Source wallet (omnibus for custodial cash-out) |
amount | USDC amount the user receives | USDC amount the user sends |
referenceNumber | Not present (assigned later at commit / completion) | Not present at creation |
fees.currency | Fiat (counter currency) | USDC |
Quote economics (fees, sendPrincipal, etc.) are included only when every figure parses cleanly from the settled quote. If any value is missing or invalid, the whole economics block is omitted rather than sending partial numbers.
Quote → KYC → Validate succeeds → RAMPS_TRANSACTION_CREATED → Commit → Done screen → RAMPS_TRANSACTION_COMPLETE │ └── id + mgiTransactionId are stable from here onward
| Stage | Event |
|---|---|
| After validate (pre-commit) | RAMPS_TRANSACTION_CREATED |
| After commit (confirmation code shown) | RAMPS_TRANSACTION_COMPLETE |
| After user pays at store | No widget event (poll status or webhook) |
| USDC delivered to omnibus | GET /status?sync=true → completed |
For custodial cash-in, there is no RAMPS_DEPOSIT_ADDRESS between creation and completion.
Persist mgiTransactionId and map it to customerIdentifier from your session when this event fires. Credit internal balances when status reaches completed (via webhook or poll).
See Custodial cash-in · Crediting pattern and Transaction status & webhooks.
createRamps({ sessionToken, wallet: { address, chain: 'solana', asset: 'USDC', walletType }, transaction: { type: 'on-ramp' }, onTransactionCreated: (tx) => { savePendingTransaction({ id: tx.id, mgiTransactionId: tx.mgiTransactionId, type: tx.type, // 'cash-in' amount: String(tx.amount), status: 'created', walletType: tx.walletType, createdAt: Date.now(), }) }, onComplete: (tx) => { updateTransaction(tx.id, { referenceNumber: tx.referenceNumber, status: tx.status, }) },})
case 'RAMPS_TRANSACTION_CREATED': { const p = payload as TransactionCreatedRecord await AsyncStorage.setItem(`mgi_tx_${p.id}`, JSON.stringify({ id: p.id, mgiTransactionId: p.mgiTransactionId, type: p.type, amount: String(p.amount), asset: p.asset, status: 'created', walletType: p.walletType, createdAt: Date.now(), })) break}
Both events report the same id. Treat creation as an upsert and completion as an update:
// Key storage on id aloneconst key = `mgi_tx_${record.id}`
RAMPS_TRANSACTION_CREATED | RAMPS_TRANSACTION_COMPLETE | |
|---|---|---|
| When | After validate succeeds | Done screen |
status | 'created' | Final status (e.g. 'completed', 'committed') |
mgiTransactionId | Present when validate bound a quote | Not present (use created event or status API) |
referenceNumber | Absent | Present when MoneyGram has assigned one |
quote | Economics flattened onto payload | Full quote object on TransactionRecord |
| View mode input | Yes (viewTransaction.id) | N/A (do not expect re-fire in view mode) |