1. Documentation
Vortex
  • Documentation
    • Overview
    • Quick Start With The SDK
    • Authentication And Partner Keys
    • Ramp Lifecycle
    • Ephemeral Key Custody
    • Quotes And Pricing
    • Webhooks
    • Widget Integration
    • BRL / KYC notes
    • Sandbox
    • Production Checklist
    • AI Agent Integration
  • API Endpoints
    • Vortex Widget
      • Create widget session
    • Quotes
      • Create a new quote
      • Get existing quote
      • Create a quote for the best network
    • Ramp
      • Get ramp status
      • Get ramp error logs
      • Get ramp history for wallet address
      • Register new ramp process
      • Start ramp process
      • Update ramp process
    • Reference Data
      • Supported Countries
      • Supported Cryptocurrencies
      • Supported Fiat Currencies
      • Supported Payment Methods
    • Public Key
      • Public Key
    • Webhooks
      • Register Webhook
      • Delete Webhook
    • Account Management
      • Create user or retry KYC
      • Get user's KYC status
      • Get selfie liveness URL
      • Get KYC document upload URLs
      • Get user information
      • Get user's remaining transaction limits
      • Submit KYC level 1 data
      • Validate Pix key
    • Schemas
      • AccountMeta
      • AveniaDocumentType
      • AveniaKYCDataUploadRequest
      • AveniaKYCDataUploadResponse
      • BrlaAddress
      • BrlaErrorResponse
      • BrlaGetSelfieLivenessUrlResponse
      • BrlaValidatePixKeyResponse
      • CleanupPhase
      • CountryCode
      • CreateBestQuoteRequest
      • CreateQuoteRequest
      • CreateSubaccountRequest
      • CreateSubaccountResponse
      • DestinationType
      • DocumentUploadEntry
      • ErrorResponse
      • FiatToken
      • GetKycStatusResponse
      • GetRampErrorLogsResponse
      • GetRampHistoryResponse
      • GetRampHistoryTransaction
      • GetUserRemainingLimitResponse
      • GetUserResponse
      • GetWidgetUrlLocked
      • GetWidgetUrlRefresh
      • KYCDataUploadFileFiles
      • KYCDocType
      • KycLevel1Payload
      • KycLevel1Response
      • Networks
      • OnChainToken
      • PaymentData
      • PaymentMethod
      • PresignedTx
      • QuoteResponse
      • RampCurrency
      • RampDirection
      • RampErrorLog
      • RampPhase
      • RampProcess
      • RegisterRampRequest
      • SimpleStatus
      • StartKYC2Request
      • StartKYC2Response
      • StartRampRequest
      • TaxIdType
      • TriggerOfframpRequest
      • TriggerOfframpResponse
      • UnsignedTx
      • UpdateRampRequest
      • ValidatePixKeyResponse
  1. Documentation

Webhooks

Vortex webhooks let your application receive real-time notifications when ramp lifecycle events occur, instead of continuously polling GET /v1/ramp/{id}.
You can subscribe to:
Transaction creation — a new ramp is registered.
Status changes — a ramp's status moves between PENDING, COMPLETE, and FAILED.

Security Model#

Every webhook request includes:
X-Vortex-Signature — RSA-PSS signature of the raw request body, base64-encoded.
X-Vortex-Timestamp — Unix timestamp (seconds) of the request.
All webhook URLs must use HTTPS. Signatures are verified against the RSA-PSS 2048-bit public key returned by GET /v1/public-key.

Registering A Webhook#

{
  "url": "https://partner.example.com/vortex/webhook",
  "quoteId": "quote_...",
  "events": ["TRANSACTION_CREATED", "STATUS_CHANGE"]
}
The body must include exactly one of quoteId or sessionId. Use sessionId to subscribe to events from a Widget-hosted ramp instead of a partner-created quote.
Store the returned webhook ID so you can delete it later.
Webhook endpoints require a partner secret key. They do not accept Supabase Bearer tokens.

Event Types#

TRANSACTION_CREATED#

Fired immediately after the ramp state is created (POST /v1/ramp/register).
{
  "eventType": "TRANSACTION_CREATED",
  "timestamp": "2025-01-15T10:30:00.000Z",
  "payload": {
    "quoteId": "quote_...",
    "transactionId": "tx_...",
    "sessionId": "session_...",
    "transactionStatus": "PENDING",
    "transactionType": "BUY"
  }
}
FieldDescription
quoteIdUnique identifier for the quote.
transactionIdUnique identifier for the ramp (rampId).
sessionIdWidget session identifier if registered against a session.
transactionStatusAlways "PENDING" for new transactions.
transactionType"BUY" (onramp) or "SELL" (offramp).

STATUS_CHANGE#

Fired whenever the ramp's status changes during processing.
{
  "eventType": "STATUS_CHANGE",
  "timestamp": "2025-01-15T10:35:00.000Z",
  "payload": {
    "quoteId": "quote_...",
    "transactionId": "tx_...",
    "sessionId": "session_...",
    "transactionStatus": "COMPLETE",
    "transactionType": "BUY"
  }
}
Status values:
PENDING — ramp is in progress.
COMPLETE — ramp completed successfully.
FAILED — ramp failed or timed out.

Retry Mechanism#

Vortex automatically retries failed webhook deliveries:
Attempts: up to 5
Backoff: exponential (1s, 2s, 4s, 8s, 16s)
Timeout: 30 seconds per request
Auto-deactivation: after 5 consecutive failures, the webhook is disabled and must be re-registered.
Return 2xx quickly. Do heavy work asynchronously after acknowledging the request.

Verification#

Fetch the current public key:
Verify signatures using RSA-PSS with SHA-256. Reject requests that fail signature verification, are outside an acceptable timestamp window, contain malformed payloads, or do not match the expected event structure.

Example: Bun + TypeScript Listener#

When To Still Poll#

Webhooks are preferable for reconciliation, back-office automation, and support workflows. Polling GET /v1/ramp/{id} is still useful for live user-facing status screens where you want sub-second updates without waiting for the next webhook delivery. GET /v1/ramp/{id}/errors returns the structured error log and is useful for support tooling.

Modified at 2026-05-19 08:03:57
Previous
Quotes And Pricing
Next
Widget Integration
Built with