<!-- @generated by `npm run docs:gen` from src/content/docs/ — DO NOT EDIT. -->

# Get profile

Get a single profile directly by its id. Stateless — you do not need a prior search, and there is no result-set handle to manage. Billed per fetch.

`GET /v1/profiles/{id}`

Authenticated with your `x-api-key`. See [Authentication](https://ask.xverum.com/docs/authentication.md).

## How it works

Every search result carries an `id`. Pass it here to retrieve that person's complete profile — the card fields plus employment history, education and profile summary. You can also fetch any id you already hold; a prior search is not required.

There is one response shape and one price. The endpoint takes no options beyond the id.

The charge is **deduped per `(api-key, id)`** within a short window: a repeat fetch of the same profile re-reads fresh data but charges `0`. Only the charge is deduped — the data returned is always current.

## Request

```http
GET /v1/profiles/{id}
Host: search-api.xverum.com
x-api-key: XVERUM-API-KEY
```

### Path parameter

| Parameter | Description |
| --- | --- |
| `id` | Opaque profile id, e.g. from a `search_people_xverum` result. Stable across sessions — an id you received in a previous search or session stays fetchable. |

## Example

```bash
curl "https://search-api.xverum.com/v1/profiles/a1b2c3d4" \
  -H "x-api-key: XVERUM-API-KEY"
```

## Response — 200 OK

| Field | Type | Description |
| --- | --- | --- |
| `social_url` | string \| null | Person social URL; `null` when no public profile URL is on record for the person |
| `full_name` | string | Full name |
| `headline` | string \| null | Person social headline or summary; `null` when the person has not written one |
| `location` | string \| null | Location string; `null` when no location is on record for the person |
| `company_name` | string \| null | Most recent employer (current role); `null` when no current employer is held for the person |
| `position` | string \| null | Most recent job title (current role); `null` when no current role is held for the person |
| `industry` | string \| null | Industry vertical, taken from the person's current employer; `null` when that employer, or its industry, is not known |
| `evidence_summary` | string | How recently this profile was verified, from its refresh date — `Verified last 30 days` through `Verified over 120 days ago` |
| `experience` | `ExperienceItem[] \| null` | Employment history; `null` if none is held |
| `education` | `EducationItem[] \| null` | Education history; `null` when no education history is on record for the person |
| `about_me` | string \| null | Profile summary; `null` if none is held |
| `credits_used` | integer | Credits deducted (`4`; `0` on a deduped retry) |
| `credits_remaining` | integer | Credits left after this call — a best-effort fresh read from billing; on a transient billing outage it falls back to the balance seen at auth time |
| `request_id` | string | Correlation id — also returned in the `X-Request-Id` header |

Every field is always present in the JSON. A `null` means the value is not held for that person, never that it was withheld from this response.

### ExperienceItem shape

```json
{
  "position": "Senior Python Engineer",
  "company_name": "Acme",
  "start_time": "2018-03",
  "end_time": null,
  "duration": "6 yrs",
  "location": "Seattle, WA",
  "job_description": "...",
  "industry": "software"
}
```

Every field is nullable, and `null` means the detail was not held for that entry in the source profile — never that it was withheld here.

| Field | Type | Description |
| --- | --- | --- |
| `position` | string \| null | Job title for this entry; `null` when no title is on record |
| `company_name` | string \| null | Employer for this entry; `null` when no employer name is on record |
| `start_time` | string \| null | Start month, `YYYY-MM`; `null` when the start date is not on record |
| `end_time` | string \| null | End month, `YYYY-MM`; an ongoing role reads `Present`. `null` when no end date is on record in the source profile |
| `duration` | string \| null | Human-readable length of the role; `null` when it cannot be derived from the dates |
| `location` | string \| null | Where the role was based; `null` when no location is on record |
| `job_description` | string \| null | Free-text role description; `null` when the person did not write one |
| `industry` | string \| null | Industry of this employer; `null` when the employer, or its industry, is not known |

### EducationItem shape

`education` is `null` when no education history is on record for the person. For each education entry:

| Field | Type | Description |
| --- | --- | --- |
| `social_url` | string \| null | Institution social URL; `null` when no public URL is on record for the institution |
| `institution_name` | string \| null | Institution name; `null` when it is not recorded on the education entry |
| `degree` | string[] | Degrees or programmes; `[]` when none are recorded on the education entry |
| `start_time` | string \| null | Start date; `null` when it is not recorded on the education entry |
| `end_time` | string \| null | End date; `null` when it is not recorded on the education entry |
| `description` | string \| null | Education description; `null` when no description is recorded on the education entry |

### Example response

```json
{
  "social_url": "https://www.linkedin.com/in/jane-doe-sea",
  "full_name": "Jane Doe",
  "headline": "Senior Python Engineer at Acme",
  "location": "Seattle, WA",
  "company_name": "Acme",
  "position": "Senior Python Engineer",
  "industry": "software",
  "evidence_summary": "Verified last 30 days",
  "experience": [
    {
      "position": "Senior Python Engineer",
      "company_name": "Acme",
      "start_time": "2018-03",
      "end_time": null,
      "duration": "6 yrs",
      "location": "Seattle, WA",
      "job_description": "...",
      "industry": "software"
    }
  ],
  "education": [
    {
      "social_url": "https://www.linkedin.com/school/uc-berkeley",
      "institution_name": "UC Berkeley",
      "degree": ["BSc Computer Science"],
      "start_time": "2010",
      "end_time": "2014",
      "description": null
    }
  ],
  "about_me": "Backend engineer focused on distributed systems...",
  "credits_used": 4,
  "credits_remaining": 4996,
  "request_id": "1a2b3c4d5e6f7081"
}
```

## Billing

Every fetch costs **4 credits**, echoed back as `credits_used`; `credits_remaining` shows the balance left. A repeat fetch of the same `id` with the same API key within the dedup window charges `0` (you still get fresh data).

`credits_remaining` is read fresh from billing on each successful call and is **best-effort**: if billing is briefly unavailable it falls back to the balance seen at authentication. Treat it as an indicative post-call balance, not a settled ledger figure.

## Errors

All `/v1` errors use the structured envelope (see [Authentication](https://ask.xverum.com/docs/authentication.md)):

| Status | `error.code` | Condition |
| --- | --- | --- |
| `401` | `invalid_api_key` | Missing or invalid API key |
| `402` | `out_of_credits` | Out of credits — the envelope carries an `upgrade_url` to top up |
| `403` | `account_not_authorized` | Account not authorized |
| `404` | `profile_not_found` | No profile exists for the given `id` |
| `422` | `validation_error` | The `id` is empty or longer than 128 characters |
| `429` | `rate_limited` | Rate limit exceeded — see [Rate limits](https://ask.xverum.com/docs/rate-limits.md) |
| `502` | `upstream_unavailable` | An upstream dependency failed — retry shortly |
| `503` | `search_unavailable` | The profile store is temporarily saturated or unreachable — retry shortly |
| `503` | `auth_unavailable` | Authentication is briefly unreachable — retry shortly |
| `503` | `classification_degraded` | Temporarily degraded — retry shortly |

```json
{
  "error": {
    "code": "profile_not_found",
    "message": "No profile for id 'a1b2c3d4'.",
    "request_id": "1a2b3c4d5e6f7081"
  }
}
```
