# Automations · REST API

> An automation (also called a connection) is a single data transfer inside a workflow: it pulls data from one or more sources, optionally…

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

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

REST API · 12 endpoints

## Automations

**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/automations> ([Markdown](https://api.sheetgo.com/rest/reference/automations.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) · [Read every page of a list](/examples.md#recipe-paginate) · [Create, run and wait for an automation](/examples.md#recipe-create-run-wait) · [Find a file and build an automation payload](/examples.md#recipe-file-to-automation).

An **automation** (also called a *connection*) is a single data transfer inside a workflow: it pulls data from one or more **sources**, optionally consolidates, filters or merges it, and writes the result to one or more **destinations** — all without manual copy-paste.

Use these endpoints to **list, create, read, replace, update, run and archive** automations, and to inspect their source and destination files.

## Operations

#### GET `/rest/beta/automations/` — Get a paginated list of automations

Return a list of automations following the pagination parameters

##### Parameters

| Name | In | Type |  | Description |
| --- | --- | --- | --- | --- |
| `page` | query | integer | optional | Page number, 1-based Default: `1` · Min: `1` |
| `per_page` | query | integer | optional | Number of items per page (1-100; values above 100 are clamped to 100 and the effective size is echoed in the response) Default: `50` · Min: `1` |

##### Responses

| Status | Meaning | Body |
| --- | --- | --- |
| 200 | A paginated list of automations | [`PaginatedResponse_AutomationModel_`](#model-PaginatedResponse_AutomationModel_) |
| 401 | Authentication failed or token is invalid | — |
| 404 | Not found | — |
| 422 | Validation Error | [`HTTPValidationError`](#model-HTTPValidationError) |

##### Example request

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

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

#### POST `/rest/beta/automations/` — Create a new automation

**Column letters.** Every column field — `filter` (`columns`, `expressions[].column`), `split.column`, `left_join.column`, `remove_duplicates.columns` and `anonymize.columns` keys — takes the spreadsheet column LETTER (`D`), not the header name (`Status`), because the engine addresses columns by position. A header name is rejected with 422 `invalid_column`.

To find the letter, read the source file's header row first:

1. `GET /rest/beta/files/{provider}/{file_id}/structure?include=columns&tab=Orders&header_row=1` — use the source's `id` and `provider`, the tab you import and its `offset_header` as `header_row`. A folder id reads its newest spreadsheet.
2. Pick the letter from `tabs[].columns`, e.g. `{"letter": "D", "index": 3, "header": "Status"}`.
3. Use it in the automation:

```
"filter": {"type": "condition", "condition_type": "and",
           "expressions": [{"column": "D", "criteria": "text_is_exactly", "value": "open"}]}
```

The structure call works for Google Sheets, Excel, CSV and TSV on every provider. It reads the file, so call it once per source and reuse the result; repeat calls are cached until the file changes.

**Processor combinations.** `ai`, `filter`, `remove_duplicates` and `anonymize` can each be used on their own, and `merge` / `left_join` combine with them. These combinations are **not allowed today because the features are incompatible** in the engine, and are rejected with 422 `invalid_processor_combination`:

| Combination | Why |
| --- | --- |
| `ai` + `remove_duplicates` / `anonymize` | the engine runs the AI step or the transformers, never both — the transformer would be silently skipped |
| `filter` + `remove_duplicates` / `anonymize` | the header row is lost and the first data row is corrupted |
| `remove_duplicates` + `anonymize` | same — and a row could be left unmasked |

Automations created before this rule keep running unchanged.

##### Parameters

| Name | In | Type |  | Description |
| --- | --- | --- | --- | --- |
| `x-run` | header | boolean | optional | Set to true to run the automation immediately after creating it. The run is queued, so the response returns before it finishes — poll `GET /rest/beta/automations/{id}/run` for the outcome. Default: `false` |

##### Request body (required)

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

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `ai` | [`AIProcessor`](#model-AIProcessor) | nullable | AI step options |
| `anonymize` | [`AnonymizeProcessor`](#model-AnonymizeProcessor) | nullable | Anonymize step options. Not combinable today with `ai`, `filter` or `remove_duplicates` (features incompatible in the engine) — see Processor combinations. |
| `destinations` | array of one of (chosen by `type`): `type: "api"` → [`DestinationApiPublish`](#model-DestinationApiPublish), `type: "bigquery"` → [`DestinationBigQuery-Input`](#model-DestinationBigQuery-Input), `type: "document"` → [`DestinationDocument`](#model-DestinationDocument), `type: "file"` → [`DestinationFile`](#model-DestinationFile), `type: "folder"` → [`DestinationFolder`](#model-DestinationFolder), `type: "mail_merge"` → [`DestinationMailMerge`](#model-DestinationMailMerge), `type: "pdf"` → [`DestinationPDF`](#model-DestinationPDF), `type: "share"` → [`DestinationShare`](#model-DestinationShare), `type: "webhook"` → [`DestinationWebhook`](#model-DestinationWebhook) or one of (chosen by `type`): `type: "api"` → [`DestinationApiPublish`](#model-DestinationApiPublish), `type: "bigquery"` → [`DestinationBigQuery-Input`](#model-DestinationBigQuery-Input), `type: "document"` → [`DestinationDocument`](#model-DestinationDocument), `type: "file"` → [`DestinationFile`](#model-DestinationFile), `type: "folder"` → [`DestinationFolder`](#model-DestinationFolder), `type: "mail_merge"` → [`DestinationMailMerge`](#model-DestinationMailMerge), `type: "pdf"` → [`DestinationPDF`](#model-DestinationPDF), `type: "share"` → [`DestinationShare`](#model-DestinationShare), `type: "webhook"` → [`DestinationWebhook`](#model-DestinationWebhook) | nullable | Destinations to connect to |
| `filter` | [`FilterCondition-Input`](#model-FilterCondition-Input) or [`FilterColumn`](#model-FilterColumn) or [`FilterQuery`](#model-FilterQuery) | nullable | Filter step options. Columns are spreadsheet LETTERS — get them from `GET /rest/beta/files/{provider}/{file_id}/structure?include=columns` on the source file (see Column letters). Not combinable today with `remove_duplicates` or `anonymize` (features incompatible in the engine) — see Processor combinations. |
| `left_join` | [`LeftJoinProcessor`](#model-LeftJoinProcessor) | nullable | Left join step options |
| `merge` | [`MergeProcessor`](#model-MergeProcessor) | nullable | Merge step options |
| `name` | string | required | Name of the automation |
| `number_format` | boolean | nullable | Number format Default: `false` |
| `remove_duplicates` | [`RemoveDuplicatesProcessor`](#model-RemoveDuplicatesProcessor) | nullable | Remove duplicate rows. Not combinable today with `ai`, `filter` or `anonymize` (features incompatible in the engine) — see Processor combinations. |
| `sources` | array of [`SourceFile`](#model-SourceFile) or [`SourceFolder-Input`](#model-SourceFolder-Input) or [`SourceWebhook`](#model-SourceWebhook) or [`SourceAPI`](#model-SourceAPI) or [`SourceIntegration`](#model-SourceIntegration) or [`SourceBigQuery`](#model-SourceBigQuery) or [`SourceOutlook-Input`](#model-SourceOutlook-Input) or [`SourceGmail-Input`](#model-SourceGmail-Input) | required | List of sources to connect to |
| `split` | [`Split`](#model-Split) | nullable | Split step options |
| `transfer_format` | boolean | nullable | Transfer format Default: `false` |
| `workflow_id` | string | required | Id of the workflow this automation belongs to |

##### Responses

| Status | Meaning | Body |
| --- | --- | --- |
| 200 | The automation model created | [`AutomationModel`](#model-AutomationModel) |
| 401 | Authentication failed or token is invalid | — |
| 403 | The plan does not include this destination type | — |
| 404 | Not found | — |
| 412 | `send_from` names an Outlook account that is not connected or cannot send mail (`outlook_not_connected`), or `ai.model` / `ai.model_settings` without your own OpenAI account (`openai_not_connected`), or an Outlook source whose account cannot read mail (`outlook_not_connected`, Mail.Read), or a Gmail source whose Google account cannot read mail (`gmail_not_connected`, gmail.readonly) | — |
| 422 | Invalid destination combination, recipient format, api-source shape, integration source, endpoint, api destination or bigquery combination, documents automation (invalid\_documents\_automation), file\_filter (invalid\_file\_filter), Outlook automation (invalid\_outlook\_automation), Gmail automation (invalid\_gmail\_automation), email\_filter (invalid\_email\_filter), or a processor combination that is not allowed (invalid\_processor\_combination), or a column that is not a spreadsheet letter (invalid\_column) | — |

##### Example request

```
curl -s -X POST "https://api.sheetgo.com/rest/beta/automations/" \
  -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/automations#post-rest-beta-automations>

#### POST `/rest/beta/automations/run/{id}` — (Obsolete) Use POST /rest/beta/automations/{id}/run instead

**Deprecated.** Do not use in new code.

This endpoint will be removed

##### Parameters

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

##### Responses

| Status | Meaning | Body |
| --- | --- | --- |
| 200 | successful operation | [`SuccessResponse`](#model-SuccessResponse) |
| 401 | Authentication failed or token is invalid | — |
| 404 | Not found | — |
| 422 | Validation Error | [`HTTPValidationError`](#model-HTTPValidationError) |

##### Example request

```
curl -s -X POST "https://api.sheetgo.com/rest/beta/automations/run/ID" \
  -H "Authorization: Bearer $SHEETGO_API_KEY"
```

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

#### GET `/rest/beta/automations/{id}` — Get a single automation

Given an automation id, returns the automation model data

##### Parameters

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

##### Responses

| Status | Meaning | Body |
| --- | --- | --- |
| 200 | The automation model data | [`AutomationModel`](#model-AutomationModel) |
| 401 | Authentication failed or token is invalid | — |
| 404 | Not found | — |
| 422 | Validation Error | [`HTTPValidationError`](#model-HTTPValidationError) |

##### Example request

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

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

#### PUT `/rest/beta/automations/{id}` — Replace an existing automation entirely

**Column letters.** Every column field — `filter` (`columns`, `expressions[].column`), `split.column`, `left_join.column`, `remove_duplicates.columns` and `anonymize.columns` keys — takes the spreadsheet column LETTER (`D`), not the header name (`Status`), because the engine addresses columns by position. A header name is rejected with 422 `invalid_column`.

To find the letter, read the source file's header row first:

1. `GET /rest/beta/files/{provider}/{file_id}/structure?include=columns&tab=Orders&header_row=1` — use the source's `id` and `provider`, the tab you import and its `offset_header` as `header_row`. A folder id reads its newest spreadsheet.
2. Pick the letter from `tabs[].columns`, e.g. `{"letter": "D", "index": 3, "header": "Status"}`.
3. Use it in the automation:

```
"filter": {"type": "condition", "condition_type": "and",
           "expressions": [{"column": "D", "criteria": "text_is_exactly", "value": "open"}]}
```

The structure call works for Google Sheets, Excel, CSV and TSV on every provider. It reads the file, so call it once per source and reuse the result; repeat calls are cached until the file changes.

**Processor combinations.** `ai`, `filter`, `remove_duplicates` and `anonymize` can each be used on their own, and `merge` / `left_join` combine with them. These combinations are **not allowed today because the features are incompatible** in the engine, and are rejected with 422 `invalid_processor_combination`:

| Combination | Why |
| --- | --- |
| `ai` + `remove_duplicates` / `anonymize` | the engine runs the AI step or the transformers, never both — the transformer would be silently skipped |
| `filter` + `remove_duplicates` / `anonymize` | the header row is lost and the first data row is corrupted |
| `remove_duplicates` + `anonymize` | same — and a row could be left unmasked |

Automations created before this rule keep running unchanged.

##### Parameters

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

##### Request body (required)

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

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `ai` | [`AIProcessor`](#model-AIProcessor) | nullable | AI step options |
| `anonymize` | [`AnonymizeProcessor`](#model-AnonymizeProcessor) | nullable | Anonymize step options. Not combinable today with `ai`, `filter` or `remove_duplicates` (features incompatible in the engine) — see Processor combinations. |
| `destinations` | array of one of (chosen by `type`): `type: "api"` → [`DestinationApiPublish`](#model-DestinationApiPublish), `type: "bigquery"` → [`DestinationBigQuery-Input`](#model-DestinationBigQuery-Input), `type: "document"` → [`DestinationDocument`](#model-DestinationDocument), `type: "file"` → [`DestinationFile`](#model-DestinationFile), `type: "folder"` → [`DestinationFolder`](#model-DestinationFolder), `type: "mail_merge"` → [`DestinationMailMerge`](#model-DestinationMailMerge), `type: "pdf"` → [`DestinationPDF`](#model-DestinationPDF), `type: "share"` → [`DestinationShare`](#model-DestinationShare), `type: "webhook"` → [`DestinationWebhook`](#model-DestinationWebhook) or one of (chosen by `type`): `type: "api"` → [`DestinationApiPublish`](#model-DestinationApiPublish), `type: "bigquery"` → [`DestinationBigQuery-Input`](#model-DestinationBigQuery-Input), `type: "document"` → [`DestinationDocument`](#model-DestinationDocument), `type: "file"` → [`DestinationFile`](#model-DestinationFile), `type: "folder"` → [`DestinationFolder`](#model-DestinationFolder), `type: "mail_merge"` → [`DestinationMailMerge`](#model-DestinationMailMerge), `type: "pdf"` → [`DestinationPDF`](#model-DestinationPDF), `type: "share"` → [`DestinationShare`](#model-DestinationShare), `type: "webhook"` → [`DestinationWebhook`](#model-DestinationWebhook) | nullable | Destinations to connect to |
| `filter` | [`FilterCondition-Input`](#model-FilterCondition-Input) or [`FilterColumn`](#model-FilterColumn) or [`FilterQuery`](#model-FilterQuery) | nullable | Filter step options. Columns are spreadsheet LETTERS — get them from `GET /rest/beta/files/{provider}/{file_id}/structure?include=columns` on the source file (see Column letters). Not combinable today with `remove_duplicates` or `anonymize` (features incompatible in the engine) — see Processor combinations. |
| `id` | string | required | Id of the automation |
| `left_join` | [`LeftJoinProcessor`](#model-LeftJoinProcessor) | nullable | Left join step options |
| `merge` | [`MergeProcessor`](#model-MergeProcessor) | nullable | Merge step options |
| `name` | string | required | Name of the automation |
| `number_format` | boolean | nullable | Number format Default: `false` |
| `remove_duplicates` | [`RemoveDuplicatesProcessor`](#model-RemoveDuplicatesProcessor) | nullable | Remove duplicate rows. Not combinable today with `ai`, `filter` or `anonymize` (features incompatible in the engine) — see Processor combinations. |
| `sources` | array of [`SourceFile`](#model-SourceFile) or [`SourceFolder-Input`](#model-SourceFolder-Input) or [`SourceWebhook`](#model-SourceWebhook) or [`SourceAPI`](#model-SourceAPI) or [`SourceIntegration`](#model-SourceIntegration) or [`SourceBigQuery`](#model-SourceBigQuery) or [`SourceOutlook-Input`](#model-SourceOutlook-Input) or [`SourceGmail-Input`](#model-SourceGmail-Input) | required | List of sources to connect to |
| `split` | [`Split`](#model-Split) | nullable | Split step options |
| `transfer_format` | boolean | nullable | Transfer format Default: `false` |
| `workflow_id` | string | required | Id of the workflow this automation belongs to |

##### Responses

| Status | Meaning | Body |
| --- | --- | --- |
| 200 | The automation model updated | [`AutomationModel`](#model-AutomationModel) |
| 401 | Authentication failed or token is invalid | — |
| 403 | The plan does not include this destination type | — |
| 404 | Not found | — |
| 412 | `send_from` names an Outlook account that is not connected or cannot send mail (`outlook_not_connected`), or `ai.model` / `ai.model_settings` without your own OpenAI account (`openai_not_connected`), or an Outlook source whose account cannot read mail (`outlook_not_connected`, Mail.Read), or a Gmail source whose Google account cannot read mail (`gmail_not_connected`, gmail.readonly) | — |
| 422 | Invalid destination combination, recipient format, api-source shape, integration source, endpoint, api destination or bigquery combination, documents automation (invalid\_documents\_automation), file\_filter (invalid\_file\_filter), Outlook automation (invalid\_outlook\_automation), Gmail automation (invalid\_gmail\_automation), email\_filter (invalid\_email\_filter), or a processor combination that is not allowed (invalid\_processor\_combination), or a column that is not a spreadsheet letter (invalid\_column) | — |

##### Example request

```
curl -s -X PUT "https://api.sheetgo.com/rest/beta/automations/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/automations#put-rest-beta-automations-id>

#### PATCH `/rest/beta/automations/{id}` — Rename an automation

**Renames only.** The body is `{"name": "…"}`; any other field is rejected with 422. To change sources, destinations or processors (`filter`, `merge`, `ai`, `left_join`, `remove_duplicates`, `split`, `anonymize`), `GET` the automation, edit it and send it back with `PUT` — GET returns everything PUT accepts, so the rest of the automation is kept.

##### Parameters

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

##### Request body (required)

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

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `name` | string | required | New name of the automation Min length: `1` |

##### Responses

| Status | Meaning | Body |
| --- | --- | --- |
| 200 | The automation model updated | [`AutomationModel`](#model-AutomationModel) |
| 401 | Authentication failed or token is invalid | — |
| 404 | Not found | — |
| 422 | `name` missing or empty, or a field other than `name` (PATCH only renames) | — |

##### Example request

```
curl -s -X PATCH "https://api.sheetgo.com/rest/beta/automations/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/automations#patch-rest-beta-automations-id>

#### DELETE `/rest/beta/automations/{id}` — Archive an automation

Given a workflow id, archive the workflow

##### Parameters

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

##### Responses

| Status | Meaning | Body |
| --- | --- | --- |
| 200 | The automation was successfully archived | [`SuccessResponse`](#model-SuccessResponse) |
| 401 | Authentication failed or token is invalid | — |
| 404 | Not found | — |
| 422 | Validation Error | [`HTTPValidationError`](#model-HTTPValidationError) |

##### Example request

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

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

#### GET `/rest/beta/automations/{id}/destinations` — Get file destinations of an automation

Return the file/folder destinations of an automation.

Destinations include generated-document and PDF destinations, which are
backed by a Drive folder (and, for documents, the Docs template).

##### Parameters

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

##### Responses

| Status | Meaning | Body |
| --- | --- | --- |
| 200 | File destinations of the automation | any |
| 401 | Authentication failed or token is invalid | — |
| 404 | Not found | — |
| 422 | Validation Error | [`HTTPValidationError`](#model-HTTPValidationError) |

##### Example request

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

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

#### GET `/rest/beta/automations/{id}/files` — Get file sources and destinations of an automation

Return the sources and destinations of an automation.

Every source type is included (file, folder, api, webhook, integration,
bigquery, outlook); write-only fields such as an api source's headers
are omitted.

Destinations include generated-document and PDF destinations, which are
backed by a Drive folder (and, for documents, the Docs template).

##### Parameters

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

##### Responses

| Status | Meaning | Body |
| --- | --- | --- |
| 200 | File sources and destinations of the automation | any |
| 401 | Authentication failed or token is invalid | — |
| 404 | Not found | — |
| 422 | Validation Error | [`HTTPValidationError`](#model-HTTPValidationError) |

##### Example request

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

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

#### GET `/rest/beta/automations/{id}/run` — Get an automation's last-run status

Last-run execution status of a single automation (latest only — no history).

##### Parameters

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

##### Responses

| Status | Meaning | Body |
| --- | --- | --- |
| 200 | Automation last-run status | [`AutomationRunStatus`](#model-AutomationRunStatus) |
| 401 | Authentication failed or token is invalid | — |
| 404 | Automation not found | — |
| 422 | Validation Error | [`HTTPValidationError`](#model-HTTPValidationError) |

##### Example request

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

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

#### POST `/rest/beta/automations/{id}/run` — Run an automation

Given an automation Id, the automation will start its execution

##### Parameters

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

##### Responses

| Status | Meaning | Body |
| --- | --- | --- |
| 200 | successful operation | [`SuccessResponse`](#model-SuccessResponse) |
| 401 | Authentication failed or token is invalid | — |
| 404 | Not found | — |
| 422 | Validation Error | [`HTTPValidationError`](#model-HTTPValidationError) |

##### Example request

```
curl -s -X POST "https://api.sheetgo.com/rest/beta/automations/ID/run" \
  -H "Authorization: Bearer $SHEETGO_API_KEY"
```

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

#### GET `/rest/beta/automations/{id}/sources` — Get file sources of an automation

Return the sources of an automation.

Every source type is included (file, folder, api, webhook, integration,
bigquery, outlook), in the shape `GET /rest/beta/automations/{id}` returns;
write-only fields such as an api source's headers are omitted.

##### Parameters

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

##### Responses

| Status | Meaning | Body |
| --- | --- | --- |
| 200 | File sources of the automation | any |
| 401 | Authentication failed or token is invalid | — |
| 404 | Not found | — |
| 422 | Validation Error | [`HTTPValidationError`](#model-HTTPValidationError) |

##### Example request

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

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

## Models used on this page

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

#### `AIProcessor`

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `model` | string | nullable | OpenAI model id (e.g. `gpt-5.2`) or Assistant id (`asst_…`). Needs your own OpenAI account connected in the Sheetgo web app (412 `openai_not_connected` otherwise). Without it, a connected key still runs Sheetgo's default model. |
| `model_settings` | [`ModelSettings`](#model-ModelSettings) | nullable | Model parameters. Same OpenAI-account requirement as `model`. |
| `on_processing_error` | [`OnProcessingError`](#model-OnProcessingError) | nullable | Documents folder only: `continue` (default) keeps going when a document cannot be read; `stop` fails the run. |
| `prompt` | string | required | The AI prompt: what the AI step should do with the data. For a documents folder source it says what to extract, and its wording is the column contract. |

#### `AnonymizeMethod`

The web app's masking methods (core-lib v1/dataframe/anonymizer.py).

**Type:** one of `"salted_hash"`, `"hash"`, `"nullify"`, `"redact"`, `"partial_email"`, `"partial_start"`, `"partial_end"`, `"generalization"`

#### `AnonymizeMode`

`automatic`: Google DLP (Sheetgo's project) detects personal data and
hashes it. `custom`: a masking method per column.

**Type:** one of `"automatic"`, `"custom"`

#### `AnonymizeProcessor`

Mask personal data before it reaches the destination (the web app's
Anonymize step).

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `columns` | object (map of string → [`AnonymizeMethod`](#model-AnonymizeMethod)) | nullable | Custom mode only: column LETTER (`A`, `B`, …) → method: salted\_hash, hash, nullify, redact, partial\_email, partial\_start (first 2 characters + ***), partial\_end (*** + last 4), generalization (numbers grouped into ranges). |
| `mode` | [`AnonymizeMode`](#model-AnonymizeMode) | optional | `automatic`: personal data is detected (Google DLP, on Sheetgo's account) and hashed. `custom`: you choose a method per column. Not combinable today with `ai`, `filter` or `remove_duplicates` (features incompatible in the engine) — see Processor combinations. Default: `"custom"` |

#### `AutomationCreate`

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `ai` | [`AIProcessor`](#model-AIProcessor) | nullable | AI step options |
| `anonymize` | [`AnonymizeProcessor`](#model-AnonymizeProcessor) | nullable | Anonymize step options. Not combinable today with `ai`, `filter` or `remove_duplicates` (features incompatible in the engine) — see Processor combinations. |
| `destinations` | array of one of (chosen by `type`): `type: "api"` → [`DestinationApiPublish`](#model-DestinationApiPublish), `type: "bigquery"` → [`DestinationBigQuery-Input`](#model-DestinationBigQuery-Input), `type: "document"` → [`DestinationDocument`](#model-DestinationDocument), `type: "file"` → [`DestinationFile`](#model-DestinationFile), `type: "folder"` → [`DestinationFolder`](#model-DestinationFolder), `type: "mail_merge"` → [`DestinationMailMerge`](#model-DestinationMailMerge), `type: "pdf"` → [`DestinationPDF`](#model-DestinationPDF), `type: "share"` → [`DestinationShare`](#model-DestinationShare), `type: "webhook"` → [`DestinationWebhook`](#model-DestinationWebhook) or one of (chosen by `type`): `type: "api"` → [`DestinationApiPublish`](#model-DestinationApiPublish), `type: "bigquery"` → [`DestinationBigQuery-Input`](#model-DestinationBigQuery-Input), `type: "document"` → [`DestinationDocument`](#model-DestinationDocument), `type: "file"` → [`DestinationFile`](#model-DestinationFile), `type: "folder"` → [`DestinationFolder`](#model-DestinationFolder), `type: "mail_merge"` → [`DestinationMailMerge`](#model-DestinationMailMerge), `type: "pdf"` → [`DestinationPDF`](#model-DestinationPDF), `type: "share"` → [`DestinationShare`](#model-DestinationShare), `type: "webhook"` → [`DestinationWebhook`](#model-DestinationWebhook) | nullable | Destinations to connect to |
| `filter` | [`FilterCondition-Input`](#model-FilterCondition-Input) or [`FilterColumn`](#model-FilterColumn) or [`FilterQuery`](#model-FilterQuery) | nullable | Filter step options. Columns are spreadsheet LETTERS — get them from `GET /rest/beta/files/{provider}/{file_id}/structure?include=columns` on the source file (see Column letters). Not combinable today with `remove_duplicates` or `anonymize` (features incompatible in the engine) — see Processor combinations. |
| `left_join` | [`LeftJoinProcessor`](#model-LeftJoinProcessor) | nullable | Left join step options |
| `merge` | [`MergeProcessor`](#model-MergeProcessor) | nullable | Merge step options |
| `name` | string | required | Name of the automation |
| `number_format` | boolean | nullable | Number format Default: `false` |
| `remove_duplicates` | [`RemoveDuplicatesProcessor`](#model-RemoveDuplicatesProcessor) | nullable | Remove duplicate rows. Not combinable today with `ai`, `filter` or `anonymize` (features incompatible in the engine) — see Processor combinations. |
| `sources` | array of [`SourceFile`](#model-SourceFile) or [`SourceFolder-Input`](#model-SourceFolder-Input) or [`SourceWebhook`](#model-SourceWebhook) or [`SourceAPI`](#model-SourceAPI) or [`SourceIntegration`](#model-SourceIntegration) or [`SourceBigQuery`](#model-SourceBigQuery) or [`SourceOutlook-Input`](#model-SourceOutlook-Input) or [`SourceGmail-Input`](#model-SourceGmail-Input) | required | List of sources to connect to |
| `split` | [`Split`](#model-Split) | nullable | Split step options |
| `transfer_format` | boolean | nullable | Transfer format Default: `false` |
| `workflow_id` | string | required | Id of the workflow this automation belongs to |

Used by: [POST /rest/beta/automations/](/api/automations.md#post-rest-beta-automations)

#### `AutomationModel`

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `ai` | [`AIProcessor`](#model-AIProcessor) | nullable | The AI step, when the automation has one. |
| `anonymize` | [`AnonymizeProcessor`](#model-AnonymizeProcessor) | nullable | The Anonymize step, when the automation has one. |
| `destinations` | array of one of (chosen by `type`): `type: "api"` → [`DestinationApiPublish`](#model-DestinationApiPublish), `type: "bigquery"` → [`DestinationBigQuery-Output`](#model-DestinationBigQuery-Output), `type: "document"` → [`DestinationDocument`](#model-DestinationDocument), `type: "file"` → [`DestinationFile`](#model-DestinationFile), `type: "folder"` → [`DestinationFolder`](#model-DestinationFolder), `type: "mail_merge"` → [`DestinationMailMerge`](#model-DestinationMailMerge), `type: "pdf"` → [`DestinationPDF`](#model-DestinationPDF), `type: "share"` → [`DestinationShare`](#model-DestinationShare), `type: "webhook"` → [`DestinationWebhook`](#model-DestinationWebhook) or one of (chosen by `type`): `type: "api"` → [`DestinationApiPublish`](#model-DestinationApiPublish), `type: "bigquery"` → [`DestinationBigQuery-Output`](#model-DestinationBigQuery-Output), `type: "document"` → [`DestinationDocument`](#model-DestinationDocument), `type: "file"` → [`DestinationFile`](#model-DestinationFile), `type: "folder"` → [`DestinationFolder`](#model-DestinationFolder), `type: "mail_merge"` → [`DestinationMailMerge`](#model-DestinationMailMerge), `type: "pdf"` → [`DestinationPDF`](#model-DestinationPDF), `type: "share"` → [`DestinationShare`](#model-DestinationShare), `type: "webhook"` → [`DestinationWebhook`](#model-DestinationWebhook) | nullable | Destinations of the automation |
| `execution` | [`ExecutionStatus`](#model-ExecutionStatus) | nullable | Execution status of the automation Default: `"completed"` |
| `filter` | [`FilterCondition-Output`](#model-FilterCondition-Output) or [`FilterColumn`](#model-FilterColumn) or [`FilterQuery`](#model-FilterQuery) | nullable | The Filter step, when the automation has one the API can represent (nested groups, colour filters and conditions combined with a column selection read back as null). |
| `id` | string | required | Id of the automation |
| `input_count` | integer | nullable | Number of inputs of the automation Default: `0` |
| `last_updating_user` | string | nullable | Last updated user of the automation |
| `left_join` | [`LeftJoinProcessor`](#model-LeftJoinProcessor) | nullable | The Left join step, when the automation has one. |
| `merge` | [`MergeProcessor`](#model-MergeProcessor) | nullable | The Merge step, when the automation has one. |
| `name` | string | required | Name of the automation |
| `output_count` | integer | nullable | Number of outputs of the automation Default: `0` |
| `owner` | string | required | Owner of the automation |
| `remove_duplicates` | [`RemoveDuplicatesProcessor`](#model-RemoveDuplicatesProcessor) | nullable | The Remove duplicates step, when the automation has one. |
| `sources` | array of [`SourceFile`](#model-SourceFile) or [`SourceFolder-Output`](#model-SourceFolder-Output) or [`SourceWebhook`](#model-SourceWebhook) or [`SourceAPI`](#model-SourceAPI) or [`SourceIntegration`](#model-SourceIntegration) or [`SourceBigQuery`](#model-SourceBigQuery) or [`SourceOutlook-Output`](#model-SourceOutlook-Output) or [`SourceGmail-Output`](#model-SourceGmail-Output) | optional | Sources of the automation |
| `split` | [`Split`](#model-Split) | nullable | The Split step, when the automation has one. |
| `status` | integer | nullable | Execution result code: 0 = never executed, 1 = executed successfully, > 1 = error (inspect status\_message / status\_docs\_link). Default: `0` |
| `status_docs_link` | string | nullable | Documentation link for the error when status > 1. |
| `status_message` | string | nullable | Human-readable error description when status > 1. |

Used by: [POST /rest/beta/automations/](/api/automations.md#post-rest-beta-automations), [GET /rest/beta/automations/{id}](/api/automations.md#get-rest-beta-automations-id), [PUT /rest/beta/automations/{id}](/api/automations.md#put-rest-beta-automations-id), [PATCH /rest/beta/automations/{id}](/api/automations.md#patch-rest-beta-automations-id)

#### `AutomationPatch`

Rename only. Unknown fields are rejected (SG-14706): they used to be dropped
with a 200, and a missing `name` was saved as null, blanking the automation.

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `name` | string | required | New name of the automation Min length: `1` |

Used by: [PATCH /rest/beta/automations/{id}](/api/automations.md#patch-rest-beta-automations-id)

#### `AutomationReplace`

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `ai` | [`AIProcessor`](#model-AIProcessor) | nullable | AI step options |
| `anonymize` | [`AnonymizeProcessor`](#model-AnonymizeProcessor) | nullable | Anonymize step options. Not combinable today with `ai`, `filter` or `remove_duplicates` (features incompatible in the engine) — see Processor combinations. |
| `destinations` | array of one of (chosen by `type`): `type: "api"` → [`DestinationApiPublish`](#model-DestinationApiPublish), `type: "bigquery"` → [`DestinationBigQuery-Input`](#model-DestinationBigQuery-Input), `type: "document"` → [`DestinationDocument`](#model-DestinationDocument), `type: "file"` → [`DestinationFile`](#model-DestinationFile), `type: "folder"` → [`DestinationFolder`](#model-DestinationFolder), `type: "mail_merge"` → [`DestinationMailMerge`](#model-DestinationMailMerge), `type: "pdf"` → [`DestinationPDF`](#model-DestinationPDF), `type: "share"` → [`DestinationShare`](#model-DestinationShare), `type: "webhook"` → [`DestinationWebhook`](#model-DestinationWebhook) or one of (chosen by `type`): `type: "api"` → [`DestinationApiPublish`](#model-DestinationApiPublish), `type: "bigquery"` → [`DestinationBigQuery-Input`](#model-DestinationBigQuery-Input), `type: "document"` → [`DestinationDocument`](#model-DestinationDocument), `type: "file"` → [`DestinationFile`](#model-DestinationFile), `type: "folder"` → [`DestinationFolder`](#model-DestinationFolder), `type: "mail_merge"` → [`DestinationMailMerge`](#model-DestinationMailMerge), `type: "pdf"` → [`DestinationPDF`](#model-DestinationPDF), `type: "share"` → [`DestinationShare`](#model-DestinationShare), `type: "webhook"` → [`DestinationWebhook`](#model-DestinationWebhook) | nullable | Destinations to connect to |
| `filter` | [`FilterCondition-Input`](#model-FilterCondition-Input) or [`FilterColumn`](#model-FilterColumn) or [`FilterQuery`](#model-FilterQuery) | nullable | Filter step options. Columns are spreadsheet LETTERS — get them from `GET /rest/beta/files/{provider}/{file_id}/structure?include=columns` on the source file (see Column letters). Not combinable today with `remove_duplicates` or `anonymize` (features incompatible in the engine) — see Processor combinations. |
| `id` | string | required | Id of the automation |
| `left_join` | [`LeftJoinProcessor`](#model-LeftJoinProcessor) | nullable | Left join step options |
| `merge` | [`MergeProcessor`](#model-MergeProcessor) | nullable | Merge step options |
| `name` | string | required | Name of the automation |
| `number_format` | boolean | nullable | Number format Default: `false` |
| `remove_duplicates` | [`RemoveDuplicatesProcessor`](#model-RemoveDuplicatesProcessor) | nullable | Remove duplicate rows. Not combinable today with `ai`, `filter` or `anonymize` (features incompatible in the engine) — see Processor combinations. |
| `sources` | array of [`SourceFile`](#model-SourceFile) or [`SourceFolder-Input`](#model-SourceFolder-Input) or [`SourceWebhook`](#model-SourceWebhook) or [`SourceAPI`](#model-SourceAPI) or [`SourceIntegration`](#model-SourceIntegration) or [`SourceBigQuery`](#model-SourceBigQuery) or [`SourceOutlook-Input`](#model-SourceOutlook-Input) or [`SourceGmail-Input`](#model-SourceGmail-Input) | required | List of sources to connect to |
| `split` | [`Split`](#model-Split) | nullable | Split step options |
| `transfer_format` | boolean | nullable | Transfer format Default: `false` |
| `workflow_id` | string | required | Id of the workflow this automation belongs to |

Used by: [PUT /rest/beta/automations/{id}](/api/automations.md#put-rest-beta-automations-id)

#### `AutomationRunStatus`

The outcome of an automation's LAST run. There is no run history.

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `automation_id` | string | required | Id of the automation this status belongs to. |
| `docs_link` | string | nullable | URL of the help article for this error, when one exists. Null unless `result` is `error`. |
| `duration_seconds` | number | nullable | How long the last run took, in seconds. Null before the first run completes. |
| `error_count` | integer | nullable | Number of individual errors recorded during the run (a run can fail on several rows or files). Null when not tracked. |
| `execution` | string | required | Live phase: `running` while the run is enqueued, executing or cancelling; `completed` once it has stopped. Poll until this is `completed` before trusting `result`. |
| `message` | string | nullable | Human-readable explanation of the run's outcome — the stored run message when there is one, otherwise the standard description for `status_code`. Null on success and before the first run. |
| `result` | string | required | Outcome of the last finished run: `never_run` (it has not run yet), `success`, or `error`. While `execution` is `running`, this still describes the PREVIOUS run. |
| `status_code` | integer | optional | Sheetgo result code behind `result`: 0 = never run, 1 = success, anything greater = the specific error. Useful when you want to branch on the exact failure. Default: `0` |

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

#### `BigQueryPartition`

Partitioning for a table Sheetgo creates.

Omit `field` for ingestion-time partitioning; name a column for
field-based. There is no third setting: BigQuery infers the partition
column's *type* from the table schema, so presence of `field` is the whole
distinction.

Only applied when the table is created. An existing table keeps its own
partitioning, so change it with `write_mode: "recreate"`.

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `field` | string | nullable | Column to partition by. It must exist in the transferred data -- check with `GET /rest/beta/bigquery/.../tables/{table}`. Omit for ingestion-time partitioning. |
| `granularity` | [`BigQueryPartitionGranularity`](#model-BigQueryPartitionGranularity) | optional | Partition size: HOUR, DAY, MONTH or YEAR. Default: `"DAY"` |
| `require_filter` | boolean | optional | Require queries against the table to filter on the partition column. Applied only when the table is created. Default: `false` |

#### `BigQueryPartitionGranularity`

**Type:** one of `"HOUR"`, `"DAY"`, `"MONTH"`, `"YEAR"`

#### `BigQueryWriteMode`

What happens to data already in the destination table.

Read by `BigQueryManager.merge_temporary_to_destination`.

**Type:** one of `"append"`, `"truncate"`, `"recreate"`

#### `ConditionExpression`

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `column` | string | optional | Spreadsheet column letter (`A`, `B`, … `AA`), uppercase, as in the web app — not the header name. Find letters with `GET /rest/beta/files/{provider}/{file_id}/structure?include=columns`. Example: `"D"` |
| `criteria` | [`ExpressionCriteria`](#model-ExpressionCriteria) | optional | The criteria |
| `value` | number or integer or string | nullable | The value |

#### `ConditionType`

**Type:** one of `"and"`, `"or"`

#### `ContentType`

What a folder source reads: spreadsheets, or documents for AI extraction.

**Type:** one of `"spreadsheets"`, `"documents"`

#### `DestinationApiPublish`

Publish the automation's rows to a Sheetgo-hosted endpoint you can poll.

Read it back with `GET /rest/beta/api-destination/{public_id}`, which needs
an API key carrying the `api-destination` scope.

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `append` | boolean | optional | Add each run's rows under the previous ones instead of replacing them. The column headers must match the existing ones or the run fails. Default: `false` |
| `public_id` | string | nullable | Read-only. Assigned by Sheetgo when the automation is created; ignored if you send it. |
| `type` | `"api"` | required | Publishes the rows as a read-only JSON **API endpoint** hosted by Sheetgo. |
| `url` | string | nullable | Read-only. Where to fetch the published data. Requires an API key with the `api-destination` scope. |

#### `DestinationBigQuery-Input`

Load the automation's rows into a BigQuery table.

The table is created on the first run if it does not exist; the **dataset**
is not, and must already exist.

Must be the automation's only destination, and at most one per automation --
see validate\_bigquery\_automation.

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `dataset` | string | required | Existing BigQuery dataset id. Sheetgo does not create datasets. |
| `partition` | [`BigQueryPartition`](#model-BigQueryPartition) | nullable | Omit for an unpartitioned table. |
| `project` | string | required | GCP project id |
| `schema_evolution` | boolean | optional | Add columns to the destination table when the transferred data has new ones. With the default `false`, extra columns fail the run instead. Only ever adds -- never removes, renames or retypes. Default: `false` |
| `table` | string | required | Table id. Created on the first run if it does not exist. |
| `type` | `"bigquery"` | required | Writes the rows into a **BigQuery** table. Must be the only destination. |
| `write_mode` | [`BigQueryWriteMode`](#model-BigQueryWriteMode) | optional | `append` adds rows; `truncate` clears the data but keeps the schema and partitioning; `recreate` drops and rebuilds the table from the transferred data. Default: `"append"` |

#### `DestinationBigQuery-Output`

Load the automation's rows into a BigQuery table.

The table is created on the first run if it does not exist; the **dataset**
is not, and must already exist.

Must be the automation's only destination, and at most one per automation --
see validate\_bigquery\_automation.

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `dataset` | string | required | Existing BigQuery dataset id. Sheetgo does not create datasets. |
| `partition` | [`BigQueryPartition`](#model-BigQueryPartition) | nullable | Omit for an unpartitioned table. |
| `project` | string | required | GCP project id |
| `schema_evolution` | boolean | optional | Add columns to the destination table when the transferred data has new ones. With the default `false`, extra columns fail the run instead. Only ever adds -- never removes, renames or retypes. Default: `false` |
| `table` | string | required | Table id. Created on the first run if it does not exist. |
| `type` | `"bigquery"` | required | Writes the rows into a **BigQuery** table. Must be the only destination. |
| `write_mode` | [`BigQueryWriteMode`](#model-BigQueryWriteMode) | optional | `append` adds rows; `truncate` clears the data but keeps the schema and partitioning; `recreate` drops and rebuilds the table from the transferred data. Default: `"append"` |

#### `DestinationDocument`

Generate one Google Docs file per row from a template (docs-merge).

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `file_name` | string | required | Name pattern for each generated document. Supports {{Column}} smart tags, which are replaced with that row's value — e.g. "Invoice {{Customer}} {{Month}}". See the Smart Tags section. |
| `folder_name` | string | nullable | Name of a new folder to create instead of using an existing one. Provide this or `id`. |
| `generator_controller` | boolean | optional | Add a column to the source data holding a link to each generated document. Default: `true` |
| `generator_controller_prefix` | string | nullable | Prefix for the control column's header. Defaults to the automation name. |
| `id` | string | nullable | Id of an existing folder to write into. Provide this or `folder_name`. |
| `markdown_formatting` | boolean | optional | Render markdown found in cell values as formatted text in the document. Default: `false` |
| `parent_id` | string | nullable | Folder to create `folder_name` inside. Defaults to the drive root. Only valid together with `folder_name`. |
| `provider` | `"drive"` | optional | Storage provider. Generated documents and PDFs are Google Drive only. Default: `"drive"` |
| `template_id` | string | required | Id of the Google Docs file used as the template. Google Drive only. Google Docs are **not returned by default** by the file endpoints — find one with `GET /rest/beta/files/drive?type=gdocs`. |
| `type` | `"document"` | required | Generates a Google **Docs document** per row from a template (docs-merge). |
| `unused_fields` | [`UnusedFields`](#model-UnusedFields) | optional | What to do when a {{Tag}} in the template matches no source column: `error` fails the run, `ignore` leaves it blank. Default: `"error"` |

#### `DestinationFile`

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `append` | boolean | nullable | Data will be added under previous entries to track historical changes. Always on after an email source with `extract=fields_table`. Default: `false` |
| `enforce_header_match` | boolean | optional | Documents folder source only: line documents' columns up by position instead of by name. Ignored with `one_tab_per_document`. Default: `false` |
| `file_type` | [`FileType`](#model-FileType) | required | The file type |
| `id` | string | required | Id of the destination file or folder |
| `identify_data` | [`IdentifyDataType`](#model-IdentifyDataType) | nullable | It will create an extra column in the destination tab, identifying the latest transfers of your new sheet and/or the source file of each row of data, making data traceable when merging sources. |
| `lock_destination_tab` | boolean | nullable | Lock the destination tab and clear added columns with each transfer Default: `true` |
| `one_tab_per_document` | boolean | optional | Documents folder source only: one tab per document (up to 100) instead of all documents in one tab. Default: `false` |
| `parse_data` | boolean | nullable | Convert text to numbers, dates, and formulas Default: `true` |
| `provider` | [`Provider`](#model-Provider) | required | The storage provider that hosts the file or folder |
| `sheet_name` | string | nullable | The sheet name |
| `type` | `"file"` | required | Writes the result into an existing **file**. |
| `write_summary_tab` | boolean | optional | Documents folder source only: add a `Files` tab listing each document read, its status and row count. Default: `false` |

#### `DestinationFolder`

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `append` | boolean | nullable | Data will be added under previous entries to track historical changes. Always on after an email source with `extract=fields_table`. Default: `false` |
| `enforce_header_match` | boolean | optional | Documents folder source only: line documents' columns up by position instead of by name. Ignored with `one_tab_per_document`. Default: `false` |
| `file_type` | `"folder"` | optional | Always `folder`. Fixed by the destination type; present so folder and file destinations share one shape. Default: `"folder"` |
| `folder_name` | string | nullable | Outlook source only: name of a new folder Sheetgo creates when the automation is saved. Provide this or `id`. Each create makes a new folder (a repeated POST makes another); GET then returns its `id`. |
| `id` | string | nullable | Id of an existing folder. Provide this or `folder_name`. |
| `identify_data` | [`IdentifyDataType`](#model-IdentifyDataType) | nullable | It will create an extra column in the destination tab, identifying the latest transfers of your new sheet and/or the source file of each row of data, making data traceable when merging sources. |
| `lock_destination_tab` | boolean | nullable | Lock the destination tab and clear added columns with each transfer Default: `true` |
| `one_tab_per_document` | boolean | optional | Documents folder source only: one tab per document (up to 100) instead of all documents in one tab. Default: `false` |
| `parent_id` | string | nullable | Folder to create `folder_name` inside. Defaults to the provider's root. Only valid with `folder_name`. |
| `parse_data` | boolean | nullable | Convert text to numbers, dates, and formulas Default: `true` |
| `provider` | [`Provider`](#model-Provider) | required | The storage provider that hosts the file or folder |
| `sheet_name` | string | nullable | The sheet name |
| `type` | `"folder"` | required | Writes into a **folder**: new files per split value, or the files an Outlook source saves. |
| `write_summary_tab` | boolean | optional | Documents folder source only: add a `Files` tab listing each document read, its status and row count. Default: `false` |

#### `DestinationMailMerge`

Send one personalized email per row, rendered from `body`.

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `bcc` | array of string (email) or string | nullable | Bcc recipients. Same forms as `to`. |
| `body` | string | required | Email body template as plain text. Each line becomes one paragraph. {{Column}} smart tags are replaced per row. |
| `cc` | array of string (email) or string | nullable | Cc recipients. Same forms as `to`. |
| `generator_controller` | boolean | optional | Add a column to the source data tracking each email sent. Default: `true` |
| `generator_controller_prefix` | string | nullable | Prefix for the control column's header. Defaults to the automation name. |
| `markdown_formatting` | boolean | optional | Render markdown found in cell values as formatted text. Default: `false` |
| `multiple_email_split` | boolean | optional | Send a separate email per address when a column holds several. Default: `false` |
| `remove_sheetgo_layout` | boolean | optional | Send without the Sheetgo email layout. Default: `false` |
| `reply_to` | string | nullable | Reply-To: one address, or a "{{Header}}" reference. |
| `send_from` | [`SendFrom`](#model-SendFrom) | optional | Which mailbox sends the emails: `gmail` (default), `outlook_personal` (a personal Microsoft account) or `outlook_work` (a work or school Microsoft account). An Outlook account must be connected in Sheetgo with permission to send mail, or the request is rejected with 412 `outlook_not_connected`. Default: `"gmail"` |
| `subject` | string | required | Email subject. Supports {{Column}} smart tags. |
| `to` | array of string (email) or string | required | Recipients: a list of addresses, one address, or a "{{Header}}" reference to read the address from a column. |
| `track_click` | boolean | optional | Track when a recipient clicks a link. Default: `false` |
| `track_open` | boolean | optional | Track when a recipient opens the email. Default: `false` |
| `type` | `"mail_merge"` | required | Sends one personalized email per row (**mail merge**). |
| `unused_fields` | [`UnusedFields`](#model-UnusedFields) | optional | What to do when a {{Tag}} matches no source column: `error` fails the run, `ignore` leaves it blank. Default: `"error"` |
| `use_plain_text` | boolean | optional | Send the body as plain text instead of formatted HTML. Default: `false` |

#### `DestinationPDF`

Export the automation's output to PDF into a Drive folder (converter).

What gets converted depends on the automation's other destinations: with a
`document` destination the generated documents are converted; with a file
destination the file written by the automation is converted; with neither,
the automation's source files are.

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `folder_name` | string | nullable | Name of a new folder to create instead of using an existing one. Provide this or `id`. |
| `id` | string | nullable | Id of an existing folder to write into. Provide this or `folder_name`. |
| `merge_files` | boolean | optional | Combine every generated PDF into a single file. Default: `false` |
| `page_orientation` | [`PageOrientation`](#model-PageOrientation) | optional | Page orientation of the generated PDF. Default: `"portrait"` |
| `paper_size` | [`PaperSize`](#model-PaperSize) | optional | Page size of the generated PDF. Default: `"letter"` |
| `parent_id` | string | nullable | Folder to create `folder_name` inside. Defaults to the drive root. Only valid together with `folder_name`. |
| `provider` | `"drive"` | optional | Storage provider. Generated documents and PDFs are Google Drive only. Default: `"drive"` |
| `scale` | one of `1`, `2`, `3`, `4` | optional | Fit-to-page scaling: 1 normal, 2 fit to width, 3 fit to height, 4 fit to page. Default: `1` |
| `type` | `"pdf"` | required | Generates a **PDF** per row, by converting the merged document. |

#### `DestinationShare`

Email the files this automation produced.

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `bcc` | array of string (email) or string | nullable | Bcc recipients. Same forms as `to`. |
| `body` | string | nullable | Email body as plain text. Each line becomes one paragraph. Supports {{Column}} smart tags. |
| `cc` | array of string (email) or string | nullable | Cc recipients. Same forms as `to`. |
| `file_access_role` | [`FileAccessRole`](#model-FileAccessRole) | optional | Access granted by a shared link. Ignored for attachments. Default: `"writer"` |
| `file_sending_method` | [`FileSendingMethod`](#model-FileSendingMethod) | optional | Send the files as shared links or as attachments. Default: `"shared_link"` |
| `group_files_by_recipient` | boolean | optional | Send one email per recipient covering all their files, instead of one email per file. Default: `true` |
| `multiple_email_split` | boolean | optional | Send a separate email per address when a column holds several. Default: `false` |
| `remove_sheetgo_layout` | boolean | optional | Send without the Sheetgo email layout. Default: `false` |
| `reply_to` | string | nullable | Reply-To: one address, or a "{{Header}}" reference. |
| `send_from` | [`SendFrom`](#model-SendFrom) | optional | Alpha — sending share emails from Outlook is not offered in the Sheetgo web app yet and may change. Which mailbox sends the emails: `gmail` (default), `outlook_personal` (a personal Microsoft account) or `outlook_work` (a work or school Microsoft account). An Outlook account must be connected in Sheetgo with permission to send mail, or the request is rejected with 412 `outlook_not_connected`. Default: `"gmail"` |
| `subject` | string | required | Email subject. Supports {{Column}} smart tags. |
| `to` | array of string (email) or string | required | Recipients: a list of addresses, one address, or a "{{Header}}" reference to read the address from a column. |
| `track_click` | boolean | optional | Track when a recipient clicks a link. Default: `false` |
| `track_open` | boolean | optional | Track when a recipient opens the email. Default: `false` |
| `type` | `"share"` | required | **Emails** the automation's output as an attachment or link. |
| `use_plain_text` | boolean | optional | Send the body as plain text instead of formatted HTML. Default: `false` |

#### `DestinationWebhook`

POST the automation's rows to an endpoint you own.

Note the direction: as a **source**, `webhook` means Sheetgo mints a URL
you POST *into*; as a **destination** it means Sheetgo POSTs *out* to a URL
you own.

Must be the automation's only destination — see validate\_api\_automation.

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `body` | string | optional | Body template. `{{DATA}}` is every row including the header, `{{ROWS}}` is the rows as objects keyed by header; `{{for}}`, `{{if}}` and `{{except-last}}` are also available. This is a different syntax from smart tags and from cell references. Default: `"{{DATA}}"` |
| `endpoint` | string | required | URL that receives the request. |
| `headers` | object (map of string → string) | nullable | HTTP headers sent with the request. **Write-only** — never returned by a read, and a PUT that omits it clears it. |
| `method` | one of `"post"`, `"put"`, `"patch"`, `"delete"` | optional | HTTP method used to send the data. Default: `"post"` |
| `type` | `"webhook"` | required | POSTs the resulting rows to **your endpoint** (outgoing webhook). Must be the only destination. |

#### `EmailColumn`

**Type:** one of `"date"`, `"from"`, `"to"`, `"cc"`, `"bcc"`, `"subject"`, `"body"`, `"body_html"`, `"attachments"`, `"message_id"`, `"labels"`

#### `EmailFilter-Input`

Which emails an Outlook source reads. Groups nest (at most 3 deep).

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `condition_type` | one of `"and"`, `"or"` | optional | `and`: every rule must match; `or`: any rule. Default: `"and"` |
| `rules` | array of [`EmailFilter-Input`](#model-EmailFilter-Input) or [`EmailFilterRule`](#model-EmailFilterRule) | required | Conditions or nested groups. Min items: `1` |

#### `EmailFilter-Output`

Which emails an Outlook source reads. Groups nest (at most 3 deep).

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `condition_type` | one of `"and"`, `"or"` | optional | `and`: every rule must match; `or`: any rule. Default: `"and"` |
| `rules` | array of [`EmailFilter-Output`](#model-EmailFilter-Output) or [`EmailFilterRule`](#model-EmailFilterRule) | required | Conditions or nested groups. Min items: `1` |

#### `EmailFilterRule`

One condition of an Outlook source's `email_filter`.

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `field` | one of `"subject"`, `"sender"`, `"to"`, `"cc"`, `"attachment_name"`, `"attachment_size"`, `"has_attachment"` | required | `subject`, `sender` (from address), `to`, `cc` (addresses), `attachment_name`, `attachment_size` (MB) or `has_attachment`. |
| `operator` | string | required | Text fields: contains, not\_contains, is, is\_empty, is\_not\_empty. `attachment_size`: greater\_than, greater\_or\_equal, less\_than, less\_or\_equal, is\_not. `has_attachment`: is. |
| `value` | boolean or integer or number or string | nullable | Text for text fields (omit for is\_empty / is\_not\_empty); a number of MB for `attachment_size`; true or false for `has_attachment`. |

#### `ExecutionStatus`

**Type:** one of `"completed"`, `"running"`

#### `ExpressionCriteria`

**Type:** one of `"number_gt"`, `"number_gte"`, `"number_lt"`, `"number_lte"`, `"number_eq"`, `"number_neq"`, `"date_is"`, `"date_is_before"`, `"date_is_after"`, `"text_contains"`, `"text_does_not_contain"`, `"text_is_exactly"`, `"is_empty"`, `"is_not_empty"`, `"is_true"`, `"is_false"`

#### `FileAccessRole`

**Type:** one of `"reader"`, `"writer"`

#### `FileFilter-Input`

Which files inside a folder source are read. Groups nest.

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `condition_type` | one of `"and"`, `"or"` | optional | `and`: every rule must match; `or`: any rule. Default: `"and"` |
| `rules` | array of [`FileFilter-Input`](#model-FileFilter-Input) or [`FileFilterRule`](#model-FileFilterRule) | required | Conditions or nested groups. Min items: `1` |

#### `FileFilter-Output`

Which files inside a folder source are read. Groups nest.

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `condition_type` | one of `"and"`, `"or"` | optional | `and`: every rule must match; `or`: any rule. Default: `"and"` |
| `rules` | array of [`FileFilter-Output`](#model-FileFilter-Output) or [`FileFilterRule`](#model-FileFilterRule) | required | Conditions or nested groups. Min items: `1` |

#### `FileFilterRule`

One condition of a folder source's `file_filter`.

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `field` | one of `"file_name"`, `"file_type"`, `"date_modified"`, `"content"` | required | What to test: `file_name`, `file_type`, `date_modified` or `content` (an emptiness check by size, not a text search). |
| `operator` | string | required | `file_name`: contains, not\_contains, starts\_with, is. `file_type`: is, is\_not. `date_modified`: within, before, after, between. `content`: is\_empty, is\_not\_empty, is\_near\_empty, is\_not\_near\_empty. |
| `value` | string | nullable | Text for `file_name`; a type for `file_type` (google\_sheets, excel, csv, tsv, pdf, google\_docs); `today`/`last_week`/`last_month` for `within`; a YYYY-MM-DD date for before / after / between. Omit for `content`. |
| `value_to` | string | nullable | End date (YYYY-MM-DD) for `between` only. |

#### `FileSendingMethod`

How the files reach the recipient. Wire values use a hyphen.

**Type:** one of `"shared_link"`, `"attachment"`

#### `FileType`

**Type:** one of `"gsheets"`, `"xlsx"`, `"csv"`, `"tsv"`, `"folder"`

#### `FilterColumn`

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `columns` | array of string | optional | The selected columns. Each is a spreadsheet column letter (`A`, `B`, … `AA`), uppercase, as in the web app — not the header name. Find letters with `GET /rest/beta/files/{provider}/{file_id}/structure?include=columns`. Example: `["A", "C"]` |
| `type` | `"column"` | required | A **column** filter: choose which columns are carried through. |

#### `FilterCondition-Input`

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `columns` | array of string | nullable | The selected columns. Each is a spreadsheet column letter (`A`, `B`, … `AA`), uppercase, as in the web app — not the header name. Find letters with `GET /rest/beta/files/{provider}/{file_id}/structure?include=columns`. Example: `["A", "C"]` |
| `condition_type` | [`ConditionType`](#model-ConditionType) | nullable | The filter condition type |
| `expressions` | array of [`ConditionExpression`](#model-ConditionExpression) | nullable | The filter expression |
| `type` | `"condition"` | required | A **condition** filter: keep rows where a column matches a comparison. |

#### `FilterCondition-Output`

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `columns` | array of string | nullable | The selected columns. Each is a spreadsheet column letter (`A`, `B`, … `AA`), uppercase, as in the web app — not the header name. Find letters with `GET /rest/beta/files/{provider}/{file_id}/structure?include=columns`. Example: `["A", "C"]` |
| `condition_type` | [`ConditionType`](#model-ConditionType) | nullable | The filter condition type |
| `expressions` | array of [`ConditionExpression`](#model-ConditionExpression) | nullable | The filter expression |
| `type` | `"condition"` | required | A **condition** filter: keep rows where a column matches a comparison. |

#### `FilterQuery`

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `query` | string | required | The filter query string |
| `type` | `"query"` | required | A **query** filter: keep rows matching an sgql expression. |

#### `GmailExtract`

**Type:** one of `"attachments"`, `"body"`, `"fields"`, `"fields_table"`

#### `GmailMailbox`

Where a Gmail source reads — the three the web app offers. The values are
the ones the services Gmail source maps to a search (`in:inbox`, `in:sent`,
`in:anywhere`), so they are stored as they are.

**Type:** one of `"inbox"`, `"sent"`, `"anywhere"`

#### `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)

#### `IdentifyDataType`

**Type:** one of `"source_file_location"`, `"source_file_name"`, `"source_file_creation_date"`, `"source_file_update_date"`, `"source_tab_name"`, `"destination_file_transfer_datetime"`

#### `ImportMode`

Which files a folder source imports, ordered by modified time.

**Type:** one of `"all_newest_first"`, `"all_oldest_first"`, `"newest_file"`, `"oldest_file"`

#### `IntegrationProvider`

Third-party services with a pre-configured, server-managed API source.

Distinct from `Provider`, which lists storage backends. The value is also
the prefix of the compound `service_origin` a compiled source carries
(`shopify:<shop>`), which is what makes core-lib's load\_provider\_manager
pick the provider-specific request manager.

**Type:** one of `"shopify"`, `"quickbooks"`

Used by: [GET /rest/beta/integrations/{provider}/options](/api/integrations.md#get-rest-beta-integrations-provider-options)

#### `KeepDuplicateType`

**Type:** one of `"first"`, `"last"`

#### `LeftJoinProcessor`

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `column` | string | optional | Spreadsheet column letter (`A`, `B`, … `AA`), uppercase, as in the web app — not the header name. Find letters with `GET /rest/beta/files/{provider}/{file_id}/structure?include=columns`. Example: `"A"` |

#### `MergeProcessor`

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `offset_header` | integer | optional | The header position Default: `1` |
| `remove_header` | boolean | optional | Remove header during the merge process Default: `false` |

#### `ModelSettings`

OpenAI settings the AI step passes to the model. Honoured only with the
user's own OpenAI key (core-lib ai\_processor/processors.py).

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `frequency_penalty` | number | nullable |  |
| `max_completion_tokens` | integer | nullable |  |
| `presence_penalty` | number | nullable |  |
| `reasoning_effort` | one of `"low"`, `"medium"`, `"high"` | nullable | Applied by the engine only to models whose id starts with `o`. |
| `temperature` | number | nullable |  |
| `top_p` | number | nullable |  |

#### `OnProcessingError`

What a documents run does when one document cannot be read.

**Type:** one of `"continue"`, `"stop"`

#### `OutlookAccount`

Which connected Microsoft account reads the mailbox.

**Type:** one of `"personal"`, `"work"`

#### `OutlookExtract`

What an email source saves for each message. Gmail offers the same modes
(GmailExtract is generated from this list, so the two cannot drift).

`fields` (SG-14893) was missing here while the web app already saved it, so an
automation in that mode read back WITHOUT its source: the stored value failed this
enum and the parser drops what it cannot map.

**Type:** one of `"attachments"`, `"body"`, `"fields"`, `"fields_table"`

#### `OutlookMailbox`

The mailbox folder to read — the three the web app offers.

**Type:** one of `"inbox"`, `"archive"`, `"sent_items"`

#### `PageOrientation`

**Type:** one of `"portrait"`, `"landscape"`

#### `PaginatedResponse_AutomationModel_`

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `page` | integer | nullable | Page number Default: `1` |
| `per_page` | integer | nullable | Number of items per page Default: `50` |
| `results` | array of [`AutomationModel`](#model-AutomationModel) | optional | List of results |
| `total` | integer | nullable | Total number of pages Default: `0` |

Used by: [GET /rest/beta/automations/](/api/automations.md#get-rest-beta-automations)

#### `PaginationCursor`

Follow a cursor until the response says there is no more.

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `cursor_param` | string | optional | Request parameter carrying the cursor. Default: `"cursor"` |
| `has_more_key` | string | optional | Response key holding the more-pages flag. Default: `"has_more"` |
| `limit` | integer | nullable | Stop once this many items have been collected. Omit (or 0) to keep going until the endpoint runs out. |
| `next_cursor_key` | string | optional | Response key holding the next cursor. Default: `"next_cursor"` |
| `rate_limit` | string | nullable | Pause between requests. Either "N/seconds" — e.g. "100/10" for 100 requests per 10 seconds — or a plain number of seconds, e.g. "0.5". |
| `scope` | one of `"query"`, `"body"` | optional | Where the paging parameters are placed: the query string or the JSON body. Default: `"query"` |
| `type` | `"cursor"` | required | Selects **cursor** pagination: the response carries an opaque cursor that is sent back to fetch the next page. |

#### `PaginationHeaderLink`

Follow a next-page link found in a response header (e.g. RFC 5988 Link).

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `limit` | integer | nullable | Stop once this many items have been collected. Omit (or 0) to keep going until the endpoint runs out. |
| `next_link_key` | string | optional | Response header holding the next-page URL. Default: `"next"` |
| `rate_limit` | string | nullable | Pause between requests. Either "N/seconds" — e.g. "100/10" for 100 requests per 10 seconds — or a plain number of seconds, e.g. "0.5". |
| `type` | `"header-link"` | required | Selects **header-link** pagination: the next page's URL is read from the response's `Link` header. |

#### `PaginationLink`

Follow a next-page link found in the response body.

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `limit` | integer | nullable | Stop once this many items have been collected. Omit (or 0) to keep going until the endpoint runs out. |
| `next_link_key` | string | optional | Response key holding the next-page URL. Default: `"next"` |
| `rate_limit` | string | nullable | Pause between requests. Either "N/seconds" — e.g. "100/10" for 100 requests per 10 seconds — or a plain number of seconds, e.g. "0.5". |
| `type` | `"link"` | required | Selects **link** pagination: the next page's full URL is read out of the response body. |

#### `PaginationOffset`

Advance an offset by the limit until a short page comes back.

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `limit` | integer | nullable | Stop once this many items have been collected. Omit (or 0) to keep going until the endpoint runs out. |
| `limit_param` | string | optional | Request parameter carrying the page size. Default: `"limit"` |
| `offset_param` | string | optional | Request parameter carrying the offset. Default: `"offset"` |
| `rate_limit` | string | nullable | Pause between requests. Either "N/seconds" — e.g. "100/10" for 100 requests per 10 seconds — or a plain number of seconds, e.g. "0.5". |
| `scope` | one of `"query"`, `"body"` | optional | Where the paging parameters are placed: the query string or the JSON body. Default: `"query"` |
| `type` | `"offset"` | required | Selects **offset** pagination: a row offset is advanced by the page size on each request. |

#### `PaginationPage`

Increment a page number until a short page comes back.

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `limit` | integer | nullable | Stop once this many items have been collected. Omit (or 0) to keep going until the endpoint runs out. |
| `page_param` | string | optional | Request parameter carrying the page number. Default: `"page"` |
| `per_page_param` | string | optional | Request parameter carrying the page size. Default: `"per_page"` |
| `rate_limit` | string | nullable | Pause between requests. Either "N/seconds" — e.g. "100/10" for 100 requests per 10 seconds — or a plain number of seconds, e.g. "0.5". |
| `scope` | one of `"query"`, `"body"` | optional | Where the paging parameters are placed: the query string or the JSON body. Default: `"query"` |
| `type` | `"page"` | required | Selects **page-number** pagination: a page counter is incremented until the response runs out of rows. |

#### `PaginationQueryOffset`

Rewrite offset/limit keywords inside a SQL-like query parameter.

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `limit` | integer | nullable | Stop once this many items have been collected. Omit (or 0) to keep going until the endpoint runs out. |
| `query_key` | string | optional | Request parameter holding the query string. Default: `"query"` |
| `query_limit_key` | string | optional | Keyword inside the query that sets the page size. Default: `"limit"` |
| `query_offset_key` | string | optional | Keyword inside the query that sets the offset. Default: `"offset"` |
| `rate_limit` | string | nullable | Pause between requests. Either "N/seconds" — e.g. "100/10" for 100 requests per 10 seconds — or a plain number of seconds, e.g. "0.5". |
| `type` | `"query-offset"` | required | Selects **query-offset** pagination: the offset travels in the query string of the request URL. |

#### `PaperSize`

**Type:** one of `"letter"`, `"tabloid"`, `"legal"`, `"statement"`, `"executive"`, `"folio"`, `"A3"`, `"A4"`, `"A5"`, `"B4"`, `"B5"`

#### `Provider`

**Type:** one of `"drive"`, `"onedrive"`, `"sharepoint"`, `"dropbox"`

Used by: [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/files/{provider}/{file\_id}/structure](/api/files.md#get-rest-beta-files-provider-file-id-structure)

#### `RemoveDuplicatesProcessor`

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `columns` | array of string | optional | The selected columns. Each is a spreadsheet column letter (`A`, `B`, … `AA`), uppercase, as in the web app — not the header name. Find letters with `GET /rest/beta/files/{provider}/{file_id}/structure?include=columns`. Example: `["A", "C"]` |
| `keep` | [`KeepDuplicateType`](#model-KeepDuplicateType) | optional | Keep duplicated rows Default: `"first"` |

#### `SendFrom`

Which mailbox sends an email destination's messages.

Each value is one of the three (mimetype, service\_origin) pairs Core API's
validator accepts for an email interface (connection/utils.py
\_is\_email\_interface), which the share service reads to pick the sender
(sheetgo-microservices/share/mail\_provider.py). Mirrors the web app's
EmailSendFrom (web-app/src/constants/Mail/index.js).

**Type:** one of `"gmail"`, `"outlook_personal"`, `"outlook_work"`

#### `SourceAllTabs`

**Type:** one of `"all_tabs"`

#### `SourceAPI`

Request an HTTP endpoint and use the JSON it returns as source data.

Cannot be combined with file, folder or webhook sources — see
validate\_api\_automation.

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `auth` | [`SourceAuth`](#model-SourceAuth) | nullable | OAuth2 token refresh. **Write-only** — never returned by a read, and a PUT that omits it clears it. |
| `body` | string | nullable | Request body, sent as JSON when the endpoint expects it. Supports `{{Tab!Ref}}` cell references. Do not put credentials here — unlike `headers`, it is returned by reads. |
| `data_root` | string | nullable | Dotted path to the list of records inside the response, e.g. `data.orders`. Omit to let Sheetgo detect it. |
| `endpoint` | string | required | URL to request. Supports `{{Tab!Ref}}` cell references — see the Cell References section. |
| `header_root` | string | nullable | Dotted path to a list of column names inside the response, used as the header row. |
| `headers` | object (map of string → string) | nullable | HTTP headers sent with the request, e.g. `{"Authorization": "Bearer …"}`. Supports `{{Tab!Ref}}` cell references. **Write-only** — never returned by a read, and a PUT that omits it clears it. |
| `method` | one of `"get"`, `"post"` | optional | HTTP method. Only GET and POST can read data. Default: `"get"` |
| `name` | string | nullable | Label for this source. Also used as the destination tab name when several sources are transferred without a merge. Defaults to `API`. |
| `pagination` | one of (chosen by `type`): `type: "cursor"` → [`PaginationCursor`](#model-PaginationCursor), `type: "header-link"` → [`PaginationHeaderLink`](#model-PaginationHeaderLink), `type: "link"` → [`PaginationLink`](#model-PaginationLink), `type: "offset"` → [`PaginationOffset`](#model-PaginationOffset), `type: "page"` → [`PaginationPage`](#model-PaginationPage), `type: "query-offset"` → [`PaginationQueryOffset`](#model-PaginationQueryOffset) | nullable | How to walk a paginated endpoint. Omit for a single request. |
| `type` | `"api"` | required | Marks this source as an **API request**: Sheetgo calls your endpoint and turns the response into rows. Cannot be combined with file, folder or webhook sources. |

#### `SourceAuth`

OAuth2 refresh for an API source.

⚠️ `refresh_params` typically carries a client secret and a refresh token.
Automation interface payloads are NOT encrypted at rest, and the engine
ROTATES the refresh token in place after a successful refresh
(sheetgo-microservices getvalues/service\_api.py:71-77) — so the stored
value can change without any API call.

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `auth_method` | `"oauth2"` | required | Only `oauth2` is supported. The engine refreshes the token on a 401/403 and retries. |
| `auth_type` | string | optional | Scheme used in the Authorization header after a refresh, e.g. `Bearer`. Default: `"Bearer"` |
| `refresh_headers` | object (map of string → string) | nullable | Extra headers sent with the refresh request. |
| `refresh_params` | object (map of string → string) | nullable | Form body of the refresh request, e.g. `client_id`, `client_secret`, `refresh_token`. Write-only: never returned by a read. |
| `refresh_url` | string | required | Token endpoint called to refresh. |

#### `SourceBigQuery`

Read a BigQuery table, or the results of a query over it.

`project` + `dataset` + `table` are always required -- they form the
interface id the engine reads the project back out of, and they match the
web app, where selecting a table is mandatory and the SQL is seeded from it.

Cannot be combined with any other source, and at most one per automation --
see validate\_bigquery\_automation.

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `dataset` | string | required | BigQuery dataset id |
| `name` | string | nullable | Label for this source. Also used as the destination tab name. Defaults to the table name. |
| `project` | string | required | GCP project id. List them with `GET /rest/beta/bigquery/projects`. |
| `query` | string | nullable | Standard-SQL query to run instead of reading the whole table. Validate it first with `POST /rest/beta/bigquery/projects/{project}/validate-query`. Omit it and Sheetgo reads every row of the table -- there is no implicit row limit, so add your own `LIMIT` here if you want one. |
| `table` | string | required | BigQuery table id |
| `type` | `"bigquery"` | required | Marks this source as **BigQuery**. Only one BigQuery source per automation, and it cannot be mixed with other source kinds. |

#### `SourceFile`

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `data_ranges` | string | nullable | The data range |
| `date_format` | string | nullable | Format for date fields Default: `"#month/day/YEAR"` |
| `file_type` | [`FileType`](#model-FileType) | required | The file type |
| `id` | string | required | Id of the source file or folder |
| `offset_header` | integer | nullable | The header position Default: `1` |
| `provider` | [`Provider`](#model-Provider) | required | The storage provider that hosts the file or folder |
| `sheet_tabs` | string or [`SourceAllTabs`](#model-SourceAllTabs) or array of string | nullable | One or more sheet tab names or all\_tabs |
| `type` | `"file"` | required | Marks this source as a single **file** — one spreadsheet, CSV, TSV or Excel workbook. |

#### `SourceFolder-Input`

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `content_type` | [`ContentType`](#model-ContentType) | optional | `spreadsheets` reads Sheets / Excel / CSV / TSV files. `documents` reads Google Docs, PDF, Word (.docx) and text files through the AI step (`ai.prompt` required). Default: `"spreadsheets"` |
| `data_ranges` | string | nullable | The data range |
| `date_format` | string | nullable | Format for date fields Default: `"#month/day/YEAR"` |
| `file_filter` | [`FileFilter-Input`](#model-FileFilter-Input) | nullable | Only read the files that match these conditions. |
| `file_type` | `"folder"` | required | Always `folder`. Fixed by the source type; present so folder and file sources share one shape. |
| `id` | string | required | Id of the source file or folder |
| `import` | [`ImportMode`](#model-ImportMode) | optional | Which files to import, by modified time: every file newest or oldest first, or only the newest / oldest one. Applied after `file_filter` and `process_once`. Default: `"all_newest_first"` |
| `include_subfolders` | boolean | optional | Also read files inside subfolders. Default: `false` |
| `offset_header` | integer | nullable | The header position Default: `1` |
| `process_once` | boolean | optional | Documents only: skip files already read by an earlier run (new or changed files are read again). Ignored for spreadsheets. Default: `true` |
| `provider` | [`Provider`](#model-Provider) | required | The storage provider that hosts the file or folder |
| `sheet_tabs` | string or [`SourceAllTabs`](#model-SourceAllTabs) or array of string | nullable | One or more sheet tab names or all\_tabs |
| `type` | `"folder"` | required | Marks this source as a **folder**: every matching file inside it is read. |

#### `SourceFolder-Output`

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `content_type` | [`ContentType`](#model-ContentType) | optional | `spreadsheets` reads Sheets / Excel / CSV / TSV files. `documents` reads Google Docs, PDF, Word (.docx) and text files through the AI step (`ai.prompt` required). Default: `"spreadsheets"` |
| `data_ranges` | string | nullable | The data range |
| `date_format` | string | nullable | Format for date fields Default: `"#month/day/YEAR"` |
| `file_filter` | [`FileFilter-Output`](#model-FileFilter-Output) | nullable | Only read the files that match these conditions. |
| `file_type` | `"folder"` | required | Always `folder`. Fixed by the source type; present so folder and file sources share one shape. |
| `id` | string | required | Id of the source file or folder |
| `import` | [`ImportMode`](#model-ImportMode) | optional | Which files to import, by modified time: every file newest or oldest first, or only the newest / oldest one. Applied after `file_filter` and `process_once`. Default: `"all_newest_first"` |
| `include_subfolders` | boolean | optional | Also read files inside subfolders. Default: `false` |
| `offset_header` | integer | nullable | The header position Default: `1` |
| `process_once` | boolean | optional | Documents only: skip files already read by an earlier run (new or changed files are read again). Ignored for spreadsheets. Default: `true` |
| `provider` | [`Provider`](#model-Provider) | required | The storage provider that hosts the file or folder |
| `sheet_tabs` | string or [`SourceAllTabs`](#model-SourceAllTabs) or array of string | nullable | One or more sheet tab names or all\_tabs |
| `type` | `"folder"` | required | Marks this source as a **folder**: every matching file inside it is read. |

#### `SourceGmail-Input`

Read emails from the user's Gmail and save their attachments, bodies or
fields into a folder — or, with `extract=fields_table`, their fields as rows
of a spreadsheet (SG-14893).

Must be the only source, with no processors and exactly one destination: a
`folder`, or a `file` for `fields_table` — see validate\_gmail\_automation.
Gmail is only ever read.

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `columns` | array of [`EmailColumn`](#model-EmailColumn) | nullable | With `extract=fields_table`, the columns the sheet gets: any of `date`, `from`, `to`, `cc`, `bcc`, `subject`, `body`, `body_html`, `attachments`, `message_id`, `labels`. `date` is always among them, sent or not: every row carries its email's date. They are written in that order, whatever order they are sent in. Omit for every column. Refused with any other extract mode. |
| `email_filter` | [`EmailFilter-Input`](#model-EmailFilter-Input) | nullable | Only read the emails that match these conditions. `attachment_size` is not available for Gmail. Omit to read every email (each run scans at most 1000). |
| `extract` | [`GmailExtract`](#model-GmailExtract) | optional | `attachments` saves each email's file attachments into a folder; `body` saves each email's body as `<subject>.html`; `fields` saves that body with the message's date, from, to, cc, bcc, subject, attachment names, Message-ID and labels above it. `fields_table` writes those same fields to a SPREADSHEET instead — one row per email, with the body as plain text and as HTML, the columns chosen with `columns` — and so needs a `file` destination (gsheets, xlsx or csv) rather than a `folder`. That destination always appends: each run adds the emails that arrived since the previous one, and a large mailbox is copied over several runs. Cells are written as plain values, so a subject or body starting with `=` is never run as a formula. Default: `"attachments"` |
| `mailbox` | [`GmailMailbox`](#model-GmailMailbox) | optional | `inbox`, `sent` or `anywhere` (all mail, including spam and trash). The Google account must be connected in Sheetgo with permission to read mail (412 `gmail_not_connected` otherwise). Default: `"inbox"` |
| `name` | string | nullable | Label for the source. Defaults to `Gmail`. |
| `process_once` | boolean | optional | Skip emails already saved by an earlier run. Always on for `fields_table`, whatever is sent: the sheet appends, so each run adds only the emails not exported yet. Default: `true` |
| `type` | `"gmail"` | required | Marks this source as **Gmail**: emails from the user's mailbox. |

#### `SourceGmail-Output`

Read emails from the user's Gmail and save their attachments, bodies or
fields into a folder — or, with `extract=fields_table`, their fields as rows
of a spreadsheet (SG-14893).

Must be the only source, with no processors and exactly one destination: a
`folder`, or a `file` for `fields_table` — see validate\_gmail\_automation.
Gmail is only ever read.

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `columns` | array of [`EmailColumn`](#model-EmailColumn) | nullable | With `extract=fields_table`, the columns the sheet gets: any of `date`, `from`, `to`, `cc`, `bcc`, `subject`, `body`, `body_html`, `attachments`, `message_id`, `labels`. `date` is always among them, sent or not: every row carries its email's date. They are written in that order, whatever order they are sent in. Omit for every column. Refused with any other extract mode. |
| `email_filter` | [`EmailFilter-Output`](#model-EmailFilter-Output) | nullable | Only read the emails that match these conditions. `attachment_size` is not available for Gmail. Omit to read every email (each run scans at most 1000). |
| `extract` | [`GmailExtract`](#model-GmailExtract) | optional | `attachments` saves each email's file attachments into a folder; `body` saves each email's body as `<subject>.html`; `fields` saves that body with the message's date, from, to, cc, bcc, subject, attachment names, Message-ID and labels above it. `fields_table` writes those same fields to a SPREADSHEET instead — one row per email, with the body as plain text and as HTML, the columns chosen with `columns` — and so needs a `file` destination (gsheets, xlsx or csv) rather than a `folder`. That destination always appends: each run adds the emails that arrived since the previous one, and a large mailbox is copied over several runs. Cells are written as plain values, so a subject or body starting with `=` is never run as a formula. Default: `"attachments"` |
| `mailbox` | [`GmailMailbox`](#model-GmailMailbox) | optional | `inbox`, `sent` or `anywhere` (all mail, including spam and trash). The Google account must be connected in Sheetgo with permission to read mail (412 `gmail_not_connected` otherwise). Default: `"inbox"` |
| `name` | string | nullable | Label for the source. Defaults to `Gmail`. |
| `process_once` | boolean | optional | Skip emails already saved by an earlier run. Always on for `fields_table`, whatever is sent: the sheet appends, so each run adds only the emails not exported yet. Default: `true` |
| `type` | `"gmail"` | required | Marks this source as **Gmail**: emails from the user's mailbox. |

#### `SourceIntegration`

A pre-configured third-party source (Shopify, QuickBooks).

Everything an `api` source makes you supply -- URL, headers, token,
pagination, response parsing -- is built server-side per provider from the
authorized account's credentials, so only the choice of data source (and,
for QuickBooks reports, its parameters) is yours.

Unlike SourceAPI, this round-trips completely on a read: it holds no
caller-supplied secret, so nothing has to be write-only.

Counts as an api-like source for the no-mixing rule -- see
validate\_api\_automation.

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `account` | string | nullable | Which authorized account to use — the shop domain for Shopify, the realm (company) id for QuickBooks. Optional: omit it and Sheetgo uses your only connection for that provider. With several connected, omitting it is a 422. |
| `data_source` | string | required | Which data to pull, e.g. `get_products`. Get the list from `GET /rest/beta/integrations/{provider}/options`. |
| `name` | string | nullable | Label for this source. Also used as the destination tab name when several sources are transferred without a merge. Defaults to the provider's display name. |
| `parameters` | object (map of string → string) | nullable | Values for the parameters that data source declares. Only QuickBooks reports declare any; sending parameters to anything else is a 422. |
| `provider` | [`IntegrationProvider`](#model-IntegrationProvider) | required | The integration to read from. List them with `GET /rest/beta/integrations`. |
| `type` | `"integration"` | required | Marks this source as a pre-configured **integration** (Shopify, QuickBooks). URL, auth and pagination are managed by Sheetgo. |

#### `SourceOutlook-Input`

Read emails from an Outlook mailbox folder and save their file
attachments, bodies or fields into a folder — or, with
`extract=fields_table`, their fields as rows of a spreadsheet.

Must be the only source, with no processors and exactly one destination: a
`folder`, or a `file` for `fields_table` — see validate\_outlook\_automation.

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `account` | [`OutlookAccount`](#model-OutlookAccount) | optional | `personal` (a personal Microsoft account) or `work` (work or school). It must be connected in Sheetgo with permission to read mail (412 `outlook_not_connected` otherwise). Default: `"personal"` |
| `columns` | array of [`EmailColumn`](#model-EmailColumn) | nullable | With `extract=fields_table`, the columns the sheet gets: any of `date`, `from`, `to`, `cc`, `bcc`, `subject`, `body`, `body_html`, `attachments`, `message_id`, `labels`. `date` is always among them, sent or not: every row carries its email's date. They are written in that order, whatever order they are sent in. Omit for every column. Refused with any other extract mode. |
| `email_filter` | [`EmailFilter-Input`](#model-EmailFilter-Input) | nullable | Only read the emails that match these conditions. Omit to read every email (each run scans at most 1000). |
| `extract` | [`OutlookExtract`](#model-OutlookExtract) | optional | `attachments` saves each email's file attachments into a folder; `body` saves each email's body as `<subject>.html`; `fields` saves that body with the message's date, from, to, cc, bcc, subject, attachment names, Message-ID and labels above it. `fields_table` writes those same fields to a SPREADSHEET instead — one row per email, with the body as plain text and as HTML, the columns chosen with `columns` — and so needs a `file` destination (gsheets, xlsx or csv) rather than a `folder`. That destination always appends: each run adds the emails that arrived since the previous one, and a large mailbox is copied over several runs. Cells are written as plain values, so a subject or body starting with `=` is never run as a formula. Default: `"attachments"` |
| `mailbox` | [`OutlookMailbox`](#model-OutlookMailbox) | optional | `inbox`, `archive` or `sent_items`. Default: `"inbox"` |
| `name` | string | nullable | Label for the source. Defaults to `Outlook`. |
| `process_once` | boolean | optional | Skip emails already saved by an earlier run. Always on for `fields_table`, whatever is sent: the sheet appends, so each run adds only the emails not exported yet. Default: `true` |
| `type` | `"outlook"` | required | Marks this source as **Outlook**: emails from a mailbox folder, saved as files into a folder destination. |

#### `SourceOutlook-Output`

Read emails from an Outlook mailbox folder and save their file
attachments, bodies or fields into a folder — or, with
`extract=fields_table`, their fields as rows of a spreadsheet.

Must be the only source, with no processors and exactly one destination: a
`folder`, or a `file` for `fields_table` — see validate\_outlook\_automation.

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `account` | [`OutlookAccount`](#model-OutlookAccount) | optional | `personal` (a personal Microsoft account) or `work` (work or school). It must be connected in Sheetgo with permission to read mail (412 `outlook_not_connected` otherwise). Default: `"personal"` |
| `columns` | array of [`EmailColumn`](#model-EmailColumn) | nullable | With `extract=fields_table`, the columns the sheet gets: any of `date`, `from`, `to`, `cc`, `bcc`, `subject`, `body`, `body_html`, `attachments`, `message_id`, `labels`. `date` is always among them, sent or not: every row carries its email's date. They are written in that order, whatever order they are sent in. Omit for every column. Refused with any other extract mode. |
| `email_filter` | [`EmailFilter-Output`](#model-EmailFilter-Output) | nullable | Only read the emails that match these conditions. Omit to read every email (each run scans at most 1000). |
| `extract` | [`OutlookExtract`](#model-OutlookExtract) | optional | `attachments` saves each email's file attachments into a folder; `body` saves each email's body as `<subject>.html`; `fields` saves that body with the message's date, from, to, cc, bcc, subject, attachment names, Message-ID and labels above it. `fields_table` writes those same fields to a SPREADSHEET instead — one row per email, with the body as plain text and as HTML, the columns chosen with `columns` — and so needs a `file` destination (gsheets, xlsx or csv) rather than a `folder`. That destination always appends: each run adds the emails that arrived since the previous one, and a large mailbox is copied over several runs. Cells are written as plain values, so a subject or body starting with `=` is never run as a formula. Default: `"attachments"` |
| `mailbox` | [`OutlookMailbox`](#model-OutlookMailbox) | optional | `inbox`, `archive` or `sent_items`. Default: `"inbox"` |
| `name` | string | nullable | Label for the source. Defaults to `Outlook`. |
| `process_once` | boolean | optional | Skip emails already saved by an earlier run. Always on for `fields_table`, whatever is sent: the sheet appends, so each run adds only the emails not exported yet. Default: `true` |
| `type` | `"outlook"` | required | Marks this source as **Outlook**: emails from a mailbox folder, saved as files into a folder destination. |

#### `SourceWebhook`

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `name` | string | nullable | Optional label for the webhook source |
| `type` | `"webhook"` | required | Marks this source as a **webhook**: your system pushes data in, rather than Sheetgo pulling it. |

#### `Split`

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `column` | string | optional | Spreadsheet column letter (`A`, `B`, … `AA`), uppercase, as in the web app — not the header name. Find letters with `GET /rest/beta/files/{provider}/{file_id}/structure?include=columns`. Example: `"C"` |

#### `SuccessResponse`

The legacy success envelope, returned by the pre-existing CRUD routes.

It always carries HTTP 200; the outcome is in `code`/`type`, not the status
line. Newer endpoints return the resource directly instead.

| Field | Type |  | Description |
| --- | --- | --- | --- |
| `code` | integer | optional | Result code. 1 means the operation succeeded. Default: `1` |
| `message` | string | optional | Human-readable confirmation of what happened. Default: `"OK"` |
| `type` | string | optional | Kind of result — `success` for this envelope. Default: `"success"` |

Used by: [POST /rest/beta/workflows/run/{id}](/api/workflows.md#post-rest-beta-workflows-run-id), [DELETE /rest/beta/workflows/{id}](/api/workflows.md#delete-rest-beta-workflows-id), [POST /rest/beta/workflows/{id}/run](/api/workflows.md#post-rest-beta-workflows-id-run), [POST /rest/beta/automations/run/{id}](/api/automations.md#post-rest-beta-automations-run-id), [DELETE /rest/beta/automations/{id}](/api/automations.md#delete-rest-beta-automations-id), [POST /rest/beta/automations/{id}/run](/api/automations.md#post-rest-beta-automations-id-run), [DELETE /rest/beta/workflows/{workflow\_id}/forms/{form\_id}](/api/forms.md#delete-rest-beta-workflows-workflow-id-forms-form-id)

#### `UnusedFields`

What happens to a `{{Tag}}` in the template that no source column matches.

**Type:** one of `"ignore"`, `"error"`

#### `ValidationError`

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