Payments - Usage Examples

Last Updated: 2026-07-08

Endpoints below use the root-level hyphenated routes (/payment-methods/, /payment-processors/, /refunds/) where they exist, and the app-prefixed routes (/payments/payments/, /payments/terminal/..., /payments/confirm/) where they don't. See Views for the full URL grounding, both route families are live.

Authentication

# Step 1: Obtain token
curl -s -X POST https://api.djanity.com/auth/login/ \
  -H "Content-Type: application/json" \
  -d '{"username": "[email protected]", "password": "..."}'
# Returns: {"access": "<jwt>", "refresh": "<jwt>"}

# Step 2: All subsequent requests use:
# -H "Authorization: Bearer <token>"

Payment Methods

List payment methods for a store

curl -s "https://api.djanity.com/payment-methods/by_store/?store_id=<django-store-uuid>"

Response:

{
  "store_id": "<django-store-uuid>",
  "available_methods": [
    {
      "id": "pm-a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "sanity_id": "pm-cash",
      "name": "Cash",
      "method_type": "cash",
      "is_active": true,
      "is_pos_available": true,
      "minimum_amount": "0.01",
      "maximum_amount": null,
      "display_order": 1,
      "configuration": {},
      "processor": null
    },
    {
      "id": "pm-b2c3d4e5-f6a7-8901-bcde-f12345678901",
      "sanity_id": "pm-visa-mastercard",
      "name": "Visa/Mastercard",
      "method_type": "credit_card",
      "is_active": true,
      "is_pos_available": true,
      "minimum_amount": "0.50",
      "maximum_amount": null,
      "display_order": 2,
      "processor": {
        "id": "processor-uuid",
        "name": "Stripe Production",
        "processor_type": "stripe",
        "processing_fee_percentage": "2.90",
        "processing_fee_fixed": "0.30"
      }
    }
  ],
  "count": 2
}

processor.configuration is never included in this response, only fee and display metadata needed by POS clients.


Terminal Payments

Request a connection token (processor-agnostic)

curl -s -X POST https://api.djanity.com/payments/terminal/connection-token/ \
  -H "Content-Type: application/json" \
  -d '{"processor_type": "stripe"}'

Response:

{
  "secret": "pctx_1OqXxX2eZvKYlo2C8nKLpQXY",
  "processor_type": "stripe"
}

Create a terminal payment session

curl -s -X POST https://api.djanity.com/payments/terminal/create-payment/ \
  -H "Content-Type: application/json" \
  -d '{
    "processor_type": "stripe",
    "amount": 4318,
    "currency": "usd"
  }'

Response:

{
  "id": "pi_1OqXxX2eZvKYlo2CAbCdEfGh",
  "client_secret": "pi_1OqXxX2eZvKYlo2CAbCdEfGh_secret_...",
  "amount": 4318,
  "currency": "usd",
  "status": "requires_payment_method"
}

Confirm a payment after a 3DS challenge

curl -s -X POST https://api.djanity.com/payments/confirm/ \
  -H "Content-Type: application/json" \
  -d '{"payment_intent_id": "pi_1OqXxX2eZvKYlo2CAbCdEfGh"}'

Response (success):

{"confirmed": true, "transaction_id": "223e4567-e89b-12d3-a456-426614174001"}

Response (failure):

{"confirmed": false, "error": "Payment failed. Status: requires_payment_method"}

This endpoint is authorized by matching the caller's web session to the CheckoutSession behind the referenced payment, not by a bearer token, it is safe to call unauthenticated because ownership is verified server-side against local DB state.


Refunds

RefundService - tuple unpacking

RefundService.process_refund always returns a 3-tuple. Call sites must unpack all three values:

from nextango.apps.payments.services import RefundService
from decimal import Decimal

# Success path
success, refund, message = RefundService.process_refund(
    payment_id=payment_uuid,
    amount=Decimal("43.18"),
    reason="Customer returned item"
)

if success:
    # refund is a Refund instance with status='succeeded'
    print(f"Refund {refund.refund_id} processed: {message}")
else:
    if refund is not None:
        # A failed Refund record was persisted (status='failed')
        # This happens when payment.payment_method is None
        print(f"Refund {refund.refund_id} created but failed: {message}")
    else:
        # Validation error or unexpected exception, no Refund record created
        print(f"Refund rejected: {message}")

Key behavior: when payment.payment_method is None, a Refund row is written to the database with status='failed' and returned as the second element of the tuple. Callers should check refund is not None before accessing refund.refund_id.


Process a refund

curl -s -X POST https://api.djanity.com/payments/payments/pay-uuid-here/process_refund/ \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": "43.18",
    "reason": "Customer returned item, defective product"
  }'

Response (201 Created):

{
  "id": "ref-uuid-here",
  "refund_id": "REF-20260708-A1B2C3D4",
  "payment": "pay-uuid-here",
  "amount": "43.18",
  "reason": "Customer returned item, defective product",
  "status": "pending",
  "processor_refund_id": null,
  "created_at": "2026-07-08T15:00:00Z"
}

This is the recommended path over POST /refunds/ directly, process_refund includes the cumulative-refund-amount check against existing refunds on the same payment.


Was this page helpful?