Skip to main content
Payment endpoints integrate with Stripe for card payments and support bank transfer orders. Most endpoints require authentication.

Create Payment Intent

Create a Stripe Payment Intent for processing card payments. Validates cart items, applies coupons, and creates a Stripe customer if needed.

Authentication

Required. User must be authenticated via Clerk.

Request Body

cartItems
array
required
Array of items to purchase
cartItems[].product
object
required
Product object with _id field
cartItems[].quantity
number
required
Quantity to purchase
shippingAddress
object
required
Shipping address details
shippingAddress.fullName
string
required
Recipient’s full name
shippingAddress.streetAddress
string
required
Street address
shippingAddress.city
string
required
City
shippingAddress.phoneNumber
string
required
Contact phone number
couponCode
string
Optional coupon code for discount

Response

clientSecret
string
required
Stripe client secret for completing the payment on the frontend
paymentIntentId
string
required
Stripe Payment Intent ID

Example Request

curl -X POST https://api.donpalitojr.com/api/payment/create-intent \
  -H "Authorization: Bearer YOUR_AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "cartItems": [
      {
        "product": {"_id": "65f8a1b2c3d4e5f6g7h8i9j3"},
        "quantity": 2
      }
    ],
    "shippingAddress": {
      "fullName": "Juan Pérez",
      "streetAddress": "Calle 123 #45-67",
      "city": "Bogotá",
      "phoneNumber": "+57 300 123 4567"
    },
    "couponCode": "WELCOME10"
  }'

Example Response

{
  "clientSecret": "pi_3ABC123DEF456_secret_XYZ789",
  "paymentIntentId": "pi_3ABC123DEF456"
}

Error Responses

400 Bad Request
Cart is empty, shipping address missing, insufficient stock, invalid coupon, or amount below minimum
{
  "error": "Cart is empty"
}
{
  "error": "Insufficient stock for Empanada de Pollo"
}
{
  "error": "El cupón no es válido o ha expirado."
}
{
  "error": "The minimum amount to process payments is $2000 COP"
}
404 Not Found
Product not found
{
  "error": "Product Empanada de Pollo not found"
}

Stripe Webhook Handler

Webhook endpoint for Stripe to notify payment events. Handles payment_intent.succeeded events to create orders automatically.

Authentication

No authentication required. Validates Stripe signature instead.

Headers

stripe-signature
string
required
Stripe webhook signature for verification

Request Body

Stripe event object (raw body required for signature verification).

Response

{
  "received": true
}

Event Handling

When a payment_intent.succeeded event is received:
  1. Validates payment hasn’t already been processed
  2. Creates order with items from payment metadata
  3. Reduces product stock
  4. Marks coupon as used (if applicable)
  5. Sends order confirmation emails to customer and admin

Example Webhook Event

{
  "type": "payment_intent.succeeded",
  "data": {
    "object": {
      "id": "pi_3ABC123DEF456",
      "amount": 1700000,
      "currency": "cop",
      "metadata": {
        "userId": "65f8a1b2c3d4e5f6g7h8i9j1",
        "clerkId": "user_2abc123def456",
        "orderItems": "[{\"product\":\"65f8a1b2c3d4e5f6g7h8i9j3\",\"price\":3500,\"quantity\":2}]",
        "shippingAddress": "{\"fullName\":\"Juan Pérez\",\"streetAddress\":\"Calle 123\",\"city\":\"Bogotá\",\"phoneNumber\":\"+57 300 123 4567\"}",
        "totalPrice": "17000",
        "couponCode": "WELCOME10"
      }
    }
  }
}

Error Responses

400 Bad Request
Invalid webhook signature
{
  "error": "Webhook Error: Invalid signature"
}

Create Transfer Order

Create an order with bank transfer as the payment method. The order is created immediately with “pending” status.

Authentication

Required. User must be authenticated via Clerk.

Request Body

cartItems
array
required
Array of items to purchase
cartItems[].product
object
required
Product object with _id field
cartItems[].quantity
number
required
Quantity to purchase
shippingAddress
object
required
Shipping address details (same fields as payment intent)
couponCode
string
Optional coupon code for discount

Response

order
object
The created order object
order._id
string
Order unique identifier
order.orderItems
array
Array of ordered items
order.shippingAddress
object
Shipping address details
order.paymentResult
object
Payment info with id like “transfer_1234567890” and status: "pending"
order.totalPrice
number
Total order price (includes discount, no shipping cost)
order.status
string
Order status (always “pending” initially)

Example Request

curl -X POST https://api.donpalitojr.com/api/payment/create-transfer-order \
  -H "Authorization: Bearer YOUR_AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "cartItems": [
      {
        "product": {"_id": "65f8a1b2c3d4e5f6g7h8i9j3"},
        "quantity": 2
      }
    ],
    "shippingAddress": {
      "fullName": "Juan Pérez",
      "streetAddress": "Calle 123 #45-67",
      "city": "Bogotá",
      "phoneNumber": "+57 300 123 4567"
    },
    "couponCode": "SAVE15"
  }'

Example Response

{
  "order": {
    "_id": "65f8a1b2c3d4e5f6g7h8i9j0",
    "user": "65f8a1b2c3d4e5f6g7h8i9j1",
    "clerkId": "user_2abc123def456",
    "orderItems": [
      {
        "product": "65f8a1b2c3d4e5f6g7h8i9j3",
        "name": "Empanada de Pollo",
        "price": 3500,
        "quantity": 2
      }
    ],
    "shippingAddress": {
      "fullName": "Juan Pérez",
      "streetAddress": "Calle 123 #45-67",
      "city": "Bogotá",
      "phoneNumber": "+57 300 123 4567"
    },
    "paymentResult": {
      "id": "transfer_1710512400000",
      "status": "pending"
    },
    "totalPrice": 5950,
    "status": "pending",
    "createdAt": "2024-03-15T10:30:00.000Z"
  }
}

Error Responses

400 Bad Request
Cart is empty, shipping address missing, insufficient stock, or invalid/expired coupon
{
  "error": "Cart is empty"
}
{
  "error": "Stock insuficiente para Empanada de Pollo"
}
{
  "error": "Ya usaste este cupón anteriormente."
}
404 Not Found
Product not found
{
  "error": "Producto no encontrado"
}

Payment Flow

1

Create Payment Intent

Call /api/payment/create-intent to get a Stripe client secret
2

Complete Payment on Frontend

Use Stripe.js with the client secret to collect payment details
3

Stripe Processes Payment

Stripe charges the customer and sends webhook to /api/payment/webhook
4

Order Created Automatically

Webhook handler creates the order, reduces stock, and sends emails

Alternative: Bank Transfer Flow

1

Create Transfer Order

Call /api/payment/create-transfer-order to create order with pending status
2

Customer Transfers Payment

Customer makes bank transfer offline
3

Admin Confirms Payment

Admin updates order status to “paid” via admin endpoints

Build docs developers (and LLMs) love