# Connect

Connect any mailbox with one hosted link, or from your own form with discovery and a direct connect call that checks everything before it stores anything.

## Send the user to the hosted page

Request a link for a profile and send the user to `authUrl`. It is valid for one hour:

```bash
curl "https://zernio.com/api/v1/connect/email?profileId=PROFILE_ID&redirect_url=https://example.com/done" \
  -H "Authorization: Bearer $ZERNIO_API_KEY"
```

```json
{ "authUrl": "https://zernio.com/connect/email?connect_token=…", "expiresAt": "2026-11-10T13:00:00.000Z" }
```

The page asks for the email address first. Gmail and Microsoft addresses, found by domain or MX, go to Google or Microsoft sign-in. Every other mailbox gets its provider's app-password steps and a password field.

When it finishes, the browser goes to `redirect_url` with `status=success`, `accountId`, `platform` and `email`, or with `status=error` and `error`.

Pass `email` to skip the first screen, and `name` for the name people see on sent mail.

## Find the settings for your own form

Call `POST /v1/email/imap/discover` with the address. `route` says where it connects:

```bash
curl -X POST "https://zernio.com/api/v1/email/imap/discover" \
  -H "Authorization: Bearer $ZERNIO_API_KEY" -H "Content-Type: application/json" \
  -d '{"email": "ana@icloud.com"}'
```

```json
{
  "data": {
    "route": "imap",
    "provider": { "id": "icloud", "name": "iCloud Mail" },
    "source": "preset",
    "confidence": "high",
    "imap": { "host": "imap.mail.me.com", "port": 993, "security": "tls", "username": "ana@icloud.com" },
    "smtp": { "host": "smtp.mail.me.com", "port": 587, "security": "starttls" },
    "auth": { "kind": "app_password", "label": "App-specific password", "helpUrl": "https://account.apple.com/account/manage", "steps": ["…"] },
    "preflight": []
  }
}
```

Show `auth.steps` and `auth.helpUrl` before the password field, and every `preflight` item before the user continues. `route` is `google_oauth` or `microsoft_oauth` for Gmail and Microsoft mail, and `unsupported` for Proton Mail.

Discovery tries presets, the domain's MX, its autoconfig, Thunderbird's ISPDB, SRV records and a probe, within 15 seconds. It is limited to 20 calls a minute.

## Connect from your own form

Call `POST /v1/email/imap/accounts`. The email and password are enough when discovery finds the servers:

```bash
curl -X POST "https://zernio.com/api/v1/email/imap/accounts" \
  -H "Authorization: Bearer $ZERNIO_API_KEY" -H "Content-Type: application/json" \
  -d '{"profileId": "PROFILE_ID", "email": "ana@icloud.com", "password": "abcd-efgh-ijkl-mnop", "name": "Ana Ruiz"}'
```

Zernio signs in to IMAP and SMTP and finds the folders before it stores anything. Pass `imap` and `smtp` with `host`, `port` and `security` to name the servers yourself.

Add `"dryRun": true` to run the same checks without connecting, for live validation in your form.

## Reconnect a mailbox

Connecting an address that is already on the profile updates it in place and keeps its `accountId`.

For a mailbox in `reconnect_required`, pass `reconnectAccountId`: the stored servers are kept and only the new password is checked. The hosted link takes the same parameter and asks only for the password.

## If it fails

A failed check answers `422` with the failing stage's `code`, and `details.stages` says which checks passed.

| Code | Cause | Fix |
|------|-------|-----|
| `app_password_required` | The provider rejected the account password | Create an app password at `details.helpUrl` |
| `imap_auth_failed` | The IMAP server rejected the password | Check the password and that IMAP access is on |
| `smtp_auth_failed` | Reading works, sending does not | Pass `smtp.username` and `smtp.password` |
| `imap_disabled` | IMAP access is off at the provider | Turn it on in the mailbox settings |
| `use_oauth` | A Google or Microsoft mailbox | Use the Google or Microsoft connect |
| `tls_hostname_mismatch` | The certificate is for another name | Use `details.suggestion.host` |
| `smtp_unreachable` | The SMTP port did not answer | Try `details.suggestion.port` |
| `too_many_attempts` | The provider is refusing sign-ins | Wait for `Retry-After` |

## Related

- [IMAP email](/platforms/imap/email)
- [Limits & errors](/platforms/imap/reference)