---
title: "Person B2B social"
description: "POST /v1/person/b2b-social — email in, the person's LinkedIn profile URL out."
canonical: "https://kingminos.com/docs/api/person-b2b-social/"
sourceKind: "source-mdx"
---

import TryItLink from '../../../../components/docs/TryItLink.astro';

`POST https://api.kingminos.com/v1/person/b2b-social`

<TryItLink method="POST" path="/v1/person/b2b-social" />

Send a person's `email` (top level or under `person`). It is required: it is the one key KingMinos looks the person up by. You get back the person's LinkedIn profile URL, for CRM profile-URL stamps and social sequencing.

Three inputs are **match-only**. They only reject a wrong answer and never discover or score anything:
- `linkedin_url` rejects a profile with a different slug (`person_mismatch`). A LinkedIn company page is `400 invalid_linkedin_url`.
- `first_name` / `last_name` reject a profile that belongs to someone else (`person_mismatch`).

`person.b2b_social` answers for API tenant keys (`osr_…`). It does not stamp Salesforce Contacts or Leads.

```bash
curl 'https://api.kingminos.com/v1/person/b2b-social' \
  -H 'Authorization: Bearer <your-key>' \
  -H 'Content-Type: application/json' \
  -d '{
    "email": "anna@example.com",
    "first_name": "Anna",
    "last_name": "Example",
    "routing": { "path": "accuracy" }
  }'
```

## Paths and price

You pay for the outcome, not the call. A hit bills the path's price **once**. A miss, a person mismatch, an answer below your confidence floor and a timeout cost **0**.

| `routing.path` | What it does | Credits on a hit |
| --- | --- | --- |
| `speed` | One email-keyed profile lookup, with a fallback source only when the first answers nothing. Never `high` confidence. | 2 |
| `balance` (default) | Email-keyed sources in turn. Stops at the first profile. | 3 |
| `accuracy` | Always two independent email-keyed sources, with a 10 s cap. Agreement gives `high` confidence. | 5 |

There is no `coverage` path: a profile URL is one answer. `coverage` returns `400 invalid_routing`.

**Aliases:** `value`, `fast` and `name_only` mean `speed`; `auto` means `balance`.

**Vendor isolation:** `routing.only` and `routing.ignore` limit which vendors a path may use. An unknown provider returns `400 unknown_provider`. A `routing.max_provider_credits` below the path price returns `max_credits_reached` before anything runs (0 credits).

## What comes back

| Layer | Fields | Use |
| --- | --- | --- |
| Control | `es_decision`, `answer.outcome`, `answer.confidence` | Whether to stamp. |
| Answer | `result.linkedin_url`, `result.linkedin_slug` | The values. |
| Evidence | `result.candidates`, `result.confidence`, `result.flags`, `result.source` | Humans and logs. |
| Billing | `usage.credits`, `usage.hops` | What ran and what was billed. |

`result.linkedin_url` is always the canonical `https://www.linkedin.com/in/<slug>`; regional hosts such as `de.linkedin.com` are normalized. `result.candidates` lists every profile URL the sources returned, winner first, each with `agrees`. `result.person` is the matched profile on a hit and `null` otherwise: a miss is never a free lookup.

**Outcomes:**

| Result | `answer.outcome` / reason | `es_decision` | Credits |
| --- | --- | --- | --- |
| A profile URL at or above your floor | `found` | `hit` | path price |
| Below your confidence floor | `not_found` / `below_min_confidence` | `miss` | 0 |
| Nothing found | `not_found` / `zero_hits` | `miss` | 0 |
| Only someone else's profile | `not_found` / `person_mismatch` | `miss` | 0 |

**Stamp rule:** confidence is the only write signal. Write the URL on a billed `found` answer when `answer.confidence` meets your floor and neither `conflicting_profiles` nor `unconfirmed_identity` is flagged.

**Confidence:** two independent sources agreeing on the same profile give `high`. One source gives `medium`. Sources that disagree give the best guess at `low`, flagged `conflicting_profiles`.

**Confidence floors:** `speed` defaults to `low`, `balance` to `medium`, `accuracy` to `high`. Send `min_confidence` (`high`, `medium` or `low`) to override. Below the floor `linkedin_url` comes back blank, the confidence and `candidates` stay, and the call costs 0. In practice `accuracy` only delivers when two sources agree.

### Flags

| Flag | Meaning |
| --- | --- |
| `conflicting_profiles` | Sources returned different profiles. Do not stamp. |
| `person_mismatch` | A source returned someone else's profile, which was rejected. |
| `unconfirmed_identity` | You sent a name but the profile carries none. Never `high`. Do not stamp. |
| `single_source` | One source answered. |

## Cache

Answers are cached for 30 days. The cache key includes the path, `linkedin_url`, `first_name` / `last_name`, `min_confidence` and `routing.only` / `ignore`. A repeat call replays with `usage.cached: true` at 0 credits.

To force a fresh run, send one of:
- `skip_cache: true`;
- `X-Router-Cache: bypass`;
- `Cache-Control: no-cache`.

`DELETE /v1/subjects/email:<address>` or `li:<slug>` erases cached answers.

## Errors

`400 validation_failed` with one of these reasons:
- `email_required`
- `invalid_linkedin_url`
- `min_confidence`

Also `400 invalid_routing` and `400 unknown_provider`. A person who asked not to be looked up returns `451 subject_suppressed` at 0 credits; do not retry. Business misses stay HTTP `200`.
