POST /v1/decisions/pick_person
| Call | POST /v1/decisions/pick_person |
| Price | $0.005 per call, billed only when an answer is returned |
| Scope | decisions:write |
| Operation id | pickPerson |
What it does
Section titled “What it does”Who in this roster should I write to? Returns the roster ranked, each person with p.
Call it when you have several people at a firm and must choose whom to write to. Give a roster of up to 50 people (name, title, seniority, department; no LinkedIn data), the ICP and an optional question. Returns the whole roster ranked in people, each with p; p and answer (pick or no_pick) refer to the top person. One price per call for up to 50 people.
Price: $0.005 per call (x-verdict-price-usd), billed only when an answer is returned: errors (including decision_unavailable, 503 with Retry-After) and refused calls are free. Send X-Max-Cost-USD to cap spend and Idempotency-Key (required) to retry safely; a repeated key within 24 hours returns the stored response and bills nothing. Every response carries the common envelope: id, p (always present, calibrated), answer, reason_code, reason, evidence, calibration, cost and balance_usd. Report what happened next with POST /v1/outcomes.
Scope: decisions:write.
Example request
Section titled “Example request”Copy it as curl. Set VERDICT_API_KEY first; uuidgen makes a fresh Idempotency-Key.
curl -X POST 'https://api.askverdict.io/v1/decisions/pick_person' \ -H "Authorization: Bearer $VERDICT_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H 'Content-Type: application/json' \ -d '{ "roster": [ { "ref": "c-101", "name": "Dana Whitfield", "title": "Chief Operating Officer", "seniority": "c_level", "department": "Operations" }, { "ref": "c-102", "name": "Sam Ortega", "title": "Operations Associate", "seniority": "entry", "department": "Operations" }, { "ref": "c-103", "name": "Priya Raman", "title": "Chief Compliance Officer", "seniority": "c_level", "department": "Compliance" } ], "firm": { "domain": "northfieldcapital.com" }, "icp_id": "icp_01JC3Z4Y8R9K2M5N7P1Q3S5T7V"}'Example response
Section titled “Example response”200: The pick_person decision, in the common envelope.
{ "id": "dec_01JC3Z4Y8R9K2M5N7P1Q3S5T7V", "version": "2026-11-01", "question_set_version": "2026-11-01", "model": "jev", "calibration": { "basis": "org", "n_outcomes": 412, "threshold": 0.6 }, "latency_ms": 180, "created_at": "2026-11-07T14:03:00Z", "decision": "pick_person", "p": 0.74, "answer": "pick", "reason_code": "buyer_role_match", "reason": "Chief Operating Officer owns operations tooling at a 12-person adviser.", "evidence": [ { "source": "request", "url": null, "observed_at": "2026-11-07", "pointer": "/roster/0" } ], "people": [ { "index": 0, "ref": "c-101", "rank": 1, "p": 0.74 }, { "index": 2, "ref": "c-103", "rank": 2, "p": 0.41 }, { "index": 1, "ref": "c-102", "rank": 3, "p": 0.09 } ], "cost": { "decision_usd": 0.005, "vendor_usd": 0, "total_usd": 0.005 }, "balance_usd": 18.31}Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
idempotency-key |
header | string (uuid) | yes | A UUID you generate per logical request. Required on every POST. Repeating it within 24 hours returns the stored response and bills nothing; reusing it with a different body returns 409 idempotency_conflict. |
x-max-cost-usd |
header | string | no | Maximum you are willing to pay for this call, in US dollars (up to 6 decimals). If the call would cost more, it is refused with 402 max_cost_exceeded before spending. |
x-verdict-version |
header | string | no | API version to use, a date. Defaults to the version current when the key was created. The current version is 2026-11-01. |
Request body
Section titled “Request body”Schema PickPersonRequest. The pick_person input.
| Field | Type | Required | Description |
|---|---|---|---|
roster |
array of RosterEntry | yes | The people to rank, 1 to 50. |
roster[].ref |
string | no | Your own id for this person, echoed back in people. |
roster[].name |
string | yes | Full name. |
roster[].title |
string | yes | Job title. |
roster[].seniority |
enum: “owner”, “c_level”, “vp”, “director”, “manager”, “senior”, “entry”, “unknown” | no | Seniority, if known. |
roster[].department |
string | no | Department or function, for example Operations. |
roster[].location |
string | no | City or country. |
roster[].tenure_months |
integer | no | Months in the current role. |
firm |
FirmReference | no | A firm reference: exactly one of firm_id, domain, name (with an optional hint), lei, cik, crd or companies_house. |
firm.firm_id |
string | no | A firm id from Verdict’s index. |
firm.domain |
string | no | The firm’s web domain. |
firm.name |
string | no | The firm’s legal or trading name. |
firm.hint |
object | no | Optional country, city or domain to disambiguate the name. |
firm.hint.country |
string | no | ISO 3166-1 alpha-2 country of the firm’s headquarters. |
firm.hint.city |
string | no | City of the firm’s headquarters. |
firm.hint.domain |
string | no | A domain the firm is known to use. |
firm.lei |
string | no | The firm’s Legal Entity Identifier. |
firm.cik |
string | no | The firm’s SEC Central Index Key. |
firm.crd |
string | no | The firm’s CRD number. |
firm.companies_house |
string | no | The firm’s UK Companies House number. |
icp_id |
string | yes | The ICP profile to decide against. |
question |
string | no | Optional extra question, for example who owns trading operations?. |
Response fields (200)
Section titled “Response fields (200)”Schema PickPersonResponse.
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | yes | The decision id. Report outcomes against it. |
decision |
enum: “pick_person” | yes | The decision name. |
version |
enum: “2026-11-01” | yes | API version that served the decision. |
question_set_version |
string (date) | yes | Version (a date) of the question set that answered (spec 6.1). |
model |
enum: “jev” | yes | Decision model that answered: always jev (ADR-0008). |
p |
number | yes | Calibrated probability (spec 6.4). Always present. |
answer |
enum: “pick”, “no_pick” | yes | pick or no_pick: the top person’s p applied to your threshold. |
reason_code |
enum: “buyer_role_match”, “seniority_match”, “influencer_role_match”, “question_match”, “too_senior_for_offer”, “too_junior_for_offer”, “titles_ambiguous”, “no_strong_match” | yes | Why, from the fixed pick_person reason-code enum. |
reason |
string | yes | Short templated explanation of reason_code; never free text from a frontier model. |
evidence |
array of Evidence | yes | Cited sources, with URLs and dates. |
evidence[].source |
enum: “sec_edgar”, “gleif”, “companies_house”, “wikidata”, “request” | yes | The index source cited, or request when the evidence is part of your own input. |
evidence[].url |
string or null (uri) | yes | Link to the cited record at the source; null when source is request. |
evidence[].observed_at |
string (date) | yes | Date the source reported the fact. |
evidence[].label |
string | no | Short description of what the evidence shows. |
evidence[].pointer |
string | no | JSON Pointer into your request body when source is request, for example /thread/2. |
calibration |
Calibration | yes | How p was calibrated (spec 6.4). |
calibration.basis |
enum: “org”, “segment”, “global” | yes | org (your own outcomes), segment (your ICP’s segment) or global: how much to trust p. |
calibration.n_outcomes |
integer | yes | Outcomes behind the calibration map used. |
calibration.threshold |
number | yes | The threshold answer applied to p. |
cost |
Cost | yes | What this call was billed, itemized. Misses and errors bill nothing. |
cost.decision_usd |
number | yes | Price of the decision. US dollars, up to 6 decimals. |
cost.vendor_usd |
number | yes | Vendor pass-through charges (always 0 in v1). US dollars, up to 6 decimals. |
cost.total_usd |
number | yes | Total billed for this call. US dollars, up to 6 decimals. |
balance_usd |
number | yes | Balance after this call. US dollars, up to 6 decimals. |
latency_ms |
integer | yes | Server-side latency of the call, in milliseconds. |
created_at |
string (date-time) | yes | When the decision was made. Decisions are immutable. |
people |
array of object | yes | The whole roster ranked best first, each with p. |
people[].index |
integer | yes | Zero-based position of the person in your roster. |
people[].ref |
string or null | yes | Your ref for the person, or null if you gave none. |
people[].rank |
integer | yes | Rank, 1 is best. |
people[].p |
number | yes | Calibrated probability that this is the right person to write to. |
Errors
Section titled “Errors”Errors are RFC 9457 problem details and are never billed. Branch on type. See Errors.
| Status | Meaning |
|---|---|
400 |
Invalid request: malformed JSON, an unknown field, a failed constraint or a size limit (invalid_request). |
401 |
Missing, malformed, revoked or expired API key, or a bad webhook signature (unauthorized). |
402 |
Payment required: the balance cannot cover the call (insufficient_balance), or the call would exceed X-Max-Cost-USD (max_cost_exceeded). Nothing was spent. |
403 |
The key lacks the scope this operation needs (forbidden_scope). |
404 |
The resource does not exist in this organization (not_found). |
409 |
The Idempotency-Key was reused with a different request, or the first request is still running (idempotency_conflict). |
429 |
Rate limited (rate_limited). Wait Retry-After seconds. |
500 |
Unexpected server error (internal). Not billed; retry with the same Idempotency-Key. |
503 |
Temporarily unavailable: the decision model failed, timed out or is rate limited, or decisions are switched off (decision_unavailable), or a vendor the call depends on is unavailable (vendor_unavailable, phase 2). Not billed. Wait Retry-After seconds and retry with the same Idempotency-Key. |
Try it
Section titled “Try it”Open the interactive reference to send this request from the browser. The full document is at /openapi.json.