diff --git a/sqlite-cloud/_nav.ts b/sqlite-cloud/_nav.ts index 0d3a9ad..cf09cb9 100644 --- a/sqlite-cloud/_nav.ts +++ b/sqlite-cloud/_nav.ts @@ -95,6 +95,12 @@ const sidebarNav: SidebarNavStruct = [ type: "inner", level: 1, }, + { + title: "Management API", + filePath: "sqlite-sync-cloudsync-management-api", + type: "inner", + level: 1, + }, { title: "Best Practices", filePath: "sqlite-sync-best-practices", @@ -113,9 +119,9 @@ const sidebarNav: SidebarNavStruct = [ type: "inner", level: 1, }, - { title: "API Reference", type: "inner", level: 1 }, + { title: "Client API Reference", type: "inner", level: 1 }, { - title: "API Overview", + title: "Overview", filePath: "sqlite-sync-api-reference", type: "inner", level: 2, diff --git a/sqlite-cloud/platform/cloudsync.mdx b/sqlite-cloud/platform/cloudsync.mdx index 3760fd8..a7e2389 100644 --- a/sqlite-cloud/platform/cloudsync.mdx +++ b/sqlite-cloud/platform/cloudsync.mdx @@ -34,10 +34,11 @@ When combined with [Row-Level Security (RLS)](/docs/rls), CloudSync allows you t You can enable and manage CloudSync for your databases directly from the SQLite Cloud dashboard. Select a database from the left panel — the list shows all databases in your project along with their CloudSync status. The right panel has four tabs: **Database Setup**, **Client Integration**, **Devices**, and **Metrics**. +If you prefer automation, you can also register databases, inspect tables, and enable CloudSync programmatically with the [Management API](/docs/sqlite-sync-cloudsync-management-api). That page documents the workspace-scoped management endpoints used with a `workspace-admin` key. + ### Enabling and Disabling CloudSync When CloudSync is not yet active for a database, the right panel shows a brief explanation and an **Enable CloudSync** button. Clicking it opens a confirmation dialog; after confirming, the database is registered with the sync service and the tabbed view appears. - To disable CloudSync, click the **Disable CloudSync** button in the top-right corner of the panel and confirm in the dialog that appears. {/* */} diff --git a/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference.md b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference.md index 30ed886..1706e3e 100644 --- a/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference.md +++ b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference.md @@ -1,6 +1,6 @@ --- -title: "SQLite-Sync API Reference" -description: "Comprehensive SQLite-Sync API reference for configuration, filters, block-level LWW, helpers, schema changes, and networking." +title: "Client API Reference" +description: "Reference for the SQLite Sync client runtime functions for configuration, filters, block-level LWW, helpers, schema changes, and networking." category: platform status: publish slug: sqlite-sync-api-reference diff --git a/sqlite-cloud/sqlite-ai/sqlite-sync/block-lww.md b/sqlite-cloud/sqlite-ai/sqlite-sync/block-lww.md index 3c48b4b..d50ae80 100644 --- a/sqlite-cloud/sqlite-ai/sqlite-sync/block-lww.md +++ b/sqlite-cloud/sqlite-ai/sqlite-sync/block-lww.md @@ -127,4 +127,4 @@ SELECT cloudsync_set_column('docs', 'body', 'algo', 'block'); - **Mixed columns**: A table can have both regular and block-level LWW columns. - **Transparent reads**: The base column always contains the current full text. -For API details, see the [API Reference](/docs/sqlite-sync-api-reference). +For API details, see the [Client API Reference](/docs/sqlite-sync-api-reference). diff --git a/sqlite-cloud/sqlite-ai/sqlite-sync/cloudsync-management-api.md b/sqlite-cloud/sqlite-ai/sqlite-sync/cloudsync-management-api.md new file mode 100644 index 0000000..7d391b0 --- /dev/null +++ b/sqlite-cloud/sqlite-ai/sqlite-sync/cloudsync-management-api.md @@ -0,0 +1,411 @@ +--- +title: "Management API" +description: "Register and manage SQLite Sync databases programmatically with a workspace-admin management API key." +category: platform +status: publish +slug: sqlite-sync-cloudsync-management-api +--- + +You can register and manage CloudSync databases programmatically without using the dashboard UI. + +This page covers only the `/v1` management endpoints that are available when you authenticate with a workspace-scoped management API key that has the `workspace-admin` role. It intentionally excludes workspace management, org-wide key management, and `/v1/admin` platform-admin endpoints. + +## Authentication + +```http +Authorization: Bearer +``` + +- Base URL: `https://cloudsync.sqlite.ai` +- Use a management API key with the `workspace-admin` role. In the [SQLite Cloud Dashboard](https://dashboard.sqlitecloud.io/), go to your project, then **CloudSync** > **API Keys**. +- The workspace is derived from the key itself. +- You cannot override the workspace with headers, query parameters, or path segments. + +Use this API from backend services, CI, or trusted automation. Client apps should use the [Client API Reference](/docs/sqlite-sync-api-reference) instead. + +## Request and Response Conventions + +- Send `Content-Type: application/json` for all `POST`, `PUT`, and `PATCH` bodies. +- Successful responses use the envelope `{"data": ...}`. +- List responses may also include a `meta` object. +- Error responses use a top-level `errors` array. + +Example error response: + +```json +{ + "errors": [ + { + "status": "404", + "code": "not_found", + "title": "Not Found", + "detail": "managed database not found" + } + ] +} +``` + +## Quickstart + +Start with a workspace-level management API key from your project's **CloudSync** > **API Keys** page in the dashboard: + +```bash +export BASE_URL="https://cloudsync.sqlite.ai" +export APIKEY="" +``` + +### 1. Register a Database + +This creates the managed database entry in CloudSync and returns the CloudSync Database ID as `managedDatabaseId`. + +```bash +curl --request POST "$BASE_URL/v1/databases" \ + --header "Authorization: Bearer $APIKEY" \ + --header "Content-Type: application/json" \ + --data '{ + "label": "Primary DB", + "connectionString": "sqlitecloud://project.sqlite.cloud:8860?apikey=xxxx", + "provider": "sqlitecloud", + "flavor": "sqlitecloud", + "databaseName": "appdb" + }' +``` + +Response: + +```json +{ + "data": { + "managedDatabaseId": "db_xxxxxxxxxxxxxxxxxxxxxxxx" + } +} +``` + +Use that value as `MGMT_DB_ID` in the next calls. + +```bash +export MGMT_DB_ID="db_xxxxxxxxxxxxxxxxxxxxxxxx" +``` + +### 2. List Registered Databases + +Useful when you want to recover the managed database ID later. + +```bash +curl --request GET "$BASE_URL/v1/databases" \ + --header "Authorization: Bearer $APIKEY" +``` + +### 3. Check Available CloudSync Tables + +```bash +curl --request GET "$BASE_URL/v1/databases/$MGMT_DB_ID/cloudsync/tables" \ + --header "Authorization: Bearer $APIKEY" +``` + +### 4. Enable CloudSync for Tables + +```bash +curl --request POST "$BASE_URL/v1/databases/$MGMT_DB_ID/cloudsync/enable" \ + --header "Authorization: Bearer $APIKEY" \ + --header "Content-Type: application/json" \ + --data '{ + "tables": ["users", "orders"] + }' +``` + +## What a `workspace-admin` Key Can Manage + +With a workspace-scoped management key, you can: + +- inspect the authenticated organization with `GET /v1/orgs` +- register, list, read, update, delete, and verify managed databases in the key's workspace +- list, enable, and disable CloudSync tables for those databases +- manage Expo notification credentials and inspect notification status +- list and remove registered devices + +It cannot: + +- list or mutate workspaces +- create, list, or revoke management API keys +- use `/v1/admin/*` endpoints + +## Endpoint Summary + +| Area | Endpoints | +| --- | --- | +| Organization | `GET /v1/orgs` | +| Databases | `POST /v1/databases`, `GET /v1/databases`, `GET /v1/databases/:databaseID`, `PATCH /v1/databases/:databaseID`, `DELETE /v1/databases/:databaseID`, `GET /v1/databases/:databaseID/connection` | +| CloudSync tables | `GET /v1/databases/:databaseID/cloudsync/tables`, `POST /v1/databases/:databaseID/cloudsync/enable`, `POST /v1/databases/:databaseID/cloudsync/disable` | +| Notifications | `PUT /v1/databases/:databaseID/notifications/expo-access-token`, `GET /v1/databases/:databaseID/notifications/expo-access-token`, `DELETE /v1/databases/:databaseID/notifications/expo-access-token`, `GET /v1/databases/:databaseID/notifications/status` | +| Devices | `GET /v1/databases/:databaseID/devices`, `DELETE /v1/databases/:databaseID/devices/:siteId` | + +## Organization + +### `GET /v1/orgs` + +Returns the organization associated with the API key. + +```bash +curl "$BASE_URL/v1/orgs" \ + --header "Authorization: Bearer $APIKEY" +``` + +```json +{ + "data": { + "organizationId": "org_xxxxxxxxxxxxxxxxxxxxxxxx", + "slug": "acme", + "name": "Acme Corp", + "status": "active" + } +} +``` + +## Databases + +### `POST /v1/databases` + +Registers a new managed database. + +Required fields: + +- `label` +- `connectionString` +- `provider` — `postgres` or `sqlitecloud` +- `flavor` — for example `vanilla`, `supabase`, or `sqlitecloud` +- `databaseName` + +Optional fields: + +- `schemaName` — Postgres only +- `jwtAllowedIssuers` +- `jwtExpectedAudiences` +- `jwksUri` +- `jwtSecret` + +Important behavior for workspace-scoped keys: + +- omit `workspaceId` +- the created database is automatically attached to the workspace derived from the key + +CloudSync verifies the tenant database connection before registration is persisted. If verification fails, the database is not registered. + +Common database failure codes include `database_paused`, `database_auth_failed`, `database_unreachable`, `database_permission_denied`, `database_cloudsync_not_ready`, and `database_error`. + +### `GET /v1/databases` + +Lists managed databases visible to the key. + +Example: + +```bash +curl "$BASE_URL/v1/databases" \ + --header "Authorization: Bearer $APIKEY" +``` + +### `GET /v1/databases/:databaseID` + +Fetches a single managed database in the workspace. + +```bash +curl "$BASE_URL/v1/databases/$MGMT_DB_ID" \ + --header "Authorization: Bearer $APIKEY" +``` + +### `PATCH /v1/databases/:databaseID` + +Updates metadata, auth settings, and connection details. Only the fields you send are modified. + +Supported fields: + +- `label` +- `connectionString` +- `jwtAllowedIssuers` +- `jwtExpectedAudiences` +- `jwksUri` +- `jwtSecret` + +Notes: + +- when `connectionString` is provided, CloudSync verifies the new connection before storing it +- omitting `jwtSecret` leaves the current secret unchanged +- sending `"jwtSecret": ""` clears the current secret +- `jwtSecret` is write-only and is never returned by read endpoints + +Example: + +```bash +curl --request PATCH "$BASE_URL/v1/databases/$MGMT_DB_ID" \ + --header "Authorization: Bearer $APIKEY" \ + --header "Content-Type: application/json" \ + --data '{ + "label": "Primary DB (updated)", + "jwtAllowedIssuers": ["https://project.supabase.co/auth/v1"], + "jwtExpectedAudiences": ["authenticated"], + "jwksUri": "https://project.supabase.co/auth/v1/.well-known/jwks.json", + "jwtSecret": "" + }' +``` + +### `DELETE /v1/databases/:databaseID` + +Deletes a managed database record. + +Before removal, CloudSync attempts to: + +1. list CloudSync-managed tenant tables +2. disable enabled tables +3. delete pending jobs for the managed database + +Cleanup is best effort. The database record is still deleted even if one of those cleanup steps reports warnings. + +```bash +curl --request DELETE "$BASE_URL/v1/databases/$MGMT_DB_ID" \ + --header "Authorization: Bearer $APIKEY" +``` + +### `GET /v1/databases/:databaseID/connection` + +Runs a live connectivity check against the managed database's stored connection details. + +```bash +curl "$BASE_URL/v1/databases/$MGMT_DB_ID/connection" \ + --header "Authorization: Bearer $APIKEY" +``` + +Success response: + +```json +{ + "data": { + "ok": true, + "checkedAt": "2025-01-01T00:00:00Z" + } +} +``` + +Failure response: + +```json +{ + "data": { + "ok": false, + "checkedAt": "2025-01-01T00:00:00Z", + "failure": { + "code": "database_unreachable", + "message": "tenant database is unreachable", + "retryable": true + } + } +} +``` + +## CloudSync Tables + +### `GET /v1/databases/:databaseID/cloudsync/tables` + +Lists tables and whether CloudSync is enabled for each one. + +```bash +curl "$BASE_URL/v1/databases/$MGMT_DB_ID/cloudsync/tables" \ + --header "Authorization: Bearer $APIKEY" +``` + +```json +{ + "data": [ + { "name": "users", "enabled": true }, + { "name": "orders", "enabled": false } + ] +} +``` + +### `POST /v1/databases/:databaseID/cloudsync/enable` + +Enables CloudSync for a non-empty list of tables. + +```bash +curl --request POST "$BASE_URL/v1/databases/$MGMT_DB_ID/cloudsync/enable" \ + --header "Authorization: Bearer $APIKEY" \ + --header "Content-Type: application/json" \ + --data '{"tables": ["users", "orders"]}' +``` + +### `POST /v1/databases/:databaseID/cloudsync/disable` + +Disables CloudSync for a non-empty list of tables. + +```bash +curl --request POST "$BASE_URL/v1/databases/$MGMT_DB_ID/cloudsync/disable" \ + --header "Authorization: Bearer $APIKEY" \ + --header "Content-Type: application/json" \ + --data '{"tables": ["orders"]}' +``` + +## Notifications + +### `PUT /v1/databases/:databaseID/notifications/expo-access-token` + +Sets or rotates the Expo access token used to send push notifications. + +```bash +curl --request PUT "$BASE_URL/v1/databases/$MGMT_DB_ID/notifications/expo-access-token" \ + --header "Authorization: Bearer $APIKEY" \ + --header "Content-Type: application/json" \ + --data '{"expoAccessToken": "expo-access-token-value"}' +``` + +### `GET /v1/databases/:databaseID/notifications/expo-access-token` + +Returns metadata about the Expo access token, not the token value itself. + +```bash +curl "$BASE_URL/v1/databases/$MGMT_DB_ID/notifications/expo-access-token" \ + --header "Authorization: Bearer $APIKEY" +``` + +### `DELETE /v1/databases/:databaseID/notifications/expo-access-token` + +Removes the Expo access token from the database. + +```bash +curl --request DELETE "$BASE_URL/v1/databases/$MGMT_DB_ID/notifications/expo-access-token" \ + --header "Authorization: Bearer $APIKEY" +``` + +### `GET /v1/databases/:databaseID/notifications/status` + +Returns the current push notification status for a managed database. + +`status` can be `enabled`, `disabled`, or `paused`. When `status` is `paused`, `reason` explains why. Currently supported pause reasons include `expo_unauthorized`. + +```bash +curl "$BASE_URL/v1/databases/$MGMT_DB_ID/notifications/status" \ + --header "Authorization: Bearer $APIKEY" +``` + +## Devices + +### `GET /v1/databases/:databaseID/devices` + +Lists registered devices for a managed database. + +Query parameters: + +- `page` — default `1` +- `page_size` — default `50`, max `500` + +```bash +curl "$BASE_URL/v1/databases/$MGMT_DB_ID/devices?page=1&page_size=50" \ + --header "Authorization: Bearer $APIKEY" +``` + +### `DELETE /v1/databases/:databaseID/devices/:siteId` + +Removes a registered device by `siteId`. Associated push tokens are removed as well. + +```bash +curl --request DELETE "$BASE_URL/v1/databases/$MGMT_DB_ID/devices/site_123" \ + --header "Authorization: Bearer $APIKEY" +``` diff --git a/sqlite-cloud/sqlite-ai/sqlite-sync/getting-started.md b/sqlite-cloud/sqlite-ai/sqlite-sync/getting-started.md index 34c7833..d41d81a 100644 --- a/sqlite-cloud/sqlite-ai/sqlite-sync/getting-started.md +++ b/sqlite-cloud/sqlite-ai/sqlite-sync/getting-started.md @@ -101,3 +101,4 @@ Back on Device A, calling `cloudsync_network_sync()` will pull Device B's change For token-based authentication (required for RLS), use `cloudsync_network_set_token()` instead of `cloudsync_network_set_apikey()`. +If you want to register the managed database and enable tables programmatically instead of using the dashboard, see [Management API](/docs/sqlite-sync-cloudsync-management-api). That flow uses a workspace-level management API key and is separate from the client authentication used by `cloudsync_network_set_apikey()` and `cloudsync_network_set_token()`.