Skip to content

Developer API

The LeadJourney REST API

Run reports, read lead journeys, manage tags, tracking domains, channels and client workspaces with a workspace token. Plus the Integrations API behind the Zapier app.

  • Workspace tokens (ljw_) with scopes
  • 60 requests/min per workspace
  • JSON envelope
  • 38 Public API endpoints

Getting started

Everything the Public API expects of a request

Where requests go, how they authenticate, what a token may do, how fast you may call and what comes back.

Every Public API path in the reference is relative to it. {workspace} is the workspace UUID and must be the token's own workspace, otherwise the API answers 403 forbidden.

https://api.leadjourney.io/api/v1/public/workspaces/{workspace}
  • The plaintext token is shown once, when it is created. Only its hash is stored, so it cannot be shown again: store it right away.
  • A workspace can have at most 5 active tokens. A sixth is refused with 422; nothing is rotated for you.
  • Expiry is at most 360 days ahead. A token created without an expiry date never expires.
  • Tokens are managed by a profile with the owner or agency role in the workspace, in the dashboard, over the API itself (POST /api-tokens, scope tokens), and one is issued automatically when an agency creates a client workspace.
  • A token can only be given scopes its issuer may grant, and its scope list is never widened afterwards.

Send the workspace token as a Bearer credential on every request. A token is ljw_ followed by 40 random characters, and it reaches exactly one workspace. These are not session tokens.

Authorization: Bearer ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
401 missing token
{"success": false, "error": "unauthenticated", "message": "Missing API token. Send it as: Authorization: Bearer ljw_..."}
401 unknown, revoked or expired
{"success": false, "error": "unauthenticated", "message": "Invalid, revoked or expired API token."}
403 another workspace
{"success": false, "error": "forbidden", "message": "This token is not valid for the requested workspace."}
403 missing scope
{"success": false, "error": "insufficient_scope", "message": "This token does not have the \"tags\" scope.", "required_scope": "tags", "granted_scopes": ["reports"]}

A token carries one or more scopes. Each covers reads and writes in its area; a call outside the token's scopes answers 403 insufficient_scope. Minting a token in the dashboard needs the permission in the last column.

ScopeLabelCoversPermission to issue
reportsReports & Dashboards/reports/*, /dashboards/*Report Builder
tagsTags/tags/*Tags
leadsLeads & Attribution (read)/leads/*, returns personal data (email, phone)Lead Overview
trackingTracking/tracking-domains/*, /tracking/*Tracking
traffic_channelsTraffic Channels/traffic-channels/*, /utm/*, /short-linksTraffic Channels
agency.workspacesCreate Client Workspaces/agency/workspacesNone, but the issuer must hold the agency role and the workspace must be the agency HQ
tokensManage API Tokens/api-tokens/*None
LimitRequestsWindow
Per workspace601 minute
Per token301 minute
Per IP, before authentication1201 minute
Agency client workspace creation130 minutes per agency HQ

Every bucket is checked before any is counted, so a request refused with 429 costs no budget. A successful answer carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Scope (workspace or token), taken from whichever bucket has the least headroom.

A 429 from the workspace or token bucket carries Retry-After, X-RateLimit-Limit, X-RateLimit-Remaining: 0 and X-RateLimit-Scope:

429
{"success": false, "error": "rate_limited", "message": "Rate limit exceeded for this workspace (60 requests per minute). Retry in 12 second(s).", "scope": "workspace", "retry_after": 12}

Success answers carry success: true, the payload usually under data; some endpoints add meta or other top-level keys. Errors carry success: false, a machine readable error code and a message.

Success
{"success": true, "data": { ... }}
Error
{"success": false, "error": "<code>", "message": "<text>"}

List endpoints take page (default 1, minimum 1) and per_page (default 20, maximum 50). A larger per_page is clamped to 50, not rejected; a value below 1 falls back to 20.

Paginated answer
{"success": true, "data": [...], "meta": {"current_page": 1, "per_page": 20, "last_page": 3, "total": 47, "max_per_page": 50}}

Every error answers with its HTTP status and the error envelope above. The codes shared across endpoints are unauthenticated (401), forbidden and insufficient_scope (403), not_found (404) and rate_limited (429); each endpoint card lists its own. Two answers differ from the envelope, and they are documented as they are:

  • Validation errors answer 422 in the standard shape, not the envelope: {"message": "...", "errors": {"field": ["..."]}}.
  • A plan limit on agency workspace creation answers 402 {"message": "...", "error": "plan_limit_reached", "limit": "...", "used": n, "allowed": n}, with no success key.
  • Destructive calls ask for confirm: true: deleting a tracking domain or a traffic channel without it answers 409 confirmation_required. Deleting a tracking domain breaks every link on that host.

Your first call: ask the workspace for its report vocabulary. Any token with the reports scope can make it.

Request
curl "https://api.leadjourney.io/api/v1/public/workspaces/YOUR_WORKSPACE_ID/reports/describe" \
  -H "Authorization: Bearer ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
200 OK
{
  "success": true,
  "data": {
    "metrics": [
      "<metric_id>",
      "..."
    ],
    "metric_windows": {
      "note": "Append a window as metric@window. At most 6 distinct windows per report.",
      "ids": [
        "last_7d",
        "last_14d",
        "last_30d",
        "last_60d",
        "last_90d"
      ]
    },
    "group_by": [
      "time",
      "day_of_week",
      "sources",
      "channel_category",
      "country",
      "campaign",
      "custom_field:<key>"
    ],
    "channel_category": [
      "<channel category>",
      "..."
    ],
    "secondary_group_by": [
      "time",
      "sources",
      "channel_category",
      "country",
      "campaign"
    ],
    "granularity": [
      "Hour",
      "Day",
      "Week",
      "Month",
      "Quarter",
      "Year"
    ],
    "filter_fields": [
      "country",
      "device",
      "landing_page",
      "campaign_name",
      "traffic_channel",
      "tag"
    ],
    "filter_conditions": [
      "is_equal_to",
      "is_not_equal_to",
      "contains",
      "does_not_contain",
      "starts_with",
      "ends_with"
    ],
    "attribution_method": [
      "first_click",
      "last_click",
      "Linear",
      "Time Decay",
      "U-Shaped",
      "Progressive"
    ],
    "attribution_date_mode": [
      "click_date",
      "conversion_date"
    ],
    "chart_types": [
      "line",
      "column",
      "bar",
      "area",
      "donut",
      "table"
    ],
    "time_periods": [
      "allTime",
      "today",
      "yesterday",
      "thisWeek",
      "lastWeek",
      "thisMonth",
      "lastMonth",
      "thisQuarter",
      "lastQuarter",
      "thisYear",
      "lastYear",
      "rollingDateRange",
      "customRange"
    ],
    "traffic_channels": [
      {
        "key": "google_ads",
        "label": "Google Ads",
        "is_active": true
      }
    ],
    "pagination": {
      "default_per_page": 20,
      "max_per_page": 50
    }
  }
}

38 endpoints

Public API

Workspace tokens (ljw_) with scopes: reports and dashboards, leads, tags, tracking, traffic channels, tokens and agency client workspaces. Paths below are relative to the Public API base URL.

Base URL
https://api.leadjourney.io/api/v1/public/workspaces/{workspace}

Reports & dashboards

Describe the report vocabulary, run a report ad hoc, and manage dashboards and their saved report cards. Scope: reports.

GET/reports/describe

Describe the report vocabulary

Everything a report can be built from: metrics, windows, dimensions, filters, attribution settings, chart types and time periods. Not paginated.

Scope reports

Example request

curl
curl "https://api.leadjourney.io/api/v1/public/workspaces/YOUR_WORKSPACE_ID/reports/describe" \
  -H "Authorization: Bearer ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

Example response

200 OK
{
  "success": true,
  "data": {
    "metrics": [
      "<metric_id>",
      "..."
    ],
    "metric_windows": {
      "note": "Append a window as metric@window. At most 6 distinct windows per report.",
      "ids": [
        "last_7d",
        "last_14d",
        "last_30d",
        "last_60d",
        "last_90d"
      ]
    },
    "group_by": [
      "time",
      "day_of_week",
      "sources",
      "channel_category",
      "country",
      "campaign",
      "custom_field:<key>"
    ],
    "channel_category": [
      "<channel category>",
      "..."
    ],
    "secondary_group_by": [
      "time",
      "sources",
      "channel_category",
      "country",
      "campaign"
    ],
    "granularity": [
      "Hour",
      "Day",
      "Week",
      "Month",
      "Quarter",
      "Year"
    ],
    "filter_fields": [
      "country",
      "device",
      "landing_page",
      "campaign_name",
      "traffic_channel",
      "tag"
    ],
    "filter_conditions": [
      "is_equal_to",
      "is_not_equal_to",
      "contains",
      "does_not_contain",
      "starts_with",
      "ends_with"
    ],
    "attribution_method": [
      "first_click",
      "last_click",
      "Linear",
      "Time Decay",
      "U-Shaped",
      "Progressive"
    ],
    "attribution_date_mode": [
      "click_date",
      "conversion_date"
    ],
    "chart_types": [
      "line",
      "column",
      "bar",
      "area",
      "donut",
      "table"
    ],
    "time_periods": [
      "allTime",
      "today",
      "yesterday",
      "thisWeek",
      "lastWeek",
      "thisMonth",
      "lastMonth",
      "thisQuarter",
      "lastQuarter",
      "thisYear",
      "lastYear",
      "rollingDateRange",
      "customRange"
    ],
    "traffic_channels": [
      {
        "key": "google_ads",
        "label": "Google Ads",
        "is_active": true
      }
    ],
    "pagination": {
      "default_per_page": 20,
      "max_per_page": 50
    }
  }
}

Lists shortened. group_by: time, day_of_week, sources, channel_category, country, city, device, browser, os, isp, landing_page, domain, form, keyword, url_parameters, campaign, ad_group, ad, affiliate_campaign, affiliate_offer, affiliate_network, custom_field:<key>. secondary_group_by: time, sources, channel_category, country, city, device, browser, os, isp, landing_page, domain, keyword, url_parameters, campaign, ad_group, ad. filter_fields: country, device, landing_page, domain, campaign_name, ad_group, ad, keyword, traffic_channel, medium, tag, campaign_id, adset_id, ad_id. The affiliate_* entries only appear when affiliate features are on for the workspace. metrics are the known base metric ids of the workspace.

POST/reports/run

Run a report

Runs an ad-hoc report and returns its rows. Nothing is saved.

Scope reports

Request body

metricsstring[]
required

At least one. Each item is at most 100 characters, matches ^[a-z0-9_]+(@(last_7d|last_14d|last_30d|last_60d|last_90d))?$ and names a known base metric (see /reports/describe). Append @window for a rolling window, at most 6 distinct windows per report. A _trend suffix (with no @) requests a trend series, returned under trends.

group_bystring
required

One entry of the group_by list from /reports/describe, or custom_field:<key> (key matching [a-z][a-z0-9_]*).

granularitystring
optional

Time bucket.

Allowed: Hour, Day, Week, Month, Quarter, Year

secondary_group_bystring
optional

One entry of the secondary_group_by list from /reports/describe.

secondary_granularitystring
optional

Time bucket of the secondary dimension.

Allowed: Day, Week, Month, Quarter, Year

date_fromstring
optional

Start date, Y-m-d.

date_tostring
optional

End date, Y-m-d.

traffic_channelsstring[]
optional

Channel keys. Empty means all channels.

filtersarray
optional

Array of { field, condition, value }. field is one of filter_fields, condition one of the six filter_conditions from /reports/describe, value is required.

attribution_methodstring
optional

Defaults to last_click. First and Last are accepted as aliases; an unknown value falls back to last_click.

Allowed: first_click, last_click, Linear, Time Decay, U-Shaped, Progressive

attribution_windowstring
optional

Defaults to lifetime.

attribution_date_modestring
optional

Defaults to click_date.

Allowed: click_date, conversion_date

sort_directionstring
optional

Defaults to desc.

Allowed: asc, desc

sort_columnstring
optional

A known metric id.

limitinteger
optional

Defaults to 10.

Allowed: 5, 10, 15, 20

display_only_dates_with_databoolean
optional

Defaults to true.

pageinteger
optional

Minimum 1. Accepted in the body or the query string.

per_pageinteger
optional

Validated as 1 to 100, then clamped to 50. Defaults to 20. Accepted in the body or the query string.

Errors

503report_too_large

The query timed out. Narrow the date range or the dimensions.

422report_failed

Any other failure while running the report.

422

Validation errors, including an unknown base metric, in the standard message and errors shape.

Example request

curl
curl -X POST "https://api.leadjourney.io/api/v1/public/workspaces/YOUR_WORKSPACE_ID/reports/run" \
  -H "Authorization: Bearer ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "metrics": [
    "<metric_id>"
  ],
  "group_by": "sources",
  "date_from": "2026-10-01",
  "date_to": "2026-10-24",
  "attribution_method": "first_click"
}'

Example response

200 OK
{
  "success": true,
  "data": {
    "labels": [
      "Google Ads",
      "Meta Ads",
      "LinkedIn Ads"
    ],
    "primary_labels": null,
    "secondary_labels": null,
    "secondary_group_by": null,
    "secondary_granularity": null,
    "pagination": {
      "page": 1,
      "per_page": 20,
      "total": 3,
      "has_more": false
    }
  },
  "meta": {
    "current_page": 1,
    "per_page": 20,
    "max_per_page": 50
  }
}

Example trimmed. data also carries dimension_meta, datasets, totals, previous_totals and metric_meta, plus trends when _trend metrics are requested. The secondary keys are null unless a secondary dimension is used.

GET/dashboards

List dashboards

Lists the workspace's dashboards, ordered by order, each with its report cards.

Scope reports

Query parameters

pageinteger
optional

Page number. Defaults to 1, minimum 1.

per_pageinteger
optional

Items per page. Defaults to 20, maximum 50. A larger value is clamped to 50, a value below 1 falls back to 20.

Example request

curl
curl "https://api.leadjourney.io/api/v1/public/workspaces/YOUR_WORKSPACE_ID/dashboards" \
  -H "Authorization: Bearer ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

Example response

200 OK
{
  "success": true,
  "data": [
    {
      "id": "b2c3d4e5-f607-4819-2a3b-4c5d6e7f8091",
      "name": "Paid channels",
      "icon_key": "google_ads",
      "column_layout": 2,
      "order": 1,
      "reports": [
        {
          "id": "d4e5f607-1829-4a3b-5c6d-7e8f90a1b2c3",
          "order": 1,
          "name": "Leads by source",
          "chart_type": "column",
          "metrics": [
            "<metric_id>"
          ],
          "group_by": "sources"
        }
      ]
    }
  ],
  "meta": {
    "current_page": 1,
    "per_page": 20,
    "last_page": 1,
    "total": 1,
    "max_per_page": 50
  }
}
POST/dashboards

Create a dashboard

Creates an empty dashboard.

Scope reports

Request body

namestring
required

Max 255 characters.

icon_keystring
optional

A traffic channel key, for example meta_ads, google_ads, bing_ads, linkedin_ads, reddit_ads, chatgpt_ads, x_ads, taboola_ads, outbrain_ads, tiktok_ads, email, gmb, plus direct, referral and the organic keys.

Example request

curl
curl -X POST "https://api.leadjourney.io/api/v1/public/workspaces/YOUR_WORKSPACE_ID/dashboards" \
  -H "Authorization: Bearer ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Paid channels",
  "icon_key": "google_ads"
}'

Example response

201 Created
{
  "success": true,
  "data": {
    "id": "b2c3d4e5-f607-4819-2a3b-4c5d6e7f8091",
    "name": "Paid channels",
    "icon_key": "google_ads"
  }
}
GET/dashboards/{dashboard}

Get a dashboard

Returns one dashboard with every report card and its full report configuration.

Scope reports

Path parameters

dashboarduuid
required

Dashboard id.

Errors

404not_found

The dashboard is not in this workspace.

Example request

curl
curl "https://api.leadjourney.io/api/v1/public/workspaces/YOUR_WORKSPACE_ID/dashboards/DASHBOARD_ID" \
  -H "Authorization: Bearer ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

Example response

200 OK
{
  "success": true,
  "data": {
    "id": "b2c3d4e5-f607-4819-2a3b-4c5d6e7f8091",
    "name": "Paid channels",
    "icon_key": "google_ads",
    "column_layout": 2,
    "order": 1,
    "reports": [
      {
        "id": "d4e5f607-1829-4a3b-5c6d-7e8f90a1b2c3",
        "order": 1,
        "name": "Leads by source",
        "chart_type": "column",
        "report_config": {
          "...": "the frontend's camelCase report configuration"
        }
      }
    ]
  }
}

report_config is the full configuration in the frontend's camelCase shape.

DELETE/dashboards/{dashboard}

Delete a dashboard

Deletes the dashboard and detaches its icon.

Scope reports

Path parameters

dashboarduuid
required

Dashboard id.

Errors

404not_found

The dashboard is not in this workspace.

Example request

curl
curl -X DELETE "https://api.leadjourney.io/api/v1/public/workspaces/YOUR_WORKSPACE_ID/dashboards/DASHBOARD_ID" \
  -H "Authorization: Bearer ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

Example response

200 OK
{
  "success": true,
  "data": {
    "id": "b2c3d4e5-f607-4819-2a3b-4c5d6e7f8091",
    "name": "Paid channels",
    "deleted": true
  }
}
POST/dashboards/{dashboard}/reports

Save a report card

Saves a report card on a dashboard. Takes the fields of /reports/run (without page and per_page) plus the card's own.

Scope reports

Path parameters

dashboarduuid
required

Dashboard id.

Request body

report_namestring
required

Max 255 characters.

chart_typestring
optional

Defaults to line.

Allowed: line, column, bar, area, donut, table

time_periodstring
optional

One of time_periods from /reports/describe. Defaults to customRange when dates are given, otherwise lastMonth.

rolling_valueinteger
optional

Minimum 1.

rolling_unitstring
optional

Unit of a rolling range.

Allowed: days, weeks, months, quarters, years

metricsstring[]
required

At least one. Each item is at most 100 characters, matches ^[a-z0-9_]+(@(last_7d|last_14d|last_30d|last_60d|last_90d))?$ and names a known base metric (see /reports/describe). Append @window for a rolling window, at most 6 distinct windows per report. A _trend suffix (with no @) requests a trend series, returned under trends.

group_bystring
required

One entry of the group_by list from /reports/describe, or custom_field:<key> (key matching [a-z][a-z0-9_]*).

granularitystring
optional

Time bucket.

Allowed: Hour, Day, Week, Month, Quarter, Year

secondary_group_bystring
optional

One entry of the secondary_group_by list from /reports/describe.

secondary_granularitystring
optional

Time bucket of the secondary dimension.

Allowed: Day, Week, Month, Quarter, Year

date_fromstring
optional

Start date, Y-m-d.

date_tostring
optional

End date, Y-m-d.

traffic_channelsstring[]
optional

Channel keys. Empty means all channels.

filtersarray
optional

Array of { field, condition, value }. field is one of filter_fields, condition one of the six filter_conditions from /reports/describe, value is required.

attribution_methodstring
optional

Defaults to last_click. First and Last are accepted as aliases; an unknown value falls back to last_click.

Allowed: first_click, last_click, Linear, Time Decay, U-Shaped, Progressive

attribution_windowstring
optional

Defaults to lifetime.

attribution_date_modestring
optional

Defaults to click_date.

Allowed: click_date, conversion_date

sort_directionstring
optional

Defaults to desc.

Allowed: asc, desc

sort_columnstring
optional

A known metric id.

limitinteger
optional

Defaults to 10.

Allowed: 5, 10, 15, 20

display_only_dates_with_databoolean
optional

Defaults to true.

Errors

404not_found

The dashboard is not in this workspace.

Example request

curl
curl -X POST "https://api.leadjourney.io/api/v1/public/workspaces/YOUR_WORKSPACE_ID/dashboards/DASHBOARD_ID/reports" \
  -H "Authorization: Bearer ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "report_name": "Leads by source",
  "chart_type": "column",
  "metrics": [
    "<metric_id>"
  ],
  "group_by": "sources",
  "time_period": "lastMonth"
}'

Example response

201 Created
{
  "success": true,
  "data": {
    "id": "d4e5f607-1829-4a3b-5c6d-7e8f90a1b2c3",
    "dashboard_id": "b2c3d4e5-f607-4819-2a3b-4c5d6e7f8091",
    "dashboard_name": "Paid channels",
    "name": "Leads by source",
    "order": 1
  }
}
DELETE/dashboards/{dashboard}/reports/{report}

Delete a report card

Removes a report card from a dashboard.

Scope reports

Path parameters

dashboarduuid
required

Dashboard id.

reportuuid
required

Report card id.

Errors

404not_found

The dashboard is not in this workspace, or it has no such card.

Example request

curl
curl -X DELETE "https://api.leadjourney.io/api/v1/public/workspaces/YOUR_WORKSPACE_ID/dashboards/DASHBOARD_ID/reports/REPORT_ID" \
  -H "Authorization: Bearer ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

Example response

200 OK
{
  "success": true,
  "data": {
    "id": "d4e5f607-1829-4a3b-5c6d-7e8f90a1b2c3",
    "name": "Leads by source",
    "deleted": true
  }
}

Leads

Resolve a lead from a click id, email or phone, and read its full journey. Read-only, and the answers carry personal data (email, phone). Scope: leads.

GET/leads/find

Find a lead

Resolves a lead from a click id, an email or a phone number and returns its first and last touch. The click id is tried first, following merges for up to 5 hops; if the email or phone passed contradicts the lead behind the click id, identity matching wins, email first, then phone.

Scope leads

Query parameters

click_idstring
optional

Max 255. Required unless email or phone is given.

emailstring
optional

Max 255.

phonestring
optional

Max 64.

Example request

curl
curl "https://api.leadjourney.io/api/v1/public/workspaces/YOUR_WORKSPACE_ID/leads/find?click_id=0c1d2e3f-4a5b-6c7d-8e9f-a0b1c2d3e4f5" \
  -H "Authorization: Bearer ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

Example response

200 OK
{
  "success": true,
  "data": {
    "lead": {
      "id": "5d6e7f80-1a2b-3c4d-5e6f-708192a3b4c5",
      "click_id": "0c1d2e3f-4a5b-6c7d-8e9f-a0b1c2d3e4f5",
      "email": "[email protected]",
      "phone": "+4915112345678",
      "is_unattributed": false,
      "matched_by": "click_id",
      "created_at": "2026-10-02T08:16:40Z",
      "first_touch": {
        "clicked_at": "2026-10-02T08:14:03Z",
        "channel": "Google Ads",
        "channel_key": "google_ads",
        "utm_source": "google",
        "utm_medium": "cpc",
        "utm_campaign": "brand-search",
        "utm_content": null,
        "utm_term": "lead attribution",
        "campaign": "Brand Search",
        "campaign_id": "1234567890",
        "ad_set": "Brand Exact",
        "ad_set_id": "2345678901",
        "ad": "RSA 1",
        "ad_id": "3456789012",
        "keyword": "lead attribution",
        "keyword_id": "4567890123",
        "placement": null,
        "gclid": "EAIaIQobChMI_example",
        "wbraid": null,
        "gbraid": null,
        "fbclid": null,
        "li_fat_id": null,
        "msclkid": null,
        "rdt_cid": null,
        "twclid": null,
        "oppref": null,
        "tblci": null,
        "obclid": null,
        "ttclid": null,
        "landing_page": "/pricing",
        "full_url": "https://acme.com/pricing?utm_source=google&utm_medium=cpc",
        "referrer_domain": "google.com",
        "device_type": "desktop",
        "os": "macOS",
        "browser": "Chrome",
        "country": "DE",
        "city": "Berlin"
      },
      "last_touch": {
        "clicked_at": "2026-10-02T08:14:03Z",
        "channel": "Google Ads",
        "channel_key": "google_ads",
        "utm_source": "google",
        "utm_medium": "cpc",
        "utm_campaign": "brand-search",
        "utm_content": null,
        "utm_term": "lead attribution",
        "campaign": "Brand Search",
        "campaign_id": "1234567890",
        "ad_set": "Brand Exact",
        "ad_set_id": "2345678901",
        "ad": "RSA 1",
        "ad_id": "3456789012",
        "keyword": "lead attribution",
        "keyword_id": "4567890123",
        "placement": null,
        "gclid": "EAIaIQobChMI_example",
        "wbraid": null,
        "gbraid": null,
        "fbclid": null,
        "li_fat_id": null,
        "msclkid": null,
        "rdt_cid": null,
        "twclid": null,
        "oppref": null,
        "tblci": null,
        "obclid": null,
        "ttclid": null,
        "landing_page": "/pricing",
        "full_url": "https://acme.com/pricing?utm_source=google&utm_medium=cpc",
        "referrer_domain": "google.com",
        "device_type": "desktop",
        "os": "macOS",
        "browser": "Chrome",
        "country": "DE",
        "city": "Berlin"
      }
    }
  }
}

When nothing matches, data.lead is null with status 200, not a 404. matched_by is click_id, email or phone. Every key of a touch object is always present; timestamps are ISO 8601 UTC.

GET/leads/{lead}/journey

Get a lead's journey

The full timeline behind a lead: its conversions whole, its clicks paged oldest first.

Scope leads

Path parameters

leadstring
required

The lead id (uuid) or a click_id.

Query parameters

pageinteger
optional

Page number. Defaults to 1, minimum 1.

per_pageinteger
optional

Items per page. Defaults to 20, maximum 50. A larger value is clamped to 50, a value below 1 falls back to 20.

Errors

404not_found

The lead is not in this workspace.

Example request

curl
curl "https://api.leadjourney.io/api/v1/public/workspaces/YOUR_WORKSPACE_ID/leads/LEAD_ID/journey" \
  -H "Authorization: Bearer ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

Example response

200 OK
{
  "success": true,
  "data": {
    "lead": {
      "id": "5d6e7f80-1a2b-3c4d-5e6f-708192a3b4c5",
      "click_id": "0c1d2e3f-4a5b-6c7d-8e9f-a0b1c2d3e4f5",
      "email": "[email protected]",
      "phone": "+4915112345678",
      "is_unattributed": false,
      "matched_by": "click_id",
      "created_at": "2026-10-02T08:16:40Z",
      "first_touch": {
        "clicked_at": "2026-10-02T08:14:03Z",
        "channel": "Google Ads",
        "channel_key": "google_ads",
        "utm_source": "google",
        "utm_medium": "cpc",
        "utm_campaign": "brand-search",
        "utm_content": null,
        "utm_term": "lead attribution",
        "campaign": "Brand Search",
        "campaign_id": "1234567890",
        "ad_set": "Brand Exact",
        "ad_set_id": "2345678901",
        "ad": "RSA 1",
        "ad_id": "3456789012",
        "keyword": "lead attribution",
        "keyword_id": "4567890123",
        "placement": null,
        "gclid": "EAIaIQobChMI_example",
        "wbraid": null,
        "gbraid": null,
        "fbclid": null,
        "li_fat_id": null,
        "msclkid": null,
        "rdt_cid": null,
        "twclid": null,
        "oppref": null,
        "tblci": null,
        "obclid": null,
        "ttclid": null,
        "landing_page": "/pricing",
        "full_url": "https://acme.com/pricing?utm_source=google&utm_medium=cpc",
        "referrer_domain": "google.com",
        "device_type": "desktop",
        "os": "macOS",
        "browser": "Chrome",
        "country": "DE",
        "city": "Berlin"
      },
      "last_touch": {
        "clicked_at": "2026-10-02T08:14:03Z",
        "channel": "Google Ads",
        "channel_key": "google_ads",
        "utm_source": "google",
        "utm_medium": "cpc",
        "utm_campaign": "brand-search",
        "utm_content": null,
        "utm_term": "lead attribution",
        "campaign": "Brand Search",
        "campaign_id": "1234567890",
        "ad_set": "Brand Exact",
        "ad_set_id": "2345678901",
        "ad": "RSA 1",
        "ad_id": "3456789012",
        "keyword": "lead attribution",
        "keyword_id": "4567890123",
        "placement": null,
        "gclid": "EAIaIQobChMI_example",
        "wbraid": null,
        "gbraid": null,
        "fbclid": null,
        "li_fat_id": null,
        "msclkid": null,
        "rdt_cid": null,
        "twclid": null,
        "oppref": null,
        "tblci": null,
        "obclid": null,
        "ttclid": null,
        "landing_page": "/pricing",
        "full_url": "https://acme.com/pricing?utm_source=google&utm_medium=cpc",
        "referrer_domain": "google.com",
        "device_type": "desktop",
        "os": "macOS",
        "browser": "Chrome",
        "country": "DE",
        "city": "Berlin"
      }
    },
    "conversions": [
      {
        "id": "11223344-5566-4788-99aa-bbccddeeff00",
        "type": "Deal won",
        "occurred_at": "2026-10-21T14:00:00Z",
        "revenue": 4800,
        "cash_collected": 4800,
        "currency": "EUR",
        "original_revenue": 4800,
        "original_currency": "EUR",
        "form_name": null,
        "first_source_channel": "Google Ads",
        "first_source_channel_key": "google_ads",
        "last_source_channel": "LinkedIn Ads",
        "last_source_channel_key": "linkedin_ads"
      }
    ],
    "clicks": [
      {
        "id": "aa00bb11-cc22-4d33-8e44-ff5566778899",
        "clicked_at": "2026-10-02T08:14:03Z",
        "channel": "Google Ads",
        "channel_key": "google_ads",
        "utm_source": "google",
        "utm_medium": "cpc",
        "utm_campaign": "brand-search",
        "utm_content": null,
        "utm_term": "lead attribution",
        "campaign": "Brand Search",
        "campaign_id": "1234567890",
        "ad_set": "Brand Exact",
        "ad_set_id": "2345678901",
        "ad": "RSA 1",
        "ad_id": "3456789012",
        "keyword": "lead attribution",
        "keyword_id": "4567890123",
        "placement": null,
        "gclid": "EAIaIQobChMI_example",
        "wbraid": null,
        "gbraid": null,
        "fbclid": null,
        "li_fat_id": null,
        "msclkid": null,
        "rdt_cid": null,
        "twclid": null,
        "oppref": null,
        "tblci": null,
        "obclid": null,
        "ttclid": null,
        "landing_page": "/pricing",
        "full_url": "https://acme.com/pricing?utm_source=google&utm_medium=cpc",
        "referrer_domain": "google.com",
        "device_type": "desktop",
        "os": "macOS",
        "browser": "Chrome",
        "country": "DE",
        "city": "Berlin"
      }
    ]
  },
  "meta": {
    "current_page": 1,
    "per_page": 20,
    "last_page": 1,
    "total": 1,
    "max_per_page": 50
  }
}

meta paginates the clicks; the conversions come whole.

Tags

Tags and the rules that apply them automatically, with an optional backfill over existing data. Scope: tags.

GET/tags/rule-fields

Describe the tag rule vocabulary

Tag types, rule fields, operators, timing and the lists a rule value can come from.

Scope tags

Example request

curl
curl "https://api.leadjourney.io/api/v1/public/workspaces/YOUR_WORKSPACE_ID/tags/rule-fields" \
  -H "Authorization: Bearer ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

Example response

200 OK
{
  "success": true,
  "data": {
    "tag_types": [
      "source",
      "entry",
      "action",
      "lead",
      "lead_type",
      "product",
      "funnel",
      "referrer",
      "status"
    ],
    "rule_fields": [
      {
        "id": "entry_page",
        "label": "Entry page",
        "requires_field_key": false
      }
    ],
    "operators": [
      {
        "id": "contains",
        "label": "Contains"
      }
    ],
    "rule_logic": [
      "and",
      "or"
    ],
    "timing": {
      "anytime": "...",
      "before_conversion": "..."
    },
    "integrations": [
      {
        "id": "hubspot",
        "label": "HubSpot"
      }
    ],
    "traffic_channels": [
      {
        "id": "google_ads",
        "label": "Google Ads"
      }
    ],
    "conversion_types": [
      "Lead",
      "Deal won"
    ]
  }
}

Lists shortened. rule_fields ids: entry_page, entry_full_url, referrer_domain, landing_domain, traffic_channel, campaign, adset, ad, keyword, placement, form, form_url, source_integration, conversion_type, custom_field. operators: contains, equals, starts_with, ends_with, not_contains. integrations are the conversion sources (tracking, postback, gohighlevel, hubspot, salesforce, and more). timing holds a description of each mode.

GET/tags

List tags

Lists the workspace's tags with their rules, newest first.

Scope tags

Query parameters

pageinteger
optional

Page number. Defaults to 1, minimum 1.

per_pageinteger
optional

Items per page. Defaults to 20, maximum 50. A larger value is clamped to 50, a value below 1 falls back to 20.

Example request

curl
curl "https://api.leadjourney.io/api/v1/public/workspaces/YOUR_WORKSPACE_ID/tags" \
  -H "Authorization: Bearer ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

Example response

200 OK
{
  "success": true,
  "data": [
    {
      "id": "a1f2e3d4-5c6b-7a89-90b1-c2d3e4f5a6b7",
      "name": "Webinar lead",
      "type": "funnel",
      "color": "#03c879",
      "rule_logic": "and",
      "show_in_journey": true,
      "rules": [
        {
          "field": "entry_page",
          "field_key": null,
          "operator": "contains",
          "value": "/webinar",
          "timing": "before_conversion",
          "timing_event": null,
          "is_active": true
        }
      ],
      "created_at": "2026-10-20T09:12:00Z"
    }
  ],
  "meta": {
    "current_page": 1,
    "per_page": 20,
    "last_page": 1,
    "total": 1,
    "max_per_page": 50
  }
}
POST/tags

Create a tag

Creates a tag, optionally with rules and a backfill over existing data.

Scope tags

Request body

namestring
required

1 to 50 characters, unique in the workspace (a duplicate returns 422 invalid_tag).

typestring
required

Tag type.

Allowed: source, entry, action, lead, lead_type, product, funnel, referrer, status

colorstring
optional

#RRGGBB. Defaults to #03c879.

show_in_journeyboolean
optional

Show the tag in the lead journey.

rule_logicstring
optional

Defaults to and.

Allowed: and, or

rulesarray
optional

Rules that apply the tag automatically.

rules.*.fieldstring
conditional

Required with rules.

Allowed: entry_page, entry_full_url, referrer_domain, landing_domain, traffic_channel, campaign, adset, ad, keyword, placement, form, form_url, source_integration, conversion_type, custom_field

rules.*.field_keystring
conditional

Max 190. Required in practice when field is custom_field, otherwise 422 invalid_tag.

rules.*.operatorstring
conditional

Required with rules.

Allowed: contains, equals, starts_with, ends_with, not_contains

rules.*.valuestring
conditional

Required with rules.

rules.*.timingstring
optional

When the rule looks.

Allowed: anytime, before_conversion

rules.*.timing_eventstring
optional

The event a before_conversion rule looks before.

rules.*.is_activeboolean
optional

Whether the rule applies.

apply_to_existingboolean
optional

Queues a backfill over existing data, only if the tag has active rules.

Errors

422invalid_tag

The name is taken, or a custom_field rule has no field_key.

Example request

curl
curl -X POST "https://api.leadjourney.io/api/v1/public/workspaces/YOUR_WORKSPACE_ID/tags" \
  -H "Authorization: Bearer ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Webinar lead",
  "type": "funnel",
  "rules": [
    {
      "field": "entry_page",
      "operator": "contains",
      "value": "/webinar",
      "timing": "before_conversion"
    }
  ],
  "apply_to_existing": true
}'

Example response

201 Created
{
  "success": true,
  "data": {
    "id": "a1f2e3d4-5c6b-7a89-90b1-c2d3e4f5a6b7",
    "name": "Webinar lead",
    "type": "funnel",
    "color": "#03c879",
    "rule_logic": "and",
    "show_in_journey": true,
    "rules": [
      {
        "field": "entry_page",
        "field_key": null,
        "operator": "contains",
        "value": "/webinar",
        "timing": "before_conversion",
        "timing_event": null,
        "is_active": true
      }
    ],
    "created_at": "2026-10-20T09:12:00Z",
    "backfill_queued": true
  }
}
GET/tags/{tag}

Get a tag

Returns one tag with its rules.

Scope tags

Path parameters

taguuid
required

Tag id.

Errors

404not_found

The tag is not in this workspace.

Example request

curl
curl "https://api.leadjourney.io/api/v1/public/workspaces/YOUR_WORKSPACE_ID/tags/TAG_ID" \
  -H "Authorization: Bearer ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

Example response

200 OK
{
  "success": true,
  "data": {
    "id": "a1f2e3d4-5c6b-7a89-90b1-c2d3e4f5a6b7",
    "name": "Webinar lead",
    "type": "funnel",
    "color": "#03c879",
    "rule_logic": "and",
    "show_in_journey": true,
    "rules": [
      {
        "field": "entry_page",
        "field_key": null,
        "operator": "contains",
        "value": "/webinar",
        "timing": "before_conversion",
        "timing_event": null,
        "is_active": true
      }
    ],
    "created_at": "2026-10-20T09:12:00Z"
  }
}
PATCH/tags/{tag}

Update a tag

Changes a tag. Same fields as create, all optional.

Scope tags

Path parameters

taguuid
required

Tag id.

Request body

namestring
optional

1 to 50 characters, unique in the workspace (a duplicate returns 422 invalid_tag).

typestring
optional

Tag type.

Allowed: source, entry, action, lead, lead_type, product, funnel, referrer, status

colorstring
optional

#RRGGBB. Defaults to #03c879.

show_in_journeyboolean
optional

Show the tag in the lead journey. false is honoured.

rule_logicstring
optional

Defaults to and.

Allowed: and, or

rulesarray
optional

Rules that apply the tag automatically.

rules.*.fieldstring
optional

Required with rules.

Allowed: entry_page, entry_full_url, referrer_domain, landing_domain, traffic_channel, campaign, adset, ad, keyword, placement, form, form_url, source_integration, conversion_type, custom_field

rules.*.field_keystring
conditional

Max 190. Required in practice when field is custom_field, otherwise 422 invalid_tag.

rules.*.operatorstring
optional

Required with rules.

Allowed: contains, equals, starts_with, ends_with, not_contains

rules.*.valuestring
optional

Required with rules.

rules.*.timingstring
optional

When the rule looks.

Allowed: anytime, before_conversion

rules.*.timing_eventstring
optional

The event a before_conversion rule looks before.

rules.*.is_activeboolean
optional

Whether the rule applies.

apply_to_existingboolean
optional

Queues a backfill over existing data, only if the tag has active rules.

Errors

404not_found

The tag is not in this workspace.

422invalid_tag

The name is taken, or a custom_field rule has no field_key.

Example request

curl
curl -X PATCH "https://api.leadjourney.io/api/v1/public/workspaces/YOUR_WORKSPACE_ID/tags/TAG_ID" \
  -H "Authorization: Bearer ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "color": "#2f80ed",
  "show_in_journey": false
}'

Example response

200 OK
{
  "success": true,
  "data": {
    "id": "a1f2e3d4-5c6b-7a89-90b1-c2d3e4f5a6b7",
    "name": "Webinar lead",
    "type": "funnel",
    "color": "#2f80ed",
    "rule_logic": "and",
    "show_in_journey": false,
    "rules": [
      {
        "field": "entry_page",
        "field_key": null,
        "operator": "contains",
        "value": "/webinar",
        "timing": "before_conversion",
        "timing_event": null,
        "is_active": true
      }
    ],
    "created_at": "2026-10-20T09:12:00Z",
    "backfill_queued": false
  }
}
DELETE/tags/{tag}

Delete a tag

Deletes a tag.

Scope tags

Path parameters

taguuid
required

Tag id.

Errors

404not_found

The tag is not in this workspace.

Example request

curl
curl -X DELETE "https://api.leadjourney.io/api/v1/public/workspaces/YOUR_WORKSPACE_ID/tags/TAG_ID" \
  -H "Authorization: Bearer ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

Example response

200 OK
{
  "success": true,
  "data": {
    "id": "a1f2e3d4-5c6b-7a89-90b1-c2d3e4f5a6b7",
    "name": "Webinar lead",
    "deleted": true
  }
}

Tracking

Tracking domains, the onboarding state, the script check, stack detection and the CRM webhook details. Scope: tracking.

GET/tracking-domains

List tracking domains

Lists the workspace's tracking domains, oldest first.

Scope tracking

Query parameters

pageinteger
optional

Page number. Defaults to 1, minimum 1.

per_pageinteger
optional

Items per page. Defaults to 20, maximum 50. A larger value is clamped to 50, a value below 1 falls back to 20.

Example request

curl
curl "https://api.leadjourney.io/api/v1/public/workspaces/YOUR_WORKSPACE_ID/tracking-domains" \
  -H "Authorization: Bearer ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

Example response

200 OK
{
  "success": true,
  "data": [
    {
      "id": "c3d4e5f6-0718-293a-4b5c-6d7e8f901a2b",
      "url": "track.acme.com",
      "root_url": "acme.com",
      "status": "success",
      "status_meaning": "...",
      "free_ssl": true,
      "cname_destination": "package.leadjourney.io",
      "created_at": "2026-09-01T10:00:00Z"
    }
  ],
  "meta": {
    "current_page": 1,
    "per_page": 20,
    "last_page": 1,
    "total": 1,
    "max_per_page": 50
  }
}

status is initialize, process, fail, success or disabled.

POST/tracking-domains

Add a tracking domain

Adds a tracking domain and starts its verification. Point a CNAME at package.leadjourney.io.

Scope tracking

Request body

urlstring
required

A bare host: no https://, no www., at least one dot, 5 to 253 characters. Must be unique across LeadJourney.

root_urlstring
optional

Minimum 5 characters.

Example request

curl
curl -X POST "https://api.leadjourney.io/api/v1/public/workspaces/YOUR_WORKSPACE_ID/tracking-domains" \
  -H "Authorization: Bearer ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "url": "track.acme.com",
  "root_url": "acme.com"
}'

Example response

201 Created
{
  "success": true,
  "data": {
    "id": "c3d4e5f6-0718-293a-4b5c-6d7e8f901a2b",
    "url": "track.acme.com",
    "status": "initialize",
    "cname_destination": "package.leadjourney.io",
    "next_step": "..."
  }
}
GET/tracking-domains/{domain}

Get a tracking domain

Returns one tracking domain and its verification status.

Scope tracking

Path parameters

domainuuid
required

Domain id.

Errors

404not_found

The domain is not in this workspace.

Example request

curl
curl "https://api.leadjourney.io/api/v1/public/workspaces/YOUR_WORKSPACE_ID/tracking-domains/DOMAIN_ID" \
  -H "Authorization: Bearer ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

Example response

200 OK
{
  "success": true,
  "data": {
    "id": "c3d4e5f6-0718-293a-4b5c-6d7e8f901a2b",
    "url": "track.acme.com",
    "root_url": "acme.com",
    "status": "success",
    "status_meaning": "...",
    "free_ssl": true,
    "cname_destination": "package.leadjourney.io",
    "created_at": "2026-09-01T10:00:00Z"
  }
}
PATCH/tracking-domains/{domain}

Update a tracking domain

Changes the host or the root URL. Verification runs again for the new host.

Scope tracking

Path parameters

domainuuid
required

Domain id.

Request body

urlstring
optional

Same rules as on create.

root_urlstring
optional

Same rules as on create.

Errors

404not_found

The domain is not in this workspace.

422invalid_request

Neither url nor root_url was sent.

Example request

curl
curl -X PATCH "https://api.leadjourney.io/api/v1/public/workspaces/YOUR_WORKSPACE_ID/tracking-domains/DOMAIN_ID" \
  -H "Authorization: Bearer ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "url": "go.acme.com"
}'

Example response

200 OK
{
  "success": true,
  "data": {
    "id": "c3d4e5f6-0718-293a-4b5c-6d7e8f901a2b",
    "url": "go.acme.com",
    "root_url": "acme.com",
    "status": "initialize",
    "note": "..."
  }
}
POST/tracking-domains/{domain}/retry

Retry a domain's verification

Resets a failed domain to initialize and queues its verification again.

Scope tracking

Path parameters

domainuuid
required

Domain id.

Errors

404not_found

The domain is not in this workspace.

422invalid_state

The domain's status is not fail.

Example request

curl
curl -X POST "https://api.leadjourney.io/api/v1/public/workspaces/YOUR_WORKSPACE_ID/tracking-domains/DOMAIN_ID/retry" \
  -H "Authorization: Bearer ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

Example response

200 OK
{
  "success": true,
  "data": {
    "id": "c3d4e5f6-0718-293a-4b5c-6d7e8f901a2b",
    "url": "track.acme.com",
    "status": "initialize",
    "note": "..."
  }
}
DELETE/tracking-domains/{domain}

Delete a tracking domain

Deletes a tracking domain. Destructive: every link on that host stops working immediately.

Scope tracking

Path parameters

domainuuid
required

Domain id.

Request body

confirmboolean
required

Must be true. Read from the body or the query string.

Destructive. Requires confirm: true, otherwise 409 confirmation_required. Deleting a tracking domain breaks every link on that host, at once.

Errors

404not_found

The domain is not in this workspace.

409confirmation_required

confirm: true was not sent. The message says how many short links are on the host.

Example request

curl
curl -X DELETE "https://api.leadjourney.io/api/v1/public/workspaces/YOUR_WORKSPACE_ID/tracking-domains/DOMAIN_ID" \
  -H "Authorization: Bearer ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "confirm": true
}'

Example response

200 OK
{
  "success": true,
  "data": {
    "id": "c3d4e5f6-0718-293a-4b5c-6d7e8f901a2b",
    "url": "track.acme.com",
    "deleted": true
  }
}
GET/tracking/onboarding-status

Get the onboarding status

The workspace's onboarding state, the live tracking state and what still blocks it.

Scope tracking

Example request

curl
curl "https://api.leadjourney.io/api/v1/public/workspaces/YOUR_WORKSPACE_ID/tracking/onboarding-status" \
  -H "Authorization: Bearer ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

Example response

200 OK
{
  "success": true,
  "data": {
    "onboarding": {
      "current_step": "tracking_script",
      "completed_steps": [
        "account_created",
        "profile_setup",
        "traffic_channels",
        "ad_platforms",
        "tracking_domain"
      ],
      "is_completed": false,
      "checklist": {
        "account_created": true,
        "profile_setup": true,
        "traffic_channels": true,
        "ad_platforms": true,
        "tracking_domain": true,
        "tracking_script": false,
        "events": false,
        "contact_forms": false,
        "crm_webhooks": false
      },
      "stack": "...",
      "existing_events": [],
      "owner_profile": {
        "first_name": "Maria",
        "last_name": "Schulz",
        "phone": "+4915112345678",
        "email": "[email protected]"
      },
      "company_info": {
        "name": "Acme GmbH",
        "country": "DE",
        "region": "Berlin",
        "city": "Berlin",
        "street": "Example Street 1",
        "postal_code": "10115"
      },
      "timezone_info": {
        "time_zone": "Europe/Berlin",
        "currency": "EUR",
        "time_format": "24h"
      }
    },
    "live_state": {
      "tracking_domains": [
        {
          "url": "track.acme.com",
          "status": "success"
        }
      ],
      "verified_domains": 1,
      "conversion_events": 0
    },
    "blockers": [
      "..."
    ]
  }
}

The onboarding object is shown with the keys documented here; it may carry more.

POST/tracking/verify-script

Check the tracking script

Checks whether the tracking script is installed on a page.

Scope tracking

Request body

urlstring
required

Max 2048. https:// is prepended when no scheme is given, and a trailing / is stripped.

Example request

curl
curl -X POST "https://api.leadjourney.io/api/v1/public/workspaces/YOUR_WORKSPACE_ID/tracking/verify-script" \
  -H "Authorization: Bearer ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "url": "acme.com/pricing"
}'

Example response

200 OK
{
  "success": true,
  "data": {
    "is_installed": true,
    "message": "...",
    "checked_url": "https://acme.com/pricing",
    "caveat": "..."
  }
}

Shown with the keys documented here; the check may return more.

POST/tracking/detect-stack

Detect the website stack

Detects the CMS of a site and the form builders on up to five pages, with instructions for each.

Scope tracking

Request body

urlstring
required

Max 2048.

form_urlsstring[]
optional

At most 5 items, each max 2048. Defaults to [url].

Example request

curl
curl -X POST "https://api.leadjourney.io/api/v1/public/workspaces/YOUR_WORKSPACE_ID/tracking/detect-stack" \
  -H "Authorization: Bearer ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "url": "https://acme.com",
  "form_urls": [
    "https://acme.com/contact"
  ]
}'

Example response

200 OK
{
  "success": true,
  "data": {
    "url": "https://acme.com",
    "cms": "...",
    "cms_error": null,
    "note": "...",
    "form_builders": [
      {
        "url": "https://acme.com/contact",
        "builder": "...",
        "has_form": true,
        "has_lj_clickid": false,
        "instructions": "...",
        "details": "...",
        "knowledge_base_url": "..."
      }
    ]
  }
}

A form_builders item carries error when that page could not be checked.

GET/tracking/crm-webhook-info

Get the CRM webhook details

The postback URL and secret, the parameters a CRM webhook sends, an example payload, the affiliate networks and the CRM's instructions. The answer contains the workspace's postback secret: treat it like a password.

Scope tracking

Query parameters

crmstring
optional

Max 100. Selects which CRM's instructions are returned.

Example request

curl
curl "https://api.leadjourney.io/api/v1/public/workspaces/YOUR_WORKSPACE_ID/tracking/crm-webhook-info?crm=hubspot" \
  -H "Authorization: Bearer ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

Example response

200 OK
{
  "success": true,
  "data": {
    "postback_url": "...",
    "postback_secret": "<postback secret>",
    "authentication": {
      "method": "...",
      "header_example": "...",
      "query_example": "..."
    },
    "parameters": {
      "required_one_of": [
        "..."
      ],
      "required": [
        "..."
      ],
      "optional": [
        "..."
      ]
    },
    "conversion_types": [
      "..."
    ],
    "example_payload": {
      "...": "..."
    },
    "affiliate_networks": [
      {
        "slug": "...",
        "label": "...",
        "postback_url": "...",
        "configured": false,
        "sources": [
          {
            "name": "...",
            "api_key": "<api key>"
          }
        ]
      }
    ],
    "crm_instructions": "..."
  }
}

Traffic channels, UTM & short links

Custom traffic channels, tracking link templates per channel, and short links on a verified tracking domain. Scope: traffic_channels.

GET/traffic-channels

List traffic channels

Lists the workspace's traffic channels, built-in and custom, ordered by order. Deleted channels are left out.

Scope traffic_channels

Query parameters

pageinteger
optional

Page number. Defaults to 1, minimum 1.

per_pageinteger
optional

Items per page. Defaults to 20, maximum 50. A larger value is clamped to 50, a value below 1 falls back to 20.

Example request

curl
curl "https://api.leadjourney.io/api/v1/public/workspaces/YOUR_WORKSPACE_ID/traffic-channels" \
  -H "Authorization: Bearer ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

Example response

200 OK
{
  "success": true,
  "data": [
    {
      "id": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
      "key": "close_crm",
      "label": "Close CRM",
      "description": "Leads from Close's referral links",
      "type": "other",
      "is_active": true,
      "is_custom": true,
      "referrer_domains": [
        "close.com"
      ],
      "order": 12
    }
  ],
  "meta": {
    "current_page": 1,
    "per_page": 20,
    "last_page": 1,
    "total": 1,
    "max_per_page": 50
  }
}
POST/traffic-channels

Create a traffic channel

Creates a custom traffic channel. Its key is derived from the label: snake case, lower case.

Scope traffic_channels

Request body

labelstring
required

Max 255.

descriptionstring
optional

Max 1000.

traffic_channel_typestring
required

The channel's type.

Allowed: paid, organic_search, ai_search, organic_social, other

referrer_domainsstring[]
optional

At most 20, each max 255 and a valid domain such as close.com.

Errors

422key_conflict

The derived key collides with a built-in key, or a channel with that name exists.

422referrer_conflict

Another channel already claims one of the domains.

Example request

curl
curl -X POST "https://api.leadjourney.io/api/v1/public/workspaces/YOUR_WORKSPACE_ID/traffic-channels" \
  -H "Authorization: Bearer ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "label": "Close CRM",
  "traffic_channel_type": "other",
  "referrer_domains": [
    "close.com"
  ]
}'

Example response

201 Created
{
  "success": true,
  "data": {
    "id": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
    "key": "close_crm",
    "label": "Close CRM",
    "type": "other",
    "is_active": true,
    "is_custom": true,
    "referrer_domains": [
      "close.com"
    ],
    "next_step": "..."
  }
}
PATCH/traffic-channels/{channel}

Update a traffic channel

Changes a channel. On a built-in channel only is_active can change. Renaming re-derives the key, and links published with the old key are no longer classified.

Scope traffic_channels

Path parameters

channeluuid
required

Channel id.

Request body

labelstring
optional

Max 255. Renaming re-derives the key.

descriptionstring
optional

Max 1000.

traffic_channel_typestring
optional

The channel's type.

Allowed: paid, organic_search, ai_search, organic_social, other

is_activeboolean
optional

The one field a built-in channel accepts.

referrer_domainsstring[]
optional

Replaces the whole list; [] clears it. Same limits as on create.

Renaming a channel re-derives its key. The answer's note warns that links published with the old key will no longer be classified.

Errors

404not_found

The channel is not in this workspace.

422built_in_channel

Anything other than is_active was sent for a built-in channel.

422key_conflict

The new key collides with an existing one.

422referrer_conflict

Another channel already claims one of the domains.

422invalid_request

Nothing to change.

Example request

curl
curl -X PATCH "https://api.leadjourney.io/api/v1/public/workspaces/YOUR_WORKSPACE_ID/traffic-channels/CHANNEL_ID" \
  -H "Authorization: Bearer ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "is_active": false
}'

Example response

200 OK
{
  "success": true,
  "data": {
    "id": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
    "key": "close_crm",
    "label": "Close CRM",
    "type": "other",
    "is_active": false,
    "is_custom": true,
    "referrer_domains": [
      "close.com"
    ],
    "note": null
  }
}
DELETE/traffic-channels/{channel}

Delete a traffic channel

Soft deletes a custom channel. Built-in channels cannot be deleted.

Scope traffic_channels

Path parameters

channeluuid
required

Channel id.

Request body

confirmboolean
required

Must be true. Read from the body or the query string.

Destructive. Requires confirm: true, otherwise 409 confirmation_required.

Errors

404not_found

The channel is not in this workspace.

409confirmation_required

confirm: true was not sent.

422built_in_channel

The channel is built in.

Example request

curl
curl -X DELETE "https://api.leadjourney.io/api/v1/public/workspaces/YOUR_WORKSPACE_ID/traffic-channels/CHANNEL_ID" \
  -H "Authorization: Bearer ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "confirm": true
}'

Example response

200 OK
{
  "success": true,
  "data": {
    "id": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
    "key": "close_crm",
    "label": "Close CRM",
    "deleted": true
  }
}
GET/utm/channels

List link channels

Every channel a tracking link can be built for, by kind, with where its template goes. Not paginated.

Scope traffic_channels

Example request

curl
curl "https://api.leadjourney.io/api/v1/public/workspaces/YOUR_WORKSPACE_ID/utm/channels" \
  -H "Authorization: Bearer ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

Example response

200 OK
{
  "success": true,
  "data": {
    "paid": [
      {
        "channel": "meta_ads",
        "name": "Meta Ads",
        "kind": "paid",
        "where_to_add": "..."
      }
    ],
    "organic": [
      {
        "channel": "linkedin_organic",
        "name": "LinkedIn",
        "kind": "organic",
        "default_source": "...",
        "default_medium": "...",
        "suggested_contexts": [
          "..."
        ]
      }
    ],
    "email": {
      "channel": "email",
      "kind": "email",
      "merge_tag_tools": [
        "mailchimp",
        "..."
      ],
      "note": "..."
    },
    "fixed": [
      {
        "channel": "gmb",
        "name": "Google Business Profile",
        "kind": "fixed",
        "lj_channel": "gmb",
        "where_to_add": "..."
      }
    ],
    "custom": [
      {
        "channel": "close_crm",
        "name": "Close CRM",
        "kind": "custom"
      }
    ]
  }
}

Lists shortened. paid: meta_ads, linkedin_ads, google_ads, bing_ads, reddit_ads, x_ads, taboola_ads, outbrain_ads, tiktok_ads, chatgpt_ads. organic: linkedin_organic, youtube_organic, facebook_organic, instagram_organic, tiktok_organic, pinterest_organic, snapchat_organic. fixed: gmb. custom: the workspace's own channels.

POST/utm/build

Build a tracking link

Builds the tracking parameters or the full link for a channel. Pure computation, nothing is stored. The answer's shape depends on the channel's kind.

Scope traffic_channels

Request body

channelstring
required

Max 190. A channel from /utm/channels.

destination_urlstring
optional

A URL, max 2048. Ignored for paid channels.

with_utmboolean
optional

Paid channels only. Defaults to true: adds utm parameters to the platform's lj parameters.

campaignstring
optional

Max 190. Becomes utm_campaign, or lj_c_id on fixed and custom channels.

contentstring
optional

Max 190. Becomes utm_content, or lj_ad_id on fixed and custom channels.

termstring
optional

Max 190. Becomes utm_term, or lj_as_id on fixed and custom channels.

mediumstring
optional

Max 190. Becomes utm_medium, or lj_placement on fixed and custom channels.

sourcestring
optional

Max 190. Becomes utm_source.

email_toolstring
optional

Email channel: sets the email parameter to this tool's merge tag.

Allowed: activecampaign, aweber, brevo, cleverreach, clickfunnels, convertkit, drip, everwebinar, getresponse, hubspot, intercom, kajabi, kartra, keap, klaviyo, lemlist, mailchimp, maropost, omnisend, ontraport, sendgrid, sendlane, sendy

Errors

422unknown_channel

The channel is not one of /utm/channels.

Example request

curl
curl -X POST "https://api.leadjourney.io/api/v1/public/workspaces/YOUR_WORKSPACE_ID/utm/build" \
  -H "Authorization: Bearer ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "channel": "linkedin_organic",
  "destination_url": "https://acme.com/webinar",
  "campaign": "october-webinar"
}'

Example response

200 OK
{
  "success": true,
  "data": {
    "channel": "linkedin_organic",
    "kind": "organic",
    "parameters": {
      "utm_source": "...",
      "utm_medium": "...",
      "utm_campaign": "october-webinar"
    },
    "url": "https://acme.com/webinar?utm_source=...&utm_medium=...&utm_campaign=october-webinar",
    "suggested_contexts": [
      "..."
    ]
  }
}

By kind. paid: { channel, kind, template, destination_url: null, where_to_add, note }, template being the platform's lj parameters plus utm ones when with_utm is true. organic: { channel, kind, parameters, url, suggested_contexts }. email: { channel, kind, parameters, url, note }, utm_source defaulting to email. fixed and custom: { channel, kind, parameters, url }, fixed adding where_to_add and note; the channel becomes lj_channel.

API tokens

List, create and revoke the workspace's API tokens over the API itself. Scope: tokens.

GET/api-tokens

List API tokens

Lists the workspace's tokens, newest first. is_current marks the token making the request.

Scope tokens

Query parameters

pageinteger
optional

Page number. Defaults to 1, minimum 1.

per_pageinteger
optional

Items per page. Defaults to 20, maximum 50. A larger value is clamped to 50, a value below 1 falls back to 20.

Example request

curl
curl "https://api.leadjourney.io/api/v1/public/workspaces/YOUR_WORKSPACE_ID/api-tokens" \
  -H "Authorization: Bearer ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

Example response

200 OK
{
  "success": true,
  "data": [
    {
      "id": "e5f6a7b8-c9d0-4e1f-8a2b-3c4d5e6f7a8b",
      "name": "Reporting script",
      "last_four": "XXXX",
      "scopes": [
        "reports",
        "leads"
      ],
      "active": true,
      "last_used_at": "2026-10-24T17:40:00Z",
      "expires_at": "2027-10-01T23:59:59Z",
      "revoked_at": null,
      "created_at": "2026-10-01T09:00:00Z",
      "is_current": true
    }
  ],
  "meta": {
    "current_page": 1,
    "per_page": 20,
    "last_page": 1,
    "total": 1,
    "max_per_page": 50
  }
}

The hash and the plaintext never appear here.

POST/api-tokens

Create an API token

Mints a token for this workspace. The plaintext is in the answer once and never again. A token can only grant scopes the acting token holds.

Scope tokens

Request body

namestring
required

Max 255.

scopesstring[]
required

At least one valid scope.

Allowed: reports, tags, leads, tracking, traffic_channels, agency.workspaces, tokens

expires_atdate
optional

After now and at most 360 days ahead. Left out, the token never expires.

The plaintext token is returned once, in this answer. Store it before you do anything else.

Errors

403scope_escalation

A requested scope is one the acting token does not hold.

403scope_unavailable

agency.workspaces on a workspace that is not an agency HQ.

422token_limit_reached

The workspace already has 5 active tokens.

Example request

curl
curl -X POST "https://api.leadjourney.io/api/v1/public/workspaces/YOUR_WORKSPACE_ID/api-tokens" \
  -H "Authorization: Bearer ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Reporting script",
  "scopes": [
    "reports",
    "leads"
  ],
  "expires_at": "2027-10-01"
}'

Example response

201 Created
{
  "success": true,
  "data": {
    "token": "ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "warning": "...",
    "id": "e5f6a7b8-c9d0-4e1f-8a2b-3c4d5e6f7a8b",
    "name": "Reporting script",
    "last_four": "XXXX",
    "scopes": [
      "reports",
      "leads"
    ],
    "active": true,
    "last_used_at": "2026-10-24T17:40:00Z",
    "expires_at": "2027-10-01T23:59:59Z",
    "revoked_at": null,
    "created_at": "2026-10-01T09:00:00Z"
  }
}

created_by_user_id is copied from the token making the request.

DELETE/api-tokens/{token}

Revoke an API token

Revokes a token (it is kept with revoked_at set). A token may revoke itself; was_current says it did.

Scope tokens

Path parameters

tokenuuid
required

Token id.

Errors

404not_found

The token is not in this workspace.

Example request

curl
curl -X DELETE "https://api.leadjourney.io/api/v1/public/workspaces/YOUR_WORKSPACE_ID/api-tokens/TOKEN_ID" \
  -H "Authorization: Bearer ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

Example response

200 OK
{
  "success": true,
  "data": {
    "id": "e5f6a7b8-c9d0-4e1f-8a2b-3c4d5e6f7a8b",
    "name": "Reporting script",
    "last_four": "XXXX",
    "scopes": [
      "reports",
      "leads"
    ],
    "active": false,
    "last_used_at": "2026-10-24T17:40:00Z",
    "expires_at": "2027-10-01T23:59:59Z",
    "revoked_at": "2026-10-25T10:00:00Z",
    "created_at": "2026-10-01T09:00:00Z",
    "was_current": false
  }
}

Agency client workspaces

List an agency's client workspaces and create new ones, each with its own provisioning token. Scope: agency.workspaces, on the agency HQ workspace only.

GET/agency/workspaces

List client workspaces

Lists the agency's client workspaces and its plan quota. Not paginated. The answer contains each workspace's postback secret.

Scope agency.workspaces

Errors

409not_an_agency

The workspace has no agency owner.

409not_agency_hq

The workspace is not the agency HQ.

Example request

curl
curl "https://api.leadjourney.io/api/v1/public/workspaces/YOUR_WORKSPACE_ID/agency/workspaces" \
  -H "Authorization: Bearer ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

Example response

200 OK
{
  "success": true,
  "data": [
    {
      "id": "3a4b5c6d-7e8f-4091-a2b3-c4d5e6f70819",
      "name": "Client: Nordholm",
      "postback_secret": "<postback secret>",
      "role": "agency",
      "has_full_access": true,
      "permissions": [],
      "report_permissions": [],
      "allowed_traffic_channel_ids": [],
      "onboarding_required": true,
      "monthly_advertising_spend": null,
      "tracking_v2_enabled": true,
      "link_decoration_enabled": false,
      "cookieless_tracking_enabled": false,
      "affiliate_features_enabled": false,
      "call_tracking_enabled": false,
      "chat_tracking_enabled": false,
      "audience_sync_enabled": false,
      "automations_enabled": false,
      "meta_postback_mode_enabled": false,
      "postback_timing_enabled": false,
      "blocked": {
        "is_blocked": false,
        "type": null,
        "reason": null,
        "blocked_at": null
      },
      "trial": {
        "is_on_trial": false,
        "trial_expired": false,
        "trial_ends_at": null,
        "has_subscription": true
      }
    }
  ],
  "quota": {
    "used": 4,
    "allowed": 10,
    "is_unlimited": false,
    "remaining": 6,
    "within_quota": true
  }
}

role, has_full_access, permissions, report_permissions and allowed_traffic_channel_ids describe the agency's access to that workspace.

POST/agency/workspaces

Create a client workspace

Creates a real user account and workspace for a client, sends the invitation email and, by default, issues a provisioning token for it.

Scope agency.workspaces

Request body

workspace_namestring
required

Max 255.

first_namestring
required

Max 255.

last_namestring
required

Max 255.

emailstring
required

A deliverable address (checked against DNS). The invitation goes here.

phonestring
optional

Max 50.

issue_api_tokenboolean
optional

Defaults to true: the answer carries a provisioning token for the new workspace.

One creation every 30 minutes per agency HQ (the cooldown starts only after a successful creation), and the plan's workspace quota applies. The provisioning token is named Agency provisioning, carries every scope except agency.workspaces (tokens included) and expires in 360 days.

Errors

409not_an_agency

The workspace has no agency owner.

409not_agency_hq

The workspace is not the agency HQ.

429rate_limited

The 30 minute cooldown is running. Body carries scope: agency_workspace_creation and retry_after, plus a Retry-After header.

402plan_limit_reached

The plan's workspace quota is used up. Body: { message, error, limit, used, allowed }, with no success key. Until enforcement is switched on for the workspace the quota is recorded but not refused.

Example request

curl
curl -X POST "https://api.leadjourney.io/api/v1/public/workspaces/YOUR_WORKSPACE_ID/agency/workspaces" \
  -H "Authorization: Bearer ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "workspace_name": "Client: Nordholm",
  "first_name": "Jana",
  "last_name": "Lorenz",
  "email": "[email protected]"
}'

Example response

201 Created
{
  "success": true,
  "data": {
    "id": "3a4b5c6d-7e8f-4091-a2b3-c4d5e6f70819",
    "name": "Client: Nordholm",
    "...": "the workspace object, as in the list"
  },
  "api_token": {
    "token": "ljw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "warning": "...",
    "expires_in_days": 360,
    "id": "e5f6a7b8-c9d0-4e1f-8a2b-3c4d5e6f7a8b",
    "name": "Agency provisioning",
    "last_four": "XXXX",
    "scopes": [
      "reports",
      "tags",
      "leads",
      "tracking",
      "traffic_channels",
      "tokens"
    ],
    "active": true,
    "last_used_at": "2026-10-24T17:40:00Z",
    "expires_at": "2027-10-01T23:59:59Z",
    "revoked_at": null,
    "created_at": "2026-10-01T09:00:00Z"
  }
}

api_token is left out when issue_api_token is false.

19 endpoints

Integrations API (Zapier & legacy)

The API the LeadJourney Zapier app runs on. It authenticates with a user token from Settings, then API & Integrations, which reaches every workspace that user can open, rather than a workspace token (ljw_) limited to one workspace and its scopes. Paths below are relative to the base URL https://api.leadjourney.io/api.

Base URL
https://api.leadjourney.io/api

Account

Identify the authenticated token and list the workspaces it can act on.

GET/v1/profile

Get the authenticated user

Returns the user that owns the API token. Used to validate a connection.

Requires Bearer token

Example request

curl
curl "https://api.leadjourney.io/api/v1/profile" \
  -H "Authorization: Bearer YOUR_TOKEN"

Example response

200 OK
{
  "success": true,
  "data": {
    "user": {
      "id": "9b1c0e2a-3f4d-4a6b-8c7e-1d2f3a4b5c6d",
      "email": "[email protected]",
      "has_verified_email": true,
      "current_workspace_id": "2f8a1b3c-4d5e-6f70-8192-a3b4c5d6e7f8"
    },
    "has_verified_email": true,
    "profile": {
      "first_name": "Jamie",
      "last_name": "Rivera",
      "company_name": "Acme Inc.",
      "phone": "+15551234567"
    },
    "user_hash": "a1b2c3d4e5f6"
  }
}
GET/v1/profile/workspaces

List accessible workspaces

Lists every workspace the token can act on. The workspace id is used in the path of all workspace-scoped endpoints.

Requires Bearer token

Example request

curl
curl "https://api.leadjourney.io/api/v1/profile/workspaces" \
  -H "Authorization: Bearer YOUR_TOKEN"

Example response

200 OK
{
  "success": true,
  "data": {
    "workspaces": [
      {
        "id": "2f8a1b3c-4d5e-6f70-8192-a3b4c5d6e7f8",
        "name": "Acme Marketing",
        "role": "owner",
        "has_full_access": true,
        "onboarding_required": false,
        "tracking_v2_enabled": true,
        "trial": {
          "is_on_trial": false,
          "trial_expired": false,
          "trial_ends_at": null,
          "has_subscription": true
        }
      }
    ]
  }
}

Conversions & leads

Read conversion types and push leads or revenue conversions into a workspace.

GET/v1/workspaces/{workspace}/conversions

List conversion types

Returns the conversion types defined in the workspace.

Requires Bearer token

Path parameters

workspaceuuid
required

Workspace id.

Example request

curl
curl "https://api.leadjourney.io/api/v1/workspaces/YOUR_WORKSPACE_ID/conversions" \
  -H "Authorization: Bearer YOUR_TOKEN"

Example response

200 OK
{
  "success": true,
  "data": {
    "conversions": [
      {
        "id": "7c9e6a1b-2d3f-4051-8627-a8b9c0d1e2f3",
        "type": "Purchase",
        "default_key": null,
        "category": "Sales",
        "mode": 1,
        "send_to_ads": true,
        "include_revenue": true,
        "include_personal_details": false,
        "created_at": "2026-05-01T10:15:00Z",
        "events_count": 128,
        "latest_event_at": "2026-06-08T19:02:11Z"
      }
    ]
  }
}
POST/v1/workspaces/{workspace}/conversions

Create a conversion type

Creates a new conversion type in the workspace.

Requires Bearer token

Path parameters

workspaceuuid
required

Workspace id.

Request body

typestring
required

Conversion type name. Minimum 2 characters, unique per workspace.

modeinteger
required

Handling mode: 1 = create, 2 = ignore, 3 = edit, 4 = keep.

Allowed: 1, 2, 3, 4

send_to_adsboolean
optional

Forward matching conversions to connected ad platforms.

descriptionstring
optional

Free-text description. Max 255 characters.

categorystring
optional

Optional grouping category. Max 100 characters.

include_revenueboolean
optional

Whether conversions of this type carry revenue.

include_personal_detailsboolean
optional

Whether personal details are captured with this conversion.

Example request

curl
curl -X POST "https://api.leadjourney.io/api/v1/workspaces/YOUR_WORKSPACE_ID/conversions" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "type": "<type>",
  "mode": "1"
}'

Example response

200 OK
{
  "success": true
}
POST/v1/workspaces/{workspace}/conversions/track

Track a conversion

Records a conversion event against a lead. The lead is resolved by click_id, then email, then phone, creating a synthetic lead when none matches. Provide a type to record a conversion, or a tag to only apply a webhook tag.

Requires Bearer token

Path parameters

workspaceuuid
required

Workspace id.

Request body

click_iduuid
conditional

LeadJourney click id. One of click_id, email, or phone is required.

emailstring
conditional

Lead email. Max 255 characters.

phonestring
conditional

Lead phone. Max 50 characters.

typestring
conditional

Conversion type name. Required unless a tag is provided.

revenuestring
conditional

Revenue amount. Required when the conversion type carries revenue.

cash_collectedstring
optional

Cash collected amount.

currencystring
optional

ISO 4217 currency code (3 letters), e.g. USD.

first_namestring
optional

First name. Max 255 characters.

last_namestring
optional

Last name. Max 255 characters.

full_namestring
optional

Full name. Split into first/last when those are absent. Max 511 characters.

tagstring
optional

Tag name to apply when no conversion type is sent. Max 50 characters.

zipstring
optional

Postal code. Max 20 characters.

custom_fieldsobject
optional

Key-value pairs validated against the workspace custom fields.

At least one of click_id, email, or phone must identify the lead.

Example request

curl
curl -X POST "https://api.leadjourney.io/api/v1/workspaces/YOUR_WORKSPACE_ID/conversions/track" \
  -H "Authorization: Bearer YOUR_TOKEN"

Example response

200 OK
{
  "success": true
}
POST/v1/workspaces/{workspace}/conversions/track-lead

Track a lead

Captures a lead's identity without a revenue conversion, using the workspace default lead conversion. Resolution and de-duplication run downstream.

Requires Bearer token

Path parameters

workspaceuuid
required

Workspace id.

Request body

click_iduuid
conditional

LeadJourney click id. One of click_id, email, or phone is required.

emailstring
conditional

Lead email. Max 255 characters.

phonestring
conditional

Lead phone. Max 50 characters.

first_namestring
optional

First name. Max 255 characters.

last_namestring
optional

Last name. Max 255 characters.

full_namestring
optional

Full name. Split into first/last when those are absent. Max 511 characters.

zipstring
optional

Postal code. Max 20 characters.

At least one of email, phone, or click_id must be provided.

Example request

curl
curl -X POST "https://api.leadjourney.io/api/v1/workspaces/YOUR_WORKSPACE_ID/conversions/track-lead" \
  -H "Authorization: Bearer YOUR_TOKEN"

Example response

200 OK
{
  "success": true
}

Tags

Manage tags and apply them to individual leads.

GET/v1/workspaces/{workspace}/tags

List tags

Returns the tags defined in the workspace, with their rules.

Requires Bearer token

Path parameters

workspaceuuid
required

Workspace id.

Example request

curl
curl "https://api.leadjourney.io/api/v1/workspaces/YOUR_WORKSPACE_ID/tags" \
  -H "Authorization: Bearer YOUR_TOKEN"

Example response

200 OK
{
  "success": true,
  "data": {
    "tags": [
      {
        "id": "a1f2e3d4-5c6b-7a89-90b1-c2d3e4f5a6b7",
        "name": "Newsletter",
        "type": "source",
        "color": "#03c879",
        "rules": [],
        "created_at": "2026-04-12T08:00:00Z",
        "updated_at": "2026-04-12T08:00:00Z"
      }
    ]
  }
}
POST/v1/workspaces/{workspace}/tags

Create a tag

Creates a tag, optionally with auto-apply rules.

Requires Bearer token

Path parameters

workspaceuuid
required

Workspace id.

Request body

namestring
required

Tag name. 1 to 50 characters.

typestring
required

Tag type.

Allowed: source, entry, action, lead, lead_type, product, funnel

colorstring
optional

Hex color (#RRGGBB). Defaults to #03c879.

rule_logicstring
optional

How rules combine. Defaults to and.

Allowed: and, or

rulesarray
optional

Auto-apply rules. Each rule has field (entry_page | entry_full_url | referrer_domain), operator (contains | equals | starts_with | ends_with | not_contains), value, optional timing (anytime | before_conversion), timing_event, and is_active.

apply_to_existingboolean
optional

Apply the tag to existing leads matching the rules.

Example request

curl
curl -X POST "https://api.leadjourney.io/api/v1/workspaces/YOUR_WORKSPACE_ID/tags" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "<name>",
  "type": "source"
}'

Example response

200 OK
{
  "success": true,
  "data": {
    "tag": {
      "id": "a1f2e3d4-5c6b-7a89-90b1-c2d3e4f5a6b7",
      "name": "VIP",
      "type": "lead",
      "color": "#03c879",
      "rules": [],
      "created_at": "2026-06-09T12:00:00Z",
      "updated_at": "2026-06-09T12:00:00Z"
    }
  }
}
POST/v1/workspaces/{workspace}/zapier/leads/{lead}/tags/{tag}

Apply a tag to a lead

Attaches an existing tag to an existing lead.

Requires Bearer token

Path parameters

workspaceuuid
required

Workspace id.

leaduuid
required

Lead id.

taguuid
required

Tag id.

Example request

curl
curl -X POST "https://api.leadjourney.io/api/v1/workspaces/YOUR_WORKSPACE_ID/zapier/leads/LEAD_ID/tags/TAG_ID" \
  -H "Authorization: Bearer YOUR_TOKEN"

Example response

200 OK
{
  "success": true,
  "data": {
    "message": "Tag assigned successfully"
  }
}

Custom fields

Read, create, update and delete the custom fields stored on each lead.

GET/v1/workspaces/{workspace}/custom-fields

List custom fields

Returns the custom fields defined in the workspace.

Requires Bearer token

Path parameters

workspaceuuid
required

Workspace id.

Example request

curl
curl "https://api.leadjourney.io/api/v1/workspaces/YOUR_WORKSPACE_ID/custom-fields" \
  -H "Authorization: Bearer YOUR_TOKEN"

Example response

200 OK
{
  "success": true,
  "data": {
    "custom_fields": [
      {
        "id": 14,
        "name": "Plan",
        "key": "plan",
        "type": "text",
        "available_in_reports": true,
        "is_default": false,
        "is_locked": false,
        "sort_order": 3,
        "created_at": "2026-03-20T09:30:00Z",
        "updated_at": "2026-03-20T09:30:00Z"
      }
    ]
  }
}
POST/v1/workspaces/{workspace}/custom-fields

Create a custom field

Creates a custom field. Up to 50 user-defined fields per workspace.

Requires Bearer token

Path parameters

workspaceuuid
required

Workspace id.

Request body

namestring
required

Display name. 1 to 80 characters.

typestring
required

Field data type.

Allowed: text, number, currency

keystring
optional

Webhook key (lowercase, starts with a letter, max 64, unique). Auto-generated from name when omitted.

available_in_reportsboolean
optional

Show the field in reports. Defaults to true.

Example request

curl
curl -X POST "https://api.leadjourney.io/api/v1/workspaces/YOUR_WORKSPACE_ID/custom-fields" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "<name>",
  "type": "text"
}'

Example response

200 OK
{
  "success": true,
  "data": {
    "custom_field": {
      "id": 21,
      "name": "Plan",
      "key": "plan",
      "type": "text",
      "available_in_reports": true,
      "is_default": false,
      "is_locked": false,
      "sort_order": 4,
      "created_at": "2026-06-09T12:00:00Z",
      "updated_at": "2026-06-09T12:00:00Z"
    }
  }
}
POST/v1/workspaces/{workspace}/custom-fields/{customField}

Update a custom field

Updates a custom field's name, type or report visibility. The key cannot be changed.

Requires Bearer token

Path parameters

workspaceuuid
required

Workspace id.

customFieldinteger
required

Custom field id.

Request body

namestring
optional

Display name. 1 to 80 characters.

typestring
optional

Field data type.

Allowed: text, number, currency

available_in_reportsboolean
optional

Show the field in reports.

Every field is optional. The key cannot be changed.

Errors

403

Fields managed by LeadJourney (is_locked: true): {"message": "This custom field is managed by LeadJourney and cannot be edited."}

Example request

curl
curl -X POST "https://api.leadjourney.io/api/v1/workspaces/YOUR_WORKSPACE_ID/custom-fields/CUSTOM_FIELD_ID" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Plan tier",
  "available_in_reports": false
}'

Example response

200 OK
{
  "success": true,
  "data": {
    "custom_field": {
      "id": 21,
      "name": "Plan tier",
      "key": "plan",
      "type": "text",
      "available_in_reports": false,
      "is_default": false,
      "is_locked": false,
      "sort_order": 4,
      "created_at": "2026-06-09T12:00:00Z",
      "updated_at": "2026-06-10T08:30:00Z"
    }
  }
}
DELETE/v1/workspaces/{workspace}/custom-fields/{customField}

Delete a custom field

Deletes a custom field from the workspace.

Requires Bearer token

Path parameters

workspaceuuid
required

Workspace id.

customFieldinteger
required

Custom field id.

Errors

403

Fields managed by LeadJourney (is_locked: true): {"message": "This custom field is managed by LeadJourney and cannot be deleted."}

404

The field belongs to another workspace.

Example request

curl
curl -X DELETE "https://api.leadjourney.io/api/v1/workspaces/YOUR_WORKSPACE_ID/custom-fields/CUSTOM_FIELD_ID" \
  -H "Authorization: Bearer YOUR_TOKEN"

Example response

The body of a successful delete is not documented here.

Lead lookup

Find a single lead by click id, email, or phone.

GET/v1/workspaces/{workspace}/zapier/leads/find

Find a lead

Looks up a single lead by click id, email, or phone. Returns null in data.lead when no match is found.

Requires Bearer token

Path parameters

workspaceuuid
required

Workspace id.

Query parameters

click_idstring
optional

LeadJourney click id. One of click_id, email, or phone is required.

emailstring
optional

Lead email.

phonestring
optional

Lead phone.

Example request

curl
curl "https://api.leadjourney.io/api/v1/workspaces/YOUR_WORKSPACE_ID/zapier/leads/find" \
  -H "Authorization: Bearer YOUR_TOKEN"

Example response

200 OK
{
  "success": true,
  "data": {
    "lead": {
      "id": "5d6e7f80-1a2b-3c4d-5e6f-708192a3b4c5",
      "click_id": "0c1d2e3f-4a5b-6c7d-8e9f-a0b1c2d3e4f5",
      "email": "[email protected]",
      "phone": null,
      "first_name": "Sam",
      "last_name": "Lee",
      "created_at": "2026-06-01T14:22:00Z",
      "revenue": 199,
      "conversions_count": 2,
      "first_source": "google",
      "last_source": "email",
      "status": "converted",
      "tags": [
        {
          "id": "a1f2e3d4-5c6b-7a89-90b1-c2d3e4f5a6b7",
          "name": "Newsletter",
          "color": "#03c879",
          "type": "source",
          "source": "rule"
        }
      ],
      "custom_fields": {
        "plan": "pro"
      }
    }
  }
}

Webhooks (REST hooks)

Subscribe and unsubscribe webhook targets. Zapier uses these to power instant triggers.

POST/v1/workspaces/{workspace}/zapier/subscriptions

Create a webhook subscription

Registers a target URL to receive events. The response id is used to unsubscribe.

Requires Bearer token

Path parameters

workspaceuuid
required

Workspace id.

Request body

eventstring
required

Event to subscribe to.

Allowed: lead.created, conversion.created, click.created

target_urlstring
required

HTTPS URL that receives the event payload. Max 2048 characters.

Example request

curl
curl -X POST "https://api.leadjourney.io/api/v1/workspaces/YOUR_WORKSPACE_ID/zapier/subscriptions" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "event": "lead.created",
  "target_url": "<target_url>"
}'

Example response

200 OK
{
  "success": true,
  "data": {
    "id": "9f8e7d6c-5b4a-3210-fedc-ba9876543210"
  }
}
DELETE/v1/workspaces/{workspace}/zapier/subscriptions/{subscription}

Delete a webhook subscription

Removes a webhook subscription by id.

Requires Bearer token

Path parameters

workspaceuuid
required

Workspace id.

subscriptionuuid
required

Subscription id returned when it was created.

Example request

curl
curl -X DELETE "https://api.leadjourney.io/api/v1/workspaces/YOUR_WORKSPACE_ID/zapier/subscriptions/SUBSCRIPTION_ID" \
  -H "Authorization: Bearer YOUR_TOKEN"

Example response

200 OK
{
  "success": true
}

Recent items (polling)

Most recent items per type. Used for trigger sample data and as a polling fallback.

GET/v1/workspaces/{workspace}/zapier/recent/leads

Recent leads

Returns the most recent leads. Used for trigger sample data and polling.

Requires Bearer token

Path parameters

workspaceuuid
required

Workspace id.

Example request

curl
curl "https://api.leadjourney.io/api/v1/workspaces/YOUR_WORKSPACE_ID/zapier/recent/leads" \
  -H "Authorization: Bearer YOUR_TOKEN"

Example response

200 OK
{
  "success": true,
  "data": {
    "leads": [
      {
        "id": "5d6e7f80-1a2b-3c4d-5e6f-708192a3b4c5",
        "click_id": "0c1d2e3f-4a5b-6c7d-8e9f-a0b1c2d3e4f5",
        "email": "[email protected]",
        "phone": null,
        "first_name": "Sam",
        "last_name": "Lee",
        "created_at": "2026-06-08T14:22:00Z",
        "revenue": 199,
        "conversions_count": 2,
        "first_source": "google",
        "last_source": "email",
        "status": "converted",
        "tags": []
      }
    ]
  }
}
GET/v1/workspaces/{workspace}/zapier/recent/conversions

Recent conversions

Returns the most recent conversion events.

Requires Bearer token

Path parameters

workspaceuuid
required

Workspace id.

Example request

curl
curl "https://api.leadjourney.io/api/v1/workspaces/YOUR_WORKSPACE_ID/zapier/recent/conversions" \
  -H "Authorization: Bearer YOUR_TOKEN"

Example response

200 OK
{
  "success": true,
  "data": {
    "conversions": [
      {
        "id": "11223344-5566-7788-99aa-bbccddeeff00",
        "click_id": "0c1d2e3f-4a5b-6c7d-8e9f-a0b1c2d3e4f5",
        "email": "[email protected]",
        "phone": null,
        "conversion_type": "Purchase",
        "revenue": 199,
        "currency": "USD",
        "first_name": "Sam",
        "last_name": "Lee",
        "created_at": "2026-06-08T15:10:00Z"
      }
    ]
  }
}
GET/v1/workspaces/{workspace}/zapier/recent/clicks

Recent clicks

Returns the most recent click and pageview events.

Requires Bearer token

Path parameters

workspaceuuid
required

Workspace id.

Example request

curl
curl "https://api.leadjourney.io/api/v1/workspaces/YOUR_WORKSPACE_ID/zapier/recent/clicks" \
  -H "Authorization: Bearer YOUR_TOKEN"

Example response

200 OK
{
  "success": true,
  "data": {
    "clicks": [
      {
        "id": "aa00bb11-cc22-dd33-ee44-ff5566778899",
        "click_id": "0c1d2e3f-4a5b-6c7d-8e9f-a0b1c2d3e4f5",
        "entry_page": "/pricing",
        "entry_full_url": "https://acme.com/pricing?utm_source=email",
        "referer": "https://mail.google.com/",
        "source": "email",
        "campaign": "june-newsletter",
        "created_at": "2026-06-08T13:05:00Z"
      }
    ]
  }
}