message.comDevelopers

Campaigns Planned

Campaigns are proactive chat messages triggered by visitor behaviour. A campaign defines a trigger (URL match, time-on-page, exit intent, custom event), an audience filter, the message, and a schedule. When matched, the widget fires the message into the visitor's open chat.

This endpoint is on the roadmap. Surface and shape may change before launch. For early access, contact us; an alpha is running with a small group of customers.

Trigger kinds

KindConfigFires when
page-stayurlPattern, secondsOnPageVisitor on a matching URL for the given seconds.
exit-intenturlPatternMouse moves toward the close-tab area.
scroll-depthurlPattern, percentVisitor scrolls past a given percentage.
custom-eventeventNameYour site fires Message.track(eventName).
idlesecondsIdleNo interaction for the given seconds.

List campaigns

GET/api/v1/campaignsAuth: Bearer

Code samples

cURL
curl 'https://app.message.com/api/v1/campaigns' \
  -H 'Authorization: Bearer YOUR_WORKSPACE_JWT'
JavaScript
const res = await fetch('https://app.message.com/api/v1/campaigns', {
  headers: { Authorization: 'Bearer ' + token }
});
const { campaigns } = await res.json();
Python
import requests
r = requests.get(
    "https://app.message.com/api/v1/campaigns",
    headers={"Authorization": f"Bearer {token}"},
)
campaigns = r.json()["campaigns"]
Ruby
require "net/http"
require "json"
uri = URI("https://app.message.com/api/v1/campaigns")
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
  req = Net::HTTP::Get.new(uri)
  req["Authorization"] = "Bearer #{token}"
  http.request(req)
end
campaigns = JSON.parse(res.body)["campaigns"]
PHP
<?php
$ctx = stream_context_create([
  "http" => ["method" => "GET", "header" => "Authorization: Bearer $token"]
]);
$campaigns = json_decode(file_get_contents("https://app.message.com/api/v1/campaigns", false, $ctx), true)["campaigns"];

Get one campaign

GET/api/v1/campaigns/:idAuth: Bearer
200 OK
{
  "id": "uuid",
  "version": 1,
  "name": "Cart abandonment nudge",
  "status": "active",
  "trigger": {
    "kind": "page-stay",
    "urlPattern": "/cart",
    "secondsOnPage": 30
  },
  "audience": {
    "filters": { "isReturning": true, "tag": "in-cart" }
  },
  "message": {
    "body": "Need help checking out? I can grab a code if it helps."
  },
  "schedule": {
    "businessHoursOnly": true,
    "frequencyCap": "1-per-visitor-per-day"
  },
  "createdAt": "2026-05-13T15:30:00Z"
}

Create a campaign

POST/api/v1/campaignsAuth: Bearer
FieldTypeDescription
namerequiredstringInternal name. Used in reporting.
triggerrequiredobjectTrigger config; kind drives shape.
audienceoptionalobjectFilter on visitor attributes. Omit to target everyone.
messagerequiredobjectThe message to send when matched.
scheduleoptionalobjectBusiness-hours gating and per-visitor frequency caps.
Body
{
  "name": "Cart abandonment nudge",
  "trigger": {
    "kind": "page-stay",
    "urlPattern": "/cart",
    "secondsOnPage": 30
  },
  "audience": {
    "filters": { "isReturning": true }
  },
  "message": {
    "body": "Need help checking out?"
  }
}

Update a campaign

PATCH/api/v1/campaigns/:idAuth: Bearer

Requires expectedVersion. Edits to a running campaign take effect within ~30 seconds via the live widget config push.

Pause and resume

POST/api/v1/campaigns/:id/pauseAuth: Bearer
POST/api/v1/campaigns/:id/resumeAuth: Bearer

Toggle status between paused and active without losing config.

Campaign report

GET/api/v1/campaigns/:id/reportAuth: Bearer

Returns impressions, engagements, replies, and (if a goal is attached) conversions for the date range.

Errors

CodeWhen
400 invalid_triggerTrigger config invalid for its kind.
402 plan_limitWorkspace plan does not include campaigns or the cap is hit.
409 stale_versionOptimistic-lock mismatch.

Common pitfalls

  • No frequency cap. Without one, returning visitors see the same nudge on every visit. Default to 1-per-visitor-per-day.
  • Targeting "everyone". Wide audiences feel spammy. Lean on visitor attributes (returning, segment, intent) to keep the message relevant.
  • Confusing campaigns with AI engagements. Campaigns are rule-driven; AI engagements are model-driven.