Partners

Checkout & recovery

Reserve tickets before payment and keep the buyer informed until the purchase completes.

1. Create a checkout

Call POST /raffles/{raffleId}/checkouts from your server with an Idempotency-Key header and this body:

{"external_user_ref":"buyer_123","display_name":"Alex","qty":2}

Use a unique, non-empty key of at most 200 characters for each purchase. Persist it before making the request. On timeouts, send the same key and body again.

A 201 returns the checkout. Save its id before opening the buyer's wallet. Replays return the existing checkout's current state; they do not create a fresh payment opportunity.

FieldHow to use it
idResume and query this purchase
total_usdThe agreed total, already including quantity
paymentWallet payment details, including the exact memo
payment_deadlineDo not initiate payment after this time
settlement_deadlineLatest settlement time for this reserved purchase
status, errorThe current outcome and any failure reason
ticketsTicket objects with ticket_no and code, populated on completion

RAFFLE_PURCHASE_IN_PROGRESS means the buyer has an unresolved purchase. Resume it instead of charging again. IDEMPOTENCY_KEY_REUSED means the key was reused with a different raffle or quantity.

2. Submit the wallet payment

Follow Build the wallet payment. Use the exact payment.memo returned for this checkout. It includes the checkout ID.

After the wallet submits the transaction, call POST /raffles/{raffleId}/checkouts/{checkoutId}/payment with tx_signature. Register it promptly before payment_deadline; do not wait for finalization.

A 202 acknowledges the submission. It does not confirm tickets.

3. Track the result

Poll GET /raffles/{raffleId}/checkouts/{checkoutId}, or use payment.updated to trigger GET /payments/{operationId}. Keep the checkout ID through reloads and sign-in changes in your UI.

API statusWhat the buyer sees
awaiting_paymentReady for wallet approval, if payment has not already been submitted and the deadline has not passed
queued, processing, paidPayment processing; do not prompt for another payment
completedTickets confirmed; display the returned ticket codes
failedA clear error. Read retry_allowed before offering a retry
cancelledReservation ended; keep checking if the buyer already submitted payment
refund_pendingRefund pending
refundedRefund completed
reviewPayment under review; retain the purchase ID for support

Only completed confirms a ticket purchase

A successful HTTP response, a wallet signature, or status paid alone does not mean tickets were issued.

Handle interruptions without a second charge

  • Request timed out: retry with the same checkout key or transaction signature, depending on the step.
  • Browser closed after payment: recover the checkout ID from your server and query its status.
  • Wallet transaction outcome unknown: keep checking. Do not create a replacement payment.
  • Failed attempt: a different signature is accepted only after the previous attempt is proven failed or expired and the deadline still permits it.
  • refund_only: true: a later successful payment will be refunded. Do not show another Pay button.

Use one status request at a time with backoff. Offer a Check status action after an extended wait rather than spinning indefinitely.

Track refunds

When returned, use refund_operation_id with GET /payments/{operationId}. A refund operation has kind: "refund"; its completed status means the refund finished, not that tickets were issued.

Verity-collected refunds require no refund-confirmation call from you. That endpoint is only for separately agreed partner-collected integrations.

On this page