---
title: "Supabase Connector"
description: "Complete Supabase integration guide for syncing database records, user auth, file storage, and real-time events with your engagement platform."
url: https://tajo.io/docs/connectors/custom/supabase/
markdown: https://tajo.io/docs/connectors/custom/supabase.md
lang: en-US
robots: noindex
---

# Supabase Connector

Connector status: Planned Not built yet. Tajo does not run this connector today.

| Source field | Destination field | Sample value |
| --- | --- | --- |
| `record.id` | `source_id` | `record_1042` |
| `record.updated_at` | `updated_at` | `2026-10-18T08:00:00Z` |
| `record.value` | `value` | `sample_value` |

Connect your Supabase project to sync database records, user authentication data, file storage events, and real-time changes for customer engagement automation.

## Overview

| Property | Value |
| --- | --- |
| **Platform** | Supabase |
| **Category** | Database & Backend |
| **Setup Complexity** | Easy |
| **Official Integration** | No |
| **Data Synced** | Users, Tables, Storage, Events |
| **Available Skills** | 11 |
| **API Type** | REST (PostgREST) + Realtime WebSocket |
| **Official Docs** | [supabase.com/docs](https://supabase.com/docs) |

## Features

- **Auto-generated REST API**, CRUD operations on any Postgres table via PostgREST, no code required
- **Auth user sync**, Sync Supabase Auth users (email, phone, social logins) to your engagement platform
- **Real-time subscriptions**, Listen to INSERT, UPDATE, DELETE events on any table in real-time
- **Row Level Security**, All API access respects Postgres RLS policies for secure multi-tenant data
- **Storage integration**, Track file uploads and manage assets across Storage buckets
- **Edge Functions**, Invoke serverless Deno functions for custom logic and webhooks
- **Full-text search**, Leverage Postgres full-text search capabilities through the API

## Prerequisites

Before you begin, ensure you have:

1. A Supabase project ([app.supabase.com](https://app.supabase.com/))
2. Your project’s **API URL** and **API keys** (found in Settings → API)
3. A Tajo account with API access

API Keys

Supabase provides two keys: `anon` (public, respects RLS) and `service_role` (bypasses RLS, admin access). Use `service_role` for server-side integrations and `anon` for client-side.

## Authentication

Supabase uses API key authentication. Every request requires the `apikey` header and optionally an `Authorization` bearer token for user-scoped access.

```bash
# Using anon key (respects RLS)
curl 'https://<project_ref>.supabase.co/rest/v1/customers' \
  -H "apikey: <SUPABASE_ANON_KEY>" \
  -H "Authorization: Bearer <SUPABASE_ANON_KEY>"

# Using service_role key (bypasses RLS)
curl 'https://<project_ref>.supabase.co/rest/v1/customers' \
  -H "apikey: <SUPABASE_SERVICE_ROLE_KEY>" \
  -H "Authorization: Bearer <SUPABASE_SERVICE_ROLE_KEY>"
```

## Configuration

### Basic Setup

```yaml
connectors:
  supabase:
    enabled: true
    project_url: "https://xyzcompany.supabase.co"
    api_key: "${SUPABASE_SERVICE_ROLE_KEY}"

    # Data sync options
    sync:
      users: true
      tables:
        - customers
        - orders
        - products
      storage: true
      realtime: true

    # Map Supabase Auth users to contacts
    user_mapping:
      email: email
      phone: SMS
      user_metadata.full_name: FIRSTNAME
      created_at: SIGNUP_DATE
```

### Field Mapping

Map Supabase table columns to engagement platform attributes:

#### Default User Mappings

| Parameter | Type | Description |
| --- | --- | --- |
| `email` required | string | User email from Supabase Auth (unique identifier) |
| `phone` optional | string | Phone number for SMS/WhatsApp engagement |
| `user_metadata.full_name` optional | string | Display name from Auth user metadata |
| `user_metadata.avatar_url` optional | string | Profile image URL |
| `created_at` optional | timestamp | Account creation timestamp |
| `last_sign_in_at` optional | timestamp | Most recent login for engagement scoring |
| `app_metadata.provider` optional | string | Auth provider (email, google, github, etc.) |
| `confirmed_at` optional | timestamp | Email confirmation timestamp |

#### Custom Table Mapping

```yaml
table_mapping:
  customers:
    # Column → Attribute mapping
    email: email
    full_name: FIRSTNAME
    company: COMPANY
    plan: SUBSCRIPTION_PLAN
    mrr: MONTHLY_REVENUE
    created_at: SIGNUP_DATE

  orders:
    # Track as events
    sync_as: events
    event_name: "order_placed"
    properties:
      total: amount
      status: order_status
      items: line_items
```

## API Endpoints

The Supabase REST API is auto-generated from your database schema at `https://<ref>.supabase.co/rest/v1/`.

| Endpoint | Method | Description |
| --- | --- | --- |
| `/rest/v1/{table}` | `GET` | Query rows with filtering, ordering, pagination |
| `/rest/v1/{table}` | `POST` | Insert rows (supports bulk and upsert) |
| `/rest/v1/{table}` | `PATCH` | Update rows matching filters |
| `/rest/v1/{table}` | `DELETE` | Delete rows matching filters |
| `/rest/v1/rpc/{function}` | `POST` | Call a Postgres function |
| `/auth/v1/signup` | `POST` | Create a new user |
| `/auth/v1/token?grant_type=password` | `POST` | Sign in with password |
| `/auth/v1/user` | `GET` | Get current user |
| `/auth/v1/admin/users` | `GET` | List all users (service\_role) |
| `/storage/v1/object/{bucket}/{path}` | `POST` | Upload file |
| `/storage/v1/object/list/{bucket}` | `POST` | List files in bucket |
| `/functions/v1/{function_name}` | `POST` | Invoke Edge Function |

### Filtering Operators

| Operator | Description | Example |
| --- | --- | --- |
| `eq` | Equal | `?status=eq.active` |
| `neq` | Not equal | `?status=neq.deleted` |
| `gt`, `gte` | Greater than | `?amount=gt.100` |
| `lt`, `lte` | Less than | `?created_at=lt.2024-01-01` |
| `like`, `ilike` | Pattern match | `?name=ilike.%john%` |
| `in` | In array | `?status=in.(active,trial)` |
| `is` | Null check | `?deleted_at=is.null` |

## Events

### Auth Events

| Event | Trigger | Use Case |
| --- | --- | --- |
| `user.signed_up` | New user registration | Welcome series |
| `user.signed_in` | User login | Activity tracking |
| `user.updated` | Profile changes | Data sync |
| `user.deleted` | Account deletion | Cleanup workflows |

### Database Events (Realtime)

| Event | Trigger | Use Case |
| --- | --- | --- |
| `INSERT` | New row added | New order/customer notifications |
| `UPDATE` | Row modified | Status change workflows |
| `DELETE` | Row removed | Churn detection |

### Webhook Events

| Event | Trigger | Use Case |
| --- | --- | --- |
| `auth.user.created` | User signup via webhook | Trigger onboarding |
| `storage.object.created` | File uploaded | Asset processing |

## Code Examples

### Initialize Connector

```javascript
import { TajoClient } from '@tajo/sdk';
import { createClient } from '@supabase/supabase-js';

const tajo = new TajoClient({
  apiKey: process.env.TAJO_API_KEY,
});

// Connect Supabase project
await tajo.connectors.connect('supabase', {
  projectUrl: process.env.SUPABASE_URL,
  serviceRoleKey: process.env.SUPABASE_SERVICE_ROLE_KEY,
});
```

### Sync Users to Contacts

```javascript
// Sync all Supabase Auth users as contacts
await tajo.connectors.sync('supabase', {
  type: 'full',
  resources: ['users'],
});

// Incremental sync (new/changed users only)
await tajo.connectors.sync('supabase', {
  type: 'incremental',
  resources: ['users'],
  since: '2024-01-01T00:00:00Z',
});
```

### Listen to Real-time Changes

```javascript
// Subscribe to new orders for engagement triggers
const supabase = createClient(
  process.env.SUPABASE_URL,
  process.env.SUPABASE_SERVICE_ROLE_KEY
);

supabase
  .channel('orders')
  .on('postgres_changes',
    { event: 'INSERT', schema: 'public', table: 'orders' },
    async (payload) => {
      // Forward to Tajo as an event
      await tajo.events.track({
        email: payload.new.customer_email,
        event: 'order_placed',
        properties: {
          order_id: payload.new.id,
          total: payload.new.total,
          items: payload.new.line_items,
        },
      });
    }
  )
  .subscribe();
```

### Query and Segment

```javascript
// Query customers by plan for targeted campaigns
const { data: proUsers } = await supabase
  .from('customers')
  .select('email, full_name, plan, mrr')
  .eq('plan', 'pro')
  .gt('mrr', 100)
  .order('mrr', { ascending: false });

// Sync to a Brevo list for campaign targeting
await tajo.lists.addContacts(PRO_LIST_ID, proUsers);
```

## Rate Limits

API Rate Limits

Supabase rate limits depend on your plan. Free tier: 500 requests/minute. Pro: 1,000 requests/second. Contact Supabase for Enterprise limits.

| Plan | Rate Limit | Realtime Connections |
| --- | --- | --- |
| Free | 500 req/min | 200 concurrent |
| Pro | 1,000 req/s | 500 concurrent |
| Team | 2,000 req/s | 1,000 concurrent |
| Enterprise | Custom | Custom |

## Troubleshooting

### Common Issues

| Issue | Cause | Solution |
| --- | --- | --- |
| 401 Unauthorized | Invalid or expired API key | Check API keys in Supabase Dashboard → Settings → API |
| 403 Forbidden | RLS policy blocking access | Use `service_role` key for admin operations, or check RLS policies |
| No realtime events | Realtime not enabled for table | Enable in Database → Replication → add table to publication |
| Empty query results | RLS filtering all rows | Verify RLS policies allow the authenticated role to read |
| Storage upload fails | Bucket policies | Check Storage bucket is set to public or has correct RLS policies |

### Debug Mode

```yaml
connectors:
  supabase:
    debug: true
    log_level: verbose
    log_queries: true
    log_realtime: true
```

### Test Connection

```bash
tajo connectors test supabase
# ✓ API connection successful
# ✓ Auth endpoint accessible
# ✓ Tables readable (12 tables found)
# ✓ Storage accessible (3 buckets)
# ✓ Realtime connection established
# ✓ Edge Functions available (4 functions)
```

## Best Practices

1. **Use service\_role key server-side only**, Never expose it in client code
2. **Enable RLS on all tables**, Even with service\_role, design with RLS for defense in depth
3. **Use Realtime for event-driven sync**, More efficient than polling for changes
4. **Batch operations**, Use bulk inserts and the `in` filter for high-volume operations
5. **Map user metadata**, Store engagement-relevant fields in `user_metadata` during signup
6. **Use Edge Functions for webhooks**, Process incoming webhooks with Supabase Edge Functions for low-latency handling

## Security

- **API Key Authentication**, All requests require valid API keys
- **Row Level Security (RLS)**, Postgres-native access control per row
- **JWT Verification**, Auth tokens are signed JWTs verified on every request
- **SSL/TLS**, All connections encrypted in transit
- **SOC 2 Type II**, Supabase is SOC 2 compliant
- **Network Restrictions**, Optional IP allowlisting on paid plans

## Related Resources

- [Shopify Connector](https://tajo.io/docs/connectors/ecommerce/shopify)
- [Stripe Connector](https://tajo.io/docs/connectors/ecommerce/stripe)
- [Auth0 Connector](https://tajo.io/docs/connectors/custom/auth0)
- [Supabase Official Docs](https://supabase.com/docs)
- [Supabase REST API Guide](https://supabase.com/docs/guides/api)
- [Supabase Auth Guide](https://supabase.com/docs/guides/auth)

## Open-Source Implementation Map

No official open-source repository was found in the current Tajo connector catalog for Supabase. Keep this page focused on the verified public API contract and vendor documentation until an official schema, SDK, MCP server, or public integration repository is available.

### Tajo Revamp Checklist

- Verify authentication and scope requirements against the vendor documentation before each connector release.
- Document primary sync objects, external IDs, pagination strategy, and rate limits explicitly.
- Add smoke tests from public API examples rather than undocumented behavior.
- Capture webhook signature verification and replay protection when the vendor supports webhooks.
- Record gaps where no official public repository or schema exists so future maintainers know what still needs source-backed validation.
