Table of Contents

HTTP-Endpunkte · Integration Addon

HTTP-Endpunkte machen Actions für externe Systeme aufrufbar. Für ausgehende Ereignisse verwenden Sie Webhooks.

Note

HTTP-Endpunkte benötigen das Addon Integrationen (actions-integration).

HTTP-Endpunkte

Jede Action wird mit [HttpRoute] zusätzlich zu einem Endpunkt:

public sealed class ArtikelApiModule(IBpSession session) : BpModule
{
    public override string ModuleName => "Artikel-API";
    public override string ModuleVersion => "1.0.0";
    public override string ModuleDescription => "Stellt Artikel als REST-Endpunkte bereit.";

    [Action("list-artikel", Display = "Artikel auflisten", Form = false)]
    [HttpRoute("GET", "artikel")]
    public List<ArtikelRow> ListArtikel()
    {
        return session.QueryDataSet<Artikel>(includes: ["ArtNr", "SuchBeg"])
            .Take(50)
            .Select(artikel => new ArtikelRow(artikel.ArtNr!, artikel.SuchBeg!))
            .ToList();
    }
}

public sealed record ArtikelRow(string Nummer, string Name);

Erreichbar ist der Endpunkt unter der öffentlichen API-Adresse der Runtime:

GET http://<runtime>/m/meinefirma.artikel-api/artikel

Der Rückgabewert wird als JSON ausgeliefert. Form = false blendet das generierte Formular aus.

Endpunkt mit API-Schlüssel aufrufen

Erstellen Sie einen API-Schlüssel in Studio und übergeben Sie ihn als Bearer-Token:

curl -H "Authorization: Bearer <schlüssel>" \
     http://localhost:5220/m/meinefirma.artikel-api/artikel

Jeder Aufruf erscheint als Ausführung in der Historie, samt verwendetem Schlüssel, Eingabe, Ergebnis und Dauer. Vergeben Sie für jede Gegenstelle einen eigenen Schlüssel, damit sich Zugriffe zuordnen und Berechtigungen unabhängig widerrufen lassen.

Parameter binden und Fehler zurückgeben

Routen- und Query-Parameter füllen die Eingabeklasse der Action. Verwenden Sie die serialisierten Property-Namen: ArtNr wird standardmäßig zu artNr. Die Groß-/Kleinschreibung ist relevant:

public sealed class GetArtikelInput
{
    [Required]
    public required string ArtNr { get; init; }
}

[Action("get-artikel", Display = "Artikel lesen", Form = false)]
[HttpRoute("GET", "artikel/{artNr}")]
public ArtikelRow GetArtikel(GetArtikelInput input)
{
    var artikel = session.QueryDataSet<Artikel>().FirstOrDefault(a => a.ArtNr == input.ArtNr)
        ?? throw HttpProblem.NotFound("Nicht gefunden", $"Kein Artikel mit Nummer {input.ArtNr}.");

    return new ArtikelRow(artikel.ArtNr!, artikel.SuchBeg!);
}

HttpProblem liefert eine Fehlerantwort nach RFC 9457, ohne den Lauf als fehlgeschlagen zu markieren oder eine Benachrichtigung auszulösen. Andere Exceptions führen zu einer fehlgeschlagenen Ausführung:

Ausnahme Statuscode
ProblemHttpException (über HttpProblem) wie angegeben, Ausführung bleibt erfolgreich
KeyNotFoundException 404
ArgumentException, ArgumentNullException, ArgumentOutOfRangeException 400
alles Übrige 500, Ausführung gilt als fehlgeschlagen

Routenvorlagen unterstützen feste Segmente sowie {name} und {name:int}.

Endpunkte in Controllern bündeln

[ActionController] bündelt Actions unter einem gemeinsamen ID- und Routenpräfix:

[ActionController("adressen", Route = "Adressen")]
public sealed class AdressenController(IBpSession session) : RestEndpointsBase<Adressen>(session);

Gemeinsame Actions können in einer eigenen Basisklasse liegen, hier RestEndpointsBase<T>, oder direkt in der Controller-Klasse definiert werden.

OpenAPI-Beschreibung verwenden

Module mit Endpunkten veröffentlichen ihre Beschreibung automatisch:

Adresse Inhalt
GET /m/<modul-id>/openapi.json OpenAPI-Dokument, erzeugt aus den Actions und ihren Typen
GET /m/<modul-id>/docs Swagger-Oberfläche zum Ausprobieren im Browser