diff --git a/src/FrameProcessor/FrameProcessor.csproj b/src/FrameProcessor/FrameProcessor.csproj
index 87d8c16..cad79d6 100644
--- a/src/FrameProcessor/FrameProcessor.csproj
+++ b/src/FrameProcessor/FrameProcessor.csproj
@@ -7,11 +7,13 @@
+
+
diff --git a/src/FrameProcessor/Program.cs b/src/FrameProcessor/Program.cs
index d4fffbb..2806b3a 100644
--- a/src/FrameProcessor/Program.cs
+++ b/src/FrameProcessor/Program.cs
@@ -6,6 +6,7 @@ using FrameProcessor.Mqtt;
using FrameProcessor.Storage;
using FrameProcessor.UrlFetch;
using Microsoft.Extensions.Options;
+using Microsoft.OpenApi;
using Serilog;
var builder = WebApplication.CreateBuilder(args);
@@ -23,6 +24,34 @@ builder.Host.UseSerilog((context, services, configuration) => configuration
builder.Services.AddControllers();
+builder.Services.AddOpenApi(options =>
+{
+ options.AddDocumentTransformer((document, context, _) =>
+ {
+ document.Info.Title = "Frame Processor";
+ document.Info.Version = "v1";
+
+ document.Components ??= new OpenApiComponents();
+ document.Components.SecuritySchemes ??= new Dictionary();
+ document.Components.SecuritySchemes["ApiKey"] = new OpenApiSecurityScheme
+ {
+ Type = SecuritySchemeType.ApiKey,
+ In = ParameterLocation.Header,
+ Name = "X-Api-Key",
+ Description = "Shared API key required for /api/* endpoints.",
+ };
+
+ document.Security =
+ [
+ new OpenApiSecurityRequirement
+ {
+ [new OpenApiSecuritySchemeReference("ApiKey", document)] = new List(),
+ },
+ ];
+ return Task.CompletedTask;
+ });
+});
+
builder.Services.AddOptions()
.Bind(builder.Configuration.GetSection(MqttOptions.SectionName))
.ValidateDataAnnotations()
@@ -77,6 +106,13 @@ var app = builder.Build();
// Eagerly resolve FramesRegistry so an invalid frames.json fails startup fast.
_ = app.Services.GetRequiredService();
+app.MapOpenApi();
+app.UseSwaggerUI(options =>
+{
+ options.SwaggerEndpoint("/openapi/v1.json", "Frame Processor v1");
+ options.RoutePrefix = "swagger";
+});
+
app.UseMiddleware();
app.MapControllers();