> ## Documentation Index
> Fetch the complete documentation index at: https://docs.squarecloud.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Set GitHub webhook

> Connect an application to a GitHub repository with a personal access token via POST /v2/apps/{app_id}/deploy/webhook, or send @ to remove the webhook.

<ParamField header="Authorization" type="string" placeholder="API Key" required>
  The API key for your account. You can find this in your [account settings](https://squarecloud.app/en/account/security).
</ParamField>

Requires an API key with the `apps:deploy` [scope](/en/api-reference/authentication#scopes).

This endpoint connects an application to a GitHub repository the classic way: generate a personal access token (`ghp_*` or the fine-grained `github_pat_*` format) and Square Cloud returns a unique webhook URL to register on that repository so pushes trigger a deploy. Sending `access_token: "@"` instead removes the existing webhook and access token from the application.

Configuring or removing a webhook invalidates the cached response from [Get Current Deployment](/en/api-reference/endpoint/apps/deploy/info). Calls are rate limited to 5 per 60 seconds per user, and on workspace-shared applications the caller needs the `admin` [role](/en/api-reference/endpoint/workspace/members/invite#roles) or ownership. To review deploy attempts triggered by this webhook, use [List Deployments](/en/api-reference/endpoint/apps/deploy/list).

A webhook and a [GitHub App link](/en/api-reference/endpoint/apps/deploy/github-app-link) can be configured on the same application at the same time: setting up one does not remove the other.

## Parameters

<ParamField path="app_id" type="string" placeholder="Application ID" required>
  The ID of the application. You can find this in the URL of your application's dashboard.
</ParamField>

<ParamField body="access_token" type="string" placeholder="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" required>
  The access token for your GitHub repository. You can find this in your [GitHub Tokens Classic](https://github.com/settings/tokens/new)
</ParamField>

## Response

<ResponseField name="status" type="string">
  Indicates whether the call was successful: `success` if it was, `error` if not.
</ResponseField>

<ResponseField name="response" type="object">
  The contents of the response.

  <Expandable title="Toggle object">
    <ResponseField name="webhook" type="string">
      The URL of the webhook.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseExample>
  ```json theme={"system"}
  {
      "status": "success",
      "response": {
          "webhook": "https://api.squarecloud.app/v2/git/webhook/<webhook-code>"
      }
  }
  ```
</ResponseExample>

## Common errors

| Code | HTTP | Meaning |
| - | - | - |
| `INVALID_ACCESS_TOKEN` | 400 | `access_token` is not `@` and doesn't match the `ghp_*`/`github_pat_*` GitHub token format. |

## Webhook deliveries

GitHub sends each push to the webhook URL (`POST https://api.squarecloud.app/v2/git/webhook/{webhook}`). The reply is plain text (`text/plain`) that says whether a deploy was queued, so the **Recent Deliveries** list of the webhook on GitHub shows what happened to each push. Only the `429` replies with JSON (`KEEP_CALM`).

A `200` is sent only after the deploy was stored in the queue:

```text theme={"system"}
Deploy queued: commit 1a2b3c4 of 'main' will be deployed shortly.
```

Every other reply ends with `Nothing was deployed.`

| HTTP | Meaning |
| - | - |
| 202 | The push is for another branch than the webhook's `?branch=`, for example: `Push received but not queued: it is for 'dev', and this webhook only deploys 'main'. Nothing was deployed.` |
| 202 | `GIT_REF_NOT_SUPPORTED`: the push is for a tag or another ref outside `refs/heads/`. Tags are never deployed. |
| 202 | `GIT_BRANCH_DELETED`: the push deletes a branch (`deleted: true`, or an `after` made only of zeros). |
| 400 | The webhook URL or the payload is invalid, for example a `ping` event instead of a `push`. |
| 404 | `Unknown webhook: it is not linked to any application (it may have been regenerated). Nothing was deployed.` |
| 413 | The payload is larger than GitHub's own webhook limit. |
| 415 | The webhook does not send `application/json`. Set the content type to `application/json` in the webhook settings on GitHub. |
| 429 | Too many pushes in a short time (`KEEP_CALM`): each webhook accepts 1 push per 15 seconds. |
| 503 | A temporary failure on our side kept the deploy from being stored. |

Every `202` is answered before the rate limit, so it doesn't use up the webhook's limit of 1 push per 15 seconds. A release sent with `git push --follow-tags`, or a merged pull request whose branch GitHub deletes automatically, no longer holds back the deploy of the branch push that arrives with it. For a tag or a deleted branch, the reply starts with its code, as shown on GitHub in **Settings > Webhooks > Recent Deliveries**, in the **Response** tab:

```text theme={"system"}
GIT_REF_NOT_SUPPORTED: Push received but not queued: 'refs/tags/v1.2.0' is not a branch (tag pushes are not deployed). Nothing was deployed.
GIT_BRANCH_DELETED: Push received but not queued: it deletes the branch 'feature/login'. Nothing was deployed.
```

<Tip>If a delivery shows `503`, redeliver it on GitHub in **Settings > Webhooks > Recent Deliveries**, or push again.</Tip>

## Related

* CLI: [`squarecloud app deploy webhook`](/en/cli-reference/github-deploys#squarecloud-app-deploy-webhook)
* SDKs: [`api.apps.deploys.setWebhook()`](/en/sdks/js/deploys) (JavaScript), [`client.apps.deploys.set_webhook()`](/en/sdks/py/deploys) (Python), [`c.Apps.Deploys.SetWebhook()`](/en/sdks/go/deploys) (Go)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.