HTTP
The HTTP service in Flows provides a way for apps and blocks to receive and respond to HTTP requests from external systems. This allows your Flows applications to expose their functionality to the outside world. Receiving webhooks and exposing APIs become straightforward with this service.
HTTP endpoints are often set up during the lifecycle onSync phase and can trigger events to integrate with workflows.
This service is essential for:
- Building webhook receivers for services like GitHub, Stripe, or Slack;
- Creating API endpoints for external applications;
- Building integration bridges to external systems using complex HTTP-based authentication flows like OAuth or OIDC;
Adding HTTP capabilities
Section titled “Adding HTTP capabilities”To add HTTP capabilities to an app or a block, include an http property in its definition.
import { http } from "@slflows/sdk/v1";
{ // ... http: { onRequest: async ({ request: { method, path }}) => { // Respond to the request await http.respond(input.request.requestId, { statusCode: 200, body: { message: `Received ${method} on ${path}` }, }); }, },};HTTP endpoints and URLs
Section titled “HTTP endpoints and URLs”When you define HTTP capabilities for an app or block, Flows automatically creates a unique endpoint URL.
URL structure
Section titled “URL structure”- App endpoints: Flows generates a unique URL for each app installation
- Block endpoints: Each block with HTTP capabilities gets its own path within the app’s URL
You can access these URLs programmatically wherever app and block contexts are available:
const appEndpointUrl = input.app.http.url;const blockEndpointUrl = input.block.http.url;URL placeholders in app instructions
Section titled “URL placeholders in app instructions”When configuring apps, you can use these placeholders in instruction text that will be replaced with actual values:
{appEndpointUrl}- The complete endpoint URL (e.g.,https://app-123.flows.example.com/){appEndpointHost}- The hostname of the endpoint (e.g.,app-123.flows.example.com)
These placeholders are useful for providing users with specific URLs they need to configure in external services.
Handling requests
Section titled “Handling requests”The onRequest handler receives an input object containing:
- App or block context
- The HTTP request details
Request object structure
Section titled “Request object structure”interface HTTPRequest { requestId: string; // Unique ID for this request path: string; // Request path method: string; // HTTP method (GET, POST, etc.) headers: Record<string, string>; // HTTP headers query: Record<string, string>; // Query parameters params: Record<string, string>; // Path parameters rawBody: string; // Raw request body body: any; // Parsed body (if JSON)}Example: basic request handling
Section titled “Example: basic request handling”onRequest: async ({ request }) => { // Access request details console.log(`Method: ${request.method}`); console.log(`Path: ${request.path}`); console.log(`Query parameters:`, request.query); console.log(`Headers:`, request.headers);
// Access the body if (request.method === "POST") { console.log("Request body:", request.body); }
// Send a response await http.respond(request.requestId, { statusCode: 200, headers: { "Content-Type": "application/json", }, body: { message: "Request processed successfully", }, });};Sending responses
Section titled “Sending responses”To respond to an HTTP request, use the http.respond function:
await http.respond(requestId, response);Arguments
Section titled “Arguments”requestId: The ID of the request to respond to (from the request object)response: The HTTP response to send
Response object
Section titled “Response object”interface HTTPResponse { statusCode?: number; // Default: 200 headers?: Record<string, string>; // Response headers body?: string | object | unknown; // Response body}Response examples
Section titled “Response examples”// Simple JSON responseawait http.respond(request.requestId, { statusCode: 200, body: { message: "Success", data: result },});
// HTML responseawait http.respond(request.requestId, { statusCode: 200, headers: { "Content-Type": "text/html", }, body: "<html><body><h1>Hello World</h1></body></html>",});
// Error responseawait http.respond(request.requestId, { statusCode: 400, body: { error: "Bad request", details: "Missing required field" },});
// No content responseawait http.respond(request.requestId, { statusCode: 204,});Integrating with events
Section titled “Integrating with events”One of the most powerful patterns is using HTTP endpoints to trigger events within Flows. See the Events documentation for more details on the event system.
HTTP-to-event pattern
Section titled “HTTP-to-event pattern”import { AppBlock, http, events } from "@slflows/sdk/v1";
export const webhookBlock: AppBlock = { name: "Webhook Receiver",
http: { onRequest: async (input:): Promise<void> => { const { request } = input;
// Validate the request if (request.method !== "POST") { await http.respond(request.requestId, { statusCode: 405, body: { error: "Method not allowed" }, }); return; }
try { // Process the webhook payload const payload = request.body;
// Emit an event with the webhook data await events.emit( { type: "webhook_received", source: request.headers["user-agent"], payload, }, );
// Respond to the webhook sender await http.respond(request.requestId, { statusCode: 200, body: { status: "received" }, }); } catch (error) { console.error("Error processing webhook:", error);
await http.respond(request.requestId, { statusCode: 500, body: { error: "Internal server error" }, }); } }, },
outputs: { default: { name: "Webhook Received", description: "Emitted when a webhook is received", }, },};