Skip to content

Webhooks#

Webhooks let Codacy push a real-time HTTP notification to an endpoint you control whenever Codacy finishes the quality analysis of a branch or a pull request, instead of you having to poll the Codacy API for updates. Once you add an endpoint, Codacy posts events from every repository of your organization to it.

Adding a webhook endpoint#

Only an organization admin or organization manager can add a webhook endpoint. An organization has a maximum of 10 webhook endpoints.

The URL must use https:// and be reachable from the public internet. Codacy rejects a host that doesn't resolve or that resolves to a private or local network address. If you receive events from more than one organization, see how to tell them apart.

To add a webhook endpoint:

  1. Open your organization Integrations, page Webhooks (listed under Developer tools).
  2. Click Add endpoint.
  3. In the dialog, enter the URL that should receive the webhook deliveries in Payload URL, then click Add endpoint.
  4. Click the copy button on the card above the list of endpoints to copy the signing secret, and store it somewhere safe. Codacy generates a secret for each new endpoint and shows it once. You need it to verify deliveries. Dismiss stays disabled until you copy the secret.
  5. To test your endpoint and see a first delivery, reanalyze a commit on an enabled branch.

Warning

If you lose the secret, delete the endpoint and add it again to get a new one.

If your organization doesn't have access to webhooks yet, the Webhooks page shows an upgrade prompt instead. Talk to us about upgrading.

Managing webhook endpoints#

The Webhooks page lists the endpoints configured for your organization.

You can't edit an existing endpoint or rotate its secret. Delete the endpoint and add a new one instead. To delete an endpoint, click the Delete icon on its row and confirm. Deleting an endpoint stops Codacy from posting to it immediately and destroys its signing secret.

Once the organization reaches 10 endpoints, Add endpoint is disabled. Delete an endpoint to add another one.

If your organization loses access to webhooks later, Codacy stops sending deliveries but keeps your endpoints, and they resume with the same signing secrets when access returns.

Tip

You can also add, list, and delete webhook endpoints using the Codacy API. The endpoints you create through the API are the same ones the Webhooks page shows.

Events sent to your endpoint#

Codacy sends the quality.analysis.completed event to every webhook endpoint of your organization when:

  • A branch analysis finishes. Codacy finished analyzing a commit on an enabled branch. Codacy sends one delivery for each enabled branch that contains the commit, and reanalyzing a commit sends a new delivery. The commit isn't always the latest one on that branch: an analysis of a commit on master is also sent for every other enabled branch that contains it, such as a feature branch created from it.
  • A pull request analysis finishes. Codacy sends a new delivery each time the pull request is analyzed again, for example after new commits.

Codacy sends the event regardless of the analysis outcome, not only when it succeeds. Check the body's status field for the outcome.

Codacy sends one copy of each event to every webhook endpoint of your organization, and there's no way to filter by repository or branch.

What the event doesn't cover#

quality.analysis.completed reports the outcome of Codacy's quality analysis, including SAST and SCA. SCA runs send their own deliveries, see delivery behavior. The event doesn't report the outcome of:

  • Coverage analysis. Codacy processes the coverage data you upload apart from the quality analysis, so the event doesn't tell you whether Codacy received or processed coverage for a commit, and status doesn't reflect it. Codacy doesn't send a webhook event for coverage analysis yet.
  • DAST and container scanning.

To check whether Codacy received the coverage data for a pull request, call getPullRequestCoverageReports. See identifying commits without coverage data for an example.

Delivery payload#

Each delivery is an HTTP POST request with a JSON body and these headers:

Header Description
X-Codacy-Event The event type, always quality.analysis.completed.
X-Codacy-Delivery A UUID that uniquely identifies this delivery. A retry of the same delivery reuses it. See delivery behavior.
X-Codacy-Signature The HMAC-SHA256 signature of the request body, in the form sha256=<hex-encoded hash>.

The body identifies the organization, the repository, the commit, and either the branch or the pull request. It doesn't include the analysis results.

Branch analysis finished:

{
  "event": "quality.analysis.completed",
  "repository": { "name": "engine" },
  "organization": { "id": 123456 },
  "target": { "type": "branch", "value": "master" },
  "commitSha": "a1b2c3d4e5f60718293a4b5c6d7e8f9012345678",
  "status": "success",
  "timestamp": "2025-09-17T23:00:00Z"
}

Pull request analysis finished:

{
  "event": "quality.analysis.completed",
  "repository": { "name": "engine" },
  "organization": { "id": 123456 },
  "target": { "type": "pullRequest", "value": "464" },
  "commitSha": "a1b2c3d4e5f60718293a4b5c6d7e8f9012345678",
  "status": "success",
  "timestamp": "2025-09-17T23:00:00Z"
}
  • organization.id is the Codacy ID of the organization the delivery belongs to, as a JSON number. The payload doesn't include the organization name or its Git provider. To look them up, see receiving events from more than one organization.
  • target.type is branch for a branch analysis or pullRequest for a pull request analysis. target.value is always a string: the branch name or the pull request number.
  • status is success, partial_success, or failure, depending on whether all, some, or none of the analysis tools completed. With partial_success, Codacy reports results only from the tools that completed, so issue counts and metrics can be lower than a full analysis would report. A single failed tool is enough to cause it, while failure needs every tool to fail. The payload doesn't say which tool failed. If you keep seeing partial_success, click View logs on the pull request or commit page to find out. The status belongs to one analysis, so the branch and pull request deliveries for the same commit can differ.
  • timestamp is when the analysis finished, as an ISO 8601 UTC timestamp to the second (2025-09-17T23:00:00Z). A retry sends the same value as the original attempt. There's no separate timestamp header: the signature covers the whole body, so verify this field instead of a header if you need to reject stale deliveries.

Codacy doesn't include an issue list or a link to the analysis result in the payload. Use the Codacy API to look up the analysis details for the commit or pull request, for example listPullRequestIssues or listCommitDeltaIssues. These endpoints identify an organization by its Git provider and name, not by the organization.id in the payload, so keep a lookup from the ID to both.

Verifying a delivery#

Verify that a delivery came from Codacy by recomputing its signature and comparing it to the X-Codacy-Signature header:

  1. Compute the HMAC-SHA256 hash of the raw request body, using the endpoint's signing secret as the key. Use the secret exactly as Codacy shows it, and don't Base64-decode it. Use the body exactly as received, and don't parse and re-serialize the JSON first.
  2. Hex-encode the hash in lowercase and prefix it with sha256=.
  3. Compare the result to the X-Codacy-Signature header using a constant-time comparison, and reject the delivery if they don't match.
  4. Optionally reject a delivery whose body timestamp is too old, to guard against a captured delivery being replayed. Allow for retries and delays, because the timestamp is when the analysis finished, not when the delivery arrived.