---
title: "Run a playbook against uploaded files"
method: POST
path: "/playbooks/{id}/run"
tags: ["Playbooks"]
---

# Run a playbook against uploaded files

`POST /playbooks/{id}/run`

## Request

- Base URL: `https://app.gc.ai/api/external/v1`
- URL: `https://app.gc.ai/api/external/v1/playbooks/{id}/run`
- Auth: API key in header `Authorization`
- TypeScript: <https://skmtc.dev/gc-ai/apis/gc-ai-external-api/docs/playbooks/:id/run/post.ts> (a function with typed inputs; its response is checked against the schema)

Run a playbook against one or more uploaded files and receive structured check results.

<Note>
This endpoint is asynchronous: it returns a job envelope, and the result is filled in once the job completes. See [Asynchronous Requests](https://docs.gc.ai/api-reference/concepts/async-jobs) for how waiting, polling, and the envelope work.
</Note>

Files referenced by `file_ids` must be accessible to the caller and in `ready` status. The playbook must be in `completed` status. Org-scoped keys can run org-visible playbooks against non-access-controlled files.

<Note>
This is an inference endpoint and is [rate limited](https://docs.gc.ai/api-reference/concepts/rate-limits): 60 requests/minute per organization (20 per API key). Exceeding the limit returns `429` with a `Retry-After` header.
</Note>

## Path parameters

- `id` string, uuid, required: Playbook ID from `GET /playbooks`.

## Query parameters

- `wait` integer, nullable: Optional long-poll wait time in seconds. Use `0` for fire-and-forget behavior. If both `wait` and `Prefer: wait=...` are supplied, they must match. Values above 90 are clamped.

## Headers

- `Prefer` string: Optional RFC 7240 wait preference, for example `wait=0`. If both this header and the `wait` query parameter are supplied, they must match.

## Request body

- RunPlaybookRequest
  - `file_ids` string[], required: IDs of uploaded files to review. Files must be in `ready` status. At least one file is required.
  - `review_mode` 'first-party' | 'third-party': Whose perspective the review takes. `third-party` reviews a counterparty document (default); `first-party` reviews your own.
  - `representing_party` string: Name of the party the review represents (default: "our company").
  - `check_ids` string[]: Optional subset of check IDs to evaluate. Omit to run every check in the playbook.
  - `company_id` string, uuid: Optional company profile to ground the review in, so the checks have that company's context (industry, jurisdiction, regulations, risk posture). Discover company profiles via `GET /company-profiles`. Opt-in: supply this to ground the review against a specific company. When omitted, the review runs with no company profile. This is separate from `representing_party`, which stays free text.

## Response `200`

Job completed within the effective wait window

- RunPlaybookResponse
  - `job_id` string, uuid, required: Async job identifier
  - `kind` 'playbooks/run', required: Stable job kind for this endpoint
  - `status` 'pending' | 'running' | 'succeeded' | 'failed' | 'canceled', required: Current job status
  - `result` RunPlaybookResult, nullable, required: Playbook review payload when the job has succeeded
    - `playbookTitle` string, required
    - `totalChecks` number, required
    - `results` PlaybookCheckResult[], required
      - `checkId` string, uuid, required
      - `checkTitle` string, required
      - `evaluationResult` string, required: Evaluation outcome. One of `Pass`, `Flag`, `Fallback`, or `Error`.
      - `documentPosition` number, nullable, required: Position in the document where the matched language was found, or null if not anchored.
    - `summary` object, required
      - `flags` number, required
      - `fallbacks` number, required
      - `passes` number, required
      - `errors` number, required
    - `documents` ApiDocument[]: Redlined documents produced from the review's suggested revisions, applied as tracked changes. Present only when a single DOCX file was reviewed and at least one revision applied. Works with either a user-scoped or an org-scoped key. The original file is preserved; each entry exposes a new `file_id` and a signed download URL.
      - `file_id` string, uuid, required: The new uploaded file ID for the produced document. Use it with `POST /chat/completions` `file_ids` to apply further edits to this version. Download via `signed_url` for the finished file.
      - `original_file_id` string, uuid: The `file_id` the changes were applied to (edits only). The original file is preserved unchanged. Omitted for newly generated documents.
      - `filename` string, required: Filename of the produced document (edits are prefixed with `edited_`).
      - `original_filename` string: Filename of the source file the changes were applied to (edits only). Omitted for newly generated documents.
      - `signed_url` string, uri, required: Time-limited direct download URL (no login required). Valid for 7 days from job completion. Download promptly; the URL is not re-minted, so re-fetching the job after expiry returns the same expired URL. For a link you intend to store or email, use `download_url` instead.
      - `download_url` string, uri, required: Permanent, login-gated download link for the produced document. Unlike `signed_url` it never expires: it points at a GC AI web page that mints a fresh download for a signed-in user with access to the file, and redirects to GC AI login otherwise. Use this for links you store or email. The produced document inherits the source document's access, so it opens for whoever can already see the source: a document uploaded to the organization is org-visible, one in a project is visible to that project's members, and one in personal files stays private to the uploader. Recipients still need a GC AI login.
  - `error` object, nullable, required: Failure payload when the job has failed
    - `code` string, required
    - `message` string, required
  - `created_at` string, required: ISO 8601 creation timestamp
  - `completed_at` string, nullable, required: ISO 8601 completion timestamp, or null when not terminal

## Other responses

- `202`: Job accepted but not yet complete
- `400`: Invalid request body, playbook not ready, or files still extracting
- `401`: Missing or malformed API key
- `403`: Invalid API key
- `404`: Playbook not found, file IDs not found, or the `company_id` was not found
- `422`: One or more files have a permanent extraction failure
- `429`: Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.
- `500`: Internal server error
- `503`: Service temporarily unavailable

---

[API](https://skmtc.dev/gc-ai/apis/gc-ai-external-api.md) - [All operations](https://skmtc.dev/gc-ai/apis/gc-ai-external-api/llms.txt) - [OpenAPI document](https://skmtc.dev/gc-ai/apis/gc-ai-external-api/revisions/2bbdfddf7107?raw)
