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

# Integrate Unsiloed with Google Sheets

> Connect Google Sheets to the Unsiloed API with Apps Script, verify the connection, and choose a spreadsheet workflow.

Google Sheets formulas don't make authenticated REST API requests directly. A
spreadsheet-bound Google Apps Script provides the bridge: it reads values or
images from the sheet, calls the Unsiloed API, and writes the result back to
cells.

In this guide, we'll connect a spreadsheet to Unsiloed and verify the API key.
The resulting Apps Script project is the starting point for menu commands,
custom functions, and automated document-processing workflows.

<Note>
  This setup is for a script attached to one spreadsheet. If you need the same
  integration across many spreadsheets, package the script as a Google Workspace
  add-on instead of copying it into each file.
</Note>

## How Unsiloed Works with Google Sheets

The integration follows one request path:

`Google Sheets → Apps Script → Unsiloed API → Apps Script → Google Sheets`

Apps Script can turn this connection into several spreadsheet workflows:

* **Menu commands** process a selected cell or range and write results to another
  sheet. Use this approach for images, files, and jobs that require polling.
* **Custom functions** send a cell value or public URL to Unsiloed and return a
  value directly into the formula cell, such as `=UNSILOED(A2)`. Custom functions
  can't edit arbitrary cells, and Google stops them after 30 seconds.
* **Batch workflows** loop over a range and process several documents from one
  menu command or trigger. Batch writes reduce calls to the Google Sheets service.

Use a menu command for the first integration. It can request authorization, write
to multiple cells, and wait for asynchronous Unsiloed jobs. Add a custom function
when the input and output fit naturally into a single formula.

## Requirements for the Google Sheets Integration

Before you start, gather:

* A Google account and a spreadsheet you can edit
* An Unsiloed API key from the [Unsiloed dashboard](https://app.unsiloed.ai)
* Permission to run Apps Script in your Google Workspace organization

The script uses Google's `UrlFetchApp` service to call Unsiloed. Google asks you
to authorize external requests the first time you run it.

## Connect Google Sheets to Unsiloed

We'll create a script attached to the spreadsheet, store the API key outside the
source code, and call a read-only endpoint to verify the connection.

<Steps>
  <Step title="Create a spreadsheet-bound script">
    Open the spreadsheet, then choose **Extensions → Apps Script**. Google creates
    an Apps Script project attached to that spreadsheet and opens `Code.gs`.

    A [spreadsheet-bound script](https://developers.google.com/apps-script/guides/bound)
    can read the active cell, add menus, display sidebars, and define custom
    functions for its spreadsheet.
  </Step>

  <Step title="Store the Unsiloed API key">
    In the Apps Script editor, open **Project Settings** from the left sidebar.
    Under **Script Properties**, click **Add script property**.

    Add the following property name and use your API key as its value:

    ```text theme={null}
    UNSILOED_API_KEY
    ```

    Click **Save script properties**. The
    [Properties service](https://developers.google.com/apps-script/guides/properties)
    stores the key for this script, so you don't need to paste it into `Code.gs`.
  </Step>

  <Step title="Add a connection check">
    Replace the contents of `Code.gs` with the following code:

    ```javascript Code.gs theme={null}
    const UNSILOED_USAGE_URL =
      "https://platformbackend.unsiloed.ai/api/v1/org/get_usage";

    function unsiloedApiKey() {
      const apiKey = PropertiesService.getScriptProperties()
        .getProperty("UNSILOED_API_KEY");

      if (!apiKey) {
        throw new Error("Add UNSILOED_API_KEY to the script properties.");
      }

      return apiKey;
    }

    function checkUnsiloedConnection() {
      const response = UrlFetchApp.fetch(
        UNSILOED_USAGE_URL,
        { headers: { "api-key": unsiloedApiKey() } }
      );
      const usage = JSON.parse(response.getContentText());

      SpreadsheetApp.getActive().toast(
        "Connected to " + usage.org_name,
        "Unsiloed"
      );
    }
    ```

    The helper reads the current property value whenever the script makes a
    request. The connection check uses the read-only usage endpoint and displays
    the organization name in the spreadsheet. The workflow cookbooks use the
    separate document-processing API at `prod.visionapi.unsiloed.ai`.
  </Step>

  <Step title="Run and authorize the connection check">
    Click **Save**, select `checkUnsiloedConnection` from the function dropdown,
    and click **Run**.

    Google asks for permission the first time. Choose your account, then review
    the two things the script needs: access to this spreadsheet, so it can show
    the toast, and permission to connect to an external service, so it can reach
    Unsiloed. Click **Allow**.

    Return to the spreadsheet after the function finishes. A toast should confirm
    the Unsiloed organization connected to the API key.
  </Step>
</Steps>

<Warning>
  Anyone who can edit the spreadsheet can also view its bound Apps Script project.
  Use a dedicated API key, and don't share the spreadsheet with untrusted editors.
</Warning>

## Choose a Google Sheets Workflow

The connection is now ready for a task-specific script. Start with the table
extraction cookbook, which adds a menu command that sends an in-cell image to
`/parse` and writes the detected table to a second sheet.

Use [`/parse`](/docs/document-processing/parsing/parsing) when the sheet needs the
document's original structure, including tables and text sections. Use
[`/v2/extract`](/docs/document-processing/extraction/extraction) when each row needs
the same typed fields, such as an invoice number, date, and total.

<CardGroup cols={2}>
  <Card title="Extract a Table from an Image" icon="table" href="/docs/cookbooks/spreadsheets/google-sheets-extract-table">
    Turn an image in a cell into editable rows with a spreadsheet menu command.
  </Card>

  <Card title="Extract Chart Data with a Formula" icon="chart-line" href="/docs/cookbooks/spreadsheets/google-sheets-custom-function">
    Turn a public chart image into numeric cells with `UNSILOED_CHART`.
  </Card>

  <Card title="Parse Documents" icon="file-lines" href="/docs/document-processing/parsing/parsing">
    Review the parsing workflow, supported files, and response structure.
  </Card>

  <Card title="Extract Typed Fields" icon="brackets-curly" href="/docs/document-processing/extraction/extraction">
    Return a predictable set of fields by supplying a JSON Schema.
  </Card>
</CardGroup>

## Google Sheets Constraints

Apps Script runs on Google infrastructure, so its execution rules shape the
integration:

* Custom functions return a value to their formula cell but can't write elsewhere
  in the spreadsheet.
* Custom functions never request authorization. They can use supported services,
  including `UrlFetchApp`, but can't use services that require access to personal
  Google data. Use a menu command when a workflow needs those services.
* Custom functions are stopped at 30 seconds, which is the tightest limit here.
  Unsiloed document-processing endpoints return jobs that you then poll. In our
  tests, a small job often takes around 20 seconds, so even one can approach the
  limit and two sequential jobs are unlikely to finish in time. Keep custom
  functions to one small job, and use a menu command, which gets six minutes, for
  anything larger.
* A script can only read an image placed **in** a cell. An image floating over the
  grid exposes no method that returns its bytes, so no script can reach it.
* Menu commands can update ranges, open dialogs, and run workflows that require
  authorization.
* Repeated formulas can create one API request per cell. Prefer a function that
  accepts a range or a menu-driven batch for larger datasets.
* Script properties belong to the Apps Script project, not to the spreadsheet.
  Copying a spreadsheet copies its script but not its properties, so the copy
  starts with no API key and its first run fails until you add one.

See the [Google custom functions guide](https://developers.google.com/apps-script/guides/sheets/functions)
for the current service and execution restrictions.
