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

# Add a candidate

> Add a candidate to a Staplehire role by email, name, stage, and profile fields from the CLI, move them between stages, and read their record.

Add a candidate to a role with `candidates create`. You must place them in a stage, and the command is idempotent per role and email.

```bash theme={null}
staplehire candidates create <roleId> --email alex@example.com --name "Alex Chen" --stage "Sourced"
```

<Note>
  Create at least one [stage](/docs/stages-cli) on the role first. `candidates create` requires either `--stage <name>` or `--stage-id <id>`.
</Note>

## Add a candidate

```bash theme={null}
staplehire candidates create 550e8400-e29b-41d4-a716-446655440000 \
  --email alex@example.com \
  --name "Alex Chen" \
  --stage "Sourced"
```

Example output:

```json theme={null}
{
  "candidate": {
    "id": "cand_…",
    "email": "alex@example.com",
    "name": "Alex Chen",
    "role_id": "550e8400-e29b-41d4-a716-446655440000",
    "stage_id": "stage_…"
  }
}
```

Capture the candidate ID:

```bash theme={null}
CANDIDATE_ID=$(staplehire candidates create "$ROLE_ID" \
  --email alex@example.com --name "Alex Chen" --stage "Sourced" \
  | jq -r '.candidate.id')
```

### Parameters

| Flag                       | Required               | Description                                    |
| -------------------------- | ---------------------- | ---------------------------------------------- |
| `<roleId>`                 | Yes                    | Role to add the candidate to                   |
| `--email <email>`          | Yes                    | Candidate email address                        |
| `--stage <name>`           | One of the stage flags | Stage name resolved on the role                |
| `--stage-id <id>`          | One of the stage flags | Stage ID (takes precedence if both are passed) |
| `--name <name>`            | No                     | Display name                                   |
| `--phone <phone>`          | No                     | Phone number                                   |
| `--linkedin-url <url>`     | No                     | LinkedIn profile URL                           |
| `--portfolio-url <url>`    | No                     | Portfolio URL                                  |
| `--current-location <loc>` | No                     | Candidate location                             |

<Warning>
  You must pass `--stage` **or** `--stage-id`. Omitting both fails with exit code `3` (validation). If you pass both, `--stage-id` wins.
</Warning>

## Examples

### Add with profile links

```bash theme={null}
staplehire candidates create <roleId> \
  --email alex@example.com \
  --name "Alex Chen" \
  --linkedin-url https://linkedin.com/in/alexchen \
  --portfolio-url https://alex.dev \
  --current-location "Sydney, AU" \
  --stage "Sourced"
```

### Move a candidate to another stage

```bash theme={null}
staplehire candidates move <candidateId> --stage-id <stageId>
```

```json theme={null}
{ "candidate": { "id": "cand_…", "stage_id": "stage_…" } }
```

## Read candidates

```bash theme={null}
staplehire candidates list --role-id <roleId>          # all on a role
staplehire candidates list --email alex@example.com    # exact email match
staplehire candidates list --q "alex"                  # search name/email
staplehire candidates get <candidateId>                # one candidate
staplehire candidates screening-result <candidateId>   # latest fit/screening result
```

## Common errors

| Error                      | Exit code | Fix                                                                                                                                |
| -------------------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `ValidationError`          | `3`       | Invalid email, or no `--stage`/`--stage-id` — fix the field in `error.hint`                                                        |
| `candidate_already_exists` | `5`       | The email already exists on this role — [find and move the existing candidate](/docs/stages-cli#recover-from-a-duplicate-candidate-409) |
| `stage_not_found`          | `4`       | Run `staplehire stages list <roleId>` and use a real stage                                                                         |
| `role_not_found`           | `4`       | Confirm the role ID with `staplehire roles list`                                                                                   |

## FAQ

<AccordionGroup>
  <Accordion title="Can I add the same email twice?">
    Not on the same role — it returns `candidate_already_exists` (exit `5`). Read or move the existing candidate instead. The same email on a different role is a separate candidate.
  </Accordion>

  <Accordion title="Should I use `--stage` or `--stage-id`?">
    Use `--stage-id` when you already have the ID. Use `--stage` to let the CLI resolve a stage name on the role. If both are given, `--stage-id` is used.
  </Accordion>

  <Accordion title="Is there an alias for `candidates create`?">
    Yes — `candidates add` is a deprecated alias. Prefer `create`.
  </Accordion>
</AccordionGroup>

Related: [Manage stages](/docs/stages-cli) · [Enrich a candidate](/docs/enrich-candidate-cli) · [Send an interview](/docs/send-interview-cli)
