# Run an API

Execute an accepted source definition and receive structured records with an execution summary. Copy your source identifier, API origin, and full definition version from its connection details in the console.

```http
POST /v1/sources/{source_id}/run
```

This reference describes generated source APIs. The saved request and OpenAPI contract for your API define its supported inputs and record schema.

## Before you send a request

Create a server credential with the `run` scope and access to the source. Keep it in your server's secret store. Add `read` to retrieve connection details and `results` to retrieve retained run results. See [authentication](/docs/authentication/).

Save one unique idempotency key with the source, definition version, and input before sending the request. Reuse that exact identity when recovering the same request. Create a new key for each intentional new execution.

## Headers

| Header | Value |
| --- | --- |
| `Authorization` | `Bearer <API_KEY>` |
| `Content-Type` | `application/json` |
| `Idempotency-Key` | Required for customer workspace execution. A saved string of 1–200 characters using letters, numbers, `.`, `_`, `:`, or `-`. |

The origin comes from your API's connection details. It is separate from the website being collected. Send credentials only to that supplied HTTPS origin.

## Request body

| Field | Type | Meaning |
| --- | --- | --- |
| `expected_version` | string | Require the active definition to match this full 64-character lowercase SHA-256 version. Recommended for normal execution. |
| `definition_version` | string | Select an accepted immutable revision explicitly. Use instead of `expected_version`. It applies that revision's rules to current source content. |
| `input` | object | Inputs accepted by this source's generated contract. |
| `endpoint` | string | Optional; the supported value is `search`. |

Do not combine `expected_version` and `definition_version`, including a null value. An inactive candidate is not an accepted revision. A version selects extraction rules; it does not restore an older copy of the website.

For a collection API that supports these inputs, begin with one collection page and no detail enrichment:

```bash
umask 077
: "${CLEANEDWEB_IDEMPOTENCY_KEY:?Set the saved key for this request}"

curl --fail-with-body --max-time 60 \
  "${CLEANEDWEB_API_BASE}/v1/sources/${CLEANEDWEB_SOURCE_ID}/run" \
  -H "Authorization: Bearer ${CLEANEDWEB_API_KEY}" \
  -H "Idempotency-Key: ${CLEANEDWEB_IDEMPOTENCY_KEY}" \
  -H 'Content-Type: application/json' \
  --data "{\"expected_version\":\"${CLEANEDWEB_DEFINITION_VERSION}\",\"input\":{\"max_pages\":1,\"detail_limit\":0}}" \
  --output response.json
```

Set the connection variables as described in the [quickstart](/docs/quickstart/). Store the request key before executing this command. Use a fresh private directory or a unique output filename for each intended execution, so an earlier response is not overwritten. Keep the response file private.

`max_pages` is a collection budget, not a page number. `detail_limit: 0` disables detail enrichment. Search APIs can require a `query` instead; use their exact allowed values or constraints. Unknown fields and values outside the accepted contract are rejected.

## Response fields

| Field | Meaning |
| --- | --- |
| `records` | Array of records conforming to this source's output schema. |
| `summary.source_id` | Source that executed. |
| `summary.definition_version` | Full version used for execution. Must match the requested version. |
| `summary.status` | `completed`, `bounded`, or `partial`. |
| `summary.within_scope_passed` | Whether execution passed within its requested scope. |
| `summary.catalog_complete` | The generated contract reports `false`; a run does not establish full-catalog coverage. |
| `summary.records` | Number of returned records. |
| `summary.limits` | Collection and detail limits applied to the run. |
| `summary.details_selected` | Records selected for detail enrichment. |
| `summary.details_complete` | Selected details that completed. |
| `summary.details_not_selected` | Records outside the selected detail budget. |
| `metadata.definition_version` | Execution version; must agree with the summary and requested version. |
| `artifacts` | Additional execution artifacts. Preserve relevant diagnostics alongside the result. |
| `traceId` | Trace identifier when available; it may be null. |
| `delivery` | Present for a delivered customer workspace result: `runId`, `chargeReceiptId`, and `recordCount`. |

The generated contract can include additional summary and metadata fields. Keep the complete response so you can review missing fields, collection stop reasons, and other source-specific evidence.

## Accept or review the result

Before downstream processing, require both version fields to match your requested version, `summary.within_scope_passed` to be `true`, and `summary.status` to be `completed` or `bounded`. Validate the records against your saved schema and required fields. Compare the returned record count with the records array.

A bounded result can meet the request while leaving later pages or detail records uncollected. Preserve a partial response for review; do not replace it with an empty dataset. HTTP 200 alone does not establish a usable result. See [pagination and output](/docs/pagination/).

## Retrieve a delivered result

If you have `delivery.runId`, retrieve its retained result using a credential with the `results` scope:

```http
GET /v1/sources/{source_id}/runs/{run_id}/result
Authorization: Bearer <API_KEY>
```

This reads the saved delivery without collecting the website again. The source, workspace, and run must match. A `404` means the result was not found or is inaccessible; a `409` can mean it is not available for delivery yet.

For a lost response without a run identifier, follow [idempotency and recovery](/docs/idempotency/). For rejected requests, see [errors and retries](/docs/errors/).
