Endpoints (Beta)¶
Endpoints are the building blocks of a hosted service. Each endpoint defines a single HTTP route with its method, path, input/output schemas, code, and runtime configuration.
Creating an Endpoint¶
Endpoints are added to a draft version. You cannot modify endpoints on a published version.
import httpx
endpoint = httpx.post(
f"{api_url}/api/v1/orgs/{org_id}/workspaces/{ws_id}"
f"/hosted-services/{service_id}/versions/{version_id}/endpoints",
headers={"Authorization": f"Bearer {token}"},
json={
"path": "/analyze",
"method": "POST",
"name": "Analyze Document",
"description": "Accepts a document and returns structured analysis",
"body_mode": "json",
"request_schema": {
"type": "object",
"properties": {
"content": {"type": "string"},
"analysis_type": {"type": "string", "enum": ["summary", "entities", "sentiment"]},
},
"required": ["content"],
},
"response_schema": {
"type": "object",
"properties": {
"result": {"type": "object"},
"confidence": {"type": "number"},
},
},
"timeout_seconds": 30,
"async_eligible": True,
"expose_as_agent_tool": True,
"tool_description": "Analyze a document for summaries, entities, or sentiment",
},
).json()
curl -X POST \
"$API_URL/api/v1/orgs/$ORG_ID/workspaces/$WS_ID/hosted-services/$SERVICE_ID/versions/$VERSION_ID/endpoints" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"path": "/analyze",
"method": "POST",
"name": "Analyze Document",
"description": "Accepts a document and returns structured analysis",
"timeout_seconds": 30,
"async_eligible": true
}'
Endpoint Fields¶
Required Fields¶
| Field | Type | Description |
|---|---|---|
path |
string | URL path for the endpoint (e.g., /analyze, /users/{user_id}) |
method |
string | HTTP method: GET, POST, PUT, PATCH, or DELETE |
Optional Fields¶
| Field | Type | Default | Description |
|---|---|---|---|
name |
string | null |
Human-readable name |
description |
string | null |
What this endpoint does |
code_block_id |
UUID | null |
Reference to the code block containing the handler function |
entry_function |
string | null |
Name of the function to call in the code block |
body_mode |
string | json |
Request body format (see below) |
request_schema |
object | {} |
JSON Schema for request validation |
response_schema |
object | {} |
JSON Schema for response validation |
timeout_seconds |
integer | 30 |
Max execution time in seconds |
async_eligible |
boolean | false |
Whether the endpoint supports async job submission |
auth_mode |
string | platform |
Authentication mode (see below) |
rate_limit_tier |
string | null |
Rate limiting tier name |
requires_scopes |
array | [] |
Required permission scopes |
expose_as_api |
boolean | true |
Expose through the Service Gateway |
expose_as_workflow_step |
boolean | false |
Make available as a workflow step |
expose_as_agent_tool |
boolean | false |
Generate a Skill for agent discovery |
tool_description |
string | null |
Description shown to agents when discovering the Skill |
Body Modes¶
The body_mode field controls how the endpoint receives request data:
| Mode | Content Type | Use case |
|---|---|---|
json |
application/json |
Structured data (default) |
multipart |
multipart/form-data |
File uploads with metadata |
binary |
application/octet-stream |
Raw binary data |
empty |
n/a | No request body (GET endpoints) |
Path Parameters¶
Endpoints support path parameters using curly brace syntax:
Path parameters are extracted automatically and passed to your handler function. When the endpoint is exposed as a Skill, path parameters are included in the generated schema so agents can provide them.
Input/Output Schemas¶
Schemas use standard JSON Schema and serve two purposes:
- Runtime validation -- the gateway validates incoming requests and outgoing responses against these schemas.
- Skill generation -- schemas become the input/output definitions for auto-generated Skills.
Request Schema Example¶
{
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "Search query to process",
"minLength": 1
},
"limit": {
"type": "integer",
"description": "Maximum results to return",
"default": 10,
"minimum": 1,
"maximum": 100
},
"filters": {
"type": "object",
"properties": {
"category": {"type": "string"},
"date_from": {"type": "string", "format": "date"}
}
}
},
"required": ["query"]
}
Response Schema Example¶
{
"type": "object",
"properties": {
"results": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {"type": "string"},
"title": {"type": "string"},
"score": {"type": "number"}
}
}
},
"total": {"type": "integer"},
"query_time_ms": {"type": "number"}
}
}
Write descriptive schemas
Include description fields on your schema properties. When the endpoint is exposed as a Skill, these descriptions help agents understand what data to provide and what to expect back.
Request Context Injection¶
If your schema includes "x-hsl-request-context": true, the validation layer passes the full request context (method, headers, query params, body, files) instead of just the body:
{
"type": "object",
"x-hsl-request-context": true,
"properties": {
"method": {"type": "string"},
"body": {"type": "object"},
"query_params": {"type": "object"},
"headers": {"type": "object"}
}
}
Authentication Modes¶
Each endpoint controls its own authentication requirements:
Platform Auth (default)¶
Callers authenticate with their platform JWT token. The gateway checks that the token is valid and the caller has the required scopes.
Service Token Auth¶
Callers authenticate with an HSL service token minted specifically for this service. Useful for machine-to-machine communication where the caller is not a platform user.
No Auth¶
The endpoint is publicly accessible without authentication. Use with caution.
Auth mode applies per endpoint
Different endpoints on the same service can use different auth modes. A service might have a public health-check endpoint (none) alongside authenticated business logic endpoints (platform).
Required Scopes¶
When using platform auth mode, you can require specific permission scopes:
The gateway rejects requests where the caller's token does not include all required scopes.
Rate Limiting¶
Assign a rate limit tier to control request throughput:
Rate limits are enforced per organization, per service, per endpoint. The available tiers are configured at the platform level.
Endpoint Deprecation¶
Mark an endpoint as deprecated by adding metadata to the response schema:
{
"response_schema": {
"type": "object",
"x-hsl-deprecated": true,
"x-hsl-sunset": "2025-06-01",
"x-hsl-redirect-to": "/api/v1/orgs/{org_id}/services/{service_id}/v2/analyze",
"properties": { }
}
}
When a deprecated endpoint is called, the gateway includes standard HTTP deprecation headers in the response:
Testing Endpoints¶
Draft Preview¶
Draft endpoint testing is available through the Platform UI (Hosted Services → [Service] → Endpoints → Test). No REST preview route is exposed.
Published Endpoint Testing¶
After publishing, test through the Service Gateway:
# Active version
curl -X POST \
"$API_URL/api/v1/orgs/$ORG_ID/services/$SERVICE_ID/analyze" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"content": "Test document"}'
# Specific version
curl -X POST \
"$API_URL/api/v1/orgs/$ORG_ID/services/$SERVICE_ID/v2/analyze" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"content": "Test document"}'
Using the SDK¶
Coming Soon
The Python SDK for local development is not yet publicly available.
from flow_sdk.cli_client import CLIClient
from flow_sdk.config import FlowConfig
config = FlowConfig.load()
client = CLIClient(config)
result = client.invoke_service(
service_id="your-service-uuid",
method="POST",
path="/analyze",
body={"content": "Test document", "analysis_type": "summary"},
)
print(result)
Auto-Generated API Docs¶
Every published service gets a Swagger UI page:
The OpenAPI spec is also available as JSON:
Updating Endpoints¶
Endpoints can only be modified on draft versions. To change an endpoint:
curl -X PATCH \
"$API_URL/api/v1/orgs/$ORG_ID/workspaces/$WS_ID/hosted-services/$SERVICE_ID/versions/$VERSION_ID/endpoints/$ENDPOINT_ID" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"timeout_seconds": 60, "description": "Updated description"}'
To remove an endpoint from a draft version:
curl -X DELETE \
"$API_URL/api/v1/orgs/$ORG_ID/workspaces/$WS_ID/hosted-services/$SERVICE_ID/versions/$VERSION_ID/endpoints/$ENDPOINT_ID" \
-H "Authorization: Bearer $TOKEN"
Published endpoints are immutable
Attempting to modify or delete an endpoint on a published version returns 409 Conflict. Create a new draft version instead.