
Create an Origin Pull Request Comment via the API
Post a comment on a pull request with POST https://api.cursor.com/v1/origin/repos/{ownerSlug}/{repoName}/pulls/{pullNumber}/comments. Official reference: Origin API → Create Pull Request Comment (OpenAPI OriginService_CreatePullRequestComment). Changelog notes: September 9, 2026 (inline range past end of file → InvalidArgument), September 2, 2026 (file anchor for whole-file threads), August 29, 2026 (inline + versionNumber), August 24, 2026 (body length cap).
Origin is in Early Beta and subject to change. Authenticate with an installation access token (oit_…) or a user access token that carries repository:pull_requests:reviews:write. Availability: Early Beta per the API overview.
The comment targets exactly one of: an existing thread (threadId — a reply on general-discussion and inline threads alike), a new inline thread on the version's diff (inline), a new file-level thread (file), or, with none of those, a new general-discussion thread. file, inline, and threadId are mutually exclusive. Pull request number is a JSON string (protobuf 64-bit encoding).
Cost: 5 points against the principal budget (ordinary write).
Path parameters
| Param | Required | Meaning |
|---|---|---|
ownerSlug |
yes | Owning entity's unique slug |
repoName |
yes | Repo name, unique to the owner |
pullNumber |
yes | Pull request number within the repository (string on the wire) |
Request body
| Field | Required | Meaning |
|---|---|---|
body |
yes | Comment text; max 65,536 Unicode code points |
threadId |
no | Existing thread id to reply to. Cannot be combined with versionNumber |
inline |
no | Diff anchor for a new inline thread (path, side, startLine, optional endLine) |
file |
no | Anchor for a new file-level thread (path only; side derived from change kind) |
versionNumber |
no | Pull request version to file a new thread against. 0 or unset = latest at call time. Only for new threads; rejected with threadId |
Inline anchor (inline)
| Field | Required | Meaning |
|---|---|---|
path |
yes | File path in the pull request version's diff |
side |
yes | left (base) or right (head) |
startLine |
yes | First 1-based line on that side |
endLine |
no | Inclusive last line; omit for a single-line anchor; must be ≥ startLine |
The path must be part of that version's diff on a side the file has content on — left on an added file or right on a deleted file returns InvalidArgument (HTTP 400). Any line of a changed file can anchor (including outside hunks), but the range must fit the file on the anchored side (left at base, right at head). A range past the last line returns InvalidArgument (HTTP 400). Invalid anchors never fall back to a general-discussion comment.
File anchor (file)
| Field | Required | Meaning |
|---|---|---|
path |
yes | Deleted path for a deletion; head path otherwise. Pre-rename source path on a rename is rejected |
Origin sets thread.side from the change kind (base for deletions, head otherwise). A path outside the diff returns InvalidArgument (HTTP 400).
A body longer than 65,536 code points returns InvalidArgument (HTTP 400). A missing or unreachable pull returns 404. A 404 never distinguishes a missing pull from one your installation cannot reach.
curl --request POST \
--url 'https://api.cursor.com/v1/origin/repos/OWNER_SLUG/REPO_NAME/pulls/17/comments' \
--header 'Authorization: Bearer YOUR_ORIGIN_TOKEN' \
--header 'Content-Type: application/json' \
--data '{
"body": "Should the retry budget be configurable?"
}'
Inline thread on a line range:
curl --request POST \
--url 'https://api.cursor.com/v1/origin/repos/OWNER_SLUG/REPO_NAME/pulls/17/comments' \
--header 'Authorization: Bearer YOUR_ORIGIN_TOKEN' \
--header 'Content-Type: application/json' \
--data '{
"body": "Should the retry budget be configurable?",
"inline": {
"path": "src/telemetry/retry.ts",
"side": "right",
"startLine": 42,
"endLine": 45
},
"versionNumber": "3"
}'
File-level thread:
curl --request POST \
--url 'https://api.cursor.com/v1/origin/repos/OWNER_SLUG/REPO_NAME/pulls/17/comments' \
--header 'Authorization: Bearer YOUR_ORIGIN_TOKEN' \
--header 'Content-Type: application/json' \
--data '{
"body": "This module needs a design doc link.",
"file": {
"path": "src/telemetry/retry.ts"
},
"versionNumber": "3"
}'
Reply to an existing thread:
curl --request POST \
--url 'https://api.cursor.com/v1/origin/repos/OWNER_SLUG/REPO_NAME/pulls/17/comments' \
--header 'Authorization: Bearer YOUR_ORIGIN_TOKEN' \
--header 'Content-Type: application/json' \
--data '{
"body": "Agreed — make it configurable.",
"threadId": "cth_01k2ja2000e0080000000000s6"
}'
Response
200 returns a PullRequestComment: id, nested thread, body, author, createdAt, updatedAt. A reply may carry the thread id alone; a new general-discussion thread carries id and timestamps; a new inline thread carries the full anchor. Read Get or List Pull Request Comments for complete thread state including resolvedAt.
{
"id": "cmt_01k2ja2000e0080000000000e5",
"thread": {
"id": "cth_01k2ja2000e0080000000000s6",
"version": {
"number": "3",
"headSha": "9a41f0c3d2b8e7f6a5c4d3e2f1b0a9c8d7e6f5a4",
"baseSha": "3b1f9c2d8a7e6f5049c8b7a6d5e4f3a2b1c0d9e8",
"createdAt": "2026-08-01T09:30:00Z"
},
"path": "src/telemetry/retry.ts",
"side": "right",
"startLine": 42,
"endLine": 45,
"createdAt": "2026-08-01T09:30:00Z",
"updatedAt": "2026-08-02T14:45:00Z"
},
"body": "Should the retry budget be configurable?",
"author": {
"user": {
"id": "user_01k2ja2000e0080000000000c3",
"email": "jane@acme.dev"
}
},
"createdAt": "2026-08-01T09:30:00Z",
"updatedAt": "2026-08-02T14:45:00Z"
}
Resolve or reopen the thread with Update Pull Request Thread. Base URL: https://api.cursor.com/v1/origin.