HTTP Functions
HTTP functions create custom HTTP endpoints that execute your code on demand. Use them for custom APIs, webhook handlers, and complex operations.
How It Works
- Define a unique endpoint path (e.g.,
calculate-shipping) - Configure which HTTP methods are allowed (GET, POST)
- Set role-based access control per method
- Write JavaScript code to handle requests
- Call the endpoint via HTTP
URL Structure
/api/{function-name}
Example:
/api/calculate-shipping
External clients should replace /api with https://<region>.restapi.com/<api-name>. See Hosted Webapps for details.
Usage:
fetch("/api/calculate-shipping", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ weight: 2.5 }),
});
The path is /api/<function-name> — not /<function-name>. The /api prefix is required.
Configuration
Basic Settings
| Setting | Description |
|---|---|
| Name | Unique identifier for the function (used in URL) |
| Description | Optional documentation |
| Enabled | Toggle to enable/disable |
HTTP Methods
Configure which methods the endpoint accepts:
| Method | Typical Use |
|---|---|
GET | Retrieve data, calculations |
POST | Create resources, complex operations |
Access Control
Unlike trigger and timer functions, HTTP functions have role-based access control per HTTP method:
| Role | Description |
|---|---|
| Anonymous user | No authentication required |
| Authenticated user | Any logged-in user |
| Custom roles | Your defined roles |
Configure different permissions for each method. For example:
GET→ Anonymous (public)POST→ Authenticated users only
Execution Context
What Your Code Receives
| Object | Description |
|---|---|
req.bodyJson | Parsed JSON request body |
req.body | Raw request body string |
req.method | HTTP method (GET, POST) |
req.headers | Request headers (filtered for security) |
req.query | Query parameters |
me | Authenticated user information (if any) |
api | API information |
secrets | Configured secrets |
Returning Responses
Set the res object to return data:
// Return JSON response
res = {
status: 200,
bodyJson: {
success: true,
result: calculatedValue,
},
};
// Or just set bodyJson (status defaults to 200)
res = {
bodyJson: { message: "Done" },
};
Use Cases
Custom Calculations
Perform calculations that require server-side logic:
const { weight, destination, method } = req.bodyJson;
let baseCost = weight * 0.5;
if (destination === "international") {
baseCost *= 2.5;
}
if (method === "express") {
baseCost *= 1.5;
}
res = {
bodyJson: {
shippingCost: Math.round(baseCost * 100) / 100,
estimatedDays: method === "express" ? 2 : 7,
},
};
Webhook Handlers
Receive webhooks from external services:
// Handle Stripe webhook
const event = req.bodyJson;
switch (event.type) {
case "payment_intent.succeeded":
const paymentIntent = event.data.object;
// Update order status using built-in method
await patch(`orders/${paymentIntent.metadata.orderId}`, {
paymentStatus: "paid",
stripePaymentId: paymentIntent.id,
});
break;
case "payment_intent.payment_failed":
// Handle failure
break;
}
res = { bodyJson: { received: true } };
Aggregation Endpoints
Create endpoints that aggregate data:
// Dashboard statistics - use built-in methods
const [ordersRes, customersRes, productsRes] = await Promise.all([
get("orders?count=true"),
get("customers?count=true"),
get("products?count=true"),
]);
res = {
bodyJson: {
totalOrders: ordersRes.meta?.count || 0,
totalCustomers: customersRes.meta?.count || 0,
totalProducts: productsRes.meta?.count || 0,
recentOrders: ordersRes.data.slice(0, 5),
},
};
Multi-Step Operations
Orchestrate complex operations:
// Create order with inventory check
const { customerId, items } = req.bodyJson;
// Check inventory using built-in method
for (const item of items) {
const productRes = await get(`products/${item.productId}`);
const product = productRes.data[0];
if (product.stockLevel < item.quantity) {
res = {
status: 400,
bodyJson: {
error: `Insufficient stock for ${product.name}`,
available: product.stockLevel,
},
};
return;
}
}
// Create order
const orderRes = await post("orders", {
customerId,
items,
status: "pending",
total: items.reduce((sum, i) => sum + i.price * i.quantity, 0),
});
const orderId = orderRes.data[0];
// Reserve inventory
for (const item of items) {
const productRes = await get(`products/${item.productId}`);
const product = productRes.data[0];
await patch(`products/${item.productId}`, {
stockLevel: product.stockLevel - item.quantity,
});
}
res = { bodyJson: { orderId, status: "created" } };
Validation with Errors
Use validationErrors for user-facing validation:
const { email, name, age } = req.bodyJson;
if (!email) {
validationErrors.push("Email is required");
}
if (!name || name.length < 2) {
validationErrors.push("Name must be at least 2 characters");
}
if (age && age < 18) {
validationErrors.push("Must be 18 or older");
}
// If validationErrors has items, returns 400 automatically
if (validationErrors.length > 0) {
return; // Stop execution
}
// Proceed with valid data
const userRes = await post("users", { email, name, age });
res = { bodyJson: { userId: userRes.data[0], created: true } };
External API Integration
Call external APIs (requires paid tier):
// Verify address with external service
const { address } = req.bodyJson;
const verification = await fetch("https://api.addressvalidator.com/verify", {
method: "POST",
headers: {
Authorization: `Bearer ${secrets.ADDRESS_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ address }),
});
const result = await verification.json();
res = {
bodyJson: {
valid: result.valid,
standardized: result.standardizedAddress,
},
};
Calling HTTP Functions
From a Hosted Web App
If your frontend is hosted on RestAPI.com, use the /api virtual path — no CORS or auth headers needed:
const response = await fetch("/api/calculate-shipping", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
weight: 2.5,
destination: "domestic",
method: "standard",
}),
});
const result = await response.json();
console.log(result.shippingCost);
From External Clients
Use the full region-specific URL with an auth token:
const response = await fetch(
"https://<region>.restapi.com/<api-name>/calculate-shipping",
{
method: "POST",
headers: {
Authorization: "Bearer <token>",
"Content-Type": "application/json",
},
body: JSON.stringify({
weight: 2.5,
destination: "domestic",
method: "standard",
}),
},
);
const result = await response.json();
console.log(result.shippingCost);
From cURL
curl -X POST https://<region>.restapi.com/<api-name>/calculate-shipping \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"weight": 2.5, "destination": "domestic", "method": "standard"}'
Best Practices
- Use meaningful function names —
calculate-shippingis better thanfunc1 - Validate input — Check
req.bodyJsonfields and usevalidationErrors - Use built-in methods —
get(),post(),patch()for internal API calls - Use
fetchonly for external APIs — External calls require paid tier - Set appropriate access control — Don't expose sensitive operations publicly
- Return consistent responses — Use a standard response structure