Files
gh-djacobsmeyer-claude-skil…/docs/xanoscript-reference.md
2025-11-29 18:22:21 +08:00

14 KiB

XanoScript Reference Guide

Complete syntax reference for XanoScript, Xano's custom scripting language for building backend logic.

Table of Contents

  1. Core Syntax
  2. Primitives
  3. Variables
  4. Functions
  5. Filters
  6. Loops
  7. Conditionals
  8. Common Patterns

Core Syntax

Basic Structure

All XanoScript code follows this pattern:

<primitive_keyword> <name> <attributes> {
  input { }
  stack { }
  response = <data>
}

Example:

api get_users {
  input {
    int limit filters=min:1|max:100
  }

  stack {
    db.query users { limit = $limit } as $users
  }

  response = $users
}

Namespace Notation

Functions are organized by namespace (category):

  • db.* - Database operations
  • var.* - Variable operations
  • array.* - Array operations
  • http.* - HTTP requests
  • timestamp.* - Date/time operations

Format: namespace.function parameters { } as $variable


Primitives

Primitives are top-level constructs in Xano:

API Endpoint

api endpoint_name {
  input { }
  stack { }
  response = $result
}

Function

function function_name {
  input { }
  stack { }
  response = $result
}

Background Task

task task_name {
  stack { }
}

AI Agent

agent agent_name {
  input { }
  stack { }
  response = $result
}

Variables

Creating Variables

Use var keyword to initialize:

var $my_variable {
  value = "initial value"
}

Examples:

var $counter { value = 0 }
var $items { value = [] }
var $user_data { value = {} }
var $message { value = "Hello" }

Updating Variables

Use var.update to modify existing variables:

var.update $counter {
  value = $counter + 1
}
var.update $items {
  value = $items|push:$new_item
}

Variable Assignment

Functions assign output using as keyword:

db.query users { } as $users
http.request { url = "https://api.example.com" } as $response

Variable Naming

  • Always prefix with $: $variable_name
  • Use snake_case: $user_data, $formatted_items
  • Descriptive names: $active_users not $au

Functions

Database Functions

Query:

db.query table_name {
  where = { field: value },
  limit = 10,
  offset = 0,
  order = { field: "desc" }
} as $results

Insert:

db.insert table_name {
  field1 = $value1,
  field2 = $value2
} as $new_record

Update:

db.update table_name {
  where = { id: $user_id },
  set = { status: "active" }
} as $updated_record

Delete:

db.delete table_name {
  where = { id: $record_id }
}

Array Functions

Push (add to end):

array.push $my_array {
  value = $new_item
}

Pop (remove from end):

array.pop $my_array

Map (transform each item):

array.map $items {
  each as $item {
    return = $item.name
  }
} as $names

HTTP Functions

Request:

http.request {
  url = "https://api.example.com/data",
  method = "POST",
  headers = { "Authorization": "Bearer " + $token },
  body = { key: "value" }
} as $response

Timestamp Functions

Now:

timestamp.now as $current_time

Format:

timestamp.format $timestamp {
  format = "Y-m-d H:i:s"
} as $formatted

Filters

Filters transform data using pipe | syntax.

Basic Syntax

$data|filter_name
$data|filter_name:option
$data|filter_name:option1:option2

Common Filters

String Filters:

$text|upper                    // Convert to uppercase
$text|lower                    // Convert to lowercase
$text|capitalize               // Capitalize first letter
$text|trim                     // Remove whitespace
$text|length                   // Get string length
$email|is_email                // Check if valid email

Array Filters:

$array|count                   // Count items
$array|first                   // Get first item
$array|last                    // Get last item
$array|push:$item              // Add item to end
$array|is_empty                // Check if empty

Object Filters:

$object|set:"key":$value       // Set key to value
$object|unset:"key"            // Remove key
$object|get:"key"              // Get value by key
$object|keys                   // Get all keys
$object|values                 // Get all values

Numeric Filters:

$number|abs                    // Absolute value
$number|round                  // Round to integer
$number|ceil                   // Round up
$number|floor                  // Round down

Timestamp Filters:

$timestamp|format_timestamp:"Y-m-d H:i:s"
$timestamp|timestamp_offset:3600    // Add seconds

Logical Filters:

$value|not                     // Logical NOT
$value|is_null                 // Check if null
$value|is_empty                // Check if empty

Chaining Filters

Filters can be chained:

$user.email|trim|lower|is_email
$items|count|round
$text|trim|upper|length

Filter Examples

Validate email:

conditional {
  if ($email|trim|is_email|not) {
    response.error "Invalid email"
  }
}

Transform array of objects:

foreach ($users) {
  each as $user {
    var.update $formatted_users {
      value = $formatted_users|push:($user|set:"name":($user.name|upper))
    }
  }
}

Loops

ForEach Loop

Iterate over arrays or collections:

foreach ($items) {
  each as $item {
    // Process each item
  }
}

With Index:

foreach ($items) {
  each as $item, $index {
    // $index starts at 0
  }
}

Example:

var $formatted { value = [] }

foreach ($users) {
  each as $user {
    var $full_name {
      value = $user.first_name + " " + $user.last_name
    }

    var.update $formatted {
      value = $formatted|push:{
        id: $user.id,
        name: $full_name
      }
    }
  }
}

For Loop

Iterate a specific number of times:

for (10) {
  each as $index {
    // $index: 0, 1, 2, ... 9
  }
}

Example:

var $numbers { value = [] }

for (5) {
  each as $i {
    var.update $numbers {
      value = $numbers|push:($i + 1)
    }
  }
}
// Result: [1, 2, 3, 4, 5]

While Loop

Repeat while condition is true:

while ($condition) {
  each {
    // Update condition to eventually exit
  }
}

Example:

var $count { value = 0 }

while ($count < 5) {
  each {
    var.update $count {
      value = $count + 1
    }
  }
}

Conditionals

If Statement

conditional {
  if ($condition) {
    // Execute if true
  }
}

If-Else

conditional {
  if ($condition) {
    // Execute if true
  }
  else {
    // Execute if false
  }
}

If-ElseIf-Else

conditional {
  if ($condition1) {
    // First condition
  }
  elseif ($condition2) {
    // Second condition
  }
  elseif ($condition3) {
    // Third condition
  }
  else {
    // None matched
  }
}

Comparison Operators

In conditionals and filters:

$a == $b        // Equals
$a != $b        // Not equals
$a > $b         // Greater than
$a < $b         // Less than
$a >= $b        // Greater than or equal
$a <= $b        // Less than or equal

Logical Operators

$a and $b       // Logical AND
$a or $b        // Logical OR
$value|not      // Logical NOT (using filter)

Examples

Validate input:

conditional {
  if ($email|is_empty) {
    response.error "Email is required"
  }
  elseif ($email|is_email|not) {
    response.error "Invalid email format"
  }
}

Role-based logic:

conditional {
  if ($user.role == "admin") {
    db.query all_records { } as $records
  }
  elseif ($user.role == "user") {
    db.query records {
      where = { user_id: $user.id }
    } as $records
  }
  else {
    response.error "Unauthorized"
  }
}

Common Patterns

Pattern 1: API CRUD Endpoint

api create_user {
  input {
    text email filters=required|is_email
    text name filters=required|trim
  }

  stack {
    // Validate unique email
    db.query users {
      where = { email: $email }
    } as $existing

    conditional {
      if ($existing|count > 0) {
        response.error "Email already exists"
      }
    }

    // Create user
    db.insert users {
      email = $email|lower|trim,
      name = $name|trim,
      created_at = timestamp.now
    } as $new_user

    response = {
      success: true,
      user: $new_user
    }
  }
}

Pattern 2: Data Transformation

function format_users {
  input {
    array raw_users
  }

  stack {
    var $formatted { value = [] }

    foreach ($raw_users) {
      each as $user {
        var $user_obj {
          value = {
            id: $user.id,
            name: $user.first_name + " " + $user.last_name,
            email: $user.email|lower,
            created: $user.created_at|format_timestamp:"Y-m-d"
          }
        }

        var.update $formatted {
          value = $formatted|push:$user_obj
        }
      }
    }

    response = $formatted
  }
}

Pattern 3: External API Call

function fetch_external_data {
  input {
    text endpoint
  }

  stack {
    http.request {
      url = "https://api.example.com/" + $endpoint,
      method = "GET",
      headers = {
        "Authorization": "Bearer " + env.API_KEY
      }
    } as $response

    conditional {
      if ($response.status != 200) {
        response.error "API request failed"
      }
    }

    response = $response.body
  }
}

Pattern 4: Conditional Processing

api process_order {
  input {
    int order_id
    text action
  }

  stack {
    db.query orders {
      where = { id: $order_id }
    } as $order

    conditional {
      if ($action == "approve") {
        db.update orders {
          where = { id: $order_id },
          set = {
            status: "approved",
            approved_at: timestamp.now
          }
        }
      }
      elseif ($action == "reject") {
        db.update orders {
          where = { id: $order_id },
          set = {
            status: "rejected",
            rejected_at: timestamp.now
          }
        }
      }
      else {
        response.error "Invalid action"
      }
    }

    response = { success: true }
  }
}

Pattern 5: Aggregate and Filter

api get_user_stats {
  input {
    int user_id
  }

  stack {
    // Get user's orders
    db.query orders {
      where = { user_id: $user_id }
    } as $orders

    // Calculate totals
    var $total_amount { value = 0 }
    var $completed_count { value = 0 }

    foreach ($orders) {
      each as $order {
        var.update $total_amount {
          value = $total_amount + $order.amount
        }

        conditional {
          if ($order.status == "completed") {
            var.update $completed_count {
              value = $completed_count + 1
            }
          }
        }
      }
    }

    response = {
      total_orders: $orders|count,
      completed_orders: $completed_count,
      total_spent: $total_amount
    }
  }
}

Best Practices

1. Initialize Variables Early

// ✅ Good
var $results { value = [] }
foreach ($items) {
  each as $item {
    var.update $results { value = $results|push:$item }
  }
}

// ❌ Bad - undefined variable
foreach ($items) {
  each as $item {
    var.update $results { value = $results|push:$item }  // Error!
  }
}

2. Use Filters for Validation

// ✅ Good
conditional {
  if ($email|is_email|not) {
    response.error "Invalid email"
  }
}

// ❌ Bad - manual validation
conditional {
  if ($email.indexOf("@") == -1) {  // Not XanoScript syntax
    response.error "Invalid email"
  }
}

3. Chain Filters for Readability

// ✅ Good
$user.email|trim|lower

// ❌ Less readable
var $temp1 { value = $user.email|trim }
var $temp2 { value = $temp1|lower }

4. Use Meaningful Variable Names

// ✅ Good
$active_users
$formatted_response
$total_amount

// ❌ Bad
$au
$fr
$ta

5. Handle Errors Gracefully

// ✅ Good
http.request { url = $api_url } as $response

conditional {
  if ($response.status != 200) {
    response.error "External API failed: " + $response.status
  }
}

// ❌ Bad - no error handling
http.request { url = $api_url } as $response
response = $response.body  // Might fail if request errored

Quick Reference

Most Common Operations

Database:

  • db.query table { } as $results - Fetch records
  • db.insert table { field = value } as $record - Create record
  • db.update table { where, set } as $record - Update record
  • db.delete table { where } - Delete record

Variables:

  • var $name { value = x } - Create variable
  • var.update $name { value = y } - Update variable
  • function_call { } as $result - Assign function result

Arrays:

  • $array|count - Get length
  • $array|first - First item
  • $array|last - Last item
  • $array|push:$item - Add item

Strings:

  • $str|trim - Remove whitespace
  • $str|upper - Uppercase
  • $str|lower - Lowercase
  • $str|is_email - Validate email

Control Flow:

  • conditional { if ($cond) { } } - If statement
  • foreach ($arr) { each as $item { } } - Loop array
  • for (n) { each as $i { } } - Loop n times
  • while ($cond) { each { } } - While loop

Additional Resources


Remember: XanoScript is unique to Xano. When in doubt, check examples in the Xano visual editor or reference this guide. Test syntax incrementally to ensure correctness.