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

# Intake

> Extract structured search criteria from free text or a job description

## Extract criteria

#### `POST /api/intake`

Requires a signed-in session. Takes free text, returns structured `CriteriaV2` JSON plus
an entity-coverage breakdown the calibrate screen uses to light up chips.

### Request body

```json theme={null}
{
  "rawInput": "CFO for a PE-backed manufacturing company in Cleveland, OH, 10+ years experience"
}
```

<ParamField body="rawInput" type="string" required>
  The free-text description or pasted job description. Must be non-empty.
</ParamField>

### Response

```json theme={null}
{
  "criteria": {
    "family": "CFO",
    "metro": "Cleveland, OH",
    "industries": ["manufacturing"],
    "years_experience": { "min": 10 },
    "_meta": { "confidence": { "metro": 0.95, "family": 0.9 } }
  },
  "entityCoverage": {
    "location": { "resolved": true, "confidence": 0.95, "required": true },
    "job_title": { "resolved": true, "confidence": 0.9, "required": true },
    "years_experience": { "resolved": true, "confidence": 0.85, "required": false },
    "industry": { "resolved": true, "confidence": 0.8, "required": false },
    "skills": { "resolved": false, "confidence": 0, "required": false }
  },
  "familyUnresolved": false,
  "familySuggestions": [],
  "rawToolInput": { }
}
```

<ResponseField name="criteria" type="CriteriaV2">
  The extracted criteria object. Every field is optional — an absent field means the
  model didn't find or wasn't confident about that slot, not that it was rejected.
</ResponseField>

<ResponseField name="entityCoverage" type="object">
  One entry per calibrate-screen chip (`location`, `job_title`, `years_experience`,
  `industry`, `skills`). A chip is considered confirmed when `resolved` is true **and**
  `confidence >= 0.7`.
</ResponseField>

<ResponseField name="familyUnresolved" type="boolean">
  True if the model named a role family that isn't one of the organization's seeded
  families. When true, `criteria.family` is stripped from the response and
  `familySuggestions` lists the closest known families instead of guessing.
</ResponseField>

### Errors

| Status | `code`                     | Meaning                                                                                                    |
| ------ | -------------------------- | ---------------------------------------------------------------------------------------------------------- |
| 401    | —                          | No session.                                                                                                |
| 400    | —                          | `rawInput` missing or empty.                                                                               |
| 424    | `anthropic_not_configured` | No Anthropic API key is available (neither database-managed nor `.env`). See [API Keys](/guides/api-keys). |
| 502    | `extraction_failed`        | The model didn't return a usable result, or validation failed twice in a row.                              |
| 502    | —                          | Couldn't load role families from the database.                                                             |
| 500    | —                          | Anything else, with the raw error message.                                                                 |

### What it doesn't do

This endpoint only extracts and validates criteria — it never calls Harvest, Serper, or
any sourcing provider, and never produces a numeric score. Scoring is computed entirely
in SQL once a scan actually runs (not yet wired up in the UI).
