Skip to content

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.