Skip to main content

API Routes

Capela automatically generates API routes for your application, allowing you to interact with it through a RESTful API.

Overview

Capela provides two main types of API routes:

  1. Function Routes (/d/): Call functions on your application
  2. State Routes (/g/): Fetch and modify state variables from your application

Function Routes (/d/)

Function routes let you call functions on your application:

http POST 'http://localhost:22440/d/!partition_id/function_name' param1=value1 param2=value2

Example

# Call the say_hello_to function
http POST 'http://localhost:22440/d/!partition_id/say_hello_to' name="Alice"

Parameters

Parameters are passed as query parameters in the URL. The parameter names must match the parameter names in your function definition.

def say_hello_to(self, name: str):
this.count += 1
return f"Hello, {name}! The count is: {this.count}"

In this example, the parameter name is name, so the API call would be:

http POST 'http://localhost:22440/d/!partition_id/say_hello_to' name="Alice"

Return Values

Function routes return the return value of the function. In the example above, the return value would be:

"Hello, Alice! The count is: 1"

State Routes (/g/)

State routes let you fetch and modify state variables from your application:

# GET state
http GET 'http://localhost:22440/g/!partition_id/variable_name'

# POST state
http POST 'http://localhost:22440/g/!partition_id/variable_name' --raw value

Example

# Fetch the count variable
http GET 'http://localhost:22440/g/!partition_id/count'

# Set a value in a dictionary
http POST 'http://localhost:22440/g/!partition_id/exampleDict/"new_key"' --raw 5

# Set a value in an array
http POST 'http://localhost:22440/g/!partition_id/exampleArray/0' --raw "new_value"

Content-Location Headers

All responses include a content-location header that provides the canonical path to the accessed item. For example:

content-location: /!acb01737d7434a3877089e5cdcbe122b739c2c9cf529349f468bae1fb5a20be1/%0

You can use either:

  • The full path with %0 notation
  • The human-readable path (e.g., /go/to/path)

Nested Variables

You can access nested variables using dot notation or array notation:

# Fetch a nested variable
http GET 'http://localhost:22440/g/!partition_id/users/Alice/name'

# Set a nested variable
http POST 'http://localhost:22440/g/!partition_id/users/Alice/name' --raw "Bob"

Collection Variables

You can access collection variables using array notation or quoted keys for dictionaries:

# Fetch a collection variable
http GET 'http://localhost:22440/g/!partition_id/users'

# Set a dictionary value
http POST 'http://localhost:22440/g/!partition_id/users/"Alice"' --raw '{"name": "Alice", "age": 30}'

# Set an array value
http POST 'http://localhost:22440/g/!partition_id/users/0' --raw '{"name": "Alice", "age": 30}'

WebSocket SDK

The WebSocket SDK provides a more efficient way to interact with your application's state, especially for frontend applications. It offers real-time updates, automatic reconnection, and efficient caching.

For detailed information about the WebSocket SDK, including features, best practices, and examples, see the WebSocket SDK documentation.

Basic usage example:

import { getValue, setValue, subscribe } from 'capela-sdk';

// Get a value
const value = await getValue("!partition_id/variable_name");

// Set a value
await setValue("!partition_id/variable_name", new_value);

// Subscribe to changes
const unsubscribe = subscribe("!partition_id/variable_name", (newValue) => {
console.log("Value changed:", newValue);
});

// Later, when you want to stop listening:
unsubscribe();

Example: User Manager

Here's a simple example of an application that uses API routes:

from builtins import Node, Field, Dict, List

class User(Node):
name: str = Field(default="")
age: int = Field(default=0)
is_active: bool = Field(default=True)

def activate(self):
this.is_active = True
return this.is_active

def deactivate(self):
this.is_active = False
return this.is_active

class UserManager(Node):
users: Dict[str, User] = Field(default_factory=dict)

def register_user(self, user_name: str, age: int) -> User:
if user_name not in this.users:
user = User(name=user_name, age=age)
this.users[user_name] = user
return user
return this.users[user_name]

def get_user(self, user_name: str) -> User:
if user_name in this.users:
return this.users[user_name]
return None

def list_users(self) -> List[str]:
return list(this.users.keys())

To use this application:

  1. Deploy the application:

    capelac deploy apps/user_manager
  2. Create a partition:

    http POST 'http://localhost:22440/partitions' object_type=ai.asmc.user_manager.UserManager
  3. Use the API routes:

    # Register a user
    http POST 'http://localhost:22440/d/!partition_id/register_user' user_name="Alice" age=30

    # Get a user
    http GET 'http://localhost:22440/g/!partition_id/users/Alice'

    # List users
    http GET 'http://localhost:22440/g/!partition_id/users'

    # Activate a user
    http POST 'http://localhost:22440/d/!partition_id/users/Alice/activate'

    # Deactivate a user
    http POST 'http://localhost:22440/d/!partition_id/users/Alice/deactivate'