Skip to main content

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.
subdomain
string
required
The tenant’s subdomain identifier

Request Body

name
string
required
Customer name (max 120 characters)
location
string
Customer location or sector (max 120 characters)
items
array
required
Array of order items (minimum 1 item)
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
      }
    ]
  }'
{
  "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

WhatsApp Message Format

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.
subdomain
string
required
The tenant’s subdomain identifier

Request Body

customer_name
string
required
Customer name (max 120 characters)
modalidad
string
required
Service mode: sitio (dine-in), llevar (takeout), or delivery
items
array
required
Array of menu items (minimum 1 item)
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
      }
    ]
  }'
{
  "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

WhatsApp Message Format

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:
success
boolean
Always false for errors
error
string
Error code identifier

Common Error Codes

CodeHTTP StatusDescription
tenant_not_found404Subdomain does not exist
plan_requerido403SYNTIcat 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

Frontend Shopping Cart Integration

// 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:
  1. tenant.whatsapp_sales (dedicated sales number)
  2. tenant.phone (fallback to main phone)
  3. Empty string if neither exists (will create invalid WhatsApp link)
Always ensure tenants have a valid WhatsApp number configured to prevent broken links.

Number Formatting

Phone numbers are automatically cleaned:
  • Removes spaces, dashes, parentheses
  • Strips country code plus signs
  • Keeps only digits
Examples:
  • +58 (412) 123-4567584121234567
  • 0412-123456704121234567

Currency

All prices use REF (Venezuelan reference currency) by default. This is hardcoded in:
  • SYNTIcat: OrderService.php:62
  • SYNTIfood: WhatsApp message formatting

Date Format

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.

Build docs developers (and LLMs) love