--- title: Database API Reference description: PostgREST-style database operations via REST API --- ## Overview The Database API provides PostgREST-style CRUD operations for your database tables. All requests require authentication headers. ## Headers ```bash Authorization: Bearer your-jwt-token-or-anon-key Content-Type: application/json ``` --- ## Query Records Retrieve records from a table with filtering, sorting, and pagination. ``` GET /api/database/records/{tableName} ``` ### Query Parameters | Parameter | Type | Description | |-----------|------|-------------| | `limit` | integer | Maximum records to return (1-1000, default: 100) | | `offset` | integer | Records to skip for pagination (default: 0) | | `order` | string | Sort order (e.g., `createdAt.desc`, `name.asc`) | | `select` | string | Comma-separated columns to return | | `{field}` | string | PostgREST filter (e.g., `status=eq.active`) | ### Filter Operators | Operator | Description | Example | |----------|-------------|---------| | `eq` | Equal | `status=eq.active` | | `neq` | Not equal | `status=neq.deleted` | | `gt` | Greater than | `age=gt.18` | | `gte` | Greater than or equal | `price=gte.100` | | `lt` | Less than | `quantity=lt.10` | | `lte` | Less than or equal | `score=lte.50` | | `like` | Pattern match (case-sensitive) | `name=like.*john*` | | `ilike` | Pattern match (case-insensitive) | `email=ilike.*@gmail.com` | | `in` | In list | `status=in.(active,pending)` | | `is` | Is null/true/false | `deleted_at=is.null` | ### Example ```bash # Get all posts curl "https://your-app.insforge.app/api/database/records/posts" \ -H "Authorization: Bearer your-jwt-token" # Get posts with filters curl "https://your-app.insforge.app/api/database/records/posts?status=eq.published&order=createdAt.desc&limit=10" \ -H "Authorization: Bearer your-jwt-token" # Select specific columns curl "https://your-app.insforge.app/api/database/records/posts?select=id,title,author" \ -H "Authorization: Bearer your-jwt-token" ``` ### Response ```json [ { "id": "248373e1-0aea-45ce-8844-5ef259203749", "title": "Getting Started with InsForge", "content": "This is a guide to help you get started...", "createdAt": "2025-07-18T05:37:24.338Z", "updatedAt": "2025-07-18T05:37:24.338Z" } ] ``` ### Response Headers | Header | Description | |--------|-------------| | `X-Total-Count` | Total records matching the query | | `Content-Range` | Range of records returned (e.g., `0-99/1234`) | --- ## Create Records Create one or more records in a table. ``` POST /api/database/records/{tableName} ``` **Important**: Request body MUST be an array, even for single records. ### Headers | Header | Value | Description | |--------|-------|-------------| | `Prefer` | `return=representation` | Include to return created records | ### Example ```bash # Create a single record curl -X POST "https://your-app.insforge.app/api/database/records/posts" \ -H "Authorization: Bearer your-jwt-token" \ -H "Content-Type: application/json" \ -H "Prefer: return=representation" \ -d '[{ "title": "My First Post", "content": "Hello world!", "published": true }]' # Create multiple records curl -X POST "https://your-app.insforge.app/api/database/records/posts" \ -H "Authorization: Bearer your-jwt-token" \ -H "Content-Type: application/json" \ -H "Prefer: return=representation" \ -d '[ {"title": "Post 1", "content": "Content 1"}, {"title": "Post 2", "content": "Content 2"} ]' ``` ### Response Without `Prefer` header: ```json [] ``` With `Prefer: return=representation`: ```json [ { "id": "248373e1-0aea-45ce-8844-5ef259203749", "title": "My First Post", "content": "Hello world!", "published": true, "createdAt": "2025-07-18T05:37:24.338Z", "updatedAt": "2025-07-18T05:37:24.338Z" } ] ``` --- ## Update Records Update records matching query filters. ``` PATCH /api/database/records/{tableName} ``` ### Query Parameters Use filter operators to specify which records to update. ### Headers | Header | Value | Description | |--------|-------|-------------| | `Prefer` | `return=representation` | Include to return updated records | ### Example ```bash # Update a single record by ID curl -X PATCH "https://your-app.insforge.app/api/database/records/posts?id=eq.248373e1-0aea-45ce-8844-5ef259203749" \ -H "Authorization: Bearer your-jwt-token" \ -H "Content-Type: application/json" \ -H "Prefer: return=representation" \ -d '{ "title": "Updated Post Title", "content": "This content has been updated." }' # Update multiple records curl -X PATCH "https://your-app.insforge.app/api/database/records/posts?status=eq.draft" \ -H "Authorization: Bearer your-jwt-token" \ -H "Content-Type: application/json" \ -d '{"status": "archived"}' ``` ### Response ```json [ { "id": "248373e1-0aea-45ce-8844-5ef259203749", "title": "Updated Post Title", "content": "This content has been updated.", "createdAt": "2025-01-01T00:00:00Z", "updatedAt": "2025-01-21T11:00:00Z" } ] ``` --- ## Delete Records Delete records matching query filters. ``` DELETE /api/database/records/{tableName} ``` ### Query Parameters Use filter operators to specify which records to delete. ### Headers | Header | Value | Description | |--------|-------|-------------| | `Prefer` | `return=representation` | Include to return deleted records | ### Example ```bash # Delete by ID curl -X DELETE "https://your-app.insforge.app/api/database/records/posts?id=eq.248373e1-0aea-45ce-8844-5ef259203749" \ -H "Authorization: Bearer your-jwt-token" # Delete with Prefer header to see deleted records curl -X DELETE "https://your-app.insforge.app/api/database/records/posts?status=eq.archived" \ -H "Authorization: Bearer your-jwt-token" \ -H "Prefer: return=representation" ``` ### Response Without `Prefer` header: `204 No Content` With `Prefer: return=representation`: ```json [ { "id": "248373e1-0aea-45ce-8844-5ef259203749", "title": "Deleted Post", "createdAt": "2025-01-01T00:00:00Z" } ] ``` --- ## Error Responses ### Table Not Found (404) ```json { "error": "TABLE_NOT_FOUND", "message": "Table 'nonexistent' does not exist", "statusCode": 404, "nextActions": "Check table name and try again" } ``` ### Invalid Query (400) ```json { "error": "INVALID_QUERY", "message": "Invalid filter syntax", "statusCode": 400, "nextActions": "Check PostgREST filter documentation" } ``` ### Validation Error (400) ```json { "error": "VALIDATION_ERROR", "message": "Invalid field type: expected boolean for 'published'", "statusCode": 400, "nextActions": "Ensure field types match the table schema" } ``` --- ## Examples ### Pagination ```bash # Page 1 (first 20 records) curl "https://your-app.insforge.app/api/database/records/posts?limit=20&offset=0" # Page 2 (next 20 records) curl "https://your-app.insforge.app/api/database/records/posts?limit=20&offset=20" ``` ### Complex Filters ```bash # Multiple conditions curl "https://your-app.insforge.app/api/database/records/posts?status=eq.published&author_id=eq.123&order=createdAt.desc" # Search with pattern curl "https://your-app.insforge.app/api/database/records/users?email=ilike.*@company.com" # In list curl "https://your-app.insforge.app/api/database/records/orders?status=in.(pending,processing)" # Null check curl "https://your-app.insforge.app/api/database/records/tasks?completed_at=is.null" ``` ### Upsert (Insert or Update) Insert a record or update it if a conflict occurs on a unique constraint. ``` POST /api/database/records/{tableName} ``` #### Headers | Header | Value | Description | |--------|-------|-------------| | `Prefer` | `resolution=merge-duplicates` | Update existing record on conflict | | `Prefer` | `resolution=ignore-duplicates` | Ignore insert if record exists | #### Example ```bash # Upsert: insert or update on conflict curl -X POST "https://your-app.insforge.app/api/database/records/user_settings" \ -H "Authorization: Bearer your-jwt-token" \ -H "Content-Type: application/json" \ -H "Prefer: resolution=merge-duplicates,return=representation" \ -d '[{ "user_id": "123e4567-e89b-12d3-a456-426614174000", "theme": "dark", "notifications": true }]' ``` #### Response ```json [ { "id": "550e8400-e29b-41d4-a716-446655440000", "user_id": "123e4567-e89b-12d3-a456-426614174000", "theme": "dark", "notifications": true, "createdAt": "2025-01-01T00:00:00Z", "updatedAt": "2025-01-21T11:00:00Z" } ] ``` Upsert requires a unique constraint (e.g., primary key or unique index) on the table. The conflict resolution is based on this constraint. --- ## Call RPC Function Execute a database function via PostgREST RPC. Supports all HTTP methods (GET, POST, PUT, PATCH, DELETE). ``` POST /api/database/rpc/{functionName} ``` ### Example ```bash # Call a function with parameters curl -X POST "https://your-app.insforge.app/api/database/rpc/get_user_stats" \ -H "Authorization: Bearer your-jwt-token" \ -H "Content-Type: application/json" \ -d '{"user_id": "123e4567-e89b-12d3-a456-426614174000"}' # Call a function without parameters curl -X POST "https://your-app.insforge.app/api/database/rpc/get_total_count" \ -H "Authorization: Bearer your-jwt-token" ``` ### Response ```json { "total_posts": 42, "total_comments": 128, "last_activity": "2025-01-15T10:30:00Z" } ``` --- ## Admin Endpoints The following endpoints require admin authentication. ### Headers for Admin Endpoints ```bash Authorization: Bearer admin-jwt-token-Or-API-Key Content-Type: application/json ``` --- ## List Database Functions Get all database functions in the public schema. **Requires admin authentication.** ``` GET /api/database/functions ``` ### Example ```bash curl "https://your-app.insforge.app/api/database/functions" \ -H "Authorization: Bearer admin-jwt-token-Or-API-Key" ``` ### Response ```json [ { "name": "get_user_stats", "schema": "public", "language": "plpgsql", "returnType": "json", "arguments": "user_id uuid", "definition": "BEGIN ... END;" } ] ``` --- ## List Database Indexes Get all database indexes. **Requires admin authentication.** ``` GET /api/database/indexes ``` ### Example ```bash curl "https://your-app.insforge.app/api/database/indexes" \ -H "Authorization: Bearer admin-jwt-token-Or-API-Key" ``` ### Response ```json [ { "name": "posts_pkey", "tableName": "posts", "columns": ["id"], "isUnique": true, "isPrimary": true, "definition": "CREATE UNIQUE INDEX posts_pkey ON public.posts USING btree (id)" } ] ``` --- ## List RLS Policies Get all Row Level Security policies. **Requires admin authentication.** ``` GET /api/database/policies ``` ### Example ```bash curl "https://your-app.insforge.app/api/database/policies" \ -H "Authorization: Bearer admin-jwt-token-Or-API-Key" ``` ### Response ```json [ { "name": "Users can view own posts", "tableName": "posts", "command": "SELECT", "roles": ["authenticated"], "using": "(auth.uid() = user_id)", "withCheck": null } ] ``` --- ## List Database Triggers Get all database triggers. **Requires admin authentication.** ``` GET /api/database/triggers ``` ### Example ```bash curl "https://your-app.insforge.app/api/database/triggers" \ -H "Authorization: Bearer admin-jwt-token-Or-API-Key" ``` ### Response ```json [ { "name": "update_timestamp", "tableName": "posts", "timing": "BEFORE", "events": ["UPDATE"], "functionName": "update_updated_at_column", "enabled": true } ] ``` --- ## List Database Migrations Get the history of successful custom migrations. InsForge stores these in `system.custom_migrations`, but the endpoint returns only the migration metadata and executed statements. **Requires admin authentication.** ``` GET /api/database/migrations ``` ### Example ```bash curl "https://your-app.insforge.app/api/database/migrations" \ -H "Authorization: Bearer admin-jwt-token-Or-API-Key" ``` ### Response ```json { "migrations": [ { "version": "20260416170500", "name": "create-posts-table", "statements": [ "CREATE TABLE posts (id UUID PRIMARY KEY DEFAULT gen_random_uuid(), title TEXT NOT NULL);" ], "createdAt": "2026-04-16T17:05:00.000Z" } ] } ``` --- ## Create Database Migration Create and immediately execute a custom migration against the database. The migration is recorded only if every statement succeeds. **Requires admin authentication.** ``` POST /api/database/migrations ``` ### Request Body | Field | Type | Required | Description | |-------|------|----------|-------------| | `version` | string | Yes | Numeric migration version (up to 64 digits). Accepts Drizzle-style sequential prefixes (e.g. `0001`) or a `YYYYMMDDHHmmss` timestamp. Versions are compared numerically. The InsForge CLI generates 14-digit UTC timestamps for local migration filenames. | | `name` | string | Yes | Migration name using lowercase letters, numbers, and hyphens only | | `sql` | string | Yes | SQL text to parse and execute | ### Example ```bash curl -X POST "https://your-app.insforge.app/api/database/migrations" \ -H "Authorization: Bearer admin-jwt-token-Or-API-Key" \ -H "Content-Type: application/json" \ -d '{ "version": "20260416170500", "name": "create-posts-table", "sql": "CREATE TABLE posts (id UUID PRIMARY KEY DEFAULT gen_random_uuid(), title TEXT NOT NULL);" }' ``` ### Response ```json { "version": "20260416170500", "name": "create-posts-table", "statements": [ "CREATE TABLE posts (id UUID PRIMARY KEY DEFAULT gen_random_uuid(), title TEXT NOT NULL);" ], "createdAt": "2026-04-16T17:05:00.000Z", "message": "Migration executed successfully" } ``` Do not include `BEGIN`, `COMMIT`, or `ROLLBACK` inside a custom migration. InsForge executes the migration inside its own transaction. --- ## Execute Raw SQL (Strict Mode) Execute raw SQL query with strict sanitization. Blocks access to system tables and auth.users. **Requires admin authentication.** ``` POST /api/database/advance/rawsql ``` ### Request Body | Field | Type | Required | Description | |-------|------|----------|-------------| | `query` | string | Yes | SQL query to execute | | `params` | array | No | Query parameters for parameterized queries | ### Example ```bash curl -X POST "https://your-app.insforge.app/api/database/advance/rawsql" \ -H "Authorization: Bearer admin-jwt-token-Or-API-Key" \ -H "Content-Type: application/json" \ -d '{ "query": "SELECT * FROM posts WHERE published = $1", "params": [true] }' ``` ### Response ```json { "rows": [ { "id": "248373e1-0aea-45ce-8844-5ef259203749", "title": "My Post", "published": true } ], "rowCount": 1, "command": "SELECT" } ``` --- ## Execute Raw SQL (Relaxed Mode) Execute raw SQL query with relaxed sanitization. Allows SELECT and INSERT into system tables. **Use with caution. Requires admin authentication.** ``` POST /api/database/advance/rawsql/unrestricted ``` ### Request Body | Field | Type | Required | Description | |-------|------|----------|-------------| | `query` | string | Yes | SQL query to execute | | `params` | array | No | Query parameters for parameterized queries | ### Example ```bash curl -X POST "https://your-app.insforge.app/api/database/advance/rawsql/unrestricted" \ -H "Authorization: Bearer admin-jwt-token-Or-API-Key" \ -H "Content-Type: application/json" \ -d '{ "query": "SELECT * FROM auth.users LIMIT 10" }' ``` ### Response ```json { "rows": [...], "rowCount": 10, "command": "SELECT" } ``` This endpoint has relaxed restrictions and can access system tables. Use only when necessary and ensure proper authorization. --- ## Export Database Export database schema and/or data in SQL or JSON format. **Requires admin authentication.** ``` POST /api/database/advance/export ``` ### Request Body | Field | Type | Required | Default | Description | |-------|------|----------|---------|-------------| | `tables` | array | No | all | List of tables to export | | `format` | string | No | sql | Export format (`sql` or `json`) | | `includeData` | boolean | No | true | Include table data | | `includeFunctions` | boolean | No | false | Include database functions | | `includeSequences` | boolean | No | false | Include sequences | | `includeViews` | boolean | No | false | Include views | | `rowLimit` | integer | No | - | Maximum rows per table | ### Example ```bash curl -X POST "https://your-app.insforge.app/api/database/advance/export" \ -H "Authorization: Bearer admin-jwt-token-Or-API-Key" \ -H "Content-Type: application/json" \ -d '{ "tables": ["posts", "comments"], "format": "sql", "includeData": true, "rowLimit": 1000 }' ``` ### Response ```json { "format": "sql", "content": "CREATE TABLE posts (...); INSERT INTO posts VALUES (...);", "tables": ["posts", "comments"] } ``` --- ## Import Database Import database from SQL file. **Requires admin authentication.** ``` POST /api/database/advance/import ``` ### Request (multipart/form-data) | Field | Type | Required | Default | Description | |-------|------|----------|---------|-------------| | `file` | file | Yes | - | SQL file to import | | `truncate` | boolean | No | false | Truncate existing tables before import | ### Example ```bash curl -X POST "https://your-app.insforge.app/api/database/advance/import" \ -H "Authorization: Bearer admin-jwt-token-Or-API-Key" \ -F "file=@backup.sql" \ -F "truncate=false" ``` ### Response ```json { "filename": "backup.sql", "fileSize": 102400, "tables": ["posts", "comments", "users"], "rowsImported": 1500 } ``` --- ## Bulk Upsert Bulk insert or update data from CSV or JSON file. **Requires admin authentication.** ``` POST /api/database/advance/bulk-upsert ``` ### Request (multipart/form-data) | Field | Type | Required | Description | |-------|------|----------|-------------| | `file` | file | Yes | CSV or JSON file containing data | | `table` | string | Yes | Target table name | | `upsertKey` | string | No | Column name for upsert conflict resolution | ### Example ```bash # Import from CSV curl -X POST "https://your-app.insforge.app/api/database/advance/bulk-upsert" \ -H "Authorization: Bearer admin-jwt-token-Or-API-Key" \ -F "file=@data.csv" \ -F "table=posts" \ -F "upsertKey=id" # Import from JSON curl -X POST "https://your-app.insforge.app/api/database/advance/bulk-upsert" \ -H "Authorization: Bearer admin-jwt-token-Or-API-Key" \ -F "file=@data.json" \ -F "table=posts" ``` ### Response ```json { "rowsAffected": 150, "totalRecords": 150, "table": "posts" }