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

# Email verification

> Optional convenience: connect a mailbox and let Jobo resolve emailed verification codes and confirmation links, instead of reading the inbox yourself.

Some ATS flows pause an application on an **email verification step**: the
provider emails a one-time code to the candidate's address and the application's
`current_step` carries a field with `format: "one_time_code"` that expires in
60 seconds. Others email a confirmation **link** that has to be clicked before
the application counts as submitted.

<Note>
  **Connecting a mailbox is entirely optional.** Verification steps work the same
  whether or not Jobo can see the inbox — the code is just another answer on the
  step, so if you already read that mailbox yourself, keep doing exactly that and
  submit the code through `POST /applications/{id}/answers` as usual. These
  endpoints exist purely so you don't have to build and operate IMAP/OAuth inbox
  access if you'd rather not. Nothing else in Auto Apply depends on them, and you
  can adopt them for some mailboxes and not others.
</Note>

With a mailbox connected, Jobo reads the code — or clicks the link — for you,
and the verification step stays two API calls:

```text theme={null}
application pauses on one_time_code
        │
        ▼
POST /mailboxes/{id}/verification  ──▶ { status: "found", code: "AB12CD34" }
        │
        ▼
POST /applications/{id}/answers  (the code is just another answer)
```

## Connect a mailbox once

Mailboxes are **account-level resources** — connect each inbox once and
reference its `id` from any application. Two providers:

* **`imap`** — host, address, and a password (use an app password where the
  provider offers them, e.g. Gmail). Credentials are verified synchronously on
  create: you either get `status: "connected"` back or a
  `mailbox_verification_failed` problem and nothing is stored.
* **`outlook`** — Outlook and Microsoft 365 disabled password IMAP in
  April 2026, so this provider uses a hosted Microsoft consent flow and reads
  over Microsoft Graph (delegated `Mail.Read`). Create returns
  `status: "pending"` plus an `authorization_url`; open it (or send it to the
  mailbox owner), sign in with the **same address** you declared, and the
  mailbox flips to `connected`. The consent link expires after 15 minutes —
  fetch the mailbox again for a fresh one. No IMAP host is needed or returned
  for this provider.

Secrets are encrypted at rest with the same envelope scheme as application
data and are never returned by any endpoint. `DELETE` hard-deletes them.

## Retrieve the verification

The moment an application pauses on its verification step, call
`POST /api/auto-apply/mailboxes/{id}/verification` with the `application_id`. The call
**blocks** while Jobo polls the inbox (newest messages first, read-only — your
mail is never marked as seen) and an AI extractor picks the verification email
using the application's apply host and ATS provider as context, so a Greenhouse
code isn't confused with an unrelated login email that arrived the same minute.

Providers verify in one of two ways — a one-time **code** to type into the
form, or a confirmation **link** to click. The response's `type` says which
was found (constrain it by passing `type: "code"` or `type: "link"` in the
request; the default `any` accepts either):

```json theme={null}
{ "status": "found", "type": "code", "code": "AB12CD34",
  "email_from": "no-reply@greenhouse.io",
  "email_subject": "Your verification code", "waited_seconds": 9 }
```

```json theme={null}
{ "status": "found", "type": "link",
  "link": "https://boards.greenhouse.io/confirm?token=…",
  "link_visited": true, "link_http_status": 200, "waited_seconds": 11 }
```

```json theme={null}
{ "status": "timeout", "waited_seconds": 45 }
```

For `type: "link"` Jobo **clicks the link server-side** — https-only, public
hosts only, bounded redirects — which confirms the address the way the
applicant would. When `link_visited` is `false` the click failed; open the
returned `link` yourself.

`timeout` is an expected outcome — the email may simply not have arrived —
not an error. Real faults are RFC 7807 problems: `mailbox_not_connected`,
`mailbox_auth_failed` (reconnect the mailbox), `application_not_found`.

<Warning>
  The `one_time_code` answer window is **60 seconds**. Keep `wait_seconds` at
  the default 45 so there is time left to submit the code through the answers
  endpoint, and keep your HTTP client timeout above `wait_seconds`.
</Warning>

The extracted code is validated server-side — it must appear verbatim in the
selected email — and email contents never leave the extraction. Only the code
plus the matched email's sender, subject, and timestamp are returned.

## Timing in practice

1. `POST /applications` → application eventually pauses with a
   `one_time_code` field (the step's `answers_expire_at` tells you the
   deadline).
2. Immediately `POST /mailboxes/{id}/verification` with the `application_id` — the
   verification email typically lands within seconds of the step appearing.
3. `POST /applications/{id}/answers` with the code as the field's answer.

If the code expires before you submit it, the provider rejects it as
`verification_code_rejected` and the application offers a correction round —
call the verification endpoint again; a fresh email supersedes the old one.
