Skip to main content
Endpoints are the primary interface for querying Syft Space. They combine datasets, models, and policies into a single API that clients can query to retrieve information or generate responses.

Endpoint entity

An endpoint is defined by the following properties:
class Endpoint:
    id: UUID                # Unique identifier
    tenant_id: UUID         # Tenant isolation
    name: str               # Display name
    slug: str               # URL path (unique per tenant)
    description: str        # Markdown documentation
    summary: str            # Brief description
    dataset_id: UUID | None # Linked dataset (optional)
    model_id: UUID | None   # Linked model (optional)
    response_type: str      # "raw", "summary", or "both"
    published: bool         # Whether endpoint is queryable
    tags: str               # Comma-separated tags
    published_to: list[str] # Marketplace IDs where published
    created_at: datetime
    updated_at: datetime
Location: backend/syft_space/components/endpoints/entities.py:27
At least one of dataset_id or model_id must be provided. An endpoint cannot exist without connecting to either a dataset or a model.

Response types

Endpoints support three response configurations:
class ResponseType(Enum):
    RAW = "raw"          # Dataset search only
    SUMMARY = "summary"  # Model generation only
    BOTH = "both"        # Dataset search + model generation (RAG)
Location: backend/syft_space/components/endpoints/entities.py:19

Response type behaviors

Dataset only - returns search results without model processing.Query flow:
  1. Search dataset with user query
  2. Return matching documents
Response structure:
{
  "references": {
    "documents": [
      {
        "document_id": "doc123",
        "content": "Document text...",
        "similarity_score": 0.92,
        "metadata": {}
      }
    ],
    "provider_info": {"search_engine": "weaviate"},
    "cost": 0.0
  },
  "summary": null
}
Use cases: Document retrieval, similarity search, fact lookup

Query flow

When a client queries an endpoint, the following pipeline executes: Location: backend/syft_space/components/endpoints/handlers.py:236

Step-by-step execution

1

Authentication

Verify request has valid SyftHub tokenExtract sender_email from token for policy context
2

Pre-hook policies

Execute all attached policies’ pre_hook() methods
for policy_type, configs in policies_by_type.items():
    policy_instance.pre_hook(configs, context)
Policies can:
  • Block request (raise PolicyViolationError)
  • Modify context/request
  • Perform authorization checks
3

Dataset search (if configured)

Search dataset with user query:
if response_type in [RAW, BOTH] and dataset_id:
    result = await dataset.search(ctx, query, params)
Parameters from request:
  • similarity_threshold
  • limit
  • include_metadata
4

Model chat (if configured)

Generate response with optional context injection:
if response_type in [SUMMARY, BOTH] and model_id:
    # Inject search results as context
    if references:
        messages.insert(0, system_context_message)
    
    result = await model.chat(ctx, messages, params)
Parameters from request:
  • temperature
  • max_tokens
  • stop_sequences
5

Post-hook policies

Execute all attached policies’ post_hook() methods
for policy_type, configs in policies_by_type.items():
    policy_instance.post_hook(configs, context)
Policies can:
  • Block response (raise PolicyViolationError)
  • Record accounting transaction
  • Log usage metrics
6

Return response

Return combined result to clientResponse shape depends on response_type
Location: backend/syft_space/components/endpoints/handlers.py:236

Query request schema

class QueryEndpointRequest:
    messages: str | list[ChatMessageRequest]  # User input
    similarity_threshold: float = 0.5         # Dataset search threshold
    limit: int = 5                            # Max search results
    include_metadata: bool = True             # Include doc metadata
    max_tokens: int = 100                     # Model max tokens
    temperature: float = 0.7                  # Model temperature
    stop_sequences: list[str] = ["\n"]        # Model stop tokens
    stream: bool = False                      # Streaming mode
    presence_penalty: float = 0.0             # Model penalty
    frequency_penalty: float = 0.0            # Model penalty
    extras: dict = {}                         # Additional options
    transaction_token: str | None = None      # Accounting token
Location: backend/syft_space/components/endpoints/schemas.py:212
The messages field accepts either a simple string (converted to [{"role": "user", "content": "..."}]) or a full conversation array.

Authenticated requests

All endpoint queries require authentication:
class AuthenticatedQueryRequest(QueryEndpointRequest):
    sender_email: EmailStr  # Extracted from SyftHub token
The sender_email is:
  • Verified from the authorization token (not user-provided)
  • Injected into PolicyContext for all policy hooks
  • Used for audit logging and usage tracking
Location: backend/syft_space/components/endpoints/schemas.py:273

Slug validation

Endpoint slugs must follow strict rules:
@field_validator("slug")
def validate_slug(v: str) -> str:
    v = v.lower()
    
    # Length: 3-64 characters
    if len(v) < 3 or len(v) > 64:
        raise ValueError("Slug must be 3-64 characters")
    
    # Pattern: lowercase letters, numbers, hyphens
    # No leading/trailing/consecutive hyphens
    if not re.match(r"^[a-z0-9]+(-[a-z0-9]+)*$", v):
        raise ValueError("Invalid slug format")
    
    return v
Location: backend/syft_space/components/endpoints/schemas.py:29 Valid: my-endpoint, legal-qa-v2, docs123 Invalid: My-Endpoint (uppercase), -docs (leading hyphen), my--endpoint (consecutive hyphens)

Marketplace publishing

Endpoints can be published to SyftHub marketplaces:
async def publish_endpoint(
    slug: str,
    marketplace_ids: list[UUID] | None,
    publish_to_all_marketplaces: bool,
    tenant: Tenant
) -> PublishEndpointResponse:
    """
    1. Validates marketplace exists and is active
    2. Authenticates to marketplace with credentials
    3. Publishes endpoint metadata via SyftHub API
    4. Records publication in endpoint.published_to
    """
Location: backend/syft_space/components/endpoints/handlers.py:542

Publish payload

Published endpoints include:
{
    "name": endpoint.name,
    "description": endpoint.summary,
    "type": endpoint_type,  # "model_data_source", "model", or "data_source"
    "slug": endpoint.slug,
    "readme": endpoint.description,  # Markdown documentation
    "policies": [...]  # Attached policy configurations
    "connect": [{
        "type": "https",
        "config": {"path": f"/api/v1/endpoints/{slug}/query"}
    }]
}
Location: backend/syft_space/components/endpoints/handlers.py:911

Sync endpoints

Batch update all published endpoints:
async def sync_endpoints_to_marketplaces(
    tenant: Tenant
) -> dict[str, list[str]]:
    """
    Groups all published endpoints by marketplace
    Calls sync_endpoints API for each marketplace
    Returns synced endpoint slugs per marketplace
    """
Location: backend/syft_space/components/endpoints/handlers.py:963

Endpoint operations

Create endpoint

async def create_endpoint(
    request: CreateEndpointRequest,
    tenant: Tenant
) -> EndpointCreateResponse:
    """
    1. Validates at least one of dataset_id or model_id
    2. Checks slug uniqueness
    3. Verifies dataset and model exist (if provided)
    4. Creates endpoint entity
    """
Location: backend/syft_space/components/endpoints/handlers.py:92

Update endpoint

Partial updates (name, summary, description):
async def update_endpoint(
    slug: str,
    request: UpdateEndpointRequest,
    tenant: Tenant
) -> EndpointDetailResponse:
    """Updates metadata fields only."""
You cannot change dataset_id, model_id, or response_type after creation. Delete and recreate the endpoint instead.
Location: backend/syft_space/components/endpoints/handlers.py:189

Delete endpoint

async def delete_endpoint(slug: str, tenant: Tenant) -> dict:
    """
    Deletes endpoint and all attached policies.
    Does NOT delete the linked dataset or model.
    """
Location: backend/syft_space/components/endpoints/handlers.py:217

Relationships

  • Tenant: Each endpoint belongs to one tenant
  • Dataset: Endpoint can link to one dataset (optional)
  • Model: Endpoint can link to one model (optional)
  • Policies: Multiple policies can be attached to an endpoint

Example workflows

1

Create dataset

POST /api/v1/datasets
{
  "name": "legal-docs",
  "dtype": "weaviate",
  "configuration": {...}
}
2

Create model

POST /api/v1/models
{
  "name": "gpt-4",
  "dtype": "openai",
  "configuration": {"api_key": "..."}
}
3

Create endpoint

POST /api/v1/endpoints
{
  "slug": "legal-qa",
  "dataset_id": "<dataset-uuid>",
  "model_id": "<model-uuid>",
  "response_type": "both",
  "published": true
}
4

Query endpoint

POST /api/v1/endpoints/legal-qa/query
{
  "messages": "What are the copyright terms?",
  "limit": 5,
  "temperature": 0.7
}
Returns search results + AI-generated answer

Next steps

Policies

Protect endpoints with rate limiting and access controls

Datasets

Learn about dataset types and data ingestion

Build docs developers (and LLMs) love