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

# Supabase

> Client-mode REST API connector for Supabase PostgREST select/insert/upsert and Storage list/upload — MQTT into Postgres tables and buckets

Technical Preview

## Overview

A client-mode connector for a **curated** slice of the [Supabase Data API](https://supabase.com/docs/guides/api) (PostgREST on Postgres) plus [Storage](https://supabase.com/docs/guides/storage/uploads/standard-uploads) HTTP:

| Catalog connector event | Entity / path | Notes |
| - | - | - |
| GET rest/v1/\{table}?device\_id=eq.\{id} | `GET /rest/v1/{table}` | PostgREST filters + `select=` |
| POST rest/v1/\{table} | `POST /rest/v1/{table}` | Insert; `Prefer: return=representation` |
| Upsert merge-duplicates | `POST /rest/v1/{table}?on_conflict=` | `Prefer: resolution=merge-duplicates,return=representation` |
| (supporting) PATCH / DELETE | same table path + filter | Row updates / deletes |
| (supporting) OpenAPI | `GET /rest/v1/` | Auto-generated per project |
| (supporting) Storage list / upload | `/storage/v1/object/...` | List + standard upload |
| Database webhook | outbound from Supabase | Inbound receive → separate `ENABLE_SERVER` connector |

Default `BASE_ADDRESS` is `https://YOUR_PROJECT_REF.supabase.co` (no trailing slash). Topics use `data/supabase/<object>/<verb>`.

See the base guide: [REST API Connectors](/latest/lot-language/routes/rest-api-routes).

> [!NOTE]
>
> **Auth:** every request needs `apikey` **and** `Authorization: Bearer &lt;jwt&gt;` (anon/publishable or service\_role/secret). Prefer Hub secrets (`GET SECRET "SUPABASE_ANON_KEY"` / `"SUPABASE_SERVICE_ROLE_KEY"`). Never expose service\_role in browsers.

> [!NOTE]
>
> **Database webhooks:** Supabase POSTs outbound when rows change. Receiving those callbacks on Coreflux needs a separate server-mode REST\_API connector — not part of this client-only template.

> [!NOTE]
>
> Factory live smoke is **blocked** until a project URL + key are supplied. Point `BASE_ADDRESS` at your project and pass keys via MQTT JSON / Hub secrets before production use.

## Basic Syntax

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
# Coreflux REST_API template — Supabase PostgREST / Storage
# Auth: apikey + Authorization Bearer {value.json.api_token}
# BASE_ADDRESS: https://YOUR_PROJECT_REF.supabase.co

DEFINE ROUTE SupabaseRestApi WITH TYPE REST_API
    ADD REST_API_CONFIG
        WITH BASE_ADDRESS "https://YOUR_PROJECT_REF.supabase.co"
        WITH ENABLE_CLIENT "true"
        WITH USE_SSL "true"
        WITH REQUEST_TIMEOUT '60'
        WITH DEFAULT_CONTENT_TYPE "application/json"
    ADD EVENT SelectRows
        WITH SOURCE_TOPIC "data/supabase/rows/select"
        WITH DESTINATION_TOPIC "data/supabase/rows/select/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/rest/v1/{value.json.table}?device_id=eq.{value.json.device_id}&select={value.json.select}"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "apikey" "{value.json.api_key}"
            ADD "Authorization" "Bearer {value.json.api_token}"
    ADD EVENT UpsertRows
        WITH SOURCE_TOPIC "data/supabase/rows/upsert"
        WITH DESTINATION_TOPIC "data/supabase/rows/upsert/response"
        WITH METHOD "POST"
        WITH ENDPOINT "/rest/v1/{value.json.table}?on_conflict={value.json.on_conflict}"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Content-Type" "application/json"
            ADD "Prefer" "resolution=merge-duplicates,return=representation"
            ADD "apikey" "{value.json.api_key}"
            ADD "Authorization" "Bearer {value.json.api_token}"
        WITH BODY "{payload}"
```

Full deployable file: `SupabaseRestApi.lot` in the factory package (no `ADD METADATA`).

## Topics

| Event | Source topic | Destination topic |
| - | - | - |
| SelectRows | `data/supabase/rows/select` | `…/response` |
| InsertRows | `data/supabase/rows/insert` | `…/response` |
| UpsertRows | `data/supabase/rows/upsert` | `…/response` |
| PatchRows | `data/supabase/rows/patch` | `…/response` |
| DeleteRows | `data/supabase/rows/delete` | `…/response` |
| GetOpenApi | `data/supabase/openapi` | `…/response` |
| ListStorageObjects | `data/supabase/storage/list` | `…/response` |
| UploadStorageObject | `data/supabase/storage/upload` | `…/response` |

## Configuration

1. Set `BASE_ADDRESS` to `https://{project_ref}.supabase.co`.
2. Store anon or service\_role JWT in Hub secrets; map into MQTT `api_key` / `api_token` (or broker secret placeholders when your Hub wiring supports it).
3. Expose the target table to the Data API and add RLS policies for the role you use.
4. For upsert, pass `on_conflict` (unique / PK columns) and include those columns in the JSON body.

## References

* [Supabase Data API](https://supabase.com/docs/guides/api)
* [Creating API connectors](https://supabase.com/docs/guides/api/creating-routes)
* [Database webhooks](https://supabase.com/docs/guides/database/webhooks)
* [Storage standard uploads](https://supabase.com/docs/guides/storage/uploads/standard-uploads)
* [PostgREST tables and views](https://postgrest.org/en/stable/references/api/tables_views.html)

## Template reference

Generated from the shipped broker template `supabase` (`-routeCode SUPABASE`). It lists every event the template defines.

### Auth

apikey header + Authorization: Bearer \{value.json.api\_token} (anon/publishable or service\_role/secret JWT). Prefer GET SECRET SUPABASE\_ANON\_KEY or SUPABASE\_SERVICE\_ROLE\_KEY. Never commit real credentials.

Auth headers used by the template: `Authorization: Bearer {value.json.api_token}`, `apikey: {value.json.api_key}`.

### Template parameters

| Placeholder | Type | Description | Required |
| - | - | - | - |
| `RouteName` | string | Name of the Supabase connector | no |
| `BaseUrl` | string | Supabase base URL without trailing slash (e.g. [https://YOUR\_PROJECT\_REF.supabase.co](https://YOUR_PROJECT_REF.supabase.co)) | yes |

`BASE_ADDRESS` default: `https://YOUR_PROJECT_REF.supabase.co`.

### Events

| Event | Method | Endpoint | Request topic | Response topic | Payload fields |
| - | - | - | - | - | - |
| `SelectRows` | GET | `/rest/v1/{value.json.table}?device_id=eq.{value.json.device_id}&select={value.json.select}` | `data/supabase/rows/select` | `data/supabase/rows/select/response` | `api_key`, `api_token`, `device_id`, `select`, `table` |
| `InsertRows` | POST | `/rest/v1/{value.json.table}` | `data/supabase/rows/insert` | `data/supabase/rows/insert/response` | `api_key`, `api_token`, `body`, `table` |
| `UpsertRows` | POST | `/rest/v1/{value.json.table}?on_conflict={value.json.on_conflict}` | `data/supabase/rows/upsert` | `data/supabase/rows/upsert/response` | `api_key`, `api_token`, `body`, `on_conflict`, `table` |
| `PatchRows` | PATCH | `/rest/v1/{value.json.table}?device_id=eq.{value.json.device_id}` | `data/supabase/rows/patch` | `data/supabase/rows/patch/response` | `api_key`, `api_token`, `body`, `device_id`, `table` |
| `DeleteRows` | DELETE | `/rest/v1/{value.json.table}?device_id=eq.{value.json.device_id}` | `data/supabase/rows/delete` | `data/supabase/rows/delete/response` | `api_key`, `api_token`, `device_id`, `table` |
| `GetOpenApi` | GET | `/rest/v1/` | `data/supabase/openapi` | `data/supabase/openapi/response` | `api_key`, `api_token` |
| `ListStorageObjects` | POST | `/storage/v1/object/list/{value.json.bucket}` | `data/supabase/storage/list` | `data/supabase/storage/list/response` | `api_key`, `api_token`, `body`, `bucket` |
| `UploadStorageObject` | POST | `/storage/v1/object/{value.json.bucket}/{value.json.object_path}` | `data/supabase/storage/upload` | `data/supabase/storage/upload/response` | `api_key`, `api_token`, `body`, `bucket`, `content_type`, `object_path`, `x_upsert` |

### Deploy

Get the template card (JSON with `template` and `metadata`) from the broker, then deploy the connector:

```bash theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
mosquitto_pub -t '$SYS/Coreflux/Command' -m "-routeCode SUPABASE"
```

The deployable connector from the REST API app, with `BASE_ADDRESS` already filled in:

```lot theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
DEFINE ROUTE SupabaseRestApi WITH TYPE REST_API
    ADD REST_API_CONFIG
        WITH BASE_ADDRESS "https://YOUR_PROJECT_REF.supabase.co"
        WITH ENABLE_CLIENT "true"
        WITH USE_SSL "true"
        WITH REQUEST_TIMEOUT '60'
        WITH DEFAULT_CONTENT_TYPE "application/json"
    ADD EVENT SelectRows
        WITH SOURCE_TOPIC "data/supabase/rows/select"
        WITH DESTINATION_TOPIC "data/supabase/rows/select/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/rest/v1/{value.json.table}?device_id=eq.{value.json.device_id}&select={value.json.select}"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "apikey" "{value.json.api_key}"
            ADD "Authorization" "Bearer {value.json.api_token}"
    ADD EVENT InsertRows
        WITH SOURCE_TOPIC "data/supabase/rows/insert"
        WITH DESTINATION_TOPIC "data/supabase/rows/insert/response"
        WITH METHOD "POST"
        WITH ENDPOINT "/rest/v1/{value.json.table}"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Content-Type" "application/json"
            ADD "Prefer" "return=representation"
            ADD "apikey" "{value.json.api_key}"
            ADD "Authorization" "Bearer {value.json.api_token}"
        WITH BODY "{value.json.body}"
    ADD EVENT UpsertRows
        WITH SOURCE_TOPIC "data/supabase/rows/upsert"
        WITH DESTINATION_TOPIC "data/supabase/rows/upsert/response"
        WITH METHOD "POST"
        WITH ENDPOINT "/rest/v1/{value.json.table}?on_conflict={value.json.on_conflict}"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Content-Type" "application/json"
            ADD "Prefer" "resolution=merge-duplicates,return=representation"
            ADD "apikey" "{value.json.api_key}"
            ADD "Authorization" "Bearer {value.json.api_token}"
        WITH BODY "{value.json.body}"
    ADD EVENT PatchRows
        WITH SOURCE_TOPIC "data/supabase/rows/patch"
        WITH DESTINATION_TOPIC "data/supabase/rows/patch/response"
        WITH METHOD "PATCH"
        WITH ENDPOINT "/rest/v1/{value.json.table}?device_id=eq.{value.json.device_id}"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Content-Type" "application/json"
            ADD "Prefer" "return=representation"
            ADD "apikey" "{value.json.api_key}"
            ADD "Authorization" "Bearer {value.json.api_token}"
        WITH BODY "{value.json.body}"
    ADD EVENT DeleteRows
        WITH SOURCE_TOPIC "data/supabase/rows/delete"
        WITH DESTINATION_TOPIC "data/supabase/rows/delete/response"
        WITH METHOD "DELETE"
        WITH ENDPOINT "/rest/v1/{value.json.table}?device_id=eq.{value.json.device_id}"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Prefer" "return=representation"
            ADD "apikey" "{value.json.api_key}"
            ADD "Authorization" "Bearer {value.json.api_token}"
    ADD EVENT GetOpenApi
        WITH SOURCE_TOPIC "data/supabase/openapi"
        WITH DESTINATION_TOPIC "data/supabase/openapi/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/rest/v1/"
        WITH HEADERS
            ADD "Accept" "application/openapi+json"
            ADD "apikey" "{value.json.api_key}"
            ADD "Authorization" "Bearer {value.json.api_token}"
    ADD EVENT ListStorageObjects
        WITH SOURCE_TOPIC "data/supabase/storage/list"
        WITH DESTINATION_TOPIC "data/supabase/storage/list/response"
        WITH METHOD "POST"
        WITH ENDPOINT "/storage/v1/object/list/{value.json.bucket}"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Content-Type" "application/json"
            ADD "apikey" "{value.json.api_key}"
            ADD "Authorization" "Bearer {value.json.api_token}"
        WITH BODY "{value.json.body}"
    ADD EVENT UploadStorageObject
        WITH SOURCE_TOPIC "data/supabase/storage/upload"
        WITH DESTINATION_TOPIC "data/supabase/storage/upload/response"
        WITH METHOD "POST"
        WITH ENDPOINT "/storage/v1/object/{value.json.bucket}/{value.json.object_path}"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Content-Type" "{value.json.content_type}"
            ADD "x-upsert" "{value.json.x_upsert}"
            ADD "apikey" "{value.json.api_key}"
            ADD "Authorization" "Bearer {value.json.api_token}"
        WITH BODY "{value.json.body}"
```

Deploy it with `-addRoute` (do not include `ADD METADATA`).

### Usage example

Call `SelectRows` by publishing a JSON payload to its request topic, and read the reply on the response topic:

```bash theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
mosquitto_sub -t 'data/supabase/rows/select/response' &
mosquitto_pub -t 'data/supabase/rows/select' -m '{"api_key": "<api_key>", "api_token": "<api_token>", "device_id": "<device_id>", "select": "<select>", "table": "<table>"}'
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.