Enrichments
Entity-first alias of POST /v1/companies/signals (Phase 2): the same
research engine, cache, and price, returning the
enrichment_run envelope instead of the bare signal.
Completion semantics
- If the run is already complete when the request returns (served
from the shared answer cache), the response is
200with the result inline. - A fresh run returns
202 AcceptedwithLocation: /v1/enrichment-runs/{runId}— poll that resource (or supply awebhookUrl). This surface never long-polls; callers who want blocking behaviour keepPOST /v1/companies/signals/syncuntil its sunset.
Entity-first means the identifier is fixed by the route: domain is
required and contactProfileUrl is rejected here.
Webhook payload: webhookUrl uses the same delivery path as
/v1/companies/signals, so the callback body is the legacy signal
shape (top-level answer, no run fields) — not the
enrichment_run envelope. A run-shaped webhook payload arrives with
the sunset plan (SEL-3685); until then, poll
/v1/enrichment-runs/{runId} for the run shape.
Credits
Same pricing as POST /v1/companies/signals: 2 credits per run,
repeat calls served from the cache do not consume additional credits,
and failed runs are never charged. The run's credits block (on run
reads) states what your organization was actually 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 <= 253The research question to ask about the company
1 <= length <= 2000The expected format of the answer
"open_text"Value in
- "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
Value in
- "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"Value in
- "strict"
- "lenient"
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/v1/companies/enrich/custom" \ -H "Content-Type: application/json" \ -d '{ "domain": "acme-corp.com", "question": "Does this company use Kubernetes in production?", "answerType": "boolean" }'{ "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "object": "enrichment_run", "entityType": "company", "type": "string", "status": "processing", "entity": { "domain": "string", "companyId": "string", "contactProfileUrl": "string" }, "question": "string", "signalTemplateId": "string", "signalTemplateVersionId": "string", "answerType": "string", "result": { "type": "open_text", "openText": { "value": "string" } }, "resultSchemaVersion": "string", "reasoning": "string", "confidence": 0, "sources": [ null ], "qualificationCriteria": {}, "weight": "string", "changeContext": {}, "credits": { "state": "reserved", "amount": 0, "priceVersion": "string" }, "error": "string", "errorCode": "string", "retryable": true, "createdAt": "2019-08-24T14:15:22Z", "completedAt": "2019-08-24T14:15:22Z"}One shared question applied to a targets array of domains — one
enrichment_run per target, no question × company expansion
(unlike the legacy /v1/companies/signals/batch). Capped at 100
targets; larger workloads stay on the legacy async batch surface.
Either question or signalTemplateId must be provided.
Webhook payload: webhookUrl uses the same delivery path as
/v1/companies/signals, so each callback body is the legacy signal
shape (top-level answer, no run fields) — not the
enrichment_run envelope. A run-shaped webhook payload arrives with
the sunset plan (SEL-3685).
Credits
2 credits per run (per target), success-only, cached results free — identical to single custom enrichment.
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.
Either question or signalTemplateId must be provided; the shared config applies to every target.
Company domains; one run per target.
1 <= items <= 1001 <= length <= 500"open_text"Value in
- "open_text"
- "number"
- "boolean"
- "list"
- "percentage"
- "currency"
- "url"
- "contacts"
- "contact_posts"
- "contact_engagements"
- "json_schema"
urilength <= 2048Value in
- "important"
- "nice_to_have"
- "not_important"
uuidConnector configuration applied to every run in the batch.
Value in
- "strict"
- "lenient"
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/v1/companies/enrich/custom/batch" \ -H "Content-Type: application/json" \ -d '{ "targets": [ "string" ] }'{ "object": "enrichment_run_batch", "accepted": 0, "rejected": 0, "runs": [ { "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "object": "enrichment_run", "entityType": "company", "type": "string", "status": "processing", "entity": { "domain": "string", "companyId": "string", "contactProfileUrl": "string" }, "question": "string", "signalTemplateId": "string", "signalTemplateVersionId": "string", "answerType": "string", "result": { "type": "open_text", "openText": { "value": "string" } }, "resultSchemaVersion": "string", "reasoning": "string", "confidence": 0, "sources": [ null ], "qualificationCriteria": {}, "weight": "string", "changeContext": {}, "credits": { "state": "reserved", "amount": 0, "priceVersion": "string" }, "error": "string", "errorCode": "string", "retryable": true, "createdAt": "2019-08-24T14:15:22Z", "completedAt": "2019-08-24T14:15:22Z" } ]}Entity-first alias of POST /v1/contacts/signals: same engine, cache,
and price, enrichment_run envelope on the wire. The identifier
is fixed by the route: contactProfileUrl is required and domain
is rejected here. Completion semantics match the company surface
(200 inline on cache serve, 202 + Location for fresh runs).
Webhook payload: webhookUrl uses the same delivery path as
/v1/contacts/signals, so the callback body is the legacy signal
shape (top-level answer, no run fields) — not the
enrichment_run envelope. A run-shaped webhook payload arrives with
the sunset plan (SEL-3685); until then, poll
/v1/enrichment-runs/{runId} for the run shape.
Credits
2 credits per run; cached repeats free; failed runs 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 contact profile URL to research (e.g., "https://linkedin.com/in/johndoe")
uri1 <= length <= 500The research question to ask about the contact
1 <= length <= 2000The expected format of the answer
"open_text"Value in
- "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
Value in
- "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"Value in
- "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
application/json
curl -X POST "https://example.com/v1/contacts/enrich/custom" \ -H "Content-Type: application/json" \ -d '{ "contactProfileUrl": "https://www.linkedin.com/in/someone", "question": "Has this person changed jobs in the last 6 months?", "answerType": "boolean" }'{ "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "object": "enrichment_run", "entityType": "company", "type": "string", "status": "processing", "entity": { "domain": "string", "companyId": "string", "contactProfileUrl": "string" }, "question": "string", "signalTemplateId": "string", "signalTemplateVersionId": "string", "answerType": "string", "result": { "type": "open_text", "openText": { "value": "string" } }, "resultSchemaVersion": "string", "reasoning": "string", "confidence": 0, "sources": [ null ], "qualificationCriteria": {}, "weight": "string", "changeContext": {}, "credits": { "state": "reserved", "amount": 0, "priceVersion": "string" }, "error": "string", "errorCode": "string", "retryable": true, "createdAt": "2019-08-24T14:15:22Z", "completedAt": "2019-08-24T14:15:22Z"}Prebuilt enrichment: company profile, refined category, and customer
segments — the same research contract as POST /v1/signals/firmographics,
on the entity-first surface with the enrichment_run envelope and its
completion semantics (200 inline on a cache serve, 202 +
Location: /v1/enrichment-runs/{runId} for a fresh run). The completed
result conforms to FirmographicsSignalAnswer.
Webhook payload: webhookUrl delivers the legacy signal shape
(top-level answer, no run fields), and its namedSignal field
carries the internal catalogue key (firmographics here; tech for
tech-stack), not this surface's type vocabulary. The webhook
moves to the run shape with the sunset plan (SEL-3685); until then
poll /v1/enrichment-runs/{runId} for the public shape.
Credits
0.6 credits, charged once per result delivered to your organization. Repeat calls served from the cache are free — including results your organization already paid for via the legacy signals surface — 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.
Request body for a prebuilt signal. You supply the company
domain (plus optional delivery and refresh controls); the signal
returns its own documented, structured answer.
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
application/json
curl -X POST "https://example.com/v1/companies/enrich/firmographics" \ -H "Content-Type: application/json" \ -d '{ "domain": "acme-corp.com" }'{ "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "object": "enrichment_run", "entityType": "company", "type": "string", "status": "processing", "entity": { "domain": "string", "companyId": "string", "contactProfileUrl": "string" }, "question": "string", "signalTemplateId": "string", "signalTemplateVersionId": "string", "answerType": "string", "result": { "type": "open_text", "openText": { "value": "string" } }, "resultSchemaVersion": "string", "reasoning": "string", "confidence": 0, "sources": [ null ], "qualificationCriteria": {}, "weight": "string", "changeContext": {}, "credits": { "state": "reserved", "amount": 0, "priceVersion": "string" }, "error": "string", "errorCode": "string", "retryable": true, "createdAt": "2019-08-24T14:15:22Z", "completedAt": "2019-08-24T14:15:22Z"}Prebuilt enrichment: a company's most recent funding and public/IPO
status — the same research contract as POST /v1/signals/funding, on
the entity-first surface with the enrichment_run envelope and its
completion semantics (200 inline on a cache serve, 202 +
Location: /v1/enrichment-runs/{runId} for a fresh run). The completed
result conforms to FundingSignalAnswer.
Webhook payload: webhookUrl delivers the legacy signal shape
(top-level answer, no run fields), and its namedSignal field
carries the internal catalogue key (funding here; tech for
tech-stack), not this surface's type vocabulary. The webhook
moves to the run shape with the sunset plan (SEL-3685); until then
poll /v1/enrichment-runs/{runId} for the public shape.
Credits
0.3 credits, charged once per result delivered to your organization. Repeat calls served from the cache are free — including results your organization already paid for via the legacy signals surface — 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.
Request body for a prebuilt signal. You supply the company
domain (plus optional delivery and refresh controls); the signal
returns its own documented, structured answer.
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
application/json
curl -X POST "https://example.com/v1/companies/enrich/funding" \ -H "Content-Type: application/json" \ -d '{ "domain": "stripe.com" }'{ "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "object": "enrichment_run", "entityType": "company", "type": "string", "status": "processing", "entity": { "domain": "string", "companyId": "string", "contactProfileUrl": "string" }, "question": "string", "signalTemplateId": "string", "signalTemplateVersionId": "string", "answerType": "string", "result": { "type": "open_text", "openText": { "value": "string" } }, "resultSchemaVersion": "string", "reasoning": "string", "confidence": 0, "sources": [ null ], "qualificationCriteria": {}, "weight": "string", "changeContext": {}, "credits": { "state": "reserved", "amount": 0, "priceVersion": "string" }, "error": "string", "errorCode": "string", "retryable": true, "createdAt": "2019-08-24T14:15:22Z", "completedAt": "2019-08-24T14:15:22Z"}Prebuilt enrichment: a company's recent M&A activity, as acquirer or
acquiree — the same research contract as POST /v1/signals/mna, on
the entity-first surface with the enrichment_run envelope and its
completion semantics (200 inline on a cache serve, 202 +
Location: /v1/enrichment-runs/{runId} for a fresh run). The completed
result conforms to MAndASignalAnswer.
Webhook payload: webhookUrl delivers the legacy signal shape
(top-level answer, no run fields), and its namedSignal field
carries the internal catalogue key (mna here; tech for
tech-stack), not this surface's type vocabulary. The webhook
moves to the run shape with the sunset plan (SEL-3685); until then
poll /v1/enrichment-runs/{runId} for the public shape.
Credits
0.75 credits, charged once per result delivered to your organization. Repeat calls served from the cache are free — including results your organization already paid for via the legacy signals surface — 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.
Request body for a prebuilt signal. You supply the company
domain (plus optional delivery and refresh controls); the signal
returns its own documented, structured answer.
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
application/json
curl -X POST "https://example.com/v1/companies/enrich/mna" \ -H "Content-Type: application/json" \ -d '{ "domain": "acme-corp.com" }'{ "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "object": "enrichment_run", "entityType": "company", "type": "string", "status": "processing", "entity": { "domain": "string", "companyId": "string", "contactProfileUrl": "string" }, "question": "string", "signalTemplateId": "string", "signalTemplateVersionId": "string", "answerType": "string", "result": { "type": "open_text", "openText": { "value": "string" } }, "resultSchemaVersion": "string", "reasoning": "string", "confidence": 0, "sources": [ null ], "qualificationCriteria": {}, "weight": "string", "changeContext": {}, "credits": { "state": "reserved", "amount": 0, "priceVersion": "string" }, "error": "string", "errorCode": "string", "retryable": true, "createdAt": "2019-08-24T14:15:22Z", "completedAt": "2019-08-24T14:15:22Z"}Prebuilt enrichment: a company's current hiring — total open roles and
example titles — the same research contract as
POST /v1/signals/open-jobs, on the entity-first surface with the
enrichment_run envelope and its completion semantics (200 inline
on a cache serve, 202 + Location: /v1/enrichment-runs/{runId} for
a fresh run). The completed result conforms to
OpenJobsSignalAnswer.
Webhook payload: webhookUrl delivers the legacy signal shape
(top-level answer, no run fields), and its namedSignal field
carries the internal catalogue key (open-jobs here; tech for
tech-stack), not this surface's type vocabulary. The webhook
moves to the run shape with the sunset plan (SEL-3685); until then
poll /v1/enrichment-runs/{runId} for the public shape.
Credits
0.5 credits, charged once per result delivered to your organization. Repeat calls served from the cache are free — including results your organization already paid for via the legacy signals surface — 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.
Request body for a prebuilt signal. You supply the company
domain (plus optional delivery and refresh controls); the signal
returns its own documented, structured answer.
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
application/json
curl -X POST "https://example.com/v1/companies/enrich/open-jobs" \ -H "Content-Type: application/json" \ -d '{ "domain": "acme-corp.com" }'{ "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "object": "enrichment_run", "entityType": "company", "type": "string", "status": "processing", "entity": { "domain": "string", "companyId": "string", "contactProfileUrl": "string" }, "question": "string", "signalTemplateId": "string", "signalTemplateVersionId": "string", "answerType": "string", "result": { "type": "open_text", "openText": { "value": "string" } }, "resultSchemaVersion": "string", "reasoning": "string", "confidence": 0, "sources": [ null ], "qualificationCriteria": {}, "weight": "string", "changeContext": {}, "credits": { "state": "reserved", "amount": 0, "priceVersion": "string" }, "error": "string", "errorCode": "string", "retryable": true, "createdAt": "2019-08-24T14:15:22Z", "completedAt": "2019-08-24T14:15:22Z"}Prebuilt enrichment: which system(s) a company currently uses — the
same research contract as POST /v1/signals/tech, on the entity-first
surface with the enrichment_run envelope and its completion
semantics (200 inline on a cache serve, 202 +
Location: /v1/enrichment-runs/{runId} for a fresh run). Provide
exactly one of category (survey a category: erp or crm) or
technology (verify one specific technology). The completed result
conforms to TechSignalAnswer.
Webhook payload: webhookUrl delivers the legacy signal shape
(top-level answer, no run fields), and its namedSignal field
carries the internal catalogue key — tech, not this surface's
tech-stack — so it is NOT a value the type vocabulary admits. The
webhook moves to the run shape with the sunset plan (SEL-3685); until
then poll /v1/enrichment-runs/{runId} for the public shape.
Credits
0.75 credits, charged once per result delivered to your organization. Repeat calls served from the cache are free — including results your organization already paid for via the legacy signals surface — 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.
Request body for the Tech signal. Supply a domain plus exactly one
of category or technology — providing neither or both is a 422.
Request body for the Tech signal. Supply a domain plus exactly one
of category or technology — providing neither or both is a 422.
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.
Value in
- "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
application/json
curl -X POST "https://example.com/v1/companies/enrich/tech-stack" \ -H "Content-Type: application/json" \ -d '{ "domain": "acme-corp.com", "category": "crm" }'{ "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "object": "enrichment_run", "entityType": "company", "type": "string", "status": "processing", "entity": { "domain": "string", "companyId": "string", "contactProfileUrl": "string" }, "question": "string", "signalTemplateId": "string", "signalTemplateVersionId": "string", "answerType": "string", "result": { "type": "open_text", "openText": { "value": "string" } }, "resultSchemaVersion": "string", "reasoning": "string", "confidence": 0, "sources": [ null ], "qualificationCriteria": {}, "weight": "string", "changeContext": {}, "credits": { "state": "reserved", "amount": 0, "priceVersion": "string" }, "error": "string", "errorCode": "string", "retryable": true, "createdAt": "2019-08-24T14:15:22Z", "completedAt": "2019-08-24T14:15:22Z"}The email finder on the enrichment family (decision 16): the SAME
lookup as POST /v1/contacts/find-email — identical request and
response contract, same verification semantics, same 0.1-credit
price. This rename is a name change, not a reprice. The legacy path
keeps its 0.1-credit price until its announced sunset; use this route
going forward.
See POST /v1/contacts/find-email for the full response semantics
(status discriminator, catch-all handling, name parsing).
Credits
Each call charges 0.1 credits on success — both when a
deliverable email is found and when no email is found (the
verification attempt itself consumed work). Requests rejected
before any verification work begins are not charged; insufficient
balance returns 402 before any work is performed.
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.
Full name of the contact. Accepts 2-4 token names and
European name particles (Joey van Ommen,
Joey van der Ommen). Trailing credentials and
honorifics (Ahmed Othman, MBA, CDMP, Dr. …),
parenthetical roles, and mixed-script tails are cleaned
off before parsing, so those resolve rather than being
rejected. Non-Latin names (Arabic, Chinese, etc.) are
transliterated and attempted best-effort as
low-confidence parses. A value that is actually a
company name (Best Vision Business Center) settles as
not_found (not an error). A genuinely unparseable
name — a single lone token, or empty — is rejected with
422.
1 <= length <= 200The mail domain for the contact's company. Accepts
bare domains (saber.app), domains with www.
prefix, and trailing-dot forms. URL-shaped inputs
(https://saber.app) and email-shaped inputs
(joey@saber.app) are rejected with 422.
If the domain redirects (a rebrand) or is dead (no
mail), the finder resolves the company's real domain
and searches there too — supplying company_name
and/or location makes that discovery far more
accurate.
1 <= length <= 253Optional. The contact's company name. Used only when
the supplied domain is dead or redirects: it anchors
the web search that finds the company's real domain,
and sharply reduces wrong-company matches. Strongly
recommended whenever the domain may be stale.
length <= 200Optional. The contact's location (city / region / country). Enables location-aware candidate generation for global companies — e.g. a London contact at a firm with country domains resolves to the regional domain or subdomain.
length <= 200Response Body
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/v1/contacts/enrich/work-email" \ -H "Content-Type: application/json" \ -d '{ "full_name": "Joey Ommen", "domain": "saber.app" }'{ "status": "found", "email": "string", "verification": { "state": "deliverable", "score": 0, "accept_all": true }}Unified list across company and contact runs. Filters are the common
fields only: entityType, status, fromDate/toDate (against the
run's creation time), exact entityId (the resolved company id —
contact runs carry no entity id at rest, so an entityId filter
never matches them), and type (custom or a prebuilt enrichment
type). No per-entity attribute filters by design; look a company up
by id, not by domain.
Reads are free. Each run carries a credits block stating what your
organization was charged for it — none means it was served free
(for example a cache hit).
Authorization
ApiKeyAuth API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.
In: header
Query Parameters
Value in
- "company"
- "contact"
Exact company id; never matches contact runs.
Run type — custom or a prebuilt enrichment type.
Value in
- "custom"
- "firmographics"
- "funding"
- "mna"
- "open-jobs"
- "tech-stack"
Repeatable. Unknown values are rejected with 422.
Include runs created at or after this instant.
date-timeInclude runs created at or before this instant.
date-time1 <= value <= 100200 <= value0Response Body
application/json
application/json
application/json
application/json
application/json
curl -X GET "https://example.com/v1/enrichment-runs"{ "results": [ { "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "object": "enrichment_run", "entityType": "company", "type": "string", "status": "processing", "entity": { "domain": "string", "companyId": "string", "contactProfileUrl": "string" }, "question": "string", "signalTemplateId": "string", "signalTemplateVersionId": "string", "answerType": "string", "result": { "type": "open_text", "openText": { "value": "string" } }, "resultSchemaVersion": "string", "reasoning": "string", "confidence": 0, "sources": [ null ], "qualificationCriteria": {}, "weight": "string", "changeContext": {}, "credits": { "state": "reserved", "amount": 0, "priceVersion": "string" }, "error": "string", "errorCode": "string", "retryable": true, "createdAt": "2019-08-24T14:15:22Z", "completedAt": "2019-08-24T14:15:22Z" } ], "total": 0, "limit": 0, "offset": 0, "count": 0}The run resource is the source of truth for async enrichment: poll it
after a 202 (its path arrives in the Location header), or after a
missed webhook. Free; includes the credits block.
Authorization
ApiKeyAuth API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.
In: header
Path Parameters
uuidResponse Body
application/json
application/json
application/json
application/json
application/json
application/json
curl -X GET "https://example.com/v1/enrichment-runs/497f6eca-6276-4993-bfeb-53cbbbba6f08"{ "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "object": "enrichment_run", "entityType": "company", "type": "string", "status": "processing", "entity": { "domain": "string", "companyId": "string", "contactProfileUrl": "string" }, "question": "string", "signalTemplateId": "string", "signalTemplateVersionId": "string", "answerType": "string", "result": { "type": "open_text", "openText": { "value": "string" } }, "resultSchemaVersion": "string", "reasoning": "string", "confidence": 0, "sources": [ null ], "qualificationCriteria": {}, "weight": "string", "changeContext": {}, "credits": { "state": "reserved", "amount": 0, "priceVersion": "string" }, "error": "string", "errorCode": "string", "retryable": true, "createdAt": "2019-08-24T14:15:22Z", "completedAt": "2019-08-24T14:15:22Z"}