REST API Reference
Base URL: http://localhost:8080/api (via Traefik ingress) Internal cluster URL:
http://gateway-api.otel-lab.svc.cluster.local:5000
All endpoints accept and return application/json. Error responses follow the RFC 7807 Problem
Details format.
Projects
GET /api/projects
List all projects.
Response 200:
[
{
"id": 1,
"name": "Infrastructure Migration",
"owner": "alice",
"createdAt": "2026-04-14T10:00:00Z"
}
]
GET /api/projects/{id}
Get a single project.
Response 200:
{
"id": 1,
"name": "Infrastructure Migration",
"owner": "alice",
"createdAt": "2026-04-14T10:00:00Z"
}
Response 404: Project not found.
POST /api/projects
Create a project.
Request body:
{
"name": "Infrastructure Migration",
"owner": "alice"
}
Response 201:
{
"id": 1,
"name": "Infrastructure Migration",
"owner": "alice",
"createdAt": "2026-04-14T10:00:00Z"
}
DELETE /api/projects/{id}
Delete a project.
Response 204: Deleted. Response 404: Not found.
Orders
POST /api/orders
Create an order. Triggers a gRPC call to order-api, which
persists the order and publishes an order.created event to RabbitMQ.
Request body:
{
"projectId": 1,
"description": "Server rack provisioning",
"amount": 4500.00
}
Validation rules:
projectIdmust be > 0amountmust be > 0 and ≤ 999,999.99descriptionmust be non-empty and ≤ 500 characters
Response 201:
{
"id": 42,
"status": "Created"
}
Response 422 (validation failure):
{
"type": "https://tools.ietf.org/html/rfc7807",
"title": "One or more validation errors occurred.",
"status": 422,
"errors": {
"amount": ["Amount must be between 0 and 999999.99."]
}
}
GET /api/projects/{id}/orders
List all orders for a project. Uses gRPC server-streaming from order-api — rows are streamed from PostgreSQL cursor.
Response 200:
[
{
"id": 42,
"projectId": 1,
"description": "Server rack provisioning",
"amount": 4500.00,
"status": "Created",
"createdAt": "2026-04-14T10:30:00Z"
}
]
Notifications
GET /api/notifications
List recent notifications (proxied from notification-svc via HTTP).
Response 200:
[
{
"orderId": "42",
"projectId": "1",
"description": "Server rack provisioning",
"amount": "4500.0",
"processedAt": "2026-04-14T10:30:01.234Z",
"status": "processed"
}
]
Observability test endpoints
GET /api/slow
Artificial delay of 2–5 seconds. Always retained by tail sampling (latency > 2s policy). Useful for validating exemplars (the span is always sampled).
Response 200:
{ "message": "slow response", "delayMs": 3247 }
GET /api/error
Always returns HTTP 500 with an unhandled exception. Always retained by tail sampling (error policy).
Response 500:
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.6.1",
"title": "An error occurred while processing your request.",
"status": 500
}
The trace for this request will have otel.status_code=ERROR and an exception.stacktrace span
event.
GET /healthz
Liveness and readiness probe endpoint. Returns immediately with no downstream calls.
Response 200: "Healthy"
OTel context propagation
All API endpoints accept and propagate the W3C traceparent header. When the Angular SPA sends a
request with this header, the gateway-api HTTP server span becomes a child of the browser span.
Request:
traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
Response headers (propagated through nginx proxy):
traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-<new-span-id>-01
The trace ID (4bf92f...) is preserved end-to-end from browser to database.
Local graph
Linked from 3 notes
gRPC API Reference
Reference for the OrderService gRPC contract between gateway-api and order-api, covering RPCs, error codes, and trace propagation.
SignalForge Documentation
Documentation hub for the SignalForge OTel Microservices Validation Lab — architecture, services, API, deployment, observability, and operations.
Service: frontend (Angular SPA)
The Angular SPA's role, Faro browser instrumentation, nginx configuration, and browser-to-backend trace linkage.
Related notes
gRPC API Reference
Reference for the OrderService gRPC contract between gateway-api and order-api, covering RPCs, error codes, and trace propagation.
Replication Guides: Instrumenting Your Own Project
Step-by-step, copy-paste guides for replicating SignalForge's OpenTelemetry instrumentation pattern in a new .NET/Python/Angular/RabbitMQ/K8s project.
Guide: Collector & Pipeline Setup
Step-by-step: stand up a Grafana Alloy + grafana/k8s-monitoring Helm chart pipeline that receives OTLP traces/metrics/logs from your services and exports to Grafana Cloud or a self-hosted backend.
Guide: .NET Instrumentation
Step-by-step: instrument an ASP.NET Core / gRPC .NET 8 service with OpenTelemetry — SDK wiring, custom spans and metrics, and RabbitMQ producer-side async trace propagation via the outbox pattern.