Skip to main content
The Payments API handles payment records linked to purchase orders and exposes a public endpoint for listing available payment methods. Payment state changes are atomic — a successful payment automatically marks the associated order as paid, while a failed payment cancels the order and releases reserved slots.

Payment methods

GET /api/payments/methods/

Returns all accepted payment methods. This endpoint is public — no authentication is required.
(none)
No query parameters are accepted by this endpoint.
{
  "payment_methods": [
    {
      "id": 1,
      "method": "MASTERCARD",
      "label": "Tarjeta Mastercard",
      "description": "Pago con tarjeta Mastercard",
      "is_active": true
    },
    {
      "id": 2,
      "method": "VISA",
      "label": "Tarjeta Visa",
      "description": "Pago con tarjeta Visa",
      "is_active": true
    },
    {
      "id": 3,
      "method": "PAYPAL",
      "label": "PayPal",
      "description": "Pago a través de PayPal",
      "is_active": true
    },
    {
      "id": 4,
      "method": "SINPE",
      "label": "SINPE Móvil",
      "description": "Transferencia SINPE Móvil (Costa Rica)",
      "is_active": true
    },
    {
      "id": 5,
      "method": "CASH",
      "label": "Efectivo",
      "description": "Pago en efectivo en el sitio",
      "is_active": true
    }
  ],
  "total_methods": 5
}
Response fields
payment_methods
object[]
required
List of accepted payment methods.
total_methods
number
required
Total count of payment methods returned.

Payment records

All endpoints below require authentication.
Authenticated users see only their own payments. Staff and superusers see all payments across all users.

GET /api/payments/

List payment records visible to the authenticated user.

POST /api/payments/create/

Create a new payment record and link it to an existing purchase order. The operation runs inside a database transaction — if any step fails, the entire operation rolls back. Request body
purchase_order
number
required
ID of the purchase order to pay. The order must be in PENDING or PAID status.
payment_method
string
required
Payment method code stored in the Payments model. One of CARD, PAYPAL, SINPE, CASH.
The Payments model stores the method as CARD (not MASTERCARD or VISA). The specific card network is tracked at the frontend/payment-processor level. Use GET /api/payments/methods/ to map the user-facing labels (Mastercard, Visa) to their display values.
transaction_id
string
External transaction identifier. Required for MASTERCARD, VISA, and PAYPAL. Optional for CASH and SINPE. Must be 5–100 alphanumeric characters, hyphens, or underscores.
status
string
required
Initial payment status. One of SUCCESS, FAILED.
Example request
cURL
curl --request POST \
  --url https://api.parquemarino.example.com/api/payments/create/ \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '{
    "purchase_order": 42,
    "payment_method": "SINPE",
    "transaction_id": "SINPE-20260325-001",
    "status": "SUCCESS"
  }'
Response fields (201 Created)
id
number
required
Unique payment record ID.
purchase_order
number
required
ID of the linked purchase order.
payment_date
string
required
ISO 8601 datetime when the payment was recorded. Set automatically on creation.
payment_method
string
required
Payment method used. One of CARD, PAYPAL, SINPE, CASH (as stored in the Payments model).
transaction_id
string
required
External transaction identifier.
status
string
required
Payment result. SUCCESS or FAILED.
order_total
number
required
Total amount of the linked purchase order (read-only, computed field).
order_status
string
required
Current status of the linked purchase order after the payment was applied (read-only, computed field).
days_since_payment
number
required
Number of days elapsed since payment_date (read-only, computed field).
{
  "id": 7,
  "purchase_order": 42,
  "payment_date": "2026-03-25T14:30:00Z",
  "payment_method": "SINPE",
  "transaction_id": "SINPE-20260325-001",
  "status": "SUCCESS",
  "order_total": 15000.00,
  "order_status": "PAID",
  "days_since_payment": 0
}

GET /api/payments//

Retrieve a single payment record by ID.
id
number
required
Payment record ID.

PUT /api/payments//update/

Update a payment record. Accepts the same body fields as POST /api/payments/create/. The update also runs inside a database transaction.

DELETE /api/payments//delete/

Delete a payment record.

Status transitions and side effects

When a payment record is saved, the model automatically triggers state changes on the linked purchase order:
Payment statusPurchase order effect
SUCCESSOrder is marked as paid (mark_as_paid)
FAILEDOrder is cancelled and reserved visit slots are released (mark_as_cancelled)
These transitions are enforced at the model level and cannot be bypassed through the API.

Audit trail

All payment creation and status changes are captured by Django signals in purchase_orders/audit.py. Events are written to logs/payments.log with the following fields: timestamp, event_type, model, instance_id, user_id, user_email, changes, and extra_data. Critical events (PAYMENT_SUCCESS, PAYMENT_FAILED) emit dedicated log entries in addition to the generic UPDATE entry.

Donations

The donations system allows supporters to contribute to the park. Managed through the same payments app.
The Donation model does not require a linked PurchaseOrders record — it is independent. Authenticated users can submit and view their own donations.

Donation model

FieldTypeDescription
idintegerAuto-generated primary key
amountdecimal(10,2)Donation amount
currencystringCRC (colones) or USD (dollars)
donor_namestring (max 100)Optional donor name
donor_emailemailOptional donor email
payment_methodstringCARD, PAYPAL, or CASH (includes SINPE)
transaction_idstring (max 100)Optional external transaction reference
statusstringSUCCESS, FAILED, or PENDING (default)
created_atdatetimeAuto-set on creation

GET /api/payments/donations/

List donation records. Admins see all donations; regular users see only their own.
Requires authentication.
curl https://api.parquemarino.cr/api/payments/donations/ \
  -H "Authorization: Bearer <token>"

POST /api/payments/donations/create/

Create a new donation record.
Requires authentication.
Request body
amount
decimal
required
Donation amount. Must be a positive decimal (e.g., 5000.00).
currency
string
required
Currency code: CRC or USD.
donor_name
string
Optional name of the donor (max 100 characters).
donor_email
string
Optional email address for the donor.
payment_method
string
required
Payment method: CARD, PAYPAL, or CASH (includes SINPE).
transaction_id
string
Optional external transaction reference from the payment processor.
status
string
Initial status: SUCCESS, FAILED, or PENDING. Defaults to PENDING.
curl -X POST https://api.parquemarino.cr/api/payments/donations/create/ \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": "10000.00",
    "currency": "CRC",
    "donor_name": "María García",
    "donor_email": "[email protected]",
    "payment_method": "CARD",
    "status": "SUCCESS"
  }'
201 response
{
  "id": 5,
  "amount": "10000.00",
  "currency": "CRC",
  "donor_name": "María García",
  "donor_email": "[email protected]",
  "payment_method": "CARD",
  "transaction_id": null,
  "status": "SUCCESS",
  "created_at": "2026-03-25T10:00:00Z"
}

GET /api/payments/donations//

Retrieve a single donation record by ID. Requires authentication.

PUT /api/payments/donations//update/

Update a donation record. Requires authentication.

DELETE /api/payments/donations//delete/

Delete a donation record. Requires authentication.

Build docs developers (and LLMs) love