Home / API
API · v1 · Pro tier Base: api.signalmama.com/v1 P50 82ms

REST API for the Pro tier. GET, POST, webhooks, done.

If you want briefs, scores, and signals out of Mama and into your own pipeline — this is the surface. Standard REST, JSON in and out, API-key auth with optional HMAC signing. Webhook events for the things you'd be polling for anyway. Pro tier only; free and Team tiers use the native CRM and sequencer integrations instead.

API access is a Pro-tier feature. Most teams don't need it — our 22 native integrations cover Salesforce, HubSpot, Outreach, Salesloft, Slack and more out of the box. Use the API when you're piping Mama into a custom workflow or a data warehouse.
See Pro pricing →
01

Authentication.

Every request needs an API key in the Authorization header. Keys are workspace-scoped — one workspace, one key by default, multiple keys allowed with role-based scopes (read-only / read-write / admin).

Generating a key

Workspace settings → API keys → Create new key. Keys are shown once; copy and store somewhere you trust. Lost a key? Revoke it and generate a new one — old keys stop working within 30 seconds across all regions.

# Standard Bearer auth — works on every endpoint
curl https://api.signalmama.com/v1/accounts \
  -H "Authorization: Bearer sk_live_xxx" \
  -H "Content-Type: application/json"
import requests

resp = requests.get(
    "https://api.signalmama.com/v1/accounts",
    headers={"Authorization": f"Bearer {API_KEY}"},
)
resp.raise_for_status()
accounts = resp.json()["data"]
const resp = await fetch(
  "https://api.signalmama.com/v1/accounts",
  { headers: { Authorization: `Bearer ${process.env.MAMA_KEY}` } }
);
const { data } = await resp.json();

Optional: HMAC request signing

For incoming webhooks (and outbound calls if you're paranoid), pair the API key with an HMAC-SHA256 signature of the request body using a shared secret. The X-Mama-Signature header carries the digest. Reject requests whose signature doesn't match.

02

Rate limits.

Generous by default — most teams never see a 429. We page on our side before our customers do. Limits are per workspace, per minute, and reset on a sliding window. Every response includes the standard X-RateLimit-* headers so you can self-throttle.

Reads per minute
600req/min
~10 req/sec sustained · burst to 100 OK
Writes per minute
120req/min
Bulk endpoints don't count against this
Bulk batch size
1,000items
Per POST /v1/accounts:batch call
Webhook retries
6attempts
Exponential back-off · up to 24h
03

Accounts.

The core object. Each account has a score, a brief, a set of signals, and a list of contacts. CRUD is straightforward; bulk endpoints exist for ingest from a data warehouse or syncing back to a custom CRM.

GET /v1/accounts List accounts in workspace
GET /v1/accounts/{id} Single account + score breakdown
POST /v1/accounts Add an account to scoring
POST /v1/accounts:batch Bulk ingest up to 1,000
POST /v1/accounts/{id}:rescore Force re-score outside the 6h cycle
DELETE /v1/accounts/{id} Soft-delete · purged after 30d

Example · fetch a single account

curl https://api.signalmama.com/v1/accounts/acct_01H8X4 \
  -H "Authorization: Bearer $MAMA_KEY"
acct = mama.get(f"/accounts/{acct_id}").json()
print(acct["score"], acct["score_breakdown"])
# => 82, {fit: 95, recency: 78, strength: 82, depth: 68}
const acct = await mama.get(`/accounts/${id}`);
console.log(acct.score, acct.score_breakdown);
// => 82, { fit: 95, recency: 78, strength: 82, depth: 68 }
04

Briefs.

Briefs are immutable snapshots. Each time the score moves more than 10 points, Mama writes a new brief version rather than rewriting the previous one. Fetch the latest by default, or pass ?version=N for any historical snapshot.

GET /v1/accounts/{id}/brief Latest brief for an account
GET /v1/accounts/{id}/brief/versions All historical brief versions
POST /v1/accounts/{id}/brief:regenerate Force rewrite from existing data (Pro+ only)
POST /v1/accounts/{id}/crawl:on-demand Trigger a fresh crawl of all sources for this account (Pro+ only · ~ 30s)

Example · brief shape

{
  "id": "brf_01H8X4ZRT9",
  "account_id": "acct_01H8X4",
  "version": 7,
  "generated_at": "2026-05-22T14:32:08Z",
  "score": 82,
  "score_breakdown": {
    "fit": 95,
    "recency": 78,
    "strength": 82,
    "depth": 68
  },
  "why_now": "Series B announced 11 days ago…",
  "who_to_talk_to": [
    { "name": "Priya Mehta", "role": "VP RevOps", "tag": "new" }
  ],
  "draft_opener": "Saw the $45M Series B yesterday…",
  "signals": ["sig_…", "sig_…", "sig_…"]
}
05

Signals.

Read-only — Mama detects, you consume. Filter by signal type, by account, by time window, by strength threshold. Useful for piping raw events into a data warehouse or building custom dashboards on top.

GET /v1/signals All signals · filterable
GET /v1/signals/{id} Single signal + source attribution
GET /v1/signals/types List the 47 detectable types

Common query params: ?type=funding,exec_move, ?since=2026-05-01, ?strength_gte=70, ?account_id=acct_….

06

Custom bots.

Programmatically create, list, pause, and delete your workspace's custom bots — the user-defined persistent crawlers that ride Mama's same infra as her built-in ones. Pro plan = 25 active bots; Company plan = 100. Same hard rules as the dashboard: public sources only, robots.txt respected, auto-pause after 3 consecutive failures.

GET /v1/bots List all bots in workspace · filterable by status
GET /v1/bots/{id} Single bot with config + health stats
POST /v1/bots Create a new bot · pass source, cadence, match rule, signal type
PUT /v1/bots/{id} Update bot config
POST /v1/bots/{id}:pause Pause without deleting · keeps config + fire history
POST /v1/bots/{id}:resume Resume a paused bot
GET /v1/bots/{id}/fires All signal fires from this bot · paginated
GET /v1/bots/{id}/health Crawl success rate, last 24h / 7d / 30d
GET /v1/bots/templates List the 6 starter templates (competitor-pricing, rss, subreddit, github, discord, custom-url)

Bot config shape · POST /v1/bots

{
  "name": "Apollo pricing watcher",
  "template": "competitor-pricing",
  "source": "https://apollo.io/pricing",
  "cadence": "daily",
  "match_rule": {
    "type": "content_diff",
    "selector": ".pricing-tier"
  },
  "fires_signal": "competitor_price_change",
  "signal_score": 25,
  "alert": {
    "channel": "slack",
    "destination": "#competitive"
  }
}

Returns the created bot with id, status: "active", and the resolved next_run_at timestamp. Bots count against your workspace's bot quota immediately on creation, even before the first crawl.

07

Webhooks.

For everything you'd be polling for, we'd rather push. Register an endpoint, pick the events you care about, sign every payload with an HMAC, retry with exponential back-off up to 24 hours. Six core event types so far:

account.score_changed
Fires when an account's score moves >10 points
account.score_jumped
Fires only when score crosses the workspace floor
brief.generated
New brief version written for an account
signal.fired
Any signal detection (high volume — filter by type)
contact.added
New contact discovered on an existing account
workspace.rubric_updated
ICP rubric weights or dimensions changed

Register a webhook

curl https://api.signalmama.com/v1/webhooks \
  -H "Authorization: Bearer $MAMA_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-app.com/hooks/mama",
    "events": ["account.score_jumped", "brief.generated"],
    "secret": "whsec_yourGeneratedSecret"
  }'
mama.post("/webhooks", json={
    "url": "https://your-app.com/hooks/mama",
    "events": ["account.score_jumped", "brief.generated"],
    "secret": "whsec_yourGeneratedSecret",
})
await mama.post("/webhooks", {
  url: "https://your-app.com/hooks/mama",
  events: ["account.score_jumped", "brief.generated"],
  secret: "whsec_yourGeneratedSecret",
});

Verifying a payload

Compute HMAC-SHA256(secret, raw_body) and compare to the X-Mama-Signature header. Constant-time compare. Reject anything that doesn't match — and include a timestamp tolerance to prevent replay. Full reference impl on every endpoint page.

08

SDKs & libraries.

The REST API is the source of truth. We don't ship official SDKs yet — the surface area is small enough that requests / fetch / http is fine. If demand warrants, we'll prioritize the languages with the most launch-partner usage. Status below:

Language Package Status
Python signalmama (official) Coming Q3 2026
TypeScript / JavaScript @signalmama/node (official) Coming Q4 2026
Go go-signalmama (community) Community · maintained
Ruby, PHP, Java, .NET No plan · raw HTTP
OpenAPI spec spec.signalmama.com/v1.yaml Live · auto-generated

The OpenAPI 3.1 spec works in any code generator (openapi-generator, openapi-typescript, etc.) — most launch partners use that path instead of waiting on our SDKs.

09

Errors & conventions.

Standard HTTP status codes, JSON error bodies, idempotency keys on writes. Three conventions worth noting:

  • Idempotency. Pass an Idempotency-Key header on any POST — Mama de-dupes for 24 hours. Safe to retry on network failure.
  • Pagination. Cursor-based — never offset. Responses include has_more and next_cursor. Pass ?cursor=… on the next call.
  • Timestamps. Always ISO 8601 in UTC, with millisecond precision. Never relative ("3 days ago"). Never Unix integers in response bodies — only as query params.

Error bodies look like this:

{
  "error": {
    "type": "invalid_request",
    "code": "missing_param",
    "message": "`account_id` is required.",
    "docs_url": "https://signalmama.com/api#accounts",
    "request_id": "req_01H8X4ZRT9PQRSTU"
  }
}

Always quote the request_id when emailing [email protected] — it lets us pull the exact trace from our logs in seconds.

10

API changelog.

We version on the path (/v1/). Within a major version, we only add — never remove or rename fields, never change response shapes in incompatible ways. Breaking changes mean a new major version (/v2/), with at least 12 months of dual-running before /v1/ sunsets.

The full API changelog lives on the main /changelog page tagged api. Subscribe via the changelog RSS to get notified on every release.

For Pro tier customers

API access ships with the Pro tier. Most teams don't need it.

If our 22 native integrations cover your stack, the API isn't worth the extra cost. If you're piping briefs into a data warehouse or a custom workflow, Pro unlocks all of the above. Or get on Free first and see if the natives cover you.