Overview
SYNTIweb provides two checkout endpoints for creating orders with automatic WhatsApp integration:
SYNTIcat : Product catalog checkout with SC-XXXX order codes
SYNTIfood : Restaurant comanda system with SF-XXXX order codes
Both endpoints generate unique order IDs, persist order data to JSON storage, and return WhatsApp deep links for instant customer communication.
SYNTIcat Checkout
Create a product order for SYNTIcat tenants.
Plan Requirement : Only tenants with the cat-anual plan can use this endpoint. Requests from tenants without this plan will return a 403 error.
The tenant’s subdomain identifier
Request Body
Customer name (max 120 characters)
Customer location or sector (max 120 characters)
Array of order items (minimum 1 item) Product name (max 200 characters)
Product variant or option (max 100 characters)
curl -X POST https://yourdomain.com/{subdomain}/checkout \
-H "Content-Type: application/json" \
-d '{
"name": "Juan Pérez",
"location": "Centro",
"items": [
{
"title": "Camisa Premium",
"qty": 2,
"price": 45.50,
"variant": "Talla M"
},
{
"title": "Pantalón Casual",
"qty": 1,
"price": 68.00
}
]
}'
200 Success
403 Plan Required
404 Tenant Not Found
422 Validation Error
{
"success" : true ,
"order_id" : "SC-A3X9K2" ,
"whatsapp_url" : "https://wa.me/584121234567?text=%F0%9F%9B%8D%20Pedido%20SC-A3X9K2%0A%0A%E2%80%A2%20Camisa%20Premium%20(Talla%20M)%20x2%20%E2%80%94%20REF%2091%2C00%0A%E2%80%A2%20Pantal%C3%B3n%20Casual%20x1%20%E2%80%94%20REF%2068%2C00%0A%0ASubtotal%3A%20REF%20159%2C00%0A%0ANombre%3A%20Juan%20P%C3%A9rez%0ASector%3A%20Centro"
}
Order ID Generation
Order IDs follow the format SC-XXXXXX:
Prefix : SC- (SYNTIcat)
Code : 6-character alphanumeric string (uppercase A-Z, 0-9)
Uniqueness : Verified against existing orders in storage/app/tenants/{tenant_id}/orders/{year}/{month}/
Examples: SC-A3X9K2, SC-7BQ4M1, SC-P9ZK3R
The WhatsApp URL contains a pre-formatted message:
🛍 Pedido SC-A3X9K2
• Camisa Premium (Talla M) x2 — REF 91,00
• Pantalón Casual x1 — REF 68,00
Subtotal: REF 159,00
Nombre: Juan Pérez
Sector: Centro
The message is URL-encoded and sent to the tenant’s configured WhatsApp number (whatsapp_sales or fallback to phone).
Order Storage
Orders are persisted as JSON files:
Path : storage/app/tenants/{tenant_id}/orders/{year}/{month}/SC-XXXXXX.json
Structure :
{
"id" : "SC-A3X9K2" ,
"tenant_id" : 123 ,
"date" : "2026-03-08T15:30:45+00:00" ,
"customer" : {
"name" : "Juan Pérez" ,
"location" : "Centro"
},
"items" : [
{
"title" : "Camisa Premium" ,
"qty" : 2 ,
"price" : 45.50 ,
"variant" : "Talla M"
},
{
"title" : "Pantalón Casual" ,
"qty" : 1 ,
"price" : 68.00 ,
"variant" : null
}
],
"subtotal" : 159.00 ,
"currency" : "REF" ,
"channel" : "whatsapp"
}
SYNTIfood Checkout
Create a restaurant comanda for SYNTIfood tenants.
Plan Persistence : Comandas are permanently stored only for tenants with food-anual plan or plan_id >= 3. Other plans generate temporary comandas that are immediately deleted after returning the response.
The tenant’s subdomain identifier
Request Body
Customer name (max 120 characters)
Service mode: sitio (dine-in), llevar (takeout), or delivery
Array of menu items (minimum 1 item) Dish or product name (max 200 characters)
curl -X POST https://yourdomain.com/{subdomain}/food-checkout \
-H "Content-Type: application/json" \
-d '{
"customer_name": "María González",
"modalidad": "delivery",
"items": [
{
"nombre": "Pizza Margarita",
"qty": 2,
"precio": 12.50
},
{
"nombre": "Refresco 1L",
"qty": 1,
"precio": 3.00
}
]
}'
200 Success
404 Tenant Not Found
422 Validation Error
{
"success" : true ,
"comanda_id" : "SF-B7Y2N4" ,
"whatsapp_url" : "https://wa.me/584121234567?text=%F0%9F%8D%BD%20Comanda%20SF-B7Y2N4%0A%0A%E2%80%A2%20Pizza%20Margarita%20x2%20%E2%80%94%20REF%2025%2C00%0A%E2%80%A2%20Refresco%201L%20x1%20%E2%80%94%20REF%203%2C00%0A%0ATotal%3A%20REF%2028%2C00%0A%0ANombre%3A%20Mar%C3%ADa%20Gonz%C3%A1lez%0AModalidad%3A%20Delivery"
}
Comanda ID Generation
Comanda IDs follow the format SF-XXXXXX:
Prefix : SF- (SYNTIfood)
Code : 6-character alphanumeric string (uppercase A-Z, 0-9)
Uniqueness : Verified against existing comandas in storage/app/tenants/{tenant_id}/comandas/{year}/{month}/
Examples: SF-B7Y2N4, SF-K3M9P1, SF-Q5X8L7
The WhatsApp URL contains a pre-formatted comanda message:
🍽 Comanda SF-B7Y2N4
• Pizza Margarita x2 — REF 25,00
• Refresco 1L x1 — REF 3,00
Total: REF 28,00
Nombre: María González
Modalidad: Delivery
Modalidad labels:
sitio → “Comer en sitio”
llevar → “Para llevar”
delivery → “Delivery”
Comanda Storage
Persistent Storage (food-anual plan or plan_id >= 3):
Path : storage/app/tenants/{tenant_id}/comandas/{year}/{month}/SF-XXXXXX.json
Structure :
{
"id" : "SF-B7Y2N4" ,
"tenant_id" : 456 ,
"date" : "2026-03-08T19:45:30+00:00" ,
"customer_name" : "María González" ,
"modalidad" : "delivery" ,
"items" : [
{
"nombre" : "Pizza Margarita" ,
"qty" : 2 ,
"precio" : 12.50
},
{
"nombre" : "Refresco 1L" ,
"qty" : 1 ,
"precio" : 3.00
}
],
"total" : 28.00 ,
"channel" : "whatsapp"
}
Temporary Storage (other plans): Comanda is generated and returned but the JSON file is immediately deleted after the response.
Error Handling
Both endpoints use consistent error responses:
Common Error Codes
Code HTTP Status Description tenant_not_found404 Subdomain does not exist plan_requerido403 SYNTIcat only - tenant lacks required plan
Validation Errors
Laravel validation errors return 422 status with detailed field-level errors:
{
"message" : "The name field is required. (and 2 more errors)" ,
"errors" : {
"name" : [ "The name field is required." ],
"items.0.title" : [ "The items.0.title field is required." ],
"items.0.qty" : [ "The items.0.qty must be at least 1." ]
}
}
Integration Examples
// SYNTIcat Product Cart
async function submitOrder ( cartItems , customerInfo ) {
const orderData = {
name: customerInfo . name ,
location: customerInfo . location ,
items: cartItems . map ( item => ({
title: item . name ,
qty: item . quantity ,
price: item . price ,
variant: item . selectedVariant
}))
};
try {
const response = await fetch ( `/ ${ subdomain } /checkout` , {
method: 'POST' ,
headers: { 'Content-Type' : 'application/json' },
body: JSON . stringify ( orderData )
});
const result = await response . json ();
if ( result . success ) {
// Redirect to WhatsApp
window . location . href = result . whatsapp_url ;
} else {
alert ( `Error: ${ result . error } ` );
}
} catch ( error ) {
console . error ( 'Checkout failed:' , error );
}
}
SYNTIfood Restaurant POS
// Food Comanda Submission
async function sendComanda ( customerName , modalidad , orderItems ) {
const comandaData = {
customer_name: customerName ,
modalidad: modalidad , // 'sitio', 'llevar', or 'delivery'
items: orderItems . map ( item => ({
nombre: item . dish ,
qty: item . quantity ,
precio: item . price
}))
};
const response = await fetch ( `/ ${ subdomain } /food-checkout` , {
method: 'POST' ,
headers: { 'Content-Type' : 'application/json' },
body: JSON . stringify ( comandaData )
});
const result = await response . json ();
if ( result . success ) {
// Open WhatsApp link
window . open ( result . whatsapp_url , '_blank' );
// Display comanda ID to staff
showNotification ( `Comanda ${ result . comanda_id } creada` );
}
}
Implementation Notes
WhatsApp Number Priority
Both endpoints use the following priority for WhatsApp number selection:
tenant.whatsapp_sales (dedicated sales number)
tenant.phone (fallback to main phone)
Empty string if neither exists (will create invalid WhatsApp link)
Always ensure tenants have a valid WhatsApp number configured to prevent broken links.
Phone numbers are automatically cleaned:
Removes spaces, dashes, parentheses
Strips country code plus signs
Keeps only digits
Examples:
+58 (412) 123-4567 → 584121234567
0412-1234567 → 04121234567
Currency
All prices use REF (Venezuelan reference currency) by default. This is hardcoded in:
SYNTIcat: OrderService.php:62
SYNTIfood: WhatsApp message formatting
Order and comanda dates use ISO 8601 format with timezone:
2026-03-08T15:30:45+00:00
This ensures consistent date parsing across different system locales.