# Connect an account

> Sign in to a website through Fous, from your code, your agent or Studio, or save a site's API key. Methods on that site then run with it.

Source: https://docs.fous.com/guides/connections
Index: https://docs.fous.com/llms.txt

A connection lets methods run with your organization's login on a site (`session`) or with the site's API key (`api_key`).

## Connect a website login

```bash
curl https://api.fous.com/v1/connections \
  -H "Authorization: Bearer $FOUS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "platform": "example.com",
    "type": "session",
    "attest": true
  }'
```

`attest: true` confirms you may use the account. Add `login_url` if the sign-in page is not the obvious one. The answer is `201` with the first step:

```json
{
  "id": "conn_01m5kyvsdxea78rpr2j3qzzd1z",
  "platform": { "name": "Example", "domain": "example.com" },
  "type": "session",
  "status": "pending",
  "default": false,
  "account_hint": null,
  "connect_url": "https://app.fous.com/org_01M4CD7TVHDBPFQHZD05XMW5PB/connections?connect=conn_01m5kyvsdxea78rpr2j3qzzd1z",
  "checked_at": null,
  "created_at": "2026-10-26T09:42:14.000Z",
  "sign_in": {
    "status": "input",
    "step_id": "stp_7h2k9q",
    "message": "Enter your email or username and password to continue.",
    "fields": [
      { "id": "fld_1", "label": "Email or username", "type": "text", "required": true },
      { "id": "fld_2", "label": "Password", "type": "password", "required": true }
    ],
    "choices": [],
    "expires_at": "2026-10-26T09:52:14.000Z"
  }
}
```

Then either send the person to `connect_url` to sign in in Studio and wait with `GET /v1/connections/{id}?wait=60` until it is `active`, or relay each step from your code.

## Answer each step

| `sign_in.status` | Do |
| --- | --- |
| `working` | Wait with `GET /v1/connections/{id}?wait=30`. |
| `input` | Send values for `fields`, or one of `choices`. |
| `approval` | The person approves on their phone, picking `code`. Wait as above. |
| `failed` | Stop. `message` says why. |

Send `fields` keyed by field id, or `"choice": "<choice id>"`:

```bash
curl "https://api.fous.com/v1/connections/conn_01m5kyvsdxea78rpr2j3qzzd1z/sign-in" \
  -H "Authorization: Bearer $FOUS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "step_id": "stp_7h2k9q",
    "fields": { "fld_1": "person@example.com", "fld_2": "their-password" }
  }'
```

The answer is the next step, here a code sent by email:

```json
{
  "id": "conn_01m5kyvsdxea78rpr2j3qzzd1z",
  "platform": { "name": "Example", "domain": "example.com" },
  "type": "session",
  "status": "pending",
  "default": false,
  "account_hint": null,
  "connect_url": "https://app.fous.com/org_01M4CD7TVHDBPFQHZD05XMW5PB/connections?connect=conn_01m5kyvsdxea78rpr2j3qzzd1z",
  "checked_at": null,
  "created_at": "2026-10-26T09:42:14.000Z",
  "sign_in": {
    "status": "input",
    "step_id": "stp_4n8w2c",
    "message": "Enter the 6-digit code sent to p…@example.com.",
    "fields": [{ "id": "fld_3", "label": "Code", "type": "code", "length": 6, "required": true }],
    "choices": [],
    "expires_at": "2026-10-26T09:53:02.000Z"
  }
}
```

A rejected answer returns the same step with `rejected: true`. For a `link` field, copy the link from the email without opening it, or it is used up.

- A sign-in ends after 10 minutes without an answer, or 15 in all. An organization runs 2 at once.
- `409` with reason `step_expired`: answer the current step. `sign_in_busy`: Fous is still on the last answer.
- `{"attest": true, "restart": true}` on the sign-in endpoint starts over, for example to switch accounts. `DELETE` cancels.
- Fous never returns or logs the values, and keeps only the identifier and password, sealed, to sign in again.

## Which connection a run uses

An organization has one login per site; connecting the site again returns it with `200`. A run uses the site's active connection, then the default, then the newest, unless it names `connection`. To set the default:

```bash
curl -X PATCH "https://api.fous.com/v1/connections/conn_01m5kyvsdxea78rpr2j3qzzd1z" \
  -H "Authorization: Bearer $FOUS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"default": true}'
```

```json
{
  "id": "conn_01m5kyvsdxea78rpr2j3qzzd1z",
  "platform": { "name": "Example", "domain": "example.com" },
  "type": "session",
  "status": "active",
  "default": true,
  "account_hint": "p…@example.com",
  "checked_at": "2026-10-26T09:44:10.000Z",
  "created_at": "2026-10-26T09:42:14.000Z"
}
```

When the site signs the account out and Fous cannot sign back in, the connection turns `needs_attention` and runs answer `403 connection_required` with `connect_url`.

## Save a site's API key

```bash
curl https://api.fous.com/v1/connections \
  -H "Authorization: Bearer $FOUS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "platform": "example.com",
    "type": "api_key",
    "api_key": "your-key-for-that-site",
    "attest": true
  }'
```

```json
{
  "id": "conn_01m5kz2b4d6f8h0k2m4p6r8t0v",
  "platform": { "name": "Example", "domain": "example.com" },
  "type": "api_key",
  "status": "active",
  "default": true,
  "hint": "…site",
  "checked_at": null,
  "created_at": "2026-10-26T09:50:31.000Z"
}
```

The key is stored encrypted, never returned, and sent only to its own site.

## Disconnect

Only a person can, with **Disconnect** in Studio's **Connections**.
