Skip to content

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:

/users/{user_id}
/projects/{project_id}/documents/{doc_id}

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:

  1. Runtime validation -- the gateway validates incoming requests and outgoing responses against these schemas.
  2. 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)

{"auth_mode": "platform"}

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

{"auth_mode": "service_token"}

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

{"auth_mode": "none"}

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:

{
  "auth_mode": "platform",
  "requires_scopes": ["data:read", "analytics:execute"]
}

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_limit_tier": "standard"}

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:

Deprecation: true
Sunset: 2025-06-01
Location: /api/v1/orgs/.../v2/analyze

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:

https://api.flow.marut.cloud/api/v1/orgs/{org_id}/services/{service_id}/docs

The OpenAPI spec is also available as JSON:

https://api.flow.marut.cloud/api/v1/orgs/{org_id}/services/{service_id}/openapi.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.