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

# Refresh a contact file

> Keep your own contact file current — who moved, whether the new role is worth your time, and their new email — with your file as the database and no Tamtam list in the loop.

You have a file of contacts. Some rows have a LinkedIn URL, most have a name, a company and
maybe an email. Once a month you want to know who changed job, whether the new role is a
buyer for you, and what their new email is — written back into the same file.

Four operations do that, one per row, and none of them needs a Tamtam contact id: every
request takes what a row of your file holds, and every result echoes the `custom` map you
sent so you can join it back. Run them from n8n, a script, a spreadsheet integration —
anything that can call an HTTP API with your account key.

## The two paths a row can take

<Steps>
  <Step title="Get the person's current role">
    **Row has a LinkedIn URL:** call
    [Read people's experiences](/api-reference/people-extract/read-peoples-experiences) with
    up to 20 URLs. For a profile Tamtam already holds this is free; read `source` to see
    whether it was answered from the store or re-read from LinkedIn. `current_experience`
    is the role to compare with what your file says.

    **Row has no LinkedIn URL:** call
    [Resolve people](/api-reference/people-extract/resolve-people-to-linkedin-profiles) with
    the name, company and email you have, up to 10 per call. The answer names the profile,
    how sure we are (`match_score`), and the `headline` and `company_name` the source saw —
    usually enough to read a job change without extracting anything.
  </Step>

  <Step title="Decide whether the new role is a buyer">
    Take the new job title and, when you can, the new company. Resolve the company name to a
    LinkedIn id with [Search for a company](/api-reference/companies/search-for-a-company)
    (free), then call
    [Score job titles at a company](/api-reference/lead-score/score-job-titles-at-a-company).
    When the company does not resolve, call
    [Score job titles with no company](/api-reference/lead-score/score-job-titles-with-no-company)
    instead. Both are free and answer 0-100 against your account's buyer archetypes.
  </Step>

  <Step title="Enrich the ones above your bar">
    For rows whose score clears your threshold, call
    [Enrich people](/api-reference/people-enrichment/enrich-people-with-email-and-phone-data)
    with the name and the new company's domain or LinkedIn URL, then poll the request id for
    the email. 1 credit per email found.
  </Step>
</Steps>

## What each row costs

| Step             | When                                               | Cost                                         |
| ---------------- | -------------------------------------------------- | -------------------------------------------- |
| Read experiences | Profile Tamtam holds                               | Free                                         |
| Read experiences | Profile Tamtam does not hold, `refresh_only` false | 1 credit (a full extract, creates a contact) |
| Resolve          | Found in Tamtam's records or your CRM              | Free                                         |
| Resolve          | Found by search (`charged: true`)                  | 1 credit                                     |
| Score a title    | Always                                             | Free                                         |
| Enrich an email  | Email found                                        | 1 credit                                     |

The two read steps are priced so that a monthly run against the same file gets cheaper
over time: a profile read once is held, and its experiences are answered from the store for
30 days, then re-read from LinkedIn for free. Set `refresh_only: true` on a run that must
not spend discovery credits, and `force: true` on one that must see today's LinkedIn.

## Reading a job change

An experiences row gives you the person's `current_experience` — title, company, company
LinkedIn id, start date. Compare its `company_linkedin_id` (or `company_name`) with your
file's. Different means they moved; a newer `start_date` at the same company usually means
a promotion.

A resolve row gives you the `headline` and `company_name` the source reported. A headline
like `"VP Sales at Fresh Corp"` against a file that says `Acme` is a move. Treat it as a
strong hint rather than a fact: it is what Linkup or Sales Navigator saw, not something
Tamtam verified. When the row matters, confirm it with one call to
[Read people's experiences](/api-reference/people-extract/read-peoples-experiences) on the
`linkedin_url` you just got.

Threshold `match_score` before you spend on a resolved row. Below 50 the profile is our best
guess and may be someone else; the `match_reason` says what the score rests on.

## The two scoring questions are different questions

`at-company` scores the title as held at that company: the classifier sees the company's
size and industry, and the score is the archetype's variant for that size band. `title-only`
scores the title alone and returns the archetype's best case across bands, with
`company_context: false` on every row so the two readings never get mixed in your file.

Use `at-company` whenever the company resolves to a LinkedIn id. Use `title-only` when it
does not — not as a shortcut when it would.

## Per-row errors, whole-batch refusals

Every operation answers each row on its own. A profile gone from LinkedIn, a company Tamtam
does not hold, a name with nothing to search on: that row carries an `error` code and the
rest of the batch is answered. Branch on the code in your pipeline; the codes are stable.

The one refusal that stops a whole batch is **402**, and it is checked before anything runs:
when the fallback extracts or the searches a batch could need cannot be paid for, nothing in
that batch is spent. Split the batch, top up, or set `refresh_only`.

## Batch sizes and pacing

| Operation                 | Rows per call |
| ------------------------- | ------------- |
| Resolve people            | 10            |
| Read people's experiences | 20            |
| Score job titles          | 50            |
| Enrich people             | 100           |

Calls are synchronous and run their rows concurrently. With the account's 10 requests per
second, an 80,000-row file is a few hours of resolve calls and well under an hour of
everything else; the resolve step is the one to spread out.
