mySDRDocs

API reference

Register your own signal

Registers a signal you run yourself, or updates it: the same key again changes what you send and keeps what you leave out. It shows on the Signals page of mySDR right away. After every check, report it with POST /agent-signals/{key}/hits. At most 50 per organization.

POSThttps://mysdr.app/api/v1/agent-signals
View Markdown

A signal your agent runs itself, with its own tools: hiring spikes on careers pages, posts on X, a newsletter, a list in the CRM. Register it and the user sees it on the Signals page of mySDR, next to the signals mySDR runs: what it watches, where, how often, when you last checked and what it caught. mySDR does not run, schedule or check it: it shows what you report. These routes are the tools save_agent_signal, log_signal_hits, list_agent_signals and delete_agent_signal of the assistant server.

Authentication

Send Authorization: Bearer gtk_…. Create the key under Connect assistant → API keys. Every gtk_ key can call these routes, also while the Signals API is closed. A missing, invalid or revoked key is 401.

Body parameters

  • key string · required — Your own name for the signal: lowercase letters, digits and _, starting with a letter, up to 40 characters (Hiring spike becomes hiring_spike). Use the same key every time.
  • name string — As the user sees it on Signals, up to 100 characters, without |. Required the first time.
  • description string | null — What it watches and why that matters, up to 500 characters. null clears it.
  • source string | null — Where you look, in words ("Careers pages", "X"), up to 80 characters.
  • source_url string | null — A link to that source (https://…), e.g. a saved search.
  • schedule string | null — How often you check. Only shown: mySDR plans nothing. One of: hourly, daily, weekly, monthly, once, on_demand.
  • status string — paused = you stop running it until it is active again; a paused signal takes no checks. Default active. One of: active, paused.
  • next_check_at string | null — When you check next: a date (2026-10-27, 09:00 Brussels time) or an ISO time. Later than that, the card says the check is overdue.

Response

  • object string · required — Always agent_signal. One of: agent_signal.
  • key string · required — Your own name for it: lowercase letters, digits and _.
  • name string · required — As the user sees it.
  • description string | null · required — What it watches.
  • source string | null · required — Where you look.
  • source_url string | null · required — A link to that source.
  • schedule string | null · required — How often you check. One of: hourly, daily, weekly, monthly, once, on_demand.
  • status string · required — active or paused. One of: active, paused.
  • last_checked_at string | null · required — When you last reported a check.
  • next_check_at string | null · required — When you said you check next.
  • check_overdue boolean · required — True when the signal is active and next_check_at is more than an hour ago: the user sees "Check overdue".
  • last_check_note string | null · required — What your last check did.
  • caught object · required — leads and companies: how many people and companies it caught, each counted once.
  • last_hit_at string | null · required — When it last caught something.
  • via string | null · required — The name of the key that last registered it or reported a check ("Grok Bot").
  • created_at string · required — When it was registered.
  • updated_at string · required — When it last changed.
  • results_url string · required — The Leads or Companies table in mySDR on this signal (where it caught the most).
  • created boolean · required — True when this call registered it; false when it updated one.
  • dashboard_url string · required — The Signals page in mySDR.

Credits

Free. This call never uses credits.

Errors

  • 400 invalid_request — No key, a key that is not valid, no name the first time, a value that is too long or not one of its values (param names it), or an unknown field.
  • 409 invalid_state — The organization has 50 own signals already: delete one first.
  • 503 service_unavailable — Own signals are not available in this environment yet.
  • 409 invalid_state — The key has no user behind it, so mySDR cannot record who did it.
  • 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.
  • 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.
  • 503 service_unavailable — The API is temporarily unavailable. Retry later.
  • 500 internal_error — Something went wrong on our side.

Example

cURL

curl -X POST "https://mysdr.app/api/v1/agent-signals" \
  -H "Authorization: Bearer $MYSDR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "key": "hiring_spike",
    "name": "Hiring spike on careers pages",
    "description": "Companies whose careers page lists at least 10 open roles, up from fewer than 5.",
    "source": "Careers pages",
    "schedule": "daily",
    "next_check_at": "2026-10-26"
  }'

JavaScript

const response = await fetch('https://mysdr.app/api/v1/agent-signals', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.MYSDR_API_KEY}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    "key": "hiring_spike",
    "name": "Hiring spike on careers pages",
    "description": "Companies whose careers page lists at least 10 open roles, up from fewer than 5.",
    "source": "Careers pages",
    "schedule": "daily",
    "next_check_at": "2026-10-26"
  })
});
const body = await response.json();

Python

import json
import os
import urllib.request

payload = {
  "key": "hiring_spike",
  "name": "Hiring spike on careers pages",
  "description": "Companies whose careers page lists at least 10 open roles, up from fewer than 5.",
  "source": "Careers pages",
  "schedule": "daily",
  "next_check_at": "2026-10-26"
}

request = urllib.request.Request(
    "https://mysdr.app/api/v1/agent-signals",
    headers={
    "Authorization": f"Bearer {os.environ['MYSDR_API_KEY']}",
    "Content-Type": "application/json"
    },
    data=json.dumps(payload).encode(),
    method="POST",
)
with urllib.request.urlopen(request) as response:
    body = json.load(response)

Example response

{
  "object": "agent_signal",
  "key": "hiring_spike",
  "name": "Hiring spike on careers pages",
  "description": "Companies whose careers page lists at least 10 open roles, up from fewer than 5.",
  "source": "Careers pages",
  "source_url": null,
  "schedule": "daily",
  "status": "active",
  "last_checked_at": "2026-10-25T07:00:00.000Z",
  "next_check_at": "2026-10-26T08:00:00.000Z",
  "check_overdue": false,
  "last_check_note": "140 careers pages, 3 spikes",
  "caught": {
    "leads": 0,
    "companies": 9
  },
  "last_hit_at": "2026-10-25T07:00:00.000Z",
  "via": "Grok Bot",
  "created_at": "2026-10-20T08:00:00.000Z",
  "updated_at": "2026-10-25T07:00:00.000Z",
  "results_url": "https://mysdr.app/en/gtm/companies?signal=Hiring+spike+on+careers+pages",
  "created": true,
  "dashboard_url": "https://mysdr.app/en/gtm/signals"
}