> ## Documentation Index
> Fetch the complete documentation index at: https://docs.coderabbit.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Review pull requests with the API

> Find a repository and pull request, request a CodeRabbit review of the current head, follow its status, and read the summary and Change Stack it produced.

Use this recipe to start a CodeRabbit review from a script or an agent, wait for it, and read what it produced.

## Before you start

* You need an API key for a [GitHub Cloud organization](https://docs.coderabbit.ai/api.md#availability); requesting a review needs an agentic key. See [Authentication](https://docs.coderabbit.ai/api/authentication.md#which-keys-each-operation-accepts) for keys and [Conventions](https://docs.coderabbit.ai/api/conventions.md) for base URLs, pagination, errors, and rate limits.
* The curl examples and the Python script read the key from `CODERABBIT_API_KEY` and the API host from `CODERABBIT_API_HOST`, the variables that [Set up your shell](https://docs.coderabbit.ai/api/quickstart.md#set-up-your-shell) sets for your region. The CLI examples use the [`coderabbit api` command](https://docs.coderabbit.ai/api/cli). Each step also names its tool on the [hosted MCP server](https://docs.coderabbit.ai/api/mcp.md).
* The examples use repository ID `123456789` and pull request `42`.

## 1. Find the repository ID

Pull request operations take the repository's numeric GitHub ID, not its name. [List repositories](https://docs.coderabbit.ai/api/reference/list-repositories.md) returns the repositories where CodeRabbit is installed and you have read access on GitHub.

```bash curl theme={null}
curl --get "$CODERABBIT_API_HOST/v1/repositories" \
  --header "x-coderabbitai-api-key: $CODERABBIT_API_KEY" \
  --data-urlencode "page_size=100"
```

```bash CLI theme={null}
coderabbit api repositories list --page-size 100
```

Take the `id` of the repository you want. It's GitHub's numeric repository ID, not the `node_id`. The list has no name filter, so to look up a repository by name, filter the response on `full_name`:

```bash theme={null}
curl --get "$CODERABBIT_API_HOST/v1/repositories" \
  --header "x-coderabbitai-api-key: $CODERABBIT_API_KEY" \
  --data-urlencode "page_size=100" | jq -r '.data[] | select(.full_name == "acme/api") | .id'
```

Trimmed response:

```json Response (trimmed) theme={null}
{
  "data": [
    { "id": "123456789", "full_name": "acme/api", "private": true }
  ],
  "next_page_token": "eyJ2Ijox"
}
```

If the filter prints nothing, the repository isn't on that page: keep following `next_page_token` as described in [Pagination](https://docs.coderabbit.ai/api/conventions.md#pagination). To check a single ID, call [Get a repository](https://docs.coderabbit.ai/api/reference/get-repository.md).

MCP tools: `list_repositories`, `get_repository`.

## 2. Find the pull request

[List pull requests](https://docs.coderabbit.ai/api/reference/list-repository-pull-requests.md) returns open pull requests. Set `state` for closed or merged pull requests, and `head_branch` to find the pull request for a branch; add `head_owner` to tell forks apart.

> [!WARNING]
>
> Without `author`, the list holds only the pull requests opened by the GitHub account linked to the key's owner (`author=me`). Set `author=all` for every author, or a GitHub login for one person.

```bash curl theme={null}
curl --get "$CODERABBIT_API_HOST/v1/repositories/123456789/pull-requests" \
  --header "x-coderabbitai-api-key: $CODERABBIT_API_KEY" \
  --data-urlencode "author=all" \
  --data-urlencode "state=open"
```

```bash CLI theme={null}
coderabbit api pull-requests list 123456789 --author all --state open
```

The list comes from a live GitHub search, so it can change between pages. When `coverage.complete` is `false`, `coverage.limitations` says what the search couldn't cover; narrow the filters and search again.

To read one pull request, call [Get a pull request](https://docs.coderabbit.ai/api/reference/get-repository-pull-request.md) with the repository ID and the pull request's `number`. The `id` field in pull request responses is GitHub's internal ID and doesn't work in paths.

`include` selects the sections to return: `checks` (the default), `threads`, both, or `none`. Review threads default to unresolved threads that CodeRabbit started. Set `thread_author=all`, `thread_state=all`, or `thread_include_outdated=true` to widen that.

```bash curl theme={null}
curl --get "$CODERABBIT_API_HOST/v1/repositories/123456789/pull-requests/42" \
  --header "x-coderabbitai-api-key: $CODERABBIT_API_KEY" \
  --data-urlencode "include=threads" \
  --data-urlencode "thread_state=all"
```

```bash CLI theme={null}
coderabbit api pull-requests get 123456789 42 --include threads --thread-state all
```

Threads page separately from the rest of the response: pass `threads.next_page_token` as `thread_page_token` with the same filters. If the pull request's head commit moves while you page, the API returns `409 head_changed`; start again without the token. A thread's `replies_complete` is `false` when the response holds only part of the replies. To read the whole discussion, call [List all comments in a pull-request review thread](https://docs.coderabbit.ai/api/reference/list-pull-request-review-thread-comments.md) with the thread's `id`: it returns the root comment and every reply, and pages with its own `page_token`, separate from `thread_page_token`.

The `reviews` section shows what GitHub reports. To find out whether CodeRabbit finished reviewing the current head, use the review status in [step 4](#4-follow-the-review-status).

MCP tools: `list_pull_requests`, `get_pull_request`, and `list_pull_request_review_thread_comments`. `list_pull_requests` and `get_pull_request` take GitHub URLs instead of a repository ID and pull request number. `list_pull_request_review_thread_comments` takes the repository ID, the pull request number, and the thread's `id`, as the API does.

## 3. Request a review

[Request a review](https://docs.coderabbit.ai/api/reference/request-pull-request-review.md) asks CodeRabbit to review the pull request's current head. The pull request must be open.

```bash curl theme={null}
curl "$CODERABBIT_API_HOST/v1/repositories/123456789/pull-requests/42/review" \
  --header "x-coderabbitai-api-key: $CODERABBIT_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{}'
```

```bash CLI theme={null}
coderabbit api request -X POST /repositories/123456789/pull-requests/42/review
```

A `202` response means CodeRabbit accepted the request, not that the review finished. `observed_head_sha` is the pull request's head when you sent the request. CodeRabbit handles the request like a new push to the pull request and reviews whatever the head is when the review starts.

The API can't review an older commit or cancel a review.

MCP tool: `request_pull_request_review`. The connection needs the `reviews:write` scope; the `review` scope for local reviews doesn't include it.

## 4. Follow the review status

[Get review status](https://docs.coderabbit.ai/api/reference/get-pull-request-review.md) returns the pull request's current head and CodeRabbit's latest review status for it. It's the status that [Triage](https://docs.coderabbit.ai/triage.md) shows, but it doesn't depend on anyone using Triage: CodeRabbit records it as pull request events arrive.

```bash curl theme={null}
curl "$CODERABBIT_API_HOST/v1/repositories/123456789/pull-requests/42/review" \
  --header "x-coderabbitai-api-key: $CODERABBIT_API_KEY"
```

```bash CLI theme={null}
coderabbit api pull-requests review-status 123456789 42
```

```json Response (trimmed) theme={null}
{
  "head_sha": "9a1d3c7e5b2f4a6c8d0e1f2a3b4c5d6e7f8a9b0c",
  "review": {
    "status": "reviewing",
    "reason": null,
    "target_commit_sha": "9a1d3c7e5b2f4a6c8d0e1f2a3b4c5d6e7f8a9b0c",
    "updated_at": "2026-11-10T14:03:12.000Z"
  }
}
```

| `status` | What it means |
| - | - |
| `pending` | The review hasn't started. When `reason` is set, it says why CodeRabbit is waiting or skipped the review, for example `draft_pull_request` or `automatic_review_disabled`. |
| `starting` | CodeRabbit is preparing the review. |
| `reviewing` | The review is running. |
| `completed` | The review of `target_commit_sha` finished. |
| `failed` | The review didn't finish. `reason` can say why. |
| `unconfirmed` | A `starting` or `reviewing` review hasn't reported progress recently. It can still be running. |

Read the response with these rules:

* The current head is reviewed when `status` is `completed` and `target_commit_sha` equals `head_sha`.
* `completed` doesn't tell you what CodeRabbit posted. Read the summary in [step 5](#5-read-the-summary) and the review threads from [step 2](#2-find-the-pull-request).
* `review: null` means CodeRabbit has no status for the pull request's current commit, for example because it hasn't recorded the pull request yet or because the last status belongs to an older commit. It doesn't prove that no review ran.
* `updated_at` is when the status last changed, not when you read it.

Poll about once a minute; each call counts toward your [rate limit](https://docs.coderabbit.ai/api/conventions.md#rate-limits). This loop waits until the current head is reviewed or the review fails:

```bash theme={null}
while :; do
  RESPONSE=$(coderabbit api pull-requests review-status 123456789 42)
  STATUS=$(jq -r '.review.status // "none"' <<<"$RESPONSE")
  CURRENT=$(jq -r '.review.target_commit_sha == .head_sha' <<<"$RESPONSE")
  echo "status: $STATUS"
  if [ "$STATUS" = completed ] && [ "$CURRENT" = true ]; then break; fi
  if [ "$STATUS" = failed ]; then exit 1; fi
  sleep 60
done
```

MCP tool: `get_pull_request_review`.

## 5. Read the summary

[Get the review summary](https://docs.coderabbit.ai/api/reference/get-pull-request-review-summary.md) returns CodeRabbit's latest summary comment on the pull request, the comment that carries the [walkthrough](https://docs.coderabbit.ai/pr-reviews/walkthroughs.md). `summary.body_markdown` holds its Markdown without the hidden markers, and `summary.source_url` links to the comment on GitHub.

```bash curl theme={null}
curl "$CODERABBIT_API_HOST/v1/repositories/123456789/pull-requests/42/review/summary" \
  --header "x-coderabbitai-api-key: $CODERABBIT_API_KEY"
```

```bash CLI theme={null}
coderabbit api request /repositories/123456789/pull-requests/42/review/summary
```

`summary: null` means CodeRabbit hasn't posted a summary comment. `summary.reviewed_commit_sha` is `null` when the commit the summary describes is unknown, so use [step 4](#4-follow-the-review-status) to check that the review covers the current head.

MCP tool: `get_pull_request_review_summary`.

## 6. Read the Change Stack

[Get the Change Stack](https://docs.coderabbit.ai/api/reference/get-pull-request-change-stack.md) returns the latest saved [Change Stack](https://docs.coderabbit.ai/change-stack.md) for the pull request: its title and summary, `groups` of ordered `layers`, each layer's files, line ranges, dependencies (`depends_on`), and Mermaid diagrams. The call never builds a Change Stack; `artifact: null` means none is saved.

```bash curl theme={null}
curl "$CODERABBIT_API_HOST/v1/repositories/123456789/pull-requests/42/change-stack" \
  --header "x-coderabbitai-api-key: $CODERABBIT_API_KEY"
```

```bash CLI theme={null}
coderabbit api request /repositories/123456789/pull-requests/42/change-stack
```

Check these fields of `artifact` before you use it:

| Field | What it tells you |
| - | - |
| `snapshot_id` | The saved version you're reading. Pass it to the layer diff, or back to this call to read the same version again. |
| `reviewed_head_sha` | The commit the Change Stack describes. |
| `freshness` | `current` when `reviewed_head_sha` is the pull request's head, `outdated` when the head has moved since, and `unknown` when the reviewed commit isn't recorded. |
| `coverage` | `unassigned_ranges` and `excluded_files` list changes that no layer covers. |

An outdated Change Stack stays readable. See [Snapshots and freshness](https://docs.coderabbit.ai/change-stack/snapshots.md) for how versions relate to the live pull request.

MCP tool: `get_pull_request_change_stack`.

## 7. Read a layer's diff

[Get a layer's diff](https://docs.coderabbit.ai/api/reference/get-pull-request-change-stack-layer-diff.md) returns unified patches for the files in one layer. Use the `snapshot_id`, the group `id`, and the layer `id` from the same Change Stack response. Layer IDs are unique only within their group. For example, to pick the first layer of the first group:

```bash theme={null}
coderabbit api request /repositories/123456789/pull-requests/42/change-stack > change-stack.json
SNAPSHOT_ID=$(jq -r '.artifact.snapshot_id' change-stack.json)
GROUP_ID=$(jq -r '.artifact.groups[0].id' change-stack.json)
LAYER_ID=$(jq -r '.artifact.groups[0].layers[0].id' change-stack.json)
```

```bash curl theme={null}
curl --get "$CODERABBIT_API_HOST/v1/repositories/123456789/pull-requests/42/change-stack/groups/$GROUP_ID/layers/$LAYER_ID/diff" \
  --header "x-coderabbitai-api-key: $CODERABBIT_API_KEY" \
  --data-urlencode "snapshot_id=$SNAPSHOT_ID"
```

```bash CLI theme={null}
coderabbit api request "/repositories/123456789/pull-requests/42/change-stack/groups/$GROUP_ID/layers/$LAYER_ID/diff?snapshot_id=$SNAPSHOT_ID"
```

URL-encode the IDs if they contain reserved characters. Each file in `data` has an `availability`: `available` files carry a `patch`, and `unavailable` files are ones GitHub couldn't supply a patch for, not empty diffs. Add `path` to get one file of the layer. Results page by file, 50 files per page by default.

If the snapshot is gone or doesn't record its commits, the call returns `404 not_found`; it doesn't fall back to a newer Change Stack. Read the Change Stack again for a current `snapshot_id`.

MCP tool: `get_pull_request_change_stack_layer_diff`.

## Check every open pull request

This Python script combines steps 2 and 4: it lists every open pull request in a repository and reports whether CodeRabbit finished reviewing each one's current head, and why not when it hasn't. It needs the [`requests`](https://pypi.org/project/requests/) package and reads the key and host from `CODERABBIT_API_KEY` and `CODERABBIT_API_HOST`. Set `CODERABBIT_API_HOST` to the host of your region, without `/v1`; see [Base URLs and regions](https://docs.coderabbit.ai/api/conventions.md#base-urls-and-regions).

```python check_reviews.py theme={null}
import os
import time

import requests

API_HOST = os.environ["CODERABBIT_API_HOST"]
REPOSITORY_ID = "123456789"
session = requests.Session()
session.headers["x-coderabbitai-api-key"] = os.environ["CODERABBIT_API_KEY"]


def get(path, params=None):
    while True:
        response = session.get(f"{API_HOST}/v1{path}", params=params, timeout=60)
        if response.status_code == 403:
            raise SystemExit(f"403 forbidden: {response.text}")
        if response.status_code != 429:
            response.raise_for_status()
            return response.json()
        time.sleep(int(response.headers.get("Retry-After", "60")))


pulls = f"/repositories/{REPOSITORY_ID}/pull-requests"
params = {"author": "all", "state": "open", "page_size": 100}
open_pull_requests = {}
while True:
    page = get(pulls, params)
    open_pull_requests.update((pr["number"], pr) for pr in page["data"])
    if page["next_page_token"] is None:
        break
    params["page_token"] = page["next_page_token"]

for number, pull_request in open_pull_requests.items():
    status = get(f"{pulls}/{number}/review")
    review = status["review"]
    if review is None:
        verdict = "no status for the current head (not recorded yet, or the last status is for an older commit)"
    elif review["status"] == "completed":
        reviewed = review["target_commit_sha"] == status["head_sha"]
        verdict = "reviewed" if reviewed else "completed an older commit"
    elif review["status"] == "failed":
        verdict = f"failed ({review['reason']})"
    else:
        verdict = f"in progress or waiting ({review['status']}, reason: {review['reason']})"
    print(number, verdict, pull_request["title"], sep=" | ")
```

A `403` stops the script and prints the error, because retrying can't fix a key that the operation doesn't accept. The script collects every page before it reads any status, so page tokens don't expire while it works, and it keys pull requests by number because a live listing can repeat one. Each status read counts toward your [rate limit](https://docs.coderabbit.ai/api/conventions.md#rate-limits): on a repository with many open pull requests, the script pauses at each `429` for the time in `Retry-After`, then sends the same request again.

## Handle errors

All errors in this flow use the error format described in [Errors](https://docs.coderabbit.ai/api/conventions.md#errors). The common ones:

| Response | Likely cause | What to do |
| - | - | - |
| `403 forbidden` | The key's type isn't accepted for the operation (a review request needs an agentic key whose owner holds a seat), the key owner's role lacks the permission, or the owner can't access the repository. | Check the key type and its owner's role and access; see [Which keys each operation accepts](https://docs.coderabbit.ai/api/authentication.md#which-keys-each-operation-accepts) and [Errors](https://docs.coderabbit.ai/api/conventions.md#errors) for the codes. |
| `insufficient_scope` (MCP) | The MCP connection lacks the scope that the error names, such as `reviews:write`. | Add the scope; see [MCP troubleshooting](https://docs.coderabbit.ai/api/mcp.md#troubleshooting). |
| `400 invalid_request` | The pull request isn't open, or a page token expired or doesn't match the request. | Request reviews only for open pull requests. Restart a listing without a page token. |
| `404 not_found` | CodeRabbit isn't installed on the repository, you can't read it, the pull request number doesn't exist, or a Change Stack snapshot is gone. | Check the IDs from steps 1 and 2. Read the Change Stack again for a new snapshot. |
| `409 head_changed` | The head commit moved while you paged review threads. | Read the pull request again without `thread_page_token`. |
| `429 rate_limit_exceeded` | You sent too many requests. | Wait for the time in `Retry-After`, then poll less often. |

## What's next

> [card] [Run coding tasks](https://docs.coderabbit.ai/api/guides/coding-tasks.md)
>
> Create a Coding Agent task, review its plan, and deliver its patch through the API.

> [card] [Connect an MCP client](https://docs.coderabbit.ai/api/mcp.md)
>
> Connect an AI agent to CodeRabbit and call these operations as MCP tools.

> [card] [Handle responses](https://docs.coderabbit.ai/api/conventions.md)
>
> Look up base URLs, pagination, error formats, and rate limits for every operation.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.