# Spala Docs Full Corpus Generated: 2026-07-08 Canonical docs root: https://docs.spala.ai/ This file is for AI agents, search systems, and non-JS crawlers. It contains the full plain-text content of every public docs page. Use the canonical route URLs when citing or navigating. --- title: Advanced Integration Help route: https://docs.spala.ai/addons/javascript-addons/ path: /addons/javascript-addons description: Use built-in addons, API calls, and Spala support for advanced integration needs. section: addons updated: 2026-07-08 --- # Advanced Integration Help Use built-in addons, API calls, and Spala support for advanced integration needs. Advanced Integration Help Most Spala projects do not need custom integration code. Start with built-in addons, External API Call, webhooks, and AI Copilot. Use The Dashboard First - Install a catalog addon when one exists. - Use External API Call for REST APIs. - Store credentials in project environment variables. - Ask AI Copilot to wire the integration into your backend flow. Need something reusable? If your team needs a private reusable integration or organization-specific catalog item, contact Spala support. Addons /addons Browse ready-to-use integrations External API Steps /reference/steps/api Call external APIs from functions AI Copilot /features/ai-assistant Describe the integration you need --- title: Anthropic route: https://docs.spala.ai/addons/catalog/anthropic/ path: /addons/catalog/anthropic description: Integrate Anthropic's Claude AI models for message generation in your Spala flows. section: addons updated: 2026-07-08 --- # Anthropic Integrate Anthropic's Claude AI models for message generation in your Spala flows. Anthropic The Anthropic addon connects your Spala flows to Anthropic's Claude API. Use Claude models for conversational AI, content analysis, summarization, code generation, and other text-based tasks. Installation 1. Enable the Anthropic addon from the Addons panel 2. Enter your Anthropic API key in the addon configuration Configuration Available Steps Create Message Sends a message to a Claude model and receives a response. Example: Content Moderation // POST /api/moderate // Step 1: Create Message (Anthropic addon) // model: '' // system: 'You are a content moderator. Analyze the following text and respond with a JSON object: { "safe": boolean, "reason": string, "category": string }. Only respond with valid JSON.' // messages: [{ role: 'user', content: input.text }] // maxTokens: 200 // Output → vars.moderation // Step 2: Set Variable - Parse the response // vars.result = JSON.parse(vars.moderation.content[0].text) // Step 3: Condition - Check if content is safe // If vars.result.safe === false // Step 4: Database Query - Flag the content // INSERT INTO flagged_content (text, reason, category) VALUES (...) // Step 5: Response // { safe: vars.result.safe, reason: vars.result.reason } Example: Document Summarization // POST /api/summarize // Step 1: Database Query - Get the document // SELECT * FROM documents WHERE id = input.documentId // Step 2: Create Message (Anthropic addon) // model: '' // system: 'Summarize the following document in 2-3 paragraphs. Focus on the key points and main conclusions.' // messages: [{ role: 'user', content: vars.document.content }] // maxTokens: 1000 // Output → vars.summary // Step 3: Database Query - Save the summary // UPDATE documents SET summary = vars.summary.content[0].text WHERE id = input.documentId // Step 4: Response // { summary: vars.summary.content[0].text } Response Format The Create Message step returns Anthropic's standard response format: { id: "msg_...", type: "message", role: "assistant", content: [ { type: "text", text: "The model's response text..." } ], model: "", usage: { input_tokens: 125, output_tokens: 340 } } Access the response text with: vars.result.content[0].text Claude models excel at long-form content analysis, nuanced reasoning, and following complex instructions. They support context windows up to 200K tokens, making them suitable for processing large documents. Anthropic API calls are billed per token. Set the maxTokens parameter appropriately for your use case to control costs. Your Anthropic API key from console.anthropic.com. The Claude model to use. Choose a currently supported model from Anthropic. Array of message objects with 'role' and 'content' fields. System prompt that sets the behavior and context for the conversation. Maximum number of tokens in the response. Sampling temperature between 0 and 1 (default: 1). Addons Overview /addons Browse available addons Installing Addons /addons/installing Enable and configure addons in your project --- title: API-Based Integrations route: https://docs.spala.ai/addons/declarative-addons/ path: /addons/declarative-addons description: Use External API Call and project environment variables to connect REST APIs from Spala. section: addons updated: 2026-07-08 --- # API-Based Integrations Use External API Call and project environment variables to connect REST APIs from Spala. API-Based Integrations For services that expose an HTTP API, use the External API Call step from your function, endpoint, task, or trigger. This covers most custom integration needs without custom platform code. How It Works 1. Add the required API key in Settings > Environment. 2. Add an External API Call step to your function. 3. Configure the method, URL, headers, and request input. 4. Store the response in a variable. 5. Return the response, save data to a table, or continue the workflow. Keep secrets server-side Reference secrets from project environment variables. Do not paste secret API keys into frontend code. Good Fits - CRM updates - Notification APIs - Payment service calls not covered by the catalog - Enrichment APIs - Internal company APIs - Webhook delivery External API Steps /reference/steps/api Configure HTTP calls in functions Variables & Data /flows/variables Use environment variables and step outputs Addons /addons Use catalog integrations when available --- title: AWS S3 route: https://docs.spala.ai/addons/catalog/aws-s3/ path: /addons/catalog/aws-s3 description: Upload, download, and manage files in Amazon S3 buckets from your Spala flows. section: addons updated: 2026-07-08 --- # AWS S3 Upload, download, and manage files in Amazon S3 buckets from your Spala flows. AWS S3 The AWS S3 addon provides file storage operations using Amazon Simple Storage Service. Upload files, generate signed URLs for secure downloads, list bucket contents, and delete objects — all from your Spala flows. Installation 1. Enable the AWS S3 addon from the Addons panel 2. Enter your AWS credentials and bucket configuration Configuration Available Steps Upload File Uploads a file to S3. Get Signed URL Generates a pre-signed URL for temporary secure access to a private file. Delete File Deletes an object from S3. List Files Lists objects in an S3 bucket with an optional prefix filter. Example: File Upload Endpoint // POST /api/files/upload // Step 1: Set Variable - Generate a unique key // vars.key = 'uploads/' + vars.auth.userId + '/' + Date.now() + '-' + input.filename // Step 2: Upload File (S3 addon) // filePath: input.tempFilePath // key: vars.key // contentType: input.contentType // Step 3: Database Query - Save file record // INSERT INTO files (user_id, s3_key, filename, content_type, size) // VALUES (vars.auth.userId, vars.key, input.filename, input.contentType, input.fileSize) // RETURNING * // Step 4: Response // { file: vars.fileRecord } Example: Secure File Download // GET /api/files/:fileId/download // Step 1: Database Query - Get file record and verify ownership // SELECT * FROM files WHERE id = params.fileId AND user_id = vars.auth.userId // Step 2: Condition - File not found // If !vars.file → Respond with 404 // Step 3: Get Signed URL (S3 addon) // key: vars.file.s3_key // expiresIn: 300 // Step 4: Response // { downloadUrl: vars.signedUrl } Pre-signed URLs provide temporary, secure access to private S3 objects without making the bucket public. Set the expiration time based on your use case — short for downloads (5 minutes), longer for media playback. Use an IAM user with minimal S3 permissions. Grant access only to the specific bucket(s) your application needs, and avoid using root account credentials. AWS access key ID with S3 permissions. AWS secret access key. Default S3 bucket name. AWS region (e.g., 'us-east-1'). Local path to the file to upload. The S3 object key (path within the bucket, e.g., 'uploads/image.png'). MIME type of the file (e.g., 'image/png'). Auto-detected if not provided. Override the default bucket. The S3 object key. URL expiration time in seconds (default: 3600). Override the default bucket. The S3 object key to delete. Override the default bucket. Filter results to keys starting with this prefix (e.g., 'uploads/user-42/'). Maximum number of results to return (default: 1000). Override the default bucket. Addons Overview /addons Browse available addons Installing Addons /addons/installing Enable and configure addons in your project --- title: Custom Integrations route: https://docs.spala.ai/addons/creating-addons/ path: /addons/creating-addons description: Connect services that are not in the addon catalog using External API Call, webhooks, and project environment variables. section: addons updated: 2026-07-08 --- # Custom Integrations Connect services that are not in the addon catalog using External API Call, webhooks, and project environment variables. Custom Integrations Most integrations start with the addon catalog. If the service you need is not listed, use Spala's built-in API and webhook steps to connect it from your project. Recommended Options - External API Call — Call any HTTP API from a function, endpoint, task, or trigger - Webhooks — Receive or send events between Spala and another service - Project environment variables — Store API keys and secrets safely in Spala - AI Copilot — Describe the integration you want and let Spala create the tables, functions, and endpoints around it Use the dashboard first Public Spala docs focus on using integrations from the dashboard. For private reusable integrations or organization-specific catalog items, contact Spala support. When To Contact Spala Contact Spala support if you need a reusable organization-wide integration, a private catalog item, or help designing a complex workflow around a third-party service. Addons /addons Browse ready-to-use integrations External API Steps /reference/steps/api Call any HTTP API from a function Environment Variables /settings Store API keys and runtime values AI Copilot /features/ai-assistant Ask Spala to build the integration workflow --- title: Discord route: https://docs.spala.ai/addons/catalog/discord/ path: /addons/catalog/discord description: Send messages and notifications to Discord channels using webhooks from your Spala flows. section: addons updated: 2026-07-08 --- # Discord Send messages and notifications to Discord channels using webhooks from your Spala flows. Discord The Discord addon lets you send messages to Discord channels through webhooks. Use it to post notifications, alerts, and updates to your Discord server directly from your Spala flows. Installation 1. Enable the Discord addon from the Addons panel 2. Create a webhook in your Discord server (Server Settings > Integrations > Webhooks) 3. Enter the webhook URL in the addon configuration Configuration Integrations > Webhooks.' }, Available Steps Send Message Posts a message to the Discord channel associated with the webhook. Example: Simple Notification // Event trigger: "order.completed" // Step 1: Send Message (Discord addon) // content: '**New Order!** Order #' + event.payload.orderId + ' for Example: Rich Embed Notification // Error handler flow // Step 1: Send Message (Discord addon) // username: 'Alert Bot' // embeds: [{ // title: 'Error Alert', // description: vars.error.message, // color: 16711680, // fields: [ // { name: 'Flow', value: vars.flowName, inline: true }, // { name: 'Step', value: vars.stepName, inline: true }, // { name: 'Time', value: new Date().toISOString() } // ], // footer: { text: 'Spala Error Monitor' } // }] Discord embeds support titles, descriptions, colored sidebars, fields, images, thumbnails, and footers. The color field accepts a decimal color value (e.g., 16711680 for red, 65280 for green). Discord webhooks are channel-specific. To send messages to different channels, create separate webhooks and configure multiple environment variables, or pass the webhook URL as a step input. Discord webhook URLs should be kept secret. Anyone with the URL can post messages to your channel. Store the URL in environment variables and never expose it in client-side code. The full webhook URL from your Discord server. Found in Server Settings > Integrations > Webhooks. The text content of the message. Supports Discord markdown. Override the webhook display name for this message. Array of embed objects for rich message formatting. Error Alert Addons Overview /addons Browse available addons Installing Addons /addons/installing Enable and configure addons in your project + event.payload.total.toFixed(2) Example: Rich Embed Notification // Error handler flow // Step 1: Send Message (Discord addon) // username: 'Alert Bot' // embeds: [{ // title: 'Error Alert', // description: vars.error.message, // color: 16711680, // fields: [ // { name: 'Flow', value: vars.flowName, inline: true }, // { name: 'Step', value: vars.stepName, inline: true }, // { name: 'Time', value: new Date().toISOString() } // ], // footer: { text: 'Spala Error Monitor' } // }] Discord embeds support titles, descriptions, colored sidebars, fields, images, thumbnails, and footers. The color field accepts a decimal color value (e.g., 16711680 for red, 65280 for green). Discord webhooks are channel-specific. To send messages to different channels, create separate webhooks and configure multiple environment variables, or pass the webhook URL as a step input. Discord webhook URLs should be kept secret. Anyone with the URL can post messages to your channel. Store the URL in environment variables and never expose it in client-side code. The full webhook URL from your Discord server. Found in Server Settings > Integrations > Webhooks. The text content of the message. Supports Discord markdown. Override the webhook display name for this message. Array of embed objects for rich message formatting. Error Alert Addons Overview /addons Browse available addons Installing Addons /addons/installing Enable and configure addons in your project --- title: Firebase Authentication route: https://docs.spala.ai/addons/catalog/firebase-auth/ path: /addons/catalog/firebase-auth description: Verify Firebase ID tokens and manage users with the Firebase Auth addon for Spala. section: addons updated: 2026-07-08 --- # Firebase Authentication Verify Firebase ID tokens and manage users with the Firebase Auth addon for Spala. Firebase Authentication The Firebase Authentication addon lets you verify Firebase ID tokens in your Spala flows. Use it to authenticate users who sign in through Firebase on your frontend (Google, Apple, email/password, phone number) and access their user information in your backend flows. Installation 1. Enable the Firebase Auth addon from the Addons panel 2. Enter your Firebase project credentials in the addon configuration Configuration Project Settings.' }, Available Steps Verify ID Token Verifies a Firebase ID token and returns the decoded user information. Returns the decoded token payload: { uid: "abc123", email: "user@example.com", name: "Jane Smith", picture: "https://...", email_verified: true, auth_time: 1705000000 } Get User Retrieves a Firebase user record by UID. Example: Protected Endpoint with Firebase Auth // GET /api/profile (middleware or first step) // Step 1: Set Variable - Extract token from header // vars.token = headers.authorization?.replace('Bearer ', '') // Step 2: Condition - Check if token exists // If !vars.token → Respond with 401 // Step 3: Verify ID Token (Firebase Auth addon) // idToken: vars.token // Output → vars.firebaseUser // Step 4: Database Query - Get user profile // SELECT * FROM users WHERE firebase_uid = vars.firebaseUser.uid // Step 5: Response // { user: vars.profile } Example: Sync Firebase Users to Database // POST /api/auth/sync // Step 1: Verify ID Token (Firebase Auth addon) // idToken: input.idToken // Output → vars.firebaseUser // Step 2: Database Query - Upsert user // INSERT INTO users (firebase_uid, email, name, avatar_url) // VALUES (vars.firebaseUser.uid, vars.firebaseUser.email, vars.firebaseUser.name, vars.firebaseUser.picture) // ON CONFLICT (firebase_uid) DO UPDATE SET // email = EXCLUDED.email, name = EXCLUDED.name, avatar_url = EXCLUDED.avatar_url, // last_login = NOW() // RETURNING * // Step 3: Response // { user: vars.user } Firebase ID tokens are short-lived (1 hour). Your frontend should handle token refresh automatically using the Firebase SDK, and send the fresh token with each API request. Always verify the ID token on the server side. Never trust user information sent directly from the client without token verification. Your Firebase project ID from the Firebase Console > Project Settings. Your Firebase Web API key from the Firebase Console > Project Settings. The Firebase ID token to verify (typically sent in the Authorization header from the frontend). The Firebase user UID. Addons Overview /addons Browse available addons Installing Addons /addons/installing Enable and configure addons in your project --- title: GitHub route: https://docs.spala.ai/addons/catalog/github/ path: /addons/catalog/github description: Interact with GitHub repositories, issues, and pull requests from your Spala flows. section: addons updated: 2026-07-08 --- # GitHub Interact with GitHub repositories, issues, and pull requests from your Spala flows. GitHub The GitHub addon connects your Spala flows to the GitHub API. Create issues, manage pull requests, query repositories, and build automations around your development workflow. Installation 1. Enable the GitHub addon from the Addons panel 2. Create a personal access token or GitHub App token 3. Enter the token in the addon configuration Configuration Available Steps Create Issue Creates a new issue in a GitHub repository. List Issues Retrieves issues from a repository. Create Comment Adds a comment to an issue or pull request. Example: Auto-Create Issue from Bug Report // POST /api/bug-reports // Step 1: Create Issue (GitHub addon) // owner: 'my-org' // repo: 'my-app' // title: '[Bug] ' + input.title // body: '**Reported by:** ' + vars.auth.email + '\n\n' + input.description + '\n\n**Steps to reproduce:**\n' + input.steps // labels: ['bug', 'user-reported'] // Output → vars.issue // Step 2: Database Query - Link report to issue // INSERT INTO bug_reports (user_id, title, github_issue_number, github_issue_url) // VALUES (vars.auth.userId, input.title, vars.issue.number, vars.issue.html_url) // Step 3: Response // { issueUrl: vars.issue.html_url } Example: Deployment Tracker // Event trigger: "deployment.completed" // Step 1: Create Comment (GitHub addon) // owner: 'my-org' // repo: 'my-app' // issueNumber: event.payload.prNumber // body: '**Deployed to production** :rocket:\nVersion: ' + event.payload.version + '\nTime: ' + new Date().toISOString() For personal access tokens, use fine-grained tokens with the minimum required permissions. For issue management, you need "Issues" read/write access for the specific repository. GitHub personal access token or GitHub App installation token with the required scopes. Repository owner (user or organization). Repository name. Issue title. Issue body in Markdown format. Array of label names to apply. Array of GitHub usernames to assign. Repository owner. Repository name. 'open', 'closed', or 'all' (default: 'open'). Comma-separated list of label names to filter by. Repository owner. Repository name. The issue or pull request number. Comment body in Markdown. [Bug] Addons Overview /addons Browse available addons Installing Addons /addons/installing Enable and configure addons in your project --- title: HTML to PDF route: https://docs.spala.ai/addons/catalog/html-to-pdf/ path: /addons/catalog/html-to-pdf description: Generate PDF documents from HTML templates in your Spala flows. section: addons updated: 2026-07-08 --- # HTML to PDF Generate PDF documents from HTML templates in your Spala flows. HTML to PDF The HTML to PDF addon generates PDF documents from HTML content using a headless browser engine. Create invoices, reports, receipts, certificates, and any other document by writing HTML templates and converting them to PDF. Installation 1. Enable the HTML to PDF addon from the Addons panel 2. No setup beyond enabling the addon No API keys or external services are required — all rendering happens locally on the server. Available Steps Generate PDF Renders HTML content as a PDF document. Generate PDF from URL Renders a web page at the given URL as a PDF. Example: Invoice Generation // POST /api/invoices/:orderId/pdf // Step 1: Database Query - Get order with items // SELECT o.*, json_agg(oi.*) as items FROM orders o // JOIN order_items oi ON oi.order_id = o.id // WHERE o.id = params.orderId GROUP BY o.id // Step 2: Set Variable - Build HTML // vars.html = ` // // // //
Total: ${vars.order.total.toFixed(2)}

// // // ` // Step 3: Generate PDF (HTML to PDF addon) // html: vars.html // outputPath: storage + '/invoices/invoice-' + vars.order.id + '.pdf' // format: 'A4' // margin: { top: '20mm', bottom: '20mm', left: '15mm', right: '15mm' } // Step 4: Response // { pdfPath: vars.pdfPath } Example: Report with Header/Footer // Step 1: Generate PDF (HTML to PDF addon) // html: vars.reportHtml // outputPath: storage + '/reports/monthly-' + vars.month + '.pdf' // format: 'A4' // headerTemplate: '
Monthly Report -
' // footerTemplate: '
Page of
' // margin: { top: '30mm', bottom: '20mm' } The HTML template supports full CSS including Flexbox and Grid layouts. You can use inline images with base64 data URIs or reference external image URLs. PDF generation requires a headless browser and is resource-intensive. For high-volume document generation, run the operation in a background task to avoid blocking API responses. The HTML content to render. Can include inline CSS and images. File path where the PDF will be saved. Paper size: 'A4' (default), 'Letter', 'Legal', 'A3', 'A5', or 'Tabloid'. Set to true for landscape orientation (default: false). Margins object with top, right, bottom, left values (e.g., { top: '20mm', bottom: '20mm' }). HTML template for the page header. Use CSS classes: date, title, url, pageNumber, totalPages. HTML template for the page footer. The URL of the page to render. File path where the PDF will be saved. Paper size (default: A4). CSS selector to wait for before rendering (useful for pages with async content). Addons Overview /addons Browse available addons Installing Addons /addons/installing Enable and configure addons in your project --- title: HubSpot route: https://docs.spala.ai/addons/catalog/hubspot/ path: /addons/catalog/hubspot description: Manage contacts, deals, and CRM data through the HubSpot API from your Spala flows. section: addons updated: 2026-07-08 --- # HubSpot Manage contacts, deals, and CRM data through the HubSpot API from your Spala flows. HubSpot The HubSpot addon connects your Spala flows to the HubSpot CRM. Create and update contacts, manage deals, and sync customer data between your application and HubSpot. Installation 1. Enable the HubSpot addon from the Addons panel 2. Create a private app in HubSpot (Settings > Integrations > Private Apps) 3. Enter the access token in the addon configuration Configuration Integrations > Private Apps.' }, Available Steps Create Contact Creates a new contact in HubSpot. Update Contact Updates an existing HubSpot contact. Create Deal Creates a new deal in the HubSpot sales pipeline. Search Contacts Searches for contacts matching specified criteria. Example: Sync New Users to HubSpot // Event trigger: "user.registered" // Step 1: Create Contact (HubSpot addon) // email: event.payload.email // firstName: event.payload.firstName // lastName: event.payload.lastName // properties: { // company: event.payload.company, // signup_source: 'web_app', // plan: 'free' // } // Output → vars.hubspotContact // Step 2: Database Query - Store HubSpot ID // UPDATE users SET hubspot_contact_id = vars.hubspotContact.id // WHERE id = event.payload.userId Example: Create Deal on Purchase // Database trigger on insert for the "orders" table // Step 1: Database Query - Get customer HubSpot ID // SELECT hubspot_contact_id FROM users WHERE id = trigger.newRow.user_id // Step 2: Create Deal (HubSpot addon) // dealName: 'Order #' + trigger.newRow.id // amount: trigger.newRow.total // stage: 'closedwon' // properties: { order_id: trigger.newRow.id.toString() } HubSpot private apps require specific scopes for different operations. Grant crm.objects.contacts.write for contact operations and crm.objects.deals.write for deal operations. Private app access token from HubSpot. Found in Settings > Integrations > Private Apps. Contact email address. Contact first name. Contact last name. Additional contact properties as key-value pairs. The HubSpot contact ID. Properties to update as key-value pairs. Name of the deal. Deal amount. Pipeline stage (e.g., "qualifiedtobuy", "closedwon"). Additional deal properties. Search query string. Array of filter objects with property, operator, and value. Maximum results to return (default: 10). Addons Overview /addons Browse available addons Installing Addons /addons/installing Enable and configure addons in your project --- title: Image Processing route: https://docs.spala.ai/addons/catalog/image-processing/ path: /addons/catalog/image-processing description: Resize, crop, convert, and transform images using Sharp from your Spala flows. section: addons updated: 2026-07-08 --- # Image Processing Resize, crop, convert, and transform images using Sharp from your Spala flows. Image Processing The Image Processing addon uses the Sharp library to resize, crop, convert, and transform images in your Spala flows. It runs image operations on the server with high performance, supporting JPEG, PNG, WebP, AVIF, GIF, and TIFF formats. Installation 1. Enable the Image Processing addon from the Addons panel 2. No setup beyond enabling the addon No API keys or external services are required — all processing happens locally on the server. Available Steps Resize Image Resizes an image to the specified dimensions. Convert Format Converts an image to a different format. Crop Image Extracts a region from an image. Get Image Info Returns metadata about an image (dimensions, format, file size, color space). Returns: { width: 1920, height: 1080, format: "jpeg", size: 245760, channels: 3, space: "srgb" } Example: Image Upload with Thumbnails // POST /api/images/upload // Step 1: Save File (Local Storage addon) // path: 'uploads/originals/' + input.filename // content: input.fileData, encoding: 'base64' // Step 2: Resize Image (Image Processing addon) // inputPath: storage + '/uploads/originals/' + input.filename // outputPath: storage + '/uploads/thumbnails/' + input.filename // width: 200 // height: 200 // fit: 'cover' // Step 3: Convert Format (Image Processing addon) // inputPath: storage + '/uploads/originals/' + input.filename // outputPath: storage + '/uploads/webp/' + input.filename.replace(/\.[^.]+$/, '.webp') // format: 'webp' // quality: 85 // Step 4: Database Query - Save image record // INSERT INTO images (original_path, thumbnail_path, webp_path, ...) // Step 5: Response // { image: vars.imageRecord } Example: Avatar Processing // POST /api/users/avatar // Step 1: Save uploaded file temporarily // Step 2: Get Image Info (Image Processing addon) // inputPath: vars.tempPath // Output → vars.info // Step 3: Condition - Validate dimensions // If vars.info.width < 100 || vars.info.height < 100 // Respond with 400: "Image must be at least 100x100 pixels" // Step 4: Resize Image (Image Processing addon) // inputPath: vars.tempPath // outputPath: storage + '/avatars/' + vars.auth.userId + '.webp' // width: 256, height: 256, fit: 'cover' // Step 5: Convert Format // format: 'webp', quality: 90 Sharp processes images in a streaming pipeline, which is memory-efficient even for large images. It uses the libvips library under the hood, which is significantly faster than ImageMagick or GraphicsMagick. Image processing is CPU-intensive. For high-volume image processing, consider running these operations in background tasks to avoid blocking your API endpoints. Path to the source image file. Path where the resized image will be saved. Target width in pixels. Omit to auto-calculate from height. Target height in pixels. Omit to auto-calculate from width. 'cover' (crop to fill), 'contain' (fit within), 'fill' (stretch), 'inside', or 'outside'. Path to the source image file. Path for the converted image. 'jpeg', 'png', 'webp', 'avif', 'gif', or 'tiff'. Output quality for lossy formats, 1-100 (default: 80). Path to the source image. Path for the cropped image. Left offset in pixels. Top offset in pixels. Width of the crop region. Height of the crop region. Path to the image file. Addons Overview /addons Browse available addons Installing Addons /addons/installing Enable and configure addons in your project --- title: Installing Addons route: https://docs.spala.ai/addons/installing/ path: /addons/installing description: How to enable and configure addons in your Spala project. section: addons updated: 2026-07-08 --- # Installing Addons How to enable and configure addons in your Spala project. Installing Addons Addons are bundled with Spala but disabled by default. To use an addon, you need to enable it in your project and configure any required API keys or credentials. Enabling an Addon Open your project in Spala Click the Addons icon in the left sidebar Browse or search the addon catalog to find the addon you need Click on the addon to view its details, available steps, and required configuration Click Enable to activate the addon for your project If the addon requires API keys or other credentials, enter them in the configuration panel Click Save to complete the installation Once enabled, the addon's steps appear in the flow editor's step palette. You can drag them into any flow just like built-in steps. Configuring API Keys Most addons that connect to external services require API keys or other credentials. These are stored as project environment variables in Spala and are never exposed to the frontend. To configure an addon's credentials: 1. Open the addon's settings from the Addons panel 2. Enter the required values (API keys, secrets, webhook URLs, etc.) 3. Click Save The configuration panel shows which environment variables each addon needs, along with links to the external service's documentation for obtaining API keys. # Example environment variables for common addons STRIPE_SECRET_KEY=sk_live_... OPENAI_API_KEY=sk-... TWILIO_ACCOUNT_SID=AC... TWILIO_AUTH_TOKEN=... SENDGRID_API_KEY=SG... Never commit API keys to version control or share them in client-side code. Store secrets in Spala project environment variables or addon settings. Verifying Installation After enabling an addon, verify it is working: 1. Open the flow editor for any endpoint or task 2. Open the step palette and search for the addon's step types 3. Drag a step into the flow and configure it 4. Use the Playground to test the endpoint If the addon's steps do not appear in the palette, make sure you saved the addon configuration and refreshed the page. Disabling an Addon To disable an addon you no longer need: 1. Open the Addons panel 2. Find the enabled addon 3. Click Disable Disabling an addon removes its steps from the palette. Any flows that use the addon's steps will show a warning, and those steps will fail at runtime. Remove or replace the addon steps from your flows before disabling the addon to avoid errors. Disabling an addon does not delete its configuration. If you re-enable the addon later, your API keys and settings are preserved. Addons Overview /addons Browse available addons External API Steps /reference/steps/api Call services that are not in the addon catalog --- title: Integration Configuration route: https://docs.spala.ai/addons/addon-manifest/ path: /addons/addon-manifest description: Configure addon credentials and integration settings from the Spala dashboard. section: addons updated: 2026-07-08 --- # Integration Configuration Configure addon credentials and integration settings from the Spala dashboard. Integration Configuration Catalog addons show their required configuration in the Spala dashboard. When an addon needs an API key, webhook secret, account ID, or region, Spala prompts you for the value during setup. Where To Configure Values - Addon settings — Values specific to the enabled addon - Settings > Environment — Project-level secrets and runtime values - Endpoint/function inputs — Values that should vary per request Protect secrets Store API keys and webhook secrets in Spala project settings. Do not expose them in browser code or public repositories. Custom Service Calls If the integration is not in the catalog, use the External API Call step and reference credentials from project environment variables. Installing Addons /addons/installing Enable and configure catalog addons External API Steps /reference/steps/api Call services directly from functions Settings /settings Manage environment variables and project controls --- title: Jira route: https://docs.spala.ai/addons/catalog/jira/ path: /addons/catalog/jira description: Create and manage Jira issues and projects from your Spala flows. section: addons updated: 2026-07-08 --- # Jira Create and manage Jira issues and projects from your Spala flows. Jira The Jira addon integrates Atlassian Jira into your Spala flows. Create issues, update statuses, search with JQL, and automate your project management workflows. Installation 1. Enable the Jira addon from the Addons panel 2. Create an API token at id.atlassian.com/manage-profile/security/api-tokens 3. Enter your Jira credentials in the addon configuration Configuration Available Steps Create Issue Creates a new Jira issue. Update Issue Updates fields on an existing Jira issue. Search Issues (JQL) Searches for issues using Jira Query Language. Transition Issue Changes the status of a Jira issue (e.g., move from "To Do" to "In Progress"). Example: Auto-Create Bug from Error // Error handler flow // Step 1: Create Issue (Jira addon) // projectKey: 'APP' // issueType: 'Bug' // summary: '[Auto] Error in ' + vars.flowName + ': ' + vars.error.message // description: 'Automatically created from error monitoring.\n\nFlow: ' + vars.flowName + '\nStep: ' + vars.stepName + '\nTime: ' + new Date().toISOString() + '\n\nStack trace:\n' + vars.error.stack // priority: 'High' // Output → vars.jiraIssue // Step 2: Log // 'Created Jira issue: ' + vars.jiraIssue.key Example: Sprint Report // GET /api/sprint-report // Step 1: Search Issues (Jira addon) // jql: 'project = APP AND sprint in openSprints() AND status = Done' // fields: ['summary', 'assignee', 'status', 'story_points'] // Output → vars.completedIssues // Step 2: Response // { completed: vars.completedIssues.total, issues: vars.completedIssues.issues } Jira API authentication uses Basic Auth with your email and API token. The addon handles the encoding automatically. Make sure the account associated with the token has the necessary project permissions. Your Jira instance URL (e.g., "https://yourteam.atlassian.net"). Your Atlassian account email address. API token from your Atlassian account settings. The project key (e.g., 'PROJ'). Issue type: 'Bug', 'Task', 'Story', 'Epic', etc. Issue title/summary. Issue description (supports Atlassian Document Format or plain text). Priority: 'Highest', 'High', 'Medium', 'Low', 'Lowest'. Atlassian account ID of the assignee. The issue key (e.g., 'PROJ-123'). Object of fields to update. JQL query string (e.g., "project = PROJ AND status = Open"). Maximum results to return (default: 50). Array of field names to include in results. The issue key. The transition ID (get available transitions from the Jira API). Automatically created from error monitoring.\n\nFlow: Addons Overview /addons Browse available addons Installing Addons /addons/installing Enable and configure addons in your project --- title: Local Storage route: https://docs.spala.ai/addons/catalog/local-storage/ path: /addons/catalog/local-storage description: Read and write files on the server's local file system from your Spala flows. section: addons updated: 2026-07-08 --- # Local Storage Read and write files on the server's local file system from your Spala flows. Local Storage The Local Storage addon provides managed file operations for reading, writing, and organizing project files. Use it for uploads, temporary file processing, export generation, and workflows that need file storage. Installation 1. Enable the Local Storage addon from the Addons panel 2. Optionally configure the base storage directory Configuration Available Steps Save File Writes content to a file on the local file system. Read File Reads the contents of a file. Delete File Deletes a file from the file system. List Files Lists files in a directory. File Exists Checks whether a file exists at the given path. Example: File Upload Endpoint // POST /api/files/upload // Step 1: Set Variable - Generate unique filename // vars.filename = Date.now() + '-' + input.originalName // Step 2: Save File (Local Storage addon) // path: 'uploads/' + vars.auth.userId + '/' + vars.filename // content: input.fileData // encoding: 'base64' // Step 3: Database Query - Save file record // INSERT INTO files (user_id, filename, path, size, mime_type) // VALUES (vars.auth.userId, input.originalName, 'uploads/' + vars.auth.userId + '/' + vars.filename, input.fileSize, input.mimeType) // RETURNING * // Step 4: Response // { file: vars.fileRecord } Example: Export to CSV // GET /api/reports/export // Step 1: Database Query - Get report data // SELECT * FROM orders WHERE created_at >= input.startDate // Step 2: Set Variable - Build CSV content // vars.csv = 'id,customer,total,status,date\n' + // vars.orders.map(o => [o.id, o.customer_name, o.total, o.status, o.created_at].join(',')).join('\n') // Step 3: Save File (Local Storage addon) // path: 'exports/orders-' + Date.now() + '.csv' // content: vars.csv // encoding: 'utf8' // Output → vars.filePath // Step 4: Response // { downloadPath: vars.filePath } All file paths are sandboxed to the configured storage directory. Attempting to access files outside this directory (e.g., using "../" path traversal) will be blocked for security. For production deployments with multiple server instances, consider using the AWS S3 addon instead of local storage. Local storage is tied to a single server and files will not be available across instances. Base directory for file operations (default: './storage' relative to the project root). All file paths are resolved relative to this directory. File path relative to the storage directory (e.g., 'uploads/report.pdf'). File content — a string, Buffer, or base64-encoded data. 'utf8' (default), 'base64', 'binary', or 'buffer'. File path relative to the storage directory. 'utf8' (default), 'base64', 'binary', or 'buffer'. File path relative to the storage directory. Directory path relative to the storage directory (default: root '/'). Whether to list files in subdirectories (default: false). File path to check. Addons Overview /addons Browse available addons Installing Addons /addons/installing Enable and configure addons in your project --- title: Notion route: https://docs.spala.ai/addons/catalog/notion/ path: /addons/catalog/notion description: Create pages, query databases, and manage content in Notion from your Spala flows. section: addons updated: 2026-07-08 --- # Notion Create pages, query databases, and manage content in Notion from your Spala flows. Notion The Notion addon connects your Spala flows to Notion's API. Query databases, create pages, update properties, and sync data between your application and Notion workspaces. Installation 1. Enable the Notion addon from the Addons panel 2. Create an integration at notion.so/my-integrations 3. Share the relevant Notion databases/pages with your integration 4. Enter the integration token in the addon configuration Configuration Available Steps Query Database Queries a Notion database with optional filters and sorting. Create Page Creates a new page in a Notion database. Update Page Updates properties on an existing Notion page. Example: Log Errors to Notion // Error handler in a flow // Step 1: Create Page (Notion addon) // databaseId: env.NOTION_ERROR_DB_ID // properties: { // "Error": { title: [{ text: { content: vars.error.message } }] }, // "Flow": { rich_text: [{ text: { content: vars.flowName } }] }, // "Status": { select: { name: "Open" } }, // "Severity": { select: { name: "High" } }, // "Time": { date: { start: new Date().toISOString() } } // } Example: Sync Tasks from Notion // Scheduled task — runs every 15 minutes // Step 1: Query Database (Notion addon) // databaseId: env.NOTION_TASKS_DB_ID // filter: { property: "Status", select: { equals: "Ready" } } // Output → vars.tasks // Step 2: Loop - For each task // Step 3: Database Query - Create local task // INSERT INTO tasks (notion_id, title, priority, due_date) // VALUES (task.id, task.properties.Name.title[0].plain_text, // task.properties.Priority.select.name, // task.properties.Due.date?.start) // ON CONFLICT (notion_id) DO UPDATE SET ... Notion databases must be explicitly shared with your integration before they can be accessed. In Notion, open the database page, click the three-dot menu, and select "Connect to" to add your integration. Notion's property format is verbose. Each property type (title, rich_text, select, date, etc.) has its own structure. Refer to the Notion API documentation for the exact format of each property type. Internal integration token from notion.so/my-integrations. The Notion database ID. Filter object following the Notion filter syntax. Array of sort objects (e.g., [{ property: "Created", direction: "descending" }]). Number of results per page (default: 100, max: 100). The parent database ID. Page properties matching the database schema. Array of block objects for the page input. The Notion page ID. Properties to update. Addons Overview /addons Browse available addons Installing Addons /addons/installing Enable and configure addons in your project --- title: OpenAI route: https://docs.spala.ai/addons/catalog/openai/ path: /addons/catalog/openai description: Integrate OpenAI's GPT models, embeddings, and image generation into your Spala flows. section: addons updated: 2026-07-08 --- # OpenAI Integrate OpenAI's GPT models, embeddings, and image generation into your Spala flows. OpenAI The OpenAI addon connects your Spala flows to OpenAI's API for chat completions, text embeddings, and image generation. Build AI-powered features like chatbots, content generation, semantic search, and automated analysis. Installation 1. Enable the OpenAI addon from the Addons panel 2. Enter your OpenAI API key in the addon configuration Configuration Available Steps Chat Completion Generates a chat response from an OpenAI model. // Example messages input: [ { role: 'system', content: 'You are a helpful customer support agent.' }, { role: 'user', content: input.userMessage } ] Create Embedding Generates vector embeddings for text, useful for semantic search and similarity matching. Generate Image Creates images from text descriptions using an OpenAI image model. Example: AI Chatbot Endpoint // POST /api/chat // Step 1: Database Query - Get conversation history // SELECT * FROM messages WHERE conversation_id = input.conversationId // ORDER BY created_at ASC LIMIT 20 // Step 2: Chat Completion (OpenAI addon) // model: '' // messages: [ // { role: 'system', content: 'You are a helpful assistant for our e-commerce store.' }, // ...vars.history.map(m => ({ role: m.role, content: m.content })), // { role: 'user', content: input.message } // ] // Output → vars.aiResponse // Step 3: Database Query - Save the messages // INSERT INTO messages (conversation_id, role, content) // VALUES (input.conversationId, 'user', input.message), // (input.conversationId, 'assistant', vars.aiResponse.choices[0].message.content) // Step 4: Response // { reply: vars.aiResponse.choices[0].message.content } Example: Semantic Search // POST /api/search // Step 1: Create Embedding (OpenAI addon) // model: 'text-embedding-3-small' // input: input.query // Output → vars.embedding // Step 2: Database Query - Find similar documents // SELECT *, (embedding <=> $1) AS distance // FROM documents ORDER BY distance LIMIT 10 // Params: [vars.embedding.data[0].embedding] // Step 3: Response // { results: vars.documents } OpenAI API calls are billed per token. Monitor your usage in the OpenAI dashboard and set billing limits to avoid unexpected charges. Your OpenAI API key from platform.openai.com/api-keys. The OpenAI model to use. Choose a currently supported model from OpenAI. Array of message objects with 'role' and 'content' fields. Sampling temperature between 0 and 2 (default: 1). Lower values are more deterministic. Maximum number of tokens to generate. The embedding model (e.g., 'text-embedding-3-small'). The text string to embed, or an array of strings for batch embedding. A text description of the image to generate. The OpenAI image model to use. Image size: '1024x1024', '1792x1024', or '1024x1792'. 'standard' or 'hd' (default: 'standard'). Addons Overview /addons Browse available addons Installing Addons /addons/installing Enable and configure addons in your project --- title: QR Code route: https://docs.spala.ai/addons/catalog/qr-code/ path: /addons/catalog/qr-code description: Generate QR codes as images or data URIs from your Spala flows. section: addons updated: 2026-07-08 --- # QR Code Generate QR codes as images or data URIs from your Spala flows. QR Code The QR Code addon generates QR code images from text, URLs, or any string data. Use it for generating shareable links, event tickets, product labels, two-factor authentication setup, and payment links. Installation 1. Enable the QR Code addon from the Addons panel No API keys are required. QR codes are generated through the addon; do not send sensitive secrets in QR payloads unless you have confirmed the data handling requirements for your project. Available Steps Generate QR Code Creates a QR code image from the provided data. Returns an object with the QR code image data: { imageUrl: "https://api.qrserver.com/v1/create-qr-code/?data=...", dataUri: "data:image/png;base64,iVBORw0KGgo...", data: "https://myapp.com/ticket/abc123" } Example: Event Ticket QR Code // POST /api/tickets/generate // Step 1: Database Query - Create ticket record // INSERT INTO tickets (event_id, user_id, code) // VALUES (input.eventId, vars.auth.userId, gen_random_uuid()) // RETURNING * // Step 2: Generate QR Code (QR Code addon) // data: 'https://myapp.com/tickets/verify/' + vars.ticket.code // size: 300 // Output → vars.qrCode // Step 3: Database Query - Store QR code URL // UPDATE tickets SET qr_code_url = vars.qrCode.imageUrl WHERE id = vars.ticket.id // Step 4: Response // { ticket: vars.ticket, qrCode: vars.qrCode.imageUrl } Example: Two-Factor Authentication Setup // POST /api/auth/2fa/setup // Step 1: Set Variable - Generate TOTP secret // vars.secret = generateTOTPSecret() // Step 2: Set Variable - Build otpauth URI // vars.otpauthUri = 'otpauth://totp/MyApp:' + vars.auth.email // + '?secret=' + vars.secret + '&issuer=MyApp' // Step 3: Generate QR Code (QR Code addon) // data: vars.otpauthUri // size: 250 // Output → vars.qrCode // Step 4: Database Query - Store secret (encrypted) // UPDATE users SET totp_secret = vars.secret WHERE id = vars.auth.userId // Step 5: Response // { qrCodeDataUri: vars.qrCode.dataUri, secret: vars.secret } Example: Product Label // GET /api/products/:id/qr // Step 1: Database Query - Get product // SELECT * FROM products WHERE id = params.id // Step 2: Generate QR Code (QR Code addon) // data: 'https://mystore.com/products/' + vars.product.slug // size: 400 // darkColor: '1a1a2e' // lightColor: 'ffffff' // Output → vars.qrCode // Step 3: Response // { productName: vars.product.name, qrCodeUrl: vars.qrCode.imageUrl } QR codes can encode up to about 4,000 alphanumeric characters. For longer data, consider encoding a short URL that redirects to the full content. The dataUri format embeds the entire image as a base64 string, which is useful for embedding in HTML or emails but increases the response payload size. Use imageUrl when you only need a URL reference. The text or URL to encode in the QR code. Image size in pixels (width and height). Default: 200. 'png' (default) or 'svg'. Quiet zone margin in modules (default: 4). Color of the dark modules as hex (default: '000000'). Color of the light modules as hex (default: 'ffffff'). Addons Overview /addons Browse available addons Installing Addons /addons/installing Enable and configure addons in your project --- title: Redis Cloud route: https://docs.spala.ai/addons/catalog/redis-cloud/ path: /addons/catalog/redis-cloud description: Use Redis for caching, session storage, and pub/sub messaging from your Spala flows. section: addons updated: 2026-07-08 --- # Redis Cloud Use Redis for caching, session storage, and pub/sub messaging from your Spala flows. Redis Cloud The Redis Cloud addon connects your Spala flows to a Redis instance. Use it for caching frequently accessed data, storing session information, implementing rate limiting, and building real-time features with pub/sub messaging. Installation 1. Enable the Redis Cloud addon from the Addons panel 2. Enter your Redis connection details in the addon configuration Configuration Available Steps Redis Get Retrieves a value by key. Returns the stored value, or null if the key does not exist. JSON values are automatically parsed. Redis Set Stores a value with an optional expiration time. Redis Delete Deletes one or more keys. Redis Increment Atomically increments a numeric value. Example: API Response Caching // GET /api/products/featured // Step 1: Redis Get // key: 'cache:featured_products' // Output → vars.cached // Step 2: Condition - Cache hit // If vars.cached !== null // Step 3: Response → vars.cached // Step 4: Database Query - Fetch from database // SELECT * FROM products WHERE featured = true ORDER BY created_at DESC LIMIT 20 // Step 5: Redis Set - Cache the result // key: 'cache:featured_products' // value: vars.products // ttl: 300 (5 minutes) // Step 6: Response → { products: vars.products } Example: Rate Limiting // Middleware flow for rate-limited endpoints // Step 1: Set Variable - Build rate limit key // vars.rateLimitKey = 'ratelimit:' + vars.auth.userId + ':' + vars.path // Step 2: Redis Increment // key: vars.rateLimitKey // Output → vars.count // Step 3: Condition - First request in window // If vars.count === 1 // Step 4: Redis Set - Set expiry on first request // key: vars.rateLimitKey, value: 1, ttl: 60 // Step 5: Condition - Over limit // If vars.count > 100 // Step 6: Response with 429 Too Many Requests Example: Session Storage // POST /api/auth/login // ... authentication logic ... // Step 1: Set Variable - Generate session token // vars.sessionToken = crypto.randomUUID() // Step 2: Redis Set - Store session // key: 'session:' + vars.sessionToken // value: { userId: vars.user.id, email: vars.user.email, role: vars.user.role } // ttl: 86400 (24 hours) // Step 3: Response // { token: vars.sessionToken } Redis is ideal for data that needs fast access and can tolerate loss on restart (unless persistence is configured). For permanent data storage, use your PostgreSQL database. Set TTL values on cache keys to prevent unbounded memory growth. Keys without a TTL remain in Redis indefinitely and can eventually exhaust available memory. Redis connection URL (e.g., "redis://username:password@host:port"). The Redis key to retrieve. The Redis key. The value to store. Objects are automatically serialized to JSON. Time to live in seconds. The key is automatically deleted after this time. The key or array of keys to delete. The key to increment. Amount to increment by (default: 1). Addons Overview /addons Browse available addons Installing Addons /addons/installing Enable and configure addons in your project --- title: SendGrid route: https://docs.spala.ai/addons/catalog/sendgrid/ path: /addons/catalog/sendgrid description: Send transactional and marketing emails through SendGrid from your Spala flows. section: addons updated: 2026-07-08 --- # SendGrid Send transactional and marketing emails through SendGrid from your Spala flows. SendGrid The SendGrid addon integrates SendGrid's email delivery service into your Spala flows. Send transactional emails, use dynamic templates, and handle email notifications for user signups, order confirmations, password resets, and more. Installation 1. Enable the SendGrid addon from the Addons panel 2. Enter your SendGrid API key in the addon configuration Configuration API Keys in the SendGrid dashboard.' }, Available Steps Send Email Sends an email to one or more recipients. Send Template Email Sends an email using a SendGrid dynamic template. Example: Welcome Email // Event trigger: "user.registered" // Step 1: Send Email (SendGrid addon) // to: event.payload.email // subject: 'Welcome to Our Platform!' // html: '

Welcome, ' + event.payload.name + '!

We are glad you joined us.

' Example: Order Confirmation with Template // Database trigger on insert for the "orders" table // Step 1: Database Query - Get order details with items // SELECT o.*, json_agg(oi.*) as items FROM orders o // JOIN order_items oi ON oi.order_id = o.id WHERE o.id = trigger.newRow.id // Step 2: Send Template Email (SendGrid addon) // to: vars.order.customer_email // templateId: 'd-abc123def456' // dynamicData: { // customerName: vars.order.customer_name, // orderId: vars.order.id, // total: vars.order.total, // items: vars.order.items // } Dynamic templates are created in the SendGrid dashboard. They support Handlebars syntax for variable substitution, conditionals, and iteration, giving you full control over email layout. The sender email address must be verified in SendGrid. Unverified sender addresses will cause emails to fail. Verify your domain or individual sender in the SendGrid dashboard under Settings > Sender Authentication. Your SendGrid API key from Settings > API Keys in the SendGrid dashboard. The verified sender email address (e.g., noreply@yourdomain.com). The sender display name (e.g., "My App"). Recipient email address or array of addresses. Email subject line. HTML email input. Plain text email body (fallback for clients that do not render HTML). Recipient email address or array of addresses. The SendGrid dynamic template ID (starts with d-). Object of key-value pairs to populate template variables. Addons Overview /addons Browse available addons Installing Addons /addons/installing Enable and configure addons in your project --- title: Shopify route: https://docs.spala.ai/addons/catalog/shopify/ path: /addons/catalog/shopify description: Manage products, orders, and customers in your Shopify store from Spala flows. section: addons updated: 2026-07-08 --- # Shopify Manage products, orders, and customers in your Shopify store from Spala flows. Shopify The Shopify addon connects your Spala backend to a Shopify store. Query products, manage orders, update inventory, and sync customer data through the Shopify Admin API. Installation 1. Enable the Shopify addon from the Addons panel 2. Create a custom app in your Shopify admin (Settings > Apps and sales channels > Develop apps) 3. Enter the store credentials in the addon configuration Configuration Available Steps Get Products Retrieves products from your Shopify store. Get Order Retrieves a single order by ID. Update Inventory Updates the inventory level for a product variant at a location. Create Product Creates a new product in your Shopify store. Example: Sync Products to Local Database // Scheduled task — runs every hour // Step 1: Get Products (Shopify addon) // limit: 250 // status: 'active' // Output → vars.products // Step 2: Loop - For each product // Step 3: Database Query - Upsert product // INSERT INTO products (shopify_id, title, price, inventory, updated_at) // VALUES (product.id, product.title, product.variants[0].price, // product.variants[0].inventory_quantity, NOW()) // ON CONFLICT (shopify_id) DO UPDATE SET // title = EXCLUDED.title, price = EXCLUDED.price, // inventory = EXCLUDED.inventory, updated_at = NOW() Example: Low Inventory Alert // Scheduled task — runs daily // Step 1: Get Products (Shopify addon) // limit: 250 // Output → vars.products // Step 2: Set Variable - Filter low stock // vars.lowStock = vars.products.filter(p => // p.variants.some(v => v.inventory_quantity < 10) // ) // Step 3: Condition - If any low stock items // If vars.lowStock.length > 0 // Step 4: Send Email or Slack notification // "Low inventory alert: " + vars.lowStock.length + " products below threshold" The Shopify Admin API has rate limits of 2 requests per second for regular apps. The addon handles rate limiting automatically with request queuing, but be mindful of this when processing large catalogs. Your Shopify store domain (e.g., "mystore.myshopify.com"). Admin API access token from your custom Shopify app. Number of products to return (default: 50, max: 250). Filter products by collection. 'active', 'draft', or 'archived'. The Shopify order ID. The inventory item ID. The location ID. Quantity adjustment (positive to add, negative to remove). Product title. Product description in HTML. Product vendor name. Product type for categorization. Array of variant objects with price, sku, and inventory details. Addons Overview /addons Browse available addons Installing Addons /addons/installing Enable and configure addons in your project --- title: Slack API route: https://docs.spala.ai/addons/catalog/slack-api/ path: /addons/catalog/slack-api description: Send messages, manage channels, and integrate with Slack workspaces from your Spala flows. section: addons updated: 2026-07-08 --- # Slack API Send messages, manage channels, and integrate with Slack workspaces from your Spala flows. Slack API The Slack API addon connects your Spala flows to a Slack workspace. Send messages to channels, post notifications, and build automated workflows that keep your team informed about important events. Installation 1. Enable the Slack API addon from the Addons panel 2. Create a Slack App at api.slack.com/apps and install it to your workspace 3. Enter the Bot Token in the addon configuration Configuration Available Steps Send Message Posts a message to a Slack channel. Send Direct Message Sends a direct message to a Slack user. Example: Deployment Notification // Scheduled task or event trigger // Step 1: Send Message (Slack addon) // channel: '#deployments' // text: ':rocket: *Deployment Complete*\nVersion ' + vars.version + ' has been deployed to production.' Example: Error Alert with Block Kit // Error handler in a critical flow // Step 1: Send Message (Slack addon) // channel: '#alerts' // text: 'Error in payment processing' // blocks: [ // { // type: 'section', // text: { type: 'mrkdwn', text: ':warning: *Payment Processing Error*' } // }, // { // type: 'section', // fields: [ // { type: 'mrkdwn', text: '*Order ID:*\n' + vars.orderId }, // { type: 'mrkdwn', text: '*Error:*\n' + vars.error.message }, // { type: 'mrkdwn', text: '*Time:*\n' + new Date().toISOString() } // ] // } // ] Your Slack App needs the chat:write scope to post messages. Add additional scopes like channels:read and users:read if your flows need to look up channel or user information. Use channel IDs instead of channel names when possible. Channel names can change, but IDs are permanent. Find a channel's ID in Slack by right-clicking the channel name and selecting "View channel details". Slack Bot User OAuth Token (starts with xoxb-). Found in your Slack App settings under OAuth & Permissions. Channel ID or name (e.g., "#general" or "C0123456789"). The message text. Supports Slack markdown formatting. Block Kit layout blocks for rich message formatting (array of block objects). The Slack user ID (starts with U). The message text. Addons Overview /addons Browse available addons Installing Addons /addons/installing Enable and configure addons in your project --- title: Stripe route: https://docs.spala.ai/addons/catalog/stripe/ path: /addons/catalog/stripe description: Process payments, manage customers, and handle subscriptions with the Stripe addon for Spala. section: addons updated: 2026-07-08 --- # Stripe Process payments, manage customers, and handle subscriptions with the Stripe addon for Spala. Stripe The Stripe addon integrates Stripe's payment processing API into your Spala flows. Create payment intents, manage customers, set up subscriptions, and handle refunds using drag-and-drop steps. Installation 1. Enable the Stripe addon from the Addons panel 2. Enter your Stripe Secret Key in the addon configuration Configuration API Keys.' }, Use a test mode key (sk_test_...) during development. Switch to a live key (sk_live_...) when you are ready to process real payments. Available Steps Create Payment Intent Creates a payment intent to handle a one-time payment. Create Customer Creates a new customer in Stripe. Create Subscription Subscribes a customer to a recurring price. Create Refund Refunds a previously created charge. Example: Payment Endpoint // POST /api/payments/charge // Step 1: Create Customer (Stripe addon) // email: input.email // name: input.name // Output → vars.customer // Step 2: Create Payment Intent (Stripe addon) // amount: input.amount // currency: 'usd' // customerId: vars.customer.id // description: 'Order #' + input.orderId // Output → vars.paymentIntent // Step 3: Database Query // INSERT INTO payments (order_id, stripe_payment_intent_id, amount, status) // VALUES (input.orderId, vars.paymentIntent.id, input.amount, vars.paymentIntent.status) // Step 4: Response // { success: true, paymentIntentId: vars.paymentIntent.id } Always validate payment amounts on the server side. Never trust amounts sent from the client, as they can be tampered with. Your Stripe secret key (starts with sk_live_ or sk_test_). Found in the Stripe Dashboard under Developers > API Keys. Your Stripe webhook signing secret (starts with whsec_). Required for the Verify Webhook Signature step. Found in the Stripe Dashboard under Developers > Webhooks. Amount in the smallest currency unit (e.g., cents). For $10.00, use 1000. Three-letter ISO currency code (e.g., 'usd', 'eur'). A Stripe customer ID to associate with the payment. An optional description for the payment. Customer email address. Customer full name. Key-value pairs of additional customer data. The Stripe customer ID. The Stripe price ID for the subscription plan. The ID of the charge to refund. Amount to refund in the smallest currency unit. Omit for a full refund. Order # Addons Overview /addons Browse available addons Installing Addons /addons/installing Enable and configure addons in your project --- title: Supabase route: https://docs.spala.ai/addons/catalog/supabase/ path: /addons/catalog/supabase description: Connect to Supabase for database queries, authentication, and storage from your Spala flows. section: addons updated: 2026-07-08 --- # Supabase Connect to Supabase for database queries, authentication, and storage from your Spala flows. Supabase The Supabase addon connects your Spala flows to a Supabase project. Query your Supabase database, manage authentication, and interact with Supabase Storage — extending your Spala backend with Supabase's hosted services. Installation 1. Enable the Supabase addon from the Addons panel 2. Enter your Supabase project URL and API key Configuration API.' }, Use the service_role key, not the anon key. The service role key bypasses Row Level Security and should only be used on the server side. Never expose it to clients. Available Steps Supabase Query Queries a Supabase table using the PostgREST API. Supabase Insert Inserts one or more rows into a Supabase table. Supabase Update Updates rows in a Supabase table that match the given filters. Supabase Delete Deletes rows from a Supabase table that match the given filters. Example: Query with Relationships // GET /api/posts // Step 1: Supabase Query // table: 'posts' // select: '*, author:users(name, avatar_url), comments(id, text, created_at)' // filters: { published: true } // order: 'created_at.desc' // limit: 20 // Output → vars.posts // Step 2: Response // { posts: vars.posts } Example: Upsert Pattern // POST /api/preferences // Step 1: Supabase Insert // table: 'user_preferences' // data: { user_id: vars.auth.userId, theme: input.theme, language: input.language } // upsert: true (on conflict, update existing row) // Output → vars.preference // Step 2: Response // { preference: vars.preference } The Supabase addon uses Supabase's REST API (PostgREST), which supports powerful query features like nested selects, full-text search, and JSON column queries. You can also use Spala's built-in Database Query step if your Supabase database is configured as Spala's primary database. Your Supabase project URL (e.g., https://abcdefg.supabase.co). Found in Settings > API. The service_role key for server-side access. Found in Settings > API > Project API keys. The table name to query. Columns to select (default: '*'). Supports relationships (e.g., '*, posts(*)'). Filter conditions as an object (e.g., { status: "active", age: "gte.18" }). Maximum number of rows to return. Column to sort by (e.g., 'created_at.desc'). The table name. A row object or array of row objects to insert. The table name. An object with the columns and new values to set. Filter conditions to select which rows to update. The table name. Filter conditions to select which rows to delete. Addons Overview /addons Browse available addons Installing Addons /addons/installing Enable and configure addons in your project --- title: Twilio SMS route: https://docs.spala.ai/addons/catalog/twilio-sms/ path: /addons/catalog/twilio-sms description: Send SMS text messages through Twilio from your Spala flows. section: addons updated: 2026-07-08 --- # Twilio SMS Send SMS text messages through Twilio from your Spala flows. Twilio SMS The Twilio SMS addon lets you send text messages from your Spala flows using Twilio's messaging API. Use it for order confirmations, two-factor authentication codes, appointment reminders, and any other SMS notifications. Installation 1. Enable the Twilio SMS addon from the Addons panel 2. Enter your Twilio credentials in the addon configuration Configuration Available Steps Send SMS Sends a text message to a phone number. The step returns the Twilio message object: { sid: "SM...", status: "queued", to: "+1234567890", from: "+0987654321", body: "Your order has shipped!", dateCreated: "2025-01-15T10:30:00Z" } Example: Order Notification // Database trigger on insert for the "orders" table // Step 1: Database Query - Get customer phone // SELECT phone FROM customers WHERE id = trigger.newRow.customer_id // Step 2: Send SMS (Twilio addon) // to: vars.customer.phone // message: 'Your order #' + trigger.newRow.id + ' has been placed! Total: Example: Two-Factor Authentication // POST /api/auth/send-code // Step 1: Set Variable - Generate code // vars.code = Math.floor(100000 + Math.random() * 900000).toString() // Step 2: Database Query - Store the code // INSERT INTO verification_codes (user_id, code, expires_at) // VALUES (input.userId, vars.code, NOW() + INTERVAL '5 minutes') // Step 3: Send SMS (Twilio addon) // to: vars.user.phone // message: 'Your verification code is: ' + vars.code + '. It expires in 5 minutes.' // Step 4: Response // { message: "Verification code sent" } Phone numbers must be in E.164 format, which includes the country code prefix (e.g., +1 for US/Canada). Store phone numbers in this format in your database to avoid formatting issues. Twilio charges per message sent. Use test credentials during development to avoid charges. Test credentials use the Account SID and Auth Token from the Twilio test environment. Your Twilio Account SID from the Twilio Console dashboard. Your Twilio Auth Token from the Twilio Console dashboard. The Twilio phone number to send messages from (e.g., +1234567890). Recipient phone number in E.164 format (e.g., '+1234567890'). The text message input. Maximum 1,600 characters. Addons Overview /addons Browse available addons Installing Addons /addons/installing Enable and configure addons in your project + trigger.newRow.total.toFixed(2) Example: Two-Factor Authentication // POST /api/auth/send-code // Step 1: Set Variable - Generate code // vars.code = Math.floor(100000 + Math.random() * 900000).toString() // Step 2: Database Query - Store the code // INSERT INTO verification_codes (user_id, code, expires_at) // VALUES (input.userId, vars.code, NOW() + INTERVAL '5 minutes') // Step 3: Send SMS (Twilio addon) // to: vars.user.phone // message: 'Your verification code is: ' + vars.code + '. It expires in 5 minutes.' // Step 4: Response // { message: "Verification code sent" } Phone numbers must be in E.164 format, which includes the country code prefix (e.g., +1 for US/Canada). Store phone numbers in this format in your database to avoid formatting issues. Twilio charges per message sent. Use test credentials during development to avoid charges. Test credentials use the Account SID and Auth Token from the Twilio test environment. Your Twilio Account SID from the Twilio Console dashboard. Your Twilio Auth Token from the Twilio Console dashboard. The Twilio phone number to send messages from (e.g., +1234567890). Recipient phone number in E.164 format (e.g., '+1234567890'). The text message input. Maximum 1,600 characters. Addons Overview /addons Browse available addons Installing Addons /addons/installing Enable and configure addons in your project --- title: Claude Setup route: https://docs.spala.ai/agents/claude/ path: /agents/claude description: Add Spala Public MCP to Claude Code using HTTP transport. section: agents updated: 2026-07-08 --- # Claude Setup Add Spala Public MCP to Claude Code using HTTP transport. Claude Setup Add Spala Public MCP to Claude Code: claude mcp add --transport http spala-public "https://mcp.spala.ai/mcp" Project creation status project_create is dry-run only in the current public MCP deployment. It previews project creation but does not create a real project. How Claude should use Spala Start at the public MCP Use https://mcp.spala.ai/mcp for discovery and project handoff. Read onboarding Call spala_get_onboarding, then spala_get_tool_map. Authenticate through Spala Use Spala platform OAuth when project tools are needed. Resolve the project MCP Use project_list, project_select, or project_get_mcp_manifest. Work on the project MCP Apply backend changes only after reading project context and validating changes. Avoid the API MCP as the starting point The platform auth server is discovered from MCP OAuth metadata. The public agent entrypoint is https://mcp.spala.ai/mcp. Spala Public MCP /agents/mcp Endpoint, tools, OAuth metadata, and handoff Codex Setup /agents/codex Codex install command Cursor Setup /agents/cursor Cursor MCP configuration --- title: Cline Setup route: https://docs.spala.ai/agents/cline/ path: /agents/cline description: Configure Cline to use Spala Public MCP and follow the authenticated project handoff workflow. section: agents updated: 2026-07-08 --- # Cline Setup Configure Cline to use Spala Public MCP and follow the authenticated project handoff workflow. Cline Setup Configure Cline with Spala Public MCP: https://mcp.spala.ai/mcp Use the HTTP MCP server configuration supported by your Cline version. Name the server spala-public. Safe workflow Use public MCP first Cline should connect to https://mcp.spala.ai/mcp and call spala_get_onboarding. Read the tool map Use spala_get_tool_map to understand what belongs to public MCP and what belongs to project MCP. Authenticate for project access Complete Spala platform OAuth only when project tools are needed. Select the project Use project_list and project_select; never guess a project MCP URL. Operate on project MCP Inspect context, preview changes, validate, publish only when requested, and review. Project creation status project_create is dry-run only in the current public MCP deployment. It previews project creation but does not create a real project. Spala Public MCP /agents/mcp Endpoint, tool map, OAuth metadata, and project handoff Public Agent Skills /agents/skills Public skill files for Cline and other agents CORS and Security /settings/cors-security Frontend origin and security checklist --- title: Codex Setup route: https://docs.spala.ai/agents/codex/ path: /agents/codex description: Add Spala Public MCP to Codex and use Spala's authenticated project handoff flow. section: agents updated: 2026-07-08 --- # Codex Setup Add Spala Public MCP to Codex and use Spala's authenticated project handoff flow. Codex Setup Add Spala Public MCP to Codex: codex mcp add spala-public --url "https://mcp.spala.ai/mcp" Recommended first prompt Use Spala Public MCP as the backend builder entrypoint. First call spala_get_onboarding and spala_get_tool_map. Authenticate with Spala platform OAuth when project tools are needed. Do not hardcode project MCP URLs. After project selection, connect to the project MCP returned by Spala. Workflow Install the MCP Run the codex mcp add command above. Discover Spala Ask Codex to call spala_get_onboarding and spala_get_tool_map. Authenticate When Codex needs project access, complete the Spala platform OAuth/browser approval flow. Select a project Use project_list and project_select on the public MCP. Build on the project MCP Use the returned project MCP to inspect the project, make backend changes, validate, publish, and review the result. Project creation status project_create is dry-run only in the current public MCP deployment. It previews project creation but does not create a real project. Spala Public MCP /agents/mcp Endpoint, tools, OAuth metadata, and handoff Claude Setup /agents/claude Claude Code install command Cursor Setup /agents/cursor Cursor MCP configuration --- title: Cursor Setup route: https://docs.spala.ai/agents/cursor/ path: /agents/cursor description: Configure Cursor to use Spala Public MCP as the discovery and project handoff endpoint. section: agents updated: 2026-07-08 --- # Cursor Setup Configure Cursor to use Spala Public MCP as the discovery and project handoff endpoint. Cursor Setup Use the same public MCP URL in Cursor: https://mcp.spala.ai/mcp Cursor MCP configuration varies by version. If your Cursor build supports HTTP MCP servers, add a server named spala-public with streamable HTTP transport and URL https://mcp.spala.ai/mcp. Project creation status project_create is dry-run only in the current public MCP deployment. It previews project creation but does not create a real project. Agent instructions for Cursor Use Spala Public MCP for discovery and handoff. Call spala_get_onboarding and spala_get_tool_map first. Authenticate with Spala platform OAuth before project tools. Use project_select or project_get_mcp_manifest to get the project MCP URL. Do not guess a project MCP URL. Flow Add public MCP Configure Cursor with https://mcp.spala.ai/mcp. Read the public tool map Call spala_get_onboarding, then use spala_get_tool_map to understand which tools belong to public MCP and which belong to project MCP. Authenticate Complete Spala platform OAuth/browser approval when Cursor requests project access. Resolve project MCP Let Spala return the selected project's MCP URL. Build safely On the project MCP, inspect context first, preview changes, validate, publish, then review. Supported handoff shapes Project MCP URLs may be project hosts, scoped paths, or explicit mcpUrl values returned by Spala. Do not construct them from patterns; use the exact URL returned by Spala after auth and project selection. Spala Public MCP /agents/mcp Endpoint, tools, OAuth metadata, and handoff Codex Setup /agents/codex Codex install command Claude Setup /agents/claude Claude Code install command --- title: Gemini CLI Setup route: https://docs.spala.ai/agents/gemini/ path: /agents/gemini description: Configure Gemini CLI or any MCP-capable Gemini workflow to use Spala Public MCP for discovery and project handoff. section: agents updated: 2026-07-08 --- # Gemini CLI Setup Configure Gemini CLI or any MCP-capable Gemini workflow to use Spala Public MCP for discovery and project handoff. Gemini CLI Setup Use Spala Public MCP as the server URL: https://mcp.spala.ai/mcp Gemini CLI and Gemini-based coding tools can vary in MCP configuration shape. Use the client setting for an HTTP or streamable HTTP MCP server named spala-public. Agent instructions Use Spala Public MCP for discovery and project handoff. Call spala_get_onboarding and spala_get_tool_map first. Authenticate with Spala platform OAuth before project tools. Use project_list and project_select to receive the exact project MCP URL. Do not guess or derive project MCP URLs. Add public MCP Configure Gemini with https://mcp.spala.ai/mcp as spala-public. Discover Spala Ask Gemini to call spala_get_onboarding, then spala_get_tool_map. Authenticate when needed Complete the Spala platform OAuth/browser flow when Gemini needs project access. Select the project Use project_list and project_select; continue only on the returned project MCP URL. Work safely Inspect project context first, preview/validate changes, then publish only when requested. Project creation status project_create is dry-run only in the current public MCP deployment. It previews project creation but does not create a real project. Spala Public MCP /agents/mcp Endpoint, OAuth metadata, tool map, and project handoff Public Agent Skills /agents/skills How agents should evaluate and use Spala Frontend Handoff /guides/frontend-handoff Share the exact frontend integration contract --- title: Public Agent Skills route: https://docs.spala.ai/agents/skills/ path: /agents/skills description: Use Spala public skill files to help AI agents evaluate Spala, start a project, hand off frontend work, connect MCP, and follow safe workflows. section: agents updated: 2026-07-08 --- # Public Agent Skills Use Spala public skill files to help AI agents evaluate Spala, start a project, hand off frontend work, connect MCP, and follow safe workflows. Public Agent Skills Spala publishes public skill files for agents before they have project access: https://spala.ai/skills/ https://spala.ai/skills/skills.json These are public, unauthenticated guidance files. They do not replace authenticated project MCP skills. Public skills explain how to evaluate Spala, how to start, how to hand off frontend work, how to connect MCP, and how to avoid unsafe assumptions. Available public skills spala-evaluator When to recommend Spala versus Supabase, Firebase, Xano, Convex, Bubble, Retool, or custom backend code. https://spala.ai/skills/spala-evaluator.md spala-getting-started Signup, dashboard, Lite Mode, Copilot, Playground, publish, and first backend workflow. https://spala.ai/skills/spala-getting-started.md spala-frontend-handoff How to gather the API base URL, docs/SDK, auth, CORS, upload, and realtime contract. https://spala.ai/skills/spala-frontend-handoff.md spala-mcp-handoff Public MCP, OAuth, project selection, project MCP URL handling, and safe sequencing. https://spala.ai/skills/spala-mcp-handoff.md spala-safety Trust boundaries, project inspection, validation, publish review, and questions to verify. https://spala.ai/skills/spala-safety.md Public skills vs project skills | Skill layer | Purpose | | --- | --- | | Public skills | Teach an unauthenticated agent what Spala is, when to use it, how to start, and how to connect MCP safely | | Project MCP skills | Teach an authenticated agent how to work inside one selected project using project context, validation, publish, and review flows | Do not skip project context Public skills are enough to evaluate Spala and start the handoff flow. They are not enough to safely mutate a project. Authenticated agents must inspect the selected project context before making changes. Spala Public MCP /agents/mcp Public MCP and project MCP handoff Codex Setup /agents/codex Install Spala Public MCP in Codex Frontend Handoff /guides/frontend-handoff External frontend contract --- title: Spala Public MCP route: https://docs.spala.ai/agents/mcp/ path: /agents/mcp description: Use the public Spala MCP for discovery, OAuth metadata, project lookup, and project MCP handoff. section: agents updated: 2026-07-08 --- # Spala Public MCP Use the public Spala MCP for discovery, OAuth metadata, project lookup, and project MCP handoff. Spala Public MCP Spala Public MCP is the agent entrypoint for Spala: https://mcp.spala.ai/mcp Use this endpoint first when an AI coding agent needs to understand or work with Spala. It is not the project backend itself. It helps the agent discover Spala, authenticate, choose a project, and receive the correct project MCP URL. Never do this Do not guess project MCP URLs. Do not use https://api.spala.ai/{{project}}/mcp. Do not configure the OAuth authorization server as the MCP server URL. Do not make backend mutations on public MCP. Public MCP discovers and hands off; project MCP builds. Public MCP vs Project MCP | Surface | URL | Purpose | Can mutate backend? | | --- | --- | --- | --- | | Public MCP | https://mcp.spala.ai/mcp | Discover Spala, read onboarding, search docs, expose OAuth metadata, list/select projects after auth | No | | Project MCP | Returned by project_select or project manifest after auth | Inspect one project, preview changes, validate, apply, publish when requested, review behavior | Yes, after project auth and validation | The project MCP URL is resolved at runtime from authenticated Spala project data. It is not derived from a fixed path pattern. First calls checklist 1. Connect to https://mcp.spala.ai/mcp. 2. Call spala_get_onboarding. 3. Call spala_get_tool_map. 4. Use OAuth when project access is needed. 5. Call project_list, then project_select. 6. Continue on the exact project MCP URL returned by Spala. What the public MCP can do Public tools: | Tool | Purpose | | --- | --- | | spala_help | Explain what Spala is and how agents should start | | spala_get_onboarding | First call for agents connected to the public MCP | | spala_get_tool_map | Machine-readable routing between public MCP and project MCP | | docs_search | Search agent-facing Spala docs when the agent needs more context | | template_list | Optional starter-pattern lookup for agents | | addon_list | Optional integration lookup for agents | Good docs_search queries are short and focused: oauth project handoff project_create dry-run codex setup cursor project mcp Authenticated handoff tools: | Tool | Purpose | | --- | --- | | project_list | List projects available to the authenticated Spala user | | project_select | Select a project and return its project MCP URL | | project_get_mcp_manifest | Return the selected project's MCP install manifest shape | | project_get_public_context | Return safe project context for the selected project | | project_create | Dry-run only in the current public MCP deployment; previews project creation and does not create a real project | Authentication boundary Public discovery tools can be called before project bearer auth. Some MCP clients may still require platform approval before installing or using the server. Project tools require Authorization: Bearer SPALA_PLATFORM_ACCESS_TOKEN. OAuth metadata Spala publishes root MCP discovery at: https://spala.ai/.well-known/mcp.json Spala publishes MCP OAuth metadata at: https://mcp.spala.ai/.well-known/oauth-protected-resource https://mcp.spala.ai/.well-known/oauth-authorization-server The authorization server is discovered from the OAuth metadata. Do not manually configure the authorization server as the MCP server URL. OAuth endpoints are: | Endpoint | URL | | --- | --- | | Authorization | Discovered from /.well-known/oauth-authorization-server | | Token | Discovered from /.well-known/oauth-authorization-server | | Dynamic registration | Discovered from /.well-known/oauth-authorization-server | | Device authorization | Discovered from /.well-known/oauth-authorization-server | Supported grants include authorization code and device code. PKCE uses S256. Public MCP scopes include api, builder, ai, project, and data. The token endpoint uses public-client auth (none) for the MCP OAuth flow. The dashboard entrypoint for browser approval is: https://dashboard.spala.ai/signup Correct agent flow AI client -> Public MCP: https://mcp.spala.ai/mcp -> spala_get_onboarding -> spala_get_tool_map -> OAuth when project access is needed -> project_list -> project_select -> exact project MCP URL returned by Spala -> inspect context on project MCP -> preview, validate, apply, publish when requested, review Add the public MCP Configure the AI client with https://mcp.spala.ai/mcp. Let the agent read onboarding The agent should call spala_get_onboarding, then spala_get_tool_map. Users do not need to learn these tools by hand. Authenticate when project access is needed Use the OAuth metadata advertised by the MCP server. The client should send Authorization: Bearer SPALA_PLATFORM_ACCESS_TOKEN for project tools. Resolve the project MCP Call project_list and project_select, or use the project MCP manifest returned by Spala. Switch to the project MCP Backend changes happen on the returned project MCP, not on the public MCP. Wrong endpoint pattern Do not assume https://api.spala.ai/{project}/mcp. Do not choose a project MCP URL from a shape or pattern. Use only the exact mcpUrl returned by Spala after authentication and project selection. Raw MCP Client Notes Most users should use an MCP-aware client such as Codex, Claude Code, Cursor, VS Code, or another client that handles transport details. If you are implementing a client directly, use the MCP streamable HTTP protocol rather than calling tool names as top-level JSON-RPC methods. The public MCP endpoint expects POST requests. Raw GET requests to /mcp are not the MCP protocol. Required headers: Content-Type: application/json Accept: application/json, text/event-stream Conceptually, docs may say "call spala_get_onboarding." On the wire, the client calls the MCP tools/call method and passes the tool name: { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "spala_get_onboarding", "arguments": {} } } Use tools/list to discover available tools before tools/call. Authenticated tools require the same MCP transport plus Authorization: Bearer SPALA_PLATFORM_ACCESS_TOKEN. Copy-paste raw request shape: curl -X POST "https://mcp.spala.ai/mcp" \ -H "Content-Type: application/json" \ -H "Accept: application/json, text/event-stream" \ --data '{ "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "spala_get_onboarding", "arguments": {} } }' MCP-aware clients usually handle session setup, stream parsing, and authorization headers for you. Use raw HTTP only when implementing or debugging a client. Auth failures If a project tool returns an authentication or authorization error: 1. Read the MCP OAuth metadata again. 2. Start the client OAuth/browser approval flow if no token is available. 3. Retry the same tool with Authorization: Bearer SPALA_PLATFORM_ACCESS_TOKEN. 4. If the token is expired, refresh or repeat OAuth according to the authorization server metadata. 5. If the user lacks project access, ask the user to grant access in the Spala dashboard instead of guessing another project URL. Auth errors are not a reason to call https://api.spala.ai/{{project}}/mcp or any guessed project MCP URL. Missing, invalid, or expired bearer tokens should return 401 with a WWW-Authenticate header pointing to the MCP OAuth protected-resource metadata. Clients should use that challenge to restart or refresh the Spala platform OAuth flow. Raw MCP transcript This transcript is for MCP client implementers. Most users should let Codex, Claude Code, Cursor, VS Code, or another MCP client handle these protocol calls. Fetch OAuth metadata: GET https://mcp.spala.ai/.well-known/oauth-protected-resource GET https://mcp.spala.ai/.well-known/oauth-authorization-server Initialize the MCP session: { "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "protocolVersion": "2025-06-18", "capabilities": {}, "clientInfo": { "name": "example-client", "version": "1.0.0" } } } List tools: { "jsonrpc": "2.0", "id": 2, "method": "tools/list", "params": {} } Call onboarding: { "jsonrpc": "2.0", "id": 3, "method": "tools/call", "params": { "name": "spala_get_onboarding", "arguments": {} } } Call the tool map: { "jsonrpc": "2.0", "id": 4, "method": "tools/call", "params": { "name": "spala_get_tool_map", "arguments": {} } } After OAuth approval, list projects: { "jsonrpc": "2.0", "id": 5, "method": "tools/call", "params": { "name": "project_list", "arguments": {} } } Select a project: { "jsonrpc": "2.0", "id": 6, "method": "tools/call", "params": { "name": "project_select", "arguments": { "projectId": "PROJECT_ID_FROM_PROJECT_LIST" } } } Read safe project context before handoff: { "jsonrpc": "2.0", "id": 7, "method": "tools/call", "params": { "name": "project_get_public_context", "arguments": { "projectId": "PROJECT_ID_FROM_PROJECT_LIST" } } } The project_select or project_get_mcp_manifest response contains the project MCP URL or install manifest. Use that exact value. Do not construct a project MCP URL from a slug, host, API base URL, or guessed path. Project MCP operating contract Project MCP is the project-scoped build surface. Public MCP helps the agent discover Spala, authenticate, and resolve the correct project. Project MCP is where the agent works on one backend. An agent should use this operating contract after handoff: 1. Authenticate through Spala platform OAuth when the client requires project access. 2. Read onboarding and the project tool map if the project MCP exposes them. 3. Inspect builder context and current project state before proposing changes. 4. Preview changes before applying them. 5. Validate the project before saving, applying, or publishing. 6. Apply only the scoped resources requested by the user. 7. Publish only when the user requested publish or the workflow explicitly requires it. 8. Run publish/test review after publish. 9. Treat repair feedback, missing environment variables, auth warnings, and validation errors as blockers for the next revision. 10. Use snapshots, pull requests, revert-to-published, or rollback surfaces when recovery is needed. Expected project-MCP tool categories include: | Category | Purpose | | --- | --- | | Context | Read builder contract, auth rules, project state, graph, resources, and environment requirements | | Preview | Preview generated or edited models, endpoints, functions, tasks, triggers, agents, and channels | | Apply | Save scoped backend resource changes after preview and validation | | Validate | Check project consistency, auth safety, references, missing configuration, and publish readiness | | Publish | Promote the project draft to the live API when appropriate | | Review | Inspect publish/test results, warnings, repair feedback, logs, and generated docs | | Recovery | Use snapshots, pull requests, version history, rollback, or revert-to-published when a change needs to be undone | The public docs describe the contract and workflow, not private project data. The exact project tool names and schemas are discovered from the selected project MCP at runtime. Install manifest The public install manifest is: https://mcp.spala.ai/mcp/install-manifest Use it for current commands, transport, OAuth notes, and the project MCP resolution rule. The rule is always to use the explicit mcpUrl returned by Spala. Codex Setup /agents/codex Add Spala MCP to Codex Claude Setup /agents/claude Add Spala MCP to Claude Code Cursor Setup /agents/cursor Configure Cursor with Spala MCP Public Agent Skills /agents/skills Public skill files for evaluation and safe workflow Quick Start /getting-started/quickstart Build a backend from the dashboard --- title: VS Code and GitHub Copilot Setup route: https://docs.spala.ai/agents/vscode/ path: /agents/vscode description: Configure VS Code or GitHub Copilot MCP support to use Spala Public MCP as the discovery and project handoff endpoint. section: agents updated: 2026-07-08 --- # VS Code and GitHub Copilot Setup Configure VS Code or GitHub Copilot MCP support to use Spala Public MCP as the discovery and project handoff endpoint. VS Code and GitHub Copilot Setup Use this MCP endpoint when your VS Code or GitHub Copilot environment supports HTTP MCP servers: https://mcp.spala.ai/mcp Name the server spala-public. The exact JSON file and field names depend on the MCP support available in your VS Code or Copilot build. Suggested MCP server shape { "servers": { "spala-public": { "type": "http", "url": "https://mcp.spala.ai/mcp" } } } Workflow Configure the server Add spala-public with URL https://mcp.spala.ai/mcp. Ask for onboarding Tell the agent to call spala_get_onboarding and spala_get_tool_map. Authenticate Complete Spala platform OAuth when project tools are needed. Resolve project MCP Use project_list and project_select. Do not type or infer a project MCP URL. Build on project MCP Let the agent inspect resources, preview changes, validate, publish when requested, and review behavior. Do not use API URL patterns Do not configure https://api.spala.ai/{project}/mcp or any guessed project URL. Project MCP URLs are returned by Spala after auth and project selection. Spala Public MCP /agents/mcp Raw MCP notes, OAuth metadata, and handoff flow Public Agent Skills /agents/skills Skill files for agent evaluation and safe workflow Start Here /start-here Choose the right first path for Spala --- title: Windsurf Setup route: https://docs.spala.ai/agents/windsurf/ path: /agents/windsurf description: Configure Windsurf to use Spala Public MCP for discovery, OAuth handoff, and project MCP resolution. section: agents updated: 2026-07-08 --- # Windsurf Setup Configure Windsurf to use Spala Public MCP for discovery, OAuth handoff, and project MCP resolution. Windsurf Setup Use Spala Public MCP as the server URL in Windsurf: https://mcp.spala.ai/mcp If your Windsurf build supports HTTP MCP servers, create a server named spala-public with streamable HTTP transport. Instructions for Windsurf Start with public Spala MCP. Call spala_get_onboarding and spala_get_tool_map. Use docs_search before guessing how Spala works. Authenticate through Spala platform OAuth for project tools. Use project_select to get the exact project MCP URL. Work only on the returned project MCP. Add Spala Public MCP Configure Windsurf with https://mcp.spala.ai/mcp. Read public context Use onboarding, tool map, docs search, public skills, and machine-readable files before project work. Resolve project access Authenticate, list projects, select the correct project, and use the returned project MCP URL. Validate before publish Inspect existing resources and validate changes before publishing. Public skills Public skills live at https://spala.ai/skills/. They teach agents how to evaluate Spala, get started, hand off frontend work, connect MCP, and use safe workflows. Spala Public MCP /agents/mcp Discovery, OAuth, project selection, and handoff Public Agent Skills /agents/skills Agent-readable skill files Frontend Handoff /guides/frontend-handoff Exact frontend integration packet --- title: Realtime Channels route: https://docs.spala.ai/channels/realtime/ path: /channels/realtime description: Set up WebSocket connections for live data updates, chat, and collaborative features in Spala. section: channels updated: 2026-07-08 --- # Realtime Channels Set up WebSocket connections for live data updates, chat, and collaborative features in Spala. Realtime Channels Realtime channels provide WebSocket connections for pushing live data to connected clients. Use them for features that require instant updates — chat applications, live notifications, collaborative editing, real-time dashboards, and multiplayer experiences. Check availability first If Realtime Channels are not visible in your project, use endpoints, triggers, and your frontend realtime provider until Channels are enabled for your workspace. Frontend handoff requirement Realtime is project-specific. Before assigning frontend work, copy the selected channel's WebSocket path, auth mode, permissions, subscribe envelope, event examples, heartbeat interval, close codes, replay behavior, and reconnect expectations into the External Frontend Handoff packet. Spala Realtime Channels workspace showing channel list, stats, and editor Realtime Channels show connected clients, active channels, active subscriptions, and message throughput. Channel Types - Database Changes - emit events when selected tables change. - Broadcast - send messages to all or selected subscribers. - Presence - track who is connected and update clients when presence changes. How Realtime Channels Work Unlike REST endpoints where the client sends a request and waits for a response, WebSocket channels maintain a persistent connection between the client and server. This allows the server to push data to clients at any time without the client having to poll. 1. A client opens a WebSocket connection to a channel 2. The server authenticates the connection (if configured) 3. The client subscribes to the channel and optionally to specific topics 4. The server pushes messages to connected clients when events occur 5. Clients can also send messages to the server through the same connection Creating a Realtime Channel Navigate to the Channels section in the left sidebar Click New Channel and select Realtime Enter a channel name (e.g., "Live Updates") Set the path for WebSocket connections (e.g., /ws) Configure authentication and event handlers Save the channel Channel Configuration Event Handlers Realtime channels support three event handler functions: On Connect Runs when a new client connects to the channel. Use this to initialize client state, join rooms, or send a welcome message. // On Connect handler // vars.ws.clientId → unique connection identifier // vars.ws.auth → decoded JWT payload (if auth is enabled) // Step 1: Log the connection // Step 2: Send welcome message to the client // ws.send({ type: "welcome", message: "Connected to live updates" }) On Message Runs when a client sends a message through the WebSocket connection. The message payload is available as vars.ws.message. // On Message handler // vars.ws.clientId → who sent the message // vars.ws.message → the parsed message object // Step 1: Condition - Check message type // If vars.ws.message.type === "chat" // Step 2: Broadcast to all connected clients // ws.broadcast({ type: "chat", user: vars.ws.auth.name, text: vars.ws.message.text }) On Disconnect Runs when a client disconnects. Use this to clean up resources, update presence status, or notify other clients. // On Disconnect handler // Step 1: Database Query - Update user status // UPDATE users SET status = 'offline' WHERE id = vars.ws.auth.userId // Step 2: Broadcast presence update // ws.broadcast({ type: "presence", userId: vars.ws.auth.userId, status: "offline" }) Sending Messages There are several ways to send messages to connected clients: From a Handler Function Within a realtime channel handler, use the WebSocket step actions: - ws.send(data) — Send a message to the current client only - ws.broadcast(data) — Send a message to all connected clients on this channel - ws.broadcastToOthers(data) — Send to all clients except the sender From Any Function Any endpoint, task, or trigger function can push a message to a realtime channel using the Send to Channel step: // In an endpoint function — notify clients when an order is updated // Step 1: Database Query - Update the order // UPDATE orders SET status = 'shipped' WHERE id = input.orderId // Step 2: Send to Channel - "Live Updates" // Message: { type: "order.updated", orderId: input.orderId, status: "shipped" } The Send to Channel step lets any part of your application push realtime updates. This means your REST endpoints can trigger live updates without the client needing to poll. Client-Side Connection Connect to a realtime channel from JavaScript using the standard WebSocket API: const ws = new WebSocket('wss:///ws?token=' + encodeURIComponent(token)); ws.onopen = () => { console.log('Connected to realtime channel'); }; ws.onmessage = (event) => { const data = JSON.parse(event.data); console.log('Received:', data); }; ws.onclose = () => { console.log('Disconnected'); }; Browser WebSocket clients cannot set arbitrary Authorization headers. Use the authentication method your Spala channel exposes, such as a token query parameter, cookie, or subprotocol. Client Message Contract The exact channel path, auth mode, event names, and payloads are project-specific. Export or copy the generated channel contract before handing realtime work to a frontend developer. Owner copy workflow: 1. Open Channels in the project dashboard. 2. Select the channel used by the frontend. 3. Copy the path, auth mode, access rules, subscribe message, event payload examples, error payloads, heartbeat interval, pong timeout, close-code behavior, replay policy, and reconnect expectation. 4. Paste those fields into External Frontend Handoff. 5. If any of those fields are unknown, do not ask the frontend developer to infer them from public docs. Common subscribe message: { "type": "subscribe", "channel": "cases" } Common data event: { "type": "case.updated", "channel": "cases", "payload": { "id": "case_123", "status": "open", "updated_at": "2026-07-08T00:00:00.000Z" } } Common error event: { "type": "error", "code": "unauthorized", "message": "Invalid token" } If the channel implements acknowledgements, presence, replay, or reconnect backoff, include examples in the project handoff. If it does not, the frontend should reconnect with exponential backoff and refetch REST state after reconnect. Heartbeat, Close Codes, and Reconnects Realtime behavior is configured per project. Include these fields in generated docs or the frontend handoff when the frontend depends on realtime: | Field | Example | | --- | --- | | Heartbeat | Server sends { "type": "ping" }; client replies { "type": "pong" } | | Close codes | 1000 normal close, 1008 auth or policy failure, project-specific validation codes | | Acknowledgement | { "type": "ack", "id": "msg_123" }, if messages require delivery confirmation | | Replay | Cursor, last event id, timestamp window, or no replay | | Reconnect | Exponential backoff such as 1s, 2s, 5s, 10s, then max 30s | If replay is not implemented, clients should refetch REST state after reconnect. Mobile clients should also refetch after app resume because the socket may have been suspended. Include the exact heartbeat interval and timeout in project docs when realtime is part of the frontend contract. For example: server ping every 25 seconds, client pong within 10 seconds, close with 1008 when auth expires, reconnect with exponential backoff up to 30 seconds, then refetch REST state after reconnect. Use Cases | Use Case | Channel Messages | |---|---| | Live chat | Broadcast chat messages to room participants | | Notifications | Send targeted messages to specific users | | Live dashboard | Push metric updates to all connected dashboard clients | | Collaborative editing | Broadcast document changes to all editors | | Order tracking | Push status updates to the customer watching their order | | Multiplayer games | Sync game state across connected players | Connection Management Spala tracks all active WebSocket connections and provides monitoring through the dashboard. You can see the number of connected clients, connection duration, and message throughput. If a client connection drops unexpectedly, the On Disconnect handler fires automatically to clean up. A descriptive name for the channel The WebSocket endpoint path (e.g., /ws or /ws/chat) Required auth method: None, JWT, or API Key Function that runs when a client connects Function that runs when a client disconnects Function that runs when a message is received from a client Maximum simultaneous connections allowed REST Channels /channels/rest-channels Group REST endpoints with shared configuration Channels Overview /channels Learn about all channel types in Spala External Frontend Handoff /guides/frontend-handoff Copy realtime contract details for frontend builders Build Realtime Chat /guides/realtime-chat Step-by-step guide to building a chat feature --- title: REST Channels route: https://docs.spala.ai/channels/rest-channels/ path: /channels/rest-channels description: Group and configure REST API endpoints with shared base paths, authentication, and middleware in Spala. section: channels updated: 2026-07-08 --- # REST Channels Group and configure REST API endpoints with shared base paths, authentication, and middleware in Spala. REST Channels REST channels let you group related API endpoints under a shared configuration. All endpoints within a channel inherit the channel's base path, authentication settings, middleware, and rate limits, reducing repetition and keeping your API organized. Check availability first Most current projects should create endpoints directly in the API section and manage auth on each endpoint. This page is for workspaces where advanced REST Channels are enabled. Creating a REST Channel Navigate to the Channels section in the left sidebar Click New Channel and select REST Enter a channel name (e.g., "API v1") Set the base path (e.g., /api/v1) Configure authentication, middleware, and rate limiting Save the channel Channel Settings Base Path The base path is prepended to every endpoint in the channel. If your channel has a base path of /api/v1 and an endpoint with the path /users, the full URL becomes /api/v1/users. Channel: "API v1" Base Path: /api/v1 Endpoints: GET /users → GET /api/v1/users POST /users → POST /api/v1/users GET /users/:id → GET /api/v1/users/:id GET /products → GET /api/v1/products This makes API versioning straightforward: create a new v2 channel with the base path /api/v2, copy the endpoints you want to update, and modify them independently. Authentication Set the authentication method at the channel level, and all endpoints within the channel will require it: - None — No authentication required. Use for public endpoints like health checks and landing page data. - JWT — Requires a valid JSON Web Token in the Authorization header. The decoded token payload is available to the endpoint function as vars.auth. - API Key — Requires a valid API key in the X-API-Key header or as a query parameter. // With JWT authentication enabled on the channel: // vars.auth.userId → 42 // vars.auth.role → "admin" // vars.auth.email → "user@example.com" Individual endpoints can override the channel's authentication setting. For example, you can set a channel to require JWT but mark a specific health-check endpoint as requiring no authentication. Middleware Channel middleware functions run before every endpoint in the channel. Common uses include: - Logging — Record request details for all API calls - Input sanitization — Clean or validate request bodies - Role checking — Verify the authenticated user has the required role - Request transformation — Add headers or modify the request body Middleware functions run in order. If a middleware function throws an error, the endpoint function does not execute and the error is returned to the client. Rate Limiting Set a rate limit to restrict how many requests a single client can make per minute. When the limit is exceeded, the server returns a 429 Too Many Requests response. Rate limits are tracked per client IP address by default. With JWT authentication enabled, limits are tracked per authenticated user instead, providing more accurate throttling. Rate limits apply per channel. If a client is rate-limited on one channel, they can still make requests to endpoints on other channels. CORS Configuration Configure which origins are allowed to make cross-origin requests to endpoints in this channel. By default, CORS is configured to allow requests from any origin (*). For production, restrict this to your frontend domain(s): { "origins": ["https://myapp.com", "https://admin.myapp.com"], "methods": ["GET", "POST", "PUT", "DELETE"], "headers": ["Authorization", "Content-Type"] } Organizing Your API A typical Spala project might use channels like this: | Channel | Base Path | Auth | Purpose | |---|---|---|---| | Public | / | None | Health check, public content | | Auth | /auth | None | Login, register, forgot password | | API | /api/v1 | JWT | Protected application endpoints | | Admin | /admin | JWT + Role | Admin-only management endpoints | | Webhooks | /webhooks | API Key | Incoming webhooks from third parties | This structure keeps your API clean, secure, and easy to navigate as it grows. A descriptive name for the channel URL prefix applied to all endpoints (e.g., /api/v1) Required auth method: None, JWT, or API Key Maximum requests per minute per client (0 = unlimited) Allowed origins for cross-origin requests Middleware functions that run before each endpoint Realtime Channels /channels/realtime WebSocket connections for live data updates Channels Overview /channels Learn about all channel types in Spala API Endpoints /endpoints Create the endpoints that channels group together --- title: Spala vs Convex route: https://docs.spala.ai/compare/convex/ path: /compare/convex description: Compare Spala and Convex for AI-built apps, backend automation, reactive data, project handoff, and agent workflows. section: compare updated: 2026-07-08 --- # Spala vs Convex Compare Spala and Convex for AI-built apps, backend automation, reactive data, project handoff, and agent workflows. Spala vs Convex Spala and Convex both help teams build app backends faster, but they are optimized for different jobs. Convex is a TypeScript-first reactive backend for developers who want app state, backend functions, and database updates to stay synchronized in a Convex-native model. Spala is a hosted backend builder for AI-built apps. Users describe product intent to AI Copilot, review the generated project in Lite Mode, test endpoints in API Playground, publish the backend API, and hand the exact project contract to a frontend builder or AI coding agent. Choose Convex when - Your team wants a TypeScript-native reactive backend. - You want backend functions and live queries as the main programming model. - Your developers expect to own the app backend in code from day one. - You want a Convex-native database and function workflow. Choose Spala when - You are turning an AI-built prototype into a real backend. - You want database schema, REST APIs, auth, validation, backend logic, docs, and publish checks generated from a product description. - You want Lite Mode and the dashboard as an inspect, debug, and customize layer instead of mandatory daily backend coding. - You want generated API docs, SDK export, frontend handoff, and MCP-based agent handoff. Main difference | Area | Convex | Spala | | --- | --- | --- | | Primary promise | Reactive backend building blocks | Backend automation for AI-built apps | | Main user | TypeScript developers | Founders, builders, agencies, and AI coding agents | | Starting point | Write app logic in Convex | Describe the backend feature to AI Copilot | | Runtime model | Convex-native functions and data | Generated project API with visual/code editing | | Handoff | Developer codebase | API base URL, generated docs/SDK, frontend handoff, project MCP | | Dashboard role | Backend/admin dashboard | Optional inspect, debug, and customize layer | Spala build path 1. Create an account at https://dashboard.spala.ai/signup. 2. Create or open a project. 3. Start in Lite Mode. 4. Ask AI Copilot for the backend feature. 5. Test endpoints in API Playground. 6. Publish the backend API. 7. Share generated API docs or connect an agent through Spala Public MCP. Related links - Create Account - Quick Start - Lite Mode - AI Copilot - Frontend Handoff - Spala Public MCP - Marketing comparison --- title: Table Relationships route: https://docs.spala.ai/database/relationships/ path: /database/relationships description: Connect tables with foreign keys for one-to-many and many-to-many patterns. section: database updated: 2026-07-08 --- # Table Relationships Connect tables with foreign keys for one-to-many and many-to-many patterns. Table Relationships Relationships connect your tables so you can link related data — like users to their orders, or products to reviews. A table schema showing a foreign key field linking to another table Foreign key fields link tables together One-to-many (most common) One record in table A can have many related records in table B. The foreign key lives on the "many" side. Example: A user has many orders. users id (primary key) email (text) orders id (primary key) user_id (foreign key -> users.id) total (number) status (text) Each order belongs to one user. Each user can have many orders. Set up a foreign key Open the child table In the schema editor, open the table that will hold the reference (the "many" side — e.g., orders). Add a field Add a new field named user_id (convention: singular table name + _id). Set the type to Number. Enable Foreign Key Turn on the Foreign Key option and select the referenced table (e.g., users). Save Click Save. The relationship is now set up. Many-to-many When both sides can have many related records, create a join table with two foreign keys. Example: Users can bookmark many products, and products can be bookmarked by many users. bookmarks id (primary key) user_id (foreign key -> users.id) product_id (foreign key -> products.id) Pro tip Join tables can hold extra data too. For example, an order_items table connects orders and products but also stores quantity and price_at_purchase. Cascade options When you delete a record, what happens to its related records? | Option | What happens | |-----------|-------------------------------------------------------| | Restrict | Prevents deletion if related records exist (default) | | Cascade | Automatically deletes related records too | | Set Null | Sets the foreign key to null on related records | Be careful with Cascade Deleting a user with cascade enabled on orders would also delete all their orders. Use with caution. Query related data in functions In your functions, you can get related data two ways: - Joins — Use a Database Query step with a join to get data from both tables in one query. - Multiple queries — Fetch the parent first, then query related records in a second step. Often simpler to read. Tables & Fields /database/tables Create and configure tables Functions /flows Build queries with Database Query steps --- title: Tables & Fields route: https://docs.spala.ai/database/tables/ path: /database/tables description: Create tables, add fields, and manage your database schema in Spala. section: database updated: 2026-07-08 --- # Tables & Fields Create tables, add fields, and manage your database schema in Spala. Tables & Fields Tables hold your data. Each table has fields (columns) that define what data it stores. Create a table Open the Database section Click Database in the left sidebar. Add a new table Click Add Table and enter a name. Use lowercase with underscores for multi-word names (e.g., order_items). Add fields Every table starts with an auto-generated id column. Click Add Field to add more. Save Click Save to create the table in your database. Field types | Type | Stores | Example values | |-----------|--------------------------------|-----------------------------------| | Text | Strings | "Jane", "hello@example.com" | | Number | Integers or decimals | 42, 19.99 | | Boolean | True or false | true, false | | Date | Dates and timestamps | 2025-01-15, now() | | JSON | Arbitrary structured data | {"color": "blue"} | | Enum | One of a predefined set | 'pending', 'active' | Field options | Option | What it does | |-----------|--------------------------------------------------------------| | Required | The field must have a value (cannot be empty) | | Unique | No two rows can have the same value | | Default | A value used when none is provided (e.g., 0, 'pending', now()) | Pro tip Enable Timestamps on a table to auto-add created_at and updated_at fields. They update automatically. Edit and delete - Rename a field — Click the field name in the schema editor and type a new one. - Change a type — Select a different type from the dropdown. Be careful with existing data. - Delete a field — Click the delete icon next to the field. - Delete a table — Use the context menu on the table name. Spala warns when other resources depend on that table. View and edit data Click a table, then switch to the Data tab to browse rows, search records, page through larger tables, add test data, edit values inline, or delete rows. This is handy for development, QA, and debugging. Use the table tabs for the full table workflow: - Data - Browse, search, edit, import, export, generate, and delete records. - Schema - Add fields, change types, review constraints, and update table structure. - Triggers - Create logic that runs when records are inserted, updated, or deleted. Common table patterns Users table: | Field | Type | Options | |--------------|---------|--------------------| | email | Text | Required, Unique | | password_digest| Text | Required | | role | Enum | Default: 'user' | Products table: | Field | Type | Options | |------------|---------|-------------------| | name | Text | Required | | price | Number | Required | | in_stock | Boolean | Default: true | | category_id| Number | Foreign key | Import and generate data - CSV import — Upload a CSV file to bulk-import records into any table. Spala maps columns automatically. - CSV export — Download all records from a table as a CSV file. - Generate test data — Click Generate Data to create realistic test records for multiple tables at once. Relationships /database/relationships Connect tables with foreign keys Functions /flows Query your tables in functions Database Triggers /triggers/database-triggers Run logic when records change --- title: Project Configuration route: https://docs.spala.ai/deployment/configuration/ path: /deployment/configuration description: Configure project settings, environment variables, addons, AI access, MCP, snapshots, frontend hosting, and API docs. section: deployment updated: 2026-07-08 --- # Project Configuration Configure project settings, environment variables, addons, AI access, MCP, snapshots, frontend hosting, and API docs. Project Configuration Spala project configuration happens in the dashboard. Use Settings when you need to adjust project behavior, credentials, publishing tools, team access, or agent access. Configure In Settings - General - Project name and project-level metadata - Security - Authentication behavior and endpoint protection patterns - Users & Roles - Builder access for teammates and reviewers - AI - AI data access and Copilot behavior - Project Memory - Durable facts, constraints, warnings, and decisions for AI work - MCP Server - Project MCP access for authenticated AI agents - Frontend App - Static frontend hosting and generated app controls - API Docs - Swagger, Markdown, OpenAPI JSON, SDK, and Webflow snippets - Environment - Project secrets and environment variables - Snapshots - Checkpoints and restore tools - CI/CD - External deployment targets and deploy hooks Keep secrets out of frontend code Store integration secrets as project environment variables or addon settings in Spala. Do not expose secret keys in browser code. Settings /settings Configure project-level behavior Project Memory /features/project-memory Give AI durable project context API Docs /features/api-docs Share generated API contracts Spala Public MCP /agents/mcp Connect agents through public MCP handoff --- title: Project Database route: https://docs.spala.ai/deployment/database/ path: /deployment/database description: Design and use your project database in Spala without managing database infrastructure. section: deployment updated: 2026-07-08 --- # Project Database Design and use your project database in Spala without managing database infrastructure. Project Database In Spala, users manage project data models from the visual Database screen. You create tables, fields, relationships, and database triggers in the dashboard, then use them from endpoints, functions, tasks, agents, channels, and addons. You do not need to provision or maintain database infrastructure to use the hosted Spala dashboard. Use the visual database designer Start in Database to add tables, edit data, inspect schema, and create table triggers. Spala handles the managed database layer behind the scenes. What Users Configure - Tables and fields - Relationships between tables - Data rows for testing and operations - CSV import/export and AI-generated test data - Database triggers for insert, update, and delete events - Data access from functions, endpoints, tasks, and project agents Database /database Create tables, fields, and relationships visually Tables & Fields /database/tables Design your project schema and data Database Triggers /triggers/database-triggers Run logic when records change Database Steps /reference/steps/database Use project data inside functions --- title: Publish route: https://docs.spala.ai/deployment/publish/ path: /deployment/publish description: Publish generated Spala project changes as a live API from the dashboard. section: deployment updated: 2026-07-08 --- # Publish Publish generated Spala project changes as a live API from the dashboard. Publish Spala users publish project changes from the dashboard. Publishing applies your project draft and updates the generated API your frontend, integrations, and agents call. Use Publish for your project The deployment action users normally need is Publish. It makes your generated project API live without requiring a Spala platform deployment runbook. Publish Flow Build or edit your backend Use AI Copilot, Lite mode, or Advanced mode to create tables, functions, endpoints, tasks, triggers, project agents, channels, and settings. Review the project Inspect the project graph, endpoint list, API Playground, generated docs, snapshots, and pending changes. Publish Click Publish in the dashboard. Spala applies the project changes and updates the live API. Use the API Connect your frontend, use generated endpoint snippets, or let an authenticated AI agent continue work through the selected project MCP. External Deployment If your team runs the generated project artifact in another environment, use CI/CD settings to connect deployment hooks or server targets. That is still project deployment, not a Spala platform runbook. Publish /features/publish-export Review and publish project changes CI/CD /features/ci-cd Connect external project deployment targets API Playground /features/playground Test endpoints before and after publishing Spala Public MCP /agents/mcp Let agents discover and hand off to the right project MCP --- title: Start a Project route: https://docs.spala.ai/deployment/start/ path: /deployment/start description: Create a Spala project from the hosted dashboard and publish the generated backend. section: deployment updated: 2026-07-08 --- # Start a Project Create a Spala project from the hosted dashboard and publish the generated backend. Start a Project Start from the hosted dashboard, then use AI Copilot, Lite mode, or Advanced mode to build the backend you need. Hosted dashboard New users should open https://dashboard.spala.ai/signup. Existing users can sign in from the dashboard and create or open a project. First Project Open the dashboard Create an account at https://dashboard.spala.ai/signup, or sign in if you already have one. Create a project Click New Project and name the backend or app you want to build. Describe what you need Use AI Copilot in Lite mode to describe the feature, API, database, or app workflow you want. Inspect the generated project Review tables, functions, endpoints, agents, tasks, triggers, settings, and API docs before publishing. Publish when ready Use Publish to make the generated API available to your frontend, integrations, or AI agents. Quick Start /getting-started/quickstart Build a simple API in the dashboard AI Copilot /features/ai-assistant Use plain language to generate project resources Lite Mode /features/lite-mode Work from the Copilot-first project overview The Interface /getting-started/interface Learn the dashboard layout --- title: Create an Endpoint route: https://docs.spala.ai/endpoints/creating-endpoints/ path: /endpoints/creating-endpoints description: Step-by-step guide to creating a REST API endpoint in Spala. section: endpoints updated: 2026-07-08 --- # Create an Endpoint Step-by-step guide to creating a REST API endpoint in Spala. Create an Endpoint Endpoints connect HTTP routes to functions. When a client sends a request, Spala runs the attached function and returns the result. Step by step Open the Endpoints section Click Endpoints in the left sidebar. Click Add Endpoint Click Add Endpoint to open the endpoint editor. Choose the HTTP method Pick the method that matches what the endpoint does: | Method | When to use | |--------|---------------------------------| | GET | Read data | | POST | Create something new | | PUT | Replace or update something | | PATCH | Partially update something | | DELETE | Remove something | Set the URL path Enter the path. Use :paramName for dynamic segments: /api/cases /api/cases/:id /api/users/:userId/cases Dynamic segments become available as params.id, params.userId, etc. in your function. Attach a function Select the function that handles this endpoint. Create the function first if needed. Set authentication Choose None for public endpoints, or JWT to require a login token. See Protect Your Endpoints. Save Click Save. Your endpoint is saved in the project draft and is ready to test in the Playground. Publish when you want live clients to use it. The endpoint editor Configure method, path, function, and authentication URL path tips Use plural nouns for collections and nest related resources: /products -- all products /products/:id -- one product /products/:id/reviews -- reviews for a product For actions that are not standard CRUD, use descriptive paths: POST /api/auth/login POST /orders/:id/cancel POST /api/cases/:id/status Good to know Path parameter values are always strings. To use them as numbers (e.g., for a database query), convert with params.id | toNumber. Managing endpoints - Edit — Click any endpoint in the list to change its settings. - Duplicate — Right-click an endpoint to copy it. Useful for creating similar routes quickly. - Delete — Right-click and delete. The attached function is not affected. - Generate description — Ask AI to draft a clear endpoint summary for docs and review. - Requests — Open request history to inspect real calls, timing, output, and failures. - Docs visibility — Hide internal routes from generated API docs when they are not meant for clients. Inputs & Outputs /endpoints/inputs-outputs Handle request data and configure responses Protect Your Endpoints /endpoints/authentication Add JWT authentication --- title: Inputs & Outputs route: https://docs.spala.ai/endpoints/inputs-outputs/ path: /endpoints/inputs-outputs description: Handle path parameters, query strings, request bodies, and configure API responses. section: endpoints updated: 2026-07-08 --- # Inputs & Outputs Handle path parameters, query strings, request bodies, and configure API responses. Inputs & Outputs Your endpoints receive data from requests and send back responses. Define the inputs an endpoint expects, attach a function, then use those values from the function steps. The endpoint editor showing input and output configuration Configure inputs and outputs in the endpoint editor Inputs When a request arrives, Spala makes the data available through built-in variables: Path parameters (params) Dynamic segments in the URL path: // Endpoint: GET /api/cases/:id // Request: GET /api/cases/42 params.id // "42" Query string (query) Key-value pairs after the ? in the URL: // Request: GET /api/cases?page=2&limit=10 query.page // "2" query.limit // "10" Good to know Query string and path parameter values are always strings. Convert them with query.page | toNumber when you need a number. Request body (input) The JSON body for POST, PUT, and PATCH requests: // Request: POST /api/cases // Body: { "case_name": "Contract Review", "status": "open" } input.case_name // "Contract Review" input.status // "open" Headers (headers) HTTP headers sent with the request: headers.authorization // "Bearer eyJhbG..." headers['content-type'] // "application/json" File inputs For upload endpoints, add a file input in the endpoint editor and use the generated input in the attached function. This keeps the Playground, generated docs, and implementation in sync. Outputs Use a Return step in your function to set the response: // Return data with a 200 status Value: vars.cases Status: 200 // Return an error with a 404 status Value: { error: "Case not found" } Status: 404 // Return a created resource with 201 Value: vars.newCase Status: 201 Common status codes | Code | Meaning | When to use | |------|------------------|------------------------------------| | 200 | OK | Successful read or update | | 201 | Created | Successfully created a resource | | 400 | Bad Request | Missing or invalid input | | 401 | Unauthorized | Missing or bad authentication | | 404 | Not Found | Resource does not exist | | 500 | Server Error | Something went wrong | Create an Endpoint /endpoints/creating-endpoints Set up your endpoints API Docs /features/api-docs Share endpoint inputs and responses Protect Your Endpoints /endpoints/authentication Add authentication --- title: Protect Your Endpoints route: https://docs.spala.ai/endpoints/authentication/ path: /endpoints/authentication description: Add authentication to your API endpoints with JWT tokens and role-based access. section: endpoints updated: 2026-07-08 --- # Protect Your Endpoints Add authentication to your API endpoints with JWT tokens and role-based access. Protect Your Endpoints Not every endpoint should be public. You can require authentication so only logged-in users (or users with specific roles) can access certain routes. The endpoint editor with the JWT authentication option Enable JWT authentication on any endpoint Require authentication Open the endpoint Go to Endpoints and click the endpoint you want to protect. Set authentication to JWT In the endpoint editor, change Authentication from None to JWT. Save Click Save. The endpoint now requires a valid token in the Authorization header. Clients must include the token like this: Authorization: Bearer eyJhbGciOiJIUzI1NiJ9... If the token is missing or invalid, Spala returns a 401 Unauthorized response automatically. How JWT tokens work JWT (JSON Web Tokens) is a simple way to handle login sessions: 1. A user logs in with their email and password via a public /api/auth/login endpoint 2. Your login function verifies the credentials and creates a token using a Generate Auth Token step 3. The client stores the token and sends it with every request 4. Protected endpoints automatically verify the token before running the function Good to know Tokens contain user data (like id, email, role) and expire after a set time (e.g., 24 hours). No database lookup is needed to verify them. Frontend session contract Frontend builders need the exact session contract generated for the project. At handoff time, document: | Field | Example | | --- | --- | | Login route | POST /api/auth/login | | Signup route | POST /api/auth/register | | Token field | token, accessToken, or data.token | | Protected header | Authorization: Bearer USER_JWT | | Expiry | 24h, 7d, or project-specific | | Refresh route | POST /api/auth/refresh, if implemented | | Logout behavior | Clear local token, revoke server session, or both | | Cookie mode | credentials: "include" if the project uses cookie sessions | | CSRF header | Required only when the project implements CSRF protection | If no refresh route is documented, treat token expiry as a login-required event. If the project uses cookie sessions, browser CORS must also allow credentials and the frontend must use credentials: "include". Cookie-session request example: const response = await fetch(`${SPALA_API_BASE_URL}/api/me`, { credentials: "include", headers: { "X-CSRF-Token": csrfToken, }, }); The CSRF header name, cookie attributes, same-site policy, and logout behavior are project-specific. Document them in the generated API docs or frontend handoff packet before asking an external frontend developer to integrate cookie auth. Cookie checklist for browser clients: | Field | What to confirm | | --- | --- | | SameSite | Lax, Strict, or None; cross-site cookies require SameSite=None | | Secure | Required for cross-site HTTPS cookies | | Domain/path | Which frontend and API hosts receive the cookie | | CSRF source | Meta tag, cookie, endpoint, or generated page value | | Logout | Whether logout expires the cookie, revokes the server session, or both | Built-in endpoint auth vs manual verification Use endpoint-level JWT authentication when an endpoint should be protected before its function runs. This is the usual production path for user-facing APIs because Spala rejects missing or invalid tokens automatically and exposes decoded auth data to the function. Use a manual Verify JWT step inside a function only when the endpoint intentionally accepts mixed public/authenticated traffic, needs to verify a secondary token, or is implementing a custom auth handshake such as a realtime connection or webhook signature. Access the logged-in user in a function When an endpoint has JWT authentication enabled, the decoded token data is available in your function: vars.auth.userId // The user's ID vars.auth.email // The user's email vars.auth.role // The user's role, such as "admin" or "user" Use this to personalize responses or restrict actions: // Only return the current user's cases Database Query: SELECT * FROM cases WHERE client_id = vars.auth.userId Add role-based access For admin-only endpoints, add a role check at the start of your function: // Step 1: Check role If/Else: vars.auth.role !== 'admin' True branch: Return { error: "Admin access required" }, Status: 403 // Step 2: Continue with admin logic... Which endpoints to protect? | Endpoint | Auth | Why | |----------------------|--------|----------------------------------| | POST /api/auth/login | None | Users need to log in | | POST /api/auth/register| None | Users need to sign up | | GET /products | None | Anyone can browse | | POST /products | JWT | Only logged-in users can create | | DELETE /products/:id| JWT | Only admins can delete | | GET /orders | JWT | Users see only their own orders | Never store plain-text passwords Always use the Hash Password step (bcrypt) before saving passwords, and Verify Password when verifying during login. Create an Endpoint /endpoints/creating-endpoints Set up endpoints step by step Inputs & Outputs /endpoints/inputs-outputs Handle request data User Authentication Guide /guides/user-auth Full login and registration setup --- title: AI Copilot route: https://docs.spala.ai/features/ai-assistant/ path: /features/ai-assistant description: The fastest way to build with Spala — describe what you need in plain English and the AI builds your entire backend. section: features updated: 2026-07-08 --- # AI Copilot The fastest way to build with Spala — describe what you need in plain English and the AI builds your entire backend. AI Copilot The fastest way to build with Spala. Describe what you need in plain English and the AI creates your database tables, functions, and API endpoints in seconds. This is how most people build with Spala Skip the step-by-step setup. Tell the AI Copilot what you want, review the changes, and apply. The AI Copilot panel open in Build mode showing context tabs and prompt area Open the AI Copilot (⌘J) and describe what you want to build Build a complete feature in 30 seconds Describe what you need Open the AI Copilot with ⌘J (or click the AI button in the header) and type what you want. Be as specific as you like: > "I need a booking system where users can reserve time slots, cancel bookings, and get email confirmations. Each booking has a date, time, duration, and status." The AI understands your intent and figures out the right tables, functions, and endpoints. Review the diff The AI generates a complete set of changes and shows them as a diff, exactly like a pull request. You see every table, function, and endpoint that will be created or modified. Nothing changes until you approve it. Apply with one click Click Apply to add the feature to your project draft: tables created, functions wired up, endpoints ready to test. Test it in the Playground, then publish when you are ready. If Autopublish is enabled, Spala can publish after applying. What the AI Copilot creates for you A single prompt can generate: - Database tables with the right fields, types, and relationships - Functions with queries, conditions, validation, and error handling - API endpoints with proper methods, paths, and authentication - Addon integrations like email notifications or payment processing The AI Copilot showing a diff of proposed changes with tables and endpoints The AI generates a full diff — review every change before applying Context tabs The AI Copilot shows your project context across several tabs at the top of the panel: - General — Project-wide settings and overview - Data — Database tables and relationships the AI considers - Functions — Existing backend logic the AI can reference or extend - API — Current endpoints and routes - Tasks — Scheduled and background tasks - Triggers — Database change triggers and event handlers These tabs let you see exactly what context the AI has when generating changes. The AI reads your entire project structure to produce accurate, compatible output. Additional Context Click Additional Context (below the context tabs) to add custom instructions that are included in every AI request. Use this for: - Coding conventions ("Always add created_at and updated_at timestamps") - Business rules ("All prices should be stored in cents") - Tech stack preferences ("Use the email addon for notifications") The Additional Context text area expanded in the AI Copilot panel Add custom context that the AI includes in every request Copilot settings Click the ⋮ menu in the copilot header to configure: | Setting | What it does | |---|---| | PRO mode | Uses a more capable AI model for complex prompts | | Autopublish | Automatically publishes changes after applying (skips the manual publish step) | | Test with AI | Has the AI review its own generated changes for quality before you apply | You can also toggle PRO mode and Test with AI directly from the badges below the context tabs. Write better prompts The more context you give, the better the result: | Good prompt | Why it works | |---|---| | "A tasks table with title, status, priority, due_date, and assigned_to (references users)" | Specifies fields and relationships | | "When a task is marked complete, send an email to the project owner" | Describes behavior, not implementation | | "GET /api/tasks should support filtering by status and sorting by due_date" | Specifies API contract | | "If the time slot is already booked, return a 409 error" | Includes edge cases | AI Copilot + manual editing The AI Copilot is your starting point, not a replacement for the visual editor. A typical workflow: 1. AI Copilot creates the feature scaffolding (tables, functions, endpoints) 2. Visual editor lets you fine-tune individual steps and conditions 3. Code view gives you full JavaScript control when you need it You can also use the AI Copilot to modify existing features: "Add pagination to the list products endpoint" or "Add a discount_code field to the orders table." When to use what | Start with AI Copilot | Build manually | |---|---| | New features from scratch | Fine-tuning an existing function | | Standard patterns (CRUD, auth, search) | Complex custom business logic | | Rapid prototyping | Precise control over every step | | Setting up database + endpoints together | Working with niche addon configurations | Ask questions about your project The AI Copilot in Ask mode for querying your project Switch to Ask mode to chat about your project Switch to Ask mode to chat with the AI about your project. Ask things like: - "Which endpoints use the orders table?" - "How does the login flow work?" - "What addons are installed?" The AI searches across your entire project to give you accurate, referenced answers. AI Data Access By default, Ask mode only sees your project structure (tables, functions, endpoints). To let the AI query actual data from your database, enable AI Data Access in Settings > AI. The AI Data Access settings page showing table access configuration Configure which tables and fields the AI can query in Ask mode With Data Access enabled, you can ask questions like: - "How many users signed up this week?" - "Show me the last 10 orders with status 'pending'" - "What is the average order value?" You control exactly which tables and fields the AI can access: - Enable/disable per table — Toggle access for each table individually - Field-level control — Select which fields the AI can see (exclude sensitive columns like password hashes) - Max rows per table — Limit how many rows the AI can query (default: 20) - Allow Aggregates — Enable COUNT, SUM, AVG, MIN, MAX queries AI Data Access uses read-only SELECT queries only. The AI cannot modify, insert, or delete data. Review which fields you expose — avoid granting access to columns with sensitive information. Quality review After the AI generates changes, toggle Test with AI to have it review its own work. The AI: - Scores each generated item for quality - Identifies gaps (missing validation, error handling, edge cases) - Suggests fixes you can apply with one click This catches issues before you apply changes to your project. Quick Start /getting-started/quickstart Build your first API step by step Lite Mode /features/lite-mode Use the Copilot workspace and project graph Addons /addons Add payments, email, AI, and more to your functions --- title: API Docs route: https://docs.spala.ai/features/api-docs/ path: /features/api-docs description: Share generated endpoint docs, OpenAPI, SDK files, and snippets with humans or AI frontend builders. section: features updated: 2026-07-08 --- # API Docs Share generated endpoint docs, OpenAPI, SDK files, and snippets with humans or AI frontend builders. API Docs API Docs turns your Spala endpoints into shareable contracts. Use it when a frontend developer, AI coding agent, or external integration needs to know what routes exist and how to call them. API Docs cover REST Generated API Docs, OpenAPI JSON, and SDK files are the source of truth for REST endpoints. They may not describe realtime channel protocol, direct-to-storage upload CORS, required signed-upload PUT headers, cookie/CSRF details, refresh/logout behavior, OAuth callback URLs, or mobile app resume behavior. Include those details in the External Frontend Handoff when the project uses them. What You Can Share Swagger UI Interactive browser explorer for testing live endpoints. /features/api-docs Markdown Docs Readable endpoint documentation that works well as AI context. /features/api-docs OpenAPI JSON Machine-readable API contract for tools and clients. /features/api-docs SDK Generated JavaScript or TypeScript client helpers for your published API. /features/api-docs Webflow Snippets Embed-ready snippets for no-code or lightweight frontend pages. /features/api-docs Generated Artifact Routes Settings → API Docs is the easiest way to copy or export the contract. Authenticated project tooling can also request these generated routes from the project base URL: | Artifact | Route | Notes | | --- | --- | --- | | Markdown docs | GET {{PROJECT_BASE_URL}}/api/__internal/docs | Builder-authenticated source for humans and AI agents | | JSON docs | GET {{PROJECT_BASE_URL}}/api/__internal/docs?format=json | Structured project docs with full URLs | | OpenAPI JSON | GET {{PROJECT_BASE_URL}}/api/__internal/docs/openapi.json | Use for API clients, Swagger, and codegen | | TypeScript SDK | GET {{PROJECT_BASE_URL}}/api/__internal/docs/sdk.ts | Generated client helpers for the current project | | Public Markdown docs | GET {{PROJECT_BASE_URL}}/api/docs | Available only when public API docs are enabled | | Public JSON docs | GET {{PROJECT_BASE_URL}}/api/docs?format=json | Available only when public API docs are enabled | | Swagger UI | Settings → API Docs | Dashboard UI; use a direct route only if the selected project explicitly exposes one | If the generated docs show a base URL with a scoped path, keep it exactly as shown. Do not derive or shorten project URLs from the project name. Why It Matters Generated docs reduce the gap between backend and frontend work. Instead of explaining routes manually, you can share the current API contract, let an AI frontend builder read it, and keep implementation details tied to the project state. Use docs before frontend work After publishing backend changes, open Settings > API Docs and share the Markdown, OpenAPI JSON, or SDK with the person or agent building the UI. Recommended Workflow 1. Build or update endpoints in Spala. 2. Test them in the Playground. 3. Publish the backend. 4. Open Settings > API Docs. 5. Share the best format for the consumer: Markdown for AI, Swagger for manual testing, OpenAPI for tooling, SDK for app code. 6. Add separate handoff details for realtime, signed uploads, cookies/CSRF, refresh/logout, mobile callbacks, and CORS when those features are used. Public Docs Switch The internal generated docs require builder authentication. Public GET /api/docs is available only when public API docs are enabled in project security settings. Leave public docs off for private APIs unless you intentionally want unauthenticated consumers to read the contract. API Playground /features/playground Test endpoints before sharing docs Frontend App /features/frontend-app Host the app UI that consumes the API API Endpoints /endpoints Create the routes that appear in generated docs External Frontend Handoff /guides/frontend-handoff Copy the complete packet for frontend builders --- title: API Playground route: https://docs.spala.ai/features/playground/ path: /features/playground description: Test your endpoints right in the browser — no Postman or curl needed. section: features updated: 2026-07-08 --- # API Playground Test your endpoints right in the browser — no Postman or curl needed. API Playground Test your endpoints right in the browser — no Postman or curl needed. The API Playground ready to send a request Select an endpoint, set parameters, and send a request to see the response. How to use the Playground Select an endpoint Open the Playground screen and pick an endpoint from the dropdown. The method, path, and any path parameters are filled in automatically. Set your request Add path parameters, query parameters, authentication, body fields, or file uploads depending on what your endpoint expects. Send and inspect Click Send. The response appears below with status, timing, output, and logs so you can see exactly what your endpoint returned. Pro tip The Playground auto-fills your endpoint's path and method. Just add your data and send. Testing authenticated endpoints For endpoints protected with JWT authentication, use the Playground authentication field: 1. First, call your login endpoint to get a token 2. Copy the token from the response 3. Paste the token into the authentication field 4. Now you can test any protected endpoint Good to know Draft or modified endpoints may need to be published before the Playground can call the live route. What To Check - Required path parameters are filled in - Query parameters are converted to the types your function expects - Auth tokens are present for protected endpoints - File uploads match the endpoint input shape - Logs explain failures before you publish or connect a frontend Build a REST API /guides/build-rest-api Create endpoints to test Add User Authentication /guides/user-auth Set up JWT tokens for protected endpoints Publish /features/publish-export Publish your tested endpoints --- title: CI/CD route: https://docs.spala.ai/features/ci-cd/ path: /features/ci-cd description: Configure deploy hooks or approved project artifact delivery after publishing. section: features updated: 2026-07-08 --- # CI/CD Configure deploy hooks or approved project artifact delivery after publishing. CI/CD CI/CD connects a published Spala project backend to a deployment workflow. It can trigger external deploy hooks or deliver approved project artifacts when enabled for the account. It does not grant Spala dashboard, builder, or platform source code. Verify runtime packaging, portability, self-hosting, support, and migration terms before relying on an external deployment path. Generated Project Artifact The generated project artifact is the backend artifact for one Spala project. It represents the published project API behavior: route handlers, function logic, runtime configuration, docs metadata, and the environment-variable contract needed by that project. It is not the Spala dashboard, visual builder, platform auth system, or Spala source repository. Hosted Publish is the normal path for most users. CI/CD is the advanced path when your team wants the generated project artifact delivered to your configured deployment target when enabled for your account or deploy provider. Feature availability depends on the generated project artifact package and the target environment you configure, so test the target with dry run before treating it as production. Delivery Boundary | Action | What changes | Where it runs | | --- | --- | --- | | Publish backend API | Hosted project API behavior becomes live | Spala-managed project API | | Publish frontend app | Static UI assets become live | Spala frontend hosting for the project | | Deploy generated project artifact | Generated project runtime is delivered outside the default hosted publish path | Your server or external deploy provider | Supported Target Types - SSH server - SFTP server with SSH commands - Vercel deploy hook - Render deploy hook - Netlify deploy hook - Railway deploy hook - Custom webhook Recommended Workflow Publish the backend First publish the project so the generated backend state is ready. Add a deployment target Open Settings > CI/CD, choose a provider, and enter the target credentials or deploy hook URL. Run a dry run Use dry run to check the bundle and target configuration before deploying. Deploy Deploy manually, or enable auto-deploy after publish when the target is stable. Project deployment only CI/CD is for deploying your generated project backend or triggering your configured deployment target when enabled for your account. It is not a guide for running the Spala dashboard or platform. Why Users Care Some teams want Spala to build and validate the backend while their production deployment workflow remains in their configured cloud or deployment workflow. CI/CD keeps that path explicit and repeatable. Publish /features/publish-export Publish project changes before deployment Project Snapshots /features/project-snapshots Create checkpoints before large deploys Environment Variables /settings Store deploy and runtime values safely --- title: Editor Workspace route: https://docs.spala.ai/features/editor-workspace/ path: /features/editor-workspace description: Use tabs, search, view modes, Ask AI, Try, compare, save, version history, and run history while editing Spala resources. section: features updated: 2026-07-08 --- # Editor Workspace Use tabs, search, view modes, Ask AI, Try, compare, save, version history, and run history while editing Spala resources. Editor Workspace The editor workspace is where direct resource editing happens. Open tables, functions, endpoints, tasks, triggers, and channels from the sidebar, search palette, project graph, or overview cards. Spala function editor with Gherkin, Visual, Split, and Code view modes Function editors can switch between readable, visual, split, and code views. Open Resources As Tabs Spala keeps resources open as editor tabs so you can move between related work without losing context. - Pin important tabs so they stay open - Drag tabs to reorder your working set - Close one tab, tabs to the left or right, or every other tab - Use the modified indicator to spot unsaved work - Return to recently opened resources from search Editor Header Actions View Modes Switch between Gherkin, Visual, Split, and Code when the resource supports them. /flows/code-view Remember View Save your preferred view mode so future resources open the way you work. /getting-started/interface Ask AI Ask the Copilot about the resource or request a targeted change. /features/ai-assistant Try Run an endpoint, function, task, or supported resource with sample input. /flows/debugging Compare Review pending changes before saving or publishing. /features/pull-requests Save Controls Save, discard, or revert unpublished changes from the change bar. /features/publish-export Spala Code view showing JavaScript for a backend function Code view is available when you need direct JavaScript control. Resource Menu The resource menu exposes actions that are useful during review and recovery: - Edit - rename or adjust resource metadata - Versions - inspect resource history - Runs - open run and execution history - Export JSON - download the resource definition for review or support - Revert to Published - discard draft changes and return to the live version - Delete - remove the resource, with dependency checks where needed Search Palette Press Cmd+K or Ctrl+K to open search. Search covers tables, functions, endpoints, tasks, triggers, and channels. When the query is empty, Spala shows recent resources first. | Prefix | Searches | |--------|----------| | @t, @table | Tables | | @f, @fn, @function | Functions | | @e, @endpoint | Endpoints | | @tk, @task | Tasks | | @tr, @trigger | Triggers | | @ch, @channel | Channels | Use search for speed The fastest way to jump into a known resource is usually Cmd+K or Ctrl+K, then a type prefix and part of the name or route. The Interface /getting-started/interface Learn the main Spala screens Project Overview /features/project-overview Inspect the whole backend before opening editors AI Copilot /features/ai-assistant Ask for changes from the editor Try & Runs /flows/debugging Run resources and inspect execution output --- title: Frontend App route: https://docs.spala.ai/features/frontend-app/ path: /features/frontend-app description: Publish a static frontend UI to your project URL, preview it first, and roll back if needed. section: features updated: 2026-07-08 --- # Frontend App Publish a static frontend UI to your project URL, preview it first, and roll back if needed. Frontend App Frontend App lets you host a static user interface next to the backend you built in Spala. Use it when your project needs a simple deployed app UI without wiring another hosting service first. What It Helps With - One project URL - keep the backend API and app UI connected to the same Spala project. - Preview before frontend publish - upload a build, inspect the preview URL, then publish the frontend app only when it looks right. - Agent handoff - copy instructions for an AI coding agent so it can build and upload the frontend package. - Rollback - restore the previous frontend app if the new upload is not correct. - Cleanup - remove old staged uploads after review. Publish A Frontend App Frontend App Use this screen when you already have a static build ZIP or want to give an agent upload instructions. Upload or use agent mode Upload a ZIP manually, or copy the agent instruction and let an AI coding tool prepare the build. Preview Spala validates the upload and returns a preview URL. Check routing, API calls, login behavior, and mobile layout before publishing. Publish frontend app Click Publish in Frontend App to make the staged UI live for the project. This publishes static frontend assets; backend API changes still use Publish backend API. Delivery Boundary | Action | What changes | Where it lives | | --- | --- | --- | | Publish backend API | Tables, functions, endpoints, tasks, triggers, agents, channels, settings, and generated API behavior | Project API base URL | | Publish frontend app | Static UI files uploaded through Frontend App | Project frontend URL | | Deploy generated project artifact | Generated project runtime sent to an external target | Your server or deploy provider | Backend first, frontend next Spala is still the source of truth for your backend: tables, auth, endpoints, functions, tasks, triggers, docs, and MCP. Frontend App gives that backend a hosted UI when you need one. When To Use It Use Frontend App for product demos, internal tools, client portals, and AI-generated app UIs that call your Spala endpoints. If you already host your frontend on Vercel, Netlify, or another provider, you can keep doing that and use Spala only for the backend API. API Docs /features/api-docs Give frontend builders the generated API contract Publish /features/publish-export Publish backend changes before connecting the frontend MCP /agents/mcp Let agents resolve the right project MCP before working --- title: Lite Mode route: https://docs.spala.ai/features/lite-mode/ path: /features/lite-mode description: Use Spala's Copilot workspace to inspect a backend, ask for changes, and jump into focused tools without opening the full builder. section: features updated: 2026-07-08 --- # Lite Mode Use Spala's Copilot workspace to inspect a backend, ask for changes, and jump into focused tools without opening the full builder. Lite Mode Lite mode is Spala's Copilot-first workspace. It keeps the AI Copilot, project graph, high-level resource counts, base API URL, frontend status, and common actions visible so you can understand and change a project without navigating every builder screen. Spala Lite mode showing the AI Copilot and project graph Lite mode keeps the Copilot and project graph visible together. What Lite Mode Shows AI Copilot Build or ask about the backend from the left panel. /features/ai-assistant Project Graph Inspect tables, endpoints, functions, and relationships visually. /features/lite-mode Resource Cards See tables, endpoints, functions, tasks, agents, triggers, and publish state at a glance. /getting-started/interface Base API URL Copy the project API URL when connecting a frontend, integration, or coding agent. /features/api-docs Frontend Status Check whether a hosted frontend exists and jump to frontend app controls. /features/frontend-app Mode Switch Move between Lite and Advanced mode from the header. /getting-started/interface Tools Menu Open environment, docs, auth, MCP, settings, and publish tools from one compact menu. /settings What You Can Do From Lite Mode - Ask Copilot to create or change project resources - Review the project network before opening detailed editors - Copy the base API URL for frontend and integration work - See drafts, recent activity, and publish readiness - Jump into API docs, MCP, environment, auth, frontend app, snapshots, or settings When To Use Advanced Mode Use Advanced when you need the full visual builder: detailed table editing, endpoint configuration, function/code view, task and trigger editing, addons, pull requests, and low-level settings. Spala Advanced mode project overview with sidebar navigation Advanced mode exposes the full builder navigation and resource editors. Switch without losing context The mode switch changes the product surface, not the project. Start with the Copilot workspace and switch to Advanced when you need direct control over a specific resource. AI Copilot /features/ai-assistant Build and inspect a backend with AI The Interface /getting-started/interface Learn the main Spala screens Settings /settings Configure project, AI, MCP, docs, environment, and deployment settings --- title: Project Agents route: https://docs.spala.ai/features/project-agents/ path: /features/project-agents description: Build project-native agents that run manually, from chat, webhooks, schedules, database changes, or realtime events. section: features updated: 2026-07-08 --- # Project Agents Build project-native agents that run manually, from chat, webhooks, schedules, database changes, or realtime events. Project Agents Project Agents are automations that live inside a Spala project. They are different from external AI coding agents connected through MCP: project agents are part of the backend you build and can run workflows for your app. Spala Project Agents screen with builder, chat, activity, timeline, settings, and metrics Project Agents include builder, chat, activity, timeline, settings, and metrics views. Trigger Types Manual Run the agent yourself or start it from chat. /features/project-agents Webhook Trigger the agent from an HTTP request. /features/project-agents Schedule Run the agent on a repeat schedule. /features/project-agents Database Changes React when project data is inserted, updated, or deleted. /features/project-agents WebSocket Respond to realtime messages and channel events. /features/project-agents What Agents Include - Builder - create or inspect the agent workflow. - Chat - run an agent conversationally with live input. - Activity - review recent executions, statuses, and output. - Timeline - inspect a step-by-step run timeline. - Settings - configure triggers, required environment variables, retry behavior, and execution limits. - Metrics - track active agents, execution volume, success rate, and errors. Project agents vs MCP agents MCP agents are external tools like Codex, Claude, or Cursor that help build the backend. Project Agents are backend automations inside your Spala project. When To Use Project Agents Use project agents for recurring operational workflows, webhook handlers, internal assistants, data-change responders, and automations that need a visible execution history. AI Agents & MCP /agents Connect external coding agents to build with Spala Scheduled Tasks /tasks/scheduled-tasks Use tasks for simpler scheduled functions Triggers /triggers Run logic directly from database events --- title: Project Memory route: https://docs.spala.ai/features/project-memory/ path: /features/project-memory description: Save durable project context so Copilot, repair flows, publish review, frontend generation, and MCP agents stay aligned. section: features updated: 2026-07-08 --- # Project Memory Save durable project context so Copilot, repair flows, publish review, frontend generation, and MCP agents stay aligned. Project Memory Project Memory stores durable context for one generated project. Use it for decisions, constraints, preferences, warnings, and facts that AI should remember across future Copilot runs, repairs, publish reviews, frontend generation, and MCP agent work. What To Save - Business rules: "Invoices must be immutable after payment." - Data constraints: "Never expose password digest fields to AI data access." - Architecture decisions: "Use Stripe Checkout, not Payment Intents, for hosted checkout." - Frontend expectations: "The client portal is mobile-first and uses email login." - Deployment notes: "Production deploys through the configured Render hook." How It Works Add memory Open Settings > Project Memory and write the fact, decision, constraint, preference, or warning. Set scope Choose a scope such as project, auth, frontend, deployment, data, agent, or resource. Approve or pin important items Approved active memories can be used by AI. Pinned memories stay easy to find for critical context. Archive old context Archive memory that is no longer true. Archived items remain available for audit but are ignored by AI. Memory should be true and useful Do not store secrets in Project Memory. Put API keys and private values in Environment variables or addon settings. Why Users Care AI gets better when it has stable product context. Project Memory prevents the same explanations from being repeated and helps different agents respect the same project rules. AI Copilot /features/ai-assistant Use memory as context for generation and Ask mode MCP /agents/mcp Give authenticated agents the right project context Settings /settings Find Project Memory in the settings modal --- title: Project Overview route: https://docs.spala.ai/features/project-overview/ path: /features/project-overview description: Use the project overview to inspect your backend, copy connection details, review drafts, and jump into the right editor. section: features updated: 2026-07-08 --- # Project Overview Use the project overview to inspect your backend, copy connection details, review drafts, and jump into the right editor. Project Overview The Project Overview is the first place to check what Spala has built. It shows your backend resources, publish state, base API URL, frontend status, recent activity, and the project graph in one place. Spala Project Overview showing tables, endpoints, functions, tasks, and publish controls Project Overview gives you a scan-friendly view of the backend before you open detailed editors. What You Can See Base API URL Copy the URL your frontend, integrations, or agents should call. /features/api-docs Resource Cards Review tables, endpoints, functions, and tasks with important fields and routes visible. /getting-started/interface Endpoint Summary See the API routes that exist and jump into the full endpoint list when needed. /endpoints Frontend Status Check whether a hosted frontend exists and open frontend app controls. /features/frontend-app Draft Changes Spot unpublished work before you publish the live API. /features/publish-export Recent Activity Review recent edits and operational events without leaving the overview. /features/project-overview Project Network The Project Network tab shows how the project fits together: tables, endpoints, functions, tasks, agents, triggers, channels, and auth-related nodes. Use it to understand dependencies before changing or deleting resources. Spala Project Network graph showing connected backend resources The project graph helps you find related resources and navigate from a high-level map. From the graph you can: - Inspect connected resources before making changes - Open a quick view for a node - Jump from the graph into the resource editor - Check whether an endpoint, trigger, task, or agent depends on another resource - Explain the project structure to a teammate or AI agent Agents Tab The overview also gives quick access to project agents. Use this when you want to run or inspect an automation without leaving the project context. Spala Project Agents screen with builder, chat, activity, timeline, and settings tabs Project agents can be built, run from chat, reviewed in activity logs, and inspected through timeline and metrics views. Overview first, editor second Start from Project Overview when you need to understand the whole backend. Open a focused editor when you need to change a table, endpoint, function, task, trigger, agent, or setting. Lite Mode /features/lite-mode Use the Copilot workspace and project graph Editor Workspace /features/editor-workspace Use tabs, view modes, Ask AI, Try, and save controls Publish /features/publish-export Review and publish draft changes Project Agents /features/project-agents Build backend automations inside your project --- title: Project Snapshots route: https://docs.spala.ai/features/project-snapshots/ path: /features/project-snapshots description: Create checkpoints, inspect diffs, and restore a full draft or selected resources after larger changes. section: features updated: 2026-07-08 --- # Project Snapshots Create checkpoints, inspect diffs, and restore a full draft or selected resources after larger changes. Project Snapshots Project Snapshots are checkpoints for a Spala project draft. Use them before larger AI changes, refactors, imports, or deployments so you can inspect what changed and restore safely. What Snapshots Help With - Review changed tables, functions, endpoints, tasks, triggers, channels, and agents. - Restore the full draft state after a bad change. - Restore selected resources without undoing everything else. - Keep an audit trail of important project checkpoints. Create And Restore Snapshots Use this screen before a large Copilot run, agent edit, or manual refactor. Create a snapshot Add a short checkpoint message so future you knows why the snapshot exists. Inspect the diff Select a snapshot to see which resources changed. Restore carefully Restore the whole draft or only selected resources, then review and publish when ready. Snapshot before broad AI edits Before asking Copilot or an MCP agent to change many resources, create a snapshot. It gives you a clean recovery point if the result is not what you wanted. AI Copilot /features/ai-assistant Create checkpoints before large AI changes Publish /features/publish-export Review and publish after restore or edit Pull Requests /features/pull-requests Route changes through review before merge --- title: Publish route: https://docs.spala.ai/features/publish-export/ path: /features/publish-export description: Review your generated backend changes and publish them as a live API from the Spala dashboard. section: features updated: 2026-07-08 --- # Publish Review your generated backend changes and publish them as a live API from the Spala dashboard. Publish Publishing makes your current Spala project changes live. When you publish, Spala applies the project draft and updates the API your frontend or integrations call. The Spala publish dialog Review pending changes before publishing your backend. Publishing Changes Build or edit your backend Use AI Copilot, Lite mode, or Advanced mode to create or change tables, functions, endpoints, tasks, triggers, channels, addons, and settings. Review the draft Check the project graph, endpoint list, Playground, settings, and generated API docs before publishing. Click Publish Click Publish in the top bar. Spala applies the changes and updates the live API. Test the live API Use the Playground, generated endpoint snippets, or your frontend to confirm the API behaves as expected. No platform deployment required You publish your project from Spala. You do not deploy the Spala platform or manage its runtime infrastructure to use the hosted dashboard. Delivery Boundary | Action | What changes | Who manages it | | --- | --- | --- | | Publish backend API | Project draft becomes the live generated API | You review and approve publish from Spala | | Publish frontend app | Static frontend assets become the live project UI | You upload, preview, and publish from Frontend App | | Deploy generated project artifact | Generated project runtime is delivered to an external target | You configure and operate the external target | The publish dialog showing changes ready to publish Review changes before publishing. Team Review For teams, Spala can route changes through Pull Requests before they go live: - Users with publish permission can publish directly. - Users without publish permission can prepare changes for review. - Reviewers can inspect changed tables, functions, endpoints, and settings before approving. Version History Spala keeps project history so you can: - Review what changed and when - Compare versions of project resources - Recover from mistakes using snapshots and history tools - Understand who made a change before it was published After Publishing After publishing, use the API from: - Your frontend app - API Playground - Generated endpoint snippets - AI agents connected through the selected project MCP API Playground /features/playground Test your endpoints before and after publishing Pull Requests /features/pull-requests Review and approve changes before publish Project Snapshots /features/project-snapshots Create checkpoints before larger changes Build a REST API /guides/build-rest-api Create endpoints to publish Spala Public MCP /agents/mcp Connect AI agents through project handoff --- title: Pull Requests route: https://docs.spala.ai/features/pull-requests/ path: /features/pull-requests description: Review backend changes before they merge into the project draft or become publishable. section: features updated: 2026-07-08 --- # Pull Requests Review backend changes before they merge into the project draft or become publishable. Pull Requests Pull Requests give teams a review path for Spala changes. Use them when a user or AI agent prepares backend changes that should be inspected before merging or publishing. Spala Pull Requests screen showing review status, changed resources, comments, and actions Pull Requests give AI and human changes a review path before they merge into the project draft. What You Can Review - Changed database tables and fields - Updated functions and backend logic - Endpoint method, path, auth, and response changes - Scheduled or background task changes - Trigger, channel, and agent changes when included in a PR - Comments, approvals, and requested changes - AI review comments and AI-generated fix PRs - Draft, open, approved, merged, declined, and needs-rebase states Review Workflow Open Pull Requests Use the Pull Requests screen from Advanced mode when changes need team review. Inspect the diff Review changed models, functions, endpoints, tasks, and comments before merging. Use AI review when useful Ask AI to review the PR for missing validation, broken assumptions, or obvious backend issues. Approve, request changes, or merge Merge approved work into the project draft, then publish when the live API should change. Clean up old review work Close, reopen, delete, or bulk-delete PRs when they are no longer needed. Useful for agent work Pull Requests are especially useful when an MCP agent or Copilot makes a broad change. They give humans a clear review point before anything becomes live. Publish /features/publish-export Make reviewed changes live Project Snapshots /features/project-snapshots Keep checkpoints around larger changes MCP /agents/mcp Let agents work through the project MCP --- title: Team Access route: https://docs.spala.ai/features/team-access/ path: /features/team-access description: Manage builder users, roles, permissions, and secure access to the Spala project dashboard. section: features updated: 2026-07-08 --- # Team Access Manage builder users, roles, permissions, and secure access to the Spala project dashboard. Team Access Team Access controls who can use the Spala builder and what they can do. Use it when a project has multiple builders, reviewers, or operators. What You Manage - Builder users who can access the project dashboard - Roles and permissions for editing, publishing, settings, data, and review actions - Authentication and security settings for builder access - Trash and restore permissions for deleted resources Why Users Care Backend builders need different levels of access. A developer may need to edit functions, a reviewer may only approve changes, and an operator may only inspect logs or data. Roles keep those responsibilities separate. Give publish permission deliberately Publishing changes the live API. Keep publish access limited to users who should be able to affect production behavior. Related Settings - Users & Roles - invite or manage dashboard users and permissions. - Security - configure origins, trusted hosts, tokens, and request controls. - Trash Bin - restore deleted resources or permanently remove them. Settings /settings Open Users & Roles and Security settings Pull Requests /features/pull-requests Review changes before merge or publish Publish /features/publish-export Understand what publish permission controls --- title: Use AI Copilot route: https://docs.spala.ai/features/templates/ path: /features/templates description: Build from a plain-language prompt instead of choosing a starter pattern. section: features updated: 2026-07-08 --- # Use AI Copilot Build from a plain-language prompt instead of choosing a starter pattern. Use AI Copilot The recommended way to start a Spala project is the AI Copilot. Describe the backend you need in plain language, review the generated tables, functions, endpoints, and settings, then publish when it looks right. Start with a prompt You do not need to choose a starter pattern first. Tell Spala what the app should do, then refine the generated backend with Copilot, Lite mode, or Advanced mode. AI Copilot /features/ai-assistant Describe what you want and let Spala build it Lite Mode /features/lite-mode Use the Copilot workspace and project graph Quick Start /getting-started/quickstart Build a simple API from the dashboard --- title: Code View route: https://docs.spala.ai/flows/code-view/ path: /flows/code-view description: Use JavaScript alongside Spala's Gherkin, Visual, and Split views. section: flows updated: 2026-07-08 --- # Code View Use JavaScript alongside Spala's Gherkin, Visual, and Split views. Code View Use JavaScript alongside Spala's Gherkin, Visual, and Split views. Built-in steps round-trip cleanly between visual views and code; custom JavaScript is preserved as Custom Code when it cannot be represented as a built-in step. The code view showing JavaScript for a function Every function has a Code tab next to Gherkin, Visual, and Split. How to switch 1. Open any function in the editor 2. Click the Code tab at the top 3. Edit the JavaScript directly 4. Switch back to Gherkin, Visual, or Split to review the function visually Pro tip Built-in steps stay connected across visual views and code. Unsupported JavaScript is preserved as Custom Code so you do not lose work. What it looks like Here is how common steps translate to JavaScript: Set Variable: let greeting = "Hello, " + input.name; Database Query: let cases = await db.query("SELECT * FROM cases WHERE client_id = $1", [vars.user.id]); If/Else: if (vars.cases.length === 0) { return { message: "No cases yet" }; } Loop: for (let caseRecord of vars.cases) { // steps inside the loop } When to use code view - Complex expressions — Multi-line logic that is awkward in the properties panel - Rapid prototyping — Writing code can be faster than dragging steps - Copy-paste — Duplicate logic by copying code blocks - Refactoring — Restructure function logic by editing code directly When to use visual view - Getting an overview — The visual editor shows function structure at a glance - Configuring steps — The properties panel surfaces all options for each step type - Collaboration — Visual functions are easier for non-coders to read and modify Good to know If you write JavaScript that does not map to a built-in step type (like a class definition), it gets wrapped in a Custom Code step. The code is preserved, but appears as a single block in the visual editor. Create a Function /flows/creating-flows Build functions in the visual editor Variables & Data /flows/variables Work with data in both views Try & Runs /flows/debugging Test your functions --- title: Create a Function route: https://docs.spala.ai/flows/creating-flows/ path: /flows/creating-flows description: Step-by-step guide to building backend logic in Spala. section: flows updated: 2026-07-08 --- # Create a Function Step-by-step guide to building backend logic in Spala. Create a Function Functions contain your backend logic. Each function is a reusable sequence of steps that you can attach to endpoints, tasks, triggers, agents, or other functions. Build your first function Go to Functions Click Functions in the left sidebar. Add a new function Click Create Function and give it a descriptive name, like "List Cases" or "Create Order". Choose the right view Start in Gherkin or Visual view to understand the function outline, then switch to Split or Code when you want more detail. Configure each step In Visual view, select a step and fill in its settings. Use Add Step search to find database, API, auth, control-flow, and addon steps. Save Press Ctrl+S (or Cmd+S) to save. Your function is now ready to attach to an endpoint, task, trigger, or agent. The function editor showing inputs, output, and execution outline Start from the readable outline to review inputs, output, and execution path. The editor layout - Gherkin — A readable behavior outline for reviewing what the function does. - Visual — Editable step blocks and inputs. - Split — Visual and Code together. - Code — JavaScript for advanced editing. Common steps to start with | Step | What to use it for | |---------------|-----------------------------------------------------| | Set Variable | Store a value: greeting = "Hello, " + input.name | | Database Query| Read or write data: select, insert, update, delete | | If/Else | Add a condition: if vars.user exists, else 404 | | Return | Send the response: return vars.cases | Good to know A single function can be used by multiple endpoints. You can also call one function from another using a Run Function step. Tips - Duplicate a function — Right-click a function and choose Duplicate to create a copy you can modify. - Name functions descriptively — Use names like "List Cases", "Create Order", "Send Welcome Email" so you can find them quickly. - Keep functions focused — One function per action. If a function gets too long, split it into smaller functions and use Run Function to call them. Variables & Data /flows/variables Set and use variables in your functions Code View /flows/code-view See and edit the JavaScript version Try & Runs /flows/debugging Test your functions with sample data --- title: Try & Runs route: https://docs.spala.ai/flows/debugging/ path: /flows/debugging description: Test functions with sample data, inspect variables, and review execution history. section: flows updated: 2026-07-08 --- # Try & Runs Test functions with sample data, inspect variables, and review execution history. Try & Runs Use Try to test a function with sample data, inspect variables, and review each execution. This helps you catch missing inputs, broken conditions, and unexpected API responses before publishing. Try a function Open the function Go to Functions and open the function you want to test. Click Try Click the Try button in the toolbar. Set test inputs Fill in sample data for the request body, path parameters, or query string - whatever your function expects. Run and inspect Run the function and inspect each step result. The run view shows outputs, variables, and errors. Set breakpoints Breakpoints pause execution at a specific step so you can inspect the variable state. 1. Hover over a step in the editor 2. Click the dot that appears on the left edge 3. A red dot confirms the breakpoint 4. Try the function - it pauses at the breakpoint When paused, you can: | Control | What it does | |---------------|--------------------------------------------------| | Continue | Run until the next breakpoint or the end | | Step Over | Execute just this step, then pause again | | Stop | Cancel the function run | Inspect variables The variable inspector shows every variable and its current value after each step. You can see: - vars — Variables you set during the function run - input — The request body - params — Path parameters - query — Query string values Objects and arrays can be expanded to drill into their contents. Pro tip Use step-by-step execution (click Step Over repeatedly) to walk through a function without setting breakpoints. The inspector updates after each step. Troubleshooting tips Variable is undefined? Check that the step assigning it actually runs. It might be inside an If/Else branch that was not taken. Database query returns empty? Use the variable inspector to check your WHERE condition values. Then verify the data exists using the Data tab in the Database section. API call fails? Inspect the URL, headers, and body in the variable inspector. Check that env variables like API keys are set correctly. Execution history Open Runs from the resource menu to review previous executions. Endpoint, task, trigger, and function runs can include: - Duration, status (success/error), and timestamp - The full request and response data - Step-by-step execution logs - Analyze with AI — click to send an error directly to the AI Copilot for diagnosis Create a Function /flows/creating-flows Build your function Variables & Data /flows/variables Understand the data available to your function Code View /flows/code-view Debug using the JavaScript view --- title: Variables & Data route: https://docs.spala.ai/flows/variables/ path: /flows/variables description: Set variables, access request data, and use expressions in your functions. section: flows updated: 2026-07-08 --- # Variables & Data Set variables, access request data, and use expressions in your functions. Variables & Data Variables store data as your function runs. You create them with Set Variable steps and reference them in any step that follows. The step properties panel showing variable configuration Configure step properties and variables in the right panel Set a variable Use a Set Variable step to create or update a variable: - Variable Name — e.g., greeting, totalPrice, isAdmin - Value — An expression that computes the value | Variable Name | Value | |--------------|-------------------------------------| | greeting | "Hello, " + input.name | | totalPrice | input.price * input.quantity | | isAdmin | vars.user.role === "admin" | Built-in variables Every function has access to these built-in data sources: | Variable | What it contains | Example | |-----------|----------------------------------------------|----------------------------| | vars | Variables you set during the function | vars.cases | | input | The request body (POST, PUT, PATCH) | input.name | | params | URL path parameters | params.id | | query | URL query string parameters | query.page | | headers | HTTP request headers | headers.authorization | | env | Server environment variables | env.JWT_SECRET | Examples // Path: GET /api/cases/:id?include=updates params.id // "42" query.include // "updates" // Body: POST /api/cases { "case_name": "Contract Review" } input.case_name // "Contract Review" // Environment env.API_KEY // Your configured API key Good to know Query string and path parameter values are always strings. Use params.id | toNumber or Number(params.id) when you need a number. Using expressions Expressions let you compute values dynamically. They use JavaScript syntax and work in any step property: // Arithmetic input.price * input.quantity // String concatenation "Hello, " + input.name // Ternary vars.count > 0 ? "found" : "empty" // Access nested data vars.user.address.city vars.products[0].name // Default values input.page || 1 query.limit ? Number(query.limit) : 20 Filters Filters transform values using a pipe (|) syntax. They are a shorthand for common operations: input.email | lowercase | trim query.page | toNumber | default: 1 vars.items | map: "name" vars.name | uppercase Pro tip Check the Filters Reference for the full list of available filters. Variable scoping - Variables are scoped to the current function execution - A variable set inside an If/Else branch is still accessible after the branch - Each request creates a fresh context — variables do not leak between requests Create a Function /flows/creating-flows Build your first function step by step Code View /flows/code-view See variables as JavaScript code Try & Runs /flows/debugging Inspect variable values at each step --- title: Addons route: https://docs.spala.ai/addons/ path: /addons description: Extend your backend with ready-to-use integrations for payments, email, AI, storage, and more. section: general updated: 2026-07-08 --- # Addons Extend your backend with ready-to-use integrations for payments, email, AI, storage, and more. Addons Extend your backend with ready-to-use integrations for payments, email, AI, storage, and more. Addons marketplace showing available integrations Browse and install addons from the marketplace. How addons work Enable an addon and new steps appear in your flow editor. Configure them with your API keys and common requests are preconfigured, so you spend less time wiring provider APIs by hand. For example, enabling the Stripe addon gives you steps like "Create Payment Intent" and "Create Customer." Enabling OpenAI gives you AI steps for text and image workflows. Each step handles authentication, request formatting, and error handling for you. Popular addons Stripe Accept payments, manage subscriptions, and handle refunds. /addons/catalog/stripe OpenAI Add AI chat, text generation, and image creation to your API. /addons/catalog/openai SendGrid Send transactional and marketing emails at scale. /addons/catalog/sendgrid AWS S3 Store and serve files in the cloud. /addons/catalog/aws-s3 Twilio Send SMS messages. /addons/catalog/twilio-sms Slack Send notifications and messages to Slack channels. /addons/catalog/slack-api How to enable an addon Open the Addons screen Go to Addons from the sidebar. Browse the marketplace or search for the addon you need. Click Enable Click the addon card and hit Enable. The addon's steps are now available in your flow editor. Add your API key Go to Settings > Environment Variables and add the API key the addon needs (e.g., STRIPE_SECRET_KEY). Each addon's page tells you which variables to set. All addons Anthropic Claude AI models for message generation. /addons/catalog/anthropic AWS S3 Store and serve files in the cloud. /addons/catalog/aws-s3 Discord Send messages and notifications to Discord channels. /addons/catalog/discord Firebase Auth Verify Firebase ID tokens and manage users. /addons/catalog/firebase-auth GitHub Interact with repositories, issues, and pull requests. /addons/catalog/github HTML to PDF Generate PDF documents from HTML templates. /addons/catalog/html-to-pdf HubSpot Manage contacts, deals, and CRM data. /addons/catalog/hubspot Image Processing Resize, crop, convert, and transform images. /addons/catalog/image-processing Jira Create and manage Jira issues and projects. /addons/catalog/jira Local Storage Read and write project files in managed storage. /addons/catalog/local-storage Notion Create pages, query databases, and manage content. /addons/catalog/notion OpenAI AI chat, text generation, and image creation. /addons/catalog/openai QR Code Generate QR codes as images or data URIs. /addons/catalog/qr-code Redis Cloud Caching, session storage, and pub/sub messaging. /addons/catalog/redis-cloud SendGrid Send transactional and marketing emails at scale. /addons/catalog/sendgrid Shopify Manage products, orders, and customers. /addons/catalog/shopify Slack Send notifications and messages to Slack channels. /addons/catalog/slack-api Stripe Accept payments, manage subscriptions, and refunds. /addons/catalog/stripe Supabase Database queries, authentication, and storage. /addons/catalog/supabase Twilio SMS Send SMS messages. /addons/catalog/twilio-sms Need a custom integration? Start with the built-in External API Call step, webhooks, or AI Copilot. If you need a reusable integration that is not in the catalog, contact Spala support. Installing Addons /addons/installing Enable and configure addons in your project External API Steps /reference/steps/api Call services that are not in the addon catalog AI Copilot /features/ai-assistant Ask Spala to wire an integration into your backend --- title: AI Agents & MCP route: https://docs.spala.ai/agents/ path: /agents description: Connect AI coding agents to Spala through the public MCP, authenticate with Spala, select a project, and hand off to the project MCP. section: general updated: 2026-07-08 --- # AI Agents & MCP Connect AI coding agents to Spala through the public MCP, authenticate with Spala, select a project, and hand off to the project MCP. AI Agents & MCP Spala exposes a public MCP endpoint for AI coding agents that need to discover Spala, authenticate with the Spala platform, select a project, and hand off to the selected project MCP. The public endpoint is: https://mcp.spala.ai/mcp Spala also publishes machine-readable MCP discovery at: https://spala.ai/.well-known/mcp.json Do not guess project MCP URLs Project MCP URLs are resolved after Spala platform authentication from project/access-url data. Do not hardcode patterns like https://api.spala.ai/{project}/mcp. Public MCP vs project MCP | MCP surface | Purpose | | --- | --- | | https://mcp.spala.ai/mcp | Public discovery, OAuth metadata, agent onboarding, authenticated project lookup, project handoff | | Project MCP | Backend work for one project: inspect context, make changes, validate, publish, and review | | OAuth authorization server | Discovered from the MCP OAuth metadata. Do not configure it manually as the MCP server URL. | Project creation status project_create is dry-run only in the current public MCP deployment. It previews project creation but does not create a real project. Start here Public MCP Understand the discovery, authentication, project selection, and handoff flow. /agents/mcp Codex Setup Add Spala Public MCP to Codex and start with onboarding/tool-map calls. /agents/codex Claude Setup Add Spala Public MCP to Claude Code over HTTP transport. /agents/claude Cursor Setup Use the same public MCP URL and let Spala resolve project MCP after auth. /agents/cursor Gemini CLI Setup Configure Gemini with Spala Public MCP and the project handoff workflow. /agents/gemini VS Code and Copilot Setup Use Spala Public MCP from VS Code or GitHub Copilot MCP support. /agents/vscode Windsurf Setup Configure Windsurf with Spala Public MCP and safe project handoff. /agents/windsurf Cline Setup Configure Cline with Spala Public MCP and authenticated project selection. /agents/cline Public Agent Skills Use public Spala skill files before authenticated project work. /agents/skills Public MCP /agents/mcp Discovery, auth, project selection, and project MCP handoff Public Agent Skills /agents/skills Agent-readable skill files for evaluation and safe workflow Quick Start /getting-started/quickstart Build a simple REST API from the dashboard Publish /features/publish-export Validate and publish your backend API --- title: API Endpoints route: https://docs.spala.ai/endpoints/ path: /endpoints description: Create REST API endpoints and connect them to your backend logic. section: general updated: 2026-07-08 --- # API Endpoints Create REST API endpoints and connect them to your backend logic. API Endpoints Create REST API endpoints that your frontend or any HTTP client can call. Each endpoint maps a URL and HTTP method to a function that handles the request. The API section showing all endpoints organized by route prefix in the sidebar All your endpoints organized by route prefix — click any to edit Quick walkthrough Create an endpoint Click Endpoints in the sidebar, then Add Endpoint. Set method and path Choose the HTTP method (GET, POST, PUT, DELETE) and enter a path like /api/cases or /api/cases/:id. The :id segment is a path parameter - it matches any value and is available in your function as params.id. Attach a function Select the function that handles the request. The function runs when someone calls this endpoint. Test it Open the Playground and send a request to see the response. Publish when ready Review the changes and publish when the endpoint should be available to live clients. Pro tip Most APIs follow a standard pattern. For a cases resource, you would typically create five endpoints: list, get, create, update, and delete. Common endpoint patterns | Method | Path | Function | What it does | |--------|----------------|----------------|--------------------| | GET | /api/cases | List Cases | Get all cases | | GET | /api/cases/:id | Get Case | Get one case | | POST | /api/cases | Create Case | Create a new case | | PUT | /api/cases/:id | Update Case | Update a case | | DELETE | /api/cases/:id | Delete Case | Delete a case | Learn more Endpoint Controls Endpoints can also control operational behavior: - Authentication - require JWT auth for protected routes. - Inputs - define path, query, body, and file inputs for clearer testing and docs. - Rate limiting - protect expensive or public routes from abuse. - Hide from API docs - keep internal or experimental routes out of generated public docs. - AI summary - ask AI to draft a human-readable endpoint description for docs and review. - Requests - inspect recent request history when debugging live behavior. Create an Endpoint Step-by-step guide to setting up endpoints with methods, paths, and functions. /endpoints/creating-endpoints Inputs & Outputs Handle path parameters, query strings, request bodies, and responses. /endpoints/inputs-outputs Protect Your Endpoints Add authentication with JWT tokens and role-based access. /endpoints/authentication Functions /flows Build the logic that powers your endpoints Publish /features/publish-export Review and publish endpoints for live clients Build a REST API /guides/build-rest-api Step-by-step guide to creating a complete API --- title: Build backends for AI-built apps route: https://docs.spala.ai/ path: / description: Spala turns product intent into database, auth, REST APIs, backend logic, docs, publishing, and MCP access for coding agents. section: general updated: 2026-07-08 --- # Build backends for AI-built apps Spala turns product intent into database, auth, REST APIs, backend logic, docs, publishing, and MCP access for coding agents. Build backends for AI-built apps Tell Spala what your app needs and get a backend you can inspect, edit, validate, and publish: database, auth, REST APIs, backend logic, docs, and agent access. The Spala Lite workspace showing AI Copilot and the project graph Start from the Copilot workspace and inspect the generated project graph. Three ways to build AI Copilot Describe what you want in plain English. The AI builds your tables, flows, and endpoints — ready to use in seconds. /features/ai-assistant Lite Mode Start with a Copilot workspace and project graph, then jump into focused backend tools. /features/lite-mode Function Editor Use Gherkin, Visual, Split, and Code views to inspect and refine API behavior. No boilerplate, no setup. /flows Code View Use Code view for advanced JavaScript while keeping built-in steps connected to visual views. /flows/code-view AI Agents & MCP Connect Codex, Claude, Cursor, or another MCP client to discover Spala, authenticate, select a project, and hand off to the project MCP. /agents/mcp Project Agents Create backend automations that run from chat, webhooks, schedules, database changes, or realtime events. /features/project-agents Frontend App Preview and publish a static app UI next to the generated backend, or let an agent prepare the upload. /features/frontend-app Start building in 5 minutes Choose the right first path on Start Here, then follow the Quick Start to build a Cases API. If you are using an AI coding assistant, start with Spala Public MCP. Explore the docs Start Here Pick the dashboard, frontend, AI agent, or raw MCP path. /start-here Quick Start Build a Cases API in under 5 minutes. /getting-started/quickstart Addons Integrations for payments, email, AI, storage, and more. /addons Guides Step-by-step tutorials for building real features. /guides MCP Setup Install the public Spala MCP and let authenticated project data resolve the project MCP URL. /agents/mcp Settings Configure AI, MCP, API docs, environment variables, snapshots, auth, and project controls. /settings API Docs Share OpenAPI, Markdown docs, SDK files, and snippets with frontend builders or agents. /features/api-docs Project Memory Save durable project context that Copilot, publish review, frontend generation, and MCP agents can use. /features/project-memory Quick Start /getting-started/quickstart Build a Cases API in under 5 minutes Spala Public MCP /agents/mcp Connect an AI coding agent to Spala safely AI Copilot /features/ai-assistant Describe what you want and the AI builds it for you Lite Mode /features/lite-mode Use the Copilot workspace and project graph Publish /features/publish-export Review and publish your backend API --- title: Channels route: https://docs.spala.ai/channels/ path: /channels description: Manage realtime channels for database changes, broadcasts, and presence when Channels are enabled for your project. section: general updated: 2026-07-08 --- # Channels Manage realtime channels for database changes, broadcasts, and presence when Channels are enabled for your project. Channels Channels let a project push live updates to clients when realtime capabilities are enabled. Use them for database-change feeds, broadcasts, presence, live dashboards, chat, and collaborative interfaces. Advanced availability Channels are not the main starting point for most projects. If you do not see Channels in your dashboard, build with API Endpoints, Triggers, and Scheduled Tasks, or contact Spala support to confirm whether Channels are enabled for your project. The Channels section showing realtime channel list and editor Manage realtime channels from the Channels screen when enabled for the project. Channel types The current Channels workspace focuses on realtime channel behavior: - Database Changes - push events when selected project data changes. - Broadcast - send messages to connected clients subscribed to a channel. - Presence - track connected users or sessions for collaborative and live-status features. Advanced REST-channel organization may be available in some workspaces, but most projects should start with regular API Endpoints and add realtime channels only when the product needs live updates. Learn more REST Channels Group and configure REST API endpoints with shared settings. /channels/rest-channels Realtime Channels Set up WebSocket connections for live data updates. /channels/realtime Build Realtime Chat /guides/realtime-chat Full tutorial for building a chat backend Triggers /triggers Auto-run logic that can emit realtime events --- title: Database route: https://docs.spala.ai/database/ path: /database description: Design your database visually — create tables, add fields, and set up relationships. section: general updated: 2026-07-08 --- # Database Design your database visually — create tables, add fields, and set up relationships. Database Design your database visually — create tables, add fields, set up relationships. No SQL required. The database tables list showing all tables in the project All your tables at a glance Quick walkthrough Create a table Click Database in the sidebar, then Add Table. Give it a name like cases. An id column is added automatically. Add fields Click Add Field and choose a type (Text, Number, Boolean, Date, etc.). Set whether the field is required, unique, or has a default value. Save Click Save and your table is created. Spala handles the database setup for you. Good to know Spala uses PostgreSQL under the hood. You never need to write SQL, but you can use Raw SQL steps in your functions if you want to. Use your tables in functions Once your tables exist, you interact with them through Database Query steps in your functions: - Select — Read rows with conditions, sorting, and pagination - Insert — Create new rows - Update — Modify existing rows - Delete — Remove rows Schema Visualizer Click the Visualize button (the link icon next to DATABASE in the sidebar header) to open an interactive ER diagram of your entire database. The Schema Visualizer showing an ER diagram with all tables, fields, and relationship lines See all your tables and relationships in one diagram The visualizer shows: - Every table with its fields, types, and constraints - Primary keys (🔑) and foreign keys (→) highlighted - Relationship lines connecting tables through foreign key references - Reset Layout to auto-arrange the diagram Click any table's edit icon to jump directly to its schema editor. Drag tables to rearrange the layout. Learn more Tables & Fields Create tables, add fields, and manage your schema. /database/tables Relationships Connect tables with foreign keys for one-to-many and many-to-many patterns. /database/relationships Database Steps /reference/steps/database Reference for all database step types in functions Database Triggers /triggers/database-triggers Auto-run logic when rows are inserted, updated, or deleted Publish /features/publish-export Make your project API live after schema changes --- title: Functions route: https://docs.spala.ai/flows/ path: /flows description: Build backend logic with Gherkin, Visual, Split, and Code views. section: general updated: 2026-07-08 --- # Functions Build backend logic with Gherkin, Visual, Split, and Code views. Functions Functions contain your backend logic. Build them with Gherkin, Visual, Split, and Code views. Query your database, send emails, call external APIs, and switch to JavaScript when you need more control. The Spala function editor showing a readable function outline The readable outline summarizes the function contract and execution path. What is a function? A function is a sequence of steps that executes your backend logic. Functions run when an endpoint is called, a task fires, a database trigger activates, an agent runs, or another function calls them. Steps execute top to bottom. Each step does one thing: query data, set a variable, check a condition, call an API, or return a response. Quick example Here is a function that gets a case by ID with a 404 fallback: 1. Database Query — Select from cases where id = params.id, assign to caseRecord 2. If/Else — Condition: vars.caseRecord - True: Return vars.caseRecord - False: Return { error: "Not found" } with status 404 Attach this to a GET /api/cases/:id endpoint and you have a working API route. Pro tip Built-in steps stay connected across visual views and Code view. Custom JavaScript is preserved when it cannot be represented as a built-in step. Common step types | Step | What it does | |------------------|-------------------------------------------------| | Set Variable | Store a value for later steps | | Database Query | Read, insert, update, or delete database rows | | If/Else | Branch logic based on a condition | | Loop | Repeat steps for each item in a list | | Return | Send a response back to the client | | External API Call| Call an outside API (Stripe, OpenAI, etc.) | | Try/Catch | Handle errors gracefully | | Run Function | Call another function as a subroutine | Learn more Create a Function Step-by-step guide to building your first function. /flows/creating-flows Variables & Data Set variables and access request data, environment variables, and more. /flows/variables Code View Use JavaScript alongside visual flow views. /flows/code-view Try & Runs Use Try, runs, breakpoints, and variable inspection to test functions. /flows/debugging Steps Reference /reference/steps Complete reference for available step types Filters Reference /reference/filters Data transformation filters for expressions API Endpoints /endpoints Connect your functions to REST API endpoints --- title: Functions route: https://docs.spala.ai/functions/ path: /functions description: Spala functions are backend workflows. The current docs route is /flows because older builds used the word flow for the same editor surface. section: general updated: 2026-07-08 --- # Functions Spala functions are backend workflows. The current docs route is /flows because older builds used the word flow for the same editor surface. Functions Spala functions are backend workflows that power endpoints, tasks, triggers, project agents, and internal automation. Some older docs and URLs use the word flows for the same editor surface. Terminology In the current product UI, think Functions. In docs URLs, /flows is the canonical route for the function editor and related reference pages. Use functions when you need to: - Read and write database records - Validate inputs - Call APIs and addons - Send emails, files, payments, or AI requests - Return API responses - Run logic from endpoints, tasks, triggers, or project agents Functions Overview /flows Build backend logic with the function editor Create a Function /flows/creating-flows Create and connect function steps Code View /flows/code-view Edit function logic as JavaScript Variables & Data /flows/variables Pass data between function steps --- title: Guides route: https://docs.spala.ai/guides/ path: /guides description: Step-by-step tutorials for building real features with Spala. section: general updated: 2026-07-08 --- # Guides Step-by-step tutorials for building real features with Spala. Guides Step-by-step tutorials for building real features. Each guide walks you through a complete, working example you can adapt to your own project. Build a REST API /guides/build-rest-api Create a cases API with tables, endpoints, and CRUD operations in minutes. Add User Authentication /guides/user-auth Set up signup, login, JWT tokens, and protected endpoints. Accept Payments with Stripe /guides/stripe-payments Install the Stripe addon, create a checkout function, and handle webhooks. Send Emails /guides/send-emails Configure email delivery and send transactional emails from your functions. Upload Files /guides/file-uploads Accept file uploads, store them in S3 or locally, and serve them back. Add AI Features /guides/ai-integration Build a chat completion endpoint with the OpenAI addon. Build Realtime Chat /guides/realtime-chat Set up WebSocket channels and broadcast messages to connected clients. Advanced CRUD /guides/crud-operations Add pagination, filtering, sorting, and batch operations to your endpoints. Run Scheduled Jobs /guides/scheduled-jobs Automate cleanup routines, reports, and data syncing with tasks. Quick Start /getting-started/quickstart Build your first API in under 5 minutes Functions /flows Learn the fundamentals of building backend logic Addons /addons Extend your backend with integrations --- title: Legacy Self-Hosting Links route: https://docs.spala.ai/self-hosting/ path: /self-hosting description: Legacy compatibility page for old self-hosting URLs. Spala is used from the hosted dashboard. section: general updated: 2026-07-08 --- # Legacy Self-Hosting Links Legacy compatibility page for old self-hosting URLs. Spala is used from the hosted dashboard. Legacy Self-Hosting Links Spala is designed to be used from the hosted dashboard at https://dashboard.spala.ai. You create a project, describe what you need in the AI Copilot, inspect the generated backend, publish the API, and connect your frontend or AI agent. This page is kept only for old self-hosting links. The current docs for getting projects live are in Project Delivery. Users do not self-host the Spala dashboard, builder, or platform source code. Start in the dashboard If you want to build a backend, open the hosted dashboard and start with AI Copilot or Lite mode. Spala handles the platform behind the scenes. What You Manage - Your project resources: tables, endpoints, functions, tasks, triggers, channels, addons, and settings - Your published API behavior - Environment variables for your project integrations - Agent access through Spala MCP - Project publishing and review What Spala Manages - Platform hosting and dashboard delivery - Builder runtime - Managed project infrastructure - Platform updates and operational maintenance Project Delivery /deployment Publish and connect the projects you build in Spala AI Copilot /features/ai-assistant Describe what you need and let Spala build the backend Lite Mode /features/lite-mode Use the Copilot workspace and project graph Publish Your API /features/publish-export Make your project changes live Spala Public MCP /agents/mcp Connect AI agents through the public MCP handoff --- title: Project Delivery route: https://docs.spala.ai/deployment/ path: /deployment description: Publish and connect the projects you build in Spala from the hosted dashboard. section: general updated: 2026-07-08 --- # Project Delivery Publish and connect the projects you build in Spala from the hosted dashboard. Project Delivery Spala users deliver the projects they build: the generated API, static frontend, API docs, and integration settings. You use Spala from the hosted product; you do not run the Spala platform yourself. In these docs, deployment always means project delivery: a project artifact or generated project artifact, never the Spala dashboard, builder, or platform source code. User project, not Spala platform These docs are about getting your Spala project live. Platform hosting, dashboard delivery, builder runtime, and operational updates are managed by Spala. What You Can Ship Published API Review project changes and publish the generated backend API. /features/publish-export Frontend App Host a static frontend next to the backend when your project needs a simple UI. /features/frontend-app API Docs Share Swagger, Markdown, OpenAPI JSON, SDK, and Webflow snippets. /features/api-docs CI/CD Connect generated project deployment to your server, deploy hook, or external workflow. /features/ci-cd Delivery Actions | Action | What changes | Who manages it | Where it lives | | --- | --- | --- | --- | | Publish backend API | Live generated API behavior for the project | You review and publish; Spala serves the hosted API | Project API base URL | | Publish frontend app | Static frontend files uploaded to the project | You or an agent upload, preview, and publish | Project frontend URL | | Share API docs | Generated Markdown, JSON, OpenAPI, SDK, or snippets | You choose what to expose or share | Settings → API Docs and generated docs routes | | Deploy generated project artifact | Generated project runtime sent to an external server or deploy provider | You configure target credentials and operations | Your infrastructure | What You Manage - Project resources: tables, endpoints, functions, tasks, triggers, agents, channels, addons, and settings - Project environment variables and integration credentials - Published API behavior and generated API docs - Frontend app assets when you use Spala frontend hosting - Agent access through public MCP discovery and the selected project MCP What Spala Manages - Hosted dashboard and builder runtime - Platform authentication and account access - Managed project infrastructure used by the hosted experience - Platform updates and operational maintenance Start a Project /deployment/start Create a project from the hosted dashboard Publish /deployment/publish Publish generated backend changes Settings /settings Configure project-level tools Spala Public MCP /agents/mcp Let agents discover, authenticate, and hand off to projects --- title: Reference route: https://docs.spala.ai/reference/ path: /reference description: Complete reference documentation for Spala step types, filters, operators, and data types. section: general updated: 2026-07-08 --- # Reference Complete reference documentation for Spala step types, filters, operators, and data types. Reference Detailed reference documentation for every building block in Spala. Steps /reference/steps Step types organized by category: variables, database, control flow, API, auth, crypto, file, encoding, and more. Filters /reference/filters Data transformation filters for strings, arrays, numbers, dates, objects, and type conversions. Applied using the pipe operator. Operators /reference/operators Arithmetic, comparison, logical, ternary, nullish coalescing, and optional chaining operators for expressions. Data Types /reference/data-types Supported data types: string, number, boolean, null, array, object, date, and buffer. Functions /flows Build backend logic using steps, expressions, and filters Quick Start /getting-started/quickstart See steps and filters in action with a hands-on tutorial --- title: Settings route: https://docs.spala.ai/settings/ path: /settings description: Configure project metadata, database, auth, AI, MCP, frontend hosting, API docs, environment variables, snapshots, and project controls. section: general updated: 2026-07-08 --- # Settings Configure project metadata, database, auth, AI, MCP, frontend hosting, API docs, environment variables, snapshots, and project controls. Settings Settings is the control panel for project-level behavior. Open it from the sidebar in Advanced mode, or from the Lite mode tools menu. Settings Areas General Project name, API docs, project controls, and editor preferences. /settings Database Database copy, backup, restore, connection, and data management controls. /database Security Security policy, CORS origins, trusted hosts, tokens, and request controls. /settings/cors-security Users & Roles Builder users, roles, permissions, and access control. /features/team-access AI Provider configuration, usage limits, data access controls, and AI instructions. /features/ai-assistant Project Memory Saved project memory that AI can search, pin, approve, edit, or archive. /features/project-memory MCP Server Project MCP access for desktop AI tools, install manifests, scopes, and connection instructions. /agents/mcp Publishing Review and publish project changes as a live API. /features/publish-export Frontend App Frontend hosting and generated app deployment settings. /features/frontend-app API Docs Public API docs export and documentation behavior. /features/api-docs Environment Runtime environment variables used by flows, addons, and generated apps. /addons Snapshots Project snapshots for review, rollback, and publish history. /features/project-snapshots CI/CD Deploy generated backend bundles or trigger deployment hooks after publish. /features/ci-cd Trash Bin Deleted resources and recovery/cleanup controls. /features/team-access Advanced Request history, instance configuration, runtime tools, reload controls, and bulk cleanup. /settings AI Settings Spala AI settings showing provider and data access controls AI settings control provider access, usage limits, and which project data AI can read. Use AI settings to configure provider credentials, data access, and limits. Data access matters because Ask mode can answer questions using project context only when the relevant tables and fields are allowed. Project Memory adds durable instructions and decisions that keep future AI work aligned. MCP Settings Spala MCP settings showing server status, install manifest exposure, tools, scopes, and client choices MCP settings expose project MCP access and client-specific connection instructions. Project MCP is different from the public Spala MCP. The public MCP helps agents discover Spala, authenticate, select a project, and hand off. Project MCP is where authenticated agents inspect and operate one backend. Do not hardcode project MCP URLs Let Spala return the project MCP URL from authenticated project data. Project URLs can vary by hosted domain, project slug, or explicit manifest configuration. Environment And Publishing Spala environment settings for runtime variables Environment variables feed addons, flows, generated frontends, and runtime integrations. Environment variables are the right place for API keys and runtime values used by your project. Addon pages list the variables each addon expects. API Docs, Snapshots, And CI/CD Spala API Docs settings showing public docs, SDK, OpenAPI, and snippets controls API Docs settings let you share the API contract with frontend builders and agents. Spala project snapshots settings showing project restore points Snapshots give you checkpoints before larger AI, agent, or manual changes. Spala CI/CD settings showing deployment target controls CI/CD connects generated project deployment to your server, deploy hook, or external workflow. Project Delivery Tools Settings also includes the operational tools around the generated backend: - Frontend App - upload, preview, publish, roll back, or let an agent package a static UI. - API Docs - share Swagger UI, Markdown docs, OpenAPI JSON, SDK files, and snippets with frontend builders. - Snapshots - create checkpoints and restore the full draft or selected resources after larger changes. - CI/CD - deploy generated bundles to your own targets or trigger external deploy hooks after publish. - Team Access - manage builder users, roles, permissions, security, and recovery controls. Advanced And Recovery Controls The General and Advanced tabs hold tools that are useful during review, migration, or recovery: - Export Project JSON - download a redacted project definition for backup, review, or support. - Download Runtime ZIP - generate a project runtime bundle for advanced deployment workflows. - Import Project JSON - restore or move a project definition when you intentionally need to. - API Docs Markdown / JSON - download documentation artifacts without enabling public docs. - Editor Preferences - set default view behavior for focused editing. - Request & Execution History - inspect API calls, function runs, errors, and timing. - Instance Configuration - view read-only CONFIG_* values available to the project runtime. - Danger Zone - bulk-delete functions, endpoints, tasks, triggers, channels, models, or addons when you are intentionally resetting a project. Project runtime, not the Spala platform Advanced export and runtime tools are for the backend project you build in Spala. They do not package the hosted Spala product or replace the dashboard. Lite Mode /features/lite-mode Use the Copilot workspace and tools menu Project Overview /features/project-overview Inspect resources, project graph, drafts, and agents Public MCP /agents/mcp Connect AI agents to Spala safely Publish /features/publish-export Review and publish your backend API Frontend App /features/frontend-app Host a static app UI for the project API Docs /features/api-docs Share endpoint docs and SDKs with frontend builders CORS and Security /settings/cors-security Configure browser origins before frontend handoff --- title: Start Here route: https://docs.spala.ai/start-here/ path: /start-here description: Choose the right first path for Spala: dashboard builder, frontend integration, AI agent, or raw MCP. section: general updated: 2026-07-08 --- # Start Here Choose the right first path for Spala: dashboard builder, frontend integration, AI agent, or raw MCP. Start Here Spala is a hosted backend builder for AI-built apps. Use the hosted dashboard to create and publish project APIs. Connect AI coding agents through Spala MCP when an agent needs to discover projects, read context, or hand off into a project-specific MCP. Pick the path that matches your job. Boundary glossary | Term | Meaning | | --- | --- | | Spala platform | The hosted dashboard, builder runtime, platform auth, updates, and managed infrastructure operated by Spala | | Project | The backend app you build in Spala: tables, functions, endpoints, tasks, triggers, channels, addons, settings, docs, and frontend assets | | Publish backend API | Promote the project draft to the live generated API that frontends and integrations call | | Deploy generated project artifact | Advanced CI/CD path for deploying a generated project artifact outside the default hosted publish flow | | Frontend App | Static UI assets hosted beside the generated project backend | | Project Agent | Backend automation that belongs to one Spala project and runs from chat, schedules, webhooks, data changes, or realtime events | | AI/MCP Agent | External coding agent or MCP client, such as Codex, Claude, Cursor, or VS Code, that helps build or inspect a project | | Public MCP | https://mcp.spala.ai/mcp, used for discovery, auth metadata, docs search, project lookup, and handoff | | Project MCP | The project-scoped MCP URL returned after auth and project selection; backend changes happen there | Before you build Start from the hosted dashboard at https://dashboard.spala.ai. New users should create an account from the dashboard sign-up screen. If you are joining an existing company workspace, accept the workspace invite or ask the workspace owner to add you. You also need permission to create or edit a project. A first Copilot-built API usually takes a few minutes; at the end you should have tested endpoints, a published API base URL, and generated API docs for frontend work. Delivery actions | Action | What changes | Who manages it | Where it lives | | --- | --- | --- | --- | | Publish backend API | Draft project resources become the live API | You approve publish; Spala serves the hosted project API | Project API base URL | | Publish frontend app | Static UI assets become the live project UI | You upload or agent-build the frontend; Spala hosts the assets | Project frontend URL | | Deploy generated project artifact | Generated project runtime is sent to an external target | You configure the target and credentials | Your server or deploy provider | | Use project MCP | An authenticated agent edits one selected project | You grant access; agent uses returned MCP URL | Project-scoped MCP endpoint | I am building in the dashboard Use this path when you want to create a backend from a prompt and publish it from Spala. 1. Open https://dashboard.spala.ai. 2. Create an account, sign in, or accept your workspace invite. 3. Create or open a project. 4. Start in Lite Mode from the project header or mode switch. 5. Ask AI Copilot for the backend feature you need. 6. Review generated tables, functions, endpoints, tasks, triggers, channels, and settings. 7. Test in API Playground. 8. Use Publish backend API to make the generated project API live. Quick Start Build and publish a Cases API from the dashboard. /getting-started/quickstart AI Copilot Describe the backend feature and review generated resources. /features/ai-assistant Lite Mode Use the Copilot workspace and project graph as the first screen. /features/lite-mode I am connecting a frontend Use this path when you already have, or are building, a React, Next.js, Vite, Webflow, mobile, or external frontend. 1. Find the project API base URL in Lite Mode or Project Overview. 2. Open Settings → API Docs for the generated Markdown, JSON, OpenAPI, or SDK contract. 3. Find routes in Endpoints or the generated API Docs. 4. Use /api/... route paths exactly as published. 5. For protected endpoints, send Authorization: Bearer USER_JWT. 6. Store environment values in your frontend as VITE_SPALA_API_BASE_URL or NEXT_PUBLIC_SPALA_API_BASE_URL. 7. Test calls in API Playground before wiring the frontend. Frontend Integration Cookbook Copyable examples for base URLs, auth, uploads, realtime, and env vars. /guides/frontend-integration External Frontend Handoff Share the exact packet a frontend developer or AI agent needs without dashboard access. /guides/frontend-handoff API Endpoints Create and inspect REST API routes. /endpoints API Docs Export OpenAPI, Markdown docs, SDK files, and snippets. /features/api-docs I am an AI coding agent Use this path when Codex, Claude Code, Cursor, VS Code, or another agent needs to work with Spala. 1. Connect to the public MCP server at https://mcp.spala.ai/mcp. 2. Call spala_get_onboarding. 3. Call spala_get_tool_map. 4. Use public tools for docs, templates, and addons. 5. When project access is needed, complete Spala platform OAuth. 6. Use project_list and project_select. 7. Switch to the exact project MCP URL returned by Spala. 8. Inspect project context before making changes. 9. Preview, validate, apply, publish backend API when requested, and review through the project MCP. Do not guess project MCP URLs Project MCP URLs are resolved after authentication from Spala project data. Do not hardcode https://api.spala.ai/{{project}}/mcp or any other pattern. Spala Public MCP Public MCP tools, OAuth metadata, raw transcript, and project handoff. /agents/mcp Codex Setup Add Spala Public MCP to Codex. /agents/codex Cursor Setup Configure Cursor with the public MCP entrypoint. /agents/cursor More MCP Clients Gemini CLI, VS Code/Copilot, Windsurf, and Cline setup paths. /agents Public Agent Skills Skill files that help agents evaluate Spala and start safely. /agents/skills I am implementing raw MCP Use this path only if you are building an MCP client or debugging MCP transport directly. 1. Use POST https://mcp.spala.ai/mcp. 2. Send Content-Type: application/json. 3. Send Accept: application/json, text/event-stream. 4. Call MCP protocol methods such as initialize, tools/list, and tools/call. 5. Pass Spala tool names inside tools/call; do not call tool names as top-level JSON-RPC methods. 6. Discover OAuth endpoints from MCP OAuth metadata. Spala Public MCP /agents/mcp Full raw MCP notes and transcript Project Delivery /deployment Publish projects without self-hosting Spala itself Settings /settings Configure API docs, auth, env vars, MCP, and publishing --- title: Tasks route: https://docs.spala.ai/tasks/ path: /tasks description: Run logic on a schedule or in the background. section: general updated: 2026-07-08 --- # Tasks Run logic on a schedule or in the background. Tasks Run logic on a schedule or in the background for jobs that should not block an API response. The Tasks section showing scheduled and background tasks in the sidebar View and manage all your tasks in one place How to create a scheduled task Open the Tasks screen Go to Tasks from the sidebar and click New Task. Set how it runs Give your task a name. Add a frequency such as every 5 minutes, every hour, or every day, or leave it as a manual task that only runs on demand. Build the function Use the same function editor you use for endpoints. Add database queries, API calls, email sends, or any other backend steps the task needs. Good to know Tasks can run in the main API process or in a background process with resource limits. Use background execution for slower jobs that should not block normal API traffic. Learn more Scheduled Tasks Set repeat frequency, manual runs, background execution, and resource limits. /tasks/scheduled-tasks Background Tasks Run long operations without blocking your API responses. /tasks/background-tasks Scheduled Jobs Guide /guides/scheduled-jobs Build cleanup routines and periodic syncs Triggers /triggers Auto-run logic when data changes instead of on a schedule --- title: Triggers route: https://docs.spala.ai/triggers/ path: /triggers description: Auto-run logic when your data changes — send emails on signup, update inventory on orders, and more. section: general updated: 2026-07-08 --- # Triggers Auto-run logic when your data changes — send emails on signup, update inventory on orders, and more. Triggers Auto-run logic when your data changes — send a welcome email when a user signs up, update inventory when an order is placed. The Triggers section showing trigger list in the sidebar Manage all your triggers in one place What triggers do A trigger watches for a specific event, like a row being inserted or updated, and automatically runs a function when it happens. You set it up once, and it fires every time. Examples: - A new user signs up → send a welcome email - An order is placed → reduce inventory count - A record is updated → log the change for auditing - A custom event fires → notify connected clients How to create a trigger Open the Triggers screen Go to Triggers from the sidebar and click New Trigger. Choose the table and events Pick the table and the insert, update, or delete events that should fire the trigger. Build the function Use the function editor to define what happens when the trigger fires. You have access to the operation plus old and new row data, so you can react to specific changes. Pro tip Use the sync/async setting to decide whether the trigger should run inline with the data change or as follow-up work. Trigger types Database Triggers Run functions when rows are inserted, updated, or deleted. /triggers/database-triggers Event Triggers Availability note for event-driven workflow alternatives. /triggers/event-triggers Scheduled Tasks /tasks Run logic on a schedule instead of on data changes Build a REST API /guides/build-rest-api Create endpoints that can fire triggers --- title: Welcome to Spala route: https://docs.spala.ai/getting-started/ path: /getting-started description: Spala builds backend infrastructure for AI-built apps: database, auth, REST APIs, logic, docs, publishing, and MCP access for coding agents. section: general updated: 2026-07-08 --- # Welcome to Spala Spala builds backend infrastructure for AI-built apps: database, auth, REST APIs, logic, docs, publishing, and MCP access for coding agents. Welcome to Spala Spala is a backend automation platform for AI-built apps. Describe what your product needs and Spala helps create the database, auth, REST APIs, validation, backend logic, docs, and publishing flow. You can work in Lite mode with the Copilot and project graph, open Advanced mode for full resource editing, switch into code, or connect an approved AI coding agent through Spala MCP. The Spala Lite workspace showing AI Copilot and the project graph Start from the Copilot workspace and inspect the generated project graph. How people build with Spala Most users start with the AI Copilot. Describe a feature in plain English, and the AI generates your database tables, functions, and API endpoints. Then fine-tune with the visual editor or switch to JavaScript for full control. Lite Mode Start from the Copilot workspace, inspect the project graph, and jump into focused tools. /features/lite-mode AI Copilot Describe what you want and the AI builds it. The fastest way to create features. /features/ai-assistant AI Agent MCP Connect Codex, Claude, Cursor, or another MCP client to discover projects and hand off to the project MCP. /agents/mcp Frontend App Publish a static UI next to your backend, or give an agent upload instructions. /features/frontend-app Function Editor Use Gherkin, Visual, Split, and Code views to inspect and refine backend behavior. /flows Code View Every function can be edited as JavaScript and kept connected to visual views. /flows/code-view Addons Stripe, OpenAI, SendGrid, S3, Twilio, Slack, and more — plug in what you need. /addons Who is Spala for? - Indie developers who want to ship APIs fast without boilerplate - Startups that need to prototype and iterate quickly - Agencies building custom backends for clients - Beginners who want real APIs without learning a framework - AI coding agents that need a safe backend builder and project handoff flow Key features - Lite mode — Start from the Copilot workspace, inspect the project graph, and jump into focused tools - AI Copilot — Describe features in English, get a complete backend in seconds - Public MCP — Agents start at https://mcp.spala.ai/mcp, authenticate with Spala, select a project, then switch to the returned project MCP - Function editor — Use Gherkin, Visual, Split, and Code views to build backend logic. - Addons — Payments, email, file storage, AI models, SMS, and more - Code view — Edit visually or in JavaScript while preserving the function structure. - Project graph — See the database, APIs, functions, tasks, triggers, and channels the Copilot created - Database designer — Create tables and relationships visually - Project agents — Run project-native automations from chat, webhooks, schedules, data changes, or realtime events - Try & Runs — Set breakpoints, inspect variables, and review execution history - Settings — Configure AI, MCP, auth, API docs, environment variables, team access, snapshots, CI/CD, and frontend hosting - Publish — Review changes and make your generated API live Ready to build? Jump to the Quick Start to build a Cases API in 5 minutes. If you are using an AI coding assistant, connect Spala Public MCP first. Quick Start /getting-started/quickstart Build a Cases API from scratch Spala Public MCP /agents/mcp Connect an AI coding assistant to Spala AI Copilot /features/ai-assistant The fastest way to build with Spala Lite Mode /features/lite-mode Use the Copilot workspace and project graph Addons /addons Integrations for payments, email, AI, storage, and more The Interface /getting-started/interface A visual tour of the Spala UI --- title: Quick Start: Build a Cases API route: https://docs.spala.ai/getting-started/quickstart/ path: /getting-started/quickstart description: Create a working REST API for a client portal from the hosted Spala dashboard. section: getting-started updated: 2026-07-08 --- # Quick Start: Build a Cases API Create a working REST API for a client portal from the hosted Spala dashboard. Quick Start: Build a Cases API The fastest way to build in Spala is to start with AI Copilot. This guide starts with the Copilot path, then shows the same pieces manually so you understand what Spala creates. Examples use /api/... paths so the published API is easy to recognize from client code. Hosted dashboard first Start from the hosted Spala dashboard at https://dashboard.spala.ai. Most users can describe the whole feature to the AI Copilot first; this guide shows the manual editor tour so you understand the pieces Spala creates. Before you begin Start from https://dashboard.spala.ai. New users should create an account from the dashboard sign-up screen. If you are joining an existing company workspace, accept the workspace invite first. You also need permission to create or edit a project. This guide should leave you with a tested GET /api/cases endpoint, a published project API base URL, and generated API Docs you can hand to a frontend developer or AI coding agent. 1. Create a project Open Spala Open https://dashboard.spala.ai and create an account or sign in. If you are joining an existing company workspace, accept the invite first. Create a new project Click New Project on the dashboard. Name it "Legal Client Portal API" and click Create. 2. Fast path: ask AI Copilot Open Lite Mode Lite Mode keeps AI Copilot and the project graph visible together. If the project opens in Advanced mode, use the header mode switch to move to Lite Mode. Describe the feature Ask Copilot: "Create a cases API for a legal client portal with a cases table, GET /api/cases list endpoint, and POST /api/cases/:id/status update endpoint." Review the result Check the generated tables, functions, endpoints, and project graph. Use Ask mode if you want Copilot to explain what it created. Test and publish Test the endpoint in Playground, then click Publish when the project draft is ready to become the live API. Manual tour below The rest of this guide shows the manual path through Database, Functions, Endpoints, Playground, and Publish. Use it when you want to understand or directly edit the resources Copilot creates. 3. Create the cases table Open the Database section Click Database in the left sidebar. Add a table Click Add Table and name it cases. Spala creates an id column automatically. Add fields Add these fields to your cases table: | Field Name | Type | Required | |-------------|-----------------|----------| | case_number | Text | Yes | | case_title | Text | Yes | | status | Text | Yes | | client_id | Table Reference | No | | attorney_id | Table Reference | No | | created_at | Timestamp | No | Save Click Save. Your table is saved in the project draft and is ready to use in functions. The table creation entry point in Spala Create a table from the Database screen. 4. Build a "List Cases" function Go to Functions Click Functions in the sidebar, then Create Function. Name it "List Cases". Add a Database Query step Open Visual view and add a Database Query step. Configure it: - Table: cases - Operation: Select - Assign To: cases Add a Return step Add a Return step after the query. Set its value to: vars.cases 5. Create the GET /api/cases endpoint Go to Endpoints Click Endpoints in the sidebar, then Add Endpoint. Configure it - Method: GET - Path: /api/cases - Function: List Cases - Authentication: None Save Click Save. Your endpoint is saved in the project draft and ready to test. 6. Test it in the Playground Open the Playground Click Playground in the sidebar. Select your GET /api/cases endpoint. Send a request Click Send. You will see an empty array [] since there is no case data yet. Add some cases Go back to Database, click the cases table, and use the Data tab to add a few rows. Then test the endpoint again. 7. Publish it Open Publish Click Publish in the header when the table, function, and endpoint look right. Review the changes Review the pending changes, then publish. After publishing, your endpoint is available from your project's API base URL. The Spala publish dialog Review pending changes before publishing your backend. 8. Confirm the live API After publish, complete this checklist before giving the backend to a frontend builder: 1. Copy the project API base URL from Lite Mode or Project Overview. 2. Open Settings → API Docs and confirm GET /api/cases appears. 3. Test the live endpoint from API Playground. 4. Copy the generated Markdown docs, OpenAPI JSON, or SDK if another person or agent is building the frontend. 5. Add your frontend origin in Settings → Security → CORS Allowed Origins if browser calls are blocked. First frontend call: const API_BASE_URL = import.meta.env.VITE_SPALA_API_BASE_URL; const response = await fetch(`${API_BASE_URL}/api/cases`); if (!response.ok) { throw new Error(`Spala API error: ${response.status}`); } const cases = await response.json(); Bonus: Add an "Update Case Status" endpoint Take it further by creating a POST /api/cases/:id/status endpoint: Create a new function Add a function called "Update Case Status". Add a Database Query step Configure it: - Table: cases - Operation: Update - Set: status to input.status - Where: id = params.id - Assign To: updatedCase Return the result Add a Return step with value vars.updatedCase. Create the endpoint Add a POST endpoint at /api/cases/:id/status, attach the function, save it, test it, then publish when it is ready. Pro tip You can build the whole feature with the AI Copilot. Describe what you want: "Create a cases API for a legal client portal with GET /api/cases and POST /api/cases/:id/status endpoints." Using an AI coding agent If you want Codex, Claude, Cursor, or another MCP client to help with the backend, connect the public Spala MCP first: codex mcp add spala-public --url "https://mcp.spala.ai/mcp" The public MCP is for discovery, OAuth metadata, project lookup, and handoff. After authentication, let Spala return the selected project MCP URL. Do not hardcode a URL such as https://api.spala.ai/{project}/mcp. What's next? Spala Public MCP /agents/mcp Connect an AI coding assistant to Spala The Interface /getting-started/interface Learn your way around the Spala UI Database /database Tables, fields, and relationships Functions /flows All the ways to build backend logic API Endpoints /endpoints Methods, paths, authentication, and more --- title: The Interface route: https://docs.spala.ai/getting-started/interface/ path: /getting-started/interface description: A visual tour of the Spala UI — learn where everything is and what each section does. section: getting-started updated: 2026-07-08 --- # The Interface A visual tour of the Spala UI — learn where everything is and what each section does. The Interface This page gives you a quick tour of the Spala UI so you know where everything lives. Dashboard When you open a project, Lite mode shows the Copilot next to your project graph. This is where most users describe what they want, inspect what Spala built, and jump into focused editors. The Spala Lite workspace showing AI Copilot and the project graph Lite mode keeps the Copilot and project graph side by side. Advanced mode opens on Project Overview. Use the tabs there to scan backend resources, inspect the project network, and run or review project agents before you open a focused editor. The Spala Project Overview showing backend resources and endpoint summary Project Overview shows the live shape of your backend and the most common jump points. Sidebar The left sidebar is your main navigation. Here is what each section does: | Section | What it does | |--------------|-------------------------------------------------------------| | Database | Design tables, add fields, set up relationships | | Functions | Build backend logic with Gherkin, Visual, Split, and Code views | | Endpoints | Create REST API routes and attach functions to them | | Tasks | Set up functions that run manually, in the background, or on a repeat schedule | | Triggers | Auto-run functions when database records change | | Channels | Manage realtime channels when enabled for the project | | Agents | Build project-native automations with triggers, chat, timeline, and metrics | | Pull Requests | Review generated backend changes before merging or publishing | | Background Tasks | Monitor queued, running, failed, and completed async jobs | | Addons | Browse and enable addons for email, payments, AI, and more | | Playground| Test your endpoints with sample requests | The Editor When you open a function, endpoint, or table, the editor takes over the main area. Function editing starts in Gherkin view: The Spala Gherkin view showing a function outline and typed inputs The Gherkin view shows the function contract, outline, and response shape. Function editors have several views: - Gherkin - A readable outline of inputs, outputs, preparation, business logic, and response shape. - Visual - Editable step blocks and inputs for users who want direct control without writing code. - Split - Visual and Code together when you need both context and detail. - Code - JavaScript for advanced editing. The editor workspace also gives you open tabs, view-mode memory, Ask AI, Try, Compare, Discard, Save, version history, run history, export, revert, and delete controls. Code View Every function has a Code tab next to Gherkin, Visual, and Split. Click it to see and edit the JavaScript version of your function. Changes stay connected to the visual views. The code view showing JavaScript Switch between visual and code at any time Good to know You do not have to choose one or the other. Build visually, then fine-tune in code — or write code and see it appear as visual steps. Publish When your project is ready, click Publish to publish the backend API. Your endpoints become accessible at your configured project API base URL. This publishes project API behavior; it does not deploy or self-host the Spala platform. Search everything Press Cmd+K (or Ctrl+K on Windows) to open the search palette. It searches across your tables, functions, endpoints, tasks, triggers, and settings. Use type prefixes to filter: | Prefix | Searches | |--------|----------| | @t, @table | Tables | | @f, @fn, @function | Functions | | @e, @endpoint | Endpoints | | @tk, @task | Tasks | | @tr, @trigger | Triggers | | @ch, @channel | Channels | Settings and delivery tools Settings is where project-level operations live: AI configuration, Project Memory, MCP, Frontend App hosting, generated API Docs, Environment variables, Snapshots, CI/CD, Team Access, and Trash Bin recovery. Keyboard shortcuts | Shortcut | Action | |----------|--------| | Cmd/Ctrl + K | Search palette | | Cmd/Ctrl + J | AI Copilot | | Cmd/Ctrl + L | Log terminal | | Escape | Close panel | Trash bin Deleted items go to the Trash Bin (in Settings). You can preview and restore anything you accidentally deleted. Quick Start /getting-started/quickstart Build your first API Project Overview /features/project-overview Inspect the whole backend from one screen Editor Workspace /features/editor-workspace Use tabs, search, view modes, Ask AI, Try, and save controls Database /database Design your data model Functions /flows Start building backend logic Frontend App /features/frontend-app Publish a UI for the project --- title: Accept Payments with Stripe route: https://docs.spala.ai/guides/stripe-payments/ path: /guides/stripe-payments description: Install the Stripe addon, create a checkout endpoint, and handle webhooks. section: guides updated: 2026-07-08 --- # Accept Payments with Stripe Install the Stripe addon, create a checkout endpoint, and handle webhooks. Accept Payments with Stripe Set up Stripe checkout in your API — create payment sessions, redirect users to pay, and track order status with webhooks. What you will build - POST /api/checkout — create a Stripe checkout session - POST /api/webhooks/stripe — handle payment status updates Steps Install the Stripe addon Go to Addons, find Stripe, and click Install. Then add your Stripe secret key as STRIPE_SECRET_KEY in Settings > Environment Variables. Create an orders table In the Database screen, create an orders table: | Column | Type | Notes | |--------|------|-------| | id | Serial | Primary key | | user_id | Integer | Foreign key to users | | stripe_session_id | Text | Links to Stripe | | status | Text | Default: 'pending' | | total | Decimal | Order amount | | created_at | Timestamp | Default: now() | Build the checkout endpoint Create POST /api/checkout with this function: 1. External API Call — Method: POST, URL: 'https://api.stripe.com/v1/checkout/sessions', Auth: Bearer env.STRIPE_SECRET_KEY, Content Type: form-encoded, Body: { mode: 'payment', success_url: input.successUrl, cancel_url: input.cancelUrl, 'line_items[0][price_data][currency]': 'usd', 'line_items[0][price_data][product_data][name]': input.productName, 'line_items[0][price_data][unit_amount]': input.amountCents, 'line_items[0][quantity]': input.quantity | default(1) }, Assign To: session 2. Database Insert — Table: orders, Data: { user_id: vars.auth.userId, stripe_session_id: vars.session.body.id, status: 'pending', total: input.total } 3. Respond — Status: 200, Body: { url: vars.session.body.url } Your frontend redirects the user to the returned URL to complete payment. Build the webhook endpoint Create POST /api/webhooks/stripe. Stripe calls this URL when payment status changes. 1. Verify webhook signature — Validate the Stripe signature header with the webhook signing secret before trusting the payload. 2. Set Variable — Name: event, Value: input 3. Switch — Expression: vars.event.type - Case 'checkout.session.completed': Database Update — Table: orders, Data: { status: 'paid' }, Where: { stripe_session_id: vars.event.data.object.id } - Case 'charge.refunded': Database Update — Table: orders, Data: { status: 'refunded' }, Where: { stripe_session_id: vars.event.data.object.id } 4. Respond — Status: 200, Body: { received: true } Configure the webhook in Stripe In your Stripe dashboard, go to Developers > Webhooks, add your /api/webhooks/stripe URL, and select the events checkout.session.completed and charge.refunded. Important Webhook signature verification must happen before you update orders. Use the signing secret from your Stripe dashboard and reject requests that fail verification. Addons /addons Browse all available integrations Build a REST API /guides/build-rest-api Create the product endpoints to sell --- title: Add AI Features route: https://docs.spala.ai/guides/ai-integration/ path: /guides/ai-integration description: Build a chat completion endpoint and add AI-powered features with the OpenAI addon. section: guides updated: 2026-07-08 --- # Add AI Features Build a chat completion endpoint and add AI-powered features with the OpenAI addon. Add AI Features Build AI-powered endpoints — chat, summarization, content moderation — using the OpenAI addon. What you will build - POST /api/ai/chat — send a message and get an AI response - POST /api/ai/summarize — summarize a block of text - A content moderation pattern for user submissions Steps Install the OpenAI addon Go to Addons and install OpenAI. Add your API key as OPENAI_API_KEY in Settings > Environment Variables. Build a chat endpoint Create POST /api/ai/chat: 1. External API Call — Method: POST, URL: 'https://api.openai.com/v1/responses', Auth: Bearer env.OPENAI_API_KEY, Body: { "model": "", "instructions": "You are a helpful assistant.", "input": "input.message" } Assign To: aiResponse 2. Set Variable — Name: reply, Value: vars.aiResponse.body.output_text 3. Respond — Status: 200, Body: { reply: vars.reply } Send { "message": "What is Spala?" } to test it. Build a summarization endpoint Create POST /api/ai/summarize — same pattern, different system prompt: 1. External API Call — same setup, but with a different instruction: { "model": "", "instructions": "Summarize the following text in 2-3 sentences.", "input": "input.text" } Assign To: result 2. Respond — Body: { summary: vars.result.body.output_text } Add content moderation Before saving user-generated content, check it with OpenAI's moderation endpoint: 1. External API Call — URL: 'https://api.openai.com/v1/moderations', Body: { input: input.content }, Assign To: moderation 2. If/Else — Condition: vars.moderation.body.results | first | get('flagged') == true - True: Respond — Status: 400, Body: { error: 'Content violates community guidelines' } - False: proceed with saving the content Handle errors gracefully Wrap API calls in a Try/Catch step. In the Catch branch, check the status code — 429 means rate-limited (tell the user to retry), and 500+ means a provider error (return a generic error message). Pro tip The same pattern works with other AI providers. Swap the URL and authentication to use Anthropic, Mistral, or any OpenAI-compatible API. Addons /addons Browse AI and other integrations Build a REST API /guides/build-rest-api Create the API structure for your AI features --- title: Add User Authentication route: https://docs.spala.ai/guides/user-auth/ path: /guides/user-auth description: Set up signup, login with JWT tokens, and protect your endpoints. section: guides updated: 2026-07-08 --- # Add User Authentication Set up signup, login with JWT tokens, and protect your endpoints. Add User Authentication Set up user registration, login, and JWT-based endpoint protection. By the end, you will have a working auth system you can add to any project. What you will build - POST /api/auth/register — create a new user account - POST /api/auth/login — sign in and receive a JWT token - A reusable pattern for protecting any endpoint Steps Create the users table In the Database screen, create a users table: | Column | Type | Notes | |--------|------|-------| | id | Serial | Primary key | | email | Text | Unique, required | | password_digest | Text | Required | | name | Text | Optional | | role | Text | Default: 'user' | | created_at | Timestamp | Default: now() | Build the register endpoint Create POST /api/auth/register: 1. Find One — Table: users, Where: { email: input.email }, Assign To: existing 2. If/Else — Condition: vars.existing != null - True: Respond — Status: 409, Body: { error: 'Email already registered' } 3. Hash Password — Password: input.password, Salt Rounds: 12, Assign To: hashedPassword 4. Database Insert — Table: users, Data: { email: input.email, name: input.name, password_digest: vars.hashedPassword }, Returning: id, email, name, Assign To: user 5. Respond — Status: 201, Body: { data: vars.user } Build the login endpoint Create POST /api/auth/login: 1. Find One — Table: users, Where: { email: input.email }, Assign To: user 2. If/Else — Condition: vars.user == null - True: Respond — Status: 401, Body: { error: 'Invalid credentials' } 3. Verify Password — Password: input.password, Hash: vars.user.password_digest, Assign To: isValid 4. If/Else — Condition: vars.isValid == false - True: Respond — Status: 401, Body: { error: 'Invalid credentials' } 5. Generate Auth Token — User ID: vars.user.id, Assign To: token 6. Respond — Status: 200, Body: { token: vars.token } Protect an endpoint The usual production path is to set the endpoint's Authentication option to JWT in the endpoint editor. Spala then rejects missing or invalid tokens before the function runs and exposes decoded auth data to the function. Use manual verification steps only when an endpoint intentionally accepts mixed public/authenticated traffic or needs to verify a secondary token. For that custom case, add these steps at the top of its function: 1. Set Variable — Name: authHeader, Value: headers.authorization 2. If/Else — Condition: vars.authHeader == null - True: Respond — Status: 401, Body: { error: 'No token provided' } 3. Try/Catch - Try: Verify JWT — Token: vars.authHeader | split(' ') | last, Secret: env.JWT_SECRET, Assign To: auth - Catch: Respond — Status: 401, Body: { error: 'Invalid token' } After this, vars.auth.userId and vars.auth.role are available in the rest of the function. Add the JWT secret Go to Settings > Environment Variables and add JWT_SECRET with a long, random string. Test login In the Playground, call POST /api/auth/register with an email and password. Then call POST /api/auth/login with the same credentials and confirm you get a token back. Important Never store plaintext passwords. Always use the Hash Password step with bcrypt before inserting into the database. Build a REST API /guides/build-rest-api Create the endpoints you want to protect API Playground /features/playground Test your auth endpoints in the browser --- title: Advanced CRUD route: https://docs.spala.ai/guides/crud-operations/ path: /guides/crud-operations description: Add pagination, filtering, sorting, and batch operations to your endpoints. section: guides updated: 2026-07-08 --- # Advanced CRUD Add pagination, filtering, sorting, and batch operations to your endpoints. Advanced CRUD Once you have basic CRUD endpoints, add pagination, filtering, and sorting to make them production-ready. This guide builds on the patterns from Build a REST API. Steps Add pagination Update your list endpoint to support ?page=1&limit=20: 1. Set Variable — Name: page, Value: query.page | toNumber | default(1) 2. Set Variable — Name: limit, Value: query.limit | toNumber | default(20) | clamp(1, 100) 3. Set Variable — Name: offset, Value: (vars.page - 1) * vars.limit 4. Count — Table: products, Assign To: total 5. Database Select — Table: products, Limit: vars.limit, Offset: vars.offset, Order By: created_at DESC, Assign To: products 6. Respond — Body: { data: vars.products, pagination: { page: vars.page, limit: vars.limit, total: vars.total, pages: (vars.total / vars.limit) | ceil } } Add filtering Build a dynamic Where clause from query parameters: 1. Set Variable — Name: where, Value: {} 2. If/Else — Condition: query.category != null - True: Set Variable — Value: vars.where | set('category', query.category) 3. If/Else — Condition: query.minPrice != null - True: Set Variable — Value: vars.where | set('price', { $gte: query.minPrice | toNumber }) Pass vars.where as the Where parameter in your Database Select step. Clients filter with ?category=electronics&minPrice=50. Add sorting Accept ?sort=price&order=asc: 1. Set Variable — Name: allowedSorts, Value: ['created_at', 'price', 'name'] 2. If/Else — Condition: vars.allowedSorts | includes(query.sort | default('created_at')) - False: Respond — Status: 400, Body: { error: 'Unsupported sort field' } 3. Set Variable — Name: sortField, Value: query.sort | default('created_at') 4. Set Variable — Name: sortOrder, Value: (query.order == 'asc') ? 'ASC' : 'DESC' 5. Set Variable — Name: orderBy, Value: vars.sortField + ' ' + vars.sortOrder Use vars.orderBy in the Order By property of your Database Select step. Batch updates Create PATCH /api/products/batch for updating multiple records: 1. Loop — Iterable: input.updates, Item Variable: update - Database Update — Table: products, Data: vars.update.data, Where: { id: vars.update.id } 2. Respond — Status: 200, Body: { updated: input.updates | length } Keep sorting safe Always validate sort columns against a whitelist. Do not pass arbitrary query parameter values into an Order By field. Build a REST API /guides/build-rest-api Start with the basic CRUD setup Add User Authentication /guides/user-auth Protect these endpoints --- title: Build a REST API route: https://docs.spala.ai/guides/build-rest-api/ path: /guides/build-rest-api description: Create a complete REST API for case management with tables, endpoints, and CRUD operations. section: guides updated: 2026-07-08 --- # Build a REST API Create a complete REST API for case management with tables, endpoints, and CRUD operations. Build a REST API Create a cases API with full CRUD operations — from database table to tested endpoints — in about 10 minutes. What you will build A cases API with five endpoints: - GET /api/cases — list all cases - GET /api/cases/:id — get a single case - POST /api/cases — create a case - PUT /api/cases/:id — update a case - DELETE /api/cases/:id — delete a case Steps Create the cases table Open the Database screen and create a new table called cases with these columns: | Column | Type | Notes | |--------|------|-------| | id | UUID | Primary key | | case_number | Text | Required, unique external reference | | case_name | Text | Required client-facing title | | description | Text | Summary of the matter | | status | Text | e.g., open, review, closed | | created_at | Timestamp | Default: now() | Create the list endpoint Go to Endpoints and create GET /api/cases. In the function editor, add two steps: 1. Database Select — Table: cases, Order By: created_at DESC, Assign To: cases 2. Respond — Status: 200, Body: { data: vars.cases } Expected response: { "data": [{ "id": "8b6f2f8a-1c5a-4f3d-9b3f-9f9a8d1a2345", "case_number": "CASE-1042", "case_name": "Contract Review", "status": "open" }] } Create the get-by-id endpoint Create GET /api/cases/:id with this function: 1. Find One — Table: cases, Where: { id: params.id }, Assign To: caseRecord 2. If/Else — Condition: vars.caseRecord == null - True: Respond — Status: 404, Body: { error: 'Case not found' } - False: Respond — Status: 200, Body: { data: vars.caseRecord } Create the create endpoint Create POST /api/cases: 1. Database Insert — Table: cases, Data: input, Returning: *, Assign To: newCase 2. Respond — Status: 201, Body: { data: vars.newCase } Send this body to test: { "case_number": "CASE-1043", "case_name": "New Client Intake", "status": "open" } Create update and delete endpoints Create PUT /api/cases/:id with a Database Update step (Where: { id: params.id }, Data: input) and a Respond step. Create DELETE /api/cases/:id with a Database Delete step (Where: { id: params.id }) and a Respond step returning status 204. Test in the Playground Open the Playground screen. Select POST /api/cases, enter a JSON body, and click Send. Then select GET /api/cases and verify your case appears in the list. Pro tip Add input validation by inserting an If/Else step before the database insert to check that input.case_number exists. Advanced CRUD /guides/crud-operations Add pagination, filtering, and sorting Add User Authentication /guides/user-auth Protect your endpoints with JWT tokens API Playground /features/playground Test your endpoints in the browser --- title: Build Realtime Chat route: https://docs.spala.ai/guides/realtime-chat/ path: /guides/realtime-chat description: Set up WebSocket channels, broadcast messages, and build a live chat backend. section: guides updated: 2026-07-08 --- # Build Realtime Chat Set up WebSocket channels, broadcast messages, and build a live chat backend. Build Realtime Chat Build a chat backend where messages appear instantly for all connected users — using WebSocket channels and a message history endpoint. What you will build - A chat_messages table - POST /api/chat/send — send a message and broadcast it live - GET /api/chat/history — fetch recent messages - A WebSocket channel for live delivery Steps Create the messages table In the Database screen, create a chat_messages table: | Column | Type | Notes | |--------|------|-------| | id | Serial | Primary key | | channel | Text | Chat room name | | user_id | Integer | Foreign key to users | | username | Text | Display name | | content | Text | Message body | | created_at | Timestamp | Default: now() | Create a channel Go to the Channels screen and create a new channel called chat. This channel manages WebSocket subscriptions — clients subscribe and receive all events emitted to it. Build the send message endpoint Create POST /api/chat/send (protected with JWT auth): 1. Verify JWT — extract user info from the token 2. Database Insert — Table: chat_messages, Data: { channel: input.channel, user_id: vars.auth.userId, username: vars.auth.username, content: input.content }, Returning: *, Assign To: message 3. Emit Event — Event: new_message, Data: vars.message, Channel: 'chat_' + input.channel 4. Respond — Status: 201, Body: { data: vars.message } The Emit Event step broadcasts the message to every connected client instantly. Build the history endpoint Create GET /api/chat/history: 1. Database Select — Table: chat_messages, Where: { channel: query.channel }, Order By: created_at DESC, Limit: 50, Assign To: messages 2. Set Variable — Name: reversed, Value: vars.messages | reverse 3. Respond — Status: 200, Body: { data: vars.reversed } Connect from the frontend On the client side, open a WebSocket connection and subscribe: const ws = new WebSocket('wss://your-project.spala.dev/ws'); ws.onopen = () => { ws.send(JSON.stringify({ type: 'subscribe', channel: 'chat_general' })); }; ws.onmessage = (event) => { const data = JSON.parse(event.data); if (data.event === 'new_message') { // Append message to your chat UI } }; Add typing indicators (optional) Create POST /api/chat/typing that emits a typing event without saving anything: 1. Emit Event — Event: typing, Data: { username: vars.auth.username }, Channel: 'chat_' + input.channel 2. Respond — Status: 200 Good to know Channel events are scoped by name — chat_general and chat_support operate independently. Use different names to create separate chat rooms. Realtime /channels Learn more about WebSocket channels Add User Authentication /guides/user-auth Set up the auth system for your chat users --- title: External Frontend Handoff route: https://docs.spala.ai/guides/frontend-handoff/ path: /guides/frontend-handoff description: Share the exact Spala project contract a frontend developer or AI coding agent needs when they do not have dashboard access. section: guides updated: 2026-07-08 --- # External Frontend Handoff Share the exact Spala project contract a frontend developer or AI coding agent needs when they do not have dashboard access. External Frontend Handoff Use this page when a React, Next.js, mobile, Webflow, or AI-built frontend needs to connect to a Spala backend but the frontend developer does not have dashboard access. The public docs explain the stable Spala integration rules. A specific frontend still needs the generated project contract from the project owner. Owner action required The project owner or builder should copy this packet from Lite Mode, Project Overview, Settings → API Docs, Settings → Security, Endpoints, and Channels before handing the work to an external frontend developer or AI coding agent. OpenAPI is not the whole frontend contract OpenAPI and generated SDK files cover REST routes. They may not include realtime channel protocol, storage-provider CORS, signed-upload PUT headers, cookie/CSRF details, refresh/logout behavior, or mobile callback rules unless those details are separately documented in the project handoff. Copyable handoff packet # Spala frontend handoff Project name: Environment: preview | production Published backend API: yes | no API_BASE_URL= OpenAPI JSON file or URL= Generated SDK file or URL= Markdown API docs file or URL= Auth: - Login route: - Signup/register route: - Token response field: - Protected request header: Authorization: Bearer USER_JWT - Token lifetime / refresh behavior: - Session mode: bearer token | refresh token | cookie session | custom - Cookie credential mode, if used: include | same-origin | none - CSRF requirement, if cookie session is used: - Logout behavior: Routes: - List the main /api/... routes or attach the generated API Docs export. Errors: - HTTP status codes used by each route: - Error response JSON shape: - Validation error shape: - Auth error shape: - Request id / trace id field, if exposed: Files/uploads: - Upload mode: multipart | signed URL | addon-backed storage | none - Upload route: - Max file size: - Returned file object shape: Realtime: - WebSocket URL or path: - Auth mode: query token | cookie | subprotocol | API key | project-specific handshake | none - Subscribe message envelope: - Event payload examples: - Heartbeat interval / pong timeout: - Close codes: - Replay or no replay: - Permissions/channel access: - Reconnect expectations: CORS: - Frontend origin: - Origin added in Settings → Security → CORS Allowed Origins: yes | no - Backend API republished after CORS/settings change: yes | no - Credentials required by browser requests: yes | no - Expected preflight headers: Public docs: - Public /api/docs enabled: yes | no - If no, attach private Markdown/OpenAPI/SDK exports. Minimum viable handoff At minimum, provide these four items: 1. The exact API_BASE_URL copied from Lite Mode or Project Overview. 2. The generated OpenAPI JSON, Markdown docs, or TypeScript SDK from Settings → API Docs. 3. The auth route and token response shape. 4. Confirmation that the frontend origin is allowed in Settings → Security → CORS Allowed Origins. Without those, an external frontend developer can understand Spala but cannot safely wire a real private project. If the project uses uploads, realtime, cookies, CSRF, refresh tokens, OAuth callbacks, or direct-to-storage signed URLs, the owner must also include those contracts. Do not assume OpenAPI or the generated SDK fully describes them. Auth/session fields to include Generated Spala projects commonly use bearer JWT auth, but projects can define different session behavior. Include the exact variant used by the project: | Session field | What the frontend needs | | --- | --- | | Login and signup routes | Exact /api/... paths and request bodies from generated API Docs | | Token field | Exact JSON field such as token, accessToken, or data.token | | Refresh behavior | Whether refresh exists, the refresh route, expiry, and retry rules | | Cookie sessions | Whether requests need credentials: "include" and whether CSRF headers are required | | Logout | Whether logout is local token clear, server-side session revoke, or both | | Error semantics | Expected 401 and 403 behavior | If the project uses cookies, include the cookie mode and CSRF header names. If it uses bearer tokens, include the token lifetime and storage expectation. Public Spala docs describe the patterns; the generated project docs are the source of truth. REST error fields to include REST error handling is route-specific. A public documentation page cannot provide a private project's actual error response bodies. Before a frontend developer or AI agent wires error handling, the project owner should copy the status codes and error JSON examples from generated API Docs, OpenAPI, SDK types, or API Playground. At minimum, include: | Error field | What the frontend needs | | --- | --- | | Status codes | Expected 400, 401, 403, 404, 409, 422, and 500 cases for each route, as applicable | | Error body shape | Exact JSON body returned by the route, such as message, code, details, fieldErrors, or project-specific fields | | Validation errors | Field-level validation format and how arrays/nested objects are reported | | Auth errors | Token-expired, missing-token, invalid-token, and insufficient-permission behavior | | Request trace | Request id, trace id, or log correlation field if the project exposes one | Do not assume one universal error schema across all Spala projects. If a route's error response is not shown in generated docs, test the route in API Playground before wiring frontend error handling. CORS fields to include For browser frontends, include the exact deployed frontend origin, not a wildcard or partial host: Frontend origin: https://app.example.com Methods used: GET, POST, PUT, PATCH, DELETE Request headers: Content-Type, Authorization Credentials: true | false The origin must match the browser page origin, including scheme, host, and port. After changing Settings → Security → CORS Allowed Origins, publish the backend API again before asking the frontend developer to retest. Use CORS and Security for the exact owner checklist. Example SDK handoff If Settings → API Docs generated a TypeScript SDK, attach it or share the authenticated download route. A minimal generated SDK normally exposes the base URL, typed request helpers, and route functions similar to this: export type SpalaClientOptions = { baseUrl: string; token?: string; }; export function createSpalaClient(options: SpalaClientOptions) { async function request(path: string, init: RequestInit = {}): Promise { const response = await fetch(`${options.baseUrl}${path}`, { ...init, headers: { "Content-Type": "application/json", ...(options.token ? { Authorization: `Bearer ${options.token}` } : {}), ...init.headers, }, }); if (!response.ok) { throw new Error(`Spala API error ${response.status}`); } return response.json() as Promise; } return { listCases: () => request>("/api/cases"), }; } This snippet shows the expected shape only. Use the project-generated sdk.ts for real route names and types. Realtime fields to include If the project uses realtime channels, the owner should copy the contract from Channels and the generated project docs into this handoff. There is no safe public-docs default for a private project's realtime protocol. Owner workflow: 1. Open the project in the dashboard. 2. Open Channels and select the channel used by the frontend. 3. Copy the exact WebSocket path or URL, auth mode, allowed audience, and permissions. 4. Copy subscribe, event, error, heartbeat, close-code, replay, and reconnect examples from the channel configuration or generated project docs. 5. Add those examples to the handoff packet before assigning frontend work. Include a complete message sample: { "connectUrl": "wss://PROJECT_HOST/ws?token=USER_JWT", "subscribe": { "type": "subscribe", "channel": "cases" }, "event": { "type": "case.updated", "channel": "cases", "payload": { "id": "case_123", "status": "open" } }, "error": { "type": "error", "code": "unauthorized", "message": "Invalid token" } } Also state whether replay, presence, acknowledgements, or reconnect backoff are implemented. If the project does not define those behaviors, the frontend should treat realtime as best-effort live updates and fetch REST state after reconnect. No dashboard access workflow 1. Project owner publishes or previews the backend API. 2. Project owner exports API Docs from Settings → API Docs. 3. Project owner copies the API base URL from Lite Mode or Project Overview. 4. Project owner copies realtime, upload, cookie/CSRF, refresh/logout, and mobile callback details when the project uses them. 5. Project owner adds the frontend origin in Settings → Security. 6. Project owner republishes the backend API after CORS/security changes. 7. Project owner sends the handoff packet and generated docs to the frontend developer. 8. Frontend developer stores the base URL in VITE_SPALA_API_BASE_URL or NEXT_PUBLIC_SPALA_API_BASE_URL. 9. Frontend developer tests one public route, one auth route, and one protected route before building the full UI. Verification commands Replace the placeholders with project values. curl "$API_BASE_URL/api/health" curl -X POST "$API_BASE_URL/api/auth/login" \ -H "Content-Type: application/json" \ --data '{"email":"user@example.com","password":"example"}' curl "$API_BASE_URL/api/me" \ -H "Authorization: Bearer USER_JWT" If browser calls fail but curl works, check CORS first. The frontend origin must match exactly, including scheme and port, and published settings must be live. Handoff quality checklist - API_BASE_URL is exact and includes any required scoped path. - OpenAPI, Markdown docs, or SDK matches the currently published API. - Auth token response is documented with the exact field name. - Route-specific error response shapes are documented or verified in API Playground. - Upload and realtime contracts are included when those features are used. - CORS origin is configured before browser integration starts. - Public docs are intentionally enabled, or private docs exports are attached. - The frontend developer knows whether they are targeting preview or production. Frontend Integration Cookbook /guides/frontend-integration Stable frontend request, auth, upload, realtime, and CORS patterns API Docs /features/api-docs Export generated project contracts CORS and Security /settings/cors-security Add frontend origins and publish security changes Publish /features/publish-export Publish backend API changes before external integrations depend on them --- title: Frontend Integration Cookbook route: https://docs.spala.ai/guides/frontend-integration/ path: /guides/frontend-integration description: Connect a frontend to a Spala backend with base URL, routes, auth headers, file upload, realtime, and env vars. section: guides updated: 2026-07-08 --- # Frontend Integration Cookbook Connect a frontend to a Spala backend with base URL, routes, auth headers, file upload, realtime, and env vars. Frontend Integration Cookbook Use this page when a frontend developer or AI coding agent needs to connect an app UI to a Spala project API. Specific project handoff required Public docs cannot contain a private project's real base URL, route list, auth payloads, upload modes, or realtime channels. To integrate a specific project, start with that project's generated API Docs export from Settings → API Docs. Use this page to understand the stable Spala integration patterns around that project contract. If the frontend developer or AI coding agent does not have dashboard access, first send the packet from External Frontend Handoff. It defines the exact API_BASE_URL, OpenAPI/SDK files, auth routes, upload mode, realtime path, and CORS origin needed for a safe integration. Guaranteed discovery flow Spala projects are configurable, so the public docs cannot safely derive a real project API base URL or route list from a slug. The guaranteed integration flow is: 1. Open the project in https://dashboard.spala.ai. 2. Copy the API base URL from Lite Mode or Project Overview. 3. Open Settings → API Docs. 4. Export or copy the project contract: Markdown docs, JSON docs, OpenAPI JSON, SDK files, or snippets where enabled. 5. Wire the frontend from that generated contract. 6. Use this cookbook for the standard request, auth, upload, realtime, environment, and CORS patterns. Example OpenAPI shape: https://docs.spala.ai/examples/spala-openapi-example.json That file is an example contract shape only. Real projects expose their own generated API contract from Settings → API Docs. REST docs are not the whole integration OpenAPI JSON and generated SDK files describe REST endpoints. They may not cover realtime channel protocol, signed-upload storage CORS, required direct-upload PUT headers, cookie/CSRF behavior, refresh/logout rules, OAuth callback URLs, or mobile-specific storage and resume behavior. Include those details separately in the frontend handoff when the project uses them. Project integration artifacts Use the generated project artifacts as the source of truth. In the hosted dashboard, Settings → API Docs gives the same contract in UI form. For authenticated project tooling, the generated docs routes are: | Artifact | Route | Access | | --- | --- | --- | | Markdown API docs | GET {{PROJECT_BASE_URL}}/api/__internal/docs | Builder authentication | | JSON API docs | GET {{PROJECT_BASE_URL}}/api/__internal/docs?format=json | Builder authentication | | OpenAPI JSON | GET {{PROJECT_BASE_URL}}/api/__internal/docs/openapi.json | Builder authentication | | TypeScript SDK | GET {{PROJECT_BASE_URL}}/api/__internal/docs/sdk.ts | Builder authentication | | Public Markdown docs | GET {{PROJECT_BASE_URL}}/api/docs | Only when public docs are enabled in Security | | Public JSON docs | GET {{PROJECT_BASE_URL}}/api/docs?format=json | Only when public docs are enabled in Security | | Swagger UI | Settings → API Docs | Use the dashboard UI unless your project explicitly exposes a public Swagger route | For shared-runtime projects, the project base can include a scoped path such as https://shared.spala.ai/PROJECT_ID. Do not strip that path. Use the exact base URL and full URLs shown by the generated docs. Do not expose builder docs by accident The api/__internal/docs routes require builder authentication. Only enable public api/docs when you intentionally want the project API contract to be readable without builder auth. Find the API base URL The API base URL is shown in Lite Mode and Project Overview. Copy it from the project workspace after the project has been published or previewed. Use the full base URL plus the endpoint path: SPALA_API_BASE_URL=https://your-project-host.example GET {{SPALA_API_BASE_URL}}/api/cases POST {{SPALA_API_BASE_URL}}/api/cases Do not guess the host. Use the value shown in the project. Contract discovery matrix | Need | Where to find it | Stable rule | | --- | --- | --- | | API base URL | Lite Mode or Project Overview | Copy the displayed value; do not infer it from project name | | REST routes | Endpoints or Settings → API Docs | Use the exact /api/... paths in the project | | Markdown/JSON docs | Settings → API Docs or GET /api/__internal/docs | Use the generated project artifact as the source of truth | | OpenAPI JSON | Settings → API Docs or GET /api/__internal/docs/openapi.json | Use the generated project artifact as the source of truth | | TypeScript SDK | Settings → API Docs or GET /api/__internal/docs/sdk.ts | Use the generated project artifact as the source of truth | | Auth routes | Endpoints or API Docs | Common routes are /api/auth/login and /api/auth/register, but project docs are authoritative | | Upload mode | API Docs and file upload endpoint | Multipart and signed URL flows are different contracts | | Realtime URL | Channels and generated project docs | Use the project WebSocket path, auth mode, message envelope, heartbeat, replay, and permissions | | Browser origins | Settings → Security → CORS Allowed Origins | Add the frontend origin and republish if browser calls are blocked | Environment variables For Vite: VITE_SPALA_API_BASE_URL=https://your-project-host.example export const SPALA_API_BASE_URL = import.meta.env.VITE_SPALA_API_BASE_URL; For Next.js: NEXT_PUBLIC_SPALA_API_BASE_URL=https://your-project-host.example export const SPALA_API_BASE_URL = process.env.NEXT_PUBLIC_SPALA_API_BASE_URL!; Public endpoint call const response = await fetch(`${SPALA_API_BASE_URL}/api/cases`); if (!response.ok) { throw new Error(`Spala API error: ${response.status}`); } const cases = await response.json(); Protected endpoint call Protected endpoints expect a user JWT from your login flow. const response = await fetch(`${SPALA_API_BASE_URL}/api/me`, { headers: { Authorization: `Bearer ${userJwt}`, }, }); if (response.status === 401) { // Send the user back through your login flow. } const profile = await response.json(); Auth contract Common generated auth endpoints return a user token that frontends send as a bearer token. Treat the project API Docs as the authoritative contract for exact route names and response shape. Typical login response: { "token": "USER_JWT" } Some projects also return a user object or a data wrapper. The generated API Docs for the project are authoritative; the stable frontend rule is to extract the token value returned by the login endpoint and send it as a bearer token. Typical protected request: Authorization: Bearer USER_JWT Recommended frontend behavior: - Keep tokens out of logs and source control. - On 401, clear local session state and send the user through login again. - On 403, keep the user logged in but show a permissions message. - Confirm refresh-token behavior from the generated project API Docs if the project implements refresh tokens. Session variants | Variant | Frontend request behavior | Notes | | --- | --- | --- | | Bearer JWT | Send Authorization: Bearer USER_JWT on protected requests | Most common generated pattern | | Bearer JWT with refresh | Retry once through the project refresh route, then send the new token | Use only if generated API Docs expose refresh | | Cookie session | Send credentials: "include" and follow CSRF rules if configured | Requires exact CORS credentials settings | | API key or custom header | Send the header documented by the project | Common for server-to-server or internal tools | Browser clients cannot invent session behavior. If the project docs do not mention refresh tokens, cookie sessions, or CSRF, assume bearer-token login and re-login on expiry. Token storage Store user tokens according to your frontend threat model. Prefer short-lived tokens, avoid logging tokens, and never commit real tokens into source code or docs. Login example The exact route names depend on your project. A common pattern is: const response = await fetch(`${SPALA_API_BASE_URL}/api/auth/login`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ email, password, }), }); if (!response.ok) { throw new Error("Login failed"); } const { token } = await response.json(); File upload example Use FormData for multipart upload endpoints. const form = new FormData(); form.append("file", file); const response = await fetch(`${SPALA_API_BASE_URL}/api/upload`, { method: "POST", headers: { Authorization: `Bearer ${userJwt}`, }, body: form, }); if (!response.ok) { throw new Error(`Upload failed: ${response.status}`); } const uploadedFile = await response.json(); If your project uses S3 or signed URLs, follow the route contract generated in Settings → API Docs. Do not mix multipart upload and signed URL flows unless the project explicitly exposes both. Upload contract matrix | Upload mode | Request | Response | When to use | | --- | --- | --- | --- | | Multipart endpoint | POST /api/upload with FormData | JSON record for the stored file | Simple browser file uploads through the project API | | Signed URL | Request signed URL, then upload directly to storage | Storage URL or file metadata | Larger files or direct-to-S3 style flows | | Addon-backed storage | Project-specific endpoint calls an addon such as S3 | Project-defined JSON | When storage provider behavior is part of backend logic | Signed URL frontend sequence: const signResponse = await fetch(`${SPALA_API_BASE_URL}/api/uploads/sign`, { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${userJwt}`, }, body: JSON.stringify({ filename: file.name, contentType: file.type, size: file.size, }), }); const { uploadUrl, fileId, headers = {} } = await signResponse.json(); const uploadResponse = await fetch(uploadUrl, { method: "PUT", headers, body: file, }); if (!uploadResponse.ok) { throw new Error(`Storage upload failed: ${uploadResponse.status}`); } await fetch(`${SPALA_API_BASE_URL}/api/uploads/${fileId}/complete`, { method: "POST", headers: { Authorization: `Bearer ${userJwt}`, }, }); For signed URLs, the storage bucket CORS policy may also need to allow the frontend origin. That is separate from the Spala project API CORS setting. Signed upload contract fields to include: | Field | Why it matters | | --- | --- | | Required PUT headers | Some storage signatures require exact Content-Type, checksum, or metadata headers | | Content type | The uploaded Content-Type may need to match the signing input exactly | | Size limits | The project or storage provider may reject files above the signed limit | | Retry/cancel behavior | Retrying may require a new signed URL if the old one expires | | Complete body | The finalize route may need storage key, file id, checksum, or public URL | | File object schema | Frontends need the returned id, url, name, size, and metadata shape | CORS and browser request behavior Server-to-server calls and curl do not prove that browser calls will work. Browser frontends also need a matching CORS configuration. Checklist for browser calls: 1. Add the exact frontend origin in Settings → Security → CORS Allowed Origins. 2. Include the scheme and port, such as http://localhost:5173 or https://app.example.com. 3. Publish the backend API after changing CORS settings. 4. If the frontend sends bearer tokens, allow the Authorization request header. 5. If the frontend sends JSON bodies, allow Content-Type. 6. If the project uses cookie sessions, enable credentialed requests and call fetch with credentials: "include". Use CORS and Security for the owner-side settings checklist. Example preflight the browser may send: OPTIONS /api/cases HTTP/1.1 Origin: https://app.example.com Access-Control-Request-Method: POST Access-Control-Request-Headers: authorization, content-type Expected allowed response shape: Access-Control-Allow-Origin: https://app.example.com Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS Access-Control-Allow-Headers: Authorization, Content-Type If credentials are enabled, Access-Control-Allow-Origin must be the exact origin, not *, and the response should also include: Access-Control-Allow-Credentials: true Cookie-session fetch example: const response = await fetch(`${SPALA_API_BASE_URL}/api/me`, { credentials: "include", headers: { "X-CSRF-Token": csrfToken, }, }); The CSRF header name, cookie attributes, and whether CSRF is required are project-specific. Confirm them from generated project docs before using cookie sessions. Cookie-session checklist: | Field | What to confirm | | --- | --- | | SameSite | Lax, Strict, or None; cross-site cookies require SameSite=None | | Secure | Required for cross-site HTTPS cookies | | Domain/path | Which frontend and API hosts receive the cookie | | CSRF source | Meta tag, cookie, endpoint, or generated page value | | Logout | Whether logout expires the cookie, revokes the server session, or both | Realtime connection example Realtime channel URLs are project-specific. Use the WebSocket URL shown by the project or documented in generated project docs. Do not assume the generated OpenAPI file contains the realtime protocol. const wsUrl = new URL("/ws", SPALA_API_BASE_URL); wsUrl.protocol = wsUrl.protocol === "https:" ? "wss:" : "ws:"; wsUrl.searchParams.set("token", userJwt); const socket = new WebSocket(wsUrl.toString()); socket.addEventListener("open", () => { socket.send(JSON.stringify({ type: "subscribe", channel: "cases", })); }); socket.addEventListener("message", (event) => { const message = JSON.parse(event.data); console.log("Spala realtime message", message); }); The default examples use /ws because it is the common channel path, but the project channel settings win. If the project base URL includes a scoped path, or the channel uses a path such as /ws/chat, copy the exact WebSocket URL or path from the generated project docs. Do not strip scoped paths from shared-runtime URLs. Common message envelope: { "type": "subscribe", "channel": "cases" } Common event and error envelopes: { "type": "case.updated", "channel": "cases", "payload": { "id": "case_123", "status": "open" } } { "type": "error", "code": "unauthorized", "message": "Invalid or expired token" } Reconnect behavior, presence, history replay, and channel-specific payloads are project-defined. Confirm them from the generated project docs or channel configuration. Owner realtime contract workflow: 1. Open Channels in the project dashboard. 2. Select the channel the frontend will use. 3. Copy the exact WebSocket URL or path, auth mode, permissions, subscribe envelope, event examples, errors, heartbeat interval, pong timeout, close codes, replay behavior, and reconnect expectations. 4. Attach that contract to the frontend handoff packet. 5. If the contract is missing, treat realtime integration as blocked until the owner supplies it. Common realtime operational fields to include in a handoff: | Field | Example | | --- | --- | | Heartbeat | Server sends { "type": "ping" }; client replies { "type": "pong" } | | Close codes | 1000 normal, 1008 auth or policy failure, project-specific codes | | Acknowledgement | { "type": "ack", "id": "msg_123" }, if implemented | | Replay | Last-event-id, cursor, or no replay | | Reconnect | Exponential backoff such as 1s, 2s, 5s, 10s, max 30s | If no replay is implemented, refetch REST state after reconnect. Mobile clients Native mobile apps do not use browser CORS, but they still need the exact same project contract: API base URL, auth routes, token field, upload mode, realtime path, and publish environment. Store tokens in platform secure storage, not plain local storage. Confirm deep-link or callback URLs if the project uses OAuth providers. Reconnect websockets with backoff and refetch REST state after app resume. Mobile implementation notes: | Platform concern | Guidance | | --- | --- | | Token storage | Use iOS Keychain, Android Keystore, Expo SecureStore, or another platform secure store | | File uploads | Convert platform file URI/blob data to the request body expected by the project upload route | | OAuth callbacks | Confirm deep-link scheme, universal link, or app link callback URLs before release | | App resume | Treat resume as a possible stale-session event; refetch /api/me and resubscribe realtime channels | | WebSocket recovery | Reconnect with backoff and refetch REST state if replay is not guaranteed | CORS and trusted origins Browser frontends must be allowed by the project security settings when credentials or restricted origins are involved. 1. Open Settings → Security. 2. Find CORS Allowed Origins. 3. Add the exact frontend origin, for example https://app.example.com. 4. Save security settings. 5. Publish backend API changes before expecting saved security settings to affect the live published API. Origins must include scheme and host. Do not add paths. For local development, add the exact dev origin such as http://localhost:5173. If browser requests fail before reaching your endpoint, check DevTools for a CORS error, confirm the origin matches exactly, and verify that the frontend is calling the copied project API base URL. For production, confirm the exact realtime auth contract in your project docs. Some projects use bearer headers through a client library, query tokens, cookies, or a project-specific handshake. Realtime contract matrix | Item | Rule | | --- | --- | | URL | Use the WebSocket URL or path generated for the project | | Browser auth | Browsers cannot set arbitrary WebSocket Authorization headers; use the documented project handshake | | Message shape | Use the channel event envelope from project API Docs | | Reconnect | Add reconnect/backoff logic in production clients | | Permissions | Confirm whether the channel uses public, JWT, API key, or project-specific auth | Frontend quick verify Before a frontend developer or AI coding agent starts implementation, give them: 1. Project API base URL. 2. Generated Markdown docs, OpenAPI JSON, or SDK. 3. Auth route and token response shape. 4. Upload endpoint contract if files are involved. 5. Realtime path and message envelope if live updates are involved. 6. Required frontend origin in Settings → Security → CORS Allowed Origins. 7. Confirmation whether public docs are intentionally enabled for this project or builder-authenticated docs must be used. Use External Frontend Handoff when this information needs to be shared as one copyable packet. Integration checklist - API base URL copied from Lite Mode or Project Overview - Endpoint paths copied from Endpoints or API Docs - Auth routes tested in API Playground - Protected calls send Authorization: Bearer USER_JWT - Upload route contract confirmed before wiring file inputs - Realtime URL and auth handshake confirmed from project docs - VITE_SPALA_API_BASE_URL or NEXT_PUBLIC_SPALA_API_BASE_URL configured - CORS/trusted origins configured in project settings when browser calls are blocked API Endpoints /endpoints Create and inspect REST routes External Frontend Handoff /guides/frontend-handoff Copyable packet for developers without dashboard access Protect Your Endpoints /endpoints/authentication JWT and protected endpoint behavior Upload Files /guides/file-uploads Build file upload endpoints Realtime Channels /channels/realtime Build realtime subscriptions CORS and Security /settings/cors-security Add frontend origins and publish security changes API Docs /features/api-docs Export OpenAPI and Markdown contracts --- title: Run Scheduled Jobs route: https://docs.spala.ai/guides/scheduled-jobs/ path: /guides/scheduled-jobs description: Automate cleanup routines, reports, and data syncing with Spala tasks. section: guides updated: 2026-07-08 --- # Run Scheduled Jobs Automate cleanup routines, reports, and data syncing with Spala tasks. Run Scheduled Jobs Use tasks for backend work that should run without a user request: cleanup routines, recurring reports, imports, sync jobs, and long-running operations. Steps Create a task Go to Tasks and click New Task. Give it a clear name, such as cleanup-expired-sessions or sync-stripe-customers. Choose how it runs Set a repeat frequency and unit, such as every 15 minutes, every 1 hour, or every 1 day. Leave the schedule empty when you want a manual task that only runs when started directly. Build the task function Add steps for the work the task should do. For a cleanup task, query stale records, delete or update them, then log the result. Tune execution Use Run in Background for longer work. Set timeout and memory limits so expensive jobs fail predictably instead of silently consuming resources. Example Cleanup Task 1. Set Variable - Name: cutoff, Value: '' | now | addHours(-24) | toISO 2. Database Delete - Table: sessions, Where: { expires_at: { $lt: vars.cutoff } }, Returning: id, Assign To: deleted 3. Log - Message: 'Cleaned up ' + (vars.deleted | length) + ' expired sessions' When To Use Manual Tasks Manual tasks are useful for admin jobs that should not run on a timer: - Backfill missing data after an import - Recalculate analytics - Re-send a batch of notifications - Run a one-off cleanup before publish Use background execution for long jobs Tasks that process many records or call external APIs should run in the background. Monitor them from Background Tasks to see status, logs, result data, retries, and failures. Scheduled Tasks /tasks/scheduled-tasks Configure repeat frequency, manual runs, and resource limits Background Tasks /tasks/background-tasks Monitor queued, running, completed, and failed work Send Emails /guides/send-emails Send reports and alerts from tasks --- title: Send Emails route: https://docs.spala.ai/guides/send-emails/ path: /guides/send-emails description: Configure email delivery and send transactional emails from your backend functions. section: guides updated: 2026-07-08 --- # Send Emails Configure email delivery and send transactional emails from your backend functions. Send Emails Set up email delivery and send transactional emails — password resets, welcome messages, order confirmations — from any backend function. What you will build - Email addon configured with SMTP or SendGrid - POST /api/auth/forgot-password — sends a password reset email - A reusable email template pattern Steps Install the email addon Go to Addons and install the Email addon. Then add your provider's credentials in Settings > Environment Variables: For SMTP: - SMTP_HOST — e.g., smtp.gmail.com - SMTP_PORT — typically 587 - SMTP_USER — your email address - SMTP_PASS — your password or app password For SendGrid: - SENDGRID_API_KEY — your API key from the SendGrid dashboard Build the forgot-password endpoint Create POST /api/auth/forgot-password: 1. Find One — Table: users, Where: { email: input.email }, Assign To: user 2. If/Else — Condition: vars.user == null - True: Respond — Status: 200, Body: { message: 'If an account exists, a reset email has been sent' } 3. Random String — Length: 32, Characters: hex, Assign To: resetToken 4. Database Update — Table: users, Data: { reset_token: vars.resetToken, reset_expires: '' | now | addHours(1) | toISO }, Where: { id: vars.user.id } 5. Send Email — To: vars.user.email, Subject: 'Password Reset Request', Body: your HTML template (see next step) 6. Respond — Status: 200, Body: { message: 'If an account exists, a reset email has been sent' } Create the email template Use HTML in the Send Email body for formatted emails: '

Reset Your Password

' + '

Hi ' + vars.user.name + ',

' + '

Click the link below to reset your password. This link expires in 1 hour.

' + 'Reset Password' Test email delivery Use the Playground to call your forgot-password endpoint. During development, use a service like Mailtrap to capture test emails without sending real ones. Pro tip For production, use a dedicated email service like SendGrid, Mailgun, or Amazon SES. They offer better deliverability and higher sending limits than personal SMTP. Add User Authentication /guides/user-auth Set up the user system that needs emails Addons /addons Browse email and communication addons --- title: Upload Files route: https://docs.spala.ai/guides/file-uploads/ path: /guides/file-uploads description: Accept file uploads, store them in S3 or locally, and serve them back. section: guides updated: 2026-07-08 --- # Upload Files Accept file uploads, store them in S3 or locally, and serve them back. Upload Files Accept file uploads from clients, validate them, store them in S3 or locally, and serve them back through your API. What you will build - POST /api/upload — accept and store a file - GET /api/files/:filename — serve a stored file Steps Install a storage addon Go to Addons and install Local Storage (for development) or S3 Storage (for production). S3 requires your bucket name, region, access key, and secret key in Settings > Environment Variables. Create a files table In the Database screen, create a files table: | Column | Type | Notes | |--------|------|-------| | id | Serial | Primary key | | filename | Text | Original file name | | path | Text | Storage path | | size | Integer | File size in bytes | | mimetype | Text | e.g., image/png | | created_at | Timestamp | Default: now() | Build the upload endpoint Create POST /api/upload: 1. Upload File — Field Name: file, Destination: 'uploads/', Max Size: 5242880 (5 MB), Allowed Types: ['image/png', 'image/jpeg', 'application/pdf'], Assign To: uploaded 2. Database Insert — Table: files, Data: { filename: vars.uploaded.originalName, path: vars.uploaded.path, size: vars.uploaded.size, mimetype: vars.uploaded.mimetype }, Returning: *, Assign To: fileRecord 3. Respond — Status: 201, Body: { data: vars.fileRecord } Build the download endpoint Create GET /api/files/:filename: 1. Find One — Table: files, Where: { filename: params.filename }, Assign To: fileRecord 2. If/Else — Condition: vars.fileRecord == null - True: Respond — Status: 404, Body: { error: 'File not found' } 3. Download File — Path: vars.fileRecord.path, Filename: vars.fileRecord.filename, Content Type: vars.fileRecord.mimetype Test the upload In the Playground, select POST /api/upload. Switch the body type to Form Data, add a field named file with type File, pick a file from your computer, and click Send. Good to know When you switch from Local Storage to S3 Storage for production, your upload and download flows stay the same. The storage addon handles the difference. Signed URL Upload Flow Some projects avoid sending large files through the project API. In that setup, the frontend asks Spala for a signed storage URL, uploads the file directly to storage, then calls the project API again to finalize metadata. Typical frontend sequence: 1. POST /api/uploads/sign with filename, content type, and size. 2. Receive uploadUrl, optional required headers, and a project file id. 3. PUT the file bytes directly to uploadUrl. 4. POST /api/uploads/:id/complete so the backend records metadata and returns the project file object. Example: const signed = await fetch(`${SPALA_API_BASE_URL}/api/uploads/sign`, { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${userJwt}`, }, body: JSON.stringify({ filename: file.name, contentType: file.type, size: file.size, }), }).then((response) => response.json()); await fetch(signed.uploadUrl, { method: "PUT", headers: signed.headers ?? {}, body: file, }); const fileRecord = await fetch(`${SPALA_API_BASE_URL}/api/uploads/${signed.fileId}/complete`, { method: "POST", headers: { Authorization: `Bearer ${userJwt}`, }, }).then((response) => response.json()); The exact route names and response fields are generated by the project. If the upload goes directly to S3 or another storage provider, that storage provider also needs its own CORS policy for the frontend origin. Addons /addons Browse storage addons Build a REST API /guides/build-rest-api Create the API your uploads belong to --- title: API Steps route: https://docs.spala.ai/reference/steps/api/ path: /reference/steps/api description: Steps for making HTTP requests, sending responses, and managing headers and cookies. section: reference updated: 2026-07-08 --- # API Steps Steps for making HTTP requests, sending responses, and managing headers and cookies. API Steps API steps handle HTTP communication -- making outbound requests to external services and sending responses back to clients. External API Call Makes an HTTP request to an external API. Supports all common HTTP methods and authentication schemes. Method: POST URL: 'https://api.stripe.com/v1/charges' Headers: { 'Content-Type': 'application/x-www-form-urlencoded' } Body: { amount: vars.amount, currency: 'usd' } Auth Type: bearer Auth Value: env.STRIPE_SECRET_KEY Assign To: chargeResult The result stored in vars.chargeResult contains: - body -- the parsed response body - status -- the HTTP status code - headers -- the response headers Respond Sends an HTTP response to the client. Use this to control exactly what the client receives. Status Code: 201 Body: { success: true, user: vars.newUser } Headers: { 'X-Request-Id': vars.requestId } If no Respond step is used, the flow automatically responds with the value from the Return step, or an empty 200 response. Redirect Sends an HTTP redirect response to the client. URL: '/dashboard' Status Code: 302 Set Header Sets a response header for the current request. Name: Content-Type Value: 'application/xml' Set Cookie Sets a cookie on the client response. Name: session_token Value: vars.token Max Age: 86400 HTTP Only: true Secure: true Same Site: strict HTTP method: `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `HEAD`, `OPTIONS`. The full URL to call. Request headers as key-value pairs. Request input. Automatically serialized to JSON for object values. URL query parameters as key-value pairs. Authentication type: `none`, `bearer`, `basic`, `api-key`. The token, credentials, or API key depending on auth type. Request timeout in milliseconds. Defaults to 30000. Variable name to store the response (includes `body`, `status`, `headers`). HTTP status code. Defaults to 200. The response input. Additional response headers. The URL to redirect to. Redirect status code: `301` (permanent) or `302` (temporary). Defaults to 302. The header name. The header value. The cookie name. The cookie value. Cookie lifetime in seconds. Cookie path. Defaults to `/`. Whether the cookie is inaccessible to JavaScript. Defaults to true. Whether to only send over HTTPS. Defaults to false. SameSite policy: `strict`, `lax`, or `none`. Steps Reference /reference/steps Browse all step categories API Endpoints /endpoints Create endpoints that use API steps Auth Steps /reference/steps/auth Add authentication to your API --- title: Array Filters route: https://docs.spala.ai/reference/filters/array/ path: /reference/filters/array description: Filters for transforming, searching, and manipulating arrays. section: reference updated: 2026-07-08 --- # Array Filters Filters for transforming, searching, and manipulating arrays. Array Filters Array filters manipulate lists of data. They are especially useful with database results and collections. Usage examples Get unique categories from products: vars.products | map('category') | unique | sort Paginate results: vars.allItems | slice(vars.offset, vars.offset + vars.limit) Calculate order total: vars.orderItems | reduce('price', 0) Group and count by status: vars.orders | groupBy('status') // { pending: [...], shipped: [...], delivered: [...] } Filters Reference /reference/filters Browse all filter categories Object Filters /reference/filters/object Transform objects and key-value pairs String Filters /reference/filters/string Transform text strings --- title: Auth Steps route: https://docs.spala.ai/reference/steps/auth/ path: /reference/steps/auth description: Steps for JWT tokens, password hashing, and API key generation. section: reference updated: 2026-07-08 --- # Auth Steps Steps for JWT tokens, password hashing, and API key generation. Auth Steps Auth steps provide common authentication and authorization operations -- creating tokens, hashing passwords, and generating API keys. Sign JWT Creates a JSON Web Token with a payload and signing secret. Payload: { userId: vars.user.id, role: vars.user.role } Secret: env.JWT_SECRET Expires In: 7d Assign To: token Verify JWT Verifies a JWT and extracts its payload. Throws an error if the token is invalid or expired. Token: headers.authorization | split(' ') | last Secret: env.JWT_SECRET Assign To: decoded Wrap Verify JWT in a Try/Catch step to handle invalid or expired tokens gracefully and return a 401 response. Hash Password Hashes a plaintext password using bcrypt for secure storage. Password: input.password Salt Rounds: 12 Assign To: hashedPassword Verify Password Compares a plaintext password against a bcrypt hash. Returns true if they match, false otherwise. Password: input.password Hash: vars.user.password_digest Assign To: isValid Generate API Key Generates a cryptographically secure random API key string. Prefix: sk_live_ Length: 48 Assign To: apiKey The data to encode in the token (e.g., user ID, role). The signing secret. Use `env.JWT_SECRET` for environment variables. Token expiration duration (e.g., `1h`, `7d`, `30m`). Defaults to `1h`. Signing algorithm: `HS256`, `HS384`, `HS512`. Defaults to `HS256`. Variable name to store the generated token string. The JWT string to verify. The signing secret used to create the token. Variable name to store the decoded payload. The plaintext password to hash. Number of bcrypt salt rounds. Defaults to 10. Variable name to store the hashed password. The plaintext password to verify. The bcrypt hash to compare against. Variable name to store the boolean result. Length of the generated key in characters. Defaults to 32. Optional prefix for the key (e.g., `sk_live_`). Variable name to store the generated key. Steps Reference /reference/steps Browse all step categories Add User Authentication /guides/user-auth Step-by-step auth guide Crypto Steps /reference/steps/crypto Encryption and hashing steps --- title: Control Flow Steps route: https://docs.spala.ai/reference/steps/control-flow/ path: /reference/steps/control-flow description: Steps for conditional branching, loops, error handling, and flow control. section: reference updated: 2026-07-08 --- # Control Flow Steps Steps for conditional branching, loops, error handling, and flow control. Control Flow Steps Control flow steps determine the execution path of your flow -- branching, looping, and handling errors. If/Else Executes one branch if a condition is true, and optionally another if it is false. The If/Else step creates two branches on the canvas: a True branch and a False branch. Place subsequent steps inside either branch. Condition: vars.user != null && vars.user.role == 'admin' Switch Multi-way branching based on the value of an expression. Each case defines a value to match and a branch of steps to execute. Expression: params.action Cases: ['create', 'update', 'delete'] Default: true Loop Iterates over an array or a numeric range, executing the contained steps for each iteration. Iterable: vars.products Item Variable: product Index Variable: i Inside the loop body, access vars.product and vars.i. For Each A simplified loop that iterates over an array. Functionally similar to Loop but optimized for common array iteration. Array: vars.orderItems Item Variable: orderItem While Repeats the contained steps as long as a condition remains true. Condition: vars.retryCount < 3 && vars.success == false Be careful with While loops. If the condition never becomes false, the flow will run indefinitely. Always include logic inside the loop that eventually changes the condition. Try/Catch Wraps steps in error handling. If any step in the Try block throws an error, execution jumps to the Catch block. The Try/Catch step creates two branches: a Try branch for the main logic and a Catch branch for error handling. Error Variable: err Inside the Catch branch, access vars.err.message and vars.err.stack. Break Exits the current loop immediately. Only valid inside Loop, For Each, or While steps. Break has no configurable properties. Drag it into a loop body and it will stop iteration when reached. Continue Skips the remainder of the current loop iteration and proceeds to the next one. Only valid inside Loop, For Each, or While steps. Continue has no configurable properties. Place it inside a conditional branch within a loop to skip specific iterations. Throw Error Throws an error with a custom message. If inside a Try/Catch block, the error is caught. Otherwise, the flow terminates with an error response. Message: 'User not found' Status Code: 404 A boolean expression to evaluate. The value to match against each case. List of case values. Each case creates a branch on the canvas. Whether to include a default branch for unmatched values. An array expression or range to iterate over. Variable name for the current item. Defaults to `item`. Variable name for the current index. Defaults to `index`. The array to iterate over. Variable name for the current item. A boolean expression evaluated before each iteration. Variable name to store the caught error object. Defaults to `error`. The error message. HTTP status code to return if the error is unhandled. Defaults to 500. Steps Reference /reference/steps Browse all step categories Variable Steps /reference/steps/variables Set variables and return values Operators /reference/operators Operators for conditions and expressions --- title: Crypto Steps route: https://docs.spala.ai/reference/steps/crypto/ path: /reference/steps/crypto description: Steps for encryption, decryption, hashing, and random value generation. section: reference updated: 2026-07-08 --- # Crypto Steps Steps for encryption, decryption, hashing, and random value generation. Crypto Steps Crypto steps provide cryptographic operations -- encrypting and decrypting data, generating hashes, and producing random values. Encrypt Encrypts data using a symmetric encryption algorithm. Data: vars.sensitiveData Key: env.ENCRYPTION_KEY Algorithm: aes-256-gcm Assign To: encrypted Decrypt Decrypts data that was encrypted with the Encrypt step. Data: vars.encrypted Key: env.ENCRYPTION_KEY Algorithm: aes-256-gcm Assign To: decrypted Hash Generates a hash digest of the input data. Hashing is one-way -- the original data cannot be recovered. Data: vars.fileContent Algorithm: sha256 Encoding: hex Assign To: checksum For password hashing, use the Hash Password step (bcrypt) instead of this step. General-purpose hash algorithms like SHA-256 are not suitable for password storage. Generate UUID Generates a universally unique identifier (UUID v4). Assign To: orderId Result example: "f47ac10b-58cc-4372-a567-0e02b2c3d479" Random Number Generates a random number within a specified range. Min: 1000 Max: 9999 Integer: true Assign To: verificationCode Random String Generates a random string of specified length and character set. Length: 24 Characters: alphanumeric Assign To: sessionId The data to encrypt. Strings and objects are accepted. The encryption key. Use `env.ENCRYPTION_KEY` for environment variables. Encryption algorithm: `aes-256-cbc`, `aes-256-gcm`. Defaults to `aes-256-cbc`. Variable name to store the encrypted string. The encrypted data string. The same key used for encryption. Must match the algorithm used for encryption. Variable name to store the decrypted data. The data to hash. Hash algorithm: `md5`, `sha1`, `sha256`, `sha512`. Defaults to `sha256`. Output encoding: `hex`, `base64`. Defaults to `hex`. Variable name to store the hash string. Variable name to store the UUID string. Minimum value (inclusive). Defaults to 0. Maximum value (inclusive). Defaults to 100. Whether to return an integer. Defaults to true. Variable name to store the generated number. Length of the string. Defaults to 16. Character set: `alphanumeric`, `alpha`, `numeric`, `hex`. Defaults to `alphanumeric`. Variable name to store the generated string. Steps Reference /reference/steps Browse all step categories Auth Steps /reference/steps/auth JWT tokens and password hashing Encoding Steps /reference/steps/encoding Base64 and URL encoding --- title: Data Types route: https://docs.spala.ai/reference/data-types/ path: /reference/data-types description: Reference for all data types supported in Spala expressions and flows. section: reference updated: 2026-07-08 --- # Data Types Reference for all data types supported in Spala expressions and flows. Data Types Spala supports the following data types in expressions, variables, and step properties. String A sequence of characters, enclosed in single quotes in expressions. 'Hello, world!' 'Order #' + vars.orderId Strings support all string filters for transformation. Number Integer or floating-point numeric values. No quotes needed. 42 3.14 -100 Arithmetic operators and number filters work with numeric values. Boolean A true or false value. Used in conditions, If/Else steps, and logical expressions. true false vars.isActive == true Null Represents the intentional absence of a value. Different from undefined (which means a variable was never set). null Use | isNull or == null to check for null values. The nullish coalescing operator ?? provides fallbacks for null values. Array An ordered list of values. Arrays can contain any mix of data types. [1, 2, 3] ['apple', 'banana', 'cherry'] [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }] Arrays are the primary way to work with collections of data. Database query results return arrays of objects. See array filters for transformation operations. Object A collection of key-value pairs. Keys are strings, values can be any type. { name: 'Alice', age: 30, active: true } { user: vars.currentUser, timestamp: '' | now } Access properties with dot notation (vars.user.name) or bracket notation (vars.user['name']). See object filters for manipulation operations. Date Date values represent a point in time. They are created from ISO strings or the now filter. '' | now '2026-03-06T12:00:00Z' | fromISO Dates stored in the database are automatically parsed. Use date filters to format, compare, and perform arithmetic on dates. Buffer Binary data used for file contents, encryption results, and raw data. Buffers are typically produced by file operations or crypto steps rather than created directly in expressions. Buffers can be converted to strings with an encoding: vars.fileBuffer | toString vars.binaryData | toBase64 All data types are automatically serialized to JSON when used in API responses. Dates become ISO strings, buffers become Base64 strings, and all other types map directly to their JSON equivalents. Type checking Use the typeOf filter to inspect a value's type at runtime: vars.input | typeOf // Returns: 'string', 'number', 'boolean', 'object', 'array', or 'null' Use type conversion filters to ensure values are the expected type: | Filter | Description | |--------|-------------| | toString | Convert to string | | toNumber | Convert to number | | toBoolean | Convert to boolean | | toArray | Wrap in array if not already | See the type filters reference for details. Filters Reference /reference/filters Transform data types with pipe filters Operators /reference/operators Arithmetic, comparison, and logical operators --- title: Database Steps route: https://docs.spala.ai/reference/steps/database/ path: /reference/steps/database description: Steps for querying, inserting, updating, deleting, and aggregating database records. section: reference updated: 2026-07-08 --- # Database Steps Steps for querying, inserting, updating, deleting, and aggregating database records. Database Steps Database steps interact with your project's PostgreSQL database. They provide both raw SQL access and structured operations that generate SQL for you. Database Query Executes a raw SQL query. Use this for complex queries that the structured steps cannot express. Query: SELECT * FROM products WHERE price > $1 AND category = $2 Parameters: [29.99, 'electronics'] Assign To: products Always use parameterized queries instead of string concatenation to prevent SQL injection. Database Insert Inserts one or more rows into a table. Table: users Data: { name: input.name, email: input.email } Returning: * Assign To: newUser Database Update Updates rows in a table matching the given conditions. Table: users Data: { name: input.name } Where: { id: vars.userId } Returning: * Assign To: updatedUser Database Delete Deletes rows from a table matching the given conditions. Table: sessions Where: { expires_at: { $lt: 'NOW()' } } Database Select Retrieves rows from a table with structured filtering, sorting, and pagination. Table: products Columns: id, name, price Where: { category: 'electronics' } Order By: price ASC Limit: 20 Offset: 0 Assign To: products Find One Retrieves a single row matching the conditions. Returns null if no match is found. Table: users Where: { email: input.email } Assign To: user Find Many Retrieves all rows matching the conditions. Table: orders Where: { user_id: vars.userId, status: 'pending' } Assign To: pendingOrders Count Returns the number of rows matching the conditions. Table: orders Where: { status: 'completed' } Assign To: completedCount Aggregate Performs aggregation operations on a table (SUM, AVG, MIN, MAX, COUNT). Function: SUM Column: amount Table: orders Where: { status: 'completed' } Group By: category Assign To: salesByCategory The SQL query to execute. Use `$1`, `$2`, etc. for parameterized values. Array of values for parameterized placeholders. Variable name to store the query result. The target table name. An object (single row) or array of objects (multiple rows) to insert. Columns to return from the inserted rows (e.g., `*` or `id`). Variable name to store the returned data. The target table name. Key-value pairs of columns to update. Conditions to match rows for updating. Columns to return from the updated rows. Variable name to store the returned data. The target table name. Conditions to match rows for deletion. Columns to return from the deleted rows. Variable name to store the returned data. The table to query. Columns to select. Defaults to `*`. Filter conditions. Column and direction for sorting (e.g., `created_at DESC`). Maximum number of rows to return. Number of rows to skip. Variable name to store the result. The table to query. Filter conditions. Variable name to store the result. The table to query. Filter conditions. Variable name to store the result array. The table to query. Filter conditions. Variable name to store the count. The table to query. The aggregation function: `SUM`, `AVG`, `MIN`, `MAX`, or `COUNT`. The column to aggregate. Filter conditions. Column to group results by. Variable name to store the result. Steps Reference /reference/steps Browse all step categories Database Overview /database Design tables and relationships Variable Steps /reference/steps/variables Store query results in variables --- title: Date Filters route: https://docs.spala.ai/reference/filters/date/ path: /reference/filters/date description: Filters for formatting, comparing, and manipulating dates. section: reference updated: 2026-07-08 --- # Date Filters Filters for formatting, comparing, and manipulating dates. Date Filters Date filters format, compare, and perform arithmetic on date values. Format patterns The format filter accepts the following tokens: | Token | Output | Example | |-------|--------|---------| | YYYY | 4-digit year | 2026 | | MM | 2-digit month | 03 | | DD | 2-digit day | 06 | | HH | 24-hour hour | 14 | | mm | Minutes | 30 | | ss | Seconds | 45 | Usage examples Format a creation date for display: vars.user.created_at | format('YYYY-MM-DD HH:mm') Check if a token has expired: vars.token.expires_at | isBefore('' | now) Calculate days until deadline: vars.deadline | diffInDays('' | now) Set an expiration date 30 days from now: '' | now | addDays(30) | toISO Filters Reference /reference/filters Browse all filter categories Number Filters /reference/filters/number Round, clamp, and transform numbers String Filters /reference/filters/string Format dates as strings --- title: Encoding Steps route: https://docs.spala.ai/reference/steps/encoding/ path: /reference/steps/encoding description: Steps for parsing and encoding JSON, Base64, URLs, and HTML entities. section: reference updated: 2026-07-08 --- # Encoding Steps Steps for parsing and encoding JSON, Base64, URLs, and HTML entities. Encoding Steps Encoding steps convert data between formats -- parsing JSON strings into objects, encoding data to Base64, and escaping URLs and HTML. JSON Parse Parses a JSON string into a JavaScript object or array. Value: vars.apiResponse.body Assign To: data External API Call steps automatically parse JSON responses, so you usually do not need JSON Parse for API results. Use it for JSON stored in files or database fields. JSON Stringify Converts an object or array to a JSON string. Value: { users: vars.users, total: vars.count } Pretty: true Assign To: jsonString Base64 Encode Encodes data to a Base64 string. Value: vars.fileContent Assign To: encoded Base64 Decode Decodes a Base64 string back to its original form. Value: vars.encodedData Encoding: utf-8 Assign To: decoded URL Encode Encodes a string for safe use in URLs, replacing special characters with percent-encoded equivalents. Value: vars.searchQuery Assign To: encodedQuery Result: "hello world" becomes "hello%20world" URL Decode Decodes a percent-encoded URL string back to its original form. Value: query.q Assign To: searchTerm HTML Encode Encodes special characters as HTML entities to prevent XSS when rendering user content. Value: vars.userComment Assign To: safeComment Result: "" becomes "<script>alert('xss')</script>" HTML Decode Decodes HTML entities back to their original characters. Value: vars.encodedContent Assign To: decodedContent The JSON string to parse. Variable name to store the parsed result. The value to serialize. Whether to format with indentation. Defaults to false. Variable name to store the JSON string. The string or buffer to encode. Variable name to store the encoded string. The Base64 string to decode. Output encoding: `utf-8`, `binary`. Defaults to `utf-8`. Variable name to store the decoded result. The string to encode. Variable name to store the encoded string. The encoded string to decode. Variable name to store the decoded string. The string to encode. Variable name to store the encoded string. The HTML-encoded string to decode. Variable name to store the decoded string. Steps Reference /reference/steps Browse all step categories Crypto Steps /reference/steps/crypto Encryption and hashing operations API Steps /reference/steps/api HTTP requests and responses --- title: File Steps route: https://docs.spala.ai/reference/steps/file/ path: /reference/steps/file description: Steps for reading, writing, deleting, and managing files. section: reference updated: 2026-07-08 --- # File Steps Steps for reading, writing, deleting, and managing files. File Steps File steps handle file system operations -- reading, writing, listing, uploading, and downloading files. File steps require a storage addon to be installed (Local Storage or S3 Storage). Configure your storage addon before using these steps. Read File Reads the contents of a file from storage. Path: 'uploads/' + vars.filename Encoding: utf-8 Assign To: fileContent Write File Writes content to a file in storage. Creates the file if it does not exist, or overwrites it if it does. Path: 'reports/' + vars.reportId + '.json' Content: vars.reportData | toJSON Encoding: utf-8 Delete File Deletes a file from storage. Path: 'uploads/' + vars.oldFilename List Directory Lists all files and subdirectories within a directory. Path: 'uploads/images' Recursive: false Assign To: imageFiles Upload File Handles an incoming file upload from a multipart form request and saves it to storage. Field Name: avatar Destination: 'uploads/avatars' Max Size: 5242880 Allowed Types: ['image/png', 'image/jpeg', 'image/webp'] Assign To: uploadedFile The result stored in the assigned variable includes path, originalName, size, and mimetype. Download File Sends a file from storage as a download response to the client. Path: 'reports/' + vars.reportId + '.pdf' Filename: 'monthly-report.pdf' Content Type: application/pdf The file path relative to the storage root. File encoding: `utf-8`, `base64`, `binary`. Defaults to `utf-8`. Variable name to store the file contents. The destination file path. The data to write. File encoding: `utf-8`, `base64`, `binary`. Defaults to `utf-8`. The file path to delete. The directory path to list. Whether to include files in subdirectories. Defaults to false. Variable name to store the array of file paths. The form field name for the uploaded file. Directory path to save the file. Defaults to `uploads/`. Maximum file size in bytes. Defaults to 10MB. Array of allowed MIME types (e.g., `["image/png", "image/jpeg"]`). Variable name to store file metadata (path, size, mimetype). The file path in storage. The filename presented to the client. Defaults to the original filename. MIME type for the response. Auto-detected if not specified. Steps Reference /reference/steps Browse all step categories Upload Files /guides/file-uploads Step-by-step file upload guide Encoding Steps /reference/steps/encoding Base64 encoding for file data --- title: Filters Reference route: https://docs.spala.ai/reference/filters/ path: /reference/filters description: Complete reference for data transformation filters in Spala expressions. section: reference updated: 2026-07-08 --- # Filters Reference Complete reference for data transformation filters in Spala expressions. Filters Reference Filters transform values within Spala expressions. They are applied using the pipe (|) operator and can be chained together to perform multiple transformations in sequence. Syntax expression | filterName expression | filterName(arg1, arg2) expression | filter1 | filter2 | filter3 Filters read the value on the left side of the pipe, transform it, and pass the result to the next filter or use it as the final value. Examples vars.name | uppercase // "john doe" → "JOHN DOE" vars.items | map('name') | join(', ') // [{name: "Apple"}, {name: "Banana"}] → "Apple, Banana" vars.price | round(2) // 19.956 → 19.96 vars.createdAt | format('YYYY-MM-DD') // Date → "2026-03-06" Chaining Filters are evaluated left to right. Each filter receives the output of the previous one: vars.description | trim | lowercase | truncate(100) This trims whitespace, converts to lowercase, then truncates to 100 characters. Filter arguments can be literals, variable references, or nested expressions. For example: vars.items | slice(0, vars.pageSize). Categories String Filters /reference/filters/string Transform text: uppercase, lowercase, trim, replace, split, slugify, and more. Array Filters /reference/filters/array Manipulate arrays: map, filter, sort, unique, flatten, groupBy, and more. Number Filters /reference/filters/number Work with numbers: round, floor, ceil, clamp, abs, toFixed, and more. Date Filters /reference/filters/date Format and manipulate dates: format, addDays, diffInDays, isAfter, and more. Object Filters /reference/filters/object Transform objects: keys, values, pick, omit, merge, has, and more. Type Filters /reference/filters/type Convert and check types: toString, toNumber, toBoolean, isEmpty, typeOf, and more. Steps Reference /reference/steps Step types that use filters in expressions Operators /reference/operators Operators for use alongside filters in expressions Data Types /reference/data-types Supported data types that filters transform --- title: Number Filters route: https://docs.spala.ai/reference/filters/number/ path: /reference/filters/number description: Filters for rounding, clamping, and transforming numeric values. section: reference updated: 2026-07-08 --- # Number Filters Filters for rounding, clamping, and transforming numeric values. Number Filters Number filters perform mathematical operations and numeric conversions. Usage examples Format a price with two decimal places: vars.price | toFixed(2) // 9.9 → "9.90" Clamp a pagination page number: vars.requestedPage | clamp(1, vars.totalPages) Round a calculated discount: vars.originalPrice * 0.15 | round(2) Ensure a quantity is at least 1: input.quantity | max(1) Note that toFixed returns a string (for display), while round returns a number (for further calculations). Filters Reference /reference/filters Browse all filter categories Date Filters /reference/filters/date Format and manipulate dates Type Filters /reference/filters/type Convert between data types --- title: Object Filters route: https://docs.spala.ai/reference/filters/object/ path: /reference/filters/object description: Filters for transforming, querying, and manipulating objects. section: reference updated: 2026-07-08 --- # Object Filters Filters for transforming, querying, and manipulating objects. Object Filters Object filters work with key-value pairs -- extracting, merging, and reshaping objects. Usage examples Strip sensitive fields from a user object before responding: vars.user | omit(['password_digest', 'reset_token']) Safely access nested data with a default: vars.config | get('database.host', 'db.example.internal') Merge request body with defaults: { page: 1, limit: 20 } | merge(input) Build a response by picking specific fields: vars.order | pick(['id', 'status', 'total', 'created_at']) Check if a required field exists: input | has('email') Filters Reference /reference/filters Browse all filter categories Array Filters /reference/filters/array Transform arrays of objects Type Filters /reference/filters/type Check and convert value types --- title: Operators route: https://docs.spala.ai/reference/operators/ path: /reference/operators description: Reference for all expression operators available in Spala. section: reference updated: 2026-07-08 --- # Operators Reference for all expression operators available in Spala. Operators Operators are used within Spala expressions to perform calculations, comparisons, and logical operations. They work the same way as JavaScript operators. Arithmetic operators | Operator | Description | Example | Result | |----------|-------------|---------|--------| | + | Addition (or string concatenation) | 5 + 3 | 8 | | - | Subtraction | 10 - 4 | 6 | | * | Multiplication | 6 * 7 | 42 | | / | Division | 15 / 4 | 3.75 | | % | Modulo (remainder) | 17 % 5 | 2 | The + operator also concatenates strings: 'Hello ' + vars.name // "Hello Alice" Comparison operators | Operator | Description | Example | Result | |----------|-------------|---------|--------| | == | Equal to | vars.status == 'active' | true/false | | != | Not equal to | vars.role != 'admin' | true/false | | > | Greater than | vars.age > 18 | true/false | | < | Less than | vars.price < 100 | true/false | | >= | Greater than or equal | vars.count >= 10 | true/false | | <= | Less than or equal | vars.score <= 50 | true/false | Spala uses == for equality comparisons (not ===). Type coercion applies, so '5' == 5 is true. Logical operators | Operator | Description | Example | Result | |----------|-------------|---------|--------| | && | Logical AND | vars.isAdmin && vars.isActive | true if both are true | | \|\| | Logical OR | vars.role == 'admin' \|\| vars.role == 'owner' | true if either is true | | ! | Logical NOT | !vars.isDeleted | Inverts the boolean | Logical operators short-circuit: && stops at the first falsy value, || stops at the first truthy value. Ternary operator The ternary operator provides inline conditional expressions: condition ? valueIfTrue : valueIfFalse vars.count > 0 ? 'Items found' : 'No items' Ternary expressions can be nested, but keep them simple for readability: vars.role == 'admin' ? 'Full access' : vars.role == 'editor' ? 'Edit access' : 'Read only' Nullish coalescing operator The ?? operator returns the right-hand value when the left-hand value is null or undefined (but not other falsy values like 0, '', or false). vars.config.timeout ?? 5000 // Returns vars.config.timeout if it exists, otherwise 5000 Contrast with || which treats 0, '', and false as falsy: vars.count || 10 // If count is 0, returns 10 vars.count ?? 10 // If count is 0, returns 0 Optional chaining operator The ?. operator safely accesses nested properties without throwing an error if an intermediate value is null or undefined. vars.user?.address?.city // Returns the city if user and address exist, otherwise undefined Without optional chaining, accessing vars.user.address.city would throw an error if user or address is null. Works with method calls too: vars.items?.map('name') Operator precedence Operators are evaluated in this order (highest to lowest): 1. ?. -- optional chaining 2. ! -- logical NOT 3. *, /, % -- multiplication, division, modulo 4. +, - -- addition, subtraction 5. >, <, >=, <= -- comparisons 6. ==, != -- equality 7. && -- logical AND 8. || -- logical OR 9. ?? -- nullish coalescing 10. ? : -- ternary Use parentheses to override precedence when needed: (vars.a + vars.b) * vars.c Filters Reference /reference/filters Data transformation filters for expressions Data Types /reference/data-types Supported data types in Spala expressions --- title: Other Steps route: https://docs.spala.ai/reference/steps/other/ path: /reference/steps/other description: Steps for sending emails, adding delays, executing sub-flows, custom code, and emitting events. section: reference updated: 2026-07-08 --- # Other Steps Steps for sending emails, adding delays, executing sub-flows, custom code, and emitting events. Other Steps Additional step types for email, timing, sub-flows, raw code, and event-driven patterns. Send Email Sends an email using a configured email addon (SMTP or a provider like SendGrid). To: vars.user.email Subject: 'Your order #' + vars.order.id + ' has been confirmed' Body: '

Order Confirmed

Thank you for your purchase!

' The email addon must be installed and configured before using the Send Email step. See the Send Emails guide for setup instructions. Sleep/Delay Pauses flow execution for a specified duration. Useful for rate limiting, retry delays, or timed sequences. Duration: 2000 This pauses the flow for 2 seconds before continuing to the next step. Execute Flow Calls another flow as a sub-flow, passing data in and receiving a result back. This enables modular flow design by breaking complex logic into reusable pieces. Flow: validateOrder Input: { items: vars.cartItems, userId: vars.userId } Assign To: validationResult Custom Code Executes raw JavaScript code within the flow. Use this for logic that cannot be expressed with the built-in steps. // Access variables, request, and environment const items = vars.cartItems; const total = items.reduce((sum, item) => sum + item.price * item.qty, 0); const tax = total * 0.08; return { subtotal: total, tax, total: total + tax }; Custom Code steps cannot be converted back to visual steps. Prefer built-in steps when possible to maintain full visual editing capability. Emit Event Emits a named event that can be consumed by event listeners, WebSocket channels, or other flows subscribed to the event. Event: order.created Data: { orderId: vars.order.id, userId: vars.userId } Channel: 'user_' + vars.userId Recipient email address or array of addresses. Email subject line. Email body content. Supports HTML. Sender email address. Defaults to the addon configuration. CC recipients. BCC recipients. Reply-to email address. Time to wait in milliseconds. The name or ID of the flow to execute. Data to pass as input to the sub-flow. Accessible as `input` in the target flow. Variable name to store the sub-flow return value. JavaScript code to execute in the managed Spala runtime. Use documented flow variables like `input`, `params`, `query`, `headers`, `vars`, and `env`. Variable name to store the return value of the code. The event name to emit. Data payload to include with the event. Optional channel to scope the event to specific WebSocket subscribers. Steps Reference /reference/steps Browse all step categories Event Triggers /triggers/event-triggers React to emitted events with trigger flows Background Tasks /tasks/background-tasks Run sub-flows asynchronously --- title: Steps Reference route: https://docs.spala.ai/reference/steps/ path: /reference/steps description: Complete reference for all step types available in Spala flows. section: reference updated: 2026-07-08 --- # Steps Reference Complete reference for all step types available in Spala flows. Steps Reference Steps are the building blocks of Spala flows. Each step performs a specific action -- assigning a variable, querying a database, calling an API, or controlling the flow of execution. You build backend logic by dragging steps onto the canvas and configuring their properties. Spala provides step types organized into the following categories. Categories Variables /reference/steps/variables Set variables, log output, return values, and add comments to document your flows. Database /reference/steps/database Query, insert, update, delete, and aggregate data using built-in database steps. Control Flow /reference/steps/control-flow Conditional branching, loops, error handling, and flow control with if/else, switch, for each, try/catch, and more. API /reference/steps/api Make external HTTP requests, send responses, set headers, cookies, and redirects. Auth /reference/steps/auth Generate and verify JWTs, hash and verify passwords, and create API keys. Crypto /reference/steps/crypto Encrypt, decrypt, hash data, and generate UUIDs, random numbers, and random strings. File /reference/steps/file Read, write, delete, and list files. Handle uploads and downloads. Encoding /reference/steps/encoding Parse and stringify JSON, encode and decode Base64, URLs, and HTML entities. Other /reference/steps/other Send emails, add delays, execute sub-flows, write custom code, and emit events. How steps work Every step in a flow executes sequentially from top to bottom. Each step can read variables set by previous steps using expressions like vars.myVariable. Steps that produce output can assign their result to a variable for use downstream. Set Variable → Database Select → Loop → Respond All step properties support expressions -- dynamic values that reference variables, use operators, and apply filters. See the Operators and Filters reference for details. Filters Reference /reference/filters Data transformation filters for step expressions Operators /reference/operators Arithmetic, comparison, and logical operators Functions /flows Learn how to build backend logic with steps --- title: String Filters route: https://docs.spala.ai/reference/filters/string/ path: /reference/filters/string description: Filters for transforming and manipulating text strings. section: reference updated: 2026-07-08 --- # String Filters Filters for transforming and manipulating text strings. String Filters String filters transform text values. Apply them with the pipe operator on any string expression. Usage examples Format a URL slug from user input: vars.title | trim | slugify // " My Blog Post! " → "my-blog-post" Build a display name: vars.firstName | capitalize + ' ' + vars.lastName | capitalize Check if an email domain is allowed: vars.email | split('@') | last | lowercase // "User@Example.COM" → "example.com" Filters Reference /reference/filters Browse all filter categories Array Filters /reference/filters/array Transform and manipulate arrays Type Filters /reference/filters/type Convert between data types --- title: Type Filters route: https://docs.spala.ai/reference/filters/type/ path: /reference/filters/type description: Filters for converting between types and checking values. section: reference updated: 2026-07-08 --- # Type Filters Filters for converting between types and checking values. Type Filters Type filters convert values between types and check for null, undefined, or empty states. Behavior details isEmpty returns true for: - Empty strings '' - Empty arrays [] - Empty objects {} - null and undefined default returns the fallback value when the input is null, undefined, or '' (empty string). Otherwise returns the original value. toArray wraps non-array values in an array. If the value is already an array, it is returned unchanged. Usage examples Provide a fallback for missing query parameters: query.page | toNumber | default(1) Validate that required fields are not empty: input.name | isEmpty // Use in an If/Else condition to return a 400 error Determine type for dynamic handling: vars.input | typeOf // 'string', 'number', 'object', 'array', etc. Ensure a value is always an array: vars.tags | toArray // "javascript" → ["javascript"] // ["javascript", "node"] → ["javascript", "node"] Filters Reference /reference/filters Browse all filter categories Data Types /reference/data-types All supported data types in Spala String Filters /reference/filters/string Transform text values --- title: Variable Steps route: https://docs.spala.ai/reference/steps/variables/ path: /reference/steps/variables description: Steps for setting variables, logging output, returning values, and adding comments. section: reference updated: 2026-07-08 --- # Variable Steps Steps for setting variables, logging output, returning values, and adding comments. Variable Steps Variable steps handle data assignment, output, and documentation within your flows. Set Variable Assigns a value to a variable that can be referenced by subsequent steps. Variable Name: userId Value: input.id After this step, vars.userId holds the value from the request input. Log Outputs a value to the console for debugging purposes. Log output appears in the Spala console panel during flow execution. Message: 'User created: ' + vars.userId Log steps are helpful during development but consider removing them before deploying to production to keep your logs clean. Return Ends the flow and returns a value. In endpoint flows, the returned value becomes the response body unless a Respond step has already sent a response. Value: { success: true, data: vars.result } Comment Adds a documentation note to the flow. Comment steps do not execute any logic -- they exist purely to help you and your team understand the flow. Text: Validate the incoming request before processing Comments are preserved in generated code as inline code comments, so they carry over even when you switch to code view. The name of the variable to set. Accessed later as `vars.variableName`. The value to assign. Can be a literal, expression, or the result of a filter chain. The value or message to log. Expressions are evaluated before logging. The value to return from the flow. The comment text to display on the canvas. Steps Reference /reference/steps Browse all step categories Control Flow Steps /reference/steps/control-flow Conditional branching and loops Database Steps /reference/steps/database Query and modify database records --- title: Legacy Publish Link route: https://docs.spala.ai/self-hosting/deployment/ path: /self-hosting/deployment description: This compatibility page points users to project publishing docs. section: self-hosting updated: 2026-07-08 --- # Legacy Publish Link This compatibility page points users to project publishing docs. Legacy Publish Link Spala users publish project changes from the hosted dashboard. This page is kept only for old self-hosting links; the current guide is Publish. Use Publish for your backend The deployment action users normally need is Publish. Publishing applies your project changes and makes the generated API available. Publish Flow Build or edit your backend Use AI Copilot, Lite mode, or Advanced mode to create tables, functions, endpoints, tasks, triggers, channels, and settings. Review the project Inspect the project graph, endpoint list, API Playground, and generated docs before publishing. Publish Click Publish in the dashboard. Spala applies the project changes and updates the live API. Use the API Connect your frontend, use the generated endpoint snippets, or let an authenticated AI agent continue work through the project MCP. Platform Operations Spala manages the hosted platform runtime and dashboard delivery. Public docs focus on publishing your project API from the dashboard. Publish /deployment/publish Publish generated backend changes Publish Your API /features/publish-export Review and publish project changes API Playground /features/playground Test endpoints before and after publishing AI Copilot /features/ai-assistant Build the backend from a plain-language prompt Spala Public MCP /agents/mcp Let agents discover and hand off to the right project MCP --- title: Project Configuration route: https://docs.spala.ai/self-hosting/configuration/ path: /self-hosting/configuration description: This compatibility page points users to project configuration docs. section: self-hosting updated: 2026-07-08 --- # Project Configuration This compatibility page points users to project configuration docs. Project Configuration Spala project configuration happens in the dashboard. This page is kept for old links; the current guide is Project Configuration. Configure In The Dashboard - Settings — Project name, API docs, AI access, MCP, environment variables, snapshots, and publish controls - Addons — Integration-specific API keys and settings - Security/Auth — Endpoint authentication and user access patterns - AI Data Access — Which tables and fields AI Ask mode can read - MCP — Project MCP access for authenticated AI agents Keep secrets out of frontend code Store integration secrets as project environment variables or addon settings in Spala. Do not expose secret keys in browser code. Project Configuration /deployment/configuration Configure project settings and delivery tools Settings /settings Configure project-level behavior Addons /addons Configure integrations and required API keys AI Copilot /features/ai-assistant Configure AI data access and project context Spala Public MCP /agents/mcp Connect agents through the public MCP handoff --- title: Project Database route: https://docs.spala.ai/self-hosting/postgresql/ path: /self-hosting/postgresql description: This compatibility page points users to project database docs. section: self-hosting updated: 2026-07-08 --- # Project Database This compatibility page points users to project database docs. Project Database In Spala, users manage project data models from the visual Database screen. This page is kept for old links; the current guide is Project Database. You do not need to provision or maintain database infrastructure to use the hosted Spala dashboard. Use the visual database designer Start in Database to add tables and relationships. Spala handles the managed database layer behind the scenes. What Users Configure - Tables and fields - Relationships between tables - Data access from functions and endpoints - Database triggers - Import, export, and review workflows exposed in the dashboard Project Database /deployment/database Understand project database management Database /database Create tables, fields, and relationships visually Tables & Fields /database/tables Design your project schema Database Triggers /triggers/database-triggers Run logic when records change Database Steps /reference/steps/database Use project data inside functions --- title: Start a Project route: https://docs.spala.ai/self-hosting/installation/ path: /self-hosting/installation description: This compatibility page points users to the hosted project creation flow. section: self-hosting updated: 2026-07-08 --- # Start a Project This compatibility page points users to the hosted project creation flow. Start a Project There is no local installation flow required to use Spala. This page is kept for old links; the current guide is Start a Project. Hosted dashboard New users should open https://dashboard.spala.ai/signup. Existing users can sign in from the dashboard and create or open a project. First Project Open the dashboard Create an account at https://dashboard.spala.ai/signup, or sign in if you already have one. Create a project Click New Project and name the backend you want to build. Describe what you need Use AI Copilot in Lite mode to describe the app feature or API you want. Inspect and publish Review the generated project graph, test endpoints in the Playground, and publish when ready. Start a Project /deployment/start Create a project from the hosted dashboard Quick Start /getting-started/quickstart Build a simple API in the dashboard AI Copilot /features/ai-assistant Use plain language to generate backend resources The Interface /getting-started/interface Learn the dashboard layout --- title: CORS and Security route: https://docs.spala.ai/settings/cors-security/ path: /settings/cors-security description: Configure frontend origins, credentialed browser requests, trusted hosts, and publish requirements for Spala project APIs. section: settings updated: 2026-07-08 --- # CORS and Security Configure frontend origins, credentialed browser requests, trusted hosts, and publish requirements for Spala project APIs. CORS and Security Use this page when a browser frontend, mobile app, or external UI needs to call a Spala project API. Owner Checklist 1. Open the project in the hosted dashboard. 2. Go to Settings → Security. 3. Add the exact frontend origin in CORS Allowed Origins. 4. Include the scheme, host, and port, such as https://app.example.com or http://localhost:5173. 5. Do not include URL paths. 6. Allow the request headers the frontend sends, usually Authorization and Content-Type. 7. Enable credentialed requests only when the project intentionally uses cookie sessions. 8. Save the settings. 9. Publish the backend API before asking the frontend developer to retest. Publish after security changes Saved CORS/security settings do not help the live API until the project is published. If curl works but browser requests fail, confirm the origin is exact and the latest settings are published. Browser Rules Browser CORS uses the page origin, not the API route: https://app.example.com http://localhost:5173 Do not add paths such as https://app.example.com/dashboard. If the frontend sends a bearer token, allow Authorization. If it sends JSON, allow Content-Type. If it uses cookies, the response must use the exact origin, not *, and must include credential support. Cookie Sessions Cookie sessions need a tighter contract than bearer tokens. Include these fields in the frontend handoff: | Field | What to specify | | --- | --- | | Credential mode | include, same-origin, or none | | Cookie SameSite | Lax, Strict, or None | | Cookie Secure | Required for cross-site HTTPS cookies | | Domain/path | Which frontend and API hosts receive the cookie | | CSRF | Header name and source, or not required | | Logout | Local clear, server revoke, cookie expiry, or a combination | Verification After publishing, test one preflight-shaped browser request and one real request from the frontend origin. OPTIONS /api/cases HTTP/1.1 Origin: https://app.example.com Access-Control-Request-Method: POST Access-Control-Request-Headers: authorization, content-type Expected shape: Access-Control-Allow-Origin: https://app.example.com Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS Access-Control-Allow-Headers: Authorization, Content-Type For credentialed requests: Access-Control-Allow-Credentials: true Handoff Fields Add these fields to External Frontend Handoff: - Frontend origin - Whether the origin is saved in Settings → Security - Whether the backend was republished after the change - Required request headers - Whether credentials are enabled - Cookie and CSRF details if used External Frontend Handoff /guides/frontend-handoff Copy the complete frontend packet Frontend Integration Cookbook /guides/frontend-integration Use CORS with auth, uploads, and realtime Publish /features/publish-export Publish security changes to the live API API Docs /features/api-docs Share REST contracts with frontend builders --- title: Background Tasks route: https://docs.spala.ai/tasks/background-tasks/ path: /tasks/background-tasks description: Execute long-running operations asynchronously without blocking API responses in Spala. section: tasks updated: 2026-07-08 --- # Background Tasks Execute long-running operations asynchronously without blocking API responses in Spala. Background Tasks Background tasks let you offload long-running or resource-intensive operations from your API endpoints. Instead of making users wait for a slow operation to complete, your endpoint can queue a background task and return an immediate response. Spala Background Tasks monitor showing task status, filters, logs, and retry controls The Background Tasks monitor shows queued, running, completed, failed, stopped, and timed-out work. How Background Tasks Work When a function triggers a background task: 1. The task is queued for asynchronous execution 2. The calling function continues immediately without waiting 3. The background task runs independently in its own execution context 4. Results and errors are logged for later inspection This pattern is essential for operations like sending bulk emails, processing uploaded files, generating reports, or calling slow external APIs. Creating a Background Task Navigate to the Tasks section in the left sidebar Click New Task and select Background Task Give the task a descriptive name Build the function that defines what the task does Save the task Triggering a Background Task Background tasks are triggered from within other functions using the Run Task step. You can pass input data to the task as parameters. // In your endpoint function: // Step 1: Validate the upload // ... validation logic ... // Step 2: Run Task - "Process Upload" // Pass the file path and user ID as parameters // { filePath: vars.uploadPath, userId: vars.currentUser.id } // Step 3: Respond to Client // Return immediately with a 202 Accepted status // { message: "Upload is being processed", taskId: result.taskId } In the visual editor, drag a Run Task step into your function, select the target task, and map any input variables. Passing Data to Background Tasks When you trigger a background task, you can pass an input object that becomes available inside the task function as vars.input. This lets you provide all the context the task needs to do its work. // Endpoint function - trigger the task with input data // Run Task: "Send Welcome Email" // Input: { email: input.email, name: input.name } // Inside the background task function: // vars.input.email → "user@example.com" // vars.input.name → "Jane Smith" The input data is serialized when the task is queued, so it must be JSON-serializable. Database connections, file handles, and other non-serializable values cannot be passed to background tasks. Task Configuration Example: Bulk Email Campaign An endpoint that accepts a list of recipients and sends emails in the background: // POST /api/campaigns/send // Step 1: Database Query - Get campaign details // SELECT * FROM campaigns WHERE id = input.campaignId // Step 2: Run Task - "Send Campaign Emails" // Input: { campaignId: vars.campaign.id, recipients: input.recipients } // Step 3: Update campaign status // UPDATE campaigns SET status = 'sending' WHERE id = input.campaignId // Step 4: Respond // { status: "sending", recipientCount: input.recipients.length } The background task function: // Background Task: "Send Campaign Emails" // Step 1: Database Query - Get campaign content // SELECT * FROM campaigns WHERE id = input.campaignId // Step 2: Loop - For each recipient // Step 3: Send Email (addon step) // to: recipient.email, subject: campaign.subject, body: campaign.html // Step 4: Update campaign status // UPDATE campaigns SET status = 'sent', sent_at = NOW() // WHERE id = input.campaignId Example: Image Processing Pipeline Process an uploaded image through multiple transformations without blocking the upload response: // POST /api/images/upload // Step 1: Save original file to storage // Step 2: Run Task - "Process Image" // Input: { imageId: vars.savedImage.id, path: vars.savedImage.path } // Step 3: Respond with 202 Accepted Background tasks run in a separate execution context. They do not have access to the original request headers, cookies, or authentication context. Pass any required data explicitly through the task input. Monitoring Background Tasks The Background Tasks monitor shows the status of all background task executions: - Queued — Waiting to start - Running — Currently executing - Completed — Finished successfully - Failed — Terminated with an error (check logs for details) - Stopped — Manually stopped before completion - Timed Out — Exceeded the configured timeout Each execution record includes the input data, start/end times, duration, and any error output, giving you full visibility into what happened during each run. From the monitor you can: - Filter by status or addon - Track running jobs against max concurrency - Refresh job state - Stop a running task when it is no longer needed - Retry failed work after fixing configuration or data - Open a detail view with prompt, result, and logs A descriptive name for the task Maximum execution time in seconds (default: 300) Automatically retry if the task fails Maximum retry attempts before marking as failed (default: 3) Seconds to wait between retry attempts (default: 10) Scheduled Tasks /tasks/scheduled-tasks Run functions on a repeat schedule or manually Tasks Overview /tasks Learn about all task types in Spala --- title: Scheduled Tasks route: https://docs.spala.ai/tasks/scheduled-tasks/ path: /tasks/scheduled-tasks description: Run backend functions automatically on a recurring interval or manually on demand. section: tasks updated: 2026-07-08 --- # Scheduled Tasks Run backend functions automatically on a recurring interval or manually on demand. Scheduled Tasks Scheduled tasks run backend functions automatically at a recurring interval. Use them for cleanup jobs, report generation, external API syncs, periodic health checks, and other work that should happen without a user request. Create A Task Open Tasks from the sidebar Click Create Task Give the task a clear name, like "Daily Cleanup" or "Sync Inventory" Add a schedule by choosing a frequency and unit, such as every 5 minutes, every hour, or every day Optionally set start and end times Build the function steps that should run on each execution Save and enable the task Manual Tasks If a task should only run when another function starts it, remove the schedule and keep it manual. Manual tasks are useful for reusable jobs such as "Send Report", "Process Upload", or "Rebuild Search Index". Background Execution Tasks can run in the main API process or in a background process. Use Run in Background when the task may be slow, resource-heavy, or safe to queue. Background execution runs in an isolated process with configurable timeout and memory limits. Background work can be delayed Background tasks run through a queue. Use them for async work, not for request-response behavior that must finish immediately. Task Configuration Examples Daily cleanup // Schedule: every 1 day // Step 1: Delete expired sessions // Step 2: Delete old temporary files // Step 3: Log cleanup counts Hourly inventory sync // Schedule: every 1 hour // Step 1: Call supplier API // Step 2: Loop through products // Step 3: Update local inventory rows Manual export job // No schedule // Triggered by an admin endpoint or another function // Step 1: Query records // Step 2: Generate file // Step 3: Send download link Error Handling When a task fails, Spala records the run with diagnostic details. If the task runs in the background, inspect it from the Background Tasks monitor to see status, output, and logs. A descriptive name for the task How often the task should run Seconds, minutes, hours, or days Optional time when the schedule becomes active Optional time when the schedule stops running Whether the task is active and will run on schedule Run in an isolated background process instead of the main API process Optional timeout and memory limits for background execution Background Tasks /tasks/background-tasks Monitor queued, running, completed, and failed background work Tasks Overview /tasks Learn about all task types in Spala Project Agents /features/project-agents Use agents for richer triggered automations --- title: Database Triggers route: https://docs.spala.ai/triggers/database-triggers/ path: /triggers/database-triggers description: Execute functions automatically when rows are inserted, updated, or deleted on your Spala tables. section: triggers updated: 2026-07-08 --- # Database Triggers Execute functions automatically when rows are inserted, updated, or deleted on your Spala tables. Database Triggers Database triggers run backend logic when project data changes. Use them when the action should happen no matter which endpoint, task, or agent changed the data. Trigger Events Each trigger is configured for a table and one or more events: | Event | When It Fires | Common Use | |---|---|---| | Insert | A new row is created | Send welcome emails, create related records | | Update | An existing row changes | Audit changes, sync external systems | | Delete | A row is removed | Cleanup related data, notify systems | Triggers can run synchronously or asynchronously depending on the setting in the editor. Create A Database Trigger Open Triggers from the sidebar Click Create Trigger Select the target table Choose insert, update, delete, or multiple events Choose whether the trigger runs sync or async Build the trigger function with Gherkin, Visual, Split, or Code view Save and enable the trigger Trigger Variables Inside the trigger function, Spala provides variables for the changed row: Examples Audit log // Update on users // Step 1: Insert audit row with trigger.oldRecord and trigger.newRecord // Step 2: Return success Welcome email // Insert on users // Step 1: Send email to trigger.newRecord.email // Step 2: Log delivery result Cleanup // Delete on projects // Step 1: Remove related temporary records // Step 2: Notify operations channel Use endpoints for request validation If you need to reject invalid client input before a write, put that validation in the endpoint function that performs the write. Use database triggers for automatic follow-up work around data changes. The operation type: INSERT, UPDATE, or DELETE The new row data, available on insert and update The previous row data, available on update and delete The table/model ID that fired the trigger Triggers Overview /triggers Create trigger automations from the current builder Database Steps /reference/steps/database Reference for database query steps used in trigger functions Project Agents /features/project-agents Build richer automations with multiple trigger types --- title: Event Triggers route: https://docs.spala.ai/triggers/event-triggers/ path: /triggers/event-triggers description: Availability note for event-driven workflows in Spala. section: triggers updated: 2026-07-08 --- # Event Triggers Availability note for event-driven workflows in Spala. Event Triggers Advanced availability The current builder focuses on database triggers. If Event Triggers are not visible in your workspace, use database triggers, scheduled tasks, project agents, or explicit function calls for event-driven workflows. Event-driven workflows are still useful in Spala, but the visible product surface you should rely on today is: Database Triggers Run a function when records are inserted, updated, or deleted. /triggers/database-triggers Scheduled Tasks Run recurring or manual backend jobs. /tasks/scheduled-tasks Project Agents Run agent workflows from manual, webhook, schedule, database change, or websocket triggers. /features/project-agents Run Function Call reusable backend logic from endpoints, tasks, triggers, or other functions. /flows Practical Alternatives - Use a database trigger when the workflow starts from a record change. - Use a scheduled task when the workflow starts from time or manual admin action. - Use a project agent when the workflow needs AI reasoning, chat, or multi-step agent execution. - Use Run Function when one backend action should call another reusable function directly. Database Triggers /triggers/database-triggers Fire functions on insert, update, and delete operations Triggers Overview /triggers Understand visible trigger workflows Project Agents /features/project-agents Use agent workflows for richer event handling