Skip to main content

Introduction

This section provides the official documentation for using Lovi’s API with WhatsApp via Postman. It includes detailed instructions on how to set up and test API requests for WhatsApp integration, ensuring smooth communication through the platform. Authentication is performed using tokens that enable basic authentication for the API services. For more details on how to authenticate, please refer to the Authentication page. The Lovi API supports WhatsApp notifications with multimedia content, dynamic placeholders, scheduled delivery, and conversation flow integration.

Key Features:

  • WhatsApp notifications with multimedia support
  • Dynamic content personalization with placeholders
  • Scheduled message delivery with timezone support
  • Conversation flow integration
  • Two data structure formats (nested and flat)

📣 Send WhatsApp Notification

To send a notification via the Lovi API, make a POST request to the endpoint with the necessary parameters and authentication.
Method: POST Format: JSON

Endpoint

Query Parameters

Example URLs:

Headers

Note: Authentication is handled via the access_key parameter in the URL, not through headers.

📋 Request Parameters

The API supports two data structure formats controlled by the unflatten parameter.

Required Parameters

Important: You must use either contact (for single recipient) OR contacts (for multiple recipients), but NOT both.

Optional Parameters


👥 Single vs Multiple Recipients

Using contact - Send to One Person

Use contact when you want to send a notification to one recipient. Structure:
  • contact is an object (not a list)
  • Required field: number
  • Optional fields: name, email, and any custom fields

Using contacts - Send to Multiple People (Bulk Sending)

Use contacts when you want to send the same notification to multiple recipients at once. Structure:
  • contacts is a list/array (not a single object)
  • Maximum: 100 contacts per request
  • Each contact in the list must have a number
  • Optional fields: name, email, and any custom fields
Important Restrictions:
  • ⚠️ Cannot use unflatten=true with contacts - Bulk sending only works with nested structure
  • ⚠️ Cannot use both contact and contacts in the same request - choose one
  • ⚠️ contacts list cannot be empty - must have at least 1 contact

🔄 Data Structure Formats

The API supports two formats based on the unflatten parameter:

Nested Structure (unflatten=false or omitted)

When unflatten=false or not specified, use nested objects:

Flat Structure (unflatten=true)

When unflatten=true, all nested objects must be flattened using dot notation:

When to Use Each Format

  • Nested Structure (unflatten=false): Recommended for better readability and when your system supports nested objects
  • Flat Structure (unflatten=true): Use when your system doesn’t support nested objects or requires flat data structure

🎨 Components & Multimedia

IMPORTANT: Components you can send dynamically are ONLY those returned by the template components endpoint. The structure varies depending on whether the template has variables or media.

Component Naming Rules

  • Header media: header_image, header_video, header_document (NO suffix number)
  • Body variables: body_text_0, body_text_1, body_text_2, etc. (with index number for each {"{1}"}, {"{2}"}, {"{3}"} placeholder)
  • Footer and Buttons: Are STATIC in the template definition and CANNOT be sent dynamically

How to Know Which Components to Send

  1. First, call the template components endpoint:
  2. The API returns only the components you need to provide:
  3. Send ONLY those components in your notification request

Component Types by Position

Header Components (Media Only)

IMPORTANT: Only ONE header component per template. Header text is STATIC in the template. Note: header_text is NOT a dynamic component. Header text is defined in the template and cannot be changed.

Body Components (Variables Only)

Body text with placeholders requires variables in order: {"{1}"}, {"{2}"}, {"{3}"}, etc. Example Template: “Hello {"{1}"}, your course {"{2}"} is ready”
  • body_text_0: Value for {"{1}"} (e.g., “Maria”)
  • body_text_1: Value for {"{2}"} (e.g., “JavaScript”)
⚠️ Footer is STATIC - defined in the template and cannot be modified per message.

Button Components

IMPORTANT: Most buttons are STATIC in the template. However, URL buttons with variables CAN be dynamic. Example Template Button: "url": "https://example.com/{"{1}"}"
  • The template defines the URL pattern with placeholder
  • You provide the value for {"{1}"} via buttons_url_0
Note: Quick reply buttons are always static and cannot be modified per message.

Component Examples

Example 1: Template with Image Header (Nested Structure)

Example 2: Template with Body Variables (Nested Structure)

Example 3: Template with Image and Variables (Flat Structure)


🧩 Template Variables (Body Text)

CRITICAL: Variables in WhatsApp templates use positional placeholders like {"{1}"}, {"{2}"}, {"{3}"}, NOT named variables like {"{name}"}.

How Template Variables Work

WhatsApp templates define variables as numbered placeholders in the template body text:
  • Template text: “Hello {"{1}"}, your course {"{2}"} is ready”
  • {"{1}"} maps to body_text_0
  • {"{2}"} maps to body_text_1

Variable Assignment

You provide the values for these numbered placeholders in the components_push object:
Result: “Hello María, your course JavaScript Advanced Course is ready”

Important Rules

  1. Positional order matters: body_text_0 = {"{1}"}, body_text_1 = {"{2}"}, etc.
  2. Direct values: Provide the actual value, not {"{variable}"} syntax
  3. All variables required: Must provide values for all {"{N}"} placeholders in the template
  4. No mixing: Cannot combine variables with static text in components_push

✅ Valid Examples

Template: “Hello {"{1}"}, your order {"{2}"} is ready”
You can also use contact fields directly:

❌ Invalid Examples

Variable Resolution

The system resolves {"{variable}"} references in components_push by searching:
  1. First in contact object
  2. Then in root-level parameters

⏰ Scheduling & Conversation Flows

Immediate Delivery (Default)

If datetime_sending is not specified, the message is sent immediately:

Scheduled Delivery

Use datetime_sending and timezone to schedule messages: Nested Structure:
Flat Structure:

Conversation Flow Integration

Use name_event to trigger specific conversation flows:

📋 Complete Examples

Example 1: Single Recipient with Body Variables

Sending to ONE person using contact Template: “Hello {"{1}"}, thank you for your interest in {"{2}"}!” Request:
Response:

Example 1B: Multiple Recipients (Bulk Sending)

Sending to MULTIPLE people using contacts Template: “Hello {"{1}"}, thank you for your interest in {"{2}"}!” Request:
Response:
If some contacts fail:

Example 2: Template with Image Header

Template components: ["header_image"] URL:
Nested Structure:
Note: Body, footer, and buttons are static in the template and cannot be modified.

Example 3: Template with PDF Document

Template components: ["header_document"] URL:
Flat Structure:

Example 4: Conversation Flow Trigger

Nested Structure:

📊 Response Codes

Successful Response (200 OK)

Immediate sending:
Scheduled sending:

Error Responses

400 Bad Request - Invalid Parameters

401 Unauthorized - Invalid Access Key

404 Not Found - Template Not Found

422 Unprocessable Entity - Business Logic Error

429 Too Many Requests - Rate Limit


🔧 Best Practices

Data Structure

  • Prefer nested structure (unflatten=false) for better readability
  • Use flat structure (unflatten=true) only when your system requires it
  • Validate structure before sending requests

Media Guidelines

  • Use HTTPS URLs for all media files
  • Optimize file sizes for faster delivery
  • Use public URLs without authentication requirements
  • Test media URLs before sending to ensure accessibility

Scheduling

  • Specify timezone when using datetime_sending
  • Validate future dates before scheduling
  • Consider business hours for better engagement
  • Test scheduling in development environment

Placeholders

  • Use meaningful variable names that match your data
  • Test variable substitution before production
  • Keep one variable per field to avoid errors
  • Provide fallback values in your application logic

Performance

  • Batch multiple notifications when possible
  • Cache template information to reduce API calls
  • Monitor rate limits and implement backoff strategies
  • Use connection pooling for better performance

🚨 Common Errors & Solutions

Contact/Contacts Validation Errors

Error: Missing Contact Information

Problem: Request doesn’t include contact or contacts
Solution: You must include either contact (for one person) OR contacts (for multiple people)

Error: Using Both Contact and Contacts

Problem: Request includes both contact and contacts at the same time
Solution: Choose only one - use contact for single recipient or contacts for multiple recipients

Error: Contact is a List Instead of Object

Problem: Sent contact as a list [...] instead of an object {...}
Solution: For single recipient, use contact as an object:

Error: Contacts is Not a List

Problem: Sent contacts as an object {...} instead of a list [...]
Solution: For multiple recipients, use contacts as a list:

Error: Empty Contacts List

Problem: Sent contacts as an empty list []
Solution: Include at least one contact in the list

Error: Too Many Contacts

Problem: Sent more than 100 contacts in the contacts list
Solution: Split your contacts into multiple requests of maximum 100 contacts each

Error: Unflatten with Contacts

Problem: Used unflatten=true with contacts (bulk sending)
Solution: Bulk sending with contacts only works with nested structure. Remove unflatten=true or use unflatten=false

Structure Mismatch

Problem: Mixing nested and flat structures Solution: Choose one format consistently based on unflatten parameter

Template Not Found

Problem: Using non-existent or non-approved template Solution: Verify template name and approval status using template management endpoints

Invalid Phone Format

Problem: Including ’+’ or spaces in phone number Solution: Use clean international format without symbols (e.g., 34666033135)

Component Naming Errors

Problem: Using incorrect component names like header_image_0 instead of header_image Solution: Always check template components first using the /notify/template/components endpoint

Variable Position Errors

Problem: Incorrect mapping between template placeholders and body_text components Solution: Remember {"{1}"} = body_text_0, {"{2}"} = body_text_1, etc.

Modifying Static Components

Problem: Trying to send footer, buttons, or header text dynamically Solution: These components are static in the template. Only send components returned by the template components endpoint

Scheduling Errors

Problem: Past dates or invalid timezone Solution: Use future dates in ISO 8601 format with valid IANA timezone codes

🔬 Template Examples

These examples demonstrate different types of template structures.

Example 1: Simple Text Only Template

Components returned by API: [] (empty - no dynamic components)
Note: No components_push needed since template has no dynamic components.

Example 2: Template with Body Variables

Template Body: “Hello {"{1}"}, your {"{2}"} is ready!” Components returned by API: ["body_text_0", "body_text_1"]
Result: “Hello John, your Premium Package is ready!”

Example 3: Template with Image Header

Components returned by API: ["header_image"]
Note: Body, footer, and buttons are static in the template.

Example 4: Template with Video Header

Components returned by API: ["header_video"]

Example 5: Template with PDF Document

Components returned by API: ["header_document"]

Example 6: Template with Header Text and Body Variable

Header: “Important Notice” (static text in template) Body: “Hello {"{1}"}, welcome to our platform!” Components returned by API: ["body_text_0"]
Result:
  • Header: “Important Notice”
  • Body: “Hello Michael, welcome to our platform!”

Example 7: Template with Dynamic URL Button

Body: Static text Buttons:
  • URL button with variable: "url": "https://example.com/{"{1}"}" (dynamic)
  • Quick reply button: “Contact Support” (static) Components returned by API: ["buttons_url_0"]
Result: The URL button will link to https://example.com/profile/12345 Note: The variable in buttons_url_0 can reference contact fields using {"{variable}"} syntax, and the system will resolve it before sending.