Skip to content
GitmoapAPIBeta
Planissue-criteria
PATCH/repositories/{repo_id}/issues/{issue_id}/criteria/{criterion_id}

Edit an acceptance criterion

update_issue_criterion
  • issue:update
    A token needs the issue:update scope: Update work items — status, fields, hierarchyGranted by mcp_agent_write, write_api, write_repository.Every operation this scope unlocks
  • Audited · mutation

    x-gitmoap-audit: {"kind":"audited","arg":"mutation"}

  • Quota · criteria per repo

    x-gitmoap-quota: {"kind":"enforced","arg":"criteria_per_repo"}

Changes a criterion's text, description, binding, position, whether it is required to close, or its tick; only the fields you send change, and a null binding makes it manual again. A new binding resets the evidence gathered so far unless the issue settings say to keep it, and a bound criterion cannot be ticked by hand. Developers and above may edit criteria; giving one a binding counts against the repository's limit on bound criteria.

Parameters

Path
  • repo_idRepositoryId (string · uuid)Repository ID
  • issue_idIssueId (integer · int64)Work-item iid
  • criterion_idCriterionId (string · uuid)Criterion ID

Request body

application/json
  • bindingCriterionBinding or nulloptional{"binding": {...}} re-binds it and resets its evidence, {"binding": null} turns it into a manual checkbox, and omitting the key leaves the binding untouched.
  • checkedboolean or nulloptionalTick or untick a manual criterion. Refused with a 409 for a bound one, whose state comes from its evidence.
  • descriptionstring or nulloptional
  • ordinalinteger · int32 or nulloptional0–∞
  • required_for_closeboolean or nulloptional
  • textstring or nulloptional
Request body exampleSynthesized example
{}

Responses

200The updated criterion. Changing the binding resets the criterion's evidenceapplication/json
  • created_atstring
  • criterion_idCriterionId (string · uuid)The criterion's identifier. It never changes, so rewording or re-binding a criterion keeps its identity and its evidence.
  • issue_uidIssueUid (string · uuid)
  • satisfiedboolean
  • stateCriterionStateunverifiedpassingfailingstalemanualA criterion's verdict.
  • textstringThe human statement — the criterion's title. The label, not the identity.
  • updated_atstring
  • bindingCriterionBinding or nulloptional
  • binding_exprstring or nulloptionalThe binding's @-expression, as written. Absent for a manual criterion.
  • binding_keystring or nulloptionalThe normalised form of binding_expr, which two equivalent spellings share. Absent for a manual criterion.
  • checkedbooleanoptionalWhether the box is ticked. Meaningful only for a manual criterion — a bound one is ticked by its state, and ticking it by hand is refused with a 409.
  • descriptionstring or nulloptionalAn optional longer description (markdown) — the per-criterion detail a flat checkbox could never hold.
  • evidenceEvidence or nulloptional
    • The Evidence schema
    • commit_shaCommitHash (string)
    • observed_atstringWhen the run that produced the evidence finished, RFC 3339.
    • pipeline_idPipelineId (string · uuid)
    • pipeline_run_idPipelineRunId (string · uuid)
    • node_run_idNodeRunId (string · uuid) or nulloptional
    • valuenumber · double or nulloptional
  • facet_categoryFacetCategory (string) or nulloptional
  • facet_keyFacetKey (string) or nulloptionalThe blueprint facet this criterion belongs to, when a blueprint added it. Absent for a criterion written directly. A facet's state is rolled up from the criteria carrying its key.
  • last_evidence_atstring or nulloptional
  • last_evidence_commit_shaCommitHash (string) or nulloptional
  • last_evidence_node_run_idNodeRunId (string · uuid) or nulloptional
  • last_evidence_pipeline_idPipelineId (string · uuid) or nulloptionalThe pipeline whose run last provided evidence for this criterion. Only a later run of the same pipeline can make the criterion stale.
  • last_evidence_run_idPipelineRunId (string · uuid) or nulloptional
  • last_evidence_valuenumber · double or nulloptionalThe observed value, for a Metric or Coverage binding.
  • ordinalinteger · int32optional0–∞Position in the description, so the list round-trips in authoring order.
  • required_for_closebooleanoptional@optional opts out. Everything else in a Definition of Done is required by definition.
200 exampleSynthesized example
{
"created_at": "2026-10-12T09:36:41Z",
"criterion_id": "dad175da-9686-4f61-9d25-085b5d0f53c8",
"issue_uid": "cb6f31d8-cbb5-436f-a54e-d115b77e330c",
"satisfied": false,
"state": "unverified",
"text": "text-95f7",
"updated_at": "2026-10-17T08:53:12Z",
"binding": {
"kind": "test",
"test_id": "f780eee8-721d-44df-b5a6-fc5c55dec320",
"suite": "suite-b122"
},
"binding_expr": "binding-expr-36ab",
"binding_key": "binding-key-a382",
"checked": false,
"description": "Renders each region as density contours of its operations.",
"evidence": {
"commit_sha": "5c7e3ced392a7e4dda299785b6d763359738ea43",
"observed_at": "2026-10-11T06:43:24Z",
"pipeline_id": "7caa491c-affb-4f8f-bd9f-a9677f4b09e2",
"pipeline_run_id": "9e2b7c41-3d5a-4f8e-b1c2-7a6d5e4f3c2b",
"node_run_id": "547b33fb-d3b8-4704-a451-ae90850d5b18",
"value": 3
},
"facet_category": "facet-category-7415",
"facet_key": "facet-key-4b71",
"last_evidence_at": "2026-10-17T08:27:53Z",
"last_evidence_commit_sha": "93ec118119f3e38e1641f4e2cb98ec3509796237",
"last_evidence_node_run_id": "def9ddec-55ab-4824-99c9-652527b678cc",
"last_evidence_pipeline_id": "c7a69cb0-4510-40f9-b740-f2710c296fb7",
"last_evidence_run_id": "9e2b7c41-3d5a-4f8e-b1c2-7a6d5e4f3c2b",
"last_evidence_value": 48,
"ordinal": 2,
"required_for_close": false
}
400The text is empty or too long, or the binding's arguments do not validateapplication/json
Error codes
  • BAD_REQUESTThe request is malformed: a parameter or a body field is not a well-formed value of its type
  • errorErrorBody
    • The ErrorBody schema
    • codestringThe coarse category, tied to the status: NOT_FOUND, CONFLICT, INSUFFICIENT_SCOPE. Every error has one; the API reference's error catalogue lists them all.
    • messagestringWhat went wrong, for a person. Written to be read, not parsed: match on reason or code.
    • fieldstring or nulloptionalOn a 400 that refused one field's value, the field, as its JSON path: email, items[0].name. Put the message under that input. Absent on every other error.
    • reasonstring or nulloptionalThe specific code, when the error has one: LAST_ORGANIZATION_OWNER, BRANCH_PROTECTED. The message starts with it too. Match on this when it is present, and on code otherwise.
    • required_scopestring or nulloptionalThe scope the access token was missing, on INSUFFICIENT_SCOPE.
    • violationsanyoptionalPresent on the structured-validation errors (PROVIDER_VALIDATION_FAILED per-node, PIPELINE_VALIDATION_FAILED DAG): a JSON array of the offending elements, so a caller can fix every one in a single round-trip. Absent (omitted) on every other error.
400 exampleSynthesized example
{
"error": {
"code": "code-05ca",
"message": "Pin a page's payload to the build that rendered it"
}
}
401Unauthenticated — no credential, or an invalid oneapplication/json
Error codes
  • UNAUTHORIZEDNo credential was sent, or the one sent is invalid, expired or revoked
  • errorErrorBody
    • The ErrorBody schema
    • codestringThe coarse category, tied to the status: NOT_FOUND, CONFLICT, INSUFFICIENT_SCOPE. Every error has one; the API reference's error catalogue lists them all.
    • messagestringWhat went wrong, for a person. Written to be read, not parsed: match on reason or code.
    • fieldstring or nulloptionalOn a 400 that refused one field's value, the field, as its JSON path: email, items[0].name. Put the message under that input. Absent on every other error.
    • reasonstring or nulloptionalThe specific code, when the error has one: LAST_ORGANIZATION_OWNER, BRANCH_PROTECTED. The message starts with it too. Match on this when it is present, and on code otherwise.
    • required_scopestring or nulloptionalThe scope the access token was missing, on INSUFFICIENT_SCOPE.
    • violationsanyoptionalPresent on the structured-validation errors (PROVIDER_VALIDATION_FAILED per-node, PIPELINE_VALIDATION_FAILED DAG): a JSON array of the offending elements, so a caller can fix every one in a single round-trip. Absent (omitted) on every other error.
401 exampleSynthesized example
{
"error": {
"code": "code-3a80",
"message": "Stream pipeline status into the run header"
}
}
403Forbidden — the caller's access level or token scope is insufficientapplication/json
Error codes
  • FORBIDDENYou are signed in but may not do this here; reason names the permission or the rule that refused it
  • INSUFFICIENT_SCOPEThe access token lacks the scope this operation needs; required_scope names it
  • PERMISSION_REQUIREDYou need a permission you do not hold here; the message names it
  • errorErrorBody
    • The ErrorBody schema
    • codestringThe coarse category, tied to the status: NOT_FOUND, CONFLICT, INSUFFICIENT_SCOPE. Every error has one; the API reference's error catalogue lists them all.
    • messagestringWhat went wrong, for a person. Written to be read, not parsed: match on reason or code.
    • fieldstring or nulloptionalOn a 400 that refused one field's value, the field, as its JSON path: email, items[0].name. Put the message under that input. Absent on every other error.
    • reasonstring or nulloptionalThe specific code, when the error has one: LAST_ORGANIZATION_OWNER, BRANCH_PROTECTED. The message starts with it too. Match on this when it is present, and on code otherwise.
    • required_scopestring or nulloptionalThe scope the access token was missing, on INSUFFICIENT_SCOPE.
    • violationsanyoptionalPresent on the structured-validation errors (PROVIDER_VALIDATION_FAILED per-node, PIPELINE_VALIDATION_FAILED DAG): a JSON array of the offending elements, so a caller can fix every one in a single round-trip. Absent (omitted) on every other error.
403 exampleSynthesized example
{
"error": {
"code": "code-9e1e",
"message": "Stream pipeline status into the run header"
}
}
404Work item or criterion not foundapplication/json
Error codes
  • NOT_FOUNDThe resource does not exist — or exists and you cannot see it: a private resource you have no access to answers exactly as an absent one does
  • errorErrorBody
    • The ErrorBody schema
    • codestringThe coarse category, tied to the status: NOT_FOUND, CONFLICT, INSUFFICIENT_SCOPE. Every error has one; the API reference's error catalogue lists them all.
    • messagestringWhat went wrong, for a person. Written to be read, not parsed: match on reason or code.
    • fieldstring or nulloptionalOn a 400 that refused one field's value, the field, as its JSON path: email, items[0].name. Put the message under that input. Absent on every other error.
    • reasonstring or nulloptionalThe specific code, when the error has one: LAST_ORGANIZATION_OWNER, BRANCH_PROTECTED. The message starts with it too. Match on this when it is present, and on code otherwise.
    • required_scopestring or nulloptionalThe scope the access token was missing, on INSUFFICIENT_SCOPE.
    • violationsanyoptionalPresent on the structured-validation errors (PROVIDER_VALIDATION_FAILED per-node, PIPELINE_VALIDATION_FAILED DAG): a JSON array of the offending elements, so a caller can fix every one in a single round-trip. Absent (omitted) on every other error.
404 exampleSynthesized example
{
"error": {
"code": "code-3f46",
"message": "Pin a page's payload to the build that rendered it"
}
}
409A bound criterion cannot be ticked by hand; unbind it firstapplication/json
Error codes
  • CONFLICTThe request conflicts with the resource's current state; reason says how
  • CRITERION_IS_BOUNDThe criterion is bound to evidence a pipeline produces, so it cannot be ticked by hand; unbind it first
  • LEGAL_ACCEPTANCE_REQUIREDAccept the current Terms of Service before changing anything; reading stays open
  • errorErrorBody
    • The ErrorBody schema
    • codestringThe coarse category, tied to the status: NOT_FOUND, CONFLICT, INSUFFICIENT_SCOPE. Every error has one; the API reference's error catalogue lists them all.
    • messagestringWhat went wrong, for a person. Written to be read, not parsed: match on reason or code.
    • fieldstring or nulloptionalOn a 400 that refused one field's value, the field, as its JSON path: email, items[0].name. Put the message under that input. Absent on every other error.
    • reasonstring or nulloptionalThe specific code, when the error has one: LAST_ORGANIZATION_OWNER, BRANCH_PROTECTED. The message starts with it too. Match on this when it is present, and on code otherwise.
    • required_scopestring or nulloptionalThe scope the access token was missing, on INSUFFICIENT_SCOPE.
    • violationsanyoptionalPresent on the structured-validation errors (PROVIDER_VALIDATION_FAILED per-node, PIPELINE_VALIDATION_FAILED DAG): a JSON array of the offending elements, so a caller can fix every one in a single round-trip. Absent (omitted) on every other error.
409 exampleSynthesized example
{
"error": {
"code": "code-3390",
"message": "Draw the region map from operation density"
}
}
429Bound-criterion limit reached for this repositoryapplication/json
Error codes
  • TOO_MANY_REQUESTSRetryableA quota, a rate limit or a transfer budget is spent. When the response carries Retry-After, retry after that many seconds
  • errorErrorBody
    • The ErrorBody schema
    • codestringThe coarse category, tied to the status: NOT_FOUND, CONFLICT, INSUFFICIENT_SCOPE. Every error has one; the API reference's error catalogue lists them all.
    • messagestringWhat went wrong, for a person. Written to be read, not parsed: match on reason or code.
    • fieldstring or nulloptionalOn a 400 that refused one field's value, the field, as its JSON path: email, items[0].name. Put the message under that input. Absent on every other error.
    • reasonstring or nulloptionalThe specific code, when the error has one: LAST_ORGANIZATION_OWNER, BRANCH_PROTECTED. The message starts with it too. Match on this when it is present, and on code otherwise.
    • required_scopestring or nulloptionalThe scope the access token was missing, on INSUFFICIENT_SCOPE.
    • violationsanyoptionalPresent on the structured-validation errors (PROVIDER_VALIDATION_FAILED per-node, PIPELINE_VALIDATION_FAILED DAG): a JSON array of the offending elements, so a caller can fix every one in a single round-trip. Absent (omitted) on every other error.
429 exampleSynthesized example
{
"error": {
"code": "code-0f32",
"message": "Inline scalar newtypes but keep their brand"
}
}

CLI

gitmoap issue-criteria update

  • --repo-ididRepository ID (id or owner/repo path)
  • --issue-ididWork-item iid
  • --criterion-ididCriterion ID
  • --bindingjsonoptional
  • --checkedflagoptionalTick or untick a manual criterion. Refused with a `409` for a bound one, whose state comes from its evidence.
  • --descriptionstringoptional
  • --ordinalnumberoptional
  • --required-for-closeflagoptional
  • --textstringoptional

Used in these guides