Long-running capabilities should be modeled as durable jobs, not as a single HTTP connection that must remain open until completion.

## Submit once

Create an idempotency key for the logical operation and call `POST /execute`. A moderate `Prefer: wait` value can capture fast completions without changing the job model.

If the response is pending, persist the returned `job_id` with your application record before scheduling a poll.

## Poll with a deadline

Use exponential backoff with jitter and cap the interval. Inspect both HTTP status and JSON `state`:

- HTTP `202`: still queued, running, or retrying;
- HTTP `200`, `state: "completed"`: consume `results[0].data`;
- HTTP `200`, `state: "failed"`: record the error and stop;
- HTTP `404`: the job is unknown or inaccessible to this account.

Set an application deadline based on your user experience. Reaching that deadline should stop local polling or move it to a background queue; it does not cancel the Upscrape job.

## Avoid duplicate work

Do not create a new execution because a poll timed out or a process restarted. Resume from the stored job ID. If the initial submission's outcome was unknown, replay the same request with the original idempotency key.

## Full results after MCP

MCP previews can be truncated at 24 KiB. When your integration also controls a suitable API key, retrieve the full job through the REST job endpoint.
