New You can now talk to your Gelee agent from Claude, ChatGPT or Cursor through our MCP. Read the docs →

Reference

Campaigns and analytics

Create, edit, launch and pause campaigns, and read performance, daily numbers and health.

Last updated 22 October 2026

List campaigns

GET/campaigns

Every campaign, newest first: the seats that send, limits, schedule, where leads come from, whether auto top-up is on, prospects per status, and a link into the app. GET /campaigns/{id} adds the full sequence.

curl "https://www.gelee.ai/api/v1/campaigns" \
  -H "Authorization: Bearer gk_your_key"
Response
{ "data": [
    { "id": "9a2c…", "name": "Q4 Founders", "description": null,
      "status": "active", "outreach_type": "outbound",
      "source": { "type": "search_url",
                  "search_url": "https://www.linkedin.com/search/results/people/?keywords=founder" },
      "auto_top_up": { "enabled": true, "type": "search" },
      "daily_limit": 25, "max_targets": 1000,
      "schedule": { "days": [1, 2, 3, 4, 5], "start": "06:00", "end": "23:00" },
      "seats": [ { "seat_id": "SExF…", "name": "Sofia Salazar",
                   "public_identifier": "sofiasalazar",
                   "linkedin_url": "https://www.linkedin.com/in/sofiasalazar" } ],
      "prospect_counts": { "messaged": 120, "replied": 18, "completed": 9 },
      "app_url": "https://web.gelee.ai/campaigns/9a2c…",
      "created_at": "2026-10-02T10:00:00Z", "updated_at": "2026-10-11T18:22:00Z" }
  ] }

Create a campaign

POST/campaignsread_write

It lands as a draft. Only nameis required; everything else defaults to what the in-app create does, including your workspace's default filters.

Body
namestringrequired
The campaign name.
outreach_typestring
outbound (default, starts with a connection request) or inbound (starts with a message to people already connected).
source_typestring
custom_list, linkedin_search, sales_navigator, search_url, post_engagers, post_commenters, post_keywords or website_visitors.
daily_limitinteger
Default 20.
scheduleobject
{ timezone, workingDays, startTime, endTime }.
sequencearray
The message steps, same shape GET /campaigns/{id} returns.
meta.hard_filtersobject
Who it may contact. An impossible filter answers 422 naming the problem.
source_configobject
Source settings, for example a search URL.

POST /campaigns/{id}/duplicate copies a campaign you like (sequence, schedule, filters, AI settings, seats) into a fresh draft, without its leads or stats.

curl -X POST "https://www.gelee.ai/api/v1/campaigns" \
  -H "Authorization: Bearer gk_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Q4 Founders",
    "outreach_type": "outbound",
    "source_type": "custom_list"
  }'
Response
{ "ok": true, "item": { "id": "b41d…", "name": "Q4 Founders", "status": "draft", … } }

Edit a campaign

PATCH/campaigns/{id}read_write

Send only what changes. Same rules as the app editor. Answers with the campaign as GET returns it.

Body
name, description, daily_limit, max_targets, connection_note, schedule
The basics.
stepsarray
Replace the whole sequence.
step_editsarray
Change steps by position.
inmailobject
{ on, subject, body }.
seat_idsarray
Which seats send.
filtersobject
titles, locations, keywords and the rest of the campaign's filters.
searchobject
The LinkedIn search it refills from.
auto_top_upobject
{ "enabled": true } keeps the campaign topped up with new leads when it runs low; false stops it.
curl -X PATCH "https://www.gelee.ai/api/v1/campaigns/9a2c…" \
  -H "Authorization: Bearer gk_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "daily_limit": 30,
    "auto_top_up": {
      "enabled": true
    },
    "filters": {
      "titles": [
        "Founder",
        "CEO"
      ],
      "locations": [
        "Canada"
      ]
    }
  }'

Launch and pause

POST/campaigns/{id}/launchread_write

launch starts a draft or resumes a paused campaign. Real invites and messages then go out from its seats. It is refused while messages still contain [blanks] unless you send allow_unfilled_blanks: true; force_launch: true starts one that is still enriching. POST /campaigns/{id}/pause stops sending and everyone keeps their place.

curl -X POST "https://www.gelee.ai/api/v1/campaigns/9a2c…/launch" \
  -H "Authorization: Bearer gk_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "allow_unfilled_blanks": false
  }'

What each message books

GET/campaigns/{id}/performance

Each step and A/B variant with how many people got it, replied and booked. The same numbers as the campaign's Messages tab.

curl "https://www.gelee.ai/api/v1/campaigns/9a2c…/performance" \
  -H "Authorization: Bearer gk_your_key"

One row per day

GET/analytics/daily

Zero-filled UTC days, up to 92 at a time. GET /analytics is the all-time version.

Query
from, toYYYY-MM-DD
Inclusive. Defaults to the last 30 days.
campaign_idstring
Only this campaign.
seat_idstring
Only this LinkedIn seat.
curl "https://www.gelee.ai/api/v1/analytics/daily?from=2026-10-01&to=2026-10-21" \
  -H "Authorization: Bearer gk_your_key"
Response
{ "data": [
    { "date": "2026-10-01", "invites_sent": 42, "connections_accepted": 11,
      "messages_sent": 23, "replies": 6, "positive_replies": 3,
      "negative_replies": 1, "bookings": 2, "invites_withdrawn": 5 }
  ],
  "meta": { "from": "2026-10-01", "to": "2026-10-21", "timezone": "UTC" } }

Planned versus sent today

GET/health

Is the workspace sending what it should today, and if not, why. capacity counts invites and InMails across your seats; should_send_today is what should be out by the end of the day; delayed lists today's hold-up reasons, biggest first; today is the hour-by-hour line. 30 calls a minute.

verdictMeaning
healthyOn track.
supply_boundNot enough leads ready. Add leads or turn on auto top-up.
engine_boundLeads are ready but sending is behind.
idleNothing is meant to send right now.
curl "https://www.gelee.ai/api/v1/health" \
  -H "Authorization: Bearer gk_your_key"
Response
{ "data": {
    "verdict": "healthy",
    "ready": 412,
    "capacity": 180, "capacity_invites": 150, "capacity_inmails": 30,
    "sent_today": 96, "messages_sent_today": 41,
    "should_send_today": 180,
    "delayed": [ { "reason": "…", "count": 12 } ],
    "today": [ … hour by hour … ] } }