API / read-origin-check-run-upsert-outcome-via-api

API

Read Origin Check Run Upsert Outcome via the API

Every Post Check Run and Batch Upsert Check Runs response now pairs each stored run with an outcome so you can tell a create from an update from a no-op. Official reference: Origin API → Check runs / Ordering writes. Changelog: September 22, 2026.

Origin is in Early Beta and subject to change. Authenticate with an installation access token (oit_…) that carries repository:checks:write. Availability: Early Beta per the API overview.

A stale post still returns HTTP 200 with the stored suite and run — not the posted values — and does not move updatedAt. Only outcome (or each results[].outcome in a batch) tells you what happened.

outcome Meaning
created No run existed for (externalId, key) in the suite; one was created
updated An existing run was replaced with the posted values
unchanged Posted values, externalUpdatedAt included, equal the stored run; nothing written
ignored_stale Post ignored as stale; checkRun is the stored run, not the posted values

Treat an unrecognized value as "the stored run is in the response; whether it was written is unknown."

Post Check Run

POST https://api.cursor.com/v1/origin/repos/{ownerSlug}/{repoName}/check-runs returns checkSuite, checkRun, and top-level outcome.

curl --request POST \
  --url 'https://api.cursor.com/v1/origin/repos/OWNER_SLUG/REPO_NAME/check-runs' \
  --header 'Authorization: Bearer oit_...' \
  --header 'Content-Type: application/json' \
  --data '{
  "headSha": "9a41f0c3d2b8e7f6a5c4d3e2f1b0a9c8d7e6f5a4",
  "checkSuite": { "key": "ci-8842", "name": "CI" },
  "checkRun": {
    "key": "ci-8842-unit-tests",
    "name": "unit-tests",
    "status": "completed",
    "conclusion": "success",
    "externalUpdatedAt": "2026-08-02T14:44:30Z",
    "externalId": "run-8842"
  }
}'

Read outcome next to checkRun on every response.

Batch Upsert Check Runs

POST …/check-runs:batchUpsert returns results[], one entry per posted run in request order. Each entry pairs checkRun with its own outcome. A stale run does not fail the batch.

Deprecated: top-level checkRuns[] is still populated with the same stored runs in the same order, but it carries no outcomes. Migrate to results[].

Annotation message fields may contain Markdown (rendered on the pull request Checks tab and inline card). rawDetails stays plain text.

Related

Pitfalls

  • Do not branch on updatedAt to detect a no-op — it stays put for unchanged and ignored_stale.
  • Keep sending increasing externalUpdatedAt values so retries do not land as ignored_stale.