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

# Stitch integration

> With PlanetScale Connect, you can extract data from your PlanetScale database and safely load it into other destinations for analysis, transformation, and more.

export const PlatformAvailability = ({current, vitess, postgres}) => {
  const docsHref = path => {
    if (!path) return path;
    const normalized = path.startsWith('/') ? path : `/${path}`;
    return normalized;
  };
  const labels = {
    vitess: 'Vitess',
    postgres: 'Postgres'
  };
  if (current === 'both') {
    return <div className="not-prose mb-5 flex flex-wrap items-center gap-2" role="group" aria-label="Platform availability">
        <span data-engine="both" data-state="current" aria-current="true" className="inline-flex items-center gap-1.5 whitespace-nowrap rounded-full border px-2.5 py-1 text-[13px] font-semibold leading-tight no-underline data-[engine=vitess]:data-[state=current]:border-[#ffc59b] data-[engine=vitess]:data-[state=current]:bg-[#ffe8d8] data-[engine=vitess]:data-[state=current]:text-[#672002] dark:data-[engine=vitess]:data-[state=current]:border-[#962d00] dark:data-[engine=vitess]:data-[state=current]:bg-[#3c1403] dark:data-[engine=vitess]:data-[state=current]:text-[#ffe8d8] data-[engine=vitess]:data-[state=link]:border-[#ffc59b] data-[engine=vitess]:data-[state=link]:bg-transparent data-[engine=vitess]:data-[state=link]:text-[#b83a05] dark:data-[engine=vitess]:data-[state=link]:border-[#962d00] dark:data-[engine=vitess]:data-[state=link]:bg-transparent dark:data-[engine=vitess]:data-[state=link]:text-[#ffc59b] data-[engine=postgres]:data-[state=current]:border-[#a9dffe] data-[engine=postgres]:data-[state=current]:bg-[#ddf2ff] data-[engine=postgres]:data-[state=current]:text-[#0e3682] dark:data-[engine=postgres]:data-[state=current]:border-[#144eb6] dark:data-[engine=postgres]:data-[state=current]:bg-[#08204e] dark:data-[engine=postgres]:data-[state=current]:text-[#ddf2ff] data-[engine=postgres]:data-[state=link]:border-[#a9dffe] data-[engine=postgres]:data-[state=link]:bg-transparent data-[engine=postgres]:data-[state=link]:text-[#0b6ec5] dark:data-[engine=postgres]:data-[state=link]:border-[#144eb6] dark:data-[engine=postgres]:data-[state=link]:bg-transparent dark:data-[engine=postgres]:data-[state=link]:text-[#73c7f9] data-[engine=both]:data-[state=current]:border-[#d4d4d4] data-[engine=both]:data-[state=current]:bg-[#f0f0f0] data-[engine=both]:data-[state=current]:text-[#3d3d3d] dark:data-[engine=both]:data-[state=current]:border-[#525252] dark:data-[engine=both]:data-[state=current]:bg-[#2a2a2a] dark:data-[engine=both]:data-[state=current]:text-[#e5e5e5]">
          Vitess and Postgres
        </span>
      </div>;
  }
  const hasVitess = current === 'vitess' || Boolean(vitess);
  const hasPostgres = current === 'postgres' || Boolean(postgres);
  const only = !(hasVitess && hasPostgres);
  const engines = [];
  if (current === 'vitess' || current === 'postgres') engines.push(current);
  if (hasVitess && current !== 'vitess') engines.push('vitess');
  if (hasPostgres && current !== 'postgres') engines.push('postgres');
  return <div className="not-prose mb-5 flex flex-wrap items-center gap-2" role="group" aria-label="Platform availability">
      {engines.map(engine => {
    const isCurrent = current === engine;
    const href = docsHref(engine === 'vitess' ? vitess : postgres);
    const label = only ? `${labels[engine]} only` : labels[engine];
    const state = isCurrent || !href ? 'current' : 'link';
    if (isCurrent || !href) {
      return <span key={engine} data-engine={engine} data-state={state} aria-current={isCurrent ? 'true' : undefined} className="inline-flex items-center gap-1.5 whitespace-nowrap rounded-full border px-2.5 py-1 text-[13px] font-semibold leading-tight no-underline data-[engine=vitess]:data-[state=current]:border-[#ffc59b] data-[engine=vitess]:data-[state=current]:bg-[#ffe8d8] data-[engine=vitess]:data-[state=current]:text-[#672002] dark:data-[engine=vitess]:data-[state=current]:border-[#962d00] dark:data-[engine=vitess]:data-[state=current]:bg-[#3c1403] dark:data-[engine=vitess]:data-[state=current]:text-[#ffe8d8] data-[engine=vitess]:data-[state=link]:border-[#ffc59b] data-[engine=vitess]:data-[state=link]:bg-transparent data-[engine=vitess]:data-[state=link]:text-[#b83a05] dark:data-[engine=vitess]:data-[state=link]:border-[#962d00] dark:data-[engine=vitess]:data-[state=link]:bg-transparent dark:data-[engine=vitess]:data-[state=link]:text-[#ffc59b] data-[engine=postgres]:data-[state=current]:border-[#a9dffe] data-[engine=postgres]:data-[state=current]:bg-[#ddf2ff] data-[engine=postgres]:data-[state=current]:text-[#0e3682] dark:data-[engine=postgres]:data-[state=current]:border-[#144eb6] dark:data-[engine=postgres]:data-[state=current]:bg-[#08204e] dark:data-[engine=postgres]:data-[state=current]:text-[#ddf2ff] data-[engine=postgres]:data-[state=link]:border-[#a9dffe] data-[engine=postgres]:data-[state=link]:bg-transparent data-[engine=postgres]:data-[state=link]:text-[#0b6ec5] dark:data-[engine=postgres]:data-[state=link]:border-[#144eb6] dark:data-[engine=postgres]:data-[state=link]:bg-transparent dark:data-[engine=postgres]:data-[state=link]:text-[#73c7f9] data-[engine=both]:data-[state=current]:border-[#d4d4d4] data-[engine=both]:data-[state=current]:bg-[#f0f0f0] data-[engine=both]:data-[state=current]:text-[#3d3d3d] dark:data-[engine=both]:data-[state=current]:border-[#525252] dark:data-[engine=both]:data-[state=current]:bg-[#2a2a2a] dark:data-[engine=both]:data-[state=current]:text-[#e5e5e5]">
              {label}
            </span>;
    }
    return <a key={engine} href={href} data-engine={engine} data-state={state} title={`View ${labels[engine]} documentation`} className="inline-flex items-center gap-1.5 whitespace-nowrap rounded-full border px-2.5 py-1 text-[13px] font-semibold leading-tight no-underline data-[engine=vitess]:data-[state=current]:border-[#ffc59b] data-[engine=vitess]:data-[state=current]:bg-[#ffe8d8] data-[engine=vitess]:data-[state=current]:text-[#672002] dark:data-[engine=vitess]:data-[state=current]:border-[#962d00] dark:data-[engine=vitess]:data-[state=current]:bg-[#3c1403] dark:data-[engine=vitess]:data-[state=current]:text-[#ffe8d8] data-[engine=vitess]:data-[state=link]:border-[#ffc59b] data-[engine=vitess]:data-[state=link]:bg-transparent data-[engine=vitess]:data-[state=link]:text-[#b83a05] dark:data-[engine=vitess]:data-[state=link]:border-[#962d00] dark:data-[engine=vitess]:data-[state=link]:bg-transparent dark:data-[engine=vitess]:data-[state=link]:text-[#ffc59b] data-[engine=postgres]:data-[state=current]:border-[#a9dffe] data-[engine=postgres]:data-[state=current]:bg-[#ddf2ff] data-[engine=postgres]:data-[state=current]:text-[#0e3682] dark:data-[engine=postgres]:data-[state=current]:border-[#144eb6] dark:data-[engine=postgres]:data-[state=current]:bg-[#08204e] dark:data-[engine=postgres]:data-[state=current]:text-[#ddf2ff] data-[engine=postgres]:data-[state=link]:border-[#a9dffe] data-[engine=postgres]:data-[state=link]:bg-transparent data-[engine=postgres]:data-[state=link]:text-[#0b6ec5] dark:data-[engine=postgres]:data-[state=link]:border-[#144eb6] dark:data-[engine=postgres]:data-[state=link]:bg-transparent dark:data-[engine=postgres]:data-[state=link]:text-[#73c7f9] data-[engine=both]:data-[state=current]:border-[#d4d4d4] data-[engine=both]:data-[state=current]:bg-[#f0f0f0] data-[engine=both]:data-[state=current]:text-[#3d3d3d] dark:data-[engine=both]:data-[state=current]:border-[#525252] dark:data-[engine=both]:data-[state=current]:bg-[#2a2a2a] dark:data-[engine=both]:data-[state=current]:text-[#e5e5e5]">
            {label}
            <svg aria-hidden="true" width="12" height="12" viewBox="0 0 12 12" fill="none" className="shrink-0">
              <path d="M2.5 6h7M6.5 3l3 3-3 3" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
            </svg>
          </a>;
  })}
    </div>;
};

<PlatformAvailability current="vitess" />

We implemented an [Stitch Singer Tap](https://stitchdata.com/) as the pipeline between your PlanetScale source and selected destination. This document will walk you through how to connect your PlanetScale database to Stitch.

## How to connect

### Step 1 : Setup an Import API integration in Stitch.

PlanetScale's Stitch tap outputs records and metadata to stdout so that the `http tap` can import them into Stitch via [Stitch Import API](https://www.stitchdata.com/docs/developers/import-api/).

<Steps>
  <Step>
    Sign up for a [StitchData](https://app.stitchdata.com/signup) account
  </Step>

  <Step>
    Once you've signed up, create an Integration by clicking on **Add Integration**.
  </Step>

  <Step>
    On the marketplace screen, type in **import** to narrow the list down to the **Import API**

    <Frame>
      <img src="https://mintcdn.com/planetscale-2/UzFO5Pe10M0-W-uW/images/assets/docs/integrations/stitch/integration.png?fit=max&auto=format&n=UzFO5Pe10M0-W-uW&q=85&s=be1a33ff18aa41d7efa0df7d057e8293" alt="Add Stitch Integration" width="2416" height="950" data-path="images/assets/docs/integrations/stitch/integration.png" />
    </Frame>
  </Step>

  <Step>
    On the next screen, configure your integration name and destination.

    <Frame>
      <img src="https://mintcdn.com/planetscale-2/UzFO5Pe10M0-W-uW/images/assets/docs/integrations/stitch/configure.png?fit=max&auto=format&n=UzFO5Pe10M0-W-uW&q=85&s=35bc876bf5c8f251be4ac6bc6cf67a5d" alt="Configure Stitch Integration" width="1618" height="1834" data-path="images/assets/docs/integrations/stitch/configure.png" />
    </Frame>
  </Step>

  <Step>
    Once the integration is created, save the access token for use with the PlanetScale tap.

    <Frame>
      <img src="https://mintcdn.com/planetscale-2/UzFO5Pe10M0-W-uW/images/assets/docs/integrations/stitch/api-token.png?fit=max&auto=format&n=UzFO5Pe10M0-W-uW&q=85&s=3605a6820d1265d306b1c9d1cfd60f36" alt="Save Stitch API Token" width="1478" height="760" data-path="images/assets/docs/integrations/stitch/api-token.png" />
    </Frame>
  </Step>
</Steps>

### Step 2 : Configure the PlanetScale Stitch Tap

In this step, we will connect your PlanetScale database to the PlanetScale Singer Tap.

<Steps>
  <Step>
    Click on the database and branch you want to connect to.
  </Step>

  <Step>
    Click "Connect", and select "Stitch source" from the "Connect with" dropdown.
  </Step>

  <Step>
    Leave this tab open, as you'll need to copy these credentials shortly.

    <Frame>
      <img src="https://mintcdn.com/planetscale-2/UzFO5Pe10M0-W-uW/images/assets/docs/integrations/stitch/connect.png?fit=max&auto=format&n=UzFO5Pe10M0-W-uW&q=85&s=8d0374a8f67f7e3e4963c8ca8d7254cb" alt="Stitch Source config" width="1148" height="634" data-path="images/assets/docs/integrations/stitch/connect.png" />
    </Frame>
  </Step>

  <Step>
    Copy the contents of `source.json` as a file on your local file system, and save it as `source.json`. This will now act
    as the `PlanetScale source config` when connecting the `PlanetScale Stitch Tap` to your database.
  </Step>
</Steps>

### Step 3: Run the PlanetScale Stitch Tap

<Steps>
  <Step>
    Install the PlanetScale Singer tap by running:

    ```bash theme={null}
    brew install planetscale/tap/ps-singer-tap
    ```
  </Step>

  <Step>
    Install the PlanetScale Http tap by running

    ```bash theme={null}
    brew install planetscale/tap/ps-http-tap
    ```
  </Step>

  <Step>
    Save the schema for your PlanetScale database.

    ```bash theme={null}
    ps-singer-tap --config source.json  --discover > schema.json
    ```
  </Step>

  <Step>
    The `schema.json` file you saved in the previous step is a JSON document
    that describes all tables & columns available in your PlanetScale database. By default, no tables/columns are selected.
    You can select a column or table by setting its `selected` property in the table's `metadata` element in the JSON document to be true.
    Here's an example of selecting the `dept_no` property in a table.

    ```json theme={null}
    {
      "metadata": {
        "selected": true,
        "inclusion": "available",
        "breadcrumb": ["properties", "dept_no"]
      }
    }
    ```
  </Step>

  <Step>
    Sync your PlanetScale database to Stitch by running the following command:

    ```bash theme={null}
    ps-singer-tap --config source.json  --catalog schema.json | ps-http-tap  --api-token $(cat access_token)
    ```
  </Step>

  <Step>
    You should see an output similar to this:

    ```bash expandable theme={null}
    PlanetScale Tap : INFO : Syncing records for PlanetScale database : import-on-scaler
    PlanetScale Tap : INFO : syncing rows from stream "departments" from shard "-"
    PlanetScale Tap : INFO : [departments shard : -] peeking to see if there's any new rows
    PlanetScale Tap : INFO : new rows found, syncing rows for 1m0s
    PlanetScale Tap : INFO : [departments shard : -] syncing rows with cursor [shard:"-" keyspace:"import-on-scaler"]
    PlanetScale Tap : INFO : Syncing with cursor position : [], using last known PK : false, stop cursor is : [MySQL56/e42292e8-e28f-11ec-9c5b-d680f5d655b3:1-705,e4e20f06-e28f-11ec-8d20-8e7ac09cb64c:1-26,eba743a8-e28f-11ec-9227-62aa711d33c6:1-20]
    PlanetScale Tap : INFO : [departments shard : -] Continuing with cursor after server timeout
    PlanetScale Tap : INFO : [departments shard : -] peeking to see if there's any new rows
    HTTP Tap : INFO : flushing [20] messages for stream "departments"
    PlanetScale Tap : INFO : [departments shard : -] no new rows found, exiting
    HTTP Tap : INFO : Server response status : "OK", message : "Batch accepted"
    HTTP Tap : INFO : flushing [1] messages for stream "departments"
    HTTP Tap : INFO : Server response status : "OK", message : "Batch accepted"
    HTTP Tap : INFO : saving state to path : state/state-1656850746251.json
    ```
  </Step>

  <Step>
    Any state outputted by the PlanetScale Tap will be saved and you can look at the logs for the location.
    Here is an example of outputted state:

    ```bash theme={null}
    HTTP Tap : INFO : saving state to path : state/state-1656850746251.json
    ```
  </Step>

  <Step>
    In this example, you should see that Stitch loaded `21` records to be replicated.

    <Frame>
      <img src="https://mintcdn.com/planetscale-2/UzFO5Pe10M0-W-uW/images/assets/docs/integrations/stitch/success.png?fit=max&auto=format&n=UzFO5Pe10M0-W-uW&q=85&s=b85556b691d67b684879617e081bbd50" alt="Completed Stitch import" width="1630" height="988" data-path="images/assets/docs/integrations/stitch/success.png" />
    </Frame>
  </Step>

  <Step>
    To incrementally sync from this last sync position, pass the path to last saved state in step 7 as the `--state` argument when you run sync.
  </Step>
</Steps>

## Need help?

Get help from [the PlanetScale Support team](https://planetscale.com/contact?initial=support), or join our [Discord community](https://pscale.link/community) to see how others are using PlanetScale.
