Examples (Beta)¶
This page walks through three complete examples, from service creation to invocation, covering the most common patterns for hosted services.
Example 1: Data Processing Service¶
A simple service that validates, transforms, and enriches incoming data records.
Create the Service¶
curl -X POST \
"$API_URL/api/v1/orgs/$ORG_ID/workspaces/$WS_ID/hosted-services" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"slug": "data-cleaner",
"name": "Data Cleaner",
"execution_mode": "invocation",
"ring_id": "uuid-of-ring",
"description": "Validates, deduplicates, and normalizes data records"
}'
Save the returned id as $SERVICE_ID. A draft version (v1) is created automatically.
Get the Draft Version ID¶
curl "$API_URL/api/v1/orgs/$ORG_ID/workspaces/$WS_ID/hosted-services/$SERVICE_ID/versions" \
-H "Authorization: Bearer $TOKEN"
Save the version id as $VERSION_ID.
Add Endpoints¶
Endpoint 1: Clean a single record
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": "/clean",
"method": "POST",
"name": "Clean Record",
"description": "Validate and normalize a single data record",
"request_schema": {
"type": "object",
"properties": {
"record": {
"type": "object",
"description": "The raw data record to clean"
},
"rules": {
"type": "array",
"items": {"type": "string"},
"description": "Cleaning rules to apply: trim, lowercase, deduplicate, validate_email"
}
},
"required": ["record"]
},
"response_schema": {
"type": "object",
"properties": {
"cleaned": {"type": "object"},
"changes": {
"type": "array",
"items": {
"type": "object",
"properties": {
"field": {"type": "string"},
"action": {"type": "string"},
"before": {},
"after": {}
}
}
},
"valid": {"type": "boolean"}
}
},
"timeout_seconds": 10,
"expose_as_agent_tool": true,
"tool_description": "Clean and normalize a data record by applying rules like trimming whitespace, lowercasing, and email validation"
}'
Endpoint 2: Batch clean (async-eligible)
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": "/clean/batch",
"method": "POST",
"name": "Batch Clean",
"description": "Clean multiple records in one call",
"async_eligible": true,
"timeout_seconds": 300,
"request_schema": {
"type": "object",
"properties": {
"records": {
"type": "array",
"items": {"type": "object"},
"maxItems": 10000
},
"rules": {
"type": "array",
"items": {"type": "string"}
}
},
"required": ["records"]
},
"response_schema": {
"type": "object",
"properties": {
"cleaned_count": {"type": "integer"},
"error_count": {"type": "integer"},
"results": {"type": "array", "items": {"type": "object"}}
}
}
}'
Publish the Version¶
curl -X POST \
"$API_URL/api/v1/orgs/$ORG_ID/workspaces/$WS_ID/hosted-services/$SERVICE_ID/versions/$VERSION_ID/publish" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"traffic_percent": 100}'
Invoke the Service¶
Sync -- single record:
curl -X POST \
"$API_URL/api/v1/orgs/$ORG_ID/services/$SERVICE_ID/clean" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"record": {"name": " John Doe ", "email": "JOHN@EXAMPLE.COM"},
"rules": ["trim", "lowercase"]
}'
Response:
{
"cleaned": {"name": "John Doe", "email": "john@example.com"},
"changes": [
{"field": "name", "action": "trim", "before": " John Doe ", "after": "John Doe"},
{"field": "email", "action": "lowercase", "before": "JOHN@EXAMPLE.COM", "after": "john@example.com"}
],
"valid": true
}
Async -- batch records:
curl -X POST \
"$API_URL/api/v1/orgs/$ORG_ID/services/$SERVICE_ID/async/clean/batch" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-H "X-HSL-Lane: bulk" \
-d '{
"records": [
{"name": " Alice ", "email": "alice@test.com"},
{"name": "Bob", "email": "INVALID"}
],
"rules": ["trim", "validate_email"]
}'
Response:
{
"job_id": "abc-123",
"status": "staged",
"poll_url": "/api/v1/orgs/.../services/.../jobs/abc-123"
}
Example 2: AI-Powered Analysis Service¶
A service that uses the platform's AI Gateway to analyze text.
Create and Configure¶
curl -X POST \
"$API_URL/api/v1/orgs/$ORG_ID/workspaces/$WS_ID/hosted-services" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"slug": "ai-analyzer",
"name": "AI Text Analyzer",
"execution_mode": "invocation",
"ring_id": "uuid-of-ring",
"description": "LLM-powered text analysis including summarization, classification, and entity extraction"
}'
Define the Endpoints¶
After getting the service ID and draft version ID, add the endpoints.
Summarize endpoint:
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": "/summarize",
"method": "POST",
"name": "Summarize Text",
"description": "Generate a concise summary of the input text using an LLM",
"timeout_seconds": 60,
"async_eligible": true,
"expose_as_agent_tool": true,
"tool_description": "Summarize a block of text into a concise paragraph. Supports configurable length and style.",
"request_schema": {
"type": "object",
"properties": {
"text": {"type": "string", "description": "The text to summarize", "minLength": 1},
"max_length": {"type": "integer", "description": "Target summary length in words", "default": 100},
"style": {"type": "string", "enum": ["bullet_points", "paragraph", "executive"], "default": "paragraph"}
},
"required": ["text"]
},
"response_schema": {
"type": "object",
"properties": {
"summary": {"type": "string"},
"word_count": {"type": "integer"},
"model_used": {"type": "string"}
}
}
}'
Classify endpoint:
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": "/classify",
"method": "POST",
"name": "Classify Text",
"description": "Classify text into one or more categories",
"timeout_seconds": 30,
"expose_as_agent_tool": true,
"tool_description": "Classify text content into provided categories with confidence scores",
"request_schema": {
"type": "object",
"properties": {
"text": {"type": "string", "minLength": 1},
"categories": {
"type": "array",
"items": {"type": "string"},
"description": "List of categories to classify against"
},
"multi_label": {"type": "boolean", "default": false}
},
"required": ["text", "categories"]
},
"response_schema": {
"type": "object",
"properties": {
"predictions": {
"type": "array",
"items": {
"type": "object",
"properties": {
"category": {"type": "string"},
"confidence": {"type": "number"}
}
}
}
}
}
}'
Publish and Invoke¶
# Publish
curl -X POST \
"$API_URL/api/v1/orgs/$ORG_ID/workspaces/$WS_ID/hosted-services/$SERVICE_ID/versions/$VERSION_ID/publish" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"traffic_percent": 100}'
# Invoke summarization
curl -X POST \
"$API_URL/api/v1/orgs/$ORG_ID/services/$SERVICE_ID/summarize" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"text": "Manifest Platform v2 is an enterprise-ready operating system for orchestrating data, agents, and workflows. It provides hosted services, AI gateway, connectors, and a comprehensive security model...",
"max_length": 50,
"style": "executive"
}'
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)
# Sync summarization
result = client.invoke_service(
service_id="your-service-uuid",
method="POST",
path="/summarize",
body={
"text": "Long article content here...",
"max_length": 100,
"style": "bullet_points",
},
)
print(result["summary"])
# Classify
result = client.invoke_service(
service_id="your-service-uuid",
method="POST",
path="/classify",
body={
"text": "The quarterly earnings exceeded expectations...",
"categories": ["finance", "technology", "healthcare", "politics"],
},
)
for pred in result["predictions"]:
print(f" {pred['category']}: {pred['confidence']:.0%}")
Example 3: Integration Service with External APIs¶
A service that calls external APIs, authenticates with a service token, and supports both sync and async patterns.
Create the Service¶
curl -X POST \
"$API_URL/api/v1/orgs/$ORG_ID/workspaces/$WS_ID/hosted-services" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"slug": "crm-sync",
"name": "CRM Sync Service",
"execution_mode": "invocation",
"ring_id": "uuid-of-ring",
"description": "Syncs customer records between the platform and an external CRM"
}'
Define Endpoints with Service Token Auth¶
These endpoints use service_token auth for machine-to-machine access:
Sync a single contact:
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": "/contacts/{contact_id}/sync",
"method": "POST",
"name": "Sync Contact",
"description": "Push a single contact record to the external CRM",
"auth_mode": "service_token",
"timeout_seconds": 15,
"request_schema": {
"type": "object",
"properties": {
"fields": {
"type": "object",
"properties": {
"email": {"type": "string", "format": "email"},
"name": {"type": "string"},
"company": {"type": "string"},
"phone": {"type": "string"}
}
},
"upsert": {"type": "boolean", "default": true}
},
"required": ["fields"]
},
"response_schema": {
"type": "object",
"properties": {
"crm_id": {"type": "string"},
"action": {"type": "string", "enum": ["created", "updated", "skipped"]},
"synced_at": {"type": "string", "format": "date-time"}
}
}
}'
Bulk sync (async):
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": "/contacts/bulk-sync",
"method": "POST",
"name": "Bulk Sync Contacts",
"description": "Sync multiple contacts to the external CRM in batch",
"auth_mode": "service_token",
"async_eligible": true,
"timeout_seconds": 600,
"request_schema": {
"type": "object",
"properties": {
"contacts": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {"type": "string"},
"fields": {"type": "object"}
},
"required": ["id", "fields"]
},
"maxItems": 5000
}
},
"required": ["contacts"]
},
"response_schema": {
"type": "object",
"properties": {
"total": {"type": "integer"},
"created": {"type": "integer"},
"updated": {"type": "integer"},
"failed": {"type": "integer"},
"errors": {"type": "array", "items": {"type": "object"}}
}
}
}'
Publish¶
curl -X POST \
"$API_URL/api/v1/orgs/$ORG_ID/workspaces/$WS_ID/hosted-services/$SERVICE_ID/versions/$VERSION_ID/publish" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"traffic_percent": 100}'
Create an API Key and Mint a Service Token¶
Service token endpoints require an HSL service token. First, create an API key with auth scope:
# Create an auth-scoped API key
curl -X POST \
"$API_URL/api/v1/orgs/$ORG_ID/workspaces/$WS_ID/hosted-services/$SERVICE_ID/api-keys" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "CRM Integration Key", "scopes": ["auth"]}'
Save the plaintext_key from the response -- it is only shown once.
Then mint a service token:
# Mint a token using the management API (no raw API key needed)
curl -X POST \
"$API_URL/api/v1/orgs/$ORG_ID/workspaces/$WS_ID/hosted-services/$SERVICE_ID/service-tokens/mint" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"claims": {"integration": "crm", "env": "production"}, "ttl_minutes": 60}'
Invoke with a Service Token¶
# Sync: single contact
curl -X POST \
"$API_URL/api/v1/orgs/$ORG_ID/services/$SERVICE_ID/contacts/ct_123/sync" \
-H "Authorization: Bearer $SERVICE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"fields": {"email": "alice@example.com", "name": "Alice"}, "upsert": true}'
# Async: bulk sync
curl -X POST \
"$API_URL/api/v1/orgs/$ORG_ID/services/$SERVICE_ID/async/contacts/bulk-sync" \
-H "Authorization: Bearer $SERVICE_TOKEN" \
-H "Content-Type: application/json" \
-H "X-HSL-Lane: bulk" \
-d '{
"contacts": [
{"id": "ct_123", "fields": {"email": "alice@example.com"}},
{"id": "ct_456", "fields": {"email": "bob@example.com"}}
]
}'
End-to-End Python Walkthrough¶
Combining all patterns into a single Python script using the SDK:
Coming Soon
The Python SDK for local development is not yet publicly available.
"""End-to-end hosted service example using flow-sdk."""
import time
import httpx
from flow_sdk.cli_client import CLIClient
from flow_sdk.config import FlowConfig
# 1. Load config and create client
config = FlowConfig.load()
client = CLIClient(config)
api = config.platform_url
headers = {"Authorization": f"Bearer {config.access_token}"}
base = f"{api}/api/v1/orgs/{config.org_id}/workspaces/{config.workspace_id}"
# 2. Create a service
svc = httpx.post(f"{base}/hosted-services", headers=headers, json={
"slug": "example-service",
"name": "Example Service",
"execution_mode": "invocation",
"ring_id": "uuid-of-ring",
}).json()
service_id = svc["id"]
print(f"Created service: {service_id}")
# 3. Get the draft version
versions = httpx.get(
f"{base}/hosted-services/{service_id}/versions", headers=headers,
).json()
version_id = versions["items"][0]["id"]
# 4. Add an endpoint
httpx.post(
f"{base}/hosted-services/{service_id}/versions/{version_id}/endpoints",
headers=headers,
json={
"path": "/greet",
"method": "POST",
"name": "Greet",
"description": "Returns a greeting message",
"async_eligible": True,
"request_schema": {
"type": "object",
"properties": {"name": {"type": "string"}},
"required": ["name"],
},
"response_schema": {
"type": "object",
"properties": {"message": {"type": "string"}},
},
},
)
print("Added endpoint: POST /greet")
# 5. Publish the version
httpx.post(
f"{base}/hosted-services/{service_id}/versions/{version_id}/publish",
headers=headers,
json={"traffic_percent": 100},
)
print("Published version 1")
# 6. Sync invocation via SDK
result = client.invoke_service(
service_id=service_id,
method="POST",
path="/greet",
body={"name": "World"},
)
print(f"Sync result: {result}")
# 7. Async invocation
gw_base = f"{api}/api/v1/orgs/{config.org_id}/services/{service_id}"
job_resp = httpx.post(
f"{gw_base}/async/greet",
headers=headers,
json={"name": "Async World"},
).json()
job_id = job_resp["job_id"]
print(f"Async job submitted: {job_id}")
# 8. Poll for completion
while True:
status = httpx.get(
f"{gw_base}/jobs/{job_id}", headers=headers,
).json()
if status["status"] in ("completed", "failed", "cancelled"):
break
print(f" Job status: {status['status']}")
time.sleep(1)
print(f"Final status: {status['status']}")
if status["status"] == "completed":
print(f"Result: {status['result_summary']}")
# 9. Fetch generated artifacts
skills = httpx.get(f"{gw_base}/skills.json", headers=headers).json()
print(f"Skills generated: {len(skills.get('endpoint_skills', []))} endpoint(s)")
openapi = httpx.get(f"{gw_base}/openapi.json", headers=headers).json()
print(f"OpenAPI spec: {openapi.get('info', {}).get('title')}")
Explore the generated docs
After publishing, visit https://api.flow.marut.cloud/api/v1/orgs/{org_id}/services/{service_id}/docs in a browser to see the interactive Swagger UI for your service.