API reference

Campaigns

A campaign takes a persona's hot leads through a flow of steps, likes, comments, follows and DMs, all from your X account, and moves every reply to your inbox. Create one from a template or your own flow, start it, and follow its numbers.

The campaign object

An outreach flow that sends DMs to a persona's hot leads, follows up and hands replies to your inbox.

Attributes

  • idstring
    Unique identifier for the campaign.
  • objectstring
    Always campaign.
  • namestring
    The campaign's name.
  • statusstring
    Whether the campaign is sending.
    draftactivepausedarchived
  • personaobject or null
    The persona whose leads enter the campaign.
  • methodstring or null
    How the campaign's leads were found. Null for older campaigns.
    followingkeywordscompetitor_followerscompetitor_comments
  • min_scoreinteger
    Leads with a lower score never enter the campaign.
  • daily_limitinteger
    The most new leads that enter the campaign a day, 5 to 150. Default 60.
  • statsobject
    Totals since the campaign started. A reply counts when it comes within 7 days of the first DM.
  • created_atstring
    When the campaign was created, ISO 8601.
  • updated_atstring
    When the campaign last changed, ISO 8601.
Campaign object
{
  "id": "c7RkQ2wLxe",
  "object": "campaign",
  "name": "Tipsters warm intro",
  "status": "active",
  "persona": {
    "id": "lvWBPnytpS",
    "name": "Tipsters"
  },
  "method": "keywords",
  "min_score": 60,
  "daily_limit": 50,
  "stats": {
    "leads": 640,
    "dms_sent": 412,
    "replies": 57,
    "reply_rate": 13.8
  },
  "created_at": "2026-09-14T09:21:05.300Z",
  "updated_at": "2026-11-06T07:45:12.904Z"
}

List campaigns

GET/v1/campaignsread scopeMCPlist_campaigns

Returns your campaigns, newest first.

Query parameters

  • statusstring
    Only campaigns with this status.
    draftactivepausedarchived
  • personastring
    Only campaigns of this persona ID.
  • limitinteger
    How many objects to return, from 1 to 100. Defaults to 25.
  • cursorstring
    The next_cursor of the previous page, to get the page after it. See Pagination.

Returns

A list of campaign objects.

Errors

GET/v1/campaigns
curl -G https://gemlead.ai/api/v1/campaigns \
  -H "Authorization: Bearer $GEMLEAD_API_KEY" \
  -d status=active
Response200
{
  "object": "list",
  "data": [
    {
      "id": "c7RkQ2wLxe",
      "object": "campaign",
      "name": "Tipsters warm intro",
      "status": "active",
      "persona": {
        "id": "lvWBPnytpS",
        "name": "Tipsters"
      },
      "method": "keywords",
      "min_score": 60,
      "daily_limit": 50,
      "stats": {
        "leads": 640,
        "dms_sent": 412,
        "replies": 57,
        "reply_rate": 13.8
      },
      "created_at": "2026-09-14T09:21:05.300Z",
      "updated_at": "2026-11-06T07:45:12.904Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}

Retrieve a campaign

GET/v1/campaigns/:idread scope

Returns one campaign.

Path parameters

  • idstringRequired
    The campaign's ID.

Returns

A campaign object.

Errors

GET/v1/campaigns/:id
curl https://gemlead.ai/api/v1/campaigns/c7RkQ2wLxe \
  -H "Authorization: Bearer $GEMLEAD_API_KEY"
Response200
{
  "id": "c7RkQ2wLxe",
  "object": "campaign",
  "name": "Tipsters warm intro",
  "status": "active",
  "persona": {
    "id": "lvWBPnytpS",
    "name": "Tipsters"
  },
  "method": "keywords",
  "min_score": 60,
  "daily_limit": 50,
  "stats": {
    "leads": 640,
    "dms_sent": 412,
    "replies": 57,
    "reply_rate": 13.8
  },
  "created_at": "2026-09-14T09:21:05.300Z",
  "updated_at": "2026-11-06T07:45:12.904Z"
}

Create a campaign

POST/v1/campaignswrite scopeMCPcreate_campaign

Creates a campaign as a draft. Nothing goes out until you start it. Without template or flow, the campaign gets the app's default, the Warm up template for B2B and Instant for B2C.

Body parameters

  • persona_idstringRequired
    The persona whose leads enter it.
  • namestringRequired
    The campaign's name, up to 100 characters.
  • methodstring
    Only leads found this way enter. Leave it out for every lead of the persona.
    followingkeywordscompetitor_followerscompetitor_comments
  • min_scoreinteger
    Only leads with at least this score enter, 0 to 100. Default 60.
  • daily_limitinteger
    The most new leads that enter a day, 5 to 150. Default 60. Each new lead starts with Radar, which adds it to a private X list of the account, and X blocks those adds for 6 to 24 hours above a few hundred a day.
  • lead_orderstring
    Which leads enter first. Default highest, or newest for the keyword and competitor methods.
    highestlowestshufflenewest
  • templatestring
    The flow to start from. See List campaign templates. Not with flow.
    warm_upinstantdirect_messageblank
  • flowobject
    Your own flow, instead of a template.

Returns

The new campaign object, its status at draft.

Errors

POST/v1/campaigns
curl -X POST https://gemlead.ai/api/v1/campaigns \
  -H "Authorization: Bearer $GEMLEAD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "persona_id": "lvWBPnytpS",
    "name": "Tipsters warm intro",
    "method": "keywords",
    "daily_limit": 50,
    "template": "instant"
  }'
Response200
{
  "id": "c7RkQ2wLxe",
  "object": "campaign",
  "name": "Tipsters warm intro",
  "status": "draft",
  "persona": {
    "id": "lvWBPnytpS",
    "name": "Tipsters"
  },
  "method": "keywords",
  "min_score": 60,
  "daily_limit": 50,
  "stats": {
    "leads": 0,
    "dms_sent": 0,
    "replies": 0,
    "reply_rate": null
  },
  "created_at": "2026-09-14T09:21:05.300Z",
  "updated_at": "2026-11-06T07:45:12.904Z"
}

Start a campaign

POST/v1/campaigns/:campaign_id/startwrite scopeMCPset_campaign_status

Starts a draft or resumes a paused campaign. Leads enter and the steps go out from your X account.

Path parameters

  • campaign_idstringRequired
    The campaign's ID.

Returns

The campaign object, its status at active.

Errors

POST/v1/campaigns/:campaign_id/start
curl -X POST \
  https://gemlead.ai/api/v1/campaigns/c7RkQ2wLxe/start \
  -H "Authorization: Bearer $GEMLEAD_API_KEY"
Response200
{
  "id": "c7RkQ2wLxe",
  "object": "campaign",
  "name": "Tipsters warm intro",
  "status": "active",
  "persona": {
    "id": "lvWBPnytpS",
    "name": "Tipsters"
  },
  "method": "keywords",
  "min_score": 60,
  "daily_limit": 50,
  "stats": {
    "leads": 640,
    "dms_sent": 412,
    "replies": 57,
    "reply_rate": 13.8
  },
  "created_at": "2026-09-14T09:21:05.300Z",
  "updated_at": "2026-11-06T07:45:12.904Z"
}

Pause a campaign

POST/v1/campaigns/:campaign_id/pausewrite scopeMCPset_campaign_status

Pauses a campaign. No new step goes out until you start it again, and leads keep their place.

Path parameters

  • campaign_idstringRequired
    The campaign's ID.

Returns

The campaign object, its status at paused.

Errors

POST/v1/campaigns/:campaign_id/pause
curl -X POST \
  https://gemlead.ai/api/v1/campaigns/c7RkQ2wLxe/pause \
  -H "Authorization: Bearer $GEMLEAD_API_KEY"
Response200
{
  "id": "c7RkQ2wLxe",
  "object": "campaign",
  "name": "Tipsters warm intro",
  "status": "paused",
  "persona": {
    "id": "lvWBPnytpS",
    "name": "Tipsters"
  },
  "method": "keywords",
  "min_score": 60,
  "daily_limit": 50,
  "stats": {
    "leads": 640,
    "dms_sent": 412,
    "replies": 57,
    "reply_rate": 13.8
  },
  "created_at": "2026-09-14T09:21:05.300Z",
  "updated_at": "2026-11-06T07:45:12.904Z"
}

Archive a campaign

POST/v1/campaigns/:campaign_id/archivewrite scopeMCPset_campaign_status

Ends a campaign for good. Its history and its conversations stay, and Duplicate a campaign runs it again.

Path parameters

  • campaign_idstringRequired
    The campaign's ID.

Returns

The campaign object, its status at archived.

Errors

POST/v1/campaigns/:campaign_id/archive
curl -X POST \
  https://gemlead.ai/api/v1/campaigns/c7RkQ2wLxe/archive \
  -H "Authorization: Bearer $GEMLEAD_API_KEY"
Response200
{
  "id": "c7RkQ2wLxe",
  "object": "campaign",
  "name": "Tipsters warm intro",
  "status": "archived",
  "persona": {
    "id": "lvWBPnytpS",
    "name": "Tipsters"
  },
  "method": "keywords",
  "min_score": 60,
  "daily_limit": 50,
  "stats": {
    "leads": 640,
    "dms_sent": 412,
    "replies": 57,
    "reply_rate": 13.8
  },
  "created_at": "2026-09-14T09:21:05.300Z",
  "updated_at": "2026-11-06T07:45:12.904Z"
}

Duplicate a campaign

POST/v1/campaigns/:campaign_id/duplicatewrite scopeMCPduplicate_campaign

Copies a campaign's settings and flow, without its leads, as a new draft.

Path parameters

  • campaign_idstringRequired
    The campaign's ID.

Returns

The new campaign object, its status at draft.

Errors

POST/v1/campaigns/:campaign_id/duplicate
curl -X POST \
  https://gemlead.ai/api/v1/campaigns/c7RkQ2wLxe/duplicate \
  -H "Authorization: Bearer $GEMLEAD_API_KEY"
Response200
{
  "id": "c2VbN6mQrz",
  "object": "campaign",
  "name": "Tipsters warm intro copy",
  "status": "draft",
  "persona": {
    "id": "lvWBPnytpS",
    "name": "Tipsters"
  },
  "method": "keywords",
  "min_score": 60,
  "daily_limit": 50,
  "stats": {
    "leads": 0,
    "dms_sent": 0,
    "replies": 0,
    "reply_rate": null
  },
  "created_at": "2026-11-06T07:45:12.904Z",
  "updated_at": "2026-11-06T07:45:12.904Z"
}

Delete a campaign

DELETE/v1/campaigns/:campaign_idwrite scopeMCPdelete_campaign

Deletes a campaign. Its leads and their conversations stay. This cannot be undone.

Path parameters

  • campaign_idstringRequired
    The campaign's ID.

Returns

An object with the campaign's id and deleted set to true.

Errors

DELETE/v1/campaigns/:campaign_id
curl -X DELETE \
  https://gemlead.ai/api/v1/campaigns/c7RkQ2wLxe \
  -H "Authorization: Bearer $GEMLEAD_API_KEY"
Response200
{
  "id": "c7RkQ2wLxe",
  "object": "campaign",
  "deleted": true
}

The campaign stats object

A campaign's results over a period, in total and day by day.

Attributes

  • objectstring
    Always campaign_stats.
  • campaign_idstring
    The campaign's ID.
  • fromstring
    The first day, YYYY-MM-DD.
  • tostring
    The last day, YYYY-MM-DD.
  • totalsobject
    leads_added, dms_sent, replies and reply_rate over the period.
  • dailyarray of objects
    One entry a day with its date, dms_sent and replies.
Campaign stats object
{
  "object": "campaign_stats",
  "campaign_id": "c7RkQ2wLxe",
  "from": "2026-10-08",
  "to": "2026-11-06",
  "totals": {
    "leads_added": 640,
    "dms_sent": 412,
    "replies": 57,
    "reply_rate": 13.8
  },
  "daily": [
    {
      "date": "2026-11-04",
      "dms_sent": 22,
      "replies": 3
    },
    {
      "date": "2026-11-05",
      "dms_sent": 25,
      "replies": 4
    },
    {
      "date": "2026-11-06",
      "dms_sent": 9,
      "replies": 1
    }
  ]
}

Retrieve campaign stats

GET/v1/campaigns/:id/statsread scopeMCPget_campaign_stats

Returns a campaign's results over a period, in total and day by day. dms_sent counts the first DMs sent in the period, replies the replies of those leads within 7 days. Days are UTC dates.

Path parameters

  • idstringRequired
    The campaign's ID.

Query parameters

  • fromstring
    The first day, YYYY-MM-DD. Defaults to 30 days ago.
  • tostring
    The last day, YYYY-MM-DD. Defaults to today.

Returns

A campaign stats object.

Errors

GET/v1/campaigns/:id/stats
curl -G https://gemlead.ai/api/v1/campaigns/c7RkQ2wLxe/stats \
  -H "Authorization: Bearer $GEMLEAD_API_KEY" \
  -d from=2026-10-08 \
  -d to=2026-11-06
Response200
{
  "object": "campaign_stats",
  "campaign_id": "c7RkQ2wLxe",
  "from": "2026-10-08",
  "to": "2026-11-06",
  "totals": {
    "leads_added": 640,
    "dms_sent": 412,
    "replies": 57,
    "reply_rate": 13.8
  },
  "daily": [
    {
      "date": "2026-11-04",
      "dms_sent": 22,
      "replies": 3
    },
    {
      "date": "2026-11-05",
      "dms_sent": 25,
      "replies": 4
    },
    {
      "date": "2026-11-06",
      "dms_sent": 9,
      "replies": 1
    }
  ]
}

The campaign settings object

A campaign's settings and its whole flow, every step with its ID and options.

Attributes

  • objectstring
    Always campaign_settings.
  • campaign_idstring
    The campaign's ID.
  • persona_idstring or null
    The persona whose leads enter it.
  • namestring
    The campaign's name.
  • statusstring
    Where the campaign stands.
    draftactivepausedarchived
  • methodstring or null
    Only leads found this way enter. null lets every lead of the persona in.
    followingkeywordscompetitor_followerscompetitor_comments
  • min_scoreinteger
    Only leads with at least this score enter, 0 to 100.
  • daily_limitinteger
    The most new leads that enter a day, 5 to 150.
  • lead_orderstring
    Which leads enter first. highest score, lowest, shuffle or newest found.
    highestlowestshufflenewest
  • flowobject
    Its flow.
  • updated_atstring
    When it last changed, ISO 8601.
Campaign settings object
{
  "object": "campaign_settings",
  "campaign_id": "c7RkQ2wLxe",
  "persona_id": "lvWBPnytpS",
  "name": "Tipsters warm intro",
  "status": "active",
  "method": "keywords",
  "min_score": 60,
  "daily_limit": 50,
  "lead_order": "newest",
  "flow": {
    "steps": [
      {
        "id": "in-like",
        "type": "like",
        "label": "Like",
        "count": 1
      },
      {
        "id": "in-follow",
        "type": "follow",
        "label": "Follow"
      },
      {
        "id": "in-timer",
        "type": "timer",
        "label": "Timer",
        "duration": "1d"
      },
      {
        "id": "in-inbox",
        "type": "can_dm",
        "label": "Inbox opened test",
        "if_yes": [
          {
            "id": "in-dm",
            "type": "send_dm",
            "label": "Direct message",
            "mode": "ai",
            "dm_kind": "cold",
            "language": "auto",
            "instructions": null,
            "template": null
          },
          {
            "id": "in-comment-bridge",
            "type": "comment",
            "label": "Comment",
            "comment_type": "bridge",
            "language": "auto",
            "instructions": null
          }
        ],
        "if_no": [
          {
            "id": "in-comment-closed",
            "type": "comment",
            "label": "Comment",
            "comment_type": "inbox_closed",
            "language": "auto",
            "instructions": null
          }
        ]
      },
      {
        "id": "in-timer-followup",
        "type": "timer",
        "label": "Timer",
        "duration": "3d"
      },
      {
        "id": "in-dm-followup",
        "type": "send_dm",
        "label": "Direct message",
        "mode": "ai",
        "dm_kind": "follow_up",
        "language": "auto",
        "instructions": null,
        "template": null
      },
      {
        "id": "in-cleaner",
        "type": "cleaner",
        "label": "Cleaner",
        "unfollow": true,
        "delete_comments": true,
        "delete_likes": true
      }
    ]
  },
  "updated_at": "2026-11-06T07:45:12.904Z"
}

Retrieve campaign settings

GET/v1/campaigns/:campaign_id/settingsread scopeMCPget_campaign_settings

Returns a campaign's settings and its flow, every step with its ID and options. Read it before you edit the flow.

Path parameters

  • campaign_idstringRequired
    The campaign's ID.

Returns

A campaign settings object.

Errors

GET/v1/campaigns/:campaign_id/settings
curl https://gemlead.ai/api/v1/campaigns/c7RkQ2wLxe/settings \
  -H "Authorization: Bearer $GEMLEAD_API_KEY"
Response200
{
  "object": "campaign_settings",
  "campaign_id": "c7RkQ2wLxe",
  "persona_id": "lvWBPnytpS",
  "name": "Tipsters warm intro",
  "status": "active",
  "method": "keywords",
  "min_score": 60,
  "daily_limit": 50,
  "lead_order": "newest",
  "flow": {
    "steps": [
      {
        "id": "in-like",
        "type": "like",
        "label": "Like",
        "count": 1
      },
      {
        "id": "in-follow",
        "type": "follow",
        "label": "Follow"
      },
      {
        "id": "in-timer",
        "type": "timer",
        "label": "Timer",
        "duration": "1d"
      },
      {
        "id": "in-inbox",
        "type": "can_dm",
        "label": "Inbox opened test",
        "if_yes": [
          {
            "id": "in-dm",
            "type": "send_dm",
            "label": "Direct message",
            "mode": "ai",
            "dm_kind": "cold",
            "language": "auto",
            "instructions": null,
            "template": null
          },
          {
            "id": "in-comment-bridge",
            "type": "comment",
            "label": "Comment",
            "comment_type": "bridge",
            "language": "auto",
            "instructions": null
          }
        ],
        "if_no": [
          {
            "id": "in-comment-closed",
            "type": "comment",
            "label": "Comment",
            "comment_type": "inbox_closed",
            "language": "auto",
            "instructions": null
          }
        ]
      },
      {
        "id": "in-timer-followup",
        "type": "timer",
        "label": "Timer",
        "duration": "3d"
      },
      {
        "id": "in-dm-followup",
        "type": "send_dm",
        "label": "Direct message",
        "mode": "ai",
        "dm_kind": "follow_up",
        "language": "auto",
        "instructions": null,
        "template": null
      },
      {
        "id": "in-cleaner",
        "type": "cleaner",
        "label": "Cleaner",
        "unfollow": true,
        "delete_comments": true,
        "delete_likes": true
      }
    ]
  },
  "updated_at": "2026-11-06T07:45:12.904Z"
}

Update campaign settings

PATCH/v1/campaigns/:campaign_id/settingswrite scopeMCPupdate_campaign

Changes the settings you send and keeps the others. A flow replaces the whole flow, even on a running campaign. Keep the IDs of the steps you keep, leads waiting on them stay there, and the app moves the others.

Path parameters

  • campaign_idstringRequired
    The campaign's ID.

Body parameters

  • namestring
    The campaign's name, up to 100 characters.
  • methodstring or null
    Only leads found this way enter, null for every lead of the persona.
    followingkeywordscompetitor_followerscompetitor_comments
  • min_scoreinteger
    Only leads with at least this score enter, 0 to 100.
  • daily_limitinteger
    The most new leads that enter a day, 5 to 150.
  • lead_orderstring
    Which leads enter first. highest score, lowest, shuffle or newest found.
    highestlowestshufflenewest
  • flowobject
    The new flow, in full.

Returns

The updated campaign settings object.

Errors

PATCH/v1/campaigns/:campaign_id/settings
curl -X PATCH \
  https://gemlead.ai/api/v1/campaigns/c7RkQ2wLxe/settings \
  -H "Authorization: Bearer $GEMLEAD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "daily_limit": 80,
    "min_score": 70
  }'
Response200
{
  "object": "campaign_settings",
  "campaign_id": "c7RkQ2wLxe",
  "persona_id": "lvWBPnytpS",
  "name": "Tipsters warm intro",
  "status": "active",
  "method": "keywords",
  "min_score": 70,
  "daily_limit": 80,
  "lead_order": "newest",
  "flow": {
    "steps": [
      {
        "id": "in-like",
        "type": "like",
        "label": "Like",
        "count": 1
      },
      {
        "id": "in-follow",
        "type": "follow",
        "label": "Follow"
      },
      {
        "id": "in-timer",
        "type": "timer",
        "label": "Timer",
        "duration": "1d"
      },
      {
        "id": "in-inbox",
        "type": "can_dm",
        "label": "Inbox opened test",
        "if_yes": [
          {
            "id": "in-dm",
            "type": "send_dm",
            "label": "Direct message",
            "mode": "ai",
            "dm_kind": "cold",
            "language": "auto",
            "instructions": null,
            "template": null
          },
          {
            "id": "in-comment-bridge",
            "type": "comment",
            "label": "Comment",
            "comment_type": "bridge",
            "language": "auto",
            "instructions": null
          }
        ],
        "if_no": [
          {
            "id": "in-comment-closed",
            "type": "comment",
            "label": "Comment",
            "comment_type": "inbox_closed",
            "language": "auto",
            "instructions": null
          }
        ]
      },
      {
        "id": "in-timer-followup",
        "type": "timer",
        "label": "Timer",
        "duration": "3d"
      },
      {
        "id": "in-dm-followup",
        "type": "send_dm",
        "label": "Direct message",
        "mode": "ai",
        "dm_kind": "follow_up",
        "language": "auto",
        "instructions": null,
        "template": null
      },
      {
        "id": "in-cleaner",
        "type": "cleaner",
        "label": "Cleaner",
        "unfollow": true,
        "delete_comments": true,
        "delete_likes": true
      }
    ]
  },
  "updated_at": "2026-11-06T07:45:12.904Z"
}

The flow object

The steps a campaign runs for each lead, in order. A fork runs if_yes or if_no, then the steps after it. A flow holds 60 steps at most, forks go 2 deep and step IDs are unique. A step only takes the options of its type. Every like, comment, follow and DM goes out from your X account. The canvas in the app lays the flow out the same way as its own templates.

Attributes

  • stepsarray of objectsRequired
    The steps, in order.
Flow object
{
  "steps": [
    {
      "id": "in-like",
      "type": "like",
      "label": "Like",
      "count": 1
    },
    {
      "id": "in-follow",
      "type": "follow",
      "label": "Follow"
    },
    {
      "id": "in-timer",
      "type": "timer",
      "label": "Timer",
      "duration": "1d"
    },
    {
      "id": "in-inbox",
      "type": "can_dm",
      "label": "Inbox opened test",
      "if_yes": [
        {
          "id": "in-dm",
          "type": "send_dm",
          "label": "Direct message",
          "mode": "ai",
          "dm_kind": "cold",
          "language": "auto",
          "instructions": null,
          "template": null
        },
        {
          "id": "in-comment-bridge",
          "type": "comment",
          "label": "Comment",
          "comment_type": "bridge",
          "language": "auto",
          "instructions": null
        }
      ],
      "if_no": [
        {
          "id": "in-comment-closed",
          "type": "comment",
          "label": "Comment",
          "comment_type": "inbox_closed",
          "language": "auto",
          "instructions": null
        }
      ]
    },
    {
      "id": "in-timer-followup",
      "type": "timer",
      "label": "Timer",
      "duration": "3d"
    },
    {
      "id": "in-dm-followup",
      "type": "send_dm",
      "label": "Direct message",
      "mode": "ai",
      "dm_kind": "follow_up",
      "language": "auto",
      "instructions": null,
      "template": null
    },
    {
      "id": "in-cleaner",
      "type": "cleaner",
      "label": "Cleaner",
      "unfollow": true,
      "delete_comments": true,
      "delete_likes": true
    }
  ]
}

The campaign lead object

A lead in a campaign, the step it is on and what the campaign posted for it.

Attributes

  • objectstring
    Always campaign_lead.
  • idstring or null
    Unique identifier for the lead's run in this campaign.
  • campaign_idstring
    The campaign's ID.
  • lead_idstring or null
    The lead's ID.
  • statusstring
    The lead's status in the campaign, like waiting, replied, completed or failed.
  • stepstring or null
    The label of the step it is on.
  • entered_atstring or null
    When it entered the campaign, ISO 8601.
  • leadobject or null
    The lead.
  • postedobject
    What went out for this lead.
Campaign lead object
{
  "object": "campaign_lead",
  "id": "cl9TzQ4wKa",
  "campaign_id": "c7RkQ2wLxe",
  "lead_id": "msgOtJ8dvT",
  "status": "replied",
  "step": "Direct message",
  "entered_at": "2026-11-05T15:00:08.000Z",
  "lead": {
    "id": "msgOtJ8dvT",
    "object": "lead",
    "profile": {
      "x_user_id": "1460283925",
      "username": "jane_builds",
      "name": "Jane Doe",
      "bio": "Runs a paid trading community. Daily setups, no hype.",
      "followers_count": 12400,
      "following_count": 380,
      "location": "Austin, TX",
      "website": "https://janedoe.com",
      "profile_image_url": "https://pbs.twimg.com/profile_images/1460283925/jane_400x400.jpg",
      "verified": true,
      "url": "https://x.com/jane_builds"
    },
    "score": 86,
    "score_reason": "Runs a paid trading community and asks how to collect payments for it.",
    "hot": true,
    "status": "scored",
    "persona": {
      "id": "lvWBPnytpS",
      "name": "Tipsters"
    },
    "campaign": null,
    "conversation_id": null,
    "locked_to": null,
    "found_at": "2026-11-05T14:02:11.482Z",
    "scored_at": "2026-11-05T14:03:40.117Z",
    "updated_at": "2026-11-05T14:03:40.117Z",
    "metadata": {}
  },
  "posted": {
    "comments": [],
    "dms": [
      {
        "text": "Hey Jane, saw you want a real checkout for your picks. Want to see how others charge for their Discord?",
        "message_id": "1985300011122233344",
        "at": "2026-11-06T07:58:21.000Z"
      }
    ]
  }
}

List campaign leads

GET/v1/campaigns/:campaign_id/leadsread scopeMCPlist_campaign_leads

Returns a campaign's leads by where they are in the flow, with what the campaign posted for each.

Path parameters

  • campaign_idstringRequired
    The campaign's ID.

Query parameters

  • stagestring
    all is every lead that entered. step passed the step step_id, fork took one branch of it. dm_sent, replied, finished for completed or replied, completed for every step done without a reply. Default all.
    allstepforkdm_sentrepliedfinishedcompleted
  • step_idstring
    With step or fork, the step's ID.
  • branchstring
    With fork, the branch.
    yesno
  • skippedboolean
    With step on a comment or DM step, the leads it posted nothing for.
  • qstring
    Search by name or username.
  • limitinteger
    How many objects to return, from 1 to 100. Defaults to 25.
  • cursorstring
    The next_cursor of the previous page, to get the page after it. See Pagination.

Returns

A list of campaign lead objects, with total_count.

Errors

GET/v1/campaigns/:campaign_id/leads
curl -G https://gemlead.ai/api/v1/campaigns/c7RkQ2wLxe/leads \
  -H "Authorization: Bearer $GEMLEAD_API_KEY" \
  -d stage=replied
Response200
{
  "object": "list",
  "data": [
    {
      "object": "campaign_lead",
      "id": "cl9TzQ4wKa",
      "campaign_id": "c7RkQ2wLxe",
      "lead_id": "msgOtJ8dvT",
      "status": "replied",
      "step": "Direct message",
      "entered_at": "2026-11-05T15:00:08.000Z",
      "lead": {
        "id": "msgOtJ8dvT",
        "object": "lead",
        "profile": {
          "x_user_id": "1460283925",
          "username": "jane_builds",
          "name": "Jane Doe",
          "bio": "Runs a paid trading community. Daily setups, no hype.",
          "followers_count": 12400,
          "following_count": 380,
          "location": "Austin, TX",
          "website": "https://janedoe.com",
          "profile_image_url": "https://pbs.twimg.com/profile_images/1460283925/jane_400x400.jpg",
          "verified": true,
          "url": "https://x.com/jane_builds"
        },
        "score": 86,
        "score_reason": "Runs a paid trading community and asks how to collect payments for it.",
        "hot": true,
        "status": "scored",
        "persona": {
          "id": "lvWBPnytpS",
          "name": "Tipsters"
        },
        "campaign": null,
        "conversation_id": null,
        "locked_to": null,
        "found_at": "2026-11-05T14:02:11.482Z",
        "scored_at": "2026-11-05T14:03:40.117Z",
        "updated_at": "2026-11-05T14:03:40.117Z",
        "metadata": {}
      },
      "posted": {
        "comments": [],
        "dms": [
          {
            "text": "Hey Jane, saw you want a real checkout for your picks. Want to see how others charge for their Discord?",
            "message_id": "1985300011122233344",
            "at": "2026-11-06T07:58:21.000Z"
          }
        ]
      }
    }
  ],
  "has_more": true,
  "next_cursor": "eyJzIjoiMjAyNi0xMS0wNVQxNDowMzo0MC4xMTdaIn0",
  "total_count": 57
}

A campaign's activity by day over 14 days or by hour over 24 hours, as on its chart in the app.

Attributes

  • objectstring
    Always campaign_trends.
  • campaign_idstring
    The campaign's ID.
  • rangestring
    The period.
    14d24h
  • timezonestring
    The time zone of the buckets.
  • bucketsarray of objects
    One a day or an hour, each with its key and the metrics asked for.
  • totalsobject
    Since the campaign started, its started, sent, replies and follows, with last_sent_at and last_reply_at.
  • truncatedboolean
    true when the campaign is too big to count in full.
  • generated_atstring
    When the numbers were read, ISO 8601.
Campaign trends object
{
  "object": "campaign_trends",
  "campaign_id": "c7RkQ2wLxe",
  "range": "14d",
  "timezone": "Europe/Paris",
  "buckets": [
    {
      "key": "2026-11-04",
      "started": 48,
      "sent": 22,
      "replies": 3,
      "follows": 9
    },
    {
      "key": "2026-11-05",
      "started": 50,
      "sent": 25,
      "replies": 4,
      "follows": 11
    },
    {
      "key": "2026-11-06",
      "started": 21,
      "sent": 9,
      "replies": 1,
      "follows": 4
    }
  ],
  "totals": {
    "started": 640,
    "sent": 412,
    "replies": 57,
    "follows": 133,
    "last_sent_at": "2026-11-06T08:20:03.000Z",
    "last_reply_at": "2026-11-06T08:12:44.000Z"
  },
  "truncated": false,
  "generated_at": "2026-11-06T08:30:00.000Z"
}
GET/v1/campaigns/:campaign_id/trendsread scopeMCPget_campaign_trends

Returns the leads started, DMs sent, replies and follows of a campaign by day over 14 days, or by hour over 24 hours.

Path parameters

  • campaign_idstringRequired
    The campaign's ID.

Query parameters

  • metricsstring
    Any of started, sent, replies and follows, comma separated. Default all four.
    startedsentrepliesfollows
  • rangestring
    14d by day, 24h by hour. Default 14d.
    14d24h
  • timezonestring
    The IANA time zone of the buckets, like Europe/Paris. Default UTC.

Returns

A campaign trends object.

Errors

GET/v1/campaigns/:campaign_id/trends
curl -G \
  https://gemlead.ai/api/v1/campaigns/c7RkQ2wLxe/trends \
  -H "Authorization: Bearer $GEMLEAD_API_KEY" \
  -d range=14d \
  --data-urlencode "timezone=Europe/Paris"
Response200
{
  "object": "campaign_trends",
  "campaign_id": "c7RkQ2wLxe",
  "range": "14d",
  "timezone": "Europe/Paris",
  "buckets": [
    {
      "key": "2026-11-04",
      "started": 48,
      "sent": 22,
      "replies": 3,
      "follows": 9
    },
    {
      "key": "2026-11-05",
      "started": 50,
      "sent": 25,
      "replies": 4,
      "follows": 11
    },
    {
      "key": "2026-11-06",
      "started": 21,
      "sent": 9,
      "replies": 1,
      "follows": 4
    }
  ],
  "totals": {
    "started": 640,
    "sent": 412,
    "replies": 57,
    "follows": 133,
    "last_sent_at": "2026-11-06T08:20:03.000Z",
    "last_reply_at": "2026-11-06T08:12:44.000Z"
  },
  "truncated": false,
  "generated_at": "2026-11-06T08:30:00.000Z"
}

The campaign template object

A flow to start a campaign from, as the app offers it. Every template's flow is a valid flow for Create a campaign.

Attributes

  • objectstring
    Always campaign_template.
  • idstring
    The template's ID, for the template parameter.
    warm_upinstantdirect_messageblank
  • descriptionstring
    What the flow does, in a few sentences.
  • defaultboolean
    Whether the app picks it for this method and market.
  • flowobject
    Its flow.
Campaign template object
{
  "object": "campaign_template",
  "id": "direct_message",
  "description": "Radar waits until they are online, then the message. No warm up.",
  "default": false,
  "flow": {
    "steps": [
      {
        "id": "dm-snapshot",
        "type": "snapshot",
        "label": "Radar"
      },
      {
        "id": "dm-send",
        "type": "send_dm",
        "label": "Direct message",
        "mode": "ai",
        "dm_kind": "cold",
        "language": "auto",
        "instructions": null,
        "template": null
      }
    ]
  }
}

List campaign templates

GET/v1/campaign_templatesread scopeMCPlist_campaign_templates

Returns the app's templates with their whole flows, the best reference for every step type and option. Warm up likes, comments and follows before the DM. Instant does it at once and DMs a day later. Direct message only sends the DM.

Query parameters

  • methodstring
    The campaign's method. The Instant flow changes with it.
    followingkeywordscompetitor_followerscompetitor_comments
  • marketstring
    The persona's market. In b2c, Direct message sends at once, without Radar.
    b2bb2c

Returns

A list of campaign template objects.

Errors

GET/v1/campaign_templates
curl -G https://gemlead.ai/api/v1/campaign_templates \
  -H "Authorization: Bearer $GEMLEAD_API_KEY" \
  -d method=following \
  -d market=b2b
Response200
{
  "object": "list",
  "data": [
    {
      "object": "campaign_template",
      "id": "direct_message",
      "description": "Radar waits until they are online, then the message. No warm up.",
      "default": false,
      "flow": {
        "steps": [
          {
            "id": "dm-snapshot",
            "type": "snapshot",
            "label": "Radar"
          },
          {
            "id": "dm-send",
            "type": "send_dm",
            "label": "Direct message",
            "mode": "ai",
            "dm_kind": "cold",
            "language": "auto",
            "instructions": null,
            "template": null
          }
        ]
      }
    }
  ],
  "has_more": false,
  "next_cursor": null
}