Wylto API Reference

Wylto API reference

Send WhatsApp messages and templates, manage contacts and run campaigns from your own systems, and get webhooks when messages arrive or bookings change.

Getting started

  1. In Wylto, open CRM → Settings → API Settings and copy your API token. Only the app owner can see it.
  2. Send it as a Bearer token: Authorization: Bearer <token>.
  3. Call the API at https://server.wylto.com. Requests and responses are JSON.

Webhooks

Errors

Failed requests return a 4xx or 5xx status with a JSON body that describes the problem.

WhatsApp

Send messages and templates, manage templates, download media and read your phone number details.

Send a message to a phone number

POST https://server.wylto.com/api/v1/wa/send

Request body

Field Type Required Description
to string The phone number to which the message is being sent.
clientMessageId string Unique identifier of the message in your system.
message object
message.type string: text, template, image, document, video, audio, buttons, list The type of the message.
message.text object Text message content. Required when type is 'text'.
message.text.message string yes The text content of the message.
message.image object Image message content. Required when type is 'image'.
message.image.url string yes The URL of the image.
message.image.mimeType string yes The MIME type of the image (e.g., image/jpeg, image/png).
message.image.message string Optional caption for the image.
message.document object Document message content. Required when type is 'document'.
message.document.url string yes The URL of the document.
message.document.filename string The filename of the document.
message.document.mimeType string yes The MIME type of the document.
message.document.message string Optional caption for the document.
message.video object Video message content. Required when type is 'video'.
message.video.url string yes The URL of the video.
message.video.mimeType string yes The MIME type of the video.
message.video.message string Optional caption for the video.
message.audio object Audio message content. Required when type is 'audio'.
message.audio.url string yes The URL of the audio file.
message.audio.mimeType string yes The MIME type of the audio.
message.buttons object Quick reply buttons message content. Required when type is 'buttons'. WhatsApp allows up to 3 quick reply buttons.
message.buttons.imageURL string Optional image URL shown as a header above the message.
message.buttons.heading string Optional text header shown above the message (ignored when imageURL is set).
message.buttons.message string yes The body text shown above the buttons.
message.buttons.footer string Optional footer text shown below the buttons.
message.buttons.buttons object[] yes Up to 3 quick reply buttons.
message.buttons.buttons.id string yes Stable identifier returned in the user's reply payload.
message.buttons.buttons.name string yes Label shown on the button (max 20 characters).
message.list object List message content. Required when type is 'list'. WhatsApp allows up to 10 list rows.
message.list.imageURL string Optional image URL shown as a header above the message.
message.list.heading string Optional text header shown above the message (ignored when imageURL is set).
message.list.message string yes The body text shown above the list.
message.list.footer string Optional footer text shown below the list.
message.list.buttonTitle string yes Label of the button that opens the list (max 20 characters).
message.list.listItems object[] yes Up to 10 selectable rows.
message.list.listItems.id string yes Stable identifier returned in the user's selection payload.
message.list.listItems.name string yes Row title shown to the user (max 24 characters).
message.list.listItems.description string Optional secondary line shown under the title (max 72 characters).
message.template object Template message content. Required when type is 'template'.
message.template.templateName string The name of the template.
message.template.language string The language of the template. Refer https://developers.facebook.com/docs/whatsapp/business-management-api/message-templates/supported-languages/ for the codes
message.template.header object
message.template.header.type string: text The type of the header.
message.template.header.text string The text content of the header.
message.template.body object[]
message.template.body.type string: text The type of the body item.
message.template.body.text string The text content of the body item.
message.template.buttons object[]
message.template.buttons.type string The type of the button.
message.template.buttons.payload string The payload of the button.
message.template.buttons.index integer The index of the button.

Example:

{
  "to": "+919876012345",
  "message": {
    "type": "text",
    "text": {
      "message": "Hi, this is a test message"
    }
  }
}

Responses

Resolve WhatsApp media id to download URL (or stream file)

GET https://server.wylto.com/api/v1/wa/media/:mediaId

Uses the app's default WhatsApp connection to call the Meta Graph API for the given media id (e.g. message.image.id). By default returns JSON with a short-lived url and mime_type. With query action=download, resolves and streams the file in one request (WhatsApp token used server-side). Alternatively use POST /api/v1/wa/media/download with the returned url.

Parameters

Name In Type Required Description
mediaId path string yes WhatsApp media object id from the Cloud API (e.g. message.image.id).
action query string: download If set to download, response body is the raw media bytes instead of JSON. Content-Type comes from Meta mime_type when present.
filename query string When action=download, optional filename for Content-Disposition attachment (sanitized to a base name).

Responses

{
  "url": "https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=...",
  "mime_type": "image/jpeg"
}

Download WhatsApp media from temporary URL

POST https://server.wylto.com/api/v1/wa/media/download

Fetches binary content from a short-lived url returned by GET /api/v1/wa/media/:mediaId, using the app's default WhatsApp connection Bearer token when calling Meta. Response body is the raw file. Only https URLs on allowed Meta hosts (lookaside.fbsbx.com and *.fbsbx.com) are permitted.

Request body

Field Type Required Description
url string (uri) yes Temporary download URL from the WhatsApp Cloud API media response (field url).
mime_type string Optional MIME type for the response Content-Type (e.g. from the media metadata response). Defaults to application/octet-stream.
filename string Optional filename for Content-Disposition attachment. Path segments are stripped to a base name.

Example:

{
  "url": "https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=...",
  "mime_type": "image/jpeg",
  "filename": "photo.jpg"
}

Responses

Send a message to a contact

POST https://server.wylto.com/api/v1/wa/send/:contactId

Parameters

Name In Type Required Description
contactId path string yes The ID of the contact to whom the message is being sent.

Request body

Field Type Required Description
message object
message.type string: text, template, image, document, video, audio, buttons, list The type of the message.
message.text object Text message content. Required when type is 'text'.
message.text.message string yes The text content of the message.
message.image object Image message content. Required when type is 'image'.
message.image.url string yes The URL of the image.
message.image.mimeType string yes The MIME type of the image (e.g., image/jpeg).
message.image.message string Optional caption for the image.
message.document object Document message content. Required when type is 'document'.
message.document.url string yes The URL of the document.
message.document.filename string The filename of the document.
message.document.mimeType string yes The MIME type of the document.
message.document.message string Optional caption for the document.
message.video object Video message content. Required when type is 'video'.
message.video.url string yes The URL of the video.
message.video.mimeType string yes The MIME type of the video.
message.video.message string Optional caption for the video.
message.audio object Audio message content. Required when type is 'audio'.
message.audio.url string yes The URL of the audio file.
message.audio.mimeType string yes The MIME type of the audio.
message.buttons object Quick reply buttons message content. Required when type is 'buttons'. WhatsApp allows up to 3 quick reply buttons.
message.buttons.imageURL string Optional image URL shown as a header above the message.
message.buttons.heading string Optional text header shown above the message (ignored when imageURL is set).
message.buttons.message string yes The body text shown above the buttons.
message.buttons.footer string Optional footer text shown below the buttons.
message.buttons.buttons object[] yes Up to 3 quick reply buttons.
message.buttons.buttons.id string yes Stable identifier returned in the user's reply payload.
message.buttons.buttons.name string yes Label shown on the button (max 20 characters).
message.list object List message content. Required when type is 'list'. WhatsApp allows up to 10 list rows.
message.list.imageURL string Optional image URL shown as a header above the message.
message.list.heading string Optional text header shown above the message (ignored when imageURL is set).
message.list.message string yes The body text shown above the list.
message.list.footer string Optional footer text shown below the list.
message.list.buttonTitle string yes Label of the button that opens the list (max 20 characters).
message.list.listItems object[] yes Up to 10 selectable rows.
message.list.listItems.id string yes Stable identifier returned in the user's selection payload.
message.list.listItems.name string yes Row title shown to the user (max 24 characters).
message.list.listItems.description string Optional secondary line shown under the title (max 72 characters).
message.template object
message.template.templateName string The name of the template.
message.template.header object
message.template.header.type string: text The type of the header.
message.template.header.text string The text content of the header.
message.template.body object[]
message.template.body.type string: text The type of the body item.
message.template.body.text string The text content of the body item.
message.template.buttons object[]
message.template.buttons.type string The type of the button.
message.template.buttons.payload string The payload of the button.
message.template.buttons.index integer The index of the button.

Example:

{
  "message": {
    "type": "template",
    "template": {
      "templateName": "example_template_name",
      "header": {
        "type": "text",
        "text": "Your header text here"
      },
      "body": [
        {
          "type": "text",
          "text": "Your body text here"
        }
      ],
      "buttons": [
        {
          "type": "your_button_type",
          "payload": "your_button_payload",
          "index": 0
        }
      ]
    }
  }
}

Responses

List WhatsApp templates

GET https://server.wylto.com/api/v1/wa/templates

Returns all WhatsApp message templates for the app's default connection.

Responses

Create a WhatsApp template

POST https://server.wylto.com/api/v1/wa/templates

Request body

Field Type Required Description
name string yes Template name (lowercase, underscores only).
language string yes Language code (e.g., en, en_US).
category string: MARKETING, UTILITY, AUTHENTICATION yes Template category.
components object[] yes Template components.
components.type string: HEADER, BODY, FOOTER, BUTTONS
components.format string: TEXT, IMAGE, VIDEO, DOCUMENT
components.text string
components.mediaUrl string For media HEADERs (IMAGE/VIDEO/DOCUMENT): a public URL to the media. The server uploads it to WhatsApp and generates the media handle automatically. Alternatively, supply a pre-uploaded handle via example.header_handle.
components.buttons object[]
components.buttons.type string: QUICK_REPLY, URL, PHONE_NUMBER
components.buttons.text string
components.buttons.url string
components.buttons.phone_number string

Example:

{
  "name": "welcome_message",
  "language": "en",
  "category": "MARKETING",
  "components": [
    {
      "type": "HEADER",
      "format": "TEXT",
      "text": "Welcome to {{1}}!"
    },
    {
      "type": "BODY",
      "text": "Hi {{1}}, thank you for joining us. We're excited to have you!"
    },
    {
      "type": "FOOTER",
      "text": "Reply STOP to unsubscribe"
    },
    {
      "type": "BUTTONS",
      "buttons": [
        {
          "type": "QUICK_REPLY",
          "text": "Learn More"
        }
      ]
    }
  ]
}

Responses

Update a WhatsApp template

PUT https://server.wylto.com/api/v1/wa/templates/:templateId

Replaces the template's components. Name, language and category can't be changed. Meta reviews the template again after an edit, and limits how often an approved template can be edited.

Parameters

Name In Type Required Description
templateId path string yes The WhatsApp template id (the id returned by Create or List templates).

Request body

Field Type Required Description
components object[] yes The full new list of components, same format as Create template. For media headers, pass the URL in mediaUrl.

Example:

{
  "components": [
    {
      "type": "BODY",
      "text": "Your order #{{1}} is confirmed. It will reach you by {{2}}.",
      "example": {
        "body_text": [
          [
            "1001",
            "Friday"
          ]
        ]
      }
    }
  ]
}

Responses

{
  "success": true
}

Delete a WhatsApp template

DELETE https://server.wylto.com/api/v1/wa/templates/:templateName

Deletes the template by name. This deletes every language of that template. A deleted name can't be reused for 30 days.

Parameters

Name In Type Required Description
templateName path string yes The template name, e.g. order_confirmation.

Responses

{
  "success": true
}

Get template quality score

GET https://server.wylto.com/api/v1/wa/templates/:templateId/quality

Parameters

Name In Type Required Description
templateId path string yes The ID of the template.

Responses

{
  "id": "123456789",
  "name": "welcome_message",
  "status": "APPROVED",
  "qualityScore": "GREEN"
}

Get phone number details

GET https://server.wylto.com/api/v1/wa/phone-number

Returns details about the WhatsApp phone number including quality rating and messaging limits.

Responses

{
  "verified_name": "My Business",
  "display_phone_number": "+1234567890",
  "quality_rating": "GREEN",
  "messaging_limit_tier": "TIER_10K",
  "platform_type": "CLOUD_API",
  "throughput": {
    "level": "STANDARD"
  },
  "code_verification_status": "VERIFIED",
  "last_onboarded_time": "2024-01-01T00:00:00Z",
  "id": "180876681785984"
}

Contact

Create, update and read contacts, including UTM and activities.

Get a contact by phone number

GET https://server.wylto.com/api/v1/contact

Fetches a single contact by phone number. The phone number is normalized before lookup: spaces and dashes are stripped, '+' is auto-prepended if missing, and the value must contain at least 10 digits.

Parameters

Name In Type Required Description
phoneNumber query string yes Phone number to look up the contact by. '+' is auto-prepended if missing; minimum 10 digits.

Responses

{
  "id": "contact_xyz789",
  "externalId": "crm-1029",
  "name": "jane doe",
  "phoneNumber": "+14155551234",
  "email": "jane@example.com",
  "message": "Met at trade show",
  "status": "status_abc123",
  "group": "group_sales",
  "source": "tradeshow",
  "eventAt": 1740009600000,
  "tags": [
    "tag_vip",
    "tag_newsletter"
  ],
  "createdAt": 1739923200000,
  "updatedAt": 1740013200000
}

Create a new contact

POST https://server.wylto.com/api/v1/contact

Creates a contact. Pass 'utm' to record which ad or campaign the lead came from. Returns 400 if the contact already exists; use PUT /contact to update it.

Request body

Field Type Required Description
externalId string The unique identifier of the contact in your system.
name string The name of the contact.
phoneNumber string The phone number of the contact in E.164 format (with leading '+'). For the update-by-phone endpoint, '+' is auto-prepended if missing and the value must contain at least 10 digits.
email string The email address of the contact.
message string Free-text note attached to the contact.
status string Status ID. Takes precedence over 'statusName' when both are provided.
statusName string Status name. Resolved to the status ID via a case-insensitive lookup against the app's configured statuses. Ignored when 'status' is provided. Returns 400 if the name does not exist.
group string Group ID. Takes precedence over 'groupName' when both are provided.
groupName string Group name. Resolved to the group ID via a case-insensitive lookup against the app's configured groups. Ignored when 'group' is provided. Returns 400 if the name does not exist.
source string Acquisition source for the contact (e.g. 'web', 'whatsapp', 'partner').
eventAt integer (int64) Unix timestamp in milliseconds tied to the contact's status (used when the status represents a scheduled event).
tags string[] List of tag IDs. Replaces the contact's tags. Takes precedence over 'tagNames' when both are provided.
tagNames string[] List of tag names. Each is resolved to a tag ID via a case-insensitive lookup against the app's configured tags. Ignored when 'tags' is provided. Returns 400 if any name does not exist.
utm object Where the lead came from (first touch). Saved when the contact is created. On update it is saved only if the contact has no UTM yet; it is never overwritten.
utm.source string utm_source, e.g. 'google', 'facebook'.
utm.medium string utm_medium, e.g. 'cpc', 'email'.
utm.campaign string utm_campaign.
utm.term string utm_term.
utm.content string utm_content.
utm.adGroup string Ad group name or ID.
utm.ad string Ad name or ID.
utm.keyword string Search keyword.
utm.gclid string Google Ads click ID.
utm.fbclid string Facebook click ID.

Example:

{
  "name": "Jane Doe",
  "phoneNumber": "+14155551234",
  "email": "jane@example.com",
  "source": "website",
  "utm": {
    "source": "google",
    "medium": "cpc",
    "campaign": "diwali_sale",
    "term": "running shoes",
    "content": "banner_a",
    "gclid": "Cj0KCQjw..."
  }
}

Responses

Update a contact by phone number

PUT https://server.wylto.com/api/v1/contact

Looks up a contact by phone number and applies the same partial update semantics as PUT /contact/{contactId}. The phone number is normalized: '+' is auto-prepended if missing and the value must contain at least 10 digits. The lookup value can be passed via the 'phoneNumber' query parameter or the 'phoneNumber' field in the request body. Empty fields are ignored — only fields you provide are updated. Pass createIfContactNotPresent=true to create the contact from the body when no contact matches (same as POST /contact).

Parameters

Name In Type Required Description
phoneNumber query string Phone number to look up the contact by. Falls back to the body's 'phoneNumber' field when omitted. '+' is auto-prepended if missing; minimum 10 digits.
createIfContactNotPresent query boolean When true and no contact matches the phone number, a new contact is created from the request body instead of returning 404.

Request body

Field Type Required Description
externalId string The unique identifier of the contact in your system.
name string The name of the contact.
phoneNumber string The phone number of the contact in E.164 format (with leading '+'). For the update-by-phone endpoint, '+' is auto-prepended if missing and the value must contain at least 10 digits.
email string The email address of the contact.
message string Free-text note attached to the contact.
status string Status ID. Takes precedence over 'statusName' when both are provided.
statusName string Status name. Resolved to the status ID via a case-insensitive lookup against the app's configured statuses. Ignored when 'status' is provided. Returns 400 if the name does not exist.
group string Group ID. Takes precedence over 'groupName' when both are provided.
groupName string Group name. Resolved to the group ID via a case-insensitive lookup against the app's configured groups. Ignored when 'group' is provided. Returns 400 if the name does not exist.
source string Acquisition source for the contact (e.g. 'web', 'whatsapp', 'partner').
eventAt integer (int64) Unix timestamp in milliseconds tied to the contact's status (used when the status represents a scheduled event).
tags string[] List of tag IDs. Replaces the contact's tags. Takes precedence over 'tagNames' when both are provided.
tagNames string[] List of tag names. Each is resolved to a tag ID via a case-insensitive lookup against the app's configured tags. Ignored when 'tags' is provided. Returns 400 if any name does not exist.
utm object Where the lead came from (first touch). Saved when the contact is created. On update it is saved only if the contact has no UTM yet; it is never overwritten.
utm.source string utm_source, e.g. 'google', 'facebook'.
utm.medium string utm_medium, e.g. 'cpc', 'email'.
utm.campaign string utm_campaign.
utm.term string utm_term.
utm.content string utm_content.
utm.adGroup string Ad group name or ID.
utm.ad string Ad name or ID.
utm.keyword string Search keyword.
utm.gclid string Google Ads click ID.
utm.fbclid string Facebook click ID.

Example:

{
  "statusName": "Qualified",
  "tagNames": [
    "VIP",
    "Newsletter"
  ]
}

Responses

{
  "id": "contact_xyz789",
  "externalId": "crm-1029",
  "name": "jane doe",
  "phoneNumber": "+14155551234",
  "email": "jane@example.com",
  "message": "Met at trade show",
  "status": "status_abc123",
  "group": "group_sales",
  "source": "tradeshow",
  "eventAt": 1740009600000,
  "tags": [
    "tag_vip",
    "tag_newsletter"
  ],
  "createdAt": 1739923200000,
  "updatedAt": 1740013200000
}

Get a contact by ID

GET https://server.wylto.com/api/v1/contact/:contactId

Fetches a single contact by its Wylto contact ID.

Parameters

Name In Type Required Description
contactId path string yes The ID of the contact to fetch.

Responses

{
  "id": "contact_xyz789",
  "externalId": "crm-1029",
  "name": "jane doe",
  "phoneNumber": "+14155551234",
  "email": "jane@example.com",
  "message": "Met at trade show",
  "status": "status_abc123",
  "group": "group_sales",
  "source": "tradeshow",
  "eventAt": 1740009600000,
  "tags": [
    "tag_vip",
    "tag_newsletter"
  ],
  "createdAt": 1739923200000,
  "updatedAt": 1740013200000
}

Update a contact

PUT https://server.wylto.com/api/v1/contact/:contactId

Partial update for an existing contact identified by ID. Only the fields you include are written; empty strings and empty arrays are ignored. Use 'statusName' / 'groupName' / 'tagNames' to look up IDs by name (case-insensitive); the ID-form fields ('status' / 'group' / 'tags') take precedence when both are provided.

Parameters

Name In Type Required Description
contactId path string yes The ID of the contact to update.

Request body

Field Type Required Description
externalId string The unique identifier of the contact in your system.
name string The name of the contact.
phoneNumber string The phone number of the contact in E.164 format (with leading '+'). For the update-by-phone endpoint, '+' is auto-prepended if missing and the value must contain at least 10 digits.
email string The email address of the contact.
message string Free-text note attached to the contact.
status string Status ID. Takes precedence over 'statusName' when both are provided.
statusName string Status name. Resolved to the status ID via a case-insensitive lookup against the app's configured statuses. Ignored when 'status' is provided. Returns 400 if the name does not exist.
group string Group ID. Takes precedence over 'groupName' when both are provided.
groupName string Group name. Resolved to the group ID via a case-insensitive lookup against the app's configured groups. Ignored when 'group' is provided. Returns 400 if the name does not exist.
source string Acquisition source for the contact (e.g. 'web', 'whatsapp', 'partner').
eventAt integer (int64) Unix timestamp in milliseconds tied to the contact's status (used when the status represents a scheduled event).
tags string[] List of tag IDs. Replaces the contact's tags. Takes precedence over 'tagNames' when both are provided.
tagNames string[] List of tag names. Each is resolved to a tag ID via a case-insensitive lookup against the app's configured tags. Ignored when 'tags' is provided. Returns 400 if any name does not exist.
utm object Where the lead came from (first touch). Saved when the contact is created. On update it is saved only if the contact has no UTM yet; it is never overwritten.
utm.source string utm_source, e.g. 'google', 'facebook'.
utm.medium string utm_medium, e.g. 'cpc', 'email'.
utm.campaign string utm_campaign.
utm.term string utm_term.
utm.content string utm_content.
utm.adGroup string Ad group name or ID.
utm.ad string Ad name or ID.
utm.keyword string Search keyword.
utm.gclid string Google Ads click ID.
utm.fbclid string Facebook click ID.

Example:

{
  "statusName": "Qualified",
  "tagNames": [
    "VIP",
    "Newsletter"
  ]
}

Responses

{
  "id": "contact_xyz789",
  "externalId": "crm-1029",
  "name": "jane doe",
  "phoneNumber": "+14155551234",
  "email": "jane@example.com",
  "message": "Met at trade show",
  "status": "status_abc123",
  "group": "group_sales",
  "source": "tradeshow",
  "eventAt": 1740009600000,
  "tags": [
    "tag_vip",
    "tag_newsletter"
  ],
  "createdAt": 1739923200000,
  "updatedAt": 1740013200000
}

Delete a contact

DELETE https://server.wylto.com/api/v1/contact/:contactId

Parameters

Name In Type Required Description
contactId path string yes The ID of the contact to delete.

Responses

Get activities for a contact

GET https://server.wylto.com/api/v1/contact/:contactId/activities

Returns a contact's activity history (status changes, notes, call logs, chats, broadcasts and more), newest first.

Parameters

Name In Type Required Description
contactId path string yes The ID of the contact.
limit query integer Maximum number of activities to return. Default 50, max 200.

Responses

{
  "activities": [
    {
      "id": "act_123",
      "contactId": "contact_xyz789",
      "type": "STATUS_UPDATE",
      "from": "status_new",
      "to": "status_won",
      "author": "member_abc",
      "createdAt": 1740013200000
    },
    {
      "id": "act_122",
      "contactId": "contact_xyz789",
      "type": "NOTE",
      "note": "Asked for a demo next week",
      "author": "member_abc",
      "createdAt": 1740009600000
    }
  ]
}

Campaigns

Create WhatsApp broadcast campaigns and read their reports.

Create and send a campaign

POST https://server.wylto.com/api/v1/campaigns

Creates a campaign and sends messages to the provided contacts. Only CSV type campaigns are supported via API.

Request body

Field Type Required Description
campaignName string yes The name of the campaign.
contacts object[] yes List of contacts to send the campaign to.
contacts.name string The name of the contact.
contacts.phoneNumber string The phone number of the contact.
message object yes The message to send.
message.type string: template The type of message.
message.template object
message.template.templateName string The name of the template.
message.template.language string The language code of the template.
message.template.header object Header value, needed when the template has a variable or media header. For an image header use type "image" with a public image link.
message.template.header.type string: text, image
message.template.header.text string Header text. Used when type is "text".
message.template.header.image object Used when type is "image".
message.template.body object[]
message.template.body.type string
message.template.body.text string

Example:

{
  "campaignName": "January Promo",
  "contacts": [
    {
      "name": "John Doe",
      "phoneNumber": "+1234567890"
    },
    {
      "name": "Jane Smith",
      "phoneNumber": "+0987654321"
    }
  ],
  "message": {
    "type": "template",
    "template": {
      "templateName": "promo_offer",
      "language": "en",
      "body": [
        {
          "type": "text",
          "text": "20%"
        }
      ]
    }
  }
}

Responses

Get campaign report

GET https://server.wylto.com/api/v1/campaigns/:campaignId/report

Returns campaign details and all message delivery statuses.

Parameters

Name In Type Required Description
campaignId path string yes The ID of the campaign.

Responses

{
  "campaign": {
    "id": "abc123",
    "name": "January Promo",
    "type": "csv",
    "status": "completed",
    "channel": "whatsapp",
    "count": 100,
    "sent": 95,
    "delivered": 90,
    "read": 50,
    "failed": 5,
    "createdAt": 1704067200000
  },
  "messages": [
    {
      "id": "msg123",
      "name": "John Doe",
      "phoneNumber": "+1234567890",
      "state": "delivered",
      "buttonClicks": [],
      "createdAt": 1704067200000
    },
    {
      "id": "msg124",
      "name": "Jane Smith",
      "phoneNumber": "+0987654321",
      "state": "failed",
      "error": "131026- Message undeliverable",
      "buttonClicks": [],
      "createdAt": 1704067200000
    }
  ]
}

Webhooks

Messages Wylto posts to your server when a WhatsApp message arrives.

on new Message

Webhook: Wylto sends POST to your URL.

Payload

When you subscribe for a message webhook,Wylto sends this payload when a new message is received.

Field Type Required Description
contactId string Unique identifier of the contact in wylto.
clientContactId string Unique identifier of the contact in your system.
conversationId string Unique identifier of the conversation in wylto.
clientMessageId string Unique identifier of the message in your system. You need to provide this as part of the request when sending a message.
message object
message.context object
message.context.from string
message.context.id string
message.from string
message.id string
message.timestamp string (date-time)
message.type enum: text, button, document, location, image, video, audio, order, interactive
message.text object
message.text.body string
message.button object
message.button.payload string
message.button.text string
message.document object
message.document.caption string
message.document.fileName string
message.document.mimeType string
message.document.sha256 string
message.document.id string
message.location object
message.location.latitude number (double)
message.location.longitude number (double)
message.location.name string
message.location.address string
message.image object
message.image.caption string
message.image.mimeType string
message.image.sha256 string
message.image.id string
message.video object
message.video.caption string
message.video.mimeType string
message.video.sha256 string
message.video.id string
message.audio object
message.audio.caption string
message.audio.mimeType string
message.audio.sha256 string
message.audio.id string
message.audio.voice boolean
message.order object
message.order.catalogId string
message.order.productItems object[]
message.order.productItems.productRetailerId string
message.order.productItems.itemPrice integer
message.order.productItems.currency string
message.order.productItems.quantity integer
message.errors object[]
message.errors.code string
message.errors.message string
message.interactive object
message.interactive.type string
message.interactive.listReply object
message.interactive.listReply.id string
message.interactive.listReply.title string
message.interactive.listReply.description string
message.interactive.buttonReply object
message.interactive.buttonReply.id string
message.interactive.buttonReply.title string
message.interactive.nfmReply object
message.interactive.nfmReply.name string
message.interactive.nfmReply.body string
message.interactive.nfmReply.responseJSON string

Responses

Booking webhooks

Messages Wylto posts to your server when a booking is created, rescheduled, cancelled or completed.

Booking created

Webhook: Wylto sends POST to your URL.

Sent when someone books a slot: from a booking page, an embed, the chatbot or the AI agent.

Set up under Appointments → Settings → Webhooks in Wylto: add an HTTPS URL, optional custom headers and an optional signing secret, pick the events, and choose all booking pages or some. Wylto sends a JSON POST. Reply with any 2xx status within 10 seconds; failed deliveries are not retried and show in the deliveries log.

Headers

Name In Type Required Description
X-Wylto-Event header string yes Same as triggerEvent.
X-Wylto-Delivery header string yes Unique id of this delivery. Use it to ignore duplicates.
X-Wylto-Signature-256 header string Only when the webhook has a secret: sha256=<hex>, the HMAC-SHA256 of the raw request body with your secret. Compute it yourself and compare before trusting the request.
User-Agent header string

Payload

Field Type Required Description
triggerEvent string: BOOKING_CREATED, BOOKING_RESCHEDULED, BOOKING_CANCELLED, BOOKING_COMPLETED, PING yes
createdAt string (date-time) yes When the webhook was sent, UTC.
payload object yes
payload.bookingId string yes Booking id in Wylto.
payload.eventTypeId string Booking page id.
payload.eventTypeName string Booking page name, e.g. Product demo.
payload.status string: scheduled, rescheduled, cancelled, completed yes
payload.startTime string (date-time) yes Start, UTC (RFC 3339).
payload.endTime string (date-time) yes End, UTC (RFC 3339).
payload.previousStartTime string (date-time) Only on BOOKING_RESCHEDULED: the start before the change.
payload.duration integer yes Minutes.
payload.timeZone string Booker's timezone, e.g. Asia/Kolkata.
payload.location string: video, call, inPerson video (Google Meet or a video link), call (phone call) or inPerson.
payload.meetingLink string (uri)
payload.contact object The person who booked.
payload.contact.id string Wylto id.
payload.contact.name string
payload.contact.email string (email)
payload.contact.phone string With country code, digits only, e.g. 919800000000.
payload.assignedTo object Team member who takes the meeting.
payload.assignedTo.id string Wylto id.
payload.assignedTo.name string
payload.assignedTo.email string (email)
payload.assignedTo.phone string With country code, digits only, e.g. 919800000000.
payload.responses object Booking form answers, keyed by field id.
payload.minutesOfMeeting string Only on BOOKING_COMPLETED, when notes were added.
payload.source string How it was booked, e.g. event-booking (booking page).
payload.utm object UTM tags of the page the booking was made from (the embedding page for booking.js embeds, else the booking link). Only when it had any.
payload.utm.source string utm_source, e.g. 'google', 'facebook'.
payload.utm.medium string utm_medium, e.g. 'cpc', 'email'.
payload.utm.campaign string utm_campaign.
payload.utm.term string utm_term.
payload.utm.content string utm_content.
payload.utm.adGroup string Ad group name or ID.
payload.utm.ad string Ad name or ID.
payload.utm.keyword string Search keyword.
payload.utm.gclid string Google Ads click ID.
payload.utm.fbclid string Facebook click ID.
payload.rescheduleUrl string (uri) Link the booker uses to reschedule.
payload.cancelUrl string (uri) Link the booker uses to cancel.

Example:

{
  "triggerEvent": "BOOKING_CREATED",
  "createdAt": "2026-11-20T10:02:11Z",
  "payload": {
    "bookingId": "HRXLZixYtwudTxclPcbE",
    "eventTypeId": "yJ08Ls8T4CuOk2ZNhFFc",
    "eventTypeName": "Product demo",
    "status": "scheduled",
    "startTime": "2026-11-24T05:30:00Z",
    "endTime": "2026-11-24T06:00:00Z",
    "duration": 30,
    "timeZone": "Asia/Kolkata",
    "location": "video",
    "meetingLink": "https://meet.google.com/abc-defg-hij",
    "contact": {
      "id": "k2VdN8pQ1xYz",
      "name": "Asha",
      "email": "asha@example.com",
      "phone": "919800000000"
    },
    "assignedTo": {
      "id": "u7Ty3Lm9",
      "name": "Priya",
      "email": "priya@yourcompany.com"
    },
    "responses": {
      "name": "Asha",
      "email": "asha@example.com",
      "phone": "919800000000",
      "notes": "Interested in the Growth plan"
    },
    "source": "event-booking",
    "utm": {
      "source": "facebook",
      "medium": "paid_social",
      "campaign": "diwali_sale"
    },
    "rescheduleUrl": "https://app.wylto.com/booking-manage?…",
    "cancelUrl": "https://app.wylto.com/booking-manage?…"
  }
}

Responses

Booking rescheduled

Webhook: Wylto sends POST to your URL.

Sent when the booker or your team moves a booking. previousStartTime has the old start.

Set up under Appointments → Settings → Webhooks in Wylto: add an HTTPS URL, optional custom headers and an optional signing secret, pick the events, and choose all booking pages or some. Wylto sends a JSON POST. Reply with any 2xx status within 10 seconds; failed deliveries are not retried and show in the deliveries log.

Headers

Name In Type Required Description
X-Wylto-Event header string yes Same as triggerEvent.
X-Wylto-Delivery header string yes Unique id of this delivery. Use it to ignore duplicates.
X-Wylto-Signature-256 header string Only when the webhook has a secret: sha256=<hex>, the HMAC-SHA256 of the raw request body with your secret. Compute it yourself and compare before trusting the request.
User-Agent header string

Payload

Field Type Required Description
triggerEvent string: BOOKING_CREATED, BOOKING_RESCHEDULED, BOOKING_CANCELLED, BOOKING_COMPLETED, PING yes
createdAt string (date-time) yes When the webhook was sent, UTC.
payload object yes
payload.bookingId string yes Booking id in Wylto.
payload.eventTypeId string Booking page id.
payload.eventTypeName string Booking page name, e.g. Product demo.
payload.status string: scheduled, rescheduled, cancelled, completed yes
payload.startTime string (date-time) yes Start, UTC (RFC 3339).
payload.endTime string (date-time) yes End, UTC (RFC 3339).
payload.previousStartTime string (date-time) Only on BOOKING_RESCHEDULED: the start before the change.
payload.duration integer yes Minutes.
payload.timeZone string Booker's timezone, e.g. Asia/Kolkata.
payload.location string: video, call, inPerson video (Google Meet or a video link), call (phone call) or inPerson.
payload.meetingLink string (uri)
payload.contact object The person who booked.
payload.contact.id string Wylto id.
payload.contact.name string
payload.contact.email string (email)
payload.contact.phone string With country code, digits only, e.g. 919800000000.
payload.assignedTo object Team member who takes the meeting.
payload.assignedTo.id string Wylto id.
payload.assignedTo.name string
payload.assignedTo.email string (email)
payload.assignedTo.phone string With country code, digits only, e.g. 919800000000.
payload.responses object Booking form answers, keyed by field id.
payload.minutesOfMeeting string Only on BOOKING_COMPLETED, when notes were added.
payload.source string How it was booked, e.g. event-booking (booking page).
payload.utm object UTM tags of the page the booking was made from (the embedding page for booking.js embeds, else the booking link). Only when it had any.
payload.utm.source string utm_source, e.g. 'google', 'facebook'.
payload.utm.medium string utm_medium, e.g. 'cpc', 'email'.
payload.utm.campaign string utm_campaign.
payload.utm.term string utm_term.
payload.utm.content string utm_content.
payload.utm.adGroup string Ad group name or ID.
payload.utm.ad string Ad name or ID.
payload.utm.keyword string Search keyword.
payload.utm.gclid string Google Ads click ID.
payload.utm.fbclid string Facebook click ID.
payload.rescheduleUrl string (uri) Link the booker uses to reschedule.
payload.cancelUrl string (uri) Link the booker uses to cancel.

Example:

{
  "triggerEvent": "BOOKING_RESCHEDULED",
  "createdAt": "2026-11-20T10:02:11Z",
  "payload": {
    "bookingId": "HRXLZixYtwudTxclPcbE",
    "eventTypeId": "yJ08Ls8T4CuOk2ZNhFFc",
    "eventTypeName": "Product demo",
    "status": "rescheduled",
    "startTime": "2026-11-25T09:00:00Z",
    "endTime": "2026-11-25T09:30:00Z",
    "duration": 30,
    "timeZone": "Asia/Kolkata",
    "location": "video",
    "meetingLink": "https://meet.google.com/abc-defg-hij",
    "contact": {
      "id": "k2VdN8pQ1xYz",
      "name": "Asha",
      "email": "asha@example.com",
      "phone": "919800000000"
    },
    "assignedTo": {
      "id": "u7Ty3Lm9",
      "name": "Priya",
      "email": "priya@yourcompany.com"
    },
    "responses": {
      "name": "Asha",
      "email": "asha@example.com",
      "phone": "919800000000",
      "notes": "Interested in the Growth plan"
    },
    "source": "event-booking",
    "utm": {
      "source": "facebook",
      "medium": "paid_social",
      "campaign": "diwali_sale"
    },
    "rescheduleUrl": "https://app.wylto.com/booking-manage?…",
    "cancelUrl": "https://app.wylto.com/booking-manage?…",
    "previousStartTime": "2026-11-24T05:30:00Z"
  }
}

Responses

Booking cancelled

Webhook: Wylto sends POST to your URL.

Sent when the booker or your team cancels a booking.

Set up under Appointments → Settings → Webhooks in Wylto: add an HTTPS URL, optional custom headers and an optional signing secret, pick the events, and choose all booking pages or some. Wylto sends a JSON POST. Reply with any 2xx status within 10 seconds; failed deliveries are not retried and show in the deliveries log.

Headers

Name In Type Required Description
X-Wylto-Event header string yes Same as triggerEvent.
X-Wylto-Delivery header string yes Unique id of this delivery. Use it to ignore duplicates.
X-Wylto-Signature-256 header string Only when the webhook has a secret: sha256=<hex>, the HMAC-SHA256 of the raw request body with your secret. Compute it yourself and compare before trusting the request.
User-Agent header string

Payload

Field Type Required Description
triggerEvent string: BOOKING_CREATED, BOOKING_RESCHEDULED, BOOKING_CANCELLED, BOOKING_COMPLETED, PING yes
createdAt string (date-time) yes When the webhook was sent, UTC.
payload object yes
payload.bookingId string yes Booking id in Wylto.
payload.eventTypeId string Booking page id.
payload.eventTypeName string Booking page name, e.g. Product demo.
payload.status string: scheduled, rescheduled, cancelled, completed yes
payload.startTime string (date-time) yes Start, UTC (RFC 3339).
payload.endTime string (date-time) yes End, UTC (RFC 3339).
payload.previousStartTime string (date-time) Only on BOOKING_RESCHEDULED: the start before the change.
payload.duration integer yes Minutes.
payload.timeZone string Booker's timezone, e.g. Asia/Kolkata.
payload.location string: video, call, inPerson video (Google Meet or a video link), call (phone call) or inPerson.
payload.meetingLink string (uri)
payload.contact object The person who booked.
payload.contact.id string Wylto id.
payload.contact.name string
payload.contact.email string (email)
payload.contact.phone string With country code, digits only, e.g. 919800000000.
payload.assignedTo object Team member who takes the meeting.
payload.assignedTo.id string Wylto id.
payload.assignedTo.name string
payload.assignedTo.email string (email)
payload.assignedTo.phone string With country code, digits only, e.g. 919800000000.
payload.responses object Booking form answers, keyed by field id.
payload.minutesOfMeeting string Only on BOOKING_COMPLETED, when notes were added.
payload.source string How it was booked, e.g. event-booking (booking page).
payload.utm object UTM tags of the page the booking was made from (the embedding page for booking.js embeds, else the booking link). Only when it had any.
payload.utm.source string utm_source, e.g. 'google', 'facebook'.
payload.utm.medium string utm_medium, e.g. 'cpc', 'email'.
payload.utm.campaign string utm_campaign.
payload.utm.term string utm_term.
payload.utm.content string utm_content.
payload.utm.adGroup string Ad group name or ID.
payload.utm.ad string Ad name or ID.
payload.utm.keyword string Search keyword.
payload.utm.gclid string Google Ads click ID.
payload.utm.fbclid string Facebook click ID.
payload.rescheduleUrl string (uri) Link the booker uses to reschedule.
payload.cancelUrl string (uri) Link the booker uses to cancel.

Example:

{
  "triggerEvent": "BOOKING_CANCELLED",
  "createdAt": "2026-11-20T10:02:11Z",
  "payload": {
    "bookingId": "HRXLZixYtwudTxclPcbE",
    "eventTypeId": "yJ08Ls8T4CuOk2ZNhFFc",
    "eventTypeName": "Product demo",
    "status": "cancelled",
    "startTime": "2026-11-24T05:30:00Z",
    "endTime": "2026-11-24T06:00:00Z",
    "duration": 30,
    "timeZone": "Asia/Kolkata",
    "location": "video",
    "meetingLink": "https://meet.google.com/abc-defg-hij",
    "contact": {
      "id": "k2VdN8pQ1xYz",
      "name": "Asha",
      "email": "asha@example.com",
      "phone": "919800000000"
    },
    "assignedTo": {
      "id": "u7Ty3Lm9",
      "name": "Priya",
      "email": "priya@yourcompany.com"
    },
    "responses": {
      "name": "Asha",
      "email": "asha@example.com",
      "phone": "919800000000",
      "notes": "Interested in the Growth plan"
    },
    "source": "event-booking",
    "utm": {
      "source": "facebook",
      "medium": "paid_social",
      "campaign": "diwali_sale"
    },
    "rescheduleUrl": "https://app.wylto.com/booking-manage?…",
    "cancelUrl": "https://app.wylto.com/booking-manage?…"
  }
}

Responses

Booking completed

Webhook: Wylto sends POST to your URL.

Sent when your team marks a booking as completed. minutesOfMeeting has the notes, if any.

Set up under Appointments → Settings → Webhooks in Wylto: add an HTTPS URL, optional custom headers and an optional signing secret, pick the events, and choose all booking pages or some. Wylto sends a JSON POST. Reply with any 2xx status within 10 seconds; failed deliveries are not retried and show in the deliveries log.

Headers

Name In Type Required Description
X-Wylto-Event header string yes Same as triggerEvent.
X-Wylto-Delivery header string yes Unique id of this delivery. Use it to ignore duplicates.
X-Wylto-Signature-256 header string Only when the webhook has a secret: sha256=<hex>, the HMAC-SHA256 of the raw request body with your secret. Compute it yourself and compare before trusting the request.
User-Agent header string

Payload

Field Type Required Description
triggerEvent string: BOOKING_CREATED, BOOKING_RESCHEDULED, BOOKING_CANCELLED, BOOKING_COMPLETED, PING yes
createdAt string (date-time) yes When the webhook was sent, UTC.
payload object yes
payload.bookingId string yes Booking id in Wylto.
payload.eventTypeId string Booking page id.
payload.eventTypeName string Booking page name, e.g. Product demo.
payload.status string: scheduled, rescheduled, cancelled, completed yes
payload.startTime string (date-time) yes Start, UTC (RFC 3339).
payload.endTime string (date-time) yes End, UTC (RFC 3339).
payload.previousStartTime string (date-time) Only on BOOKING_RESCHEDULED: the start before the change.
payload.duration integer yes Minutes.
payload.timeZone string Booker's timezone, e.g. Asia/Kolkata.
payload.location string: video, call, inPerson video (Google Meet or a video link), call (phone call) or inPerson.
payload.meetingLink string (uri)
payload.contact object The person who booked.
payload.contact.id string Wylto id.
payload.contact.name string
payload.contact.email string (email)
payload.contact.phone string With country code, digits only, e.g. 919800000000.
payload.assignedTo object Team member who takes the meeting.
payload.assignedTo.id string Wylto id.
payload.assignedTo.name string
payload.assignedTo.email string (email)
payload.assignedTo.phone string With country code, digits only, e.g. 919800000000.
payload.responses object Booking form answers, keyed by field id.
payload.minutesOfMeeting string Only on BOOKING_COMPLETED, when notes were added.
payload.source string How it was booked, e.g. event-booking (booking page).
payload.utm object UTM tags of the page the booking was made from (the embedding page for booking.js embeds, else the booking link). Only when it had any.
payload.utm.source string utm_source, e.g. 'google', 'facebook'.
payload.utm.medium string utm_medium, e.g. 'cpc', 'email'.
payload.utm.campaign string utm_campaign.
payload.utm.term string utm_term.
payload.utm.content string utm_content.
payload.utm.adGroup string Ad group name or ID.
payload.utm.ad string Ad name or ID.
payload.utm.keyword string Search keyword.
payload.utm.gclid string Google Ads click ID.
payload.utm.fbclid string Facebook click ID.
payload.rescheduleUrl string (uri) Link the booker uses to reschedule.
payload.cancelUrl string (uri) Link the booker uses to cancel.

Example:

{
  "triggerEvent": "BOOKING_COMPLETED",
  "createdAt": "2026-11-20T10:02:11Z",
  "payload": {
    "bookingId": "HRXLZixYtwudTxclPcbE",
    "eventTypeId": "yJ08Ls8T4CuOk2ZNhFFc",
    "eventTypeName": "Product demo",
    "status": "completed",
    "startTime": "2026-11-24T05:30:00Z",
    "endTime": "2026-11-24T06:00:00Z",
    "duration": 30,
    "timeZone": "Asia/Kolkata",
    "location": "video",
    "meetingLink": "https://meet.google.com/abc-defg-hij",
    "contact": {
      "id": "k2VdN8pQ1xYz",
      "name": "Asha",
      "email": "asha@example.com",
      "phone": "919800000000"
    },
    "assignedTo": {
      "id": "u7Ty3Lm9",
      "name": "Priya",
      "email": "priya@yourcompany.com"
    },
    "responses": {
      "name": "Asha",
      "email": "asha@example.com",
      "phone": "919800000000",
      "notes": "Interested in the Growth plan"
    },
    "source": "event-booking",
    "utm": {
      "source": "facebook",
      "medium": "paid_social",
      "campaign": "diwali_sale"
    },
    "rescheduleUrl": "https://app.wylto.com/booking-manage?…",
    "cancelUrl": "https://app.wylto.com/booking-manage?…",
    "minutesOfMeeting": "Wants the Growth plan. Send pricing by Friday."
  }
}

Responses

Test ping

Webhook: Wylto sends POST to your URL.

Sent when you press Send test on a webhook. Sample data only.

Set up under Appointments → Settings → Webhooks in Wylto: add an HTTPS URL, optional custom headers and an optional signing secret, pick the events, and choose all booking pages or some. Wylto sends a JSON POST. Reply with any 2xx status within 10 seconds; failed deliveries are not retried and show in the deliveries log.

Headers

Name In Type Required Description
X-Wylto-Event header string yes Same as triggerEvent.
X-Wylto-Delivery header string yes Unique id of this delivery. Use it to ignore duplicates.
X-Wylto-Signature-256 header string Only when the webhook has a secret: sha256=<hex>, the HMAC-SHA256 of the raw request body with your secret. Compute it yourself and compare before trusting the request.
User-Agent header string

Payload

Field Type Required Description
triggerEvent string: BOOKING_CREATED, BOOKING_RESCHEDULED, BOOKING_CANCELLED, BOOKING_COMPLETED, PING yes
createdAt string (date-time) yes When the webhook was sent, UTC.
payload object yes
payload.bookingId string yes Booking id in Wylto.
payload.eventTypeId string Booking page id.
payload.eventTypeName string Booking page name, e.g. Product demo.
payload.status string: scheduled, rescheduled, cancelled, completed yes
payload.startTime string (date-time) yes Start, UTC (RFC 3339).
payload.endTime string (date-time) yes End, UTC (RFC 3339).
payload.previousStartTime string (date-time) Only on BOOKING_RESCHEDULED: the start before the change.
payload.duration integer yes Minutes.
payload.timeZone string Booker's timezone, e.g. Asia/Kolkata.
payload.location string: video, call, inPerson video (Google Meet or a video link), call (phone call) or inPerson.
payload.meetingLink string (uri)
payload.contact object The person who booked.
payload.contact.id string Wylto id.
payload.contact.name string
payload.contact.email string (email)
payload.contact.phone string With country code, digits only, e.g. 919800000000.
payload.assignedTo object Team member who takes the meeting.
payload.assignedTo.id string Wylto id.
payload.assignedTo.name string
payload.assignedTo.email string (email)
payload.assignedTo.phone string With country code, digits only, e.g. 919800000000.
payload.responses object Booking form answers, keyed by field id.
payload.minutesOfMeeting string Only on BOOKING_COMPLETED, when notes were added.
payload.source string How it was booked, e.g. event-booking (booking page).
payload.utm object UTM tags of the page the booking was made from (the embedding page for booking.js embeds, else the booking link). Only when it had any.
payload.utm.source string utm_source, e.g. 'google', 'facebook'.
payload.utm.medium string utm_medium, e.g. 'cpc', 'email'.
payload.utm.campaign string utm_campaign.
payload.utm.term string utm_term.
payload.utm.content string utm_content.
payload.utm.adGroup string Ad group name or ID.
payload.utm.ad string Ad name or ID.
payload.utm.keyword string Search keyword.
payload.utm.gclid string Google Ads click ID.
payload.utm.fbclid string Facebook click ID.
payload.rescheduleUrl string (uri) Link the booker uses to reschedule.
payload.cancelUrl string (uri) Link the booker uses to cancel.

Example:

{
  "triggerEvent": "PING",
  "createdAt": "2026-11-20T10:02:11Z",
  "payload": {
    "bookingId": "test",
    "eventTypeName": "Test booking",
    "status": "scheduled",
    "startTime": "2026-11-24T05:30:00Z",
    "endTime": "2026-11-24T06:00:00Z",
    "duration": 30,
    "contact": {
      "name": "Test contact",
      "email": "test@example.com",
      "phone": "919999999999"
    },
    "utm": {
      "source": "facebook",
      "medium": "paid_social",
      "campaign": "test_campaign"
    }
  }
}

Responses