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

# Supabase Storage

> Sync files from Supabase Storage buckets into Mixpeek using the S3-compatible API.

<Note>
  Supabase Storage exposes an S3-compatible API that Mixpeek talks to directly. You can authenticate with dedicated S3 access keys (recommended) or with a project's `anon` + `service_role` JWTs in session-token mode.
</Note>

## Overview

The Supabase integration lets Mixpeek pull objects from any Supabase Storage bucket into your Mixpeek buckets for processing. Each file becomes a Mixpeek bucket object, automatically batched into the collections that source the bucket.

Mixpeek derives the endpoint from your project reference — the short URL hash in your project's Dashboard URL (`https://<ref>.supabase.co`). You do not need to manage endpoints by hand.

## Prerequisites

* A Supabase project with at least one Storage bucket.
* Either:
  * **S3 access keys** (recommended): a dedicated key pair generated in **Project Settings → Storage → S3 Access Keys**, or
  * **Session-token credentials**: the project's `anon` key and `service_role` key from **Project Settings → API**.

## Configuration

### Connection-Level Fields

| Field                           | Required            | Description                                                                |
| ------------------------------- | ------------------- | -------------------------------------------------------------------------- |
| `project_ref`                   | Yes                 | Supabase project reference (the short hash in `https://<ref>.supabase.co`) |
| `region`                        | Yes                 | Region that hosts the project (e.g., `us-east-2`, `eu-west-1`)             |
| `credentials.type`              | Yes                 | `access_key` or `session_token`                                            |
| `credentials.access_key_id`     | for `access_key`    | S3 access key ID generated in Supabase                                     |
| `credentials.secret_access_key` | for `access_key`    | S3 secret access key — encrypted at rest                                   |
| `credentials.anon_key`          | for `session_token` | Project `anon` JWT                                                         |
| `credentials.service_role_key`  | for `session_token` | Project `service_role` JWT — encrypted at rest                             |

### Sync-Level Fields

| Field                      | Required | Description                                                         |
| -------------------------- | -------- | ------------------------------------------------------------------- |
| `source_path`              | Yes      | `<supabase-bucket>/<optional-prefix>` — e.g. `user-uploads/photos/` |
| `sync_mode`                | No       | `continuous`, `one_time`, or `scheduled`                            |
| `polling_interval_seconds` | No       | Seconds between scheduled runs                                      |
| `include_patterns`         | No       | Glob patterns to include (e.g. `["*.mp4", "*.jpg"]`)                |
| `exclude_patterns`         | No       | Glob patterns to exclude                                            |
| `modified_since`           | No       | ISO 8601 timestamp; only sync files modified after this date        |

## Setup

<Steps>
  <Step title="Generate credentials in Supabase">
    **Option A — Dedicated S3 keys (recommended):**

    1. Open your project in the [Supabase Dashboard](https://supabase.com/dashboard).
    2. Go to **Project Settings → Storage → S3 Access Keys**.
    3. Click **New access key**, give it a name (e.g. `mixpeek-sync`) and copy the `access_key_id` + `secret_access_key` immediately — the secret is shown only once.

    **Option B — Session-token credentials:**

    1. Go to **Project Settings → API**.
    2. Copy the `anon` key and the `service_role` key. Treat `service_role` like a password — it has full access to Storage.

    <Warning>
      Session-token mode is convenient when you don't have permission to mint S3 keys, but the `service_role` JWT is a superuser credential. Prefer dedicated S3 keys scoped to the buckets you actually need.
    </Warning>
  </Step>

  <Step title="Create the storage connection in Mixpeek">
    <CodeGroup>
      ```python Python theme={null}
      from mixpeek import Mixpeek

      client = Mixpeek(api_key="your-mixpeek-api-key")

      connection = client.organizations.connections.create(
          name="Supabase Uploads",
          provider_type="supabase",
          provider_config={
              "project_ref": "abcdefghijklmnopqrst",
              "region": "us-east-2",
              "credentials": {
                  "type": "access_key",
                  "access_key_id": "supabase_ak_...",
                  "secret_access_key": "supabase_sk_...",
              },
          },
      )
      print(f"Connection: {connection['connection_id']}")
      ```

      ```javascript JavaScript theme={null}
      import { Mixpeek } from 'mixpeek-sdk'

      const client = new Mixpeek({ apiKey: 'your-mixpeek-api-key' })

      const connection = await client.organizations.connections.create({
        name: 'Supabase Uploads',
        provider_type: 'supabase',
        provider_config: {
          project_ref: 'abcdefghijklmnopqrst',
          region: 'us-east-2',
          credentials: {
            type: 'access_key',
            access_key_id: 'supabase_ak_...',
            secret_access_key: 'supabase_sk_...',
          },
        },
      })
      console.log('Connection:', connection.connection_id)
      ```

      ```bash cURL theme={null}
      curl -X POST https://api.mixpeek.com/v1/organizations/connections \
        -H "Authorization: Bearer YOUR_MIXPEEK_API_KEY" \
        -H "Content-Type: application/json" \
        -d '{
          "name": "Supabase Uploads",
          "provider_type": "supabase",
          "provider_config": {
            "project_ref": "abcdefghijklmnopqrst",
            "region": "us-east-2",
            "credentials": {
              "type": "access_key",
              "access_key_id": "supabase_ak_...",
              "secret_access_key": "supabase_sk_..."
            }
          }
        }'
      ```
    </CodeGroup>

    To use session-token mode instead, swap the `credentials` block:

    ```json theme={null}
    {
      "type": "session_token",
      "anon_key": "eyJ...anon",
      "service_role_key": "eyJ...service_role"
    }
    ```
  </Step>

  <Step title="Create a sync configuration on your bucket">
    <CodeGroup>
      ```python Python theme={null}
      sync = client.buckets.syncs.create(
          bucket_id="bkt_your_bucket_id",
          connection_id=connection["connection_id"],
          source_path="user-uploads/photos/",
          sync_mode="scheduled",
          polling_interval_seconds=3600,
      )
      print(f"Sync: {sync['sync_config_id']}")
      ```

      ```bash cURL theme={null}
      curl -X POST https://api.mixpeek.com/v1/buckets/bkt_your_bucket_id/syncs \
        -H "Authorization: Bearer YOUR_MIXPEEK_API_KEY" \
        -H "X-Namespace: ns_your_namespace_id" \
        -H "Content-Type: application/json" \
        -d '{
          "connection_id": "conn_your_connection_id",
          "source_path": "user-uploads/photos/",
          "sync_mode": "scheduled",
          "polling_interval_seconds": 3600
        }'
      ```
    </CodeGroup>
  </Step>

  <Step title="Trigger your first sync">
    ```bash theme={null}
    curl -X POST https://api.mixpeek.com/v1/buckets/bkt_your_bucket_id/syncs/SYNC_CONFIG_ID/trigger \
      -H "Authorization: Bearer YOUR_MIXPEEK_API_KEY" \
      -H "X-Namespace: ns_your_namespace_id"
    ```

    Mixpeek lists objects under your Supabase prefix, downloads each one, stores it in the Mixpeek-side S3 bucket, and creates a bucket object. Any collection that sources this bucket picks the new objects up on the next batch.
  </Step>
</Steps>

## Advanced Configuration

### File Filtering

```python theme={null}
sync = client.buckets.syncs.create(
    bucket_id="bkt_your_bucket_id",
    connection_id=connection["connection_id"],
    source_path="user-uploads/",
    sync_mode="scheduled",
    polling_interval_seconds=3600,
    include_patterns=["*.mp4", "*.mov", "*.jpg"],
    exclude_patterns=["*_thumbnail.*", "*.tmp"],
)
```

### Incremental Sync

Only sync files added or modified after a specific date:

```python theme={null}
sync = client.buckets.syncs.create(
    bucket_id="bkt_your_bucket_id",
    connection_id=connection["connection_id"],
    source_path="user-uploads/",
    sync_mode="continuous",
    polling_interval_seconds=300,
    modified_since="2024-06-01T00:00:00Z",
)
```

## Source Path Format

| Format               | Example                     | Description                          |
| -------------------- | --------------------------- | ------------------------------------ |
| `bucket/prefix`      | `user-uploads/photos/`      | Preferred — Supabase bucket + prefix |
| `s3://bucket/prefix` | `s3://user-uploads/photos/` | S3-style URI also accepted           |
| `bucket`             | `user-uploads`              | Entire Supabase bucket               |

## Sync Modes

| Mode         | Description                            | When to Use                              |
| ------------ | -------------------------------------- | ---------------------------------------- |
| `continuous` | Polls every `polling_interval_seconds` | Active uploads, near-real-time ingestion |
| `one_time`   | Single import, then completes          | Historical backfills, migrations         |
| `scheduled`  | Runs on a fixed interval               | Predictable batch cadence                |

## Troubleshooting

<AccordionGroup>
  <Accordion title="Connection test returns 403 / SignatureDoesNotMatch">
    * With **access\_key** mode: the keys must come from **Project Settings → Storage → S3 Access Keys**, not the general Supabase API keys.
    * With **session\_token** mode: verify `anon_key` and `service_role_key` are both JWTs from the same project and that `project_ref` matches the project they belong to.
    * Confirm `region` matches the region shown in the Supabase Dashboard.
  </Accordion>

  <Accordion title="NoSuchBucket when triggering sync">
    The Supabase bucket in `source_path` does not exist or your credentials cannot see it:

    * Double-check the bucket name (case-sensitive).
    * For access keys with bucket scope, confirm the key grants access to the bucket you're syncing.
  </Accordion>

  <Accordion title="No files synced from a populated bucket">
    * The `source_path` prefix is too narrow — widen it, or drop the trailing prefix.
    * `include_patterns` may exclude everything — remove them temporarily to see all files.
    * Check the sync run's `matched` counter in the job log to confirm discovery.
  </Accordion>

  <Accordion title="Session-token auth works locally but fails in Mixpeek">
    Some Supabase projects rotate `anon`/`service_role` keys during upgrades. Refresh both JWTs from **Project Settings → API** and update the connection.
  </Accordion>
</AccordionGroup>

## Related

* [Bucket Syncs](/api-reference/bucket-syncs/create-sync-configuration)
* [Storage Connections](/api-reference/organization-connections/create-storage-connection)
* [Backblaze B2 Integration](/integrations/object-storage/backblaze)
* [Tigris Integration](/integrations/object-storage/tigris)
