Notice: Syft Router is in ALPHA. A major update will arrive mid-November — stay connected for updates.

Router Endpoints

Complete API reference for all router endpoints accessible through the SyftBox relay system. Learn how to interact with chat, search, and health endpoints securely without opening firewalls.

How Router APIs Work

Each router runs on its own port (http://localhost:[ROUTER_PORT]/), but this is not a regular FastAPI server accessible to the public. Instead, Syft runs relays which are responsible for forwarding messages between users and routers.

As communication is encrypted, these relays are blind to the messages exchanged, but it allows us to easily address services over the network in a unified way, just by knowing the email and the name of the router we want to query.

🔐 Secure Communication

All router endpoints are accessed through the SyftBox relay system, which routes requests based on the x-syft-url parameter. This allows secure communication without opening firewalls.

Request Structure and Parameters

All SyftBox relay requests follow a consistent structure with specific query parameters and request patterns. Understanding these parameters is crucial for successful API interactions.

Common Request Parameters

Required Headers

  • Content-Type: application/json
  • x-syft-from: Sender email identification
  • timeout: Request timeout (milliseconds)

Required Body Fields

  • x-syft-url: Target syft:// endpoint URL
  • x-syft-from: Sender email (can be in header or body)
  • suffix-sender: Boolean for sender information

Syft URL Format

The syft:// URL format is the core addressing mechanism for routers:

syft://[owner_email]/app_data/[router_name]/rpc/[endpoint]

Examples:
- syft://sender@openmined.org/app_data/mit-press-test/rpc/search
- syft://aggregator@openmined.org/app_data/claude-sonnet-3.5/rpc/chat
- syft://owner@example.com/app_data/my-router/rpc/health

Polling URL Parameters

When polling for results, the following query parameters are automatically included:

/api/v1/send/poll?[parameters]

Parameter Details:
- x-syft-request-id: Unique identifier for the specific request
- x-syft-url: URL-encoded syft:// address (RFC 3986)
- x-syft-from: Sender email address
- x-syft-raw: Response format (false = JSON wrapped, true = raw)
📋 Parameter Requirements
  • x-syft-url must be properly URL-encoded when used in query parameters
  • suffix-sender controls whether sender information is included in response metadata
  • user_email is service-specific and may be required for certain routers
  • transaction_token is used for authenticated requests and accounting

FastSyftBox JavaScript Client

For JavaScript applications, the FastSyftBox library provides a simplified interface that abstracts away the polling mechanism and request formatting. This makes it much easier to interact with SyftBox routers from web applications.

Installation

npm install fastsyftbox

Or include directly via CDN:

<script src="https://cdn.jsdelivr.net/npm/fastsyftbox@latest/dist/fastsyftbox.min.js"></script>

Basic Usage

The syftFetch function works similar to the standard fetch API but handles SyftBox routing automatically:

Standard Fetch

const url = "http://somewebsite.com/api"
const request = await fetch(url, {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json'
    },
    body: JSON.stringify({message: "Hello"})
});

SyftBox Fetch

const syftUrl = "syft://madhava@openmined.org/app_data/fastsyftbox/rpc/hello"
const request = await syftFetch(syftUrl, {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json'
    },
    body: JSON.stringify({message: "Hello"})
});

What FastSyftBox Does Under the Hood

Configuration Options

FastSyftBox can be configured for different environments:

import { configureSyftBox, syftFetch } from 'fastsyftbox';

// Configure for custom SyftBox relay
configureSyftBox({
    relayUrl: 'https://custom-relay.example.com',
    defaultTimeout: 30000,
    pollingInterval: 2000,
    maxRetries: 5
});

// Use configured client
const response = await syftFetch("syft://owner@example.com/app_data/router/rpc/chat", {
    method: 'POST',
    body: JSON.stringify({message: "Hello"})
});
📚 Learn More

For complete documentation, examples, and source code, visit the FastSyftBox GitHub repository.

Core Service Endpoints

Chat Endpoint

Send chat messages to a router's chat service through the SyftBox relay.

POST https://syftbox.net/api/v1/send/

Request Headers

  • x-syft-from: Your email address (sender identification)
  • x-syft-url: Target router endpoint in format syft://owner_email/app_data/router_name/rpc/chat
  • timeout: Request timeout in milliseconds (default: 5000)

Request Body

{
  "message": "string (required) - The user's message",
  "conversation_id": "string (optional) - Conversation identifier",
  "model": "string (optional) - Specific model to use",
  "temperature": "number (optional) - Response randomness (0.0-1.0)",
  "max_tokens": "number (optional) - Maximum response length",
  "suffix-sender": "boolean (optional) - Include sender in response",
  "x-syft-url": "string (required) - Target router syft:// URL"
}

Example Request

curl -X POST https://syftbox.net/api/v1/send/ \
  -H "Content-Type: application/json" \
  -H "x-syft-from: user@example.com" \
  -H "timeout: 5000" \
  -d '{
    "message": "What is machine learning?",
    "conversation_id": "conv_123",
    "suffix-sender": "true",
    "x-syft-url": "syft://router_owner@example.com/app_data/my_router/rpc/chat"
  }'

Response (HTTP 202 Accepted)

The SyftBox relay returns a polling response for async processing:

{
  "request_id": "req_abc123",
  "status": "accepted",
  "data": {
    "poll_url": "/api/v1/requests/req_abc123/status",
    "message": "Request queued for processing"
  }
}

Final Response (after polling)

{
  "status": "success",
  "status_code": 200,
  "headers": {
    "content-type": "application/json"
  },
  "body": {
    "response": "Machine learning is a subset of artificial intelligence...",
    "conversation_id": "conv_123",
    "model_used": "gpt-3.5-turbo",
    "tokens_used": 150,
    "processing_time": 1.2
  }
}

Search Endpoint

Query a router's document search service through the SyftBox relay.

POST https://syftbox.net/api/v1/send/

Request Body

{
  "query": "string (required) - Search query",
  "limit": "number (optional) - Max results to return (default: 5)",
  "filters": "object (optional) - Metadata filters",
  "search_type": "string (optional) - 'vector', 'keyword', or 'hybrid'",
  "suffix-sender": "boolean (optional) - Include sender in response",
  "x-syft-url": "string (required) - Target router syft:// URL"
}

Example Request

curl -X POST https://syftbox.net/api/v1/send/ \
  -H "Content-Type: application/json" \
  -H "x-syft-from: user@example.com" \
  -H "timeout: 5000" \
  -d '{
    "query": "machine learning concepts",
    "limit": 5,
    "filters": {"category": "technical"},
    "suffix-sender": "true",
    "x-syft-url": "syft://router_owner@example.com/app_data/my_router/rpc/search"
  }'

Response (after polling)

{
  "status": "success",
  "status_code": 200,
  "headers": {
    "content-type": "application/json"
  },
  "body": {
    "query": "machine learning concepts",
    "results": [
      {
        "content": "Machine learning is a method of data analysis...",
        "score": 0.95,
        "metadata": {
          "source": "ml-guide.pdf",
          "page": 1,
          "category": "technical"
        },
        "id": "doc_123"
      }
    ],
    "total_results": 1,
    "processing_time": 0.3
  }
}

Health and Status Endpoints

Health Check

Check overall router health through the SyftBox relay system.

Example Request

curl -X POST https://syftbox.net/api/v1/send/ \
  -H "Content-Type: application/json" \
  -H "x-syft-from: user@example.com" \
  -H "timeout: 5000" \
  -d '{
    "suffix-sender": "true",
    "x-syft-url": "syft://router_owner@example.com/app_data/my_router/rpc/health"
  }'

Response (after polling)

{
  "status": "success",
  "status_code": 200,
  "headers": {
    "content-type": "application/json"
  },
  "body": {
    "status": "healthy",
    "services": {
      "chat": "running",
      "search": "running"
    },
    "uptime": "2h 45m",
    "version": "1.0.0",
    "timestamp": "2024-01-15T10:30:00Z"
  }
}

Service Status

Check specific service status through the relay.

Example Request

curl -X POST https://syftbox.net/api/v1/send/ \
  -H "Content-Type: application/json" \
  -H "x-syft-from: user@example.com" \
  -d '{
    "service": "chat",
    "suffix-sender": "true",
    "x-syft-url": "syft://router_owner@example.com/app_data/my_router/rpc/status"
  }'

Response (after polling)

{
  "status": "success",
  "status_code": 200,
  "headers": {
    "content-type": "application/json"
  },
  "body": {
    "service": "chat",
    "status": "running",
    "last_request": "2024-01-15T10:30:00Z",
    "response_time_avg": "150ms",
    "error_rate": "0.1%",
    "requests_today": 142
  }
}

Router Information Endpoints

Router Metadata

Get router information and capabilities through the SyftBox relay.

Example Request

curl -X POST https://syftbox.net/api/v1/send/ \
  -H "Content-Type: application/json" \
  -H "x-syft-from: user@example.com" \
  -d '{
    "suffix-sender": "true",
    "x-syft-url": "syft://router_owner@example.com/app_data/my_router/rpc/info"
  }'

Response (after polling)

{
  "status": "success",
  "status_code": 200,
  "headers": {
    "content-type": "application/json"
  },
  "body": {
    "name": "my-ai-router",
    "version": "1.0.0",
    "description": "AI-powered chat and search router",
    "author": "router_owner@example.com",
    "services": {
      "chat": {
        "enabled": true,
        "models": ["gpt-3.5-turbo", "gpt-4"],
        "pricing": {
          "per_request": 0.01,
          "per_token": 0.0001
        }
      },
      "search": {
        "enabled": true,
        "collection_size": 10000,
        "pricing": {
          "per_request": 0.005
        }
      }
    },
    "published": true,
    "tags": ["chat", "search", "ai"]
  }
}

Error Responses

SyftBox relay responses follow a consistent format. Errors can occur at the relay level or from the target router.

Common Error Types

Relay Errors (HTTP 4xx/5xx)

{
  "error": "invalid_request",
  "message": "Missing required field: x-syft-url",
  "code": 400,
  "timestamp": "2024-01-15T10:30:00Z"
}

Authentication Errors (HTTP 401)

{
  "error": "unauthorized",
  "message": "Invalid or expired SyftBox token",
  "code": 401,
  "timestamp": "2024-01-15T10:30:00Z"
}

Router Not Found (HTTP 404)

{
  "status": "ERROR",
  "message": "No request found or router unavailable",
  "request_id": "req_abc123"
}

Polling Timeout (HTTP 500)

{
  "error": "No response exists. Polling timed out",
  "message": "Router did not respond within timeout period",
  "code": 500
}

Router Errors (Wrapped in Success Response)

When the router itself returns an error, it's wrapped in a successful polling response:

{
  "status": "success",
  "status_code": 500,
  "headers": {
    "content-type": "application/json"
  },
  "body": {
    "error": "service_unavailable",
    "message": "Chat service is currently offline",
    "service": "chat",
    "timestamp": "2024-01-15T10:30:00Z"
  }
}

Polling Mechanism

The SyftBox relay uses an asynchronous request-response pattern with polling to handle requests that may take time to process. This mechanism ensures reliable message delivery while accommodating variable processing times across different routers and services.

How Polling Works

  1. Initial Request: Send your request to https://syftbox.net/api/v1/send/
    • Returns HTTP 202 (Accepted) immediately
    • Includes request_id for tracking
    • Provides poll_url for checking status
  2. Polling Phase: Continuously check the poll_url
    • Use the full polling URL: https://syftbox.net{poll_url}
    • Poll every 1-2 seconds until response is ready
    • Handle timeout scenarios gracefully
  3. Final Response: Receive the actual router response
    • Contains the processed result from the target router
    • Includes original request metadata and timing information

Polling URL Structure

The polling URL returned in the initial response contains all necessary parameters:

/api/v1/send/poll?x-syft-request-id={request_id}&x-syft-url={encoded_syft_url}&x-syft-from={sender_email}&x-syft-raw=false

Query Parameters

  • x-syft-request-id: Unique request identifier
  • x-syft-url: URL-encoded target syft:// address
  • x-syft-from: Sender email address
  • x-syft-raw: Response format (false for JSON)

Polling States

  • Pending: Request is being processed
  • Success: Response ready
  • Error: Request failed
  • Timeout: Processing time exceeded

Complete Search + Chat Flow Example

This example demonstrates a typical workflow combining search and chat services, showing the complete polling process for both requests:

Step 1: Search Request

# Initial search request
curl -X POST https://syftbox.net/api/v1/send/ \
  -H "Content-Type: application/json" \
  -d '{
    "query": "tell me about the recent satellite crash",
    "user_email": "sarah.johnson@spacetech.org",
    "suffix-sender": true,
    "x-syft-url": "syft://data.provider@aerospace.net/app_data/space-news-index/rpc/search",
    "x-syft-from": "guest@syftbox.net"
  }'

Initial Response (HTTP 202):

{
  "request_id": "a7f2d8e5-9b41-4c67-8d93-2e5f7a1b9c84",
  "data": {
    "poll_url": "/api/v1/send/poll?x-syft-request-id=a7f2d8e5-9b41-4c67-8d93-2e5f7a1b9c84&x-syft-url=syft%3A//data.provider@aerospace.net/app_data/space-news-index/rpc/search&x-syft-from=guest@syftbox.net&x-syft-raw=false"
  },
  "message": "Request has been accepted. Please check back later."
}

Polling for Search Results:

GET https://syftbox.net/api/v1/send/poll?x-syft-request-id=a7f2d8e5-9b41-4c67-8d93-2e5f7a1b9c84&x-syft-url=syft%3A//data.provider@aerospace.net/app_data/space-news-index/rpc/search&x-syft-from=guest@syftbox.net&x-syft-raw=false

Final Search Response:

{
  "request_id": "a7f2d8e5-9b41-4c67-8d93-2e5f7a1b9c84",
  "data": {
    "message": {
      "body": {
        "cost": 0,
        "id": "3e9c8d72-5f41-4a8b-9d67-1c2e8f4a7b93",
        "providerInfo": {
          "provider": "vector_search"
        },
        "query": "tell me about the recent satellite crash",
        "results": [
          {
            "content": "BREAKING: European Space Agency confirms the loss of the EuroSat-7 communications satellite following an unexpected collision with space debris. The incident occurred at 14:32 UTC on October 14, 2025, at an altitude of 850 kilometers above the Pacific Ocean. Initial telemetry data suggests the satellite's main communications array was severely damaged, rendering it inoperable.\n\nESA Mission Control in Darmstadt is working with international partners to track the resulting debris field.",
            "embedding": null,
            "id": "0",
            "metadata": {
              "filename": "eurosat-7-collision-incident-report.md",
              "source": "European Space Agency",
              "date": "2025-10-14",
              "category": "incident_report"
            },
            "score": 0.8947263508300781
          },
          {
            "content": "**Source:** [https://spaceflightnow.com/2025/10/14/satellite-debris-collision-analysis/](https://spaceflightnow.com/2025/10/14/satellite-debris-collision-analysis/)\n\n## Technical Analysis\n\nPreliminary analysis indicates the EuroSat-7 satellite collided with a fragment from the 2019 Indian anti-satellite test. The debris piece, catalogued as object 44692, was approximately 15cm in diameter and traveling at a relative velocity of 8.2 km/s.\n\n## Impact Assessment\n\nThe collision generated an estimated 200-400 new trackable debris pieces larger than 10cm. The European Space Operations Centre has issued collision avoidance advisories for 12 operational satellites in similar orbital planes.",
            "embedding": null,
            "id": "1",
            "metadata": {
              "filename": "technical-collision-analysis-oct-2025.md",
              "source": "Spaceflight Now",
              "date": "2025-10-14",
              "category": "technical_analysis"
            },
            "score": 0.8234567123456789
          },
          {
            "content": "The loss of EuroSat-7 represents a significant disruption to telecommunications infrastructure across Central and Eastern Europe. The satellite provided critical backup communications for emergency services and rural internet connectivity. Alternative routing through EuroSat-5 and EuroSat-9 is being implemented, though some service degradation is expected for 4-6 weeks.\n\nInsurance companies estimate preliminary losses at €340 million, making this one of the costliest space incidents of 2025.",
            "embedding": null,
            "id": "2",
            "metadata": {
              "filename": "eurosat-7-service-impact-assessment.md",
              "source": "Satellite Industry Association",
              "date": "2025-10-15",
              "category": "economic_impact"
            },
            "score": 0.7891234567890123
          }
        ]
      },
      "created": "2025-10-16T09:15:22.341089Z",
      "expires": "2025-10-17T09:15:22.260641Z",
      "headers": {
        "content-length": "2847",
        "content-type": "application/json"
      },
      "id": "a7f2d8e5-9b41-4c67-8d93-2e5f7a1b9c84",
      "method": "",
      "sender": "data.provider@aerospace.net",
      "status_code": 200,
      "url": "syft://data.provider@aerospace.net/app_data/space-news-index/rpc/search"
    }
  }
}

Step 2: Chat Request Using Search Results

# Chat request with search context
curl -X POST https://syftbox.net/api/v1/send/ \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-3-haiku",
    "messages": [
      {
        "role": "system",
        "content": "You are a helpful AI assistant that can answer questions using both provided sources and your general knowledge.\n\nWhen sources are provided, use them as your primary information and supplement with your general knowledge when helpful. If you don'\''t know the answer from the sources, you can still use your general knowledge to provide a helpful response.\n\nWhen no sources are provided, rely on your general knowledge to answer the question comprehensively."
      },
      {
        "role": "system", 
        "content": "Here is relevant source context to help answer the user'\''s question:\n\n[eurosat-7-collision-incident-report.md]\nBREAKING: European Space Agency confirms the loss of the EuroSat-7 communications satellite following an unexpected collision with space debris. The incident occurred at 14:32 UTC on October 14, 2025, at an altitude of 850 kilometers above the Pacific Ocean. Initial telemetry data suggests the satellite'\''s main communications array was severely damaged, rendering it inoperable.\n\nESA Mission Control in Darmstadt is working with international partners to track the resulting debris field.\n\n[technical-collision-analysis-oct-2025.md]\n**Source:** [https://spaceflightnow.com/2025/10/14/satellite-debris-collision-analysis/](https://spaceflightnow.com/2025/10/14/satellite-debris-collision-analysis/)\n\n## Technical Analysis\n\nPreliminary analysis indicates the EuroSat-7 satellite collided with a fragment from the 2019 Indian anti-satellite test. The debris piece, catalogued as object 44692, was approximately 15cm in diameter and traveling at a relative velocity of 8.2 km/s.\n\n## Impact Assessment\n\nThe collision generated an estimated 200-400 new trackable debris pieces larger than 10cm.\n\n[eurosat-7-service-impact-assessment.md]\nThe loss of EuroSat-7 represents a significant disruption to telecommunications infrastructure across Central and Eastern Europe. The satellite provided critical backup communications for emergency services and rural internet connectivity. Insurance companies estimate preliminary losses at €340 million, making this one of the costliest space incidents of 2025."
      },
      {
        "role": "user",
        "content": "tell me about the recent satellite crash"
      }
    ],
    "user_email": "sarah.johnson@spacetech.org",
    "transaction_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImY4aGo2d20xazc1cWJscnYzZTdkODVhbiIsInNlbmRlckVtYWlsIjoic2FyYWguam9obnNvbkBzcGFjZXRlY2gub3JnIiwicmVjaXBpZW50RW1haWwiOiJhZ2dyZWdhdG9yQGFpLXJvdXRlci5jb20iLCJpYXQiOjE3Mjk2NTk3MjUsImV4cCI6MTcyOTc0NjEyNX0.9KjPnY8wLcQbWxBzVTYqS7m9VQgH5rlHZF2tI3oAZew",
    "suffix-sender": true,
    "x-syft-url": "syft://ai-router@spacetech.ai/app_data/claude-3-haiku/rpc/chat",
    "x-syft-from": "guest@syftbox.net"
  }'

Initial Chat Response (HTTP 202):

{
  "request_id": "b9c4f7e2-1a8d-4e56-9f73-3b2e8c6d4a91",
  "data": {
    "poll_url": "/api/v1/send/poll?x-syft-request-id=b9c4f7e2-1a8d-4e56-9f73-3b2e8c6d4a91&x-syft-url=syft://ai-router@spacetech.ai/app_data/claude-3-haiku/rpc/chat&x-syft-from=guest@syftbox.net&x-syft-raw=false"
  },
  "message": "Request has been accepted. Please check back later."
}

Polling Chat Request (Initial Attempts May Timeout):

# First few polling attempts might return:
{
  "error": "timeout",
  "message": "Polling timeout reached. The request may still be processing.",
  "request_id": "b9c4f7e2-1a8d-4e56-9f73-3b2e8c6d4a91"
}

Final Chat Response (After Successful Polling):

{
  "request_id": "b9c4f7e2-1a8d-4e56-9f73-3b2e8c6d4a91",
  "data": {
    "message": {
      "body": {
        "cost": 0.18,
        "finishReason": "stop",
        "id": "5f2a9c1e-8d47-4b6c-9e83-2a5f7c1d8e94",
        "logprobs": null,
        "message": {
          "content": "# EuroSat-7 Satellite Collision Analysis\n\nBased on the recent incident reports, here'\''s a comprehensive overview of the EuroSat-7 satellite crash:\n\n## Incident Overview\nOn October 14, 2025, at 14:32 UTC, the EuroSat-7 communications satellite was lost following a collision with space debris at 850 kilometers altitude above the Pacific Ocean. The European Space Agency confirmed the complete loss of the satellite after its main communications array was severely damaged.\n\n## Technical Details\n- **Collision Object**: A fragment from India'\''s 2019 anti-satellite test (catalogued as object 44692)\n- **Fragment Size**: Approximately 15cm in diameter\n- **Impact Velocity**: 8.2 km/s relative velocity\n- **Debris Generation**: 200-400 new trackable pieces larger than 10cm created\n\n## Impact Assessment\n**Service Disruption**: The loss significantly affects telecommunications across Central and Eastern Europe, particularly emergency services and rural internet connectivity.\n\n**Financial Impact**: Insurance companies estimate preliminary losses at €340 million, making this one of the costliest space incidents of 2025.\n\n**Orbital Safety**: The European Space Operations Centre has issued collision avoidance advisories for 12 operational satellites in similar orbital planes.\n\n## Recovery Efforts\nESA Mission Control in Darmstadt is coordinating with international partners to track the resulting debris field. Alternative routing through EuroSat-5 and EuroSat-9 is being implemented, though service degradation is expected for 4-6 weeks.\n\nThis incident highlights the growing concern of space debris and the Kessler Syndrome risk in increasingly congested orbital environments.",
          "name": null,
          "role": "assistant"
        },
        "model": "claude-3-haiku",
        "providerInfo": {
          "model": "claude-3-haiku",
          "provider": "anthropic"
        },
        "usage": {
          "completionTokens": 312,
          "promptTokens": 847,
          "totalTokens": 1159
        }
      },
      "created": "2025-10-16T09:23:18.492847Z",
      "expires": "2025-10-17T09:23:18.125643Z",
      "headers": {
        "content-length": "1847",
        "content-type": "application/json"
      },
      "id": "b9c4f7e2-1a8d-4e56-9f73-3b2e8c6d4a91",
      "method": "",
      "sender": "ai-router@spacetech.ai",
      "status_code": 200,
      "url": "syft://ai-router@spacetech.ai/app_data/claude-3-haiku/rpc/chat"
    }
  }
}

Advanced Features

Custom Endpoints

Routers can implement custom endpoints beyond chat and search. Access any custom endpoint using the SyftBox relay pattern:

# Custom endpoint example: document upload
curl -X POST https://syftbox.net/api/v1/send/ \
  -H "Content-Type: application/json" \
  -H "x-syft-from: user@example.com" \
  -d '{
    "document": "base64_encoded_content",
    "filename": "document.pdf",
    "metadata": {"category": "research"},
    "suffix-sender": "true",
    "x-syft-url": "syft://router_owner@example.com/app_data/my_router/rpc/upload"
  }'

Direct Router Access (Development Only)

While the SyftBox relay system is the primary access method, routers also run locally and can be accessed directly for development and testing:

# Direct chat request (local development only)
curl -X POST http://localhost:8001/chat \
  -H "Content-Type: application/json" \
  -d '{"message": "Hello locally!"}'

# Health check
curl http://localhost:8001/health

# API documentation
open http://localhost:8001/docs
⚠️ Development Only

Direct router access is only available for local development and testing. Production traffic cannot reach the router directly, so it must go through the SyftBox relay system.