Skip to main content

POST /api/orders

Create a new subscription order after payment has been processed. This endpoint validates all data server-side and creates both a customer record and order.
Important: This endpoint should only be called after successfully processing payment through Stripe or PayPal. The paymentReceiptId must be the payment intent ID or order ID from the payment provider.

Rate Limiting

  • Limit: 5 requests per IP
  • Window: 10 minutes
  • Purpose: Anti-spam protection

Security Features

  • Honeypot field detection (_hp) to catch bots
  • Server-side price validation to prevent tampering
  • Input sanitization on all fields
  • Plan and duration validation

Request Body

name
string
required
Customer’s full name (max 100 characters)Example: "Juan Pérez"
email
string
required
Customer’s email address (must be valid email format)Example: "[email protected]"
phone
string
required
Customer’s phone number (sanitized format)Example: "+1234567890"
planId
string
required
Plan identifier (max 50 characters)Must be one of: plan-1 (Basic), plan-2 (Standard), plan-3 (Premium)Example: "plan-2"
devices
number
required
Number of simultaneous devices (1-10 range, must match plan)
  • 1 for Basic plan
  • 2 for Standard plan
  • 3 for Premium plan
Example: 2
months
number
required
Subscription duration in months (1-12 range)Must be one of: 1, 2, 3, 6, or 12Example: 6
amount
number
required
Payment amount in USD (1-10000 range)Must exactly match the plan’s price for the selected duration (validated server-side within 0.01 tolerance)Example: 70
paymentMethod
string
required
Payment provider usedMust be either: "stripe" or "paypal"Example: "stripe"
paymentReceiptId
string
required
Payment receipt ID from payment provider (max 200 characters)
  • For Stripe: Payment Intent ID (e.g., pi_xxxxx)
  • For PayPal: Captured Order ID (e.g., 7XX12345XX123456X)
Example: "pi_3AbCdEfGhIjKlMnO"
_hp
string
default:""
Honeypot field (should be empty for legitimate requests)This hidden field catches bots - if filled, request is silently rejected with fake success response

Response

orderId
string
Unique identifier for the created order
expirationDate
string
ISO 8601 date string indicating when the subscription expiresCalculated as: current date + months from request

Example Request

curl -X POST https://your-domain.com/api/orders \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Juan Pérez",
    "email": "[email protected]",
    "phone": "+1234567890",
    "planId": "plan-2",
    "devices": 2,
    "months": 6,
    "amount": 70,
    "paymentMethod": "stripe",
    "paymentReceiptId": "pi_3AbCdEfGhIjKlMnO"
  }'

Example Response

201 Created
{
  "orderId": "65f8a9b2c3d4e5f6a7b8c9d0",
  "expirationDate": "2026-09-09T12:34:56.789Z"
}

Error Responses

Validation Rules

The endpoint performs extensive server-side validation:
FieldValidation
nameRequired, max 100 chars, sanitized string
emailRequired, valid email format
phoneRequired, sanitized phone format
planIdRequired, must exist in PLANS, max 50 chars
devicesRequired, 1-10 range, must match plan
monthsRequired, must be 1, 2, 3, 6, or 12
amountRequired, 1-10000 range, must match plan price
paymentMethodRequired, must be “stripe” or “paypal”
paymentReceiptIdRequired, max 200 chars

Implementation Details

The endpoint is implemented in /src/app/api/orders/route.ts:19 and uses the following architecture:
  • Use Case: CreateOrderUseCase (Clean Architecture)
  • Repositories: MongoCustomerRepository, MongoOrderRepository
  • Security: Rate limiting, honeypot detection, input sanitization
  • Validation: Server-side price and plan validation

Workflow Example

  1. User selects Standard plan (plan-2) for 6 months
  2. Client calculates price: $70
  3. Client creates Stripe payment intent via /api/stripe
  4. User completes payment, receives payment intent ID: pi_3AbCdEfGhIjKlMnO
  5. Client calls /api/orders with all details including paymentReceiptId
  6. Server validates everything and creates order
  7. Response includes orderId and expirationDate
  8. Client shows confirmation to user

Testing

When testing, ensure you:
  • Use valid plan IDs and correct pricing
  • Don’t exceed rate limits (5 per 10 minutes)
  • Provide real payment receipt IDs from test payment providers
  • Leave the _hp honeypot field empty

See Also

  • Stripe API - Create payment intents for Stripe payments
  • PayPal API - Create and capture PayPal orders
  • API Overview - General API information and authentication

Build docs developers (and LLMs) love