POST /api/reservation
POST /api/reservation
Submit a product reservation request.
Request
Method
POST
Headers
| Header | Value |
|---|---|
| Content-Type | application/json |
Body
{
"name": "山田太郎",
"email": "user@example.com",
"productSlug": "oxi-one-mk2"
}
Parameters
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Customer’s name |
email | string | Yes | Customer’s email address |
productSlug | string | Yes | Product identifier (must exist in product data) |
Response
Success (200)
{
"success": true,
"reservationId": "res_550e8400-e29b-41d4-a716-446655440000"
}
The reservationId format is res_[uuid] using crypto.randomUUID() for guaranteed uniqueness.
Validation Error (400)
{
"success": false,
"error": "入力内容に問題があります",
"details": [
{ "field": "name", "message": "お名前を入力してください" },
{ "field": "email", "message": "有効なメールアドレスを入力してください" }
]
}
Product Not Found (400)
{
"success": false,
"error": "指定された商品が見つかりません"
}
Server Error (500)
{
"success": false,
"error": "サーバーエラーが発生しました"
}
Example
cURL
curl -X POST https://takazudomodular.com/api/reservation \
-H "Content-Type: application/json" \
-d '{
"name": "山田太郎",
"email": "user@example.com",
"productSlug": "oxi-one-mk2"
}'
JavaScript (fetch)
const response = await fetch('/api/reservation', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
name: '山田太郎',
email: 'user@example.com',
productSlug: 'oxi-one-mk2',
}),
});
const data = await response.json();
if (data.success) {
console.log('Reservation ID:', data.reservationId);
} else {
console.error('Reservation failed:', data.error);
}
Implementation Details
Source File
netlify/functions/reservation.ts
Behavior
- Validates name (non-empty, trimmed)
- Validates email format
- Validates productSlug format (lowercase alphanumeric with hyphens)
- Generates unique reservation ID (
res_prefix + UUID) - Normalizes email to lowercase
- Stores reservation in Netlify Blobs
- Sends notifications in parallel (non-blocking, failures don’t affect response):
- Slack (reservation channel): Full details (product, name, email, reservation ID, timestamp) for shop management
- Auto-reply email: Confirmation email to the user via Resend
- No Discord notification (reservation contains private customer info)
- Returns success response with reservation ID
Email Normalization
Emails are normalized to lowercase before storage. This means User@Example.com is stored as user@example.com.
Reservation ID Format
The reservationId is generated with a timestamp-based format for easy sorting:
res_{timestamp}-{random}
Example: res_1706889600000-a1b2c3
Duplicate Handling
Unlike notify-signup, multiple reservations from the same email are currently allowed. This is intentional as customers may want to reserve multiple units of the same product.
Admin Management
Reservations can be managed via the zpreorder admin interface:
- POST /api/admin-reservations-list - List and filter reservations
- POST /api/admin-reservations-status - Update reservation status
Related
- POST /api/notify-signup - Simple email notification signup
- Webhook Notifications - Slack and Discord integration details
- Email Service - Resend email configuration