# Scheduled webpage captures for reports

Use this pattern for recurring captures of public dashboards, documentation, status pages, or report inputs. It keeps retries and concurrency bounded so a target outage cannot create an unbounded browser queue.

## One capture

Download and run the dependency-free Node adapter:

```sh
curl --fail-with-body \
  https://latchshot.fly.dev/examples/node.mjs \
  --output latchshot.mjs

export LATCHSHOT_API_KEY='ls_live_replace_me'
node latchshot.mjs 'https://example.com/report' report.png
```

The adapter prints output bytes, content type, server render time, and remaining monthly quota as JSON. It retries transport failures plus `429`, `502`, `503`, and `504` at most twice.

## Before a batch

```sh
curl --fail-with-body \
  -H "Authorization: Bearer $LATCHSHOT_API_KEY" \
  https://latchshot.fly.dev/v1/usage
```

Compare the returned remaining quota with the intended batch size. Automatic overages are disabled during private beta.

## Operating rules

1. Run no more than two captures concurrently unless the owner assigns a higher ceiling.
2. Give each job a 45-second client timeout; the server also enforces its own bounded browser deadline.
3. Retry only transient transport errors, `429`, and `5xx` responses, with no more than two retries.
4. Do not retry `400` or `401` until the request or credential is corrected.
5. Save response diagnostics with the report job: `X-Latchshot-Render-Ms`, `X-Latchshot-Navigation`, `X-Latchshot-Fonts`, and `X-Latchshot-Scripts`.
6. Alert before quota reaches zero; do not silently drop a report or create an unlimited retry loop.

For GitHub-hosted schedules, start from the [GitHub Actions workflow](https://latchshot.fly.dev/integrations/github-actions.yml), add a `schedule` trigger, and replace the workflow input with a fixed public URL stored in repository variables.
