Saga API Reference
Complete reference documentation for all Saga HTTP API endpoints. Saga provides a RESTful API for service registration, discovery, and management.
All endpoints are prefixed with /api/v1. The default base URL is:
http://localhost:8030/api/v1
Authentication
Saga API currently does not require authentication. This is suitable for development and internal networks, but authentication will be required in future versions for production deployments.
Endpoints Overview
| Method | Endpoint | Description |
|---|---|---|
GET | /health | Service health check |
POST | /services/register | Register a new service |
GET | /services | List all services |
GET | /services/{name} | Get service details |
DELETE | /services/{name} | Unregister a service |
POST | /services/{name}/heartbeat | Refresh service TTL |
GET | /updates/history/{service_name} | Get update history for a service |
GET | /updates/history | Get all update history |
GET | /updates/statistics | Get update statistics |
GET | /updates/history/{service_name}/export/json | Export update history as JSON |
GET | /updates/history/{service_name}/export/csv | Export update history as CSV |
POST | /webhooks/update | Receive update notification |
POST | /webhooks/check-updates | Trigger update check |
POST | /webhooks/health | Receive health status |
POST | /webhooks/lifecycle | Service lifecycle events |
POST | /webhooks/deploy | Trigger service deployment |
POST | /webhooks/rollback | Trigger service rollback |
POST | /webhooks/notify | Notification webhook |
POST | /webhooks/config | Configure webhook settings |
GET | /webhooks/config | Get webhook configuration |
Health Check
Check the health status of the Saga service, including Redis connectivity and cache statistics.
Endpoint: GET /api/v1/health
Response:
{
"status": "healthy",
"service": "saga",
"version": "0.8.1",
"redis": "connected",
"cache": {
"size": 1,
"hits": 42,
"misses": 8,
"hit_ratio": 0.84,
"last_refresh": "2025-12-22T14:29:53.944455Z"
}
}
Status Codes:
200 OK- Service is healthy and operational503 Service Unavailable- Service is unhealthy (typically Redis disconnected)
Example Request:
- cURL
- HTTPie
- JavaScript
curl http://localhost:8030/api/v1/health
http GET http://localhost:8030/api/v1/health
const response = await fetch('http://localhost:8030/api/v1/health');
const health = await response.json();
console.log(health);
The cache object provides insights into Saga's performance:
- size: Number of services cached in memory
- hits: Number of cache hits (fast lookups)
- misses: Number of cache misses (Redis queries)
- hit_ratio: Cache efficiency (hits / (hits + misses))
- last_refresh: When the cache was last refreshed from Redis
A high hit ratio (>0.8) indicates good cache performance.
Register Service
Register a new service with Saga. Services must register themselves to be discoverable by other services.
Endpoint: POST /api/v1/services/register
Request Body:
{
"service_name": "authentication",
"service_url": "http://localhost:8001",
"capabilities": ["rest", "graphql", "grpc"]
}
Request Fields:
| Field | Type | Required | Description |
|---|---|---|---|
service_name | string | ✅ Yes | Unique identifier for the service (no spaces or colons) |
service_url | string | ✅ Yes | Base URL where the service can be reached |
capabilities | string[] | ❌ No | Array of service capabilities (defaults to empty) |
Valid Capabilities:
rest- REST API supportgraphql- GraphQL API supportgrpc- gRPC API supportmcp- Model Context Protocol support
Response:
{
"service_name": "authentication",
"service_url": "http://localhost:8001",
"service_id": "a674dbe7-5147-441b-ae56-f1c05f61cdbd",
"registered_at": "2025-12-22T14:30:38.531328+00:00",
"capabilities": ["rest", "graphql"],
"ttl": 60
}
Status Codes:
200 OK- Service registered successfully400 Bad Request- Invalid request (missing fields, invalid service name, etc.)503 Service Unavailable- Redis is not available
Example Requests:
- cURL
- HTTPie
- JavaScript
curl -X POST http://localhost:8030/api/v1/services/register \
-H "Content-Type: application/json" \
-d '{
"service_name": "authentication",
"service_url": "http://localhost:8001",
"capabilities": ["rest", "graphql"]
}'
http POST http://localhost:8030/api/v1/services/register \
service_name=authentication \
service_url=http://localhost:8001 \
capabilities:='["rest","graphql"]'
const response = await fetch('http://localhost:8030/api/v1/services/register', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
service_name: 'authentication',
service_url: 'http://localhost:8001',
capabilities: ['rest', 'graphql']
})
});
const result = await response.json();
console.log('Registered:', result.service_id);
Service names must:
- Not be empty
- Not contain
:(colon) characters - Not contain spaces
- Use lowercase with hyphens recommended:
my-service
Invalid names:
my service(contains space)my:service(contains colon)- `` (empty)
Valid names:
authenticationpayment-serviceapi-gateway
- Register on startup: Register your service when it starts
- Include all capabilities: Declare all protocols your service supports
- Use consistent naming: Follow naming conventions across your services
- Handle registration failures: Implement retry logic for transient failures
List All Services
Retrieve a list of all registered services with their metadata.
Endpoint: GET /api/v1/services
Response:
{
"services": [
{
"service_name": "authentication",
"service_url": "http://localhost:8001",
"service_id": "a674dbe7-5147-441b-ae56-f1c05f61cdbd",
"registered_at": "2025-12-22T14:30:38.531328+00:00",
"last_heartbeat": "2025-12-22T14:30:38.531330+00:00",
"capabilities": ["rest", "graphql"]
},
{
"service_name": "payment",
"service_url": "http://localhost:8002",
"service_id": "b785e8f8-6258-552c-bf67-g2d16g72dece",
"registered_at": "2025-12-22T14:31:15.123456+00:00",
"last_heartbeat": "2025-12-22T14:31:45.654321+00:00",
"capabilities": ["rest"]
}
],
"total": 2
}
Status Codes:
200 OK- Success
Example Requests:
- cURL
- With jq (Pretty Print)
- JavaScript
curl http://localhost:8030/api/v1/services
curl http://localhost:8030/api/v1/services | jq .
const response = await fetch('http://localhost:8030/api/v1/services');
const data = await response.json();
console.log(`Found ${data.total} services:`);
data.services.forEach(service => {
console.log(`- ${service.service_name}: ${service.service_url}`);
});
If no services are registered, the response will be:
{
"services": [],
"total": 0
}
Get Service Details
Retrieve detailed information about a specific service by name.
Endpoint: GET /api/v1/services/{service_name}
Path Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
service_name | string | ✅ Yes | Name of the service to retrieve |
Response:
{
"service_name": "authentication",
"service_url": "http://localhost:8001",
"service_id": "a674dbe7-5147-441b-ae56-f1c05f61cdbd",
"registered_at": "2025-12-22T14:30:38.531328+00:00",
"last_heartbeat": "2025-12-22T14:30:38.531330+00:00",
"capabilities": ["rest", "graphql"]
}
Status Codes:
200 OK- Service found404 Not Found- Service not found in registry503 Service Unavailable- Redis is not available
Example Requests:
- cURL
- JavaScript
curl http://localhost:8030/api/v1/services/authentication
async function discoverService(serviceName) {
const response = await fetch(
`http://localhost:8030/api/v1/services/${serviceName}`
);
if (response.status === 404) {
throw new Error(`Service '${serviceName}' not found`);
}
return await response.json();
}
// Usage
const authService = await discoverService('authentication');
console.log(`Auth service URL: ${authService.service_url}`);
Services expire after their TTL (default 60 seconds) if no heartbeat is received. Always check the last_heartbeat timestamp to ensure the service is still active.
Unregister Service
Remove a service from the registry. This is typically called when a service shuts down gracefully.
Endpoint: DELETE /api/v1/services/{service_name}
Path Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
service_name | string | ✅ Yes | Name of the service to unregister |
Response:
{
"message": "Service 'authentication' unregistered successfully",
"service_name": "authentication"
}
Status Codes:
200 OK- Service unregistered successfully400 Bad Request- Invalid service name or Redis error503 Service Unavailable- Redis is not available
Example Requests:
- cURL
- JavaScript
curl -X DELETE http://localhost:8030/api/v1/services/authentication
async function unregisterService(serviceName) {
const response = await fetch(
`http://localhost:8030/api/v1/services/${serviceName}`,
{ method: 'DELETE' }
);
if (!response.ok) {
throw new Error(`Failed to unregister: ${response.statusText}`);
}
return await response.json();
}
// Usage
await unregisterService('authentication');
console.log('Service unregistered');
Always unregister your service during graceful shutdown to ensure clean removal from the registry:
// Example in Rust
ctrlc::set_handler(move || {
saga_client.unregister_service("my-service").await?;
std::process::exit(0);
})?;
Refresh Service Registration (Heartbeat)
Refresh the TTL of a service registration to keep it alive. This should be called periodically (every 30 seconds recommended) to prevent expiration.
Endpoint: POST /api/v1/services/{service_name}/heartbeat
Path Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
service_name | string | ✅ Yes | Name of the service to refresh |
Response:
{
"service_name": "authentication",
"message": "Service registration refreshed",
"ttl": 60
}
Status Codes:
200 OK- Registration refreshed successfully400 Bad Request- Service not found or Redis error503 Service Unavailable- Redis is not available
Example Requests:
- cURL
- JavaScript
curl -X POST http://localhost:8030/api/v1/services/authentication/heartbeat
async function sendHeartbeat(serviceName) {
const response = await fetch(
`http://localhost:8030/api/v1/services/${serviceName}/heartbeat`,
{ method: 'POST' }
);
if (!response.ok) {
throw new Error(`Heartbeat failed: ${response.statusText}`);
}
return await response.json();
}
// Periodic heartbeat
setInterval(async () => {
try {
await sendHeartbeat('authentication');
console.log('Heartbeat sent');
} catch (error) {
console.error('Heartbeat failed:', error);
}
}, 30000); // Every 30 seconds
Send heartbeats more frequently than the TTL to account for network delays:
- TTL: 60 seconds
- Recommended heartbeat interval: 30 seconds
- Maximum safe interval: 45 seconds (leaves 15s buffer)
If heartbeats are missed, the service will expire and need to re-register.
Error Responses
All error responses follow a consistent format:
{
"error": "Error type",
"message": "Detailed error message"
}
Common Error Types:
| Error Type | Status Code | Description |
|---|---|---|
Service not found | 404 | The requested service does not exist |
Redis is not available | 503 | Redis connection is unavailable |
Invalid service name | 400 | Service name validation failed |
Invalid service URL | 400 | Service URL validation failed |
Example Error Response:
{
"error": "Service not found",
"message": "Service 'unknown-service' not found in registry"
}
Error Handling Example:
- JavaScript
- Rust
async function discoverService(serviceName) {
try {
const response = await fetch(
`http://localhost:8030/api/v1/services/${serviceName}`
);
if (!response.ok) {
const error = await response.json();
if (response.status === 404) {
console.warn(`Service '${serviceName}' not found`);
return null; // Service doesn't exist
}
if (response.status === 503) {
throw new Error('Saga service unavailable - using fallback');
}
throw new Error(error.message);
}
return await response.json();
} catch (error) {
console.error('Service discovery failed:', error);
// Fallback to static configuration
return getFallbackService(serviceName);
}
}
async fn discover_service(
saga_client: &SagaServiceDiscovery,
service_name: &str,
) -> Result<ServiceInfo, Error> {
match saga_client.discover_service(service_name).await {
Ok(info) => Ok(info),
Err(e) => {
if e.to_string().contains("not found") {
// Service doesn't exist - use fallback
get_fallback_service(service_name)
} else {
// Other error - propagate
Err(e)
}
}
}
}
Update Management
Saga provides comprehensive update management capabilities for services, including update history tracking, statistics, and export functionality.
Get Service Update History
Retrieve update history for a specific service.
Endpoint: GET /api/v1/updates/history/{service_name}
Path Parameters:
service_name(string, required) - Name of the service
Query Parameters:
limit(integer, optional) - Maximum number of history entries to return
Response:
{
"service_name": "payment-service",
"history": [
{
"service_name": "payment-service",
"old_version": "1.2.3",
"new_version": "1.3.0",
"timestamp": "2024-01-15T10:30:00Z",
"status": "success",
"duration_seconds": 45,
"artifact_url": "https://github.com/example/payment/releases/v1.3.0/payment-v1.3.0.tar.gz",
"checksum": "sha256:abc123...",
"artifact_path": "/tmp/saga_artifacts/payment-service/v1.3.0",
"backup_path": "/tmp/saga_backups/payment-service/v1.2.3"
}
],
"total": 1
}
Get All Update History
Retrieve update history for all services.
Endpoint: GET /api/v1/updates/history
Query Parameters:
limit(integer, optional) - Maximum number of history entries to return
Response:
{
"history": [
{
"service_name": "payment-service",
"old_version": "1.2.3",
"new_version": "1.3.0",
"timestamp": "2024-01-15T10:30:00Z",
"status": "success",
"duration_seconds": 45
},
{
"service_name": "gateway",
"old_version": "2.0.0",
"new_version": "2.1.0",
"timestamp": "2024-01-14T15:20:00Z",
"status": "success",
"duration_seconds": 30
}
],
"total": 2
}
Get Update Statistics
Get aggregated statistics about service updates.
Endpoint: GET /api/v1/updates/statistics
Response:
{
"total_updates": 150,
"successful_updates": 142,
"failed_updates": 5,
"rolled_back_updates": 3,
"success_rate": 94.67,
"average_duration_seconds": 38.5,
"services_updated": [
{
"service_name": "payment-service",
"update_count": 45
},
{
"service_name": "gateway",
"update_count": 32
}
]
}
Export Update History
Export update history in various formats.
Endpoint: GET /api/v1/updates/history/{service_name}/export/{format}
Path Parameters:
service_name(string, required) - Name of the serviceformat(string, required) - Export format:jsonorcsv
Query Parameters:
limit(integer, optional) - Maximum number of entries to export
Response:
For JSON format, returns the same structure as the history endpoint.
For CSV format, returns a CSV file with columns:
- Service Name
- Old Version
- New Version
- Timestamp
- Status
- Duration (seconds)
- Artifact URL
- Checksum
Webhooks
Saga provides webhook endpoints for CI/CD integration and external system notifications.
Update Notification Webhook
Receive update notifications from CI/CD pipelines or external systems.
Endpoint: POST /api/v1/webhooks/update
Headers:
X-Webhook-Signature(optional) - HMAC-SHA256 signature for webhook validation
Request Body:
{
"service_name": "payment-service",
"version": "1.3.0",
"artifact_url": "https://github.com/example/payment/releases/v1.3.0/payment-v1.3.0.tar.gz",
"artifact_type": "binary",
"checksum": "sha256:abc123...",
"webhook_secret": "optional-secret-for-signature-validation"
}
Response:
{
"status": "accepted",
"message": "Update notification received for payment-service",
"service_name": "payment-service",
"version": "1.3.0"
}
Check Updates Webhook
Trigger a manual update check for a service.
Endpoint: POST /api/v1/webhooks/check-updates
Request Body:
{
"service_name": "payment-service"
}
Response:
{
"status": "checked",
"service_name": "payment-service",
"current_version": "1.2.3",
"latest_version": "1.3.0",
"update_available": true
}
Health Status Webhook
Receive health status updates from services.
Endpoint: POST /api/v1/webhooks/health
Request Body:
{
"service_name": "payment-service",
"status": "healthy",
"timestamp": "2024-01-15T10:30:00Z",
"details": {
"uptime": 3600,
"version": "1.3.0"
}
}
Response:
{
"status": "received",
"message": "Health status updated for payment-service"
}
Lifecycle Events Webhook
Receive service lifecycle events (start, stop, restart, etc.).
Endpoint: POST /api/v1/webhooks/lifecycle
Request Body:
{
"service_name": "payment-service",
"event": "started",
"timestamp": "2024-01-15T10:30:00Z",
"details": {
"version": "1.3.0",
"pid": 12345
}
}
Response:
{
"status": "received",
"message": "Lifecycle event processed for payment-service"
}
Deployment Webhook
Trigger service deployment with specified version and strategy.
Endpoint: POST /api/v1/webhooks/deploy
Request Body:
{
"service_name": "payment-service",
"version": "1.3.0",
"artifact_url": "https://github.com/example/payment/releases/v1.3.0/payment-v1.3.0.tar.gz",
"artifact_type": "binary",
"checksum": "sha256:abc123...",
"strategy": "rolling",
"webhook_secret": "optional-secret"
}
Deployment Strategies:
rolling- Rolling deployment (default)blue-green- Blue-green deploymentcanary- Canary deployment
Response:
{
"status": "accepted",
"job_id": "deploy-payment-service-1.3.0-1705312200",
"message": "Deployment process started for service payment-service",
"service_name": "payment-service",
"version": "1.3.0"
}
Rollback Webhook
Trigger service rollback to a previous version.
Endpoint: POST /api/v1/webhooks/rollback
Request Body:
{
"service_name": "payment-service",
"version": "1.2.3"
}
Response:
{
"status": "accepted",
"job_id": "rollback-payment-service-1.2.3-1705312200",
"message": "Rollback process started for service payment-service",
"service_name": "payment-service",
"version": "1.2.3"
}
Notification Webhook
Send notifications to external systems.
Endpoint: POST /api/v1/webhooks/notify
Request Body:
{
"service_name": "payment-service",
"channel": "slack",
"message": "Service payment-service updated to version 1.3.0",
"severity": "info"
}
Response:
{
"status": "sent",
"message": "Notification sent via slack"
}
Configure Webhook Settings
Configure webhook endpoints and settings.
Endpoint: POST /api/v1/webhooks/config
Request Body:
{
"service_name": "payment-service",
"endpoints": {
"slack": "https://hooks.slack.com/services/...",
"discord": "https://discord.com/api/webhooks/..."
},
"secret": "webhook-secret-key"
}
Response:
{
"status": "configured",
"message": "Webhook configuration updated for payment-service"
}
Get Webhook Configuration
Retrieve webhook configuration for a service or global settings.
Endpoint: GET /api/v1/webhooks/config
Query Parameters:
service_name(string, optional) - Service name (if not provided, returns global config)
Response:
{
"service_name": "payment-service",
"endpoints": {
"slack": "https://hooks.slack.com/services/...",
"discord": "https://discord.com/api/webhooks/..."
},
"configured_at": "2024-01-15T10:30:00Z"
}
Rate Limiting
Saga does not currently implement rate limiting. This may be added in future versions for production deployments.
API Versioning
Saga uses URL-based versioning. The current API version is v1. Future breaking changes will be introduced in v2, v3, etc.
Versioning Strategy:
- v1: Current stable API
- v2+: Future versions with breaking changes
Next Steps
- Explore Integration Examples for code samples
- Review Configuration for environment setup
- Check Troubleshooting for common issues