REST API
The REST API provides simple HTTP access to EvidentSource functionality. It’s ideal for web applications, scripting, and environments where gRPC is not available.
Base URL
Section titled “Base URL”http://localhost:8080 # Developmenthttps://api.example.com # ProductionAuthentication
Section titled “Authentication”Currently supports:
- No auth (development mode)
- API keys (via
X-API-Keyheader) - Bearer tokens (planned)
# With API keycurl -H "X-API-Key: your-api-key" https://api.example.com/databasesContent Types
Section titled “Content Types”The API accepts and returns JSON by default:
Content-Type: application/jsonAccept: application/jsonFor State Views, additional content types may be returned based on the view definition.
Database Operations
Section titled “Database Operations”List Databases
Section titled “List Databases”GET /databasesResponse:
{ "databases": [ { "name": "my-events", "created_at": "2024-01-15T10:30:00Z", "latest_revision": 12345, "event_count": 12345 } ]}Create Database
Section titled “Create Database”POST /databasesRequest:
{ "name": "my-events"}Response:
{ "database": { "name": "my-events", "created_at": "2024-01-15T10:30:00Z", "latest_revision": 0, "event_count": 0 }}Status Codes:
201 Created: Database created successfully409 Conflict: Database already exists400 Bad Request: Invalid database name
Get Database Info
Section titled “Get Database Info”GET /databases/{database_name}Response:
{ "name": "my-events", "created_at": "2024-01-15T10:30:00Z", "latest_revision": 12345, "event_count": 12345, "state_views": ["order-summary", "customer-profile"], "state_changes": ["process-order", "update-inventory"]}Delete Database
Section titled “Delete Database”DELETE /databases/{database_name}Response:
204 No ContentStatus Codes:
204 No Content: Database deleted404 Not Found: Database doesn’t exist
Event Operations
Section titled “Event Operations”Submit Events
Section titled “Submit Events”POST /databases/{database_name}/eventsRequest:
{ "events": [ { "specversion": "1.0", "id": "550e8400-e29b-41d4-a716-446655440000", "source": "order-service", "type": "OrderCreated", "subject": "order-123", "time": "2024-01-15T10:30:00Z", "datacontenttype": "application/json", "data": { "orderId": "order-123", "customerId": "customer-456", "total": 99.99 } } ], "constraints": [ { "type": "min_revision", "revision": 12344 } ]}Response:
{ "revision": 12345, "events_count": 1}Status Codes:
200 OK: Events stored successfully409 Conflict: Constraint violation400 Bad Request: Invalid event format413 Payload Too Large: Event or transaction too large
Query Events
Section titled “Query Events”POST /databases/{database_name}/queryRequest:
{ "selectors": [ { "stream": "order-service", "event_type": "OrderCreated", "subject": "order-123" } ], "revision_range": { "start": 1, "end": 1000 }, "effective_time_range": { "start": "2024-01-01T00:00:00Z", "end": "2024-01-31T23:59:59Z" }, "direction": "forward", "limit": 100}Response:
{ "events": [ { "specversion": "1.0", "id": "550e8400-e29b-41d4-a716-446655440000", "source": "order-service", "type": "OrderCreated", "subject": "order-123", "time": "2024-01-15T10:30:00Z", "datacontenttype": "application/json", "data": { "orderId": "order-123", "customerId": "customer-456", "total": 99.99 }, "revision": 12345, "recordedtime": "2024-01-15T10:30:01Z" } ], "has_more": false}Get Event by Revision
Section titled “Get Event by Revision”GET /databases/{database_name}/events/{revision}Response:
{ "specversion": "1.0", "id": "550e8400-e29b-41d4-a716-446655440000", "source": "order-service", "type": "OrderCreated", "subject": "order-123", "time": "2024-01-15T10:30:00Z", "data": {...}, "revision": 12345, "recordedtime": "2024-01-15T10:30:01Z"}State Views
Section titled “State Views”List State Views
Section titled “List State Views”GET /databases/{database_name}/state-viewsResponse:
{ "state_views": [ { "name": "order-summary", "description": "Summary of orders by status", "content_type": "application/json", "priority": "high", "parameterized": false } ]}Publish State View
Section titled “Publish State View”POST /api/v1/db/{database_name}/state-viewsContent-Type: multipart/form-dataState Views are published via multipart/form-data with two parts:
metadata: JSON containing the state view configurationwasm: The compiled WebAssembly component binary
Example with curl:
curl -X POST http://localhost:3000/api/v1/db/my-events/state-views \ -F 'metadata={ "state_view_name": "order-summary", "description": "Summary of orders by status", "content_type": "application/json", "event_selector": { "type": "or", "selectors": [ {"type": "equals", "attr": {"event_type": "OrderCreated"}}, {"type": "equals", "attr": {"event_type": "OrderCompleted"}} ] }, "query_temporality": "revision" };type=application/json' \ -F 'wasm=@order_summary.wasm;type=application/wasm'Metadata Fields:
| Field | Required | Description |
|---|---|---|
state_view_name | Yes | Unique name for the state view |
description | No | Human-readable description |
content_type | Yes | MIME type of rendered state |
content_schema | No | URI to content schema |
event_selector | Yes | Selector for events to process |
query_temporality | Yes | revision or effective_timestamp |
source_code_uri | No | URI to source code |
Response: 201 Created with redirect to admin page for the new version.
Fetch State View
Section titled “Fetch State View”GET /databases/{database_name}/state-views/{view_name}Query Parameters:
revision: Fetch state at specific revision- Additional parameters passed to the State View
Response: Content-Type based on State View definition.
Example JSON response:
{ "total_orders": 150, "orders_by_status": { "pending": 45, "completed": 100, "cancelled": 5 }, "total_revenue": 15000.00}Delete State View
Section titled “Delete State View”DELETE /databases/{database_name}/state-views/{view_name}Response:
204 No ContentState Changes
Section titled “State Changes”List State Changes
Section titled “List State Changes”GET /databases/{database_name}/state-changesResponse:
{ "state_changes": [ { "name": "process-order", "description": "Processes order creation commands", "state_view_name": "customer-profile" } ]}Publish State Change
Section titled “Publish State Change”POST /api/v1/db/{database_name}/state-changesContent-Type: multipart/form-dataState Changes are published via multipart/form-data with two parts:
metadata: JSON containing the state change configurationwasm: The compiled WebAssembly component binary
Example with curl:
curl -X POST http://localhost:3000/api/v1/db/my-events/state-changes \ -F 'metadata={ "state_change_name": "process-order", "description": "Processes order creation commands" };type=application/json' \ -F 'wasm=@process_order.wasm;type=application/wasm'Metadata Fields:
| Field | Required | Description |
|---|---|---|
state_change_name | Yes | Unique name for the state change |
description | No | Human-readable description |
source_code_uri | No | URI to source code |
Response: 201 Created with redirect to admin page for the new version.
Process Command
Section titled “Process Command”POST /databases/{database_name}/state-changes/{change_name}/processRequest:
{ "command": { "type": "CreateOrder", "customer_id": "CUST-123", "items": [ { "product_id": "PROD-456", "quantity": 2, "price": 29.99 } ] }, "parameters": { "customer_id": "CUST-123" }}Success Response:
{ "success": true, "events": [ { "specversion": "1.0", "id": "generated-id", "source": "process-order", "type": "OrderCreated", "subject": "order-789", "data": {...} } ], "revision": 12346}Error Response:
{ "success": false, "error": { "code": "INSUFFICIENT_CREDIT", "message": "Customer credit limit exceeded", "details": { "available_credit": 100.00, "order_total": 159.99 } }}Query Builder UI
Section titled “Query Builder UI”The REST API includes an interactive query builder:
GET /databases/{database_name}/query-builderReturns an HTML page with HTMX-powered query interface.
Error Responses
Section titled “Error Responses”All errors follow a consistent format:
{ "error": { "code": "INVALID_ARGUMENT", "message": "Database name must be lowercase alphanumeric", "details": { "field": "name", "value": "My-Database" } }}Common Error Codes
Section titled “Common Error Codes”| Code | HTTP Status | Description |
|---|---|---|
NOT_FOUND | 404 | Resource doesn’t exist |
ALREADY_EXISTS | 409 | Resource already exists |
INVALID_ARGUMENT | 400 | Invalid request format |
FAILED_PRECONDITION | 409 | Constraint violation |
RESOURCE_EXHAUSTED | 429 | Rate limit exceeded |
INTERNAL | 500 | Server error |
Pagination
Section titled “Pagination”Large result sets are paginated:
GET /databases/{database_name}/events?limit=50&after=12345Response:
{ "events": [...], "has_more": true, "next_cursor": "12395"}Rate Limiting
Section titled “Rate Limiting”Production deployments may include rate limiting:
HTTP/1.1 429 Too Many RequestsX-RateLimit-Limit: 1000X-RateLimit-Remaining: 0X-RateLimit-Reset: 1642098130Retry-After: 60
{ "error": { "code": "RESOURCE_EXHAUSTED", "message": "Rate limit exceeded. Please retry after 60 seconds." }}CORS Support
Section titled “CORS Support”CORS headers are included for browser-based access:
Access-Control-Allow-Origin: *Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONSAccess-Control-Allow-Headers: Content-Type, X-API-KeyConfigure allowed origins in production:
cors: allowed_origins: - https://app.example.com - https://admin.example.comHealth Check
Section titled “Health Check”GET /healthResponse:
200 OKContent-Type: text/plain
OKDetailed health check:
GET /health/detailedResponse:
{ "status": "healthy", "version": "0.1.0", "storage": { "adapter": "dynamodb", "status": "connected" }, "uptime_seconds": 3600}Examples
Section titled “Examples”Create Database and Submit Event
Section titled “Create Database and Submit Event”# Create databasecurl -X POST http://localhost:8080/databases \ -H "Content-Type: application/json" \ -d '{"name": "test-db"}'
# Submit eventcurl -X POST http://localhost:8080/databases/test-db/events \ -H "Content-Type: application/json" \ -d '{ "events": [{ "specversion": "1.0", "id": "'$(uuidgen)'", "source": "test-app", "type": "TestEvent", "data": {"message": "Hello, EvidentSource!"} }] }'Query Events with Filters
Section titled “Query Events with Filters”curl -X POST http://localhost:8080/databases/test-db/query \ -H "Content-Type: application/json" \ -d '{ "selectors": [{ "source": "test-app", "event_type": "TestEvent" }], "limit": 10 }'Fetch State View
Section titled “Fetch State View”# Simple state viewcurl http://localhost:8080/databases/test-db/state-views/event-counter
# Parameterized state viewcurl "http://localhost:8080/databases/test-db/state-views/customer-profile?customer_id=CUST-123"Client SDKs
Section titled “Client SDKs”While you can use the REST API directly, client SDKs provide a better experience. Official SDKs are available through:
- JVM (Java/Kotlin): Available via Maven Central
- JavaScript/TypeScript: Coming soon via npm
- Python: Coming soon via PyPI
- Go: Coming soon via Go modules
See Client Libraries for detailed information.
Next Steps
Section titled “Next Steps”- Try the gRPC API for better performance
- Explore Client Libraries for your language
- Download examples from the Customer Portal
- Read about Authentication