Complete REST API documentation for the food ordering backend with Stripe payment integration.
http://localhost:5000/api
Most endpoints require authentication using JWT tokens. Include the token in the Authorization header:
Authorization: Bearer <your_jwt_token>
POST /auth/register
Create a new user account.
Request Body:
{
"name": "John Doe",
"email": "john@example.com",
"password": "password123",
"phone": "+1-555-0200",
"address": {
"street": "123 Main St",
"city": "New York",
"state": "NY",
"zipCode": "10001",
"country": "USA"
}
}Response (201):
{
"success": true,
"message": "User registered successfully",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"id": "507f1f77bcf86cd799439011",
"name": "John Doe",
"email": "john@example.com",
"phone": "+1-555-0200",
"role": "customer"
}
}POST /auth/login
Request Body:
{
"email": "john@example.com",
"password": "password123"
}Response (200):
{
"success": true,
"message": "Login successful",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"id": "507f1f77bcf86cd799439011",
"name": "John Doe",
"email": "john@example.com",
"role": "customer"
}
}GET /auth/me
Requires authentication.
Response (200):
{
"success": true,
"user": {
"id": "507f1f77bcf86cd799439011",
"name": "John Doe",
"email": "john@example.com",
"role": "customer"
}
}PUT /auth/profile
Requires authentication.
Request Body:
{
"name": "John Updated",
"phone": "+1-555-9999",
"address": {
"street": "456 New St",
"city": "Los Angeles",
"state": "CA",
"zipCode": "90001"
}
}GET /menu
Query Parameters:
category- Filter by category (appetizer, main-course, dessert, beverage, special)isAvailable- Filter by availability (true/false)search- Search in name and description
Example:
GET /api/menu?category=main-course&isAvailable=true
Response (200):
{
"success": true,
"count": 10,
"data": [
{
"_id": "507f1f77bcf86cd799439011",
"name": "Grilled Salmon",
"description": "Fresh Atlantic salmon grilled to perfection",
"price": 24.99,
"category": "main-course",
"image": "https://example.com/salmon.jpg",
"isVegetarian": false,
"isVegan": false,
"isGlutenFree": true,
"isAvailable": true,
"preparationTime": 25,
"rating": {
"average": 4.5,
"count": 120
}
}
]
}GET /menu/:id
Response (200):
{
"success": true,
"data": {
"_id": "507f1f77bcf86cd799439011",
"name": "Grilled Salmon",
"description": "Fresh Atlantic salmon grilled to perfection",
"price": 24.99,
"category": "main-course",
"ingredients": ["Salmon", "Lemon", "Butter", "Herbs"],
"allergens": ["Fish", "Dairy"],
"isAvailable": true
}
}POST /menu
Requires admin authentication.
Request Body:
{
"name": "New Dish",
"description": "A delicious new dish",
"price": 19.99,
"category": "main-course",
"image": "https://example.com/dish.jpg",
"ingredients": ["Ingredient 1", "Ingredient 2"],
"allergens": ["Gluten"],
"isVegetarian": false,
"isVegan": false,
"isGlutenFree": false,
"preparationTime": 20
}PUT /menu/:id
Requires admin authentication.
DELETE /menu/:id
Requires admin authentication.
GET /orders
Requires authentication. Regular users see only their orders; admins see all.
Query Parameters:
status- Filter by order status
Response (200):
{
"success": true,
"count": 5,
"data": [
{
"_id": "507f1f77bcf86cd799439011",
"orderNumber": "ORD-12345678-001",
"user": {
"name": "John Doe",
"email": "john@example.com"
},
"items": [
{
"menuItem": "507f191e810c19729de860ea",
"name": "Grilled Salmon",
"price": 24.99,
"quantity": 2,
"subtotal": 49.98
}
],
"subtotal": 49.98,
"tax": 4.00,
"deliveryFee": 0,
"total": 53.98,
"status": "confirmed",
"paymentStatus": "completed",
"estimatedDeliveryTime": "2025-01-15T19:30:00.000Z",
"createdAt": "2025-01-15T18:45:00.000Z"
}
]
}GET /orders/:id
Requires authentication.
POST /orders
Requires authentication.
Request Body:
{
"items": [
{
"menuItem": "507f191e810c19729de860ea",
"quantity": 2
},
{
"menuItem": "507f191e810c19729de860eb",
"quantity": 1
}
],
"deliveryAddress": {
"street": "123 Main St",
"city": "New York",
"state": "NY",
"zipCode": "10001",
"country": "USA"
},
"customerName": "John Doe",
"customerEmail": "john@example.com",
"customerPhone": "+1-555-0200",
"specialInstructions": "Please ring doorbell"
}Response (201):
{
"success": true,
"message": "Order created successfully",
"data": {
"_id": "507f1f77bcf86cd799439011",
"orderNumber": "ORD-12345678-001",
"items": [...],
"subtotal": 49.98,
"tax": 4.00,
"deliveryFee": 0,
"total": 53.98,
"status": "pending",
"paymentStatus": "pending",
"estimatedDeliveryTime": "2025-01-15T19:30:00.000Z"
}
}PUT /orders/:id/status
Requires admin authentication.
Request Body:
{
"status": "preparing"
}Valid statuses: pending, confirmed, preparing, ready, out-for-delivery, delivered, cancelled
DELETE /orders/:id
Requires authentication. Only pending or confirmed orders can be cancelled.
POST /payments/create-payment-intent
Requires authentication.
Request Body:
{
"orderId": "507f1f77bcf86cd799439011"
}Response (200):
{
"success": true,
"clientSecret": "pi_3N6N9k2eZvKYlo2C1Qi9k8X3_secret_xyz",
"paymentIntentId": "pi_3N6N9k2eZvKYlo2C1Qi9k8X3",
"amount": 53.98
}Use the clientSecret with Stripe.js to complete the payment on the frontend.
POST /payments/webhook
Public endpoint for Stripe webhook events. Configure in your Stripe dashboard:
https://your-domain.com/api/payments/webhook
POST /payments/refund
Requires admin authentication.
Request Body:
{
"orderId": "507f1f77bcf86cd799439011"
}GET /payments/config
Public endpoint to get Stripe publishable key.
Response (200):
{
"success": true,
"publishableKey": "pk_test_51..."
}All endpoints return standardized error responses:
{
"success": false,
"message": "Error description",
"errors": [] // For validation errors
}Common Status Codes:
200- Success201- Created400- Bad Request (validation errors)401- Unauthorized (authentication required)403- Forbidden (insufficient permissions)404- Not Found500- Internal Server Error
pending → confirmed → preparing → ready → out-for-delivery → delivered
↓
cancelled
pending → processing → completed
↓
failed
↓
refunded
# Register
curl -X POST http://localhost:5000/api/auth/register \
-H "Content-Type: application/json" \
-d '{"name":"Test User","email":"test@example.com","password":"password123"}'
# Login
curl -X POST http://localhost:5000/api/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"test@example.com","password":"password123"}'curl http://localhost:5000/api/menucurl -X POST http://localhost:5000/api/orders \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-d '{"items":[{"menuItem":"MENU_ITEM_ID","quantity":2}],"deliveryAddress":{"street":"123 Main St","city":"NYC","zipCode":"10001"},"customerName":"Test User","customerEmail":"test@example.com","customerPhone":"555-0100"}'Currently no rate limiting is implemented. Consider adding rate limiting for production:
- Authentication endpoints: 5 requests per minute
- Payment endpoints: 10 requests per minute
- Other endpoints: 100 requests per minute
- Always use HTTPS in production
- Keep JWT_SECRET secure and random
- Validate all user inputs
- Use Stripe webhook signature verification
- Implement rate limiting
- Keep dependencies updated
- Use environment variables for secrets
- Enable MongoDB authentication
- Implement logging and monitoring
- Regular security audits