> ## Documentation Index
> Fetch the complete documentation index at: https://docs.syrto.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Person contacts

> Read the business email addresses and direct phone numbers held for a person, and buy them where they are not held yet.

Syrto can buy a person's business email addresses and direct phone numbers from external data providers. They are not part of the registry record, so they cost credits.

Two tools cover them:

| Tool                            | Costs credits | What it does                                                                                     |
| ------------------------------- | ------------- | ------------------------------------------------------------------------------------------------ |
| `syrto_get_person_contacts`     | No            | What a provider search found, what buying it would cost, and what the organization already holds |
| `syrto_request_person_contacts` | **Yes**       | Buys the contact details                                                                         |

Person IDs come from [`syrto_find_person`](/mcp/tools/find-person), or from the `person_id` on an officer, shareholder or beneficial owner returned by [`syrto_get_company_structure`](/mcp/tools/company-structure). The structure route is the more precise of the two - `syrto_find_person` is a name search, so it can land on a namesake.

<Warning>
  Purchased contacts belong to the **whole organization**, not to the person who bought them. A colleague may already have paid for them - `syrto_get_person_contacts` is how you find out, and it costs no credits.
</Warning>

***

## `syrto_get_person_contacts`

Reports the contact details held for a person and the cost of buying them. Spends no contact credits and is safe to call repeatedly.

Use it:

* **Before every purchase.** It supplies the cost to confirm with the user, and says whether anything can be found for this person at all.
* **To read contacts already bought.**
* **To collect data that is still arriving.** Providers return emails first and phone numbers afterwards, so contacts with status `IN_PROGRESS` are incomplete for a short while. Calling this again is how the rest arrives - buying again would pay twice for it.

### Arguments

<ParamField query="person_id" type="string" required>
  The person ID, from [`syrto_find_person`](/mcp/tools/find-person) or from a `person_id` in [`syrto_get_company_structure`](/mcp/tools/company-structure).
</ParamField>

<ParamField query="language" type="string">
  `"en"` for English (default) or `"it"` for Italian.
</ParamField>

### Returns

<ResponseField name="person" type="object">
  `id` (the `person_id` you passed) and `name`.
</ResponseField>

<ResponseField name="availability" type="object">
  What **can** be bought, not what is held:

  * `has_email` - an email address can be found
  * `has_direct_phone` - a direct phone number can be found
  * `credit_cost` - what buying it would cost

  Both flags `false` means nothing can be found for this person at any price.
</ResponseField>

<ResponseField name="contacts" type="object | null">
  What the organization has already bought:

  * `status` - `COMPLETED`, or `IN_PROGRESS` while more is still arriving
  * `emails` - list of email addresses
  * `phone_numbers` - list of phone numbers

  Omitted entirely when nobody has bought them yet.
</ResponseField>

<ResponseField name="credit_balance" type="object | null">
  `available` and `reserved` credits for the organization. Omitted when the credential has no organization the API can resolve credits for.
</ResponseField>

***

## `syrto_request_person_contacts`

Buys a person's contact details. **This spends the organization's credits.**

### Before buying

1. Call `syrto_get_person_contacts` for the exact `credit_cost`, and to check anything can be found for this person at all.
2. Tell the user whose contacts these are and what they cost, and get their explicit agreement to spend it.
3. Pass that cost as `expected_credit_cost`. The purchase is refused if the live price differs, which catches a stale price - it does not establish that anyone agreed to it, so step 2 still stands on its own.

<Warning>
  The duplicate and price checks run just before the purchase, not atomically with it. The upstream API takes no price ceiling, so a price that moves between the check and the purchase is charged at the new figure.
</Warning>

### When a repeat costs nothing

Two independent things decide whether a repeat is charged:

* The upstream API deduplicates a dispatched purchase intent - the same person and `force_new` - for **24 hours**, returning the first purchase rather than charging again.
* Separately, this tool refuses contacts the organization already holds, whether or not that window has passed, **unless** `force_new` is `true`.

So a plain repeat stays protected after 24 hours by the second rule, while a repeat of an intent that already carried `force_new: true` is protected only by the first, and buys again once the window passes.

Do not call this tool to collect contacts that are still arriving. Providers return emails first and phone numbers afterwards, and `syrto_get_person_contacts` returns the rest at no cost once they land.

If the call times out or fails, call it again with the same purchase intent - the same person and `force_new`. Adding `force_new` makes it a different purchase, charged in full. `expected_credit_cost` and `language` are not part of the intent.

### Arguments

<ParamField query="person_id" type="string" required>
  The person to buy contact details for.
</ParamField>

<ParamField query="expected_credit_cost" type="integer" required>
  The `credit_cost` from `syrto_get_person_contacts`, as shown to the user.
</ParamField>

<ParamField query="force_new" type="boolean">
  Run a fresh provider lookup for a person whose contacts the organization already has. Charges in full. Default `false`. Not for collecting in-progress data - that is free through `syrto_get_person_contacts`.
</ParamField>

<ParamField query="language" type="string">
  `"en"` for English (default) or `"it"` for Italian.
</ParamField>

### Returns

<ResponseField name="person" type="object">
  `id` and `name`.
</ResponseField>

<ResponseField name="contacts" type="object | null">
  `status` (`COMPLETED`, or `IN_PROGRESS` while more is arriving), `emails` and `phone_numbers`. Omitted when the provider found nothing.
</ResponseField>

<ResponseField name="credit_cost" type="integer">
  The price quoted for this enrichment, not a confirmed debit - the upstream API does not report what it charged.

  `0` is the exception and is certain: an enrichment that finds nothing is not charged for at all. A positive value can also end up uncharged, if this call repeated an identical `force_new` purchase within 24 hours - which is replayed upstream and is not detectable here.
</ResponseField>

<Note>
  The provider may find nothing. That is a successful, unbilled call: it comes back with no contacts and a `warning` saying so. It is "no contacts could be found", not an error, and retrying will not change it.
</Note>

## Example

**1. Check what is available and what it costs (free):**

```json theme={null}
{
  "person_id": "cDpJVF9SU1NNUkE4MEEwMUY4MzlY"
}
```

**2. Buy, after the user agreed to the cost:**

```json theme={null}
{
  "person_id": "cDpJVF9SU1NNUkE4MEEwMUY4MzlY",
  "expected_credit_cost": 3
}
```
