Introduction to Off-Ramp Webhooks
Ripio provides webhook notifications to keep your application informed about real-time status updates for Off-Ramp transactions. These events cover the process of converting cryptocurrency back into fiat currency and its subsequent withdrawal. Similar to On-Ramp events, Off-Ramp webhooks are sent as POST requests with a JSON payload to your configured endpoint. It is crucial to validate the signature of every incoming webhook request as detailed in the Webhooks Introduction.Event Payload Structure
Each Off-Ramp event notification message contains a JSON-formatted payload with the following general structure:eventType(String): The specific type of Off-Ramp event that occurred.issueDatetime(String): The Coordinated Universal Time (UTC) timestamp indicating when the event was triggered (e.g.,"2024-04-25T18:22:37Z").transactionObject(Object): An object containing details of the Off-Ramp transaction associated with the event.
Off-Ramp Event Types
The following event types are supported for Off-Ramp transactions:OFF-RAMP.DEPOSIT.RECEIVED
- Description: Sent after Ripio successfully confirms a cryptocurrency deposit to the address associated with the user’s active Off-Ramp session.
transactionObjecttypically includes: Off-Ramp transaction fields (see below), including details of the crypto deposit.
OFF-RAMP.TRADE.COMPLETED
- Description: Sent after Ripio successfully completes the trade operation, converting the deposited cryptocurrency into fiat currency.
transactionObjecttypically includes: Off-Ramp transaction fields.
OFF-RAMP.WITHDRAWAL.PROCESSING
- Description: Sent after Ripio initiates the fiat withdrawal process to the customer’s designated fiat account linked to the active Off-Ramp session.
transactionObjecttypically includes: Off-Ramp transaction fields.
OFF-RAMP.WITHDRAWAL.COMPLETED
- Description: Sent upon successful completion and confirmation that the fiat withdrawal to the customer’s account has been finalized.
transactionObjecttypically includes: Off-Ramp transaction fields.
OFF-RAMP.ORDER.CANCELLED
- Description: Sent if Ripio cancels the Off-Ramp order. This might occur if a customer breaches predefined transactional or periodic limits, or if the fiat payout could not be delivered to the destination account.
failureReasonsays why it was cancelled, andrefundableon the order says how it can be resolved:refundable: true— the trade never executed, so the crypto is still there and can be returned by requesting a refund for the order. A completed refund arrives asOFF-RAMP.ORDER.REFUNDED; a rejected one emits nothing, so read the order’slatestRefundfor that.refundable: false— the crypto was already sold and what failed was the fiat payout, so there is nothing to send back. Retry the payout against another destination account with Change Fiat Account and Reprocess.failureReason: INVALID_DESTINATIONis the usual cause.
transactionObjecttypically includes: Off-Ramp transaction fields.
OFF-RAMP.ORDER.REFUNDED
- Description: Sent when a crypto refund of the order’s deposit completes on-chain and the order moves to
REFUNDED. It is the only refund event on this ramp: a refund that is registered, approved or rejected emits nothing, so poll the order’slatestRefundto follow those. The refund is not necessarily one you requested —latestRefund.initiatedBysays whether it came from you, from the end user in the widget, or from Ripio’s support team. transactionObjecttypically includes: Off-Ramp transaction fields, withstatusasREFUNDEDandfailureReason/failureDetailcarrying why the order failed in the first place. The hash of the returned crypto is not in the payload — readrefundedTxnHashon the order.
OFF-RAMP.DEPOSIT.REJECTED
- Description: Sent when a crypto deposit reaches one of your customers’ deposit addresses but matches no off-ramp order, so no operation can be built from it. This only happens on the one-off order flow, where the deposit has to match an order exactly (address, amount, network, and an order still awaiting funds); a deposit into an off-ramp session’s address always finds its order and never produces this event. The money is owed back to the customer and Ripio’s support team resolves it — the event exists so that you learn about it from your own integration rather than from the customer.
transactionObjecttypically includes: deposit fields rather than order fields, because there is no order:customerId,depositId,order(null) and ametadataobject with the deposit as the blockchain reported it — amount, currency, network and transaction hash.
Transaction Object Fields for Off-Ramp Events
ThetransactionObject for Off-Ramp events generally includes the following fields:
transactionId(String): Unique identifier for the Off-Ramp transaction (often corresponds to the session ID).createdAt(String): Date and time the Off-Ramp session/transaction was created (UTC format).fiatAccountId(String): Unique identifier for the customer’s fiat account associated with the session.fromCurrency(String): The source cryptocurrency being off-ramped (e.g., “USDC”).toCurrency(String): The target fiat currency to be received (e.g., “ARS”, “MXN”).amount(String): The amount of the source cryptocurrency deposited by the customer.chain(String): The blockchain network used for the cryptocurrency deposit (e.g., “ETHEREUM”).address(String): The cryptocurrency deposit address used by the customer for this Off-Ramp transaction.status(String): The current status of the Off-Ramp transaction.txnHash(String, optional): The transaction hash for the on-chain cryptocurrency deposit. This is typically present inOFF-RAMP.DEPOSIT.RECEIVEDand subsequent events.customerId(String, optional): Unique identifier of the customer associated with the transaction.failureReason(String | null): Machine-readable reason the order failed or was cancelled. One ofINVALID_DESTINATION,EXPIRED_QUOTE,PROVIDER_REJECTED,PROVIDER_ERROR,REFUND_BY_PROVIDER,USER_BANNED,AMOUNT_LIMIT_EXCEEDED,KYC_NOT_APPROVED, orINTERNAL_ERROR. Populated in theOFF-RAMP.ORDER.CANCELLEDandOFF-RAMP.ORDER.REFUNDEDevents; null in all other events.failureDetail(String | null): Human-readable message that expands onfailureReason, suitable for display to end customers. Null wheneverfailureReasonis null.
Off-Ramp Event Flows
The following sequences illustrate the expected order of events in common Off-Ramp scenarios. As with On-Ramp events, your system should be prepared to handle webhooks that might arrive out of the typical order.-
Standard Successful Off-Ramp Transaction Flow:
OFF-RAMP.DEPOSIT.RECEIVED→OFF-RAMP.TRADE.COMPLETED→OFF-RAMP.WITHDRAWAL.PROCESSING→OFF-RAMP.WITHDRAWAL.COMPLETED- Description: This is the usual flow for a successful Off-Ramp transaction, starting from the confirmation of a cryptocurrency deposit, followed by its conversion to fiat, initiation of the fiat withdrawal, and finally, the completion of the withdrawal.
-
Order Cancellation Flow (e.g., Due to Limit Breach):
OFF-RAMP.DEPOSIT.RECEIVED→OFF-RAMP.ORDER.CANCELLED- Description: This flow occurs when a cryptocurrency deposit is received, but the transaction is subsequently cancelled, for instance, if the customer exceeds transactional limits. The crypto can then be returned by requesting a refund for the order.
-
Failed Payout and Reprocessing Flow:
OFF-RAMP.DEPOSIT.RECEIVED→OFF-RAMP.TRADE.COMPLETED→OFF-RAMP.WITHDRAWAL.PROCESSING→OFF-RAMP.ORDER.CANCELLED→ (you call Change Fiat Account and Reprocess) →OFF-RAMP.WITHDRAWAL.PROCESSING→OFF-RAMP.WITHDRAWAL.COMPLETED- Description: The trade went through but the fiat could not be delivered, so the order was cancelled with
failureReason: INVALID_DESTINATION. Pointing it at another destination account resumes it from the payout: the deposit and the trade are not replayed, so no secondOFF-RAMP.DEPOSIT.RECEIVEDorOFF-RAMP.TRADE.COMPLETEDarrives. If the new destination fails as well,OFF-RAMP.ORDER.CANCELLEDis sent again and the order can be reprocessed once more.
- Description: The trade went through but the fiat could not be delivered, so the order was cancelled with
-
Refund Flow:
OFF-RAMP.DEPOSIT.RECEIVED→OFF-RAMP.ORDER.CANCELLED→ (a refund is requested and approved) →OFF-RAMP.ORDER.REFUNDED- Description: The order was cancelled before the trade, so the crypto is still there and can be returned. Nothing is emitted between the two events: registering the refund, its approval and a rejection are all silent, and the gap can last as long as the review takes —
latestRefundon the order is what reports progress.OFF-RAMP.ORDER.REFUNDEDmeans the crypto is back on-chain.
- Description: The order was cancelled before the trade, so the crypto is still there and can be returned. Nothing is emitted between the two events: registering the refund, its approval and a rejection are all silent, and the gap can last as long as the review takes —
-
Unmatched Deposit:
OFF-RAMP.DEPOSIT.REJECTED- Description: Crypto arrived at one of your customers’ deposit addresses with no order to apply it to, so no other event follows — there is no order to have a lifecycle. Reachable only on the one-off order flow. Ripio’s support team returns the money.
Important Considerations
- Webhook Delivery Order: While these flows outline the logical progression, network latency or server processing can cause webhooks to arrive out of sequence. Design your webhook handlers to accommodate this.
- Idempotency: Ensure that processing the same webhook event multiple times does not lead to unintended side effects or data inconsistencies.
- Error Management: Implement robust error handling and logging in your webhook consumer.
- Configuration: For details on setting up your webhook endpoints within the Ripio partner system, please consult with the Ripio technical team.