Skip to main content
POST
/
api
/
v1
/
ticket-payments
Pay Ticket
curl --request POST \
  --url https://api.example.com/api/v1/ticket-payments \
  --header 'Content-Type: application/json' \
  --data '
{
  "ticketId": "<string>",
  "amountPaid": 123,
  "method": {},
  "isFinal": true,
  "notes": "<string>",
  "idempotencyKey": "<string>",
  "ventanaId": "<string>"
}
'
{
  "id": "<string>",
  "ticketId": "<string>",
  "amountPaid": 123,
  "method": "<string>",
  "isFinal": true,
  "isReversed": true,
  "paidById": "<string>",
  "createdAt": "<string>",
  "meta.cached": true
}

Overview

Registers a payment for a winning ticket. Supports partial payments and idempotency for safe retries. Only tickets in EVALUATED status with isWinner=true can be paid.

Authentication

Requires JWT authentication. User role affects RBAC filtering:
  • ADMIN: Can pay any ticket
  • VENTANA: Can pay tickets from their window
  • VENDEDOR: Can pay their own tickets

Request Body

ticketId
string
required
UUID of the winning ticket to pay
amountPaid
number
required
Amount to pay (must be > 0 and ≤ total payout)
method
enum
default:"cash"
Payment method: cash, check, transfer, system
isFinal
boolean
default:"false"
Mark as final payment (updates ticket status to PAID)
notes
string
Optional notes (max 300 characters)
idempotencyKey
string
Unique key for idempotency (min 8, max 100 characters). If key already exists, returns cached payment with meta.cached: true
ventanaId
string
Optional ventana ID override (admin only)

Response

id
string
Payment ID (UUID)
ticketId
string
Ticket ID
amountPaid
number
Amount paid
method
string
Payment method
isFinal
boolean
Whether this is marked as final payment
isReversed
boolean
Whether this payment has been reversed
paidById
string
User ID who registered the payment
createdAt
string
ISO 8601 timestamp
meta.cached
boolean
Present if payment was returned from idempotency cache (status 200 instead of 201)

Status Codes

  • 201: Payment created successfully
  • 200: Cached payment returned (idempotency key match)
  • 400: Invalid amount or ticket not in EVALUATED status
  • 403: RBAC violation (user cannot pay this ticket)
  • 404: Ticket not found
  • 409: Ticket is not a winner or already has pending payment

Example Request

{
  "ticketId": "550e8400-e29b-41d4-a716-446655440000",
  "amountPaid": 50000,
  "method": "cash",
  "isFinal": true,
  "notes": "Pago completo en efectivo",
  "idempotencyKey": "payment-2024-03-15-001"
}

Example Response

{
  "success": true,
  "data": {
    "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
    "ticketId": "550e8400-e29b-41d4-a716-446655440000",
    "amountPaid": 50000,
    "method": "cash",
    "isFinal": true,
    "isReversed": false,
    "notes": "Pago completo en efectivo",
    "paidById": "123e4567-e89b-12d3-a456-426614174000",
    "createdAt": "2024-03-15T10:30:00.000Z"
  }
}

Activity Logging

Logs action TICKET_PAY with details:
  • created: Whether payment was newly created
  • cached: Whether response was from idempotency cache

Build docs developers (and LLMs) love