# Webhooks · REST API

> A webhook is a private URL that lets external systems push data into a workflow over HTTP.

HTML version: https://developers.sheetgo.com/api/webhook/

[Developers](/index.md) › [REST API](/api.md) › [Forms & Integrations](/api.md#api-endpoints)

REST API · 3 endpoints

## Webhooks

**Complete for this group.** Each operation below lists its parameters, request body, responses and errors. Every model they use is documented under [Models used on this page](#models), so you do not need another page to build a request. Base URL `https://api.sheetgo.com`; paths are complete, version included (`/rest/beta/…`): append them to the base URL exactly as shown; send `Authorization: Bearer sg_…`. Also in the API's own docs: <https://api.sheetgo.com/rest/reference/webhook> ([Markdown](https://api.sheetgo.com/rest/reference/webhook.md)).

**Conventions for every endpoint.** Lists take `page` (from 1) and `per_page` (1-100, default 50), and `total` counts **pages**, not items. Collection URLs end with `/`. `POST …/run` returns `200` when the run is *queued*; poll `GET …/run`. Google Sheets use `provider: "drive"`; column fields take letters (`"E"`). Error bodies and status codes: [REST API › Errors](/api.md#api-errors).

**Python recipes.** [API client helper](/examples.md#recipe-sheetgo-api).

A **webhook** is a private URL that lets external systems push data into a workflow over HTTP. Your app sends a JSON payload and Sheetgo lands it in the workflow — optionally triggering a full run — with no Google APIs or OAuth to manage on your side.

Use this endpoint to **POST** data to a workflow's webhook source.

## Operations

#### GET `/rest/beta/automations/{automation_id}/webhook` — Retrieve an automation's webhook

Returns the webhook bound to this automation's webhook source — most importantly its `url`, which is the address an external system POSTs data to.

A webhook is minted automatically when an automation is created with a `webhook` source; there is no endpoint to create one separately, and no way to rotate it. Deleting the automation deletes the webhook with it. Automations without a webhook source return **404**.

##### Parameters

| Name | In | Type |  | Description |
| --- | --- | --- | --- | --- |
| `automation_id` | path | string | required | Automation id |

##### Responses

| Status | Meaning | Body |
| --- | --- | --- |
| 200 | The automation's webhook | [`WebhookOut`](#model-WebhookOut) |
| 401 | Authentication failed or token is invalid | — |
| 404 | Automation has no webhook | — |
| 422 | Validation Error | [`HTTPValidationError`](#model-HTTPValidationError) |

##### Example request

```
curl -s -X GET "https://api.sheetgo.com/rest/beta/automations/AUTOMATION_ID/webhook" \
  -H "Authorization: Bearer $SHEETGO_API_KEY"
```

In the API's own docs: <https://api.sheetgo.com/rest/reference/webhook#get-rest-beta-automations-automation-id-webhook>

#### POST `/rest/beta/webhook/{public_id}` — Push values to a webhook and trigger its bound automation

Sends rows into a workflow through an automation's webhook source, and starts a run.

Answers **202 Accepted** as soon as the data is stored and the run is queued — the run itself happens asynchronously, so a 202 means *accepted*, not *finished*. Poll `GET /rest/beta/automations/{automation_id}/run` for the outcome.

**Safe retries.** Send an `Idempotency-Key` header (any unique string, 1-255 printable characters) and reuse it when you retry the same push. Sheetgo then runs the automation once and answers the retry with the first response plus `Idempotent-Replayed: true`, for 24 hours. A server error (5xx) is not remembered, so retrying it runs again.

Get the `public_id` from `GET /rest/beta/automations/{automation_id}/webhook`. Treat it as a secret.

##### Parameters

| Name | In | Type |  | Description |
| --- | --- | --- | --- | --- |
| `public_id` | path | string | required | The webhook's public identifier, from the automation's webhook endpoint. |
| `Idempotency-Key` | header | string | optional | Optional. Reuse the same value when retrying a push so it is processed only once. |

##### Request body (required)

`application/json` · [`WebhookBody`](#model-WebhookBody)

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `async_dispatch` | boolean | optional | Default False — the automation is dispatched synchronously and the 202 is returned once dispatch has started. Pass True to dispatch asynchronously and return 202 as soon as the request is accepted; useful for high-throughput producers. Default: `false` |
| `run_workflow` | boolean | optional | If True, after this automation finishes, the parent workflow's *other* automations are re-run synchronously. Default: `false` |
| `values` | array of array of string | required | Tabular values to push (rows of strings) Min items: `1` |

##### Responses

| Status | Meaning | Body |
| --- | --- | --- |
| 202 | Accepted; dispatch started | any |
| 400 | Malformed body, invalid `Idempotency-Key`, or webhook not bound to a webhook-source automation | — |
| 401 | Auth failed | — |
| 404 | Webhook not found or not owned by caller | — |
| 409 | A request with the same `Idempotency-Key` is still being processed (`idempotency_in_progress`) | — |
| 413 | Values exceed row/byte cap | — |
| 422 | Invalid request body (FastAPI validation error), or the `Idempotency-Key` was already used with a different body (`idempotency_key_reused`) | — |

##### Example request

```
curl -s -X POST "https://api.sheetgo.com/rest/beta/webhook/PUBLIC_ID" \
  -H "Authorization: Bearer $SHEETGO_API_KEY" \
  -H "Content-Type: application/json" \
  -d @body.json
```

In the API's own docs: <https://api.sheetgo.com/rest/reference/webhook#post-rest-beta-webhook-public-id>

#### GET `/rest/beta/workflows/{workflow_id}/webhooks` — List a workflow's webhooks

Lists every webhook across the workflow's automations, so you can find the right `url` without knowing which automation owns it. Paginated with the standard `page` / `per_page` envelope. A workflow with no webhook sources returns an empty list, not a 404.

##### Parameters

| Name | In | Type |  | Description |
| --- | --- | --- | --- | --- |
| `workflow_id` | path | string | required | Workflow id |
| `page` | query | integer | optional | Page number, 1-based. Default: `1` · Min: `1` |
| `per_page` | query | integer | optional | Webhooks per page (1-100). Default: `50` · Min: `1` · Max: `100` |

##### Responses

| Status | Meaning | Body |
| --- | --- | --- |
| 200 | Webhooks in the workflow | any |
| 401 | Authentication failed or token is invalid | — |
| 422 | Validation Error | [`HTTPValidationError`](#model-HTTPValidationError) |

##### Example request

```
curl -s -X GET "https://api.sheetgo.com/rest/beta/workflows/WORKFLOW_ID/webhooks" \
  -H "Authorization: Bearer $SHEETGO_API_KEY"
```

In the API's own docs: <https://api.sheetgo.com/rest/reference/webhook#get-rest-beta-workflows-workflow-id-webhooks>

## Models used on this page

Every request and response model referenced above, including nested ones (4). The full catalogue is on the [Models](/api/models.md) page.

#### `HTTPValidationError`

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `detail` | array of [`ValidationError`](#model-ValidationError) | optional |  |

Used by: [GET /rest/beta/workflows/](/api/workflows.md#get-rest-beta-workflows), [POST /rest/beta/workflows/](/api/workflows.md#post-rest-beta-workflows), [POST /rest/beta/workflows/run/{id}](/api/workflows.md#post-rest-beta-workflows-run-id), [GET /rest/beta/workflows/{id}](/api/workflows.md#get-rest-beta-workflows-id), [PATCH /rest/beta/workflows/{id}](/api/workflows.md#patch-rest-beta-workflows-id), [DELETE /rest/beta/workflows/{id}](/api/workflows.md#delete-rest-beta-workflows-id), [GET /rest/beta/workflows/{id}/collaborators](/api/workflows.md#get-rest-beta-workflows-id-collaborators), [POST /rest/beta/workflows/{id}/collaborators](/api/workflows.md#post-rest-beta-workflows-id-collaborators), [DELETE /rest/beta/workflows/{id}/collaborators](/api/workflows.md#delete-rest-beta-workflows-id-collaborators), [PATCH /rest/beta/workflows/{id}/collaborators/{email}](/api/workflows.md#patch-rest-beta-workflows-id-collaborators-email), [DELETE /rest/beta/workflows/{id}/collaborators/{email}](/api/workflows.md#delete-rest-beta-workflows-id-collaborators-email), [GET /rest/beta/workflows/{id}/destinations](/api/workflows.md#get-rest-beta-workflows-id-destinations), [GET /rest/beta/workflows/{id}/files](/api/workflows.md#get-rest-beta-workflows-id-files), [GET /rest/beta/workflows/{id}/general-access](/api/workflows.md#get-rest-beta-workflows-id-general-access), [PUT /rest/beta/workflows/{id}/general-access](/api/workflows.md#put-rest-beta-workflows-id-general-access), [DELETE /rest/beta/workflows/{id}/general-access](/api/workflows.md#delete-rest-beta-workflows-id-general-access), [POST /rest/beta/workflows/{id}/leave](/api/workflows.md#post-rest-beta-workflows-id-leave), [POST /rest/beta/workflows/{id}/request-access](/api/workflows.md#post-rest-beta-workflows-id-request-access), [GET /rest/beta/workflows/{id}/run](/api/workflows.md#get-rest-beta-workflows-id-run), [POST /rest/beta/workflows/{id}/run](/api/workflows.md#post-rest-beta-workflows-id-run), [GET /rest/beta/workflows/{id}/sources](/api/workflows.md#get-rest-beta-workflows-id-sources), [GET /rest/beta/automations/](/api/automations.md#get-rest-beta-automations), [POST /rest/beta/automations/run/{id}](/api/automations.md#post-rest-beta-automations-run-id), [GET /rest/beta/automations/{id}](/api/automations.md#get-rest-beta-automations-id), [DELETE /rest/beta/automations/{id}](/api/automations.md#delete-rest-beta-automations-id), [GET /rest/beta/automations/{id}/destinations](/api/automations.md#get-rest-beta-automations-id-destinations), [GET /rest/beta/automations/{id}/files](/api/automations.md#get-rest-beta-automations-id-files), [GET /rest/beta/automations/{id}/run](/api/automations.md#get-rest-beta-automations-id-run), [POST /rest/beta/automations/{id}/run](/api/automations.md#post-rest-beta-automations-id-run), [GET /rest/beta/automations/{id}/sources](/api/automations.md#get-rest-beta-automations-id-sources), [GET /rest/beta/workflows/{id}/trigger](/api/triggers.md#get-rest-beta-workflows-id-trigger), [DELETE /rest/beta/workflows/{id}/trigger](/api/triggers.md#delete-rest-beta-workflows-id-trigger), [GET /rest/beta/workflows/{id}/dashboard](/api/dashboards.md#get-rest-beta-workflows-id-dashboard), [DELETE /rest/beta/workflows/{id}/dashboard/elements/{element\_id}](/api/dashboards.md#delete-rest-beta-workflows-id-dashboard-elements-element-id), [GET /rest/beta/workflows/{id}/dashboard/elements/{element\_id}/data](/api/dashboards.md#get-rest-beta-workflows-id-dashboard-elements-element-id-data), [PUT /rest/beta/workflows/{id}/dashboard/publish](/api/dashboards.md#put-rest-beta-workflows-id-dashboard-publish), [GET /rest/beta/workflows/{workflow\_id}/forms/](/api/forms.md#get-rest-beta-workflows-workflow-id-forms), [POST /rest/beta/workflows/{workflow\_id}/forms/](/api/forms.md#post-rest-beta-workflows-workflow-id-forms), [GET /rest/beta/workflows/{workflow\_id}/forms/{form\_id}](/api/forms.md#get-rest-beta-workflows-workflow-id-forms-form-id), [PATCH /rest/beta/workflows/{workflow\_id}/forms/{form\_id}](/api/forms.md#patch-rest-beta-workflows-workflow-id-forms-form-id), [DELETE /rest/beta/workflows/{workflow\_id}/forms/{form\_id}](/api/forms.md#delete-rest-beta-workflows-workflow-id-forms-form-id), [GET /rest/beta/workflows/{workflow\_id}/forms/{form\_id}/responses](/api/forms.md#get-rest-beta-workflows-workflow-id-forms-form-id-responses), [HEAD /rest/beta/workflows/{workflow\_id}/forms/{form\_id}/responses](/api/forms.md#head-rest-beta-workflows-workflow-id-forms-form-id-responses), [GET /rest/beta/automations/{automation\_id}/webhook](/api/webhook.md#get-rest-beta-automations-automation-id-webhook), [GET /rest/beta/workflows/{workflow\_id}/webhooks](/api/webhook.md#get-rest-beta-workflows-workflow-id-webhooks), [GET /rest/beta/api-destination/{public\_id}](/api/api-destination.md#get-rest-beta-api-destination-public-id), [HEAD /rest/beta/api-destination/{public\_id}](/api/api-destination.md#head-rest-beta-api-destination-public-id), [GET /rest/beta/integrations/{provider}/options](/api/integrations.md#get-rest-beta-integrations-provider-options), [GET /rest/beta/outlook/messages](/api/outlook.md#get-rest-beta-outlook-messages), [POST /rest/beta/outlook/messages/batch](/api/outlook.md#post-rest-beta-outlook-messages-batch), [GET /rest/beta/outlook/messages/{message\_id}](/api/outlook.md#get-rest-beta-outlook-messages-message-id), [GET /rest/beta/outlook/messages/{message\_id}/attachments/{attachment\_id}](/api/outlook.md#get-rest-beta-outlook-messages-message-id-attachments-attachment-id), [POST /rest/beta/outlook/send](/api/outlook.md#post-rest-beta-outlook-send), [GET /rest/beta/gmail/messages](/api/gmail.md#get-rest-beta-gmail-messages), [POST /rest/beta/gmail/messages/batch](/api/gmail.md#post-rest-beta-gmail-messages-batch), [GET /rest/beta/gmail/messages/{message\_id}](/api/gmail.md#get-rest-beta-gmail-messages-message-id), [GET /rest/beta/gmail/messages/{message\_id}/attachments/{attachment\_id}](/api/gmail.md#get-rest-beta-gmail-messages-message-id-attachments-attachment-id), [POST /rest/beta/gmail/send](/api/gmail.md#post-rest-beta-gmail-send), [GET /rest/beta/files/{provider}](/api/files.md#get-rest-beta-files-provider), [GET /rest/beta/files/{provider}/roots](/api/files.md#get-rest-beta-files-provider-roots), [GET /rest/beta/files/{provider}/search](/api/files.md#get-rest-beta-files-provider-search), [GET /rest/beta/files/{provider}/{file\_id}](/api/files.md#get-rest-beta-files-provider-file-id), [GET /rest/beta/bigquery/projects](/api/bigquery.md#get-rest-beta-bigquery-projects), [GET /rest/beta/bigquery/projects/{project}/datasets](/api/bigquery.md#get-rest-beta-bigquery-projects-project-datasets), [GET /rest/beta/bigquery/projects/{project}/datasets/{dataset}/tables](/api/bigquery.md#get-rest-beta-bigquery-projects-project-datasets-dataset-tables), [GET /rest/beta/bigquery/projects/{project}/datasets/{dataset}/tables/{table}](/api/bigquery.md#get-rest-beta-bigquery-projects-project-datasets-dataset-tables-table), [POST /rest/beta/bigquery/projects/{project}/validate-query](/api/bigquery.md#post-rest-beta-bigquery-projects-project-validate-query), [POST /rest/auth/refresh](/api/auth.md#post-rest-auth-refresh), [POST /rest/auth/token](/api/auth.md#post-rest-auth-token)

#### `ValidationError`

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `loc` | array of string or integer | required |  |
| `msg` | string | required |  |
| `type` | string | required |  |

#### `WebhookBody`

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `async_dispatch` | boolean | optional | Default False — the automation is dispatched synchronously and the 202 is returned once dispatch has started. Pass True to dispatch asynchronously and return 202 as soon as the request is accepted; useful for high-throughput producers. Default: `false` |
| `run_workflow` | boolean | optional | If True, after this automation finishes, the parent workflow's *other* automations are re-run synchronously. Default: `false` |
| `values` | array of array of string | required | Tabular values to push (rows of strings) Min items: `1` |

Used by: [POST /rest/beta/webhook/{public\_id}](/api/webhook.md#post-rest-beta-webhook-public-id)

#### `WebhookOut`

A webhook endpoint bound to one automation's webhook source.

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `active` | boolean | optional | False once the webhook has been deleted. A deleted webhook stops accepting pushes; webhooks are removed with their automation, never on their own. Default: `true` |
| `automation_id` | string | nullable | Id of the automation this webhook feeds. Null only for a webhook that is not yet bound to one. |
| `created_at` | string (date-time) | nullable | When the webhook was minted, ISO 8601. |
| `public_id` | string | required | The webhook's public identifier — the `{public_id}` path segment in `url`. Treat it as a secret: anyone holding it can push data to the automation. |
| `url` | string | required | Full URL to POST your JSON payload to. This is the value to configure in the external system that will push data. |

Used by: [GET /rest/beta/automations/{automation\_id}/webhook](/api/webhook.md#get-rest-beta-automations-automation-id-webhook)
