diff --git a/GerbilManagerWebAPI/Endpoints/SaleAdEndpoints.cs b/GerbilManagerWebAPI/Endpoints/SaleAdEndpoints.cs
new file mode 100644
index 0000000..5f73ebc
--- /dev/null
+++ b/GerbilManagerWebAPI/Endpoints/SaleAdEndpoints.cs
@@ -0,0 +1,34 @@
+using GerbilManagerWebAPI.SaleAd;
+
+namespace GerbilManagerWebAPI.Endpoints
+{
+ ///
+ /// FEAT-12a: POST /gerbils/sale-ad — AI-gestütztes Abgabe-Inserat (frozen
+ /// contract, see gerbil-manager-web/src/api/saleAd.ts).
+ ///
+ /// 503 {code:"AiKeyMissing"} while the AI section is unconfigured — the
+ /// frontend maps exactly this code to its German disabled-state hint.
+ ///
+ public static class SaleAdEndpoints
+ {
+ public static IEndpointRouteBuilder MapSaleAdEndpoints(this IEndpointRouteBuilder app)
+ {
+ app.MapPost("/gerbils/sale-ad",
+ async (SaleAdRequest request, SaleAdService service, CancellationToken ct) =>
+ {
+ var result = await service.GenerateAsync(request, ct);
+ return result.Status switch
+ {
+ SaleAdStatus.Ok => Results.Ok(new SaleAdResponse(result.Text!)),
+ SaleAdStatus.NotConfigured => Results.Json(
+ new SaleAdError("AiKeyMissing", result.Error ?? ""), statusCode: 503),
+ _ => Results.Json(
+ new SaleAdError("AiUpstreamError", result.Error ?? ""), statusCode: 502),
+ };
+ })
+ .WithTags("SaleAd");
+
+ return app;
+ }
+ }
+}
diff --git a/GerbilManagerWebAPI/Program.cs b/GerbilManagerWebAPI/Program.cs
index c4bfc3e..c960f6e 100644
--- a/GerbilManagerWebAPI/Program.cs
+++ b/GerbilManagerWebAPI/Program.cs
@@ -35,6 +35,13 @@ builder.Services.AddCors(options => options.AddPolicy(LanCorsPolicy, policy =>
// OpenAPI document for the Scalar API reference (Swashbuckle removed).
builder.Services.AddOpenApi();
+// FEAT-12a: provider-agnostic AI config (env vars AI__BaseUrl/AI__ApiKey/AI__Model
+// or user-secrets — never committed) + typed client for sale-ad generation.
+builder.Services.AddOptions()
+ .BindConfiguration(GerbilManagerWebAPI.SaleAd.AiOptions.SectionName);
+builder.Services.AddHttpClient(
+ http => http.Timeout = TimeSpan.FromSeconds(60));
+
var app = builder.Build();
app.MapDefaultEndpoints();
@@ -62,5 +69,6 @@ app.MapHealthRecordEndpoints();
app.MapWeightRecordEndpoints();
app.MapInbreedingEndpoints();
app.MapPhotoEndpoints();
+app.MapSaleAdEndpoints();
app.Run();