FounderMCPDocs

API reference

Create a watch

Runs a signal on a schedule. The first run starts within about a minute. Each later run delivers only people this watch has not delivered before, and charges per new lead.

POSThttps://foundermcp.dev/api/v1/watches
View Markdown

Runs a signal on a schedule. The first run starts within about a minute. Each later run delivers only people this watch has not delivered before, and charges per new lead.

A watch runs in mode screened. tech_adoption (raw only) is 400. events needs signal.event.event_id — look the event up with a search first. Without a schedule, an events watch follows the event (event_lifecycle).

The watch pauses by itself for monthly_cap, daily_cap or source_unavailable, and resumes when it can run again. webhook_disabled waits for PATCH status active.

Authentication

Send Authorization: Bearer gtk_…. Create the key under API Access → API Keys. A missing, invalid or revoked key is 401, including while this API is closed. A valid key while the API is closed for your organization answers 404, the same body as an unknown path. Every response includes FounderMCP-Api-Version and FounderMCP-Request-Id.

Headers

  • Idempotency-Key string · required — Required on this call. The same key and the same body replay the first response for 24 hours (Idempotent-Replayed: true). The same key with a different body is 409 idempotency_conflict.

Body parameters

  • name string | null — Up to 120 characters.
  • signal object · required — Same signal object as POST /searches. Events need event.event_id.
  • buyer_profile object — Buyer profile, mode screened only. roles (departments: ceo, sales, marketing, finance, operations, hr, it, talent_acquisition, engineering, product, customer_success, data, procurement, legal), titles, levels (c_level, vp, director, manager), countries (ISO alpha-2, or EUROPE), allow_recruiters, allow_vendors. sectors and company_sizes only on new_in_role. Empty means anyone.
  • schedule object — Required except for events. frequency daily or weekly (then weekday, Monday = 1), hour_local (default 7), timezone (default Europe/Brussels).
  • max_leads_per_run integer — 1 to 50, and at most the type cap. Defaults to 10, or lower when the type cap is lower.
  • max_credits_per_month integer · required — Most credits this watch may use in one Brussels month.
  • just_outside string — never (default) or auto. One of: never, auto.
  • webhook_endpoint_id string | null — Receives watch.leads_delivered, watch.paused and watch.failed_run.
  • status string — active (default) or paused. One of: active, paused.

Response

  • id string · required — Watch id, wtch_….
  • object string · required — Always watch. One of: watch.
  • status string · required — active, paused or deleted. One of: active, paused, deleted.
  • paused_reason string | null — user, monthly_cap, daily_cap, webhook_disabled or source_unavailable.
  • signal object · required — The signal, fixed after create.
  • schedule object · required — frequency (daily, weekly, event_lifecycle), weekday, hour_local, timezone.
  • max_leads_per_run integer · required — Cap on new leads per run.
  • max_credits_per_month integer · required — Cap for the Brussels calendar month.
  • next_run_at string | null · required — When the next run starts. Null while you paused it, or while its webhook is disabled.
  • stats object · required — leads_delivered_total and credits_this_month.

Credits

Creating a watch is free. Each run charges 20 credits per new exact lead and 5 per new lead just outside. A run that finds nobody is free. Errors and empty lookups are free. A call that spent credits puts that number in credits_used, in X-Credits-Used and in X-Credits-Charged. When the wallet can be read, the response also sends X-Credits-Remaining.

Errors

  • 400 invalid_request — The body is not valid JSON, a field is unknown or has the wrong type, or a value is not allowed.
  • 401 authentication_error — The Authorization header is missing, or the key is unknown or revoked.
  • 403 permission_error — API access is not part of your plan, or your account is suspended.
  • 404 not_found — The endpoint does not exist.
  • 429 rate_limit_error — More than 60 requests per minute, or more than 3 at the same time, on one key. Wait for the Retry-After header.
  • 429 daily_limit_reached — The request could take your organization over its daily credit limit. The limit resets at midnight (Europe/Brussels).
  • 402 insufficient_credits — The credit balance is lower than this request could cost. Nothing was charged. Add credits, or send a smaller request. The error includes code, fix and a link to the credits docs.
  • 502 upstream_error — The data source did not answer. Retry later.
  • 503 service_unavailable — The API is temporarily unavailable. Retry later.
  • 500 internal_error — Something went wrong on our side.
  • 402 max_credits_exceeded — max_credits is lower than the credits of the first row, so nothing could be returned. Nothing was charged; raise max_credits or ask for fewer rows.
  • 409 idempotency_conflict — The Idempotency-Key was already used with another request body.
  • 409 idempotency_in_progress — The first request with this Idempotency-Key is still being processed. Wait for the Retry-After header.
  • 422 unresolvable_input — A company, person or event in the request does not exist or cannot be found.

Example

cURL

curl -X POST "https://foundermcp.dev/api/v1/watches" \
  -H "Authorization: Bearer $FOUNDERMCP_API_KEY" \
  -H "Idempotency-Key: idem-1" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme engagers",
    "signal": {
      "type": "linkedin_engagement",
      "company": {
        "linkedin_url": "https://www.linkedin.com/company/acme-analytics"
      }
    },
    "buyer_profile": {
      "roles": [
        "finance"
      ],
      "countries": [
        "BE"
      ]
    },
    "schedule": {
      "frequency": "weekly",
      "weekday": 1,
      "hour_local": 7,
      "timezone": "Europe/Brussels"
    },
    "max_credits_per_month": 400
  }'

JavaScript

const response = await fetch('https://foundermcp.dev/api/v1/watches', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.FOUNDERMCP_API_KEY}`,
    'Idempotency-Key': 'idem-1',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    "name": "Acme engagers",
    "signal": {
      "type": "linkedin_engagement",
      "company": {
        "linkedin_url": "https://www.linkedin.com/company/acme-analytics"
      }
    },
    "buyer_profile": {
      "roles": [
        "finance"
      ],
      "countries": [
        "BE"
      ]
    },
    "schedule": {
      "frequency": "weekly",
      "weekday": 1,
      "hour_local": 7,
      "timezone": "Europe/Brussels"
    },
    "max_credits_per_month": 400
  })
});
const body = await response.json();

Python

import json
import os
import urllib.request

payload = {
  "name": "Acme engagers",
  "signal": {
    "type": "linkedin_engagement",
    "company": {
      "linkedin_url": "https://www.linkedin.com/company/acme-analytics"
    }
  },
  "buyer_profile": {
    "roles": [
      "finance"
    ],
    "countries": [
      "BE"
    ]
  },
  "schedule": {
    "frequency": "weekly",
    "weekday": 1,
    "hour_local": 7,
    "timezone": "Europe/Brussels"
  },
  "max_credits_per_month": 400
}

request = urllib.request.Request(
    "https://foundermcp.dev/api/v1/watches",
    headers={
    "Authorization": f"Bearer {os.environ['FOUNDERMCP_API_KEY']}",
    "Idempotency-Key": "idem-1",
    "Content-Type": "application/json"
    },
    data=json.dumps(payload).encode(),
    method="POST",
)
with urllib.request.urlopen(request) as response:
    body = json.load(response)

Example response

{
  "id": "wtch_01J9Z6P8C8V0K3W6T2N8R5M1XD",
  "object": "watch",
  "status": "active",
  "paused_reason": null,
  "max_credits_per_month": 400,
  "stats": {
    "leads_delivered_total": 0,
    "credits_this_month": 0
  }
}