Skip to main content
This page is part of an AI coding agent skill and is written for agents, not humans. For the human-readable Base44 docs, see the developer documentation.

Creating Functions

Base44 functions are serverless backend functions that run on Deno. They are defined locally in your project and deployed to the Base44 backend.

Function Directory

All function definitions must be placed in the base44/functions/ folder in your project. The simplest function is a folder with an entry.ts or entry.js file inside it. Example structure:
my-app/
  base44/
    functions/
      process-order/
        entry.ts
      send-notification/
        entry.ts

How to Create a Function

  1. Create a new directory in base44/functions/ with your function name (use kebab-case)
  2. Create entry.ts (or entry.js) in that directory
  3. Deploy the function using the CLI

Function Discovery

The CLI discovers functions from entry.ts or entry.js files. A folder that contains one of those files is a function:
base44/
  functions/
    process-order/
      entry.ts
The function name is the path from the functions root to that folder. For example:
FileFunction name
base44/functions/process-order/entry.tsprocess-order
base44/functions/orders/process/entry.tsorders/process
Rules:
  • entry.ts or entry.js must be inside a named subfolder, not directly in base44/functions/
  • all *.js, *.ts, and *.json files under the function folder are included when deploying
  • function paths with a dot in any path segment are ignored

Entry Point File

Functions run on Deno and must export using Deno.serve(). Use npm: prefix for npm packages.
import { createClientFromRequest } from "npm:@base44/sdk";

Deno.serve(async (req) => {
  // Get authenticated client from request
  const base44 = createClientFromRequest(req);
  
  // Parse input
  const { orderId, action } = await req.json();
  
  // Your logic here
  const order = await base44.entities.Orders.get(orderId);
  
  // Return response
  return Response.json({
    success: true,
    order: order
  });
});

Request Object

The function receives a standard Deno Request object:
  • req.json() - Parse JSON body
  • req.text() - Get raw text body
  • req.headers - Access request headers
  • req.method - HTTP method

Response Object

Return using Response.json() for JSON responses:
// Success response
return Response.json({ data: result });

// Error response with status code
return Response.json({ error: "Something went wrong" }, { status: 400 });

// Not found
return Response.json({ error: "Order not found" }, { status: 404 });

Complete Example

Directory Structure

base44/
  functions/
    process-order/
      entry.ts

entry.ts

import { createClientFromRequest } from "npm:@base44/sdk";

Deno.serve(async (req) => {
  try {
    const base44 = createClientFromRequest(req);
    const { orderId } = await req.json();
    
    // Validate input
    if (!orderId) {
      return Response.json(
        { error: "Order ID is required" },
        { status: 400 }
      );
    }
    
    // Fetch and process the order
    const order = await base44.entities.Orders.get(orderId);
    if (!order) {
      return Response.json(
        { error: "Order not found" },
        { status: 404 }
      );
    }
    
    return Response.json({
      success: true,
      orderId: order.id,
      processedAt: new Date().toISOString()
    });
    
  } catch (error) {
    return Response.json(
      { error: error.message },
      { status: 500 }
    );
  }
});

Using Service Role Access

For admin-level operations, use asServiceRole:
import { createClientFromRequest } from "npm:@base44/sdk";

Deno.serve(async (req) => {
  const base44 = createClientFromRequest(req);
  
  // Check user is authenticated
  const user = await base44.auth.me();
  if (!user) {
    return Response.json({ error: "Unauthorized" }, { status: 401 });
  }
  
  // Use service role for admin operations
  const allOrders = await base44.asServiceRole.entities.Orders.list();
  
  return Response.json({ orders: allOrders });
});

Using Secrets

Access environment variables configured in the app dashboard:
Deno.serve(async (req) => {
  // Access environment variables (configured in app settings)
  const apiKey = Deno.env.get("STRIPE_API_KEY");
  
  const response = await fetch("https://api.stripe.com/v1/charges", {
    headers: {
      "Authorization": `Bearer ${apiKey}`
    }
  });
  
  return Response.json(await response.json());
});

Naming Conventions

  • Directory name: Use kebab-case (e.g., process-order, send-notification)
  • Function name: Comes from the directory path under base44/functions/
    • Valid: process-order, orders/process, send_notification, myFunction
    • Invalid: process.order, send.notification.v2
  • Entry file: Use entry.ts or entry.js

Deploying Functions

After creating your function, deploy it to Base44:
npx base44 functions deploy
For more details on deploying, see functions-deploy.md.

Notes

  • Functions run on Deno runtime, not Node.js
  • Use npm: prefix for npm packages (e.g., npm:@base44/sdk)
  • Use createClientFromRequest(req) to get a client that inherits the caller’s auth context
  • Configure secrets via app dashboard for API keys
  • Make sure to handle errors gracefully and return appropriate HTTP status codes

Common Mistakes

WrongCorrectWhy
base44/functions/myFunction.js (single file)base44/functions/my-function/entry.tsFunctions must live in a named subdirectory
base44/functions/entry.tsbase44/functions/my-function/entry.tsThe function name comes from the subdirectory path
import { ... } from "@base44/sdk"import { ... } from "npm:@base44/sdk"Deno requires npm: prefix for npm packages
MyFunction or myFunction directorymy-function directoryUse kebab-case for directory names