Signals
Funding (sync)
Synchronous form of the Funding signal (POST /v1/signals/funding):
creates the signal and blocks until it completes (or the timeout is
reached), returning the result in the same response. Recommended for
interactive and agent workflows. If you supply a webhookUrl, the completed signal is
still delivered to it in addition to this response — omit it unless
you want both.
The completed answer (answer.jsonSchema) conforms to
FundingSignalAnswer. Cost: 2 credits, charged once per result delivered to your organization — your own repeat calls served from cache are free, and failed runs are never charged.
Authorization
ApiKeyAuth API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.
In: header
Header Parameters
Custom timeout in seconds (max 870 — higher values are clamped). When absent, the server-configured default (870s) applies.
1 <= value <= 870If "true", returns 408 Request Timeout on timeout instead of 200 with the latest (still-processing) status.
"true" | "false"Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
The company domain to research (e.g., "acme.com").
^[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?)*$1 <= length <= 253Optional webhook to receive the completed signal. Intended for the
async endpoints; if supplied on a synchronous /sync/ endpoint the
webhook is still delivered, in addition to the blocking response.
urilength <= 2048Force a fresh run. By default an identical request (same domain and
parameters) returns the existing result instead of re-running; set
this to true to bypass that and research again.
falseResponse Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/v1/signals/sync/funding" \ -H "X-Sbr-Timeout-Sec: 120" \ -H "X-Sbr-Timeout-Error: false" \ -H "Content-Type: application/json" \ -d '{ "domain": "stripe.com" }'{ "id": "e45c1dc4-d422-4b51-956b-cb6d3ddaf250", "signalType": "COMPANY", "namedSignal": "funding", "status": "completed", "domain": "stripe.com", "answerType": "json_schema", "createdAt": "2026-07-01T10:30:00Z", "completedAt": "2026-07-01T10:31:40Z", "answer": { "type": "json_schema", "jsonSchema": { "hasFundingEvent": true, "isPublic": false, "latestRound": "Series I", "latestEvents": [ { "eventType": "funding_round", "round": "Series I", "amount": 6500000000, "currency": "USD", "investors": [ "Andreessen Horowitz", "Sequoia Capital", "General Catalyst" ], "announcedAt": "2023-03-15", "sourceUrls": [ "https://stripe.com/newsroom/news/series-i" ] } ] } }, "confidence": 0.93, "sources": [ { "url": "https://stripe.com/newsroom/news/series-i", "title": "Stripe raises Series I" } ]}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}Funding (async)
Summarise a company's most recent funding and public/IPO status from a domain.
The AI confirms sources belong to the company at that domain, reports the
latest primary equity round (never a secondary, tender, or debt
event), and flags a completed IPO / direct listing / SPAC as
isPublic: true with latestRound: "IPO".
This is the async endpoint: it returns 201 immediately with a
processing signal. Poll GET /v1/companies/signals/{signalId} or supply a
webhookUrl to receive the completed result. For a single blocking
request, use POST /v1/signals/sync/funding.
The completed answer (answer.jsonSchema) conforms to
FundingSignalAnswer. Cost: 2 credits, charged once per result delivered to your organization — your own repeat calls served from cache are free, and failed runs are never charged.
Authorization
ApiKeyAuth API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.
In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
The company domain to research (e.g., "acme.com").
^[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?)*$1 <= length <= 253Optional webhook to receive the completed signal. Intended for the
async endpoints; if supplied on a synchronous /sync/ endpoint the
webhook is still delivered, in addition to the blocking response.
urilength <= 2048Force a fresh run. By default an identical request (same domain and
parameters) returns the existing result instead of re-running; set
this to true to bypass that and research again.
falseResponse Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/v1/signals/funding" \ -H "Content-Type: application/json" \ -d '{ "domain": "stripe.com" }'{ "id": "e45c1dc4-d422-4b51-956b-cb6d3ddaf250", "signalType": "COMPANY", "namedSignal": "funding", "status": "failed", "domain": "stripe.com", "createdAt": "2026-07-01T10:30:00Z", "error": "Research did not complete because upstream sources were unavailable. Retry later.", "retryable": true}{ "id": "e45c1dc4-d422-4b51-956b-cb6d3ddaf250", "signalType": "COMPANY", "namedSignal": "funding", "status": "processing", "domain": "stripe.com", "createdAt": "2026-07-01T10:30:00Z"}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}M&A (sync)
Synchronous form of the M&A signal (POST /v1/signals/mna):
creates the signal and blocks until it completes, returning the result in
the same response. If you supply a webhookUrl, the completed signal is still delivered to it in addition to this response — omit it unless you want both.
The completed answer (answer.jsonSchema) conforms to
MAndASignalAnswer. Cost: 2 credits, charged once per result delivered to your organization — your own repeat calls served from cache are free, and failed runs are never charged.
Authorization
ApiKeyAuth API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.
In: header
Header Parameters
Custom timeout in seconds (max 870 — higher values are clamped). When absent, the server-configured default (870s) applies.
1 <= value <= 870If "true", returns 408 Request Timeout on timeout instead of 200 with the latest (still-processing) status.
"true" | "false"Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
The company domain to research (e.g., "acme.com").
^[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?)*$1 <= length <= 253Optional webhook to receive the completed signal. Intended for the
async endpoints; if supplied on a synchronous /sync/ endpoint the
webhook is still delivered, in addition to the blocking response.
urilength <= 2048Force a fresh run. By default an identical request (same domain and
parameters) returns the existing result instead of re-running; set
this to true to bypass that and research again.
falseResponse Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/v1/signals/sync/mna" \ -H "X-Sbr-Timeout-Sec: 120" \ -H "X-Sbr-Timeout-Error: false" \ -H "Content-Type: application/json" \ -d '{ "domain": "figma.com" }'{ "id": "f56d2ec5-e533-4c62-a67c-dc7d4eeaf361", "signalType": "COMPANY", "namedSignal": "mna", "status": "completed", "domain": "figma.com", "answerType": "json_schema", "createdAt": "2026-07-01T10:30:00Z", "completedAt": "2026-07-01T10:31:20Z", "answer": { "type": "json_schema", "jsonSchema": { "detected": true, "latestEvents": [ { "role": "acquiree", "counterparty": "Adobe", "status": "terminated", "amount": 20000000000, "currency": "USD", "announcedAt": "2022-09-15", "sourceUrls": [ "https://news.adobe.com/news/2023/12/adobe-figma-update" ] } ] } }, "confidence": 0.97, "sources": [ { "url": "https://news.adobe.com/news/2023/12/adobe-figma-update", "title": "Adobe and Figma mutually terminate merger agreement" } ]}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}M&A (async)
Detect whether a company was acquired, or made acquisitions, in the recent window — counterparty, deal status, and value where disclosed.
Counts only true acquisitions (control transfer): minority investments,
funding rounds, and partnerships are excluded. role distinguishes the
queried company being bought (acquiree, reported at any age) from it
buying others (acquirer, last 24 months only). An announced deal that
later collapsed is terminated, never completed. An acquisition backed
only by a data aggregator with no primary corroboration stays
rumored and does not count as detected.
This is the async endpoint. For a single blocking request, use
POST /v1/signals/sync/mna.
The completed answer (answer.jsonSchema) conforms to
MAndASignalAnswer. Cost: 2 credits, charged once per result delivered to your organization — your own repeat calls served from cache are free, and failed runs are never charged.
Authorization
ApiKeyAuth API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.
In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
The company domain to research (e.g., "acme.com").
^[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?)*$1 <= length <= 253Optional webhook to receive the completed signal. Intended for the
async endpoints; if supplied on a synchronous /sync/ endpoint the
webhook is still delivered, in addition to the blocking response.
urilength <= 2048Force a fresh run. By default an identical request (same domain and
parameters) returns the existing result instead of re-running; set
this to true to bypass that and research again.
falseResponse Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/v1/signals/mna" \ -H "Content-Type: application/json" \ -d '{ "domain": "figma.com" }'{ "id": "f56d2ec5-e533-4c62-a67c-dc7d4eeaf361", "signalType": "COMPANY", "namedSignal": "mna", "status": "failed", "domain": "figma.com", "createdAt": "2026-07-01T10:30:00Z", "error": "Research did not complete because upstream sources were unavailable. Retry later.", "retryable": true}{ "id": "f56d2ec5-e533-4c62-a67c-dc7d4eeaf361", "signalType": "COMPANY", "namedSignal": "mna", "status": "processing", "domain": "figma.com", "createdAt": "2026-07-01T10:30:00Z"}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}Tech (sync)
Synchronous form of the Tech signal (POST /v1/signals/tech):
creates the signal and blocks until it completes, returning the result in
the same response. Supply exactly one of category or technology.
If you supply a webhookUrl, the completed signal is still delivered to it in addition to this response — omit it unless you want both.
The completed answer (answer.jsonSchema) conforms to
TechSignalAnswer. Cost: 2 credits, charged once per result delivered to your organization — your own repeat calls served from cache are free, and failed runs are never charged.
Authorization
ApiKeyAuth API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.
In: header
Header Parameters
Custom timeout in seconds (max 870 — higher values are clamped). When absent, the server-configured default (870s) applies.
1 <= value <= 870If "true", returns 408 Request Timeout on timeout instead of 200 with the latest (still-processing) status.
"true" | "false"Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
The company domain to research (e.g., "acme.com").
^[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?)*$1 <= length <= 253A coarse technology category to survey. Mutually exclusive with
technology.
"erp" | "crm"A specific technology to check for, given as free text (e.g.
"salesforce", "SAP S/4HANA"); Saber resolves it to a canonical
registry slug. An unresolvable value returns 422 with did-you-mean
suggestions. Mutually exclusive with category.
Optional webhook to receive the completed signal. Intended for the async endpoint; if supplied on the synchronous /sync/ endpoint the webhook is still delivered, in addition to the blocking response.
urilength <= 2048Force a fresh run. By default an identical request (same domain and
parameters) returns the existing result instead of re-running; set
this to true to bypass that and research again.
falseThe company domain to research (e.g., "acme.com").
^[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?)*$1 <= length <= 253A coarse technology category to survey. Mutually exclusive with
technology.
"erp" | "crm"A specific technology to check for, given as free text (e.g.
"salesforce", "SAP S/4HANA"); Saber resolves it to a canonical
registry slug. An unresolvable value returns 422 with did-you-mean
suggestions. Mutually exclusive with category.
Optional webhook to receive the completed signal. Intended for the async endpoint; if supplied on the synchronous /sync/ endpoint the webhook is still delivered, in addition to the blocking response.
urilength <= 2048Force a fresh run. By default an identical request (same domain and
parameters) returns the existing result instead of re-running; set
this to true to bypass that and research again.
falseResponse Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/v1/signals/sync/tech" \ -H "X-Sbr-Timeout-Sec: 120" \ -H "X-Sbr-Timeout-Error: false" \ -H "Content-Type: application/json" \ -d '{ "domain": "monday.com", "category": "crm" }'{ "id": "a67d3fc6-f644-5d73-b78d-ed8e5ffb0472", "signalType": "COMPANY", "namedSignal": "tech", "status": "completed", "domain": "monday.com", "answerType": "json_schema", "createdAt": "2026-07-01T10:30:00Z", "completedAt": "2026-07-01T10:32:05Z", "answer": { "type": "json_schema", "jsonSchema": { "scope": "category", "category": "crm", "primary": "salesforce", "technologies": [ { "technology": "salesforce", "displayName": "Salesforce", "status": "active", "confidence": 0.9, "lastEvidence": "2026-05", "evidence": [ { "type": "job_posting", "url": "https://monday.com/careers/salesforce-admin", "title": "Salesforce Administrator" } ] } ] } }, "confidence": 0.9, "sources": [ { "url": "https://monday.com/careers/salesforce-admin", "title": "Salesforce Administrator — Careers" } ]}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}Tech (async)
Detect which system(s) a company currently uses in a technology category, verified with public web evidence.
Supply exactly one typed parameter:
category— a coarse category (erporcrm). Returns every system detected in that category, with the current system of record inprimary.technology— a specific product (free text resolved to a canonical slug, e.g.salesforce,SAP S/4HANA). Returns a one-elementtechnologieslist whosestatuscarries the verdict (active,churned, ornot_found).
Vendor data is a prior, not the answer. Technographics detections
enter the agent loop only as leads to verify; every reported technology
must cite public web evidence — a job posting, engineering blog, docs, a
case study, or a live website fingerprint. A vendor-only hint that can't
be corroborated surfaces as status: not_found, never as a confirmed
finding.
This is the async endpoint. For a single blocking request, use
POST /v1/signals/sync/tech.
The completed answer (answer.jsonSchema) conforms to
TechSignalAnswer. Cost: 2 credits, charged once per result delivered to your organization — your own repeat calls served from cache are free, and failed runs are never charged.
Authorization
ApiKeyAuth API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.
In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
The company domain to research (e.g., "acme.com").
^[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?)*$1 <= length <= 253A coarse technology category to survey. Mutually exclusive with
technology.
"erp" | "crm"A specific technology to check for, given as free text (e.g.
"salesforce", "SAP S/4HANA"); Saber resolves it to a canonical
registry slug. An unresolvable value returns 422 with did-you-mean
suggestions. Mutually exclusive with category.
Optional webhook to receive the completed signal. Intended for the async endpoint; if supplied on the synchronous /sync/ endpoint the webhook is still delivered, in addition to the blocking response.
urilength <= 2048Force a fresh run. By default an identical request (same domain and
parameters) returns the existing result instead of re-running; set
this to true to bypass that and research again.
falseThe company domain to research (e.g., "acme.com").
^[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?)*$1 <= length <= 253A coarse technology category to survey. Mutually exclusive with
technology.
"erp" | "crm"A specific technology to check for, given as free text (e.g.
"salesforce", "SAP S/4HANA"); Saber resolves it to a canonical
registry slug. An unresolvable value returns 422 with did-you-mean
suggestions. Mutually exclusive with category.
Optional webhook to receive the completed signal. Intended for the async endpoint; if supplied on the synchronous /sync/ endpoint the webhook is still delivered, in addition to the blocking response.
urilength <= 2048Force a fresh run. By default an identical request (same domain and
parameters) returns the existing result instead of re-running; set
this to true to bypass that and research again.
falseResponse Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/v1/signals/tech" \ -H "Content-Type: application/json" \ -d '{ "domain": "monday.com", "category": "crm" }'{ "id": "a67d3fc6-f644-5d73-b78d-ed8e5ffb0472", "signalType": "COMPANY", "namedSignal": "tech", "status": "failed", "domain": "monday.com", "createdAt": "2026-07-01T10:30:00Z", "error": "Research did not complete because upstream sources were unavailable. Retry later.", "retryable": true}{ "id": "a67d3fc6-f644-5d73-b78d-ed8e5ffb0472", "signalType": "COMPANY", "namedSignal": "tech", "status": "processing", "domain": "monday.com", "createdAt": "2026-07-01T10:30:00Z"}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}Open Jobs (sync)
Synchronous form of the Open Jobs signal (POST /v1/signals/open-jobs):
creates the signal and blocks until it completes, returning the result in
the same response. If you supply a webhookUrl, the completed signal is still delivered to it in addition to this response — omit it unless you want both.
The completed answer (answer.jsonSchema) conforms to
OpenJobsSignalAnswer. Cost: 2 credits, charged once per result delivered to your organization — your own repeat calls served from cache are free, and failed runs are never charged.
Authorization
ApiKeyAuth API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.
In: header
Header Parameters
Custom timeout in seconds (max 870 — higher values are clamped). When absent, the server-configured default (870s) applies.
1 <= value <= 870If "true", returns 408 Request Timeout on timeout instead of 200 with the latest (still-processing) status.
"true" | "false"Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
The company domain to research (e.g., "acme.com").
^[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?)*$1 <= length <= 253Optional webhook to receive the completed signal. Intended for the
async endpoints; if supplied on a synchronous /sync/ endpoint the
webhook is still delivered, in addition to the blocking response.
urilength <= 2048Force a fresh run. By default an identical request (same domain and
parameters) returns the existing result instead of re-running; set
this to true to bypass that and research again.
falseResponse Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/v1/signals/sync/open-jobs" \ -H "X-Sbr-Timeout-Sec: 120" \ -H "X-Sbr-Timeout-Error: false" \ -H "Content-Type: application/json" \ -d '{ "domain": "datadoghq.com" }'{ "id": "b78e4bd7-b755-6e84-c89e-fe9f6bbc0583", "signalType": "COMPANY", "namedSignal": "open-jobs", "status": "completed", "domain": "datadoghq.com", "answerType": "json_schema", "createdAt": "2026-07-01T10:30:00Z", "completedAt": "2026-07-01T10:31:10Z", "answer": { "type": "json_schema", "jsonSchema": { "openings": 876, "topTitles": [ "Senior Software Engineer", "Product Manager", "Enterprise Account Executive" ], "hiringThemes": [ "Engineering", "Product", "Sales/GTM" ], "techHiringFor": [ "Go", "Kubernetes", "React" ], "locations": [ "New York, NY", "Remote", "Paris, France" ], "latestPostingDate": "2026-06-28", "source": "public_job_listings" } }, "confidence": 0.9}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}Open Jobs (async)
Summarise what a company is hiring for from public job postings: how many roles are open, the function areas and technologies behind them, and where.
openings is the true total matching the trailing 90-day window (the
job search tool's reported match count), not the number of sampled
listings. topTitles, hiringThemes, techHiringFor, and locations
are drawn from a small sample and are examples, not a proportional
breakdown. hiringThemes maps roles onto a fixed function taxonomy so the
field stays filterable and stable.
This is the async endpoint. For a single blocking request, use
POST /v1/signals/sync/open-jobs.
The completed answer (answer.jsonSchema) conforms to
OpenJobsSignalAnswer. Cost: 2 credits, charged once per result delivered to your organization — your own repeat calls served from cache are free, and failed runs are never charged.
Authorization
ApiKeyAuth API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.
In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
The company domain to research (e.g., "acme.com").
^[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?)*$1 <= length <= 253Optional webhook to receive the completed signal. Intended for the
async endpoints; if supplied on a synchronous /sync/ endpoint the
webhook is still delivered, in addition to the blocking response.
urilength <= 2048Force a fresh run. By default an identical request (same domain and
parameters) returns the existing result instead of re-running; set
this to true to bypass that and research again.
falseResponse Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/v1/signals/open-jobs" \ -H "Content-Type: application/json" \ -d '{ "domain": "datadoghq.com" }'{ "id": "b78e4bd7-b755-6e84-c89e-fe9f6bbc0583", "signalType": "COMPANY", "namedSignal": "open-jobs", "status": "failed", "domain": "datadoghq.com", "createdAt": "2026-07-01T10:30:00Z", "error": "Research did not complete because upstream sources were unavailable. Retry later.", "retryable": true}{ "id": "b78e4bd7-b755-6e84-c89e-fe9f6bbc0583", "signalType": "COMPANY", "namedSignal": "open-jobs", "status": "processing", "domain": "datadoghq.com", "createdAt": "2026-07-01T10:30:00Z"}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}Firmographics (sync)
Synchronous form of the Firmographics signal (POST /v1/signals/firmographics):
creates the signal and blocks until it completes, returning the result in
the same response. If you supply a webhookUrl, the completed signal is still delivered to it in addition to this response — omit it unless you want both.
The completed answer (answer.jsonSchema) conforms to
FirmographicsSignalAnswer.
Cost: 2 credits, charged once per result delivered to your organization — your own repeat calls served from cache are free, and failed runs are never charged.
Authorization
ApiKeyAuth API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.
In: header
Header Parameters
Custom timeout in seconds (max 870 — higher values are clamped). When absent, the server-configured default (870s) applies.
1 <= value <= 870If "true", returns 408 Request Timeout on timeout instead of 200 with the latest (still-processing) status.
"true" | "false"Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
The company domain to research (e.g., "acme.com").
^[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?)*$1 <= length <= 253Optional webhook to receive the completed signal. Intended for the
async endpoints; if supplied on a synchronous /sync/ endpoint the
webhook is still delivered, in addition to the blocking response.
urilength <= 2048Force a fresh run. By default an identical request (same domain and
parameters) returns the existing result instead of re-running; set
this to true to bypass that and research again.
falseResponse Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/v1/signals/sync/firmographics" \ -H "X-Sbr-Timeout-Sec: 120" \ -H "X-Sbr-Timeout-Error: false" \ -H "Content-Type: application/json" \ -d '{ "domain": "procore.com" }'{ "id": "c89f5ae8-c866-7f95-d9af-0f0a70cd0694", "signalType": "COMPANY", "namedSignal": "firmographics", "status": "completed", "domain": "procore.com", "answerType": "json_schema", "createdAt": "2026-07-01T10:30:00Z", "completedAt": "2026-07-01T10:31:55Z", "answer": { "type": "json_schema", "jsonSchema": { "name": "Procore Technologies", "domain": "procore.com", "website": "https://www.procore.com", "employeeCount": 3500, "sizeRange": "1001-5000", "type": "Public", "foundedYear": 2002, "headquarters": { "city": "Carpinteria", "state": "CA", "countryCode": "US" }, "linkedInFollowers": 320000, "linkedinIndustry": "Software Development", "saberCategory": { "primary": "Construction Software", "niche": "Construction ERP / project-cost management", "confidence": 0.92, "rationale": "Positions itself as a construction management platform for owners, GCs, and specialty contractors.", "evidence": [ { "type": "company_site", "url": "https://www.procore.com/platform", "title": "Procore Platform Overview" } ] }, "segments": [ "B2B" ], "segmentRationale": "Sells to construction firms (owners, general and specialty contractors)." } }, "confidence": 0.92, "sources": [ { "url": "https://www.procore.com/platform", "title": "Procore Platform Overview" } ]}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}Firmographics (async)
Return a company's base profile — headcount, size band, entity type, founded year, HQ location — plus a Saber-derived category that refines the coarse public industry tag, with cited web evidence.
The differentiator is saberCategory: a generalized→niche classification
that corrects the over-broad public industry label (which tags many
firms simply as "Software") using the company's own site and product
pages. segments captures who the company sells to (B2B, B2C,
B2B2C, B2G, C2C). Authoritative enrichment priors (headcount,
LinkedIn followers, type, founded year, website) are copied verbatim when
known and researched only when absent — never guessed.
This is the async endpoint. For a single blocking request, use
POST /v1/signals/sync/firmographics.
The completed answer (answer.jsonSchema) conforms to
FirmographicsSignalAnswer.
Cost: 2 credits, charged once per result delivered to your organization — your own repeat calls served from cache are free, and failed runs are never charged.
Authorization
ApiKeyAuth API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.
In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
The company domain to research (e.g., "acme.com").
^[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?)*$1 <= length <= 253Optional webhook to receive the completed signal. Intended for the
async endpoints; if supplied on a synchronous /sync/ endpoint the
webhook is still delivered, in addition to the blocking response.
urilength <= 2048Force a fresh run. By default an identical request (same domain and
parameters) returns the existing result instead of re-running; set
this to true to bypass that and research again.
falseResponse Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/v1/signals/firmographics" \ -H "Content-Type: application/json" \ -d '{ "domain": "procore.com" }'{ "id": "c89f5ae8-c866-7f95-d9af-0f0a70cd0694", "signalType": "COMPANY", "namedSignal": "firmographics", "status": "failed", "domain": "procore.com", "createdAt": "2026-07-01T10:30:00Z", "error": "Research did not complete because upstream sources were unavailable. Retry later.", "retryable": true}{ "id": "c89f5ae8-c866-7f95-d9af-0f0a70cd0694", "signalType": "COMPANY", "namedSignal": "firmographics", "status": "processing", "domain": "procore.com", "createdAt": "2026-07-01T10:30:00Z"}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}Create a company signal synchronously
⭐ This is the recommended way to create signals and get results instead of async + webhooks.
Creates a signal and waits synchronously for it to complete, returning the result in the same request. This endpoint blocks until the signal processing finishes or a timeout is reached.
Why Use the Sync Endpoint?
Advantages over async + webhooks:
- ✅ Get results immediately in one request
- ✅ No webhook hosting required
- ✅ No polling implementation needed
- ✅ Simpler integration
- ✅ Better for synchronous workflows
How It Works
- Send your signal creation request (same payload as regular POST /v1/companies/signals)
- The endpoint creates the signal and polls for completion
- Returns the completed signal with results when processing finishes
- If timeout is reached, returns the latest status (processing)
Timeout Configuration
- Default timeout: 870 seconds (server-configured, applies when the header is absent)
- Max timeout: 870 seconds — higher values are clamped
- Custom timeout: Use
X-Sbr-Timeout-Secheader to set custom timeout (up to max) - Error on timeout: Use
X-Sbr-Timeout-Error: trueheader to return 408 on timeout instead of latest status
Response Codes
200 OK- Signal completed, or timeout reached with the still-processingsignal in the body (checkstatus)408 Request Timeout- Timeout reached (when X-Sbr-Timeout-Error: true)
Using with Templates
Use signalTemplateId instead of defining questions inline for standardized research:
{ "domain": "acme.com", "signalTemplateId": "a12b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d"}Templates let you reuse research questions, qualification criteria, and answer types across multiple companies. Create templates via POST /v1/companies/signals/templates.
Credits
Each signal charges 2 credits. Repeat calls served from the 12-hour cache (see Caching Behavior on POST /v1/companies/signals) do not consume additional credits, and failed runs are never charged — reserved credits are released.
Authorization
ApiKeyAuth API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.
In: header
Header Parameters
Custom timeout in seconds (max 870 — higher values are clamped). When absent, the server-configured default (870s) applies.
1 <= value <= 870If "true", returns 408 Request Timeout on timeout instead of 200 with the latest (still-processing) status
"true" | "false"Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
The company domain to research (e.g., "acme.com")
^[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?)*$1 <= length <= 253The research question to ask about the company
1 <= length <= 500The expected format of the answer
"open_text""open_text" | "number" | "boolean" | "list" | "percentage" | "currency" | "url" | "contacts" | "contacts_generation" | "contact_posts" | "contact_engagements" | "json_schema"JSON Schema defining the expected output structure. Required when answerType is "json_schema". The AI will generate data conforming to this schema.
Supported JSON Schema features:
type: object, array, string, number, integer, boolean, nullproperties: Define object propertiesrequired: List of required property namesitems: Schema for array itemsenum: Enumeration of allowed valuesdescription: Property descriptions (helps AI generate better data)
Limitations:
- Maximum 100 total properties
- Maximum 5 levels of nesting
anyOf,oneOf,allOfare not supported$refonly supports self-references for recursive schemas
Optional webhook URL to receive notifications when processing completes.
Webhooks are only sent for freshly processed signals — cached results do not trigger webhooks.
Set forceRefresh: true to bypass the cache and ensure webhook delivery.
urilength <= 2048The importance/weight of the signal
"important" | "nice_to_have" | "not_important"Qualification criteria mapping answer values based on answerType. The structure must match the answerType specified.
For boolean answerType:
{ "yes": "good", "no": "disqualified"}For number, percentage, or currency answerType:
{ "ranges": [ { "rangeStart": 0, "rangeEnd": 100, "answerValue": "neutral" }, { "rangeStart": 101, "rangeEnd": 1000, "answerValue": "good" } ]}For list answerType:
{ "choices": { "salesforce": { "answerValue": "good", "label": "Salesforce" }, "hubspot": { "answerValue": "neutral", "label": "HubSpot" }, "none": { "answerValue": "disqualified", "label": "No CRM" } }}Valid answerValue options (from worst to best):
- disqualified: Answer indicates a deal-breaker or disqualifying factor
- poor: Answer indicates a weak fit
- neutral: Answer is acceptable but not ideal
- good: Answer indicates a strong fit
- excellent: Answer indicates an exceptional fit
Optional signal template ID to use. When provided, the template configuration (question, answerType, weight, qualificationCriteria) will be used. The system always resolves to the latest active version of the template. Only the domain parameter is required when using a template.
uuidForce re-run of the signal analysis, skipping the cache. When set to true, a new signal will be created even if a cached result exists.
falseConnector configuration for signal generation
Controls how strictly Saber verifies answers before responding.
- strict: Only returns answers backed by verified sources (primary or trusted secondary sources). Returns null when information is unavailable.
- lenient: Allows logical inference and best-effort estimates when direct evidence is missing. Uses industry benchmarks, logical correlates, and quantitative metrics.
"strict""strict" | "lenient"Response Body
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/v1/companies/signals/sync" \ -H "X-Sbr-Timeout-Sec: 120" \ -H "X-Sbr-Timeout-Error: false" \ -H "Content-Type: application/json" \ -d '{ "domain": "clay.com", "question": "Does this company have open roles in operations?", "answerType": "boolean" }'{ "id": "e45c1dc4-d422-4b51-956b-cb6d3ddaf250", "status": "completed", "domain": "clay.com", "question": "Does this company have open roles in operations?", "createdAt": "2024-01-15T10:30:00Z", "completedAt": "2024-01-15T10:32:15Z", "answer": { "type": "boolean", "boolean": { "value": true } }, "reasoning": "Based on their careers page, Clay has multiple open positions in Operations including Operations Manager and Operations Coordinator roles", "confidence": 0.95, "sources": [ { "url": "https://clay.com/careers", "title": "Careers at Clay", "snippet": "We're hiring for Operations Manager and Operations Coordinator roles..." } ]}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}List company signals
Retrieve all signals with optional filtering by domain or companyId, pagination and filtering. Results are sorted by creation date (latest first).
Note: For creating signals and getting results in one step, we recommend using the
/v1/companies/signals/sync endpoint instead, which returns the result directly.
Authorization
ApiKeyAuth API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.
In: header
Query Parameters
Filter signals by company domain (e.g., "acme.com")
^[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?)*$Filter signals by company ID
Maximum number of results per page
251 <= value <= 25Number of results to skip for pagination
00 <= valueFilter signals completed on or after this date (RFC3339 format)
date-timeFilter signals completed on or before this date (RFC3339 format)
date-timeFilter by signal status (can be specified multiple times for multiple statuses)
Filter signals by subscription ID (UUID of the signal subscription that triggered execution)
uuidResponse Body
application/json
application/json
application/json
application/json
curl -X GET "https://example.com/v1/companies/signals?domain=acme.com&companyId=comp_abc123&limit=25&offset=0&fromDate=2024-01-01T00%3A00%3A00Z&toDate=2024-12-31T23%3A59%3A59Z&status=completed&subscriptionId=a12b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d"{ "results": [ { "id": "e45c1dc4-d422-4b51-956b-cb6d3ddaf250", "status": "completed", "domain": "acme.com", "question": "What is their main product?", "createdAt": "2024-01-15T10:30:00Z", "completedAt": "2024-01-15T10:32:00Z", "answer": { "type": "open_text", "openText": { "value": "Enterprise CRM software" } }, "confidence": 0.95 }, { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "status": "processing", "domain": "acme.com", "question": "How many employees?", "createdAt": "2024-01-15T09:00:00Z" } ], "total": 42, "limit": 25, "offset": 0, "count": 2}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}Create a company signal asynchronously
Submit a domain and question to create a new research signal. The AI will analyze the domain and provide a structured answer based on the specified answer type.
When to Use This Endpoint
Use this endpoint for event-driven architectures where you need webhook notifications.
For simpler integrations, use the /v1/companies/signals/sync endpoint (recommended) which returns results immediately.
Webhooks
Configure webhooks by including a webhookUrl parameter in your request.
What we deliver:
One logical delivery per signal, once it reaches a terminal state — retries
(below) mean your endpoint may see it as more than one HTTP request, all
carrying the same X-Idempotency-Key. The body is the signal object itself —
there is no event envelope and no event-type header, so read the body's
status (completed or failed) to tell the outcome. One exception: a
Slack webhook URL (https://hooks.slack.com/services/…) receives a formatted
Slack message instead of the raw signal object.
Webhook security:
Deliveries are not signed. Treat the payload as untrusted: use an unguessable
webhookUrl, and re-read the signal via GET /v1/companies/signals/{signalId}
before acting on it. Each delivery carries an X-Idempotency-Key header you can
use to discard duplicates.
Webhook reliability:
- Deliveries that fail to connect, time out, or return 5xx are attempted up to 5 times in total with exponential backoff
- A 4xx response is treated as a permanent rejection and is not retried
- A
webhookUrlwhose host does not resolve in DNS is rejected without retry, so point it at a hostname that already resolves - Webhook requests timeout after 25 seconds
- Your endpoint should respond with 2xx status code
- A failed delivery never fails the signal: the answer is still produced, billed, and readable via the API
Caching Behavior
Your response will be cached for up to 12 hours by default, unless you set the forceRefresh flag to true.
Cache is based on a hash of the following fields: domain (or contactProfileUrl for contact signals), question, answer type, verification mode, and output schema (if provided). Changing any of these fields will create a new signal. We will not send you the webhook if you hit the cache, even if the webhook URL in the payload is different from the original request.
Instead you will receive the latest status of the signal immediately in the response.
Using with Templates
Use signalTemplateId instead of defining questions inline for standardized research:
{ "domain": "acme.com", "signalTemplateId": "a12b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d", "webhookUrl": "https://myapp.com/webhooks/signals"}Templates let you reuse research questions, qualification criteria, and answer types across multiple companies. Create templates via POST /v1/companies/signals/templates.
Credits
Each signal charges 2 credits. Repeat calls served from the cache (see Caching Behavior above) do not consume additional credits, and failed runs are never charged — reserved credits are released.
Authorization
ApiKeyAuth API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.
In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
The company domain to research (e.g., "acme.com")
^[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?)*$1 <= length <= 253The research question to ask about the company
1 <= length <= 500The expected format of the answer
"open_text""open_text" | "number" | "boolean" | "list" | "percentage" | "currency" | "url" | "contacts" | "contacts_generation" | "contact_posts" | "contact_engagements" | "json_schema"JSON Schema defining the expected output structure. Required when answerType is "json_schema". The AI will generate data conforming to this schema.
Supported JSON Schema features:
type: object, array, string, number, integer, boolean, nullproperties: Define object propertiesrequired: List of required property namesitems: Schema for array itemsenum: Enumeration of allowed valuesdescription: Property descriptions (helps AI generate better data)
Limitations:
- Maximum 100 total properties
- Maximum 5 levels of nesting
anyOf,oneOf,allOfare not supported$refonly supports self-references for recursive schemas
Optional webhook URL to receive notifications when processing completes.
Webhooks are only sent for freshly processed signals — cached results do not trigger webhooks.
Set forceRefresh: true to bypass the cache and ensure webhook delivery.
urilength <= 2048The importance/weight of the signal
"important" | "nice_to_have" | "not_important"Qualification criteria mapping answer values based on answerType. The structure must match the answerType specified.
For boolean answerType:
{ "yes": "good", "no": "disqualified"}For number, percentage, or currency answerType:
{ "ranges": [ { "rangeStart": 0, "rangeEnd": 100, "answerValue": "neutral" }, { "rangeStart": 101, "rangeEnd": 1000, "answerValue": "good" } ]}For list answerType:
{ "choices": { "salesforce": { "answerValue": "good", "label": "Salesforce" }, "hubspot": { "answerValue": "neutral", "label": "HubSpot" }, "none": { "answerValue": "disqualified", "label": "No CRM" } }}Valid answerValue options (from worst to best):
- disqualified: Answer indicates a deal-breaker or disqualifying factor
- poor: Answer indicates a weak fit
- neutral: Answer is acceptable but not ideal
- good: Answer indicates a strong fit
- excellent: Answer indicates an exceptional fit
Optional signal template ID to use. When provided, the template configuration (question, answerType, weight, qualificationCriteria) will be used. The system always resolves to the latest active version of the template. Only the domain parameter is required when using a template.
uuidForce re-run of the signal analysis, skipping the cache. When set to true, a new signal will be created even if a cached result exists.
falseConnector configuration for signal generation
Controls how strictly Saber verifies answers before responding.
- strict: Only returns answers backed by verified sources (primary or trusted secondary sources). Returns null when information is unavailable.
- lenient: Allows logical inference and best-effort estimates when direct evidence is missing. Uses industry benchmarks, logical correlates, and quantitative metrics.
"strict""strict" | "lenient"Response Body
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/v1/companies/signals" \ -H "Content-Type: application/json" \ -d '{ "domain": "clay.com", "question": "What is Clay\'s main product offering?", "answerType": "open_text", "webhookUrl": "https://myapp.com/webhooks/signals" }'{ "id": "e45c1dc4-d422-4b51-956b-cb6d3ddaf250", "status": "processing", "domain": "clay.com", "question": "What is Clay's main product offering?", "createdAt": "2024-01-15T10:30:00Z"}{ "error": "BAD_REQUEST", "message": "Invalid JSON in request body"}{ "error": "UNAUTHORIZED", "message": "Missing or invalid API key"}{ "error": "VALIDATION_ERROR", "message": "Invalid request body", "details": [ { "field": "domain", "message": "must be a valid hostname" } ]}{ "statusCode": 429, "message": "Rate limit exceeded", "error": "Too Many Requests", "retryAfter": 45}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}Create company signals in batch
Submit multiple signals and domains to create signals using a Cartesian product pattern. Each signal is combined with each domain to create individual signals.
Two ways to create batch signals:
- Inline Questions: Define questions directly in the request for ad-hoc research without creating templates
- Using Templates (recommended for reusability): Reference pre-created templates by ID for consistent, reusable questions
Cartesian Product Logic:
- If you submit 2 templates and 3 domains, the system creates 6 signals (2 × 3)
- Sync mode (default): Maximum 100 resulting signals (templates × domains ≤ 100)
- Async mode (
async: true): Maximum 20,000 resulting signals (templates × domains ≤ 20,000)
Sync Mode (default):
- Returns inline results with individual signal statuses
- Maximum 100 signals per batch
- Returns 202 with
results[]array
Async Mode (async: true):
- For large batches up to 20,000 signals
- Returns immediately with a
batchIdfor tracking - Signals are processed in background chunks
- Returns 202 with
batchId,totalSignals,status: "accepted" - Poll
/v1/companies/signals/batches/status?domain=...for progress
Partial Failure Handling (sync mode):
- Individual signal failures don't block other signals from processing
- Each signal in the response includes its own status (accepted or failed)
- Returns 202 if at least one signal is scheduled successfully
- Returns 422 if all signals failed to be scheduled
Processing:
- All signals are processed asynchronously
- No guarantee of processing order
- Use the
/v1/companies/signals/syncendpoint (recommended) to retrieve results as they complete
Webhooks:
- Each signal in the batch can include a
webhookUrlto receive notifications on completion - Webhooks fire individually per signal as each one completes processing
- Each signal gets one logical delivery, retried on failure — dedupe HTTP requests on the
X-Idempotency-Keyheader - The delivery body is the signal object itself, with no event envelope — read its
status(completedorfailed) for the outcome. A Slack webhook URL receives a formatted Slack message instead - Deliveries are not signed
Caching Behavior:
- Signals are cached based on a hash of domain, question, answer type, verification mode, and output schema (if provided)
- If a matching cached result exists, the cached response is returned immediately and no webhook is sent
- To force fresh processing (and webhook delivery), set
forceRefresh: trueon individual signals
Automatic Summary Generation:
- Set
generateSummaryOnCompletetotrueto automatically generate summaries when all signals in the batch complete - Summaries are generated per domain (one summary per unique domain in the batch)
- Summary generation is triggered automatically once all signals for a domain have completed
- Use the
/v1/companies/signals/summariesendpoint to retrieve generated summaries
Credits: 2 credits per signal created. The batch expands every question across every company — 2 questions × 3 companies creates 6 signals and charges 12 credits. Cached results and failed runs are not charged.
Authorization
ApiKeyAuth API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.
In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Array of signals to create. Each signal will be combined with each domain using Cartesian product logic. You can either:
- Provide inline signal configuration with
questionand optional fields (quick ad-hoc research) - Use
templateIdto reference a pre-created template (recommended for reusability)
1 <= itemsArray of company domains to research. Each domain will be combined with each signal template using Cartesian product logic. The total resulting signals (len(signals) × len(domains)) must not exceed 100.
1 <= items <= 100Whether to automatically generate a summary when all signals in the batch are completed.
When set to true, a summary will be automatically generated for each unique domain in the batch
once all signals for that domain have completed processing.
falseWhen true, enables async processing with a higher limit of 20,000 signals.
Returns a batchId for tracking instead of inline results.
The response shape differs from sync mode — returns { batchId, submittedAt, totalSignals, status, async }.
Use /v1/companies/signals/batches/status?domain=... to poll for progress.
falseResponse Body
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/v1/companies/signals/batch" \ -H "Content-Type: application/json" \ -d '{ "signals": [ { "question": "What is their main product offering?", "answerType": "open_text", "weight": "important" }, { "question": "How many employees do they have?", "answerType": "number", "weight": "nice_to_have" }, { "question": "Are they venture-backed?", "answerType": "boolean", "weight": "important" } ], "domains": [ "acme.com", "techcorp.io" ], "generateSummaryOnComplete": false }'{ "batchId": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "submittedAt": "2024-01-15T10:30:00Z", "totalSignals": 15000, "status": "accepted", "async": true}{ "error": "BAD_REQUEST", "message": "Invalid JSON in request body"}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": "VALIDATION_ERROR", "message": "Invalid request body", "details": [ { "field": "domains", "message": "at least one domain is required" } ]}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}Create a contact signal synchronously
⭐ This is the recommended way to create contact signals and get results instead of async + webhooks.
Creates a contact signal and waits synchronously for it to complete, returning the result in the same request. Works identically to the company signals sync endpoint but for contact-based signals.
Why Use the Sync Endpoint?
Advantages over async + webhooks:
- ✅ Get results immediately in one request
- ✅ No webhook hosting required
- ✅ No polling implementation needed
- ✅ Simpler integration
- ✅ Better for synchronous workflows
How It Works
- Send your signal creation request (same payload as regular POST /v1/contacts/signals)
- The endpoint creates the signal and polls for completion
- Returns the completed signal with results when processing finishes
- If timeout is reached, returns the latest status (processing)
Timeout Configuration
- Default timeout: 870 seconds (server-configured, applies when the header is absent)
- Max timeout: 870 seconds — higher values are clamped
- Custom timeout: Use
X-Sbr-Timeout-Secheader to set custom timeout (up to max) - Error on timeout: Use
X-Sbr-Timeout-Error: trueheader to return 408 on timeout instead of latest status
Response Codes
200 OK- Signal completed, or timeout reached with the still-processingsignal in the body (checkstatus)408 Request Timeout- Timeout reached (when X-Sbr-Timeout-Error: true)
Using with Templates
Use signalTemplateId instead of defining questions inline for standardized research:
{ "contactProfileUrl": "https://linkedin.com/in/johndoe", "signalTemplateId": "a12b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d"}Templates let you reuse research questions, qualification criteria, and answer types across multiple contacts. Create templates via POST /v1/companies/signals/templates.
Credits
Each signal charges 2 credits. Repeat calls served from the cache do not consume additional credits, and failed runs are never charged — reserved credits are released.
Authorization
ApiKeyAuth API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.
In: header
Header Parameters
Custom timeout in seconds (max 870 — higher values are clamped). When absent, the server-configured default (870s) applies.
1 <= value <= 870If "true", returns 408 Request Timeout on timeout instead of 200 with the latest (still-processing) status
"true" | "false"Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
The contact profile URL to research (e.g., "https://linkedin.com/in/johndoe")
uri1 <= length <= 500The research question to ask about the contact
1 <= length <= 500The expected format of the answer
"open_text""open_text" | "number" | "boolean" | "list" | "percentage" | "currency" | "url" | "contacts" | "contacts_generation" | "contact_posts" | "contact_engagements" | "json_schema"JSON Schema defining the expected output structure. Required when answerType is "json_schema". See CreateSignalRequest.outputSchema for full documentation.
Optional webhook URL to receive notifications when processing completes.
Webhooks are only sent for freshly processed signals — cached results do not trigger webhooks.
Set forceRefresh: true to bypass the cache and ensure webhook delivery.
urilength <= 2048The importance/weight of the signal
"important" | "nice_to_have" | "not_important"Qualification criteria mapping answer values based on answerType (same structure as company signals)
Optional signal template ID to use
uuidConnector configuration for signal generation
Controls how strictly Saber verifies answers before responding.
- strict: Only returns answers backed by verified sources (primary or trusted secondary sources). Returns null when information is unavailable.
- lenient: Allows logical inference and best-effort estimates when direct evidence is missing. Uses industry benchmarks, logical correlates, and quantitative metrics.
"strict""strict" | "lenient"Force re-run of the signal analysis, skipping the cache. When set to true, a new signal will be created even if a cached result exists.
falseResponse Body
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/v1/contacts/signals/sync" \ -H "X-Sbr-Timeout-Sec: 120" \ -H "X-Sbr-Timeout-Error: false" \ -H "Content-Type: application/json" \ -d '{ "contactProfileUrl": "https://linkedin.com/in/johndoe", "question": "What are this person\'s main professional interests?", "answerType": "open_text" }'{ "id": "e45c1dc4-d422-4b51-956b-cb6d3ddaf250", "status": "completed", "contactProfileUrl": "https://linkedin.com/in/johndoe", "question": "What are this person's main professional interests?", "createdAt": "2024-01-15T10:30:00Z", "completedAt": "2024-01-15T10:32:15Z", "answer": { "type": "open_text", "openText": { "value": "Software engineering, AI/ML, and developer tools" } }, "confidence": 0.9}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}List contact signals
Retrieve all contact signals with optional filtering by LinkedIn URL, pagination and filtering. Results are sorted by creation date (latest first).
Note: For creating contact signals and getting results in one step, we recommend using the
/v1/contacts/signals/sync endpoint instead, which returns the result directly.
Authorization
ApiKeyAuth API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.
In: header
Query Parameters
Filter signals by contact profile URL (LinkedIn or other professional profile)
uriMaximum number of results per page
251 <= value <= 25Number of results to skip for pagination
00 <= valueResponse Body
application/json
application/json
application/json
application/json
curl -X GET "https://example.com/v1/contacts/signals?contactProfileUrl=https%3A%2F%2Flinkedin.com%2Fin%2Fjohndoe&limit=25&offset=0"{ "results": [ { "id": "e45c1dc4-d422-4b51-956b-cb6d3ddaf250", "status": "processing", "question": "What is Acme Corp's main business focus?", "answerType": "boolean", "createdAt": "2024-01-15T10:30:00Z", "signalType": "COMPANY", "domain": "acme.com", "completedAt": "2024-01-15T10:32:15Z", "answer": { "type": "open_text", "open_text": { "value": "Acme Corp is a leading provider of enterprise software solutions" } }, "reasoning": "Based on the company's website and public information, Acme Corp specializes in enterprise software.", "confidence": 0.95, "sources": [ { "url": "https://acme.com/about", "title": "About Acme Corp", "snippet": "Leading provider of enterprise software..." } ], "metadata": { "companyName": "Acme Corp", "processingTimeMs": 45200, "connectors": { "salesNavigator": { "status": "ok" } } }, "error": "LinkedIn data is currently unavailable due to rate limits. Please try again later.", "errorCode": "LINKEDIN_RATE_LIMIT_EXCEEDED", "errorAction": "You can: (1) Set connectors.salesNavigator.enabled=\"off\" to skip LinkedIn data, (2) Add more LinkedIn connectors, or (3) Try again in 24 hours when rate limits reset.", "retryable": true, "changeContext": { "changeType": "CHANGED", "changeDelta": { "type": "LIST", "added": [ "Enterprise" ], "removed": [ "Starter" ] }, "previousSignalId": "feb2e1c1-dc67-49f6-a459-62383c67daf5", "changedFields": [ "certifications", "contacts", "headline" ], "addedFields": [ "contacts", "certifications" ], "updatedFields": [ "headline", "engagement.reactionCount" ], "removedFields": [ "positions" ] }, "verificationMode": "strict", "company": { "id": "comp_abc123", "name": "Acme Corp", "domain": "acme.com", "industry": "Software", "website": "https://acme.com", "size": "51-200", "type": "private", "founded": 2015, "city": "San Francisco", "state": "California", "countryCode": "US", "handle": "acme-corp", "linkedInId": 12345678, "linkedInUrl": "https://www.linkedin.com/company/acme-corp", "linkedInFollowers": 5200, "employeeCount": 150, "description": "Acme Corp is a leading provider of enterprise software solutions.", "logoUrl": "https://media.licdn.com/dms/image/acme-logo.png" } } ], "total": 0, "limit": 0, "offset": 0, "count": 0}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}Create a contact signal asynchronously
Submit a LinkedIn URL and question to create a new research signal for an individual contact. The AI will analyze the contact's profile and provide a structured answer based on the specified answer type.
Contact signals work similarly to company signals but focus on individual contacts using their LinkedIn profile URLs.
When to Use This Endpoint
Use this endpoint for event-driven architectures where you need webhook notifications.
For simpler integrations, use the /v1/contacts/signals/sync endpoint (recommended) which returns results immediately.
Webhooks
Configure webhooks by including a webhookUrl parameter in your request.
What we deliver:
One logical delivery per signal, once it reaches a terminal state — retries
(below) mean your endpoint may see it as more than one HTTP request, all
carrying the same X-Idempotency-Key. The body is the signal object itself —
there is no event envelope and no event-type header, so read the body's
status (completed or failed) to tell the outcome. One exception: a
Slack webhook URL (https://hooks.slack.com/services/…) receives a formatted
Slack message instead of the raw signal object.
Webhook security:
Deliveries are not signed. Treat the payload as untrusted: use an unguessable
webhookUrl, and re-read the signal via GET /v1/contacts/signals/{signalId}
before acting on it. Each delivery carries an X-Idempotency-Key header you can
use to discard duplicates.
Webhook reliability:
- Deliveries that fail to connect, time out, or return 5xx are attempted up to 5 times in total with exponential backoff
- A 4xx response is treated as a permanent rejection and is not retried
- A
webhookUrlwhose host does not resolve in DNS is rejected without retry, so point it at a hostname that already resolves - Webhook requests timeout after 25 seconds
- Your endpoint should respond with 2xx status code
- A failed delivery never fails the signal: the answer is still produced, billed, and readable via the API
Using with Templates
Use signalTemplateId instead of defining questions inline for standardized research:
{ "contactProfileUrl": "https://linkedin.com/in/johndoe", "signalTemplateId": "a12b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d", "webhookUrl": "https://myapp.com/webhooks/signals"}Templates let you reuse research questions, qualification criteria, and answer types across multiple contacts. Create templates via POST /v1/companies/signals/templates.
Contact signals work similarly to company signals but focus on individual contacts using their LinkedIn profile URLs.
Credits
Each signal charges 2 credits. Repeat calls served from the cache do not consume additional credits, and failed runs are never charged — reserved credits are released.
Authorization
ApiKeyAuth API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.
In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
The contact profile URL to research (e.g., "https://linkedin.com/in/johndoe")
uri1 <= length <= 500The research question to ask about the contact
1 <= length <= 500The expected format of the answer
"open_text""open_text" | "number" | "boolean" | "list" | "percentage" | "currency" | "url" | "contacts" | "contacts_generation" | "contact_posts" | "contact_engagements" | "json_schema"JSON Schema defining the expected output structure. Required when answerType is "json_schema". See CreateSignalRequest.outputSchema for full documentation.
Optional webhook URL to receive notifications when processing completes.
Webhooks are only sent for freshly processed signals — cached results do not trigger webhooks.
Set forceRefresh: true to bypass the cache and ensure webhook delivery.
urilength <= 2048The importance/weight of the signal
"important" | "nice_to_have" | "not_important"Qualification criteria mapping answer values based on answerType (same structure as company signals)
Optional signal template ID to use
uuidConnector configuration for signal generation
Controls how strictly Saber verifies answers before responding.
- strict: Only returns answers backed by verified sources (primary or trusted secondary sources). Returns null when information is unavailable.
- lenient: Allows logical inference and best-effort estimates when direct evidence is missing. Uses industry benchmarks, logical correlates, and quantitative metrics.
"strict""strict" | "lenient"Force re-run of the signal analysis, skipping the cache. When set to true, a new signal will be created even if a cached result exists.
falseResponse Body
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/v1/contacts/signals" \ -H "Content-Type: application/json" \ -d '{ "contactProfileUrl": "https://linkedin.com/in/johndoe", "question": "What are this person\'s main professional interests?", "answerType": "open_text", "webhookUrl": "https://myapp.com/webhooks/signals" }'{ "id": "e45c1dc4-d422-4b51-956b-cb6d3ddaf250", "status": "processing", "contactProfileUrl": "https://linkedin.com/in/johndoe", "question": "What are this person's main professional interests?", "createdAt": "2024-01-15T10:30:00Z"}{ "error": "BAD_REQUEST", "message": "Invalid JSON in request body"}{ "error": "UNAUTHORIZED", "message": "Missing or invalid API key"}{ "statusCode": 429, "message": "Rate limit exceeded", "error": "Too Many Requests", "retryAfter": 45}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}Get a company signal by ID
Retrieve the current status and results of a signal. If the signal is completed, the response will include the AI-generated answer, confidence score, and sources.
Authorization
ApiKeyAuth API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.
In: header
Path Parameters
The unique identifier of the signal (UUID format)
^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$Response Body
application/json
application/json
application/json
application/json
curl -X GET "https://example.com/v1/companies/signals/e45c1dc4-d422-4b51-956b-cb6d3ddaf250"{ "id": "e45c1dc4-d422-4b51-956b-cb6d3ddaf250", "status": "processing", "domain": "acme.com", "question": "What is Acme Corp's main business focus?", "createdAt": "2024-01-15T10:30:00Z"}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": "NOT_FOUND", "message": "Signal not found or access denied"}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}List signal executions for a subscription
Retrieve all signal executions that were triggered by a specific signal subscription.
Returns the same paginated response as GET /v1/companies/signals but filtered to a single subscription.
Results are sorted by creation date (latest first).
Authorization
ApiKeyAuth API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.
In: header
Path Parameters
The UUID of the signal subscription
uuidQuery Parameters
Filter signals by company domain
Filter signals by company ID
Maximum number of results per page
251 <= value <= 25Number of results to skip for pagination
00 <= valueFilter signals completed on or after this date (RFC3339 format)
date-timeFilter signals completed on or before this date (RFC3339 format)
date-timeFilter by signal status (can be specified multiple times)
Response Body
application/json
application/json
application/json
application/json
application/json
curl -X GET "https://example.com/v1/companies/signals/subscriptions/a12b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d/logs?domain=acme.com&companyId=b23c4d5e-6f7a-8b9c-0d1e-2f3a4b5c6d7e&limit=25&offset=0&fromDate=2024-01-01T00%3A00%3A00Z&toDate=2024-12-31T23%3A59%3A59Z&status=completed"{ "results": [ { "id": "e45c1dc4-d422-4b51-956b-cb6d3ddaf250", "status": "processing", "question": "What is Acme Corp's main business focus?", "answerType": "boolean", "createdAt": "2024-01-15T10:30:00Z", "signalType": "COMPANY", "domain": "acme.com", "completedAt": "2024-01-15T10:32:15Z", "answer": { "type": "open_text", "open_text": { "value": "Acme Corp is a leading provider of enterprise software solutions" } }, "reasoning": "Based on the company's website and public information, Acme Corp specializes in enterprise software.", "confidence": 0.95, "sources": [ { "url": "https://acme.com/about", "title": "About Acme Corp", "snippet": "Leading provider of enterprise software..." } ], "metadata": { "companyName": "Acme Corp", "processingTimeMs": 45200, "connectors": { "salesNavigator": { "status": "ok" } } }, "error": "LinkedIn data is currently unavailable due to rate limits. Please try again later.", "errorCode": "LINKEDIN_RATE_LIMIT_EXCEEDED", "errorAction": "You can: (1) Set connectors.salesNavigator.enabled=\"off\" to skip LinkedIn data, (2) Add more LinkedIn connectors, or (3) Try again in 24 hours when rate limits reset.", "retryable": true, "changeContext": { "changeType": "CHANGED", "changeDelta": { "type": "LIST", "added": [ "Enterprise" ], "removed": [ "Starter" ] }, "previousSignalId": "feb2e1c1-dc67-49f6-a459-62383c67daf5", "changedFields": [ "certifications", "contacts", "headline" ], "addedFields": [ "contacts", "certifications" ], "updatedFields": [ "headline", "engagement.reactionCount" ], "removedFields": [ "positions" ] }, "verificationMode": "strict", "company": { "id": "comp_abc123", "name": "Acme Corp", "domain": "acme.com", "industry": "Software", "website": "https://acme.com", "size": "51-200", "type": "private", "founded": 2015, "city": "San Francisco", "state": "California", "countryCode": "US", "handle": "acme-corp", "linkedInId": 12345678, "linkedInUrl": "https://www.linkedin.com/company/acme-corp", "linkedInFollowers": 5200, "employeeCount": 150, "description": "Acme Corp is a leading provider of enterprise software solutions.", "logoUrl": "https://media.licdn.com/dms/image/acme-logo.png" } } ], "total": 42, "limit": 25, "offset": 0, "count": 25}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}Get a contact signal by ID
Retrieve the current status and results of a contact signal. If the signal is completed, the response will include the AI-generated answer, confidence score, and sources.
Authorization
ApiKeyAuth API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.
In: header
Path Parameters
The unique identifier of the contact signal (UUID format)
^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$Response Body
application/json
application/json
application/json
application/json
curl -X GET "https://example.com/v1/contacts/signals/e45c1dc4-d422-4b51-956b-cb6d3ddaf250"{ "id": "e45c1dc4-d422-4b51-956b-cb6d3ddaf250", "status": "completed", "contactProfileUrl": "https://linkedin.com/in/johndoe", "question": "What are this person's main professional interests?", "createdAt": "2024-01-15T10:30:00Z", "completedAt": "2024-01-15T10:32:15Z", "answer": { "type": "open_text", "openText": { "value": "Software engineering, AI/ML, and developer tools" } }, "reasoning": "Based on LinkedIn profile analysis, this person regularly engages with content about software engineering and AI/ML topics.", "confidence": 0.9, "sources": [ { "url": "https://linkedin.com/in/johndoe", "title": "John Doe - LinkedIn", "snippet": "Passionate about building AI-powered developer tools..." } ]}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}Get contact research by external ID
Retrieve a contact research request by external ID and external source. This endpoint allows you to look up contact research requests using identifiers from external systems (e.g., HubSpot contact ID).
Authorization
ApiKeyAuth API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.
In: header
Query Parameters
The external identifier of the contact research request (e.g., HubSpot contact ID)
1 <= length <= 100The source system that provided the external ID (e.g., "hubspot")
1 <= length <= 50Response Body
application/json
application/json
application/json
application/json
application/json
application/json
curl -X GET "https://example.com/v1/contacts/research?externalId=hubspot_12345&externalSource=hubspot"{ "id": "cr_abc123def456", "status": "processing", "firstName": "John", "lastName": "Doe", "companyName": "Acme Corp", "companyDomain": "acme.com", "createdAt": "2024-01-15T10:30:00Z"}{ "error": "BAD_REQUEST", "message": "Invalid JSON in request body"}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": "NOT_FOUND", "message": "Contact research not found or access denied"}{ "error": "VALIDATION_ERROR", "message": "Query parameters externalId and externalSource are required"}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}Start a contact research job
Submit contact details to create a new contact research request. The AI will gather information from LinkedIn, email services, and other data sources to provide comprehensive contact insights.
The research will be processed asynchronously. Use the returned contact research ID to check status via the GET endpoint, or configure a webhook to receive completion notifications.
Credits
Each research request charges 2 credits. Credits are deducted on success and released if the research fails.
Authorization
ApiKeyAuth API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.
In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
First name of the contact
1 <= length <= 100Last name of the contact
1 <= length <= 100Name of the contact's company
1 <= length <= 200Company domain (e.g., "acme.com")
^[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?)*$1 <= length <= 253Contact profile URL of the contact (e.g., LinkedIn or other professional profile, optional)
urilength <= 500LinkedIn Sales Navigator profile URL of the contact (optional)
urilength <= 500Job title of the contact (optional)
1 <= length <= 200Optional webhook URL to receive notifications when processing completes
urilength <= 2048Response Body
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/v1/contacts/research" \ -H "Content-Type: application/json" \ -d '{ "firstName": "John", "lastName": "Doe", "companyName": "Acme Corp", "companyDomain": "acme.com", "jobTitle": "VP of Sales" }'{ "id": "cr_abc123def456", "status": "processing", "createdAt": "2024-01-15T10:30:00Z"}{ "error": "BAD_REQUEST", "message": "Invalid JSON in request body"}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": "VALIDATION_ERROR", "message": "Invalid request body", "details": [ { "field": "companyDomain", "message": "must be a valid hostname" } ]}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}Get contact research by ID
Retrieve a contact research request by ID, including its status and results if completed. This endpoint returns the current state of the research request.
Authorization
ApiKeyAuth API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.
In: header
Path Parameters
The unique identifier of the contact research request
Response Body
application/json
application/json
application/json
curl -X GET "https://example.com/v1/contacts/research/cr_abc123def456"{ "id": "cr_abc123def456", "status": "processing", "firstName": "John", "lastName": "Doe", "companyName": "Acme Corp", "companyDomain": "acme.com", "createdAt": "2024-01-15T10:30:00Z"}{ "error": "NOT_FOUND", "message": "Contact research not found or access denied"}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}Search contacts with LinkedIn Sales Navigator
Search for contacts using LinkedIn Sales Navigator. Optionally scoped to one or more companies via companyLinkedInUrls. When multiple URLs are provided, each company is searched separately and results are merged and deduplicated.
Pagination: Use limit (default 25, max 100) and offset (default 0) in the request body
to page through results. The response includes total, limit, offset, and hasMore
to support cursor-free pagination.
Requirements:
- At least one search parameter must be provided:
companyLinkedInUrls,firstName,lastName,jobTitles,keywords,countries,departments, orseniorityLevels. - LinkedIn Sales Navigator connection is required for the API key owner
Response:
- If Sales Navigator is not connected, returns
salesNavConnected: falsewith empty contacts - If connected, returns matching contacts with profile information and pagination metadata
Authorization
ApiKeyAuth API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.
In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
LinkedIn company URLs to scope the search (note: plural — pass an array even for a single company). Supports multiple companies; results are merged and deduplicated. Omit to search across all companies.
First name of the contact to search for
length <= 100Last name of the contact to search for
length <= 100Job titles to search for (plural — pass an array)
Keywords to search for in contact profiles (e.g., skills, technologies)
length <= 500Countries to filter contacts by location. Must be ISO 3166-1 alpha-2 codes (e.g., "US", "GB", "DE") — full country names are not accepted.
Department (function) filter using LinkedIn Sales Navigator taxonomy. Multiple values are OR'd together. Combined with other filters via AND. All values are treated as INCLUDED — exclusion is not currently supported.
Seniority level filter using LinkedIn Sales Navigator taxonomy. Multiple values are OR'd together. Combined with other filters via AND. All values are treated as INCLUDED — exclusion is not currently supported.
Maximum number of contacts to return per page
251 <= value <= 100Zero-based offset for pagination
00 <= valueLinkedIn company URLs to scope the search (note: plural — pass an array even for a single company). Supports multiple companies; results are merged and deduplicated. Omit to search across all companies.
First name of the contact to search for
length <= 100Last name of the contact to search for
length <= 100Job titles to search for (plural — pass an array)
Keywords to search for in contact profiles (e.g., skills, technologies)
length <= 500Countries to filter contacts by location. Must be ISO 3166-1 alpha-2 codes (e.g., "US", "GB", "DE") — full country names are not accepted.
Department (function) filter using LinkedIn Sales Navigator taxonomy. Multiple values are OR'd together. Combined with other filters via AND. All values are treated as INCLUDED — exclusion is not currently supported.
Seniority level filter using LinkedIn Sales Navigator taxonomy. Multiple values are OR'd together. Combined with other filters via AND. All values are treated as INCLUDED — exclusion is not currently supported.
Maximum number of contacts to return per page
251 <= value <= 100Zero-based offset for pagination
00 <= valueLinkedIn company URLs to scope the search (note: plural — pass an array even for a single company). Supports multiple companies; results are merged and deduplicated. Omit to search across all companies.
First name of the contact to search for
length <= 100Last name of the contact to search for
length <= 100Job titles to search for (plural — pass an array)
Keywords to search for in contact profiles (e.g., skills, technologies)
length <= 500Countries to filter contacts by location. Must be ISO 3166-1 alpha-2 codes (e.g., "US", "GB", "DE") — full country names are not accepted.
Department (function) filter using LinkedIn Sales Navigator taxonomy. Multiple values are OR'd together. Combined with other filters via AND. All values are treated as INCLUDED — exclusion is not currently supported.
Seniority level filter using LinkedIn Sales Navigator taxonomy. Multiple values are OR'd together. Combined with other filters via AND. All values are treated as INCLUDED — exclusion is not currently supported.
Maximum number of contacts to return per page
251 <= value <= 100Zero-based offset for pagination
00 <= valueLinkedIn company URLs to scope the search (note: plural — pass an array even for a single company). Supports multiple companies; results are merged and deduplicated. Omit to search across all companies.
First name of the contact to search for
length <= 100Last name of the contact to search for
length <= 100Job titles to search for (plural — pass an array)
Keywords to search for in contact profiles (e.g., skills, technologies)
length <= 500Countries to filter contacts by location. Must be ISO 3166-1 alpha-2 codes (e.g., "US", "GB", "DE") — full country names are not accepted.
Department (function) filter using LinkedIn Sales Navigator taxonomy. Multiple values are OR'd together. Combined with other filters via AND. All values are treated as INCLUDED — exclusion is not currently supported.
Seniority level filter using LinkedIn Sales Navigator taxonomy. Multiple values are OR'd together. Combined with other filters via AND. All values are treated as INCLUDED — exclusion is not currently supported.
Maximum number of contacts to return per page
251 <= value <= 100Zero-based offset for pagination
00 <= valueLinkedIn company URLs to scope the search (note: plural — pass an array even for a single company). Supports multiple companies; results are merged and deduplicated. Omit to search across all companies.
First name of the contact to search for
length <= 100Last name of the contact to search for
length <= 100Job titles to search for (plural — pass an array)
Keywords to search for in contact profiles (e.g., skills, technologies)
length <= 500Countries to filter contacts by location. Must be ISO 3166-1 alpha-2 codes (e.g., "US", "GB", "DE") — full country names are not accepted.
Department (function) filter using LinkedIn Sales Navigator taxonomy. Multiple values are OR'd together. Combined with other filters via AND. All values are treated as INCLUDED — exclusion is not currently supported.
Seniority level filter using LinkedIn Sales Navigator taxonomy. Multiple values are OR'd together. Combined with other filters via AND. All values are treated as INCLUDED — exclusion is not currently supported.
Maximum number of contacts to return per page
251 <= value <= 100Zero-based offset for pagination
00 <= valueLinkedIn company URLs to scope the search (note: plural — pass an array even for a single company). Supports multiple companies; results are merged and deduplicated. Omit to search across all companies.
First name of the contact to search for
length <= 100Last name of the contact to search for
length <= 100Job titles to search for (plural — pass an array)
Keywords to search for in contact profiles (e.g., skills, technologies)
length <= 500Countries to filter contacts by location. Must be ISO 3166-1 alpha-2 codes (e.g., "US", "GB", "DE") — full country names are not accepted.
Department (function) filter using LinkedIn Sales Navigator taxonomy. Multiple values are OR'd together. Combined with other filters via AND. All values are treated as INCLUDED — exclusion is not currently supported.
Seniority level filter using LinkedIn Sales Navigator taxonomy. Multiple values are OR'd together. Combined with other filters via AND. All values are treated as INCLUDED — exclusion is not currently supported.
Maximum number of contacts to return per page
251 <= value <= 100Zero-based offset for pagination
00 <= valueLinkedIn company URLs to scope the search (note: plural — pass an array even for a single company). Supports multiple companies; results are merged and deduplicated. Omit to search across all companies.
First name of the contact to search for
length <= 100Last name of the contact to search for
length <= 100Job titles to search for (plural — pass an array)
Keywords to search for in contact profiles (e.g., skills, technologies)
length <= 500Countries to filter contacts by location. Must be ISO 3166-1 alpha-2 codes (e.g., "US", "GB", "DE") — full country names are not accepted.
Department (function) filter using LinkedIn Sales Navigator taxonomy. Multiple values are OR'd together. Combined with other filters via AND. All values are treated as INCLUDED — exclusion is not currently supported.
Seniority level filter using LinkedIn Sales Navigator taxonomy. Multiple values are OR'd together. Combined with other filters via AND. All values are treated as INCLUDED — exclusion is not currently supported.
Maximum number of contacts to return per page
251 <= value <= 100Zero-based offset for pagination
00 <= valueLinkedIn company URLs to scope the search (note: plural — pass an array even for a single company). Supports multiple companies; results are merged and deduplicated. Omit to search across all companies.
First name of the contact to search for
length <= 100Last name of the contact to search for
length <= 100Job titles to search for (plural — pass an array)
Keywords to search for in contact profiles (e.g., skills, technologies)
length <= 500Countries to filter contacts by location. Must be ISO 3166-1 alpha-2 codes (e.g., "US", "GB", "DE") — full country names are not accepted.
Department (function) filter using LinkedIn Sales Navigator taxonomy. Multiple values are OR'd together. Combined with other filters via AND. All values are treated as INCLUDED — exclusion is not currently supported.
Seniority level filter using LinkedIn Sales Navigator taxonomy. Multiple values are OR'd together. Combined with other filters via AND. All values are treated as INCLUDED — exclusion is not currently supported.
Maximum number of contacts to return per page
251 <= value <= 100Zero-based offset for pagination
00 <= valueResponse Body
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/v1/contacts/search" \ -H "Content-Type: application/json" \ -d '{ "companyLinkedInUrls": [ "https://linkedin.com/company/google" ], "jobTitles": [ "Engineering Manager", "VP Engineering" ], "countries": [ "US" ] }'{ "items": [ { "firstName": "John", "lastName": "Doe", "fullName": "John Doe", "role": "Engineering Manager", "linkedInSalesNavigatorProfileUrl": "https://www.linkedin.com/sales/lead/ACwAAABOW1gBQZCU123", "avatar": "https://media.licdn.com/...", "location": "San Francisco, California" }, { "firstName": "Jane", "lastName": "Smith", "fullName": "Jane Smith", "role": "VP of Engineering", "linkedInSalesNavigatorProfileUrl": "https://www.linkedin.com/sales/lead/ACwAAABOW1gBQZCU456", "location": "New York, New York" } ], "total": 150, "limit": 25, "offset": 0, "hasMore": true, "salesNavConnected": true}{ "error": { "type": "BAD_REQUEST", "code": "BAD_REQUEST", "message": "Invalid request body", "requestId": "e69ed773-2674-4dca-be61-886d6698f360" }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "requestId": "e69ed773-2674-4dca-be61-886d6698f360" }}{ "statusCode": 429, "error": "Too Many Requests", "message": "Rate limit exceeded", "retryAfter": 45}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}Get remaining credit balance
Returns the remaining credits balance for your organization.
Use this endpoint to check how many credits you have available before running large batches or to monitor usage programmatically.
What Are Credits?
Credits are the single currency for every metered Saber API operation. Current costs:
- Company & contact signals (
POST /v1/companies/signals[/sync|/batch],POST /v1/contacts/signals[/sync]) — 2 credits per signal (batch: per signal created, i.e. each question × company pair); repeat calls served from cache are free - Prebuilt signals (
POST /v1/signals/[sync/]{funding|mna|tech|open-jobs|firmographics}) — 2 credits per result delivered to your organization - Signal subscription runs — the schedule/trigger is free; every signal a run freshly generates charges 2 credits (cached results free)
- Contact research (
POST /v1/contacts/research) — 2 credits per request - Email finder (
POST /v1/contacts/find-email) — 0.1 credits per successfully processed request; a found email and a verified not-found both charge (the verification work ran either way), errors are free - Market signals — subscriptions are free to configure; each signal created (stored) by a polling run charges 8 credits, independent of webhook delivery
- Company list creation with a
technologiesfilter — 1 credit per matched company, charged on the creation-time estimate; preview the same estimate for free viaPOST /v1/companies/lists/count-preview - Everything else — reads, listing, templates, summaries, subscription configuration and lifecycle — is free
Failed signal runs, failed research jobs, and rejected email-finder requests are not charged. Market-signal charges apply once a signal is stored, independent of webhook delivery. Credits reset at the start of each billing period.
When to Use This Endpoint
- Before large batches: Check that you have enough credits before submitting a bulk request
- Monitoring dashboards: Poll periodically to display current usage
- Conditional logic: Skip signal generation if credits are exhausted
Example
curl https://api.saber.app/v1/credits \ -H "Authorization: Bearer YOUR_API_KEY"Authorization
ApiKeyAuth API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.
In: header
Response Body
application/json
application/json
application/json
application/json
curl -X GET "https://example.com/v1/credits"{ "remainingCredits": 57.9}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}{ "error": { "type": "VALIDATION", "code": "VALIDATION_ERROR", "message": "validation failed for 'departments': invalid value: Engineering Ops", "errorCode": "string", "errorAction": "string", "details": {}, "requestId": "e69ed773-2674-4dca-be61-886d6698f360", "fields": [ { "field": "domain", "message": "'domain' must be a valid hostname (e.g., 'example.com') without protocol (https://) or path" } ], "debug": { "cause": "string" } }}