Distinguishing Rejected Jobs in GitHub Repository Webhooks

When configuring a webhook for a GitHub repository—specifically for the workflow_job event—it can be challenging to determine whether a given delivery corresponds to a rejected workflow job.
Rejected jobs refer to those that were not approved by a required reviewer, typically for deployments targeting a protected environment.


To identify a rejected job, let’s examine a delivery triggered by the workflow_job.completed event. We’ll focus on the workflow_job payload and highlight the key attributes that signal a rejection. Here’s an example payload from a workflow_job.completed webhook event:

"action": "completed",
  "workflow_job": {
    "id": 41511799280,
    "run_id": 14785014731,
    "workflow_name": "Get workflow runs details from current repository",
    "head_branch": "main",
    "run_url": "https://api.github.com/repos/andreypicado506/get-wf-details/actions/runs/14785014731",
    "run_attempt": 1,
    "node_id": "CR_kwDONkcfGM8AAAAJqkvJ8A",
    "head_sha": "520405cec8339c7806e42797cf03b15b4d355c86",
    "url": "https://api.github.com/repos/andreypicado506/get-wf-details/actions/jobs/41511799280",
    "html_url": "https://github.com/andreypicado506/get-wf-details/actions/runs/14785014731/job/41511799280",
    "status": "completed",
    "conclusion": "success",
    "created_at": "2025-05-01T22:55:42Z",
    "started_at": "2025-05-01T22:55:48Z",
    "completed_at": "2025-05-01T22:55:51Z",
    "name": "comment",
    "steps": [
      {
        "name": "Set up job",
        "status": "completed",
        "conclusion": "success",
        "number": 1,
        "started_at": "2025-05-01T22:55:48Z",
        "completed_at": "2025-05-01T22:55:48Z"
      },
      {
        "name": "Run actions/checkout@v4",
        "status": "completed",
        "conclusion": "success",
        "number": 2,
        "started_at": "2025-05-01T22:55:48Z",
        "completed_at": "2025-05-01T22:55:49Z"
      },
      {
        "name": "Run actions/github-script@v7",
        "status": "completed",
        "conclusion": "success",
        "number": 3,
        "started_at": "2025-05-01T22:55:50Z",
        "completed_at": "2025-05-01T22:55:50Z"
      },
      {
        "name": "Post Run actions/checkout@v4",
        "status": "completed",
        "conclusion": "success",
        "number": 6,
        "started_at": "2025-05-01T22:55:50Z",
        "completed_at": "2025-05-01T22:55:50Z"
      },
      {
        "name": "Complete job",
        "status": "completed",
        "conclusion": "success",
        "number": 7,
        "started_at": "2025-05-01T22:55:50Z",
        "completed_at": "2025-05-01T22:55:50Z"
      }
    ],
    "check_run_url": "https://api.github.com/repos/andreypicado506/get-wf-details/check-runs/41511799280",
    "labels": [
      "ubuntu-latest"
    ],
    "runner_id": 59,
    "runner_name": "GitHub Actions 38",
    "runner_group_id": 2,
    "runner_group_name": "GitHub Actions"

In this successful example, two key properties at the top level and within each step are especially relevant: status and conclusion. Since this job completed successfully, both are set to “completed” and “success“, respectively.

Let’s now compare this with a rejected job to see how those values change.

"status": "completed",
    "conclusion": "failure",
"steps": [

    ],

In this case, the conclusion is “failure“. However, this value alone is not sufficient to distinguish a rejected job—it is also the result when a job fails due to an actual error during execution.

What makes a rejected job stand out is the fact that the steps array is empty. This contrasts with a failed job, where the steps array is still populated with the steps that ran (and potentially failed).

Therefore, the conclusion field is not a reliable indicator of a rejected job. Unfortunately, there isn’t a documented or explicit flag within the workflow_job payload that definitively identifies rejections.

To clarify this behavior, I reached out to GitHub Support to confirm whether an empty steps array is unique to rejected jobs. They confirmed that an empty steps array indicates a job was rejected. You can read more about this in the GitHub Community discussion:

Differentiate between a failed job and a rejected one using the workflow_job.completed event · community · Discussion #149319

Final takeaway

If the steps array is empty in a workflow_job.completed event, it’s a reliable signal that the job was rejected.

| Theme: UPortfolio