Invocable Functions
Invocable 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, PUT, DELETE)
- Set role-based access control per method
- Write JavaScript code to handle requests
- Call the endpoint via HTTP
URL Structure
https://<region>.restapi.com/<api-name>/endpoint/<function-endpoint>
Example:
https://eu.restapi.com/my-api/endpoint/calculate-shipping
Configuration
Basic Settings
| Setting | Description |
|---|---|
| Name | Unique identifier for the function |
| Description | Optional documentation |
| Enabled | Toggle to enable/disable |
| Endpoint | URL path (e.g., calculate-shipping) |
HTTP Methods
Configure which methods the endpoint accepts:
| Method | Typical Use |
|---|---|
GET | Retrieve data, calculations |
POST | Create resources, complex operations |
PUT | Replace resources |
DELETE | Remove resources |
Access Control
Unlike trigger and timer functions, invocable 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 onlyDELETE→ Manager role only
Execution Context
What Your Code Receives
| Property | Description |
|---|---|
body | Request body (JSON) |
method | HTTP method (GET, POST, PUT, DELETE) |
headers | Request headers (filtered for security) |
query | Query parameters |
user | Authenticated user information (if any) |
Returning Responses
Return data from your function:
// Return JSON data
return {
success: true,
result: calculatedValue
};
The returned object becomes the HTTP response body.
Use Cases
Custom Calculations
Perform calculations that require server-side logic:
// Calculate shipping cost
const { weight, destination, method } = body;
let baseCost = weight * 0.5;
if (destination === 'international') {
baseCost *= 2.5;
}
if (method === 'express') {
baseCost *= 1.5;
}
return {
shippingCost: Math.round(baseCost * 100) / 100,
estimatedDays: method === 'express' ? 2 : 7
};
Webhook Handlers
Receive webhooks from external services:
// Handle Stripe webhook
const event = body;
switch (event.type) {
case 'payment_intent.succeeded':
const paymentIntent = event.data.object;
// Update order status
await fetch(`${apiUrl}/orders/${paymentIntent.metadata.orderId}`, {
method: 'PATCH',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
paymentStatus: 'paid',
stripePaymentId: paymentIntent.id
})
});
break;
case 'payment_intent.payment_failed':
// Handle failure
break;
}
return { received: true };
Aggregation Endpoints
Create endpoints that aggregate data:
// Dashboard statistics
const [orders, customers, products] = await Promise.all([
fetch(`${apiUrl}/orders?count=true`, { headers: { 'Authorization': `Bearer ${token}` } }).then(r => r.json()),
fetch(`${apiUrl}/customers?count=true`, { headers: { 'Authorization': `Bearer ${token}` } }).then(r => r.json()),
fetch(`${apiUrl}/products?count=true`, { headers: { 'Authorization': `Bearer ${token}` } }).then(r => r.json())
]);
return {
totalOrders: orders.meta.count,
totalCustomers: customers.meta.count,
totalProducts: products.meta.count,
recentOrders: orders.items.slice(0, 5)
};
Multi-Step Operations
Orchestrate complex operations:
// Create order with inventory check
const { customerId, items } = body;
// Check inventory
for (const item of items) {
const product = await fetch(`${apiUrl}/products/${item.productId}`, {
headers: { 'Authorization': `Bearer ${token}` }
}).then(r => r.json());
if (product.stockLevel < item.quantity) {
return {
error: `Insufficient stock for ${product.name}`,
available: product.stockLevel
};
}
}
// Create order
const order = await fetch(`${apiUrl}/orders`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
customerId,
items,
status: 'pending',
total: items.reduce((sum, i) => sum + i.price * i.quantity, 0)
})
}).then(r => r.json());
// Reserve inventory
for (const item of items) {
await fetch(`${apiUrl}/products/${item.productId}`, {
method: 'PATCH',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
stockLevel: { $decrement: item.quantity }
})
});
}
return { orderId: order.id, status: 'created' };
Authentication Extensions
Implement custom authentication flows:
// Verify external token and create session
const { externalToken } = body;
// Verify with external auth provider
const verification = await fetch('https://auth.example.com/verify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ token: externalToken })
}).then(r => r.json());
if (!verification.valid) {
return { error: 'Invalid token' };
}
// Find or create user
let user = await fetch(`${apiUrl}/users?filter=externalId eq "${verification.userId}"`, {
headers: { 'Authorization': `Bearer ${token}` }
}).then(r => r.json());
if (user.items.length === 0) {
user = await fetch(`${apiUrl}/users`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
externalId: verification.userId,
email: verification.email,
name: verification.name
})
}).then(r => r.json());
}
return {
userId: user.id || user.items[0].id,
authenticated: true
};
Calling Invocable Functions
From JavaScript
const response = await fetch('https://eu.restapi.com/my-api/endpoint/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://eu.restapi.com/my-api/endpoint/calculate-shipping \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"weight": 2.5, "destination": "domestic", "method": "standard"}'
Best Practices
- Use meaningful endpoint names —
/calculate-shippingis better than/func1 - Validate input — Check request body and query parameters
- Return consistent responses — Use a standard response structure
- Handle errors gracefully — Return meaningful error messages
- Set appropriate access control — Don't expose sensitive operations publicly
- Document your endpoints — Use the description field