message.comDevelopers

Goals Live

Goals turn chat into a measurable funnel. Define a URL pattern that means "converted" (checkout success, a thank-you page, a signup confirmation) and message.com matches it automatically against pages visitors view after a conversation, attributed by visitor and agent when possible.

CRUD (list, get, create, update, delete) is live. There is no manual conversion-attribution endpoint and no per-goal report endpoint yet: completions are recorded automatically, and cross-goal reporting lives on the Reports API.

How a goal matches

A goal has one condition: an operator and a value matched against the URL of a page the visitor loads (via the widget's page-view tracking). There is no event-based, tag-based, or revenue-triggered goal kind.

OperatorMatches when the URL...
containsContains value as a substring.
equalsIs exactly value.
starts-withStarts with value.
ends-withEnds with value.
regexMatches value as a regular expression.

Completions are deduplicated per visitor within a 24-hour window. An optional valueCents on the goal assigns a fixed value to every completion (e.g., a flat $49 per signup); there is no per-completion custom amount.

List goals

GET/api/v1/goalsAuth: Bearer

Code samples

cURL
curl 'https://app.message.com/api/v1/goals' \
  -H 'Authorization: Bearer YOUR_WORKSPACE_JWT'
JavaScript
const res = await fetch('https://app.message.com/api/v1/goals', {
  headers: { Authorization: 'Bearer ' + token }
});
const { goals } = await res.json();
Python
import requests
r = requests.get(
    "https://app.message.com/api/v1/goals",
    headers={"Authorization": f"Bearer {token}"},
)
goals = r.json()["goals"]
Ruby
require "net/http"
require "json"
uri = URI("https://app.message.com/api/v1/goals")
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
goals = JSON.parse(res.body)["goals"]
PHP
<?php
$ctx = stream_context_create([
  "http" => ["method" => "GET", "header" => "Authorization: Bearer $token"]
]);
$goals = json_decode(file_get_contents("https://app.message.com/api/v1/goals", false, $ctx), true)["goals"];

Get one goal

GET/api/v1/goals/:idAuth: Bearer
200 OK
{
  "id": "uuid",
  "name": "Checkout success",
  "condition": { "operator": "contains", "value": "/checkout/success" },
  "valueCents": null,
  "status": "active",
  "createdAt": "2026-05-13T15:30:00Z"
}

Create a goal

POST/api/v1/goalsAuth: Bearer
FieldTypeDescription
namerequiredstringDisplay name. Shown in reports.
conditionrequiredobjectURL match rule: { operator, value }. See operators above.
valueCentsoptionalintegerFixed value in cents assigned to every completion. Omit for an unvalued goal.
Body
{
  "name": "Checkout success",
  "condition": { "operator": "contains", "value": "/checkout/success" },
  "valueCents": 4900
}

Update / pause a goal

PATCH/api/v1/goals/:idAuth: Bearer

Partial update of name, condition, or valueCents. Set status to paused or archived to stop matching without deleting the goal.

Delete a goal

DELETE/api/v1/goals/:idAuth: Bearer

List completions

GET/api/v1/goals/:id/completionsAuth: Bearer

The per-completion list and totals for a date range (query params from / to, default last 7 days). This is the only way to see individual conversions for one goal; there is no separate "report" endpoint.

200 OK
{
  "completions": [
    {
      "id": "uuid",
      "url": "https://acme.com/checkout/success?order=4567",
      "valueCents": 4900,
      "completedAt": "2026-05-13T15:36:00Z",
      "visitorId": "uuid",
      "conversationId": "uuid",
      "attributedAgentId": "uuid",
      "attributedAgentName": "Alex Lee"
    }
  ],
  "total": 1,
  "totalValueCents": 4900
}

Cross-goal reporting

GET/api/v1/reports/conversions/goalsAuth: Bearer

For conversions across all goals (not scoped to one goal ID), see the Reports API.

Errors

CodeWhen
400 invalid_bodyPayload failed validation, including an unparseable regex condition.
404 not_foundGoal does not exist in this workspace.

Common pitfalls

  • Defining a goal on a vanity URL. The thank-you page must be unique to the conversion. If /checkout/success is also reachable from a marketing campaign, your goal over-counts.
  • Expecting event-based or tag-based goals. There is only one condition shape: a URL operator/value pair. Build your conversion flow around a distinct URL.
  • Looking for a manual attribution endpoint. There isn't one. Completions are recorded automatically from the visitor's browsing after a conversation, deduplicated per visitor per 24 hours.