Developer guide

How to create a Coolie agent with the API

Send POST /api/v1/agents with a name, an ICP (job titles, and industries, locations and company sizes taken from GET /api/v1/icp-options), three to five signal ids from GET /api/v1/signals whose available is true, and findEmail and findPhone. Coolie answers with the agent's id and launches its first search at once; GET /api/v1/agents/{agentId} then says what each search found and when the next one runs.

Updated

Before you start

  • An API key: in Coolie, open Settings → API keys, name the key and click Create key. It is shown once, so keep it in an environment variable (COOLIE_API_KEY in these examples). It acts as you, with your plan, your credits and your agents.
  • A Coolie account with its 7-day free trial started: the API answers 402 trial_required before that. A call costs what the same action costs in the app, and nothing more.
  • A free agent on your plan: creating one uses one of your plan's agents (403 agent_quota once they are all in use).

Pick the signals

GET /api/v1/signals lists the buying signals an agent can watch. Use the ids whose available is true: a signal held back, or without a source connected right now, is refused.

curl
curl https://trycoolie.ai/api/v1/signals \
  -H "Authorization: Bearer $COOLIE_API_KEY"
Answer (excerpt)
{
  "signals": [
    {
      "id": "hiring",
      "name": "Hiring",
      "description": "Companies actively hiring, to find the right profiles",
      "available": true
    },
    {
      "id": "competitor-churn",
      "name": "Competitor Churn",
      "description": "Find companies that recently churned from your competitors",
      "available": true
    }
  ]
}

Pick the ICP's values

Industries, locations and company sizes must be values of GET /api/v1/icp-options: anything else is refused with 400 invalid_icp_value. A location may also be one of the regions it lists (Europe, North America, Latin America, Asia-Pacific, Middle East, Africa, DACH, Nordics), which stands for its countries. Job titles are free text, at least one: they say whom to contact at each company.

curl
curl https://trycoolie.ai/api/v1/icp-options \
  -H "Authorization: Bearer $COOLIE_API_KEY"

Create the agent

POST the body: the agent is saved, active, and its first search starts at once.

curl
curl https://trycoolie.ai/api/v1/agents \
  -H "Authorization: Bearer $COOLIE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Ops leaders at hospitals in France",
    "icp": {
      "jobTitles": [
        "COO",
        "Head of Operations"
      ],
      "industries": [
        "Hospitals and Health Care"
      ],
      "locations": [
        "France"
      ],
      "companySizes": [
        "201-500 employees",
        "501-1000 employees"
      ],
      "keywordsInclude": [],
      "keywordsExclude": [],
      "mode": "broad"
    },
    "signalEventIds": [
      "hiring",
      "funding",
      "recent-job-change"
    ],
    "signalConfigs": {
      "hiring": {
        "jobTitles": [
          "Operations Manager"
        ]
      }
    },
    "findEmail": true,
    "findPhone": false
  }'
Python
import os

import requests

API = "https://trycoolie.ai/api/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['COOLIE_API_KEY']}"}

body = {
    "name": "Ops leaders at hospitals in France",
    "icp": {
        "jobTitles": ["COO", "Head of Operations"],
        "industries": ["Hospitals and Health Care"],
        "locations": ["France"],
        "companySizes": ["201-500 employees", "501-1000 employees"],
        "keywordsInclude": [],
        "keywordsExclude": [],
        "mode": "broad",
    },
    "signalEventIds": ["hiring", "funding", "recent-job-change"],
    "signalConfigs": {
        "hiring": {
            "jobTitles": ["Operations Manager"],
        },
    },
    "findEmail": True,
    "findPhone": False,
}

response = requests.post(f"{API}/agents", json=body, headers=HEADERS, timeout=60)
if response.status_code >= 400:
    error = response.json()
    raise SystemExit(f"{response.status_code} {error['error']}: {error['message']}")
created = response.json()
print("Agent", created["agentId"], "is running its first search, run", created["runId"])
JavaScript (Node.js 18+)
const response = await fetch("https://trycoolie.ai/api/v1/agents", {
  method: "POST",
  headers: {
    Authorization: "Bearer " + process.env.COOLIE_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "name": "Ops leaders at hospitals in France",
    "icp": {
      "jobTitles": [
        "COO",
        "Head of Operations"
      ],
      "industries": [
        "Hospitals and Health Care"
      ],
      "locations": [
        "France"
      ],
      "companySizes": [
        "201-500 employees",
        "501-1000 employees"
      ],
      "keywordsInclude": [],
      "keywordsExclude": [],
      "mode": "broad"
    },
    "signalEventIds": [
      "hiring",
      "funding",
      "recent-job-change"
    ],
    "signalConfigs": {
      "hiring": {
        "jobTitles": [
          "Operations Manager"
        ]
      }
    },
    "findEmail": true,
    "findPhone": false
  }),
});
const data = await response.json();
if (!response.ok) throw new Error(response.status + " " + data.error + ": " + data.message);
console.log("Agent " + data.agentId + " is running its first search");

signalConfigs is optional: here it tells the Hiring signal which job postings count. Competitor Churn and Competitor Renewal take competitors, Tech Used technologies, Buying Intent Topic topics, five values each at most.

Follow its first search

The first search runs one signal now; the others take turns, one search every three hours, up to your plan's daily leads. GET /api/v1/agents/{agentId} says what each search found and when the next one runs, in fields and in one sentence, activity.summary. The leads arrive at GET /api/v1/agents/{agentId}/leads.

curl
curl https://trycoolie.ai/api/v1/agents/agent-3f2a91c0 \
  -H "Authorization: Bearer $COOLIE_API_KEY"
Answer
{
  "agent": {
    "id": "agent-3f2a91c0",
    "name": "Ops leaders at hospitals in France",
    "status": "active",
    "createdAt": "2026-10-19T08:59:58.120Z",
    "icp": {
      "jobTitles": [
        "COO",
        "Head of Operations"
      ],
      "industries": [
        "Hospitals and Health Care"
      ],
      "locations": [
        "France"
      ],
      "companySizes": [
        "201-500 employees",
        "501-1000 employees"
      ],
      "keywordsInclude": [],
      "keywordsExclude": [],
      "mode": "broad"
    },
    "signalEventIds": [
      "hiring",
      "funding",
      "recent-job-change"
    ],
    "signalConfigs": {
      "hiring": {
        "jobTitles": [
          "Operations Manager"
        ],
        "jobDescriptionKeywords": [],
        "employmentTypes": [],
        "seniorities": []
      }
    },
    "findEmail": true,
    "findPhone": false,
    "sequenceConfig": null,
    "autoWritePerDay": 0,
    "activity": {
      "leads": {
        "total": 3,
        "today": 3
      },
      "lastSearches": [
        {
          "at": "2026-10-19T09:00:04.000Z",
          "running": false,
          "newLeads": 3,
          "title": "3 new leads",
          "signals": [
            {
              "signal": "hiring",
              "name": "Hiring",
              "text": "8 results, 4 new companies: 3 leads."
            }
          ],
          "note": null
        }
      ],
      "nextSearchAt": "2026-10-19T12:00:00.000Z",
      "summary": "Its last search (5 minutes ago) brought 3 new leads. 3 leads so far, 3 today. Next search in 2 h 55 min."
    }
  }
}

The rules a body follows

  • Three to five signals, and at least three searches a day: Hiring, Tech Used, Buying Intent Topic and Competitor Churn search once per value of their list (job titles, technologies, topics, competitors), the other signals once each (400 too_few_searches).
  • Five values at most in each signal's list.
  • mode broad accepts adjacent company sizes; specific does not.
  • Ten agents created through the API a day per account at most (429 agent_create_limit), and your plan's agents in all (403 agent_quota).
  • A running agent's targeting is locked: POST /api/v1/agents/{agentId}/stop before a PATCH /api/v1/agents/{agentId} that changes it (409 agent_running).

What POST /api/v1/agents answers

The new agent's id, and the id of the run its first search is. The values are examples.

JSON
{
  "agentId": "agent-3f2a91c0",
  "runId": "ui-5b9e2c41"
}

Errors

An error answers with its HTTP status and a body { "error": code, "message": sentence }: branch on the code, show or log the message.

StatusCodeWhat to do
400invalid_bodyA field is missing or wrong; message names it (for example icp.jobTitles, or fewer than 3 signals).
400invalid_icp_valueAn industry, location or company size is not in GET /api/v1/icp-options.
400signal_coming_soonA signal is not offered yet: GET /api/v1/signals says which are.
400signal_not_liveA signal has no source connected right now; the answer's signals field names it.
400too_few_searchesThe agent would make fewer than three searches a day: add signals, or values to them.
402trial_requiredStart the free trial in the app first.
403agent_quotaYour plan's agents are all in use: delete one, or add one in Settings → Billing.
429agent_create_limitTen agents created through the API today already; Retry-After says when the UTC day ends.
401missing_api_keyNo key in the request: send Authorization: Bearer coolie_sk_… or an x-api-key header.
401invalid_api_keyNot a Coolie key, or a key that is unknown or revoked: copy it again from Settings → API keys.
429rate_limitedMore than 60 requests in the minute for your account: wait the seconds Retry-After gives, then try again.

Frequently asked questions

How many signals can a Coolie agent watch?

Three to five. Hiring, Tech Used, Buying Intent Topic and Competitor Churn search once per value of their list, up to five values, the others once each, so an agent makes between three and twenty-five searches a day.

Does creating an agent cost credits?

It uses one of your plan's agents. Reading its leads costs nothing; credits pay for what you ask for on a lead, such as an email found (0.1 credit) or research (1 credit).

Can I change an agent after creating it?

Yes: PATCH /api/v1/agents/{agentId} with the fields to change, or status active or paused. Stop a running agent first if you change its targeting.

How do I pause or delete an agent?

POST /api/v1/agents/{agentId}/pause pauses it and /start switches it on again. DELETE /api/v1/agents/{agentId} deletes it with its leads, which cannot be undone.

Can an AI assistant create agents for me?

Yes, through Coolie's MCP server: connect Claude or ChatGPT and describe the market in plain words.

Every endpoint, field and error is in the API reference, and more guides are in the developer hub.

Your next conversation is already happening somewhere.

Set up an agent in five minutes. The first leads arrive with their reason to write.