Minimal API Integration
Minimal API uses the same HTTP pipeline as ASP.NET Core, so it reuses exactly the same `ImmutableLogMiddleware`. The difference is the functional registration in `Program.cs` and how you set the event and trail per endpoint via `HttpContext.Items`.
Reuse the middleware
The middleware code is identical to the ASP.NET Core page — copy `ImmutableLogMiddleware.cs` from there. Here we only show the registration and usage in Minimal API endpoints.
Registration in Program.cs
Register the options, the `IHttpClientFactory`, and the middleware. Order matters: call `UseMiddleware` before mapping the endpoints.
// Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpClient("immutablelog", c => c.Timeout = TimeSpan.FromSeconds(5));
builder.Services.AddSingleton(new ImmutableLogOptions
{
ApiKey = Environment.GetEnvironmentVariable("IMTBL_API_KEY") ?? "",
Service = "my-minimal-api",
Env = builder.Environment.EnvironmentName,
SkipPaths = new() { "/health", "/metrics" },
});
builder.Services.AddSingleton<ImmutableLogMiddleware>();
var app = builder.Build();
// Registre antes de mapear os endpoints.
app.UseMiddleware<ImmutableLogMiddleware>();
app.MapGet("/health", () => Results.Ok(new { ok = true }));
app.MapGet("/users", () => Results.Ok(new[] { "alice", "bob" }));
app.Run();Never hardcode the token. Load IMTBL_API_KEY from environment variables or user-secrets in development.
Event and trail per endpoint
Receive the `HttpContext` in the endpoint delegate and set `Items["imtbl.eventName"]` and `Items["imtbl.trail"]`. The middleware reads these values when emitting the event.
// Receba o HttpContext para definir evento/trilha por endpoint.
app.MapPost("/payments", (HttpContext ctx, PaymentDto dto) =>
{
ctx.Items["imtbl.eventName"] = "payment.created";
ctx.Items["imtbl.trail"] = "order-7782";
// ... business logic ...
return Results.Ok(new { ok = true, payment_id = "pay_123" });
});
// Trilha por fluxo de negócio:
app.MapPost("/flows/{id}/run", (HttpContext ctx, string id) =>
{
ctx.Items["imtbl.trail"] = $"flow-{id}";
return Results.Ok(new { status = "ok" });
});Auto default: http.METHOD.path.
Immutable trail (immutable_trail)
A trail groups related events into a single auditable timeline. Set `ctx.Items["imtbl.trail"]` in the endpoint delegate, or propagate it across services with the `X-Imtbl-Trail` header. The value is normalized by the middleware before sending.
The trail cannot be empty, exceed 256 characters, or contain `:` — violations return `400 invalid_immutable_trail`. The middleware's `SanitizeTrail` fixes the value before sending.
Response and status codes
The ingestion API is asynchronous. Success returns 202 (new) or 200 (idempotent duplicate). Since the middleware is fire-and-forget, these codes matter mostly if you send events manually.
| Status | Meaning |
|---|---|
| 202 | Event accepted and queued (new) |
| 200 | Idempotency-Key already exists — duplicate: true |
| 400 | Missing/empty Idempotency-Key or invalid_immutable_trail |
| 403 | Inactive/expired subscription, scope or retention |
| 413 | payload_too_large (server limit: 16KB) |
| 429 | monthly_limit_exceeded — do not retry |
| 503 | mempool_full — transient, retryable |
This documentation reflects the current integration behavior. For questions or advanced integrations, contact the support team.
