Skip to content

Endpoint index

Generated from openapi.yaml. Base URL: https://apiv2.lagrowthmachine.com/flow. Authenticate with Authorization: Bearer YOUR_API_KEY.

Get Campaigns

Use this endpoint to retrieve all your campaigns, with their status, audience, sending identity and a few key metrics.

This endpoint supports pagination using the skip and limit query parameters:

  • limit → number of items to return (required, 25 maximum)
  • skip → number of items to skip (used to navigate pages)

Examples:

  • Page 1 → ?skip=0&limit=25
  • Page 2 → ?skip=25&limit=25
  • Page 3 → ?skip=50&limit=25

You can adjust these values depending on your pagination logic. total in the response is the number of campaigns matching your filters, use it to know when to stop.

Campaigns are returned prioritised campaigns first, then by status (RUNNING, PAUSED, READY, CANCELED), then most recently launched first. When you filter on status=READY only, they are sorted by last modification date instead.

  • status: one or several statuses, comma-separated (?status=RUNNING,PAUSED).
  • search: case-insensitive match on the campaign name.

Any other query parameter is rejected with a 404 error.

Each item contains the fields documented below. Other internal fields may be present: they are not part of the contract and can change without notice. To read the settings of one campaign (autoRescheduleOutOfOffice, ignoreEmojiOnlyReply…), use Get Campaign.

Parameter In Required Description
limit query yes Number of campaigns to return (25 max).
skip query no Number of campaigns to skip (0 minimum).
status query no Comma-separated list of statuses to keep, among RUNNING, READY, PAUSED, CANCELED. Values are not validated, an unknown status simply matches nothing.
search query no Case-insensitive search on the campaign name.

Response 200:

{
"statusCode": 200,
"campaigns": [
{
"id": "64b7f0c2a1d300000000000b",
"name": "Email Only - 1 Follow-up 1 1",
"description": "",
"objective": null,
"language": "english",
"createdAt": 1791192988271,
"modifiedAt": 1791192988273,
"userId": "64b7f0c2a1d3000000000003",
"status": "READY",
"identity": {
"id": "64b7f0c2a1d3000000000004",
"firstname": "John",
"lastname": "Doe",
"gender": null,
"jobTitle": null,
"profilePicture": null
},
"launchedByMemberId": null,
"launchedAt": null,
"channels": [
"LGM",
"LINKEDIN",
"GOOGLE"
],
"slotIds": [],
"hubspot": false,
"pipedrive": false,
"enrich": false,
"isShared": false,
"accessCode": null,
"isHiddenTemplate": false,
"alternateFrom": null,
"crmSettings": {
"exclusionEnabled": false,
"excludedListIds": [],
"pauseIfCrmHasDeal": false,
"pauseOnLifecycleChange": {
"enabled": false,
"targetStages": []
},
"pauseIfInDynamicList": {
"enabled": false,
"listIds": []
}
},
"autoRescheduleOutOfOffice": false,
"lastActivity": null,
"isPrioritised": false,
"ctaBoost": null,
"categoryIsAuto": null,
"categoryIsLoading": null,
"leadsCount": 0,
"replyRatePercent": 0
}
],
"total": 1
}

Errors: 401, 404, 429, 500.

Get Public Campaigns

Lists the ready-made campaigns anyone can copy with Duplicate Campaign. The duplicated campaign has no audience and no sending identity yet: set them before launching it.

Each item has an origin:

  • catalog: official LGM strategy templates (sequence architectures such as “LinkedIn > Email - 3 Follow-ups”).
  • creators: use-case templates shared by LGM or by other LGM users. They only appear with type=public.

Use type to choose the set:

  • public (default): the full list, catalog then creators.
  • recommended: a short curated catalog shortlist, the usual starting point.
  • featured: catalog campaigns flagged as featured.

The list is not paginated. channels includes passive steps (a LinkedIn profile visit on an email sequence, for instance), so it does not tell which channel the sequence messages through; the description and name do.

Parameter In Required Description
type query no Which set of campaigns to return.

Response 200:

{
"statusCode": 200,
"campaigns": [
{
"id": "64b7f0c2a1d3000000000001",
"name": "Email Only - 1 Follow-up 1",
"description": "Simple Email outbound sequence, perfect if you want to keep it light and simple. Expect less conversion than multichannel sequences!",
"channels": [
"LGM",
"LINKEDIN",
"GOOGLE"
],
"tags": [
"HR"
],
"order": 14,
"origin": "catalog"
},
{
"id": "64b7f0c2a1d3000000000002",
"name": "Email > Linkedin - 1 Follow-ups 1",
"description": "Engage first via Emails, using LinkedIn only as a fallback. This sequence is perfect if you need to activate a high volume of leads per day",
"channels": [
"LGM",
"LINKEDIN",
"GOOGLE"
],
"tags": [
"OUTBOUND"
],
"order": 23,
"origin": "catalog"
},
{
"id": "64b7f0c2a1d3000000000003",
"name": "Email > Linkedin > Twitter - 2 Follow-ups 1",
"description": "Engage first via Emails, using LinkedIn as primary fallback, then Twitter if they haven’t replied. This sequence is perfect if you need to activate a high volume of leads per day.",
"channels": [
"LGM",
"LINKEDIN",
"GOOGLE"
],
"tags": [
"HR"
],
"order": 22,
"origin": "catalog"
}
]
}

Errors: 400, 401, 429, 500.

Get Campaign

Use this endpoint to get one campaign: its status, audience, sending identity and settings.

This endpoint takes no query parameter: any query parameter is rejected with a 404 error.

Parameter In Required Description
campaignId path yes Campaign ID (24-character hex string).

Response 200:

{
"statusCode": 200,
"campaign": {
"id": "64b7f0c2a1d300000000000b",
"name": "Email Only - 1 Follow-up 1 1",
"description": "",
"language": "english",
"createdAt": 1791192988271,
"modifiedAt": 1791192988273,
"launchedAt": null,
"userId": "64b7f0c2a1d3000000000003",
"status": "READY",
"channels": [
"LGM",
"LINKEDIN",
"GOOGLE"
],
"identityId": "64b7f0c2a1d3000000000004",
"identityFirstname": "John",
"identityLastname": "Doe",
"launchedByMemberId": null,
"converted": 0,
"activated": 0,
"hubspot": false,
"pipedrive": false,
"enrich": false,
"autoRescheduleOutOfOffice": true,
"ignoreEmojiOnlyReply": false,
"objective": null
}
}

Errors: 401, 404, 429, 500.

Get Campaign Stats

Use this endpoint to get the stats of one campaign: audience, replies, LinkedIn relations, per-channel metrics, lead statuses and per-message (template) metrics.

All ...Percent fields are integers between 0 and 100. If your plan does not include lead qualification, the detailed status.won and status.lost counters and percentages are returned as 0 (only their total is kept).

This endpoint takes no query parameter: any query parameter is rejected with a 404 error.

Parameter In Required Description
campaignId path yes Campaign ID (24-character hex string).

Response 200:

{
"statusCode": 200,
"engagementStats": {
"campaignId": "64b7f0c2a1d300000000000b",
"audienceSize": 0,
"notActivated": 0,
"converted": 0,
"completed": 0,
"started": 0,
"skipped": 0,
"skippedPercent": 0,
"replies": {
"contacted": 0,
"replied": 0,
"linkedinContacted": 0,
"emailContacted": 0,
"linkedinReplied": 0,
"emailReplied": 0,
"contactedPercent": 0,
"totalReplyPercent": 0,
"contactedReplyPercent": 0,
"linkedinContactedReplyPercent": 0,
"emailContactedReplyPercent": 0
},
"relations": {
"activated": true,
"requestSent": 0,
"relations": 0,
"newRelations": 0,
"alreadyConnected": 0,
"requestSentPercent": 0,
"relationsPercent": 0,
"totalRelationsPercent": 0,
"newRelationsPercent": 0,
"alreadyConnectedPercent": 0
},
"channel": {
"email": {
"activated": true,
"sent": 0,
"received": 0,
"opened": 0,
"replied": 0,
"clicked": 0,
"bounced": 0,
"won": 0,
"sentPercent": 0,
"receivedPercent": 0,
"openedPercent": 0,
"repliedPercent": 0,
"clickedPercent": 0,
"bouncedPercent": 0,
"wonPercent": 0
},
"linkedin": {
"activated": true,
"contactRequest": {
"activated": true,
"sent": 0,
"newRelations": 0,
"alreadyContact": 0,
"sentPercent": 0,
"newRelationsPercent": 0,
"alreadyContactPercent": 0
},
"message": {
"sent": 0,
"replied": 0,
"won": 0,
"sentPercent": 0,
"repliedPercent": 0,
"wonPercent": 0
}
},
"twitter": {
"activated": false,
"sent": 0,
"retweet": 0,
"favorited": 0,
"followed": 0,
"followBack": 0,
"followedPercent": 0,
"followBackPercent": 0
},
"enrich": {
"activated": false,
"proUpgrade": false,
"businessUpgrade": true,
"enriched": 0,
"found": {
"profile": 0,
"profileSearch": 0,
"website": 0,
"proEmail": 0,
"persoEmail": 0,
"phone": 0,
"companyPhone": 0,
"twitter": 0,
"profilePercent": 0,
"profileSearchPercent": 0,
"profileOnProfileSearchPercent": 0,
"websitePercent": 0,
"proEmailPercent": 0,
"persoEmailPercent": 0,
"phonePercent": 0,
"companyPhonePercent": 0,
"twitterPercent": 0
},
"enrichedPercent": 0
},
"call": {
"activated": false,
"contacted": 0,
"decisive": 0,
"unreachable": 0,
"won": 0,
"decisivePercent": 0,
"unreachablePercent": 0
}
},
"status": {
"activated": {
"total": 0,
"activated": 0,
"enriched": 0,
"contacted": 0,
"completed": 0,
"outOfOffice": 0,
"activatedPercent": 0,
"enrichedPercent": 0,
"contactedPercent": 0,
"completedPercent": 0,
"audiencePercent": 0,
"contactedAudiencePercent": 0,
"outOfOfficePercent": 0,
"notActivated": 0,
"notActivatedPercent": 0
},
"replied": {
"total": 0,
"toQualify": 0,
"wrongTiming": 0,
"toReview": 0,
"toCall": 0,
"inviteNote": 0,
"customMessage": 0,
"toQualifyPercent": 0,
"wrongTimingPercent": 0,
"audiencePercent": 0,
"activatedPercent": 0,
"contactedPercent": 0,
"toReviewPercent": 0,
"inviteNotePercent": 0,
"customMessagePercent": 0
},
"won": {
"total": 0,
"interested": 0,
"callBooked": 0,
"negotiating": 0,
"readyToBuy": 0,
"converted": 0,
"interestedPercent": 0,
"callBookedPercent": 0,
"negotiatingPercent": 0,
"readyToBuyPercent": 0,
"convertedPercent": 0,
"audiencePercent": 0,
"repliedPercent": 0
},
"lost": {
"total": 0,
"wrongTarget": 0,
"notInterested": 0,
"alreadyEquipped": 0,
"unsubscribed": 0,
"wrongTargetPercent": 0,
"notInterestedPercent": 0,
"alreadyEquippedPercent": 0,
"unsubscribedPercent": 0,
"audiencePercent": 0,
"repliedPercent": 0
}
},
"templates": [
{
"sent": 0,
"opened": 0,
"clicked": 0,
"replied": 0,
"bounced": 0,
"openedPercent": 0,
"clickedPercent": 0,
"repliedPercent": 0,
"bouncedPercent": 0,
"won": 0,
"channel": "GOOGLE",
"createdAt": 1791192988676,
"newHtml": "<p>Hi <var name=\"firstname\" default=\"there\"/>, a quick question about Acme.</p>",
"name": "GOOGLE message - step 4",
"subjectNewHtml": "",
"note": "",
"templateId": "64b7f0c2a1d300000000000d",
"type": "TEXT",
"position": 0,
"isCustomMessage": false
}
],
"objective": null
}
}

Errors: 401, 404, 429, 500.

Get Campaign Leads Stats

Use this endpoint to get the stats of every lead of one campaign: status in the campaign, LinkedIn relation, counts of emails, LinkedIn messages and tweets, and the lead tag.

Each request returns 25 leads maximum, most recently added leads first.

  • To get the first 25 leads, do not specify any query parameter.
  • To get the 25 next leads, use getLeadsAfter with the id of the last lead of the previous page (?getLeadsAfter=<lastLead.id>).
  • hasMore tells whether more leads follow, hasLess whether leads precede the first one returned. count is the total number of leads in the campaign audience.

getLeadsAfter and getLeadsBefore are the only accepted query parameters: any other one is rejected with a 404 error. If the campaign does not exist in your workspace or has no audience, the response is an empty list (count: 0).

Parameter In Required Description
campaignId path yes Campaign ID (24-character hex string).
getLeadsAfter query no Lead ID. Returns the leads that come after this one (next page).
getLeadsBefore query no Lead ID. Returns leads that come before this one, starting from the first lead of the campaign (see the known issue in the description of hasLess).

Response 200:

{
"leads": [
{
"firstname": "Jane",
"lastname": "Smith",
"companyName": "Acme",
"companyUrl": "https://acme.com",
"phone": null,
"companyPhone": null,
"jobTitle": "CTO",
"profilePicture": null,
"note": null,
"status": "STARTED",
"id": "64b7f0c2a1d3000000000007",
"email": "jane.smith@acme.com",
"linkedinUrl": "https://www.linkedin.com/in/jane-smith-acme",
"gender": null,
"industry": null,
"relationStatus": "NOT_SENT",
"acceptationDate": null,
"replied": 0,
"action_todo": null,
"email_sent": 0,
"email_opened": 0,
"email_clicked": 0,
"email_replied": 0,
"linkedin_visit": 0,
"linkedin_dm_sent": 0,
"linkedin_audio_sent": 0,
"linkedin_replied": 0,
"linkedin_relation_status": "NOT_SENT",
"twitter_tweeted": 0,
"twitter_retweeted": 0,
"twitter_favourited": 0,
"twitter_followed": 0,
"twitter_unfollowed": 0,
"twitter_dm_sent": 0,
"tweet_sent": 0
},
{
"firstname": "John",
"lastname": "Doe",
"companyName": "Acme",
"companyUrl": "https://acme.com",
"phone": null,
"companyPhone": null,
"jobTitle": "Head of Sales",
"profilePicture": null,
"note": null,
"status": "STARTED",
"id": "64b7f0c2a1d3000000000006",
"email": "john.doe@acme.com",
"linkedinUrl": null,
"gender": null,
"industry": null,
"relationStatus": "NOT_SENT",
"acceptationDate": null,
"replied": 0,
"action_todo": null,
"email_sent": 0,
"email_opened": 0,
"email_clicked": 0,
"email_replied": 0,
"linkedin_visit": 0,
"linkedin_dm_sent": 0,
"linkedin_audio_sent": 0,
"linkedin_replied": 0,
"linkedin_relation_status": "NOT_SENT",
"twitter_tweeted": 0,
"twitter_retweeted": 0,
"twitter_favourited": 0,
"twitter_followed": 0,
"twitter_unfollowed": 0,
"twitter_dm_sent": 0,
"tweet_sent": 0
}
],
"count": 2,
"hasMore": false,
"hasLess": false,
"statusCode": 200
}

Errors: 401, 404, 429, 500.

Get Campaign Messages

Returns the text messages (templates) configured in a campaign’s sequence: emails, LinkedIn messages and tweets. Audio and call steps are not returned.

Each message has two representations:

  • contentHtml / subjectHtml: rendered output, read-only.
  • newHtml / subjectNewHtml: editable source in the LGM editor format. Send these back to Edit Campaign Message to change a message.

order is the index of the message in this response, not its position in the sequence: use Get Campaign Steps for the sequence order.

Parameter In Required Description
campaignId path yes The campaign ID (24-character hex string).

Response 200:

{
"statusCode": 200,
"data": [
{
"id": "64b7f0c2a1d300000000000d",
"type": "TEXT",
"channel": "GOOGLE",
"contentHtml": "<span>Hi </span><span>{{firstname 'there'}}</span><span>, following up.</span><br>",
"subjectHtml": "",
"newHtml": "<p>Hi <var name=\"firstname\" default=\"there\"/>, following up.</p>",
"subjectNewHtml": "",
"order": 0,
"active": true
}
],
"total": 1
}

Errors: 400, 401, 404, 429, 500.

Get Campaign Steps

Lists the steps of a campaign sequence that carry a message (email, LinkedIn message, tweet, Twitter DM), in sequence order.

Use it to find a step’s stepId and to spot empty steps (hasMessage: false), then fill them with Add Campaign Step Message. A step that already has a message is edited with Edit Campaign Message, using the step’s templateId.

Parameter In Required Description
campaignId path yes The campaign ID (24-character hex string).

Response 200:

{
"statusCode": 200,
"data": [
{
"stepId": "00000000-0000-4000-8000-00000000000c",
"type": "GOOGLE_SEND_EMAIL",
"channel": "GOOGLE",
"position": 4,
"hasMessage": false,
"templateId": null,
"templateName": null
}
],
"total": 1
}

Errors: 400, 401, 404, 429, 500.

Update Campaign

Use this endpoint to update the settings of one campaign.

Send only the settings you want to change. At least one of name, audienceId, enrich, autoRescheduleOutOfOffice, hubspot, pipedrive, skipAlreadyContacted, ignoreEmojiOnlyReply is required. The other settings of the campaign are left unchanged. Any other field is rejected with a 400 error.

Some settings depend on the campaign status:

  • name: must not be used by another campaign of your workspace.
  • audienceId: can only be changed while the campaign has not been started yet (status READY).
  • hubspot / pipedrive: cannot be changed while the campaign is RUNNING (pause it first), and enabling them requires the CRM sync in your plan.
  • skipAlreadyContacted: can only be changed while the campaign is READY or PAUSED.
  • ignoreEmojiOnlyReply: can only be changed while the campaign is READY or PAUSED.
  • enrich and autoRescheduleOutOfOffice can be changed in any status.

Sending a setting with its current value is accepted in any status.

The response returns the updated settings of the campaign.

Parameter In Required Description
campaignId path yes Campaign ID (24-character hex string).

Request body:

{
"name": "Acme outbound (renamed)",
"audienceId": "64b7f0c2a1d3000000000005"
}

Response 200:

{
"statusCode": 200,
"data": {
"id": "64b7f0c2a1d300000000000b",
"name": "Acme outbound (renamed)",
"audience": {
"id": "64b7f0c2a1d3000000000005",
"name": "Acme prospects",
"size": 2
},
"enrich": false,
"autoRescheduleOutOfOffice": true,
"hubspot": false,
"pipedrive": false,
"skipAlreadyContacted": false,
"ignoreEmojiOnlyReply": false,
"status": "READY"
}
}

Errors: 400, 401, 403, 404, 429, 500.

Update Campaign Status

Use this endpoint to pause or resume one campaign.

Send the target status:

  • PAUSED: pauses the campaign. Only a RUNNING campaign can be paused. Scheduled actions of the campaign leads are put on hold.
  • RUNNING: resumes the campaign. Only a PAUSED campaign can be resumed. Actions of the campaign leads are scheduled again. The same plan rules as in the app apply (running campaigns limit, identity subscription, CRM / custom campaign / custom messages / A/B testing permissions).

This endpoint does not launch a campaign for the first time: a READY campaign must be launched from the LGM app.

The call is not idempotent: pausing an already paused campaign, or resuming an already running campaign, returns a 400 error and nothing is changed.

Pausing a campaign synced with your CRM can take a few seconds (one timeline event is created per lead already contacted). If your client times out, check the campaign status with Get Campaign instead of retrying.

Edits made while the campaign is paused are not retroactive: they only apply to the actions still pending once the campaign is resumed.

The response returns the id, name and new status of the campaign.

Parameter In Required Description
campaignId path yes Campaign ID (24-character hex string).

Request body:

{
"status": "PAUSED"
}

Response 200:

{
"statusCode": 200,
"data": {
"id": "65a1b2c3d4e5f60718293a4b",
"name": "My Campaign",
"status": "PAUSED"
}
}

Errors: 400, 401, 404, 429, 500.

Duplicate a campaign

Creates a new draft copy of a campaign: its sequence and every step’s message (with new message IDs). The copy is created with status READY and is not launched.

Works with:

  • your own campaigns (IDs from GET /campaigns): the copy keeps the source identity, audience and language;
  • public catalog templates (IDs from GET /campaigns/public): the copy uses the last identity you used, your last language for that identity and no audience.

The copy is named after the source campaign followed by a number (for example Acme outbound Q4 12). Duplicating a campaign with a custom sequence requires a plan that includes custom sequences.

Typical flow: duplicate the campaign, read its messages with GET /campaigns/{campaignId}/messages, then rewrite them with POST /campaigns/{campaignId}/messages/{templateId}.

This endpoint takes no request body. Unknown query parameters are rejected with a 400.

Parameter In Required Description
campaignId path yes ID of the campaign to duplicate (24-character hex string).

Response 200:

{
"statusCode": 200,
"data": {
"id": "64b7f0c2a1d300000000000b",
"name": "Email Only - 1 Follow-up 1 1",
"status": "READY"
}
}

Errors: 400, 401, 403, 404, 429, 500.

POST /campaigns/{campaignId}/messages/{templateId}

Section titled “POST /campaigns/{campaignId}/messages/{templateId}”

Edit a campaign message

Replaces the content of an existing message of a campaign step. Get the campaignId and the templateId (the id of each message) from GET /campaigns/{campaignId}/messages. To fill a step that has no message yet, use POST /campaigns/{campaignId}/steps/{stepId}/message instead.

The content is validated server-side; a malformed message is rejected with a 400 and nothing is saved.

Not retroactive. On a campaign that has already started (RUNNING or PAUSED), leads who already received this step keep the message they got; the new content only applies to actions still pending.

  • The body is a sequence of block tags (<p>…</p>, <ul><li>…</li></ul>, <h2>…</h2>); wrap all text in blocks.
  • Send the whole string on a single line, with no whitespace between top-level blocks (</p><p>, never </p> <p>).
  • Personalization variables only as <var name="firstname"/>, optionally with a fallback: <var name="firstname" default="there"/>. {{…}}, {…}, %…% or […] are not variables.
  • Inline tags: <b>, <i>, <u>, <s>, <br/> (line break inside a paragraph), <a href="https://…" track="true">text</a>, <spin>Hi|Hello</spin> (text only), <signature/> (emails).
  • Escape < as &lt; and & as &amp;.
Parameter In Required Description
campaignId path yes ID of the campaign the message belongs to (24-character hex string).
templateId path yes ID of the message to edit (24-character hex string), the id returned by GET /campaigns/{campaignId}/messages.

Request body:

{
"newHtml": "<p>Hi <var name=\"firstname\" default=\"there\"/>, a quick question about Acme.</p>"
}

Response 200:

{
"statusCode": 200,
"data": {
"id": "64b7f0c2a1d300000000000d",
"channel": "GOOGLE",
"contentHtml": "<span>Hi </span><span>{{firstname 'there'}}</span><span>, a quick question about Acme.</span><br>",
"subjectHtml": ""
}
}

Errors: 400, 401, 404, 429, 500.

POST /campaigns/{campaignId}/steps/{stepId}/message

Section titled “POST /campaigns/{campaignId}/steps/{stepId}/message”

Add a message to an empty campaign step

Creates a new message and links it to a campaign step that has no message yet (a step returned by GET /campaigns/{campaignId}/steps with hasMessage: false). The channel is inferred from the step. If the step already has a message, the call is rejected: edit it with POST /campaigns/{campaignId}/messages/{templateId} instead.

The content is validated server-side with the same rules as the edit endpoint (see the newHtml format described on POST /campaigns/{campaignId}/messages/{templateId}).

Not retroactive. On a campaign that has already started (RUNNING or PAUSED), leads who already passed this step are not sent the new message; it only applies to actions still pending.

Parameter In Required Description
campaignId path yes ID of the campaign the step belongs to (24-character hex string).
stepId path yes ID of the step, the stepId returned by GET /campaigns/{campaignId}/steps.

Request body:

{
"newHtml": "<p>Hi <var name=\"firstname\" default=\"there\"/>, following up.</p>"
}

Response 200:

{
"statusCode": 200,
"data": {
"id": "64b7f0c2a1d300000000000d",
"stepId": "00000000-0000-4000-8000-00000000000c",
"channel": "GOOGLE",
"contentHtml": "<span>Hi </span><span>{{firstname 'there'}}</span><span>, following up.</span><br>",
"subjectHtml": ""
}
}

Errors: 400, 401, 404, 429, 500.

POST /campaigns/{campaignId}/share-by-code

Section titled “POST /campaigns/{campaignId}/share-by-code”

Share a campaign by code

Generates an access code for one of your campaigns. Anyone with an LGM account and the code can preview the campaign (GET /campaigns/accessible/{code}) and copy it into their own workspace (POST /campaigns/duplicate/accessible/{code}). The preview exposes the sequence and its messages only; leads and stats are never shared.

The code is made of 24 random hex characters, a -, then a compact form of the campaign name.

Idempotent: if the campaign is already shared, the existing code is returned. Requires a plan that includes campaign sharing. This endpoint takes no request body.

Parameter In Required Description
campaignId path yes ID of the campaign to share (24-character hex string).

Response 200:

{
"statusCode": 200,
"data": {
"campaignId": "64b7f0c2a1d3e4f5a6b7c8d9",
"code": "9f3c2a1b7e6d5c4b3a291807-acmeOutboundQ4",
"shared": true
}
}

Errors: 400, 401, 404, 429, 500.

POST /campaigns/{campaignId}/stop-sharing-by-code

Section titled “POST /campaigns/{campaignId}/stop-sharing-by-code”

Stop sharing a campaign by code

Revokes the access code of a campaign. The code stops working immediately; copies already made by other accounts are not affected. Idempotent: calling it on a campaign that is not shared returns the same response. This endpoint takes no request body.

Parameter In Required Description
campaignId path yes ID of the campaign (24-character hex string).

Response 200:

{
"statusCode": 200,
"data": {
"campaignId": "64b7f0c2a1d300000000000a",
"code": null,
"shared": false
}
}

Errors: 400, 401, 404, 429, 500.

Preview a campaign shared by code

Returns a preview of a campaign shared with an access code: name, description, language, the inventory of sequence actions and the content of its messages. Use it to review a shared campaign before copying it with POST /campaigns/duplicate/accessible/{code}. Leading and trailing spaces in the code are ignored.

Parameter In Required Description
code path yes The access code received from the campaign owner.

Response 200:

{
"statusCode": 200,
"data": {
"name": "Acme outbound Q4",
"description": "Three-touch sequence for heads of sales.",
"language": "english",
"stepCount": 3,
"actions": [
{
"type": "LINKEDIN_ADD_CONTACT_WITH_NOTE",
"channel": "LINKEDIN",
"count": 1
},
{
"type": "GOOGLE_SEND_EMAIL",
"channel": "GOOGLE",
"count": 2
}
],
"messages": [
{
"type": "TEXT",
"channel": "GOOGLE",
"subjectHtml": "Quick question for <span class=\"variable\">{{company}}</span>",
"contentHtml": "<p>Hi <span class=\"variable\">{{firstname 'there'}}</span>,</p><p>How does <span class=\"variable\">{{company}}</span> handle outbound today?</p>",
"subjectNewHtml": "<p>Quick question for <var name=\"company\"/></p>",
"newHtml": "<p>Hi <var name=\"firstname\" default=\"there\"/>,</p><p>How does <var name=\"company\"/> handle outbound today?</p>"
}
],
"callScriptCount": 0,
"voiceMessageCount": 0
}
}

Errors: 401, 404, 429, 500.

POST /campaigns/duplicate/accessible/{code}

Section titled “POST /campaigns/duplicate/accessible/{code}”

Duplicate a campaign shared by code

Copies a campaign shared with an access code into your workspace, as a new draft campaign (status READY, not launched, no audience). The copy uses the last identity you used and your last language for that identity. Your workspace needs at least one identity.

Then edit its messages like any of your campaigns. This endpoint takes no request body.

Parameter In Required Description
code path yes The access code received from the campaign owner.

Response 200:

{
"statusCode": 200,
"data": {
"id": "65a1b2c3d4e5f60718293a6d",
"name": "Acme outbound Q4 3",
"status": "READY"
}
}

Errors: 401, 404, 429, 500.

List audiences

Returns all audiences of the authenticated workspace (deleted audiences excluded).

No parameter needed. Each audience carries its id, name, type, size (number of leads) and import state.

Response 200:

{
"statusCode": 200,
"audiences": [
{
"id": "64b7f0c2a1d3000000000005",
"name": "Acme prospects",
"description": "",
"userId": "64b7f0c2a1d3000000000003",
"modifiedAt": 1791192987296,
"createdAt": 1791192987020,
"size": 1,
"targetSize": null,
"sourceUrl": null,
"type": "CLASSIC",
"importationPending": false,
"sourceListId": null,
"refreshPeriod": 0,
"importStatus": null,
"deletionPending": null,
"filterLeads": null,
"enrichType": null,
"preEnrich": null,
"importationStartedAt": null,
"excludeContactedLeads": false,
"hasAutoImport": false,
"notContactedSourceCampaignId": null,
"signals": []
}
]
}

Errors: 401, 404, 429.

Create audience from linkedin url

Import leads into your LGM audiences by providing a LinkedIn Regular search URL, a Sales Navigator search or list URL, a LinkedIn post URL, a company followers URL or a LinkedIn event URL. You must also provide the identity to impersonate for the search query and specify the name of the audience to populate.

If no audience matches audience (by name, then by ID), a new one is created. The import runs asynchronously on the identity’s LinkedIn account: the response only confirms that it was queued. Follow its progress with GET /flow/audiences/{audienceId}/detail.

  • The identity’s LinkedIn account must be connected and the LGM extension (widget) open while the import runs.
  • For a post URL, set linkedinPostCategory to import the people who liked (like) or commented (comment) the post.
  • For an event URL, only an identity registered to the event can see its attendees; any other identity imports 0 leads.
  • autoImport is only available for Sales Navigator, post, followers and event URLs, not for a Regular search URL.

More information: https://www.youtube.com/watch?v=nt54qlEbZJM

Request body:

{
"audience": "Acme prospects",
"linkedinUrl": "https://www.linkedin.com/sales/search/people?query=(keywords%3Aacme)",
"identityId": "60a1b2c3d4e5f60012345678",
"excludeContactedLeads": true
}

Response 200:

{
"statusCode": 200
}

Errors: 401, 404, 429.

Create Audience

Creates an empty audience (type CLASSIC). Add leads to it with POST /flow/leads.

To create an audience from a LinkedIn URL (search or post), use POST /flow/audiences instead.

Request body:

{
"name": "Acme prospects"
}

Response 200:

{
"statusCode": 200,
"audience": {
"id": "64b7f0c2a1d3000000000005",
"name": "Acme prospects"
}
}

Errors: 400, 401, 429.

Get Audience Leads

Returns a paginated list of leads belonging to a specific audience, with the full lead record. Use skip and limit to page through the audience; total is the number of leads in the audience.

Every field is always present in the response. Values depend on the lead’s enrichment level: a lead that was never enriched returns empty strings (and null for relationsCount, emailStatus, emailFoundBy). The example response is truncated to customAttribute1–customAttribute3 for readability; all 20 are always returned.

Parameter In Required Description
audienceId path yes The audience ID (24-char hex ObjectId).
skip query no Number of leads to skip.
limit query no Max leads to return.

Response 200:

{
"statusCode": 200,
"data": [
{
"id": "64b7f0c2a1d3000000000006",
"firstname": "John",
"lastname": "Doe",
"companyName": "Acme",
"jobTitle": "Head of Sales",
"linkedinUrl": "",
"proEmail": "john.doe@acme.com",
"phone": "",
"status": "unknown",
"location": "",
"industry": "",
"shortBio": "",
"companyUrl": "https://acme.com",
"persoEmail": "",
"gender": "",
"twitter": "",
"relationsCount": null,
"enrichStatus": "Not enriched",
"emailStatus": null,
"emailFoundBy": null,
"signal": "",
"crm_id": "",
"audiences": [
"Acme prospects"
],
"customAttribute1": "",
"customAttribute2": "",
"customAttribute3": "",
"customAttribute4": "",
"customAttribute5": "",
"customAttribute6": "",
"customAttribute7": "",
"customAttribute8": "",
"customAttribute9": "",
"customAttribute10": "",
"customAttribute11": "",
"customAttribute12": "",
"customAttribute13": "",
"customAttribute14": "",
"customAttribute15": "",
"customAttribute16": "",
"customAttribute17": "",
"customAttribute18": "",
"customAttribute19": "",
"customAttribute20": ""
}
],
"total": 1
}

Errors: 400, 401, 404, 429.

Get Audience Detail

Returns detailed information about a specific audience. Use it to follow an import started with POST /flow/audiences: importStatus reports how many leads were screened.

Parameter In Required Description
audienceId path yes The audience ID (24-char hex ObjectId).

Response 200:

{
"statusCode": 200,
"data": {
"id": "64b7f0c2a1d3000000000005",
"name": "Acme prospects",
"description": "",
"size": 1,
"type": "CLASSIC",
"createdAt": "2026-10-05T09:36:27.020Z",
"modifiedAt": "2026-10-05T09:36:27.296Z",
"importStatus": ""
}
}

Errors: 400, 401, 404, 429.

Create or Update a Lead

Creates a lead (or updates it when it already exists).

At least one of the following is required: leadId, proEmail, persoEmail, linkedinUrl, twitter, crm_id, OR firstname + lastname + (companyName or companyUrl).

  • With leadId, that exact lead is updated (404 if it does not exist).
  • Otherwise the lead is matched against existing leads on these identifiers. A duplicate is merged or ignored depending on the workspace’s “merge duplicate leads” setting; the response message says which.

audience (optional) is the name (or ID) of the target audience. If no audience matches, a new one is created. If omitted, the lead is created with no audience.

All optional, max 255 characters unless specified: firstname, lastname, gender (man|woman), bio (max 5000), companyName, companyUrl, jobTitle, profilePicture, linkedinUrl, twitter, proEmail, persoEmail, industry, phone, crm_id, location, relationsCount (integer).

crm_id links the lead to a contact of the CRM connected to the workspace (HubSpot or Pipedrive).

customAttribute1…customAttribute20 (string, max 2500).

note (string, max 1500) — free-text note displayed on the lead profile. Providing it replaces the existing note; omitting it keeps it.

  • excludeContactedLeads (boolean, default false) — when true, a lead already contacted in one of your campaigns is ignored (nothing is created nor updated).
  • enrichData (object) — enrichment data already available on the caller side, keyed by field name.
  • enrichStatus (string).

Empty values ("", null, 0, false) are ignored.

Request body:

{
"audience": "Acme prospects",
"firstname": "John",
"lastname": "Doe",
"proEmail": "john.doe@acme.com",
"companyName": "Acme",
"companyUrl": "https://acme.com",
"jobTitle": "Head of Sales"
}

Response 200:

{
"statusCode": 200,
"message": "Lead created and added to the audience. Added to existing audience.",
"leadId": "64b7f0c2a1d3000000000006"
}

Errors: 401, 404, 429.

Search Lead

Searches for a lead in the authenticated workspace and returns the first match, with the campaigns it is involved in and its most recent activity.

Query params — at least one criterion required

Section titled “Query params — at least one criterion required”
  • leadId — direct lookup by id
  • crmId — direct lookup by external CRM id
  • linkedinUrl / linkedinId / linkedinPublicId / linkedinLongPublicId — LinkedIn lookup
  • email — lookup by email (pro or perso)
  • firstname + lastname + (companyName or companyUrl) — first and last name alone do not match
  1. leadId
  2. crmId
  3. Any of the other criteria: the first lead matching at least one of them is returned.
  • lead — the matched lead, with involvedCampaigns: running, paused or canceled campaigns whose audience contains the lead.
  • recentLogs — the most recent successful action per campaign (up to 20 campaigns).

Returns 404 when no lead matches.

Parameter In Required Description
leadId query no Lead id (24 chars).
crmId query no Contact id in the connected CRM.
firstname query no Lead firstname (with lastname and companyName or companyUrl).
lastname query no Lead lastname.
companyName query no Lead company name.
companyUrl query no Lead company URL.
linkedinUrl query no Lead LinkedIn profile URL (with or without trailing slash).
linkedinId query no Lead LinkedIn numeric id.
linkedinPublicId query no Lead LinkedIn public id (slug).
linkedinLongPublicId query no Lead LinkedIn long public id.
email query no Lead email (pro or perso).

Response 200:

{
"statusCode": 200,
"lead": {
"firstname": "John",
"lastname": "Doe",
"id": "64b7f0c2a1d3000000000006",
"linkedinId": null,
"gender": null,
"shortBio": null,
"linkedinLongPublicId": null,
"lastActions": {
"last": [],
"status": [],
"lastStatus": []
},
"companyName": "Acme",
"companyUrl": "https://acme.com",
"createdAt": 1791192987067,
"modifiedAt": 1791192987067,
"jobTitle": "Head of Sales",
"profilePicture": null,
"linkedinUrl": null,
"salesNavUrl": null,
"enriched": null,
"userId": "64b7f0c2a1d3000000000003",
"twitter": null,
"proEmail": "john.doe@acme.com",
"persoEmail": null,
"relationsCount": null,
"audiences": [
"64b7f0c2a1d3000000000005"
],
"addedAtByAudience": [],
"industry": null,
"phone": null,
"companyPhone": null,
"note": null,
"location": null,
"audiencesWithName": [],
"pausedCampaigns": [],
"involvedCampaigns": [],
"involvedCampaignsLogs": [],
"hubspot": {},
"pipedrive": {},
"lifecycle": null,
"tags": [],
"campaigns": [],
"enrichData": null,
"enrichStatus": null,
"deleted": false,
"migrationDone": null,
"customAttribute1": null,
"customAttribute2": null,
"customAttribute3": null,
"customAttribute4": null,
"customAttribute5": null,
"customAttribute6": null,
"customAttribute7": null,
"customAttribute8": null,
"customAttribute9": null,
"customAttribute10": null,
"customAttribute11": null,
"customAttribute12": null,
"customAttribute13": null,
"customAttribute14": null,
"customAttribute15": null,
"customAttribute16": null,
"customAttribute17": null,
"customAttribute18": null,
"customAttribute19": null,
"customAttribute20": null
},
"recentLogs": []
}

Errors: 401, 404, 429.

Update lead Status

Use this endpoint for updating lead status in campaign.

You need to specify at least one Lead field (persoEmail, proEmail, linkedinUrl, twitter, crm_id) or firstname + lastname + (companyUrl or companyName), or you can specify its ID in the body with the param leadId.

campaign is a campaign name or ID, an array of them, or "all" for every non-stopped campaign whose audience contains the lead. Campaigns that are stopped or do not contain the lead are skipped; when none matches, logs is empty.

  • PAUSED, RESUME — pause or resume the lead in the campaign.
  • STOPPED — end the campaign for the lead.
  • CONVERTED — mark the lead as converted and end the campaign.
  • SUBSCRIBED — resubscribe a lead that was unsubscribed.
  • A lead tag: NOT_ACTIVATED, SKIPPED, ACTIVATED, ENRICHED, CONTACTED, COMPLETED_WITHOUT_REPLY, TO_QUALIFY, OUT_OF_OFFICE, WRONG_TIMING, INTERESTED, NOT_INTERESTED, CALL_BOOKED, NEGOTIATING, READY_TO_BUY, CONVERTED, UNSUBSCRIBED, WRONG_TARGET, ALREADY_EQUIPPED. Tagging the lead INTERESTED, CALL_BOOKED, NEGOTIATING, READY_TO_BUY or CONVERTED also converts it; TO_QUALIFY, WRONG_TIMING, UNSUBSCRIBED, WRONG_TARGET, NOT_INTERESTED or ALREADY_EQUIPPED also ends the campaign for it.
  • Aliases: COMPLETED_NO_REPLY (= COMPLETED_WITHOUT_REPLY), REPLIED (= TO_QUALIFY), CANNOT_CONTACT (= UNSUBSCRIBED).

memberEmail picks the member on whose behalf a SUBSCRIBED change is made (default: the workspace owner); from (lead or member) records who asked for it.

More information: https://www.youtube.com/watch?v=s4jevOQR4aY

Request body:

{
"campaign": "Email Only - 1 Follow-up 1 1",
"status": "PAUSED",
"proEmail": "john.doe@acme.com"
}

Response 200:

{
"logs": [],
"statusCode": 200
}

Errors: 401, 404, 429.

Remove lead from audiences

Removes a lead from one or more audiences.

  • audience (required) — "all", an audience name or ID, or an array of names or IDs.
  • At least one lead identifier: crm_id, proEmail, persoEmail, linkedinUrl, twitter, or firstname + lastname + (companyName or companyUrl). leadId is not accepted here.

If the lead is not present in the audience, the operation is silently ignored. A single audience name that does not exist returns 404; unknown names in an array are ignored.

Request body:

{
"audience": [
"Acme prospects"
],
"proEmail": "john.doe@acme.com"
}

Response 200:

{
"statusCode": 200
}

Errors: 401, 404, 429.

Get Lead Logs

Returns a paginated list of activity logs for a specific lead, most recent first. total is the number of logs before pagination.

Parameter In Required Description
leadId path yes The lead ID (24-char hex ObjectId).
identityId query no Filter logs by identity ID (24-char hex ObjectId).
skip query no Number of logs to skip.
limit query no Max logs to return.

Response 200:

{
"statusCode": 200,
"data": []
}

Errors: 400, 401, 404, 429.

Get Lead Conversations

Returns all inbox conversations associated with a specific lead. Read the messages of a conversation with GET /flow/conversations/{conversationId}/messages.

Parameter In Required Description
leadId path yes The lead ID (24-char hex ObjectId).
identityId query no Filter conversations by identity ID (24-char hex ObjectId).

Response 200:

{
"statusCode": 200,
"data": [],
"total": 0
}

Errors: 400, 401, 404, 429.

Enrich Lead

Starts an enrichment request. Depending on enrichType, it returns a pro email, a phone number, LinkedIn profile fields, or email and LinkedIn together.

  • leadId (string, 24 chars) — id of an existing lead; the enriched fields are written on the lead.
  • OR linkedinUrl (https, linkedin.com, max 500).
  • OR firstname + lastname (+ companyName / companyUrl).

Drives what we enrich and how much it costs.

Value What it does Credits (max) Needs
EMAIL_ENRICH (default) Finds the pro email and its status 5 leadId, or linkedinUrl, or firstname + lastname + (companyName or companyUrl)
LINKEDIN_ENRICH Fetches the LinkedIn profile fields (job title, company, location…) 1 leadId or linkedinUrl
FULL_ENRICH LinkedIn profile + email 5 leadId or linkedinUrl
PHONE_ENRICH Finds a phone number (not available during the trial) 20 leadId

The credits column is the maximum charged per request. The balance is checked before the request starts: with fewer credits than this amount, the call fails with 400. Without a leadId, the email is only charged when one is found, and a result already known to LGM is returned immediately (cached) without being charged. Your balance: GET /flow/credits.

Enrichment requires a plan with enrichment; during a trial it requires the external enrichment option.

  • polling (default) — immediate response with enrichRequestId and status: pending. Poll GET /flow/leads/enrich/{enrichRequestId}.
  • sync — waits up to 60 seconds for the result.
  • webhook — immediate response with status: accepted; the result is POSTed to webhookUrl (public HTTPS URL) once ready, as { enrichRequestId, status, email?, emailStatus?, phone?, provider? } with status in upper case (ENRICHED, NOT_FOUND, ERROR…). Up to 3 attempts.

An enrichment request can be read for 24 hours.

  • EMAIL_ENRICH and FULL_ENRICH results include email + emailStatus once enriched.
  • LINKEDIN_ENRICH and FULL_ENRICH results include linkedinProfile. With a leadId, the enriched fields are also written on the lead (visible via the lead read endpoints).
  • PHONE_ENRICH results include phone.

Request body:

{
"leadId": "64b7f0c2a1d3000000000006",
"enrichType": "EMAIL_ENRICH"
}

Response 200:

{
"statusCode": 200,
"enrichRequestId": "00000000-0000-4000-8000-000000000010",
"status": "pending"
}

Errors: 400, 401, 403, 404, 429.

Get Enrich Result

Retrieves the result of an enrichment request previously created with POST /flow/leads/enrich (any mode). Requests are kept for 24 hours.

  • pending — still running, poll again later.
  • enriched — done; the result fields are in the response.
  • not_found — nothing was found.
  • error — the enrichment failed (for example not enough credits when it ran).
  • expired — a sync call timed out. If the result arrived afterwards, it is returned (and was not charged); otherwise no data is returned.

email and emailStatus are returned for EMAIL_ENRICH and FULL_ENRICH, linkedinProfile for LINKEDIN_ENRICH and FULL_ENRICH, phone for PHONE_ENRICH.

Parameter In Required Description
enrichRequestId path yes ID returned by POST /flow/leads/enrich.

Response 200:

{
"statusCode": 200,
"status": "pending"
}

Errors: 401, 404, 429.

Enrich LinkedIn Post

Fetches the content and engagement of a public LinkedIn post from its URL: text, author, reaction counts, comments and reposts, posting date and URN.

Costs 1 credit per successful call. The balance is checked first (400 when it is too low) and the credit is only charged when the post is fetched. Requires a plan with enrichment; during a trial it requires the external enrichment option.

The result is returned synchronously. No campaign or identity is needed.

Request body:

{
"postUrl": "https://www.linkedin.com/posts/bricemaur_we-now-connect-to-a-crm-we-never-built-an-share-7511039697201238019-3Fr-/"
}

Response 200:

{
"statusCode": 200,
"post": {
"isBrandPartnership": false,
"text": "We now connect to a CRM we never built an integration for 🔥\n\nHere's how that happened, and why I stopped treating the integration list as a roadmap problem.\n\nLGM has deep native syncs with HubSpot and Pipedrive. Attio isn't one of them, and people ask for it. Building a native integration for every CRM on the market is weeks of dev each, and that's weeks we'd rather spend elsewhere.\n\nSo I built it in n8n instead. When a conversation starts with a lead in LGM, the workflow checks Attio for that person on email, first name and last name. No match on any of the three and it creates the record. A match and it updates with the LinkedIn data, then stores the conversation.\n\nSame result as a native sync from where the user sits. Three hours to point it at the next CRM.\n\nI've said for a while that the upstream tools are complementary and interchangeable. The enrichment tool you love today gets swapped next year. What shouldn't move is the layer running your outreach and tying it back to revenue in your CRM.\n\nThat only holds if the layer actually talks to what you already use. Not eventually, not once it clears the roadmap, this week!\n\nMultiple templates are live: the CRM sync, reply listening, lead enrichment, and one that pauses a lead the second they book on your Calendly.\n\nWhich CRM should I do next? Tell me and I'll build it",
"totalReactionCount": 11,
"likeCount": 10,
"praiseCount": 1,
"commentsCount": 2,
"shareUrl": "https://www.linkedin.com/posts/bricemaur_we-now-connect-to-a-crm-we-never-built-an-activity-7511039698820112385-Tbnu",
"postedAt": "5d",
"postedDate": "2026-09-30 12:30:12.568 +0000 UTC",
"postedDateTimestamp": 1790771412568,
"urn": "7511039698820112385",
"shareUrn": "7511039697201238019",
"author": {
"firstname": "Brice",
"lastname": "Maurln",
"headline": "CEO at LGM | I ran outbound for clients for 9 years before building the platform I wished I had",
"url": "https://www.linkedin.com/in/bricemaur",
"avatar": "https://media.licdn.com/dms/image/v2/D4E03AQH2ULJ_2bf7pQ/profile-displayphoto-crop_800_800/B4EZ_WMW_4H0AI-/0/1786004993149?e=1792627200&v=beta&t=81H9QIMfxxQhSSsSyl94s5HAtn6NYGBfLmfw5mjhtW0"
},
"image": [
{
"url": "https://media.licdn.com/dms/image/v2/D4E10AQG-r930nLvvGQ/image-shrink_800/B4EaDySy8nGwAs-/0/1790771409394?e=1791878400&v=beta&t=hVHUXQADjuJ36lsG_zHiICjurlAdBwmLv4sSU2u3GMk",
"width": 0,
"height": 0
}
]
}
}

Errors: 400, 401, 403, 404, 429.

Send A Linkedin Message To A Lead

Sends a LinkedIn text or voice message to a lead from one of your connected LinkedIn identities.

You must provide either a leadId or a linkedinUrl, along with the identityId and the memberId performing the action.

  • You must provide at least one of: leadId or linkedinUrl.
  • You must provide at least one of: message or audioUrl. When audioUrl is set, a voice message is sent.
  • identityId and memberId are always required.
  • memberId must be retrieved with List members. It must belong to your workspace.
  • identityId must match a connected LinkedIn identity in your account (see List identities).
  • The lead is looked up by leadId, or by linkedinUrl among your existing leads. The lead is not created if it does not exist.
  • A conversation between this lead and this identity must already exist, otherwise the request fails with Conversation not found.
  • A 200 means the message has been queued for sending, not that LinkedIn has delivered it. If delivery fails, the message shows up with status SEND_FAILED in Get conversation messages.
  • Identities running through the browser extension (not LinkedIn cloud) need the extension to be connected, otherwise the request fails with Widget running identity ... need to be connected.

⚠️ Warning: Be Responsible with Your API Usage

Please ensure that your scripts are properly controlled and not unintentionally looping over this endpoint. Uncontrolled or excessive calls may affect your experience and platform stability. La Growth Machine is not responsible for accidental or abusive usage caused by misconfigured automations or scripts.

Request body:

{
"identityId": "6650a1b2c3d4e5f6a7b8c901",
"memberId": "6650a1b2c3d4e5f6a7b8c902",
"leadId": "6650a1b2c3d4e5f6a7b8c903",
"message": "Hi John, are you available to chat this week?"
}

Response 200:

{
"statusCode": 200,
"lead": {
"id": "6650a1b2c3d4e5f6a7b8c903",
"firstname": "John",
"lastname": "Doe",
"gender": "man",
"shortBio": "Head of Sales at Acme",
"jobTitle": "Head of Sales",
"companyName": "Acme",
"companyUrl": "https://acme.com",
"industry": "Software",
"location": "Paris, France",
"linkedinUrl": "https://www.linkedin.com/in/john-doe-acme",
"salesNavUrl": "https://www.linkedin.com/sales/people/ACwAAA0000000,NAME_SEARCH",
"proEmail": "john.doe@acme.com",
"twitter": null,
"phone": null,
"companyPhone": null,
"note": null,
"userId": "6650a1b2c3d4e5f6a7b8c900",
"audiences": [
"6650a1b2c3d4e5f6a7b8c910"
],
"involvedCampaigns": [
{
"_id": "6650a1b2c3d4e5f6a7b8c920",
"name": "Q3 outreach",
"status": "RUNNING",
"launchedAt": 1719820800000,
"tag": "TO_QUALIFY"
}
],
"tags": [
{
"campaignId": "6650a1b2c3d4e5f6a7b8c920",
"tag": "TO_QUALIFY",
"status": "REPLIED"
}
],
"reply": {
"repliedAt": 1720000000000,
"content": "Yes, ok for me",
"identityId": "6650a1b2c3d4e5f6a7b8c901",
"channel": "LINKEDIN"
},
"lastMessageSentAt": 1720100000000,
"createdAt": 1719000000000,
"modifiedAt": 1720100000000,
"customAttribute1": null
}
}

Errors: 400, 401, 403, 404, 429, 500.

Send An Email Message To A Lead

Sends an email to a lead from one of your connected email identities, as a reply in an existing email thread.

  • You must provide at least one of leadId or leadEmail.
  • You must provide replyInLastThread: true or a replyToMessageId:
    • replyInLastThread: true replies in the most recent email thread of the conversation. The subject is set to Re: <subject of that thread>, whatever subject you send.
    • replyToMessageId replies to a specific message (an id from Get conversation messages).
  • Sending a brand new email (only a subject, no thread to reply to) is not supported through the API: the request fails with email or replyMessageId parameter needed.
  • identityId must match a connected email identity in your account.
  • The lead is looked up by leadId, or by leadEmail among your existing leads.
  • A conversation between this lead and this identity must already exist. With replyInLastThread, it must also already contain an email.
  • The email is sent on behalf of the default member of your workspace. memberId is not accepted on this endpoint.

⚠️ Warning: Be Responsible with Your API Usage

Please ensure that your scripts are properly controlled and not unintentionally looping over this endpoint. Uncontrolled or excessive calls may affect your experience and platform stability. La Growth Machine is not responsible for accidental or abusive usage caused by misconfigured automations or scripts.

Request body:

{
"message": {
"html": "<p>Hi John,</p><p>Just following up on my last email.</p>",
"text": "Hi John, just following up on my last email."
},
"identityId": "6650a1b2c3d4e5f6a7b8c901",
"leadEmail": "john.doe@acme.com",
"replyInLastThread": true
}

Response 200:

{
"statusCode": 200,
"lead": {
"id": "6650a1b2c3d4e5f6a7b8c903",
"firstname": "John",
"lastname": "Doe",
"gender": "man",
"shortBio": "Head of Sales at Acme",
"jobTitle": "Head of Sales",
"companyName": "Acme",
"companyUrl": "https://acme.com",
"industry": "Software",
"location": "Paris, France",
"linkedinUrl": "https://www.linkedin.com/in/john-doe-acme",
"salesNavUrl": "https://www.linkedin.com/sales/people/ACwAAA0000000,NAME_SEARCH",
"proEmail": "john.doe@acme.com",
"twitter": null,
"phone": null,
"companyPhone": null,
"note": null,
"userId": "6650a1b2c3d4e5f6a7b8c900",
"audiences": [
"6650a1b2c3d4e5f6a7b8c910"
],
"involvedCampaigns": [
{
"_id": "6650a1b2c3d4e5f6a7b8c920",
"name": "Q3 outreach",
"status": "RUNNING",
"launchedAt": 1719820800000,
"tag": "TO_QUALIFY"
}
],
"tags": [
{
"campaignId": "6650a1b2c3d4e5f6a7b8c920",
"tag": "TO_QUALIFY",
"status": "REPLIED"
}
],
"reply": {
"repliedAt": 1720000000000,
"content": "Yes, ok for me",
"identityId": "6650a1b2c3d4e5f6a7b8c901",
"channel": "LINKEDIN"
},
"lastMessageSentAt": 1720100000000,
"createdAt": 1719000000000,
"modifiedAt": 1720100000000,
"customAttribute1": null
}
}

Errors: 400, 401, 403, 404, 429, 500.

List Inbox Webhooks

Lists the inbox webhooks configured in your workspace, with their IDs, names, target URLs and campaign filters.

Response 200:

[
{
"id": "00000000-0000-4000-8000-00000000000f",
"url": "https://example.com/lgm-docs-webhook",
"key": "Acme prospects",
"type": "INBOX_EVENT",
"campaigns": [
"all"
],
"createdAt": "2026-10-05T09:36:29.532Z"
}
]

Errors: 400, 401, 403, 429, 500.

Create Inbox Event Webhook

Registers a webhook that receives real-time inbox events: every new LinkedIn or email message, sent or received, in the conversations of your workspace.

url must be publicly accessible and respond to POST requests with a 200 OK.

If campaigns is omitted, the webhook receives messages from all campaigns (["all"]). To filter, pass the IDs of the campaigns to follow: an event is sent when the lead is in at least one of them. Do not send an empty array: a webhook with campaigns: [] never fires.

LGM sends a POST with a JSON body about one minute after a new message (LinkedIn or email, sent or received) is recorded. If several messages arrive for the same lead within that delay, a single call is made, for the latest one. The request carries an Authorization: Bearer <token> header with a token generated for the webhook.

The body contains the latest message at the root, the lead in lead, and the lead’s 20 latest LinkedIn and email messages (all identities, newest first) in messages:

{
"messageChannel": "LINKEDIN",
"messageBody": "Thanks for reaching out, let's talk next week.",
"messageId": "6650a1b2c3d4e5f6a7b8c950",
"conversationId": "6650a1b2c3d4e5f6a7b8c940",
"externalConversationId": "2-ZmFrZS10aHJlYWQtaWQ=",
"leadId": "6650a1b2c3d4e5f6a7b8c903",
"identityId": "6650a1b2c3d4e5f6a7b8c901",
"userId": "6650a1b2c3d4e5f6a7b8c900",
"createdAt": 1720000000000,
"sent": false,
"received": true,
"campaignId": "6650a1b2c3d4e5f6a7b8c920",
"campaignName": "Q3 outreach",
"lead": {
"id": "6650a1b2c3d4e5f6a7b8c903",
"firstName": "John",
"lastName": "Doe",
"jobTitle": "Head of Sales",
"gender": "man",
"shortBio": "Head of Sales at Acme",
"dateOfBirth": null,
"email": "john.doe@acme.com",
"persoEmail": null,
"picture": null,
"note": null,
"companyName": "Acme",
"companyWebsite": "https://acme.com",
"industry": "Software",
"linkedin": "https://www.linkedin.com/in/john-doe-acme",
"twitter": null,
"phone": null,
"location": "Paris, France",
"customAttribute1": null,
"customAttribute20": null,
"crmId": null
},
"messages": [
{
"messageChannel": "LINKEDIN",
"messageBody": "Thanks for reaching out, let's talk next week.",
"messageId": "6650a1b2c3d4e5f6a7b8c950",
"conversationId": "6650a1b2c3d4e5f6a7b8c940",
"createdAt": 1720000000000,
"sent": false,
"received": true
}
]
}
  • messageChannel: LINKEDIN or EMAIL. messageSubject is only present for emails.
  • Fields without a value are omitted: messageSubject on LinkedIn, attachments when there is none, campaignId and campaignName outside campaigns.
  • sent / received: direction of the message. Both are false while an outgoing message is still being sent or failed.
  • createdAt: Unix timestamp in milliseconds.
  • lead holds customAttribute1 to customAttribute20 (shortened above) and crmId (HubSpot or Pipedrive ID).
  • Each item of messages has the same message fields as the root (without lead).

Request body:

{
"url": "https://example.com/lgm-docs-webhook",
"name": "Acme prospects",
"campaigns": [
"all"
]
}

Response 200:

{
"id": "00000000-0000-4000-8000-00000000000f",
"url": "https://example.com/lgm-docs-webhook",
"key": "Acme prospects",
"type": "INBOX_EVENT",
"campaigns": [
"all"
],
"audiences": [
"all"
],
"tags": [],
"createdAt": "2026-10-05T09:36:29.532Z"
}

Errors: 400, 401, 403, 429, 500.

Delete Inbox Webhooks

Deletes an inbox webhook by its webhookId. Once deleted, no more inbox events are sent to its URL.

The response is {"success": true} even when no webhook has this ID: check with List inbox webhooks if needed.

Parameter In Required Description
webhookId path yes Webhook id returned at creation or by the list.

Response 200:

{
"success": true
}

Errors: 400, 401, 403, 429, 500.

Edit Inbox Conversation Note

Writes the note (post-it) attached to an inbox conversation.

Provide conversationId, or identify the lead with leadId, email or linkedinUrl. When you identify the lead and it has several conversations (one per identity), narrow it down with identityId, campaignId or campaignName (the campaign’s identity is used), otherwise the request fails with Multiple conversations found ... Be more specific.

  • replace (default): the note becomes note. An empty string clears the note.
  • append: note is added after the existing note, separated by a line -- YYYY-MM-DD HH:mm -- (UTC).

A note is limited to 1,500 characters. In append mode, when the result is longer, the oldest characters are dropped and truncated is true.

Request body:

{
"conversationId": "6650a1b2c3d4e5f6a7b8c940",
"note": "Call ASAP",
"mode": "append"
}

Response 200:

{
"success": true,
"data": {
"conversationId": "6650a1b2c3d4e5f6a7b8c940",
"leadId": "6650a1b2c3d4e5f6a7b8c903",
"note": "Phone number found\n-- 2026-02-11 04:48 --\nCall ASAP",
"mode": "append",
"truncated": false,
"noteLength": 51,
"timestamp": "2026-02-11T04:48:37.200Z"
}
}

Errors: 400, 401, 403, 404, 429, 500.

Archive conversation

Archives a conversation, removing it from the active inbox. Reversible with Unarchive conversation.

Provide conversationId, or identify the lead with leadId, email or linkedinUrl. When the lead has several conversations (one per identity), narrow it down with identityId, campaignId or campaignName.

Request body:

{
"conversationId": "6650a1b2c3d4e5f6a7b8c940"
}

Response 200:

{
"success": true,
"data": {
"conversationId": "6650a1b2c3d4e5f6a7b8c940",
"leadId": "6650a1b2c3d4e5f6a7b8c903",
"archived": true,
"timestamp": "2026-06-04T12:51:10.015Z"
}
}

Errors: 400, 401, 403, 404, 429, 500.

Unarchive conversation

Moves an archived conversation back to the active inbox.

Provide conversationId, or identify the lead with leadId, email or linkedinUrl. When the lead has several conversations (one per identity), narrow it down with identityId, campaignId or campaignName.

Request body:

{
"conversationId": "6650a1b2c3d4e5f6a7b8c940"
}

Response 200:

{
"success": true,
"data": {
"conversationId": "6650a1b2c3d4e5f6a7b8c940",
"leadId": "6650a1b2c3d4e5f6a7b8c903",
"archived": false,
"timestamp": "2026-06-04T12:51:10.015Z"
}
}

Errors: 400, 401, 403, 404, 429, 500.

Snooze conversation

Snoozes a conversation until snoozeUntil: it leaves the active inbox and comes back at that date. Reversible with Unsnooze conversation.

Provide conversationId, or identify the lead with leadId, email or linkedinUrl. When the lead has several conversations (one per identity), narrow it down with identityId, campaignId or campaignName.

A conversation that is already snoozed cannot be snoozed again: unsnooze it first.

Request body:

{
"conversationId": "6650a1b2c3d4e5f6a7b8c940",
"snoozeUntil": "2026-06-12T09:00:00.000Z"
}

Response 200:

{
"success": true,
"data": {
"conversationId": "6650a1b2c3d4e5f6a7b8c940",
"leadId": "6650a1b2c3d4e5f6a7b8c903",
"snoozed": true,
"snoozeUntil": "2026-06-12T09:00:00.000Z",
"timestamp": "2026-06-04T13:02:08.983Z"
}
}

Errors: 400, 401, 403, 404, 429, 500.

Unsnooze conversation

Brings a snoozed conversation back to the active inbox right away.

Provide conversationId, or identify the lead with leadId, email or linkedinUrl. When the lead has several conversations (one per identity), narrow it down with identityId, campaignId or campaignName.

Request body:

{
"conversationId": "6650a1b2c3d4e5f6a7b8c940"
}

Response 200:

{
"success": true,
"data": {
"conversationId": "6650a1b2c3d4e5f6a7b8c940",
"leadId": "6650a1b2c3d4e5f6a7b8c903",
"snoozed": false,
"snoozeUntil": null,
"timestamp": "2026-06-04T13:05:32.746Z"
}
}

Errors: 400, 401, 403, 404, 429, 500.

Search Conversations

Searches and filters the inbox conversations of your workspace: free text, lead, identity, campaign, audience, channel, direction of the last message, dates and flags. Filters combine with AND.

Returns conversation IDs and metadata only, no lead names or message text: get the messages with Get conversation messages.

Results are sorted by lastMessageAt, newest first, by default. Each page holds up to limit conversations (25 by default, 100 max). When hasMore is true, pass nextToken as searchAfter, with the same filters and sort, to get the next page. total is only computed on the first page (it is null on the next ones).

List filters (identityIds, leadIds, status…) take comma-separated values, e.g. status=OPEN,SNOOZED.

favourite and read apply to the member behind the API key (by default, the workspace owner).

Parameter In Required Description
q query no Full-text search on leads (name, company…). Only conversations of the matching leads are returned.
identityIds query no Identity IDs, comma-separated.
leadIds query no Lead IDs, comma-separated.
audienceIds query no Audience IDs, comma-separated.
campaignIds query no Campaign IDs, comma-separated. A campaign filters on its audience and its identity; ignored for each of these when audienceIds or identityIds is also set.
status query no Conversation status, comma-separated.
lastMessageStatus query no Status of the last message, comma-separated. RECEIVED = the lead spoke last, SENT = you spoke last.
lastMessageType query no Channel of the last message, comma-separated. EMAIL and LINKEDIN are the useful values.
lastMessageAtFrom query no Last message at or after this date (Unix timestamp in milliseconds).
lastMessageAtTo query no Last message at or before this date (Unix timestamp in milliseconds).
callCompletedAtFrom query no Call task completed at or after this date (Unix timestamp in milliseconds).
callCompletedAtTo query no Call task completed at or before this date (Unix timestamp in milliseconds).
leadReplied query no Only conversations where the lead has replied (true) or not (false).
unsubscribed query no Filter on unsubscribed leads.
favourite query no true: only the conversations starred by the member. false has no effect.
read query no false: unread conversations only; true: read ones only.
perseverance query no Reply manager follow-up filter. PERSEVERED = conversations already followed up; TO_PERSEVERE = open or curious replies still to follow up.
limit query no Page size.
searchAfter query no Pagination cursor, the nextToken of the previous page. Not a conversation ID.
sortField query no Sort field.
sortDirection query no -1 descending (newest first), 1 ascending.

Response 200:

{
"statusCode": 200,
"data": [],
"total": 0,
"hasMore": false,
"nextToken": null
}

Errors: 400, 401, 403, 429, 500.

GET /conversations/{conversationId}/messages

Section titled “GET /conversations/{conversationId}/messages”

Get Conversation Messages

Returns the 25 most recent messages of a conversation, sorted chronologically (oldest first).

Besides LinkedIn and email messages, the list can hold inbox system entries (channel LGM, COMMENT, MANUAL_TASK…). For these, and for messages with status INFO or SEND_FAILED, direction is received: rely on status to know who wrote a message.

Parameter In Required Description
conversationId path yes The conversation ID (24-char hex ObjectId).
page query no Accepted (integer, 0 or more) but currently has no effect: the 25 most recent messages are always returned.

Response 200:

{
"statusCode": 200,
"data": [
{
"id": "6650a1b2c3d4e5f6a7b8c951",
"channel": "LINKEDIN",
"status": "SENT",
"content": "Hi John, I noticed your work at Acme and wanted to connect.",
"sender": "john-doe-acme",
"createdAt": "2026-03-18T09:00:00.000Z",
"direction": "sent",
"attachments": [],
"isUnsafe": false,
"sentByReplyManager": false
},
{
"id": "6650a1b2c3d4e5f6a7b8c952",
"channel": "LINKEDIN",
"status": "RECEIVED",
"content": "Thanks for reaching out, I'd love to discuss further!",
"sender": "john-doe-acme",
"createdAt": "2026-03-20T16:45:00.000Z",
"direction": "received",
"attachments": [],
"isUnsafe": false,
"sentByReplyManager": false
}
],
"total": 2
}

Errors: 400, 401, 403, 404, 429, 500.

Complete Call Manual Task

Completes a call manual task of a campaign, as when you log the call outcome in the inbox.

The task is marked as done and leaves the call inbox. The outcome (callStatus, and tag if given) is then applied to the lead asynchronously.

Request body:

{
"manualTaskId": "6650a1b2c3d4e5f6a7b8c960",
"callStatus": "DECISIVE",
"tag": "CALL_BOOKED"
}

Response 200:

{
"manualTaskId": "6650a1b2c3d4e5f6a7b8c960",
"callStatus": "DECISIVE",
"tag": "CALL_BOOKED",
"status": "completed"
}

Errors: 400, 401, 403, 404, 429, 500.

Complete Message Manual Task

Completes a custom message manual task: you provide the message that the campaign step will send to the lead.

The message is stored on the pending campaign action, which is then released and sent by the campaign. The channel comes from the campaign step:

  • LinkedIn: message is the text sent. subject, cc, bcc and attachments are ignored.
  • Email: message is the HTML body, subject the subject; cc, bcc and attachments are optional.

Other custom message tasks of the same lead for the same campaign step are removed.

Request body:

{
"manualTaskId": "6650a1b2c3d4e5f6a7b8c961",
"message": "Hi John, congrats on the new role at Acme!"
}

Response 200:

{
"manualTaskId": "6650a1b2c3d4e5f6a7b8c961",
"status": "completed"
}

Errors: 400, 401, 403, 404, 429, 500.

POST /leads/visitors/{provider}/{audienceId}

Section titled “POST /leads/visitors/{provider}/{audienceId}”

Website Visitor Native Webhook

Native webhook for website visitor identification tools (RB2B, Warmly, Vector). Copy this URL into the tool’s dashboard (for RB2B: Integration > La Growth Machine):

https://apiv2.lagrowthmachine.com/flow/leads/visitors/{provider}/{audience}?apikey=YOUR_API_KEY

Each visitor identified by the tool is created (or updated) as a lead and added to the audience.

Make sure to replace YOUR_API_KEY with your actual API key. The key is in the URL because these tools only accept a URL; the Authorization and x-api-key headers also work.

The last segment is the name of the audience (or its ID). If no audience has this name or ID, an audience with this name is created. Defaults used in the tools’ setup: RB2B_Website_Visitor, Warmly_Website_Visitors, Vector_Website_Visitors. Spaces are allowed, URL-encoded: High%20Intent%20Visitors.

The body is the tool’s own payload. Fields are mapped as below; other fields are ignored. The visitor must have at least a LinkedIn URL or an email, or a first name, last name and company (name or website).

RB2B

{
"LinkedIn URL": "linkedinUrl",
"First Name": "firstname",
"Last Name": "lastname",
"Title": "jobTitle",
"Company Name": "companyName",
"Business Email": "proEmail",
"Website": "companyUrl",
"Industry": "industry",
"Employee Count": "customAttribute1",
"Estimate Revenue": "customAttribute2",
"City": "location",
"State": "customAttribute3",
"Zipcode": "customAttribute4",
"Seen At": "customAttribute5",
"Referrer": "customAttribute6",
"Captured URL": "customAttribute7",
"Tags": "customAttribute8"
}

Warmly

{
"LinkedIn URL": "linkedinUrl",
"Business Email": "proEmail",
"First Name": "firstname",
"Last Name": "lastname",
"Title": "jobTitle",
"City": "location",
"State": "customAttribute3",
"Country": "customAttribute4",
"Company Name": "companyName",
"Seen At": "customAttribute5",
"Website": "companyUrl",
"Industry": "industry",
"Employee Count": "customAttribute1",
"Estimate Revenue": "customAttribute2",
"Referrer": "customAttribute6",
"Session Identification Confidence": "customAttribute8",
"Pages Viewed": "customAttribute7"
}

Vector

{
"contact.first_name": "firstname",
"contact.last_name": "lastname",
"contact.email": "proEmail",
"contact.title": "jobTitle",
"contact.company": "companyName",
"contact.linkedin_url": "linkedinUrl",
"segment.id": "customAttribute1",
"segment.name": "customAttribute2"
}

All values are stored as strings.

Parameter In Required Description
provider path yes The visitor identification tool.
audienceId path yes Name of the audience (matched first) or its ID. Created with this name if it does not exist. URL-encode spaces.

Request body:

{
"LinkedIn URL": "https://www.linkedin.com/in/jane-smith-acme",
"First Name": "Jane",
"Last Name": "Smith",
"Title": "CTO",
"Company Name": "Acme",
"Business Email": "jane.smith@acme.com",
"Website": "https://acme.com"
}

Response 200:

{
"leadId": "64b7f0c2a1d3000000000007",
"status": "created",
"isNewLead": true
}

Errors: 400, 401, 404, 429.

List identities

Lists the identities (the LinkedIn and email accounts that send your campaigns) connected to the workspace. Use an identity id wherever an identityId is required, for example to create an audience from a LinkedIn URL or to send a message.

Response 200:

{
"statusCode": 200,
"identities": [
{
"id": "64b7f0c2a1d3000000000004",
"name": "John Doe",
"linkedinConnected": false,
"companyName": null,
"companyUrl": null,
"location": null,
"jobTitle": null
}
]
}

Errors: 401, 429, 500.

List identity preferences

Lists the preferences saved for an identity, sorted by category then key (by key only when filtered on a category). Preferences are key-value pairs, grouped by category, used to personalize the AI-generated content of this identity (tone, language, signature…).

Parameter In Required Description
identityId path yes ID of the identity (24-character hex string).
category query no Only return the preferences of this category.

Response 200:

{
"statusCode": 200,
"data": [
{
"id": "64b7f0c2a1d300000000000e",
"category": "tone",
"key": "formality",
"value": "Casual, first name basis, no jargon.",
"channel": null,
"createdAt": "2026-10-05T09:36:29.395Z",
"updatedAt": "2026-10-05T09:36:29.395Z"
}
],
"total": 1
}

Errors: 400, 401, 404, 429, 500.

Save an identity preference

Creates or updates a preference of an identity. A preference is identified by its category, key and channel: saving the same triple again replaces its value. An identity holds at most 50 preferences.

The response does not return the preference ID; list the preferences to get it.

Parameter In Required Description
identityId path yes ID of the identity (24-character hex string).

Request body:

{
"category": "tone",
"key": "formality",
"value": "Casual, first name basis, no jargon."
}

Response 200:

{
"statusCode": 200,
"data": {
"success": true
}
}

Errors: 400, 401, 404, 429, 500.

DELETE /identities/{identityId}/preferences/{preferenceId}

Section titled “DELETE /identities/{identityId}/preferences/{preferenceId}”

Delete an identity preference

Deletes one preference of an identity. Get the preferenceId from GET /identities/{identityId}/preferences.

Parameter In Required Description
identityId path yes ID of the identity (24-character hex string).
preferenceId path yes ID of the preference to delete (24-character hex string).

Response 200:

{
"statusCode": 200,
"data": {
"success": true
}
}

Errors: 400, 401, 404, 429, 500.

Get the authenticated member

Returns the member (the person) behind the credentials used for the call: their member ID and email. This is the person, not the workspace: in a workspace shared by several members, each member gets their own answer. With a standard API key, the member is the owner of the workspace.

Response 200:

{
"id": "64b7f0c2a1d3000000000001",
"email": "john.doe@acme.com"
}

Errors: 401, 429, 500.

List members

Lists the members (users) of the workspace. Use a member id as the memberId required by some endpoints, such as sending a LinkedIn message.

Response 200:

{
"statusCode": 200,
"members": [
{
"id": "64b7f0c2a1d3000000000001",
"name": "John Doe",
"label": "John Doe"
}
]
}

Errors: 401, 429, 500.

List workspaces

Lists the workspaces the authenticated person can act in: their own workspace and the sub-workspaces (clones) of the same account. Most accounts have a single workspace, in which case multiWorkspace is false and nothing else is needed.

By default every call acts in the workspace of your API key. On a multi-workspace account, add the header X-LGM-Workspace: <workspaceId> (a workspaceId from this list) to any endpoint of the API to act in that workspace instead. The workspace must belong to the same account as your key; otherwise the call is rejected with a 403 (You are not a member of the targeted workspace). On this endpoint, isCurrent marks the workspace the call acted in (the one from the header, or the default one).

Parameter In Required Description
X-LGM-Workspace header no ID of the workspace to act in (see above). Accepted by every endpoint of the API.

Response 200:

{
"multiWorkspace": false,
"workspaces": [
{
"workspaceId": "64b7f0c2a1d3000000000001",
"name": "Acme",
"companyName": "Acme",
"slug": "",
"plan": "PRO",
"identitiesCount": 1,
"isCurrent": true
}
]
}

Errors: 401, 403, 429, 500.

Get Credits

Returns the credit balance for the authenticated workspace, and whether it has CRM and extension access.

  • credits.total — total credits available.
  • credits.perishable — credits that expire soon (already included in total).

Credits are spent by POST /flow/leads/enrich (up to 1, 5 or 20 credits depending on enrichType) and POST /flow/posts/enrich (1 credit).

Response 200:

{
"statusCode": 200,
"credits": {
"total": 1500,
"perishable": 1500
},
"permissions": {
"crmAccess": false,
"extensionAccess": false
}
}

Errors: 400, 401, 429.

Search CRM

Looks up a contact in the CRM connected to the workspace (HubSpot or Pipedrive).

Body — at least one of the following is required

Section titled “Body — at least one of the following is required”
  • email | proEmail | persoEmail (email)
  • OR firstname (+ lastname to narrow down)
  • OR hubspotId / pipedriveId (direct lookup by CRM contact id)
  • lastname, companyName (string, max 255)
  • linkedinUrl (string, max 500), linkedinLongPublicId — used when the LinkedIn URL is mapped to a CRM field.
  1. CRM contact id.
  2. LinkedIn URL, when mapped to a CRM field.
  3. Emails.
  4. firstname + lastname.

Returns one entry per CRM connected to the workspace (empty array when none). When a search matches several contacts, the entry has found: false and tooManyResults: true: refine the search. A matched contact comes with its deals, lifecycle stage, owner and recent activities.

Request body:

{
"proEmail": "john.doe@acme.com"
}

Response 200:

{
"statusCode": 200,
"results": []
}

Errors: 400, 401, 429.