Decision makers API
POST https://api.pequod.app/v1/decision-makers. One domain is synchronous — give the client a 45 to 60 second timeout. Two or more domains become a job (202). Same finder options as the Store actor. The portal confirm screen sends this body for you.
delivery
One domain returns 200 with results[] inline — no download_url. Two or more hosts return 202 and a job id; poll GET /v1/jobs/{id}. The worker unions each batch into one CSV (delivered rows plus a has_decision_maker=false line for every no-find). The signed download_url may appear while the job is still running; it lasts 900 seconds and GET /v1/export/{ticket} is one-shot — the blob is deleted after the first fetch. Pushing that same URL to Google Sheets consumes the ticket; after a write the CSV is gone. The Apify dataset is an internal batch store, not the customer export. The portal waits until the job finishes, then either downloads the CSV or writes the sheet — not both.
request
Authorization: Bearer pq_live_…
Idempotency-Key: <uuid v4> · required
Idempotency-Key: <uuid v4> · required
Body is domain, domains, or Apify's domainList — one of the three. Omitted need is both. Pass need=email to keep the 2-credit email-only path. Sync max twenty. Two or more hosts enqueue a job. JSON, same keys as the actor (camelCase).
meter
A delivered row is email 2, phone 4, both 8. A no-find is free. Silent discards do not charge. Committee mode still bills one verified-contact event on best_contact_email per domain.
errors
400 · bad body, missing Idempotency-Key, over twenty sync
401 · missing or invalid key
402 · insufficient credits {required, available}
409 · Idempotency-Key already in flight
401 · missing or invalid key
402 · insufficient credits {required, available}
409 · Idempotency-Key already in flight
finder options
These keys are forwarded to the same parser as the Apify actor. Omit a key to keep the actor default. targetPersonas wins over targetPersona, maxContactsPerDomain, and returnAlternates. pushEmptyResults is not accepted — empty rows stay free.
| Field | Default | What it does |
|---|---|---|
| need | both | Pipeline authority: email · phone · both |
| defaultCountry | unset | ISO-2 for every host without its own country |
| targetPersona | founder_ceo | One role: preset or mode=custom + titleKeywords |
| targetPersonas | [] | Buying committee, 1–5 slots, one person each |
| targetPersona.executiveFallback | true | Senior fallback when the exact title is missing |
| salesContext | {} | productCategory / companySize shortcut |
| role | unset | Hint: ceo, cto, founder, marketing, sales, ops… |
| verifyEmails | true | SMTP. Forced off when need=phone |
| verifyPhones | true | Twilio + HLR. Forced off when need=email |
| includeGenericInbox | true | Verified info@ fallback. Off when need=phone |
| aiDiscovery | true | Public-web research when the B2B DB misses |
| identityStrictness | flag | flag · enforce · off |
| mustHaveVerifiedEmail | false | Do not ship a primary without a sendable named email |
| maxCandidates | 5 | 1–10 people evaluated per domain / slot |
| maxContactsPerDomain | 1 | 1–5 same-persona ranked extras |
| returnAlternates | false | Put extras in alternates[]. Ignored in committee |
| companyFilters | {} | excludeCompanyTypes, requireCountryMatch |
response extras
Committee runs add decision_makers[] (one element per requested slot, including misses). Same-persona extras add alternates[]. Every row can include best_contact_email, contact_kind, identity_status, send_decision, and evidence[]. Domains in the array may also be objects: {"domain":"acme.de","country":"DE"}.