# Login to any web app

Most product workflows happen behind a login screen, so Slideshot needs a way to get the recording browser into your target app. There are two distinct concepts to keep straight:

- The **Slideshot API key**: used to talk to Slideshot itself. See [API key](/docs/api).
- **Target-app credentials**: the email and password (or magic-link / OTP flow) the recording browser uses to sign into the app you want to demo. That is what this page is about.

## How target-app auth works

Every run accepts an `auth` option that controls how Slideshot signs in.

- `{ "source": "none" }`: Do not log in. Use this for marketing pages, docs, and unauthenticated flows.
- `{ "source": "default" }`: Use whichever credential is the default for the target domain. If no default exists, the run proceeds without logging in.
- `{ "source": "saved", "id": "<credential_uuid>" }`: Use a specific saved credential. The credential's domain must match the `target_url` hostname, and it must be owned by the caller.

Credentials are scoped to a domain (`app.example.com`), encrypted at rest, and never echoed back from the API. See [Credentials](/docs/api/credentials) for the endpoints.

## Save credentials up front

Saving credentials before the first run keeps the agent out of the loop for sign-in:

```bash
curl -X POST https://api.slideshot.ai/v1/agent/credentials \
  -H "x-api-key: $SLIDESHOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "label": "Example app: demo account",
    "domain": "app.example.com",
    "email": "demo@example.com",
    "password": "...",
    "is_default": true
  }'
```

Mark one credential per domain as default with `is_default: true` so plain `auth.source="default"` works without naming an ID.

## Email-only credentials

If your target app uses magic links or OTPs instead of passwords, omit `password` when creating the credential:

```bash
curl -X POST https://api.slideshot.ai/v1/agent/credentials \
  -H "x-api-key: $SLIDESHOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "label": "Example app: magic link",
    "domain": "app.example.com",
    "email": "demo@example.com"
  }'
```

During the run, the agent reaches the OTP step and pauses the run in `awaiting_input`. Fetch the code from your inbox and submit it with `POST /v1/agent/runs/:id/input`. See [Runs](/docs/api/runs#handling-awaiting-input).

## Choosing a credential at run time

Pass `auth` in `options` when creating a run:

```json
{
  "target_url": "https://app.example.com",
  "goal": "Open the analytics dashboard and create a report.",
  "options": {
    "auth": { "source": "saved", "id": "0a1b2c3d-4e5f-6789-abcd-ef0123456789" }
  }
}
```

For most flows, prefer `auth.source="default"` and rely on the per-domain default. It keeps the run options short and lets you rotate the underlying credential without touching client code.

## OTP and magic-link flows during a run

When the recording browser reaches a one-time-code step, Slideshot pauses the run. The status becomes `awaiting_input` and the run object includes:

```json
{
  "awaiting_input": {
    "prompt": "Enter the 6-digit code from your email",
    "requested_at": "2026-05-11T12:00:00Z",
    "expires_at": "2026-05-11T12:05:00Z"
  }
}
```

Submit the value before `expires_at`:

```bash
curl -X POST https://api.slideshot.ai/v1/agent/runs/$RUN_ID/input \
  -H "x-api-key: $SLIDESHOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "value": "123456" }'
```

The run resumes from where it paused. The `awaiting_input` window is also cut out of the final `demo.mp4`, so viewers do not see the wait.

## Failure modes to know about

- **Invalid UUID in `auth.saved.id`.** The run rejects at creation time with `400`.
- **Saved credential not owned by the caller.** The run fails at execution with a credentials error.
- **Saved credential's domain does not match `target_url`.** Same outcome. The run fails at execution.
- **`auth.source="default"` with no default credential.** The run proceeds without logging in. If the workflow needs auth, the agent stops at the login screen.

## Safety notes

- Use dedicated demo accounts. Do not record real-customer logins.
- Slideshot redacts filled values in the public event log. The plaintext password is never written into artifacts, prompts, or telemetry.
- Combine [`video.blur_emails: true`](/docs/customizing-video/blur-emails) with credentials that contain real-looking emails so identifiers do not leak into the published video.
- Rotate or delete credentials you no longer use with `DELETE /v1/agent/credentials/:id`.
