API und KI-Agenten

Diese Website ist nur eine von zwei Oberflächen unseres Systems — die zweite ist die Schnittstelle darunter. Katalog, Preisberechnung, Versandquote und Bestellung laufen über dieselben REST-Endpunkte, die auch der Konfigurator im Browser benutzt. Sie sind offen, brauchen kein Konto, keinen Schlüssel und kein Cookie.

Auf einen Blick
  • Basis-URL: https://metallgesellschaft.org
  • Für Programme und Agenten: /v1 — kuratiert, mit Schlüssel, Spec unter /v1/openapi.json
  • Für den Browser-Bestellpfad: /openapi.json und /llms.txt
  • JSON über HTTPS, Preise netto in EUR zzgl. 19 % USt
  • Bestellung als Gast — kein Konto, keine Anmeldung

Die Agenten-Schnittstelle /v1

Die Endpunkte unter /api/… sind die des Browsers: viele, fein geschnitten, und sie erwarten, dass der Aufrufer den Warenkorb im Kopf behält. Für Programme, Beschaffungssysteme und KI-Agenten gibt es daneben /v1 — eine kleine Oberfläche entlang des Prozesses statt entlang der Tabellen. Auf ihr sitzt unser MCP-Server.

GET /v1Selbstbeschreibung: Einheiten, Berechtigungen, Regeln
GET /v1/materialsBlech-Werkstoffe: Name, Varianten-Code, Stärken (Anzeige „2,0/3,5“), Formate mit Tafelgewicht, REACH-Hinweis
GET /v1/profilesHalbzeuge suchen (q, kategorie, werkstoff, Maße wie breite_mm): Art.-Nr., Abmessungen, kg/m, Stangenlänge, REACH-Hinweis — die art_nr geht als article_nr ins Angebot
GET /v1/dfm/rulesKonstruktionsgrenzen (Format, Loch, Steg, Rand, Kanten)
POST /v1/uploadssignierter Upload-Link für eine CAD-Datei
POST /v1/designsDatei prüfen, dauerhafte design_id erhalten
POST /v1/quotesverbindliches Angebot rechnen (24 Stunden gültig)
POST /v1/ordersgegen die quote_id bestellen; Antwort enthält die checkout_url
GET /v1/orders/…Status der Bestellung
POST /v1/webhooksAdresse für signierte Statusmeldungen hinterlegen

Feste Zusagen

  • Der Server nennt den Preis. Es gibt kein Feld, in das ein Aufrufer einen Betrag schreiben könnte. Bestellt wird gegen eine quote_id; beim Anlegen der Bestellung wird noch einmal nachgerechnet.
  • Bezahlt wird im Browser. Diese API hat kein Bezahlwerkzeug und keine Berechtigung dafür. POST /v1/orders liefert eine checkout_url, die ein Mensch öffnet.
  • Kein stilles Annehmen von Risiken. Jedes Angebot trägt requirements aus der Fertigbarkeitsprüfung. block ist nicht bestellbar; warn muss beim Bestellen in accepted_requirements genannt werden — das ist eine Entscheidung des Kunden, nicht des Agenten.
  • Einheiten sind festgelegt: Längen in Millimeter, Winkel in Grad, Geld in ganzen Cent (netto, USt und brutto getrennt), Zeit als ISO 8601 in UTC.
  • Dauerhafte Kennungen statt Warteschleifen: eine geprüfte Datei bekommt sofort eine design_id und wird nie ein zweites Mal übertragen.

Zugang und Berechtigungen

Lesende Endpunkte (GET /v1, /v1/materials, /v1/profiles, /v1/dfm/rules, /v1/guide.txt) sind frei. Alles Schreibende braucht Authorization: Bearer …. Berechtigungen sind einzeln vergebbar: catalog:read, designs:write, quotes:write, orders:write, orders:read, webhooks:write. Eine Berechtigung fürs Bezahlen gibt es bewusst nicht.

Für Agenten im Namen eines Kunden gibt es dafür einen eigenen Autorisierungsserver nach OAuth 2.1. Die Anwendung meldet sich selbst an (POST /oauth/register, RFC 7591), schickt den Kunden auf /oauth/authorize — PKCE mit S256 ist Pflicht —, und dort meldet er sich mit seinem Kundenkonto an, sieht Anwendung und Rechte im Klartext und legt eine Betragsgrenze je Bestellung und je Monat fest. Danach holt die Anwendung unter POST /oauth/token ein Zugriffstoken (zehn Minuten) und ein Refresh-Token (dreißig Tage, rotierend). Die Selbstbeschreibung steht nach RFC 8414 unter /.well-known/oauth-authorization-server, die Beschreibung der Ressource nach RFC 9728 unter /.well-known/oauth-protected-resource, der Einstieg nach RFC 9727 unter /.well-known/api-catalog.

Trägt ein Token ein Kundenkonto — GET /v1/me sagt es —, dann genügt zum Bestellen {"quote_id": "…", "payment_method": "…"}: Anschrift und USt-IdNr. kommen aus dem Konto, AGB und Widerrufsbelehrung stecken in der Zustimmung. Der Kunde sieht alle verbundenen Anwendungen unter /oauth/apps und kann jede sofort widerrufen. Für feste Anbindungen ohne Browser (ERP, Einkaufssystem) vergeben wir auf Anfrage an info@mvg-frankfurt.de einen Zugang für client_credentials.

Datei übergeben, ohne sie durchzureichen

Ein gehosteter Agent sieht weder lokale Pfade noch Chat-Anhänge, und Base64 in Werkzeugargumenten sprengt jedes Kontextfenster. Deshalb liefert POST /v1/uploads einen signierten Link: upload_url für das Programm (ein PUT, 15 Minuten, einmalig, bis 50 MiB) und browser_upload_url für den Menschen, wenn das Programm die Datei gar nicht lesen kann. Danach genügt POST /v1/designs mit der upload_id.

Doppelte Aufrufe

Schreibende Aufrufe sind idempotent: Der Kopf Idempotency-Key — oder das Feld operation_key im Rumpf für Clients ohne eigene Kopfzeilen — macht aus einer Wiederholung eine Wiedergabe (Idempotency-Replayed: true). Derselbe Schlüssel mit anderen Daten wird mit 409 idempotency_reuse abgewiesen: gleicher Wiederholversuch, gleicher Schlüssel; geänderte Eingabe, neuer Schlüssel.

Statusmeldungen statt Dauerabfrage

Wer unter POST /v1/webhooks eine https-Adresse hinterlegt, bekommt order.status_changed zugestellt, sobald sich etwas ändert. Jede Meldung trägt webhook-id, webhook-timestamp und webhook-signature: v1,<Base64> — signiert wird <id>.<timestamp>.<Rumpf> mit dem Geheimnis aus der Antwort beim Anlegen. Fehlversuche werden acht Mal mit wachsendem Abstand wiederholt.

Als MCP-Server einbinden

Wer mit Claude, ChatGPT, Codex oder einer anderen Agenten-Oberfläche arbeitet, bindet uns als Verbindung ein: https://metallgesellschaft.org/mcp (Streamable HTTP, Spezifikation 2026-07-28, zustandslos; ältere Clients mit initialize gehen weiter). Die Werkzeuge rechnen mit derselben Engine wie der Shop — Preise kommen netto und brutto, Kanal online.

# Claude Code
claude mcp add --transport http --scope user mvg https://metallgesellschaft.org/mcp

# Codex
codex mcp add mvg --url https://metallgesellschaft.org/mcp

# Mit Büroschlüssel statt Zustimmung im Browser
claude mcp add --transport http mvg https://metallgesellschaft.org/mcp \
  --header "Authorization: Bearer bw_live_…"

In Claude Desktop und claude.ai: Einstellungen → Konnektoren → eigenen Konnektor mit derselben Adresse hinzufügen.

Ohne Anmeldung (mit Ratenbremse)
find_materialsBlech-Werkstoffe mit lesbarem Code, Stärken, Tafelformaten, REACH-Hinweis; Halbzeug-Suche mit Maßen
get_priceRichtpreis für Blech-Zuschnitt, Kantteil, Halbzeug-Zuschnitt und Zubehör, netto und brutto
check_manufacturabilityKonstruktionsgrenzen und Prüfung eines Kantteils (mit Datei: Anmeldung)
get_lead_timeTermine je Stufe, Schnellversand-Regel
get_shipping_estimatePackstücke und Versandkosten (Richtwert)
search_docsMagazin, Konstruktionsrichtlinien, FAQ, Preise, Versand
get_agent_guidanceLeitfaden: Reihenfolge, Einheiten, Verbote
Mit Anmeldung (OAuth-Zustimmung oder Schlüssel)
create_uploadsignierter Link für eine STEP- oder DXF-Datei
create_quoteAngebot (24 Stunden) mit checkout_url in den Warenkorb
get_quote, update_quote_partsAngebot lesen; Mengen/Positionen ändern ergibt eine neue Fassung, die alte bleibt unverändert
list_orders, check_order_statusBestellungen des Kundenkontos (nur OAuth mit Kundenkonto)

Bestellen und Bezahlen gibt es per MCP nicht. Das Angebot liefert einen Link in den Warenkorb der Website; dort bestellt und bezahlt ein Mensch. Die Anmeldung passiert von selbst: Ein Konto-Werkzeug ohne Token antwortet mit 401 und verweist auf /.well-known/oauth-protected-resource/mcp; der Client registriert sich und schickt den Kunden auf die Zustimmungsseite (in Claude Code: /mcp → Server → Authenticate). Token für den MCP-Server gelten nur dort (resource = https://metallgesellschaft.org/mcp) und tragen kein Bestellrecht. Fachfehler kommen als Werkzeug-Ergebnis mit isError und einem Problem-Dokument nach RFC 9457. Das Prozesswissen liefert der Server als instructions mit.

Fehler

Jede Fehlerantwort unter /v1 ist ein Problem-Dokument nach RFC 9457 (application/problem+json) mit stabilem code, dem betroffenen Feld als param, der Angabe retryable, einer doc_url auf diesen Abschnitt und einer request_id für Rückfragen.

invalid_requestAnfrage ist unvollstaendig oder widerspruechlich — HTTP 422, nicht wiederholbar
unauthorizedZugangsschluessel fehlt — HTTP 401, nicht wiederholbar
invalid_tokenZugangsschluessel ist ungueltig oder widerrufen — HTTP 401, nicht wiederholbar
insufficient_scopeDer Schluessel hat diese Berechtigung nicht — HTTP 403, nicht wiederholbar
upload_not_foundUpload nicht gefunden oder abgelaufen — HTTP 404, nicht wiederholbar
upload_expiredDer Upload-Link ist abgelaufen — HTTP 410, nicht wiederholbar
not_foundObjekt nicht gefunden — HTTP 404, nicht wiederholbar
design_not_foundDesign nicht gefunden — HTTP 404, nicht wiederholbar
quote_not_foundAngebot nicht gefunden — HTTP 404, nicht wiederholbar
quote_expiredAngebot ist abgelaufen — HTTP 409, nicht wiederholbar
price_changedDer Preis hat sich geaendert — HTTP 409, nicht wiederholbar
not_manufacturableTeil ist so nicht fertigbar — HTTP 422, nicht wiederholbar
requirements_openOffene Hinweise wurden nicht bestaetigt — HTTP 409, nicht wiederholbar
file_too_largeDatei ist zu gross — HTTP 413, nicht wiederholbar
unsupported_fileDateiformat wird nicht unterstuetzt — HTTP 422, nicht wiederholbar
idempotency_reuseIdempotenz-Schluessel mit anderen Daten benutzt — HTTP 409, nicht wiederholbar
idempotency_pendingGleicher Idempotenz-Schluessel wird gerade verarbeitet — HTTP 409, wiederholbar
shipping_unavailableVersand an diese Adresse ist nicht buchbar — HTTP 409, nicht wiederholbar
payment_unavailableZahlungsseite konnte nicht geoeffnet werden — HTTP 502, wiederholbar
pricing_unavailablePreis derzeit nicht ermittelbar — HTTP 503, wiederholbar
rate_limitedZu viele Anfragen — HTTP 429, wiederholbar
internal_errorUnerwarteter Fehler — HTTP 500, wiederholbar

Der Bestellpfad des Browsers

GET /api/materialsWerkstoffe, Blechstärken und die je Stärke bestellbaren Tafelformate
GET /api/profiles/catalogHalbzeug-Katalog: Rohre, Profile, Flach- und Rundmaterial
POST /api/pricing/calculatePreis für Zuschnitte, Kantteile und Halbzeug-Abschnitte inklusive Mengenstaffel
POST /api/pricing/step-quickcalcPreis zu einer hochgeladenen STEP-Datei
POST /api/feasibility/checkFertigbarkeitsprüfung gegen die Maschinengrenzen — vor dem Bestellen
POST /api/online/shipping-quoteVersandkosten zu Postleitzahl und Warenkorb
POST /api/online/ordersBestellung anlegen; die Antwort enthält den Status-Token
GET /api/online/orders/{token}Zahlungs- und Auftragsstatus

Die vollständige Beschreibung aller öffentlichen Endpunkte mit Feldern und Beispielen steht als OpenAPI-Dokument unter /openapi.json — sie lässt sich direkt in einen Client-Generator oder in ein Agenten-Werkzeug laden.

Deep-Links in die Konfiguratoren

Jeder Konfigurator lässt sich mit Vorbelegung aufrufen — für Links aus Katalogen, E-Mails, ERP-Systemen oder Agenten. Alle Parameter sind optional, Maße in Millimetern, Dezimaltrenner Punkt oder Komma; unbekannte Werte werden ignoriert, Werkstoff-Codes kommen aus GET /api/materials (Feld code, z. B. stahl-s235jr, edelstahl-1.4301, aluminium-almg3).

  • Kantteil /online/sheets: form=L|U|Z|C mit a (Mittelschenkel), b, c, winkel (Vorgabe 90) oder generisch a, rechts=50,30, wr=90,45, sr=-1,-1, links=40, wl=90, sl=1; dazu t (Stärke), mat, tiefe (Kantlänge), qty, mass=innen|aussen, phase=material|output.
    Beispiel: /online/sheets?form=L&a=100&b=50&t=2&mat=stahl-s235jr&tiefe=500&qty=3
  • Blechzuschnitt /online/cutting: l, b, t, mat, qty, phase=material.
    Beispiel: /online/cutting?l=300&b=200&t=2&mat=stahl-s235jr&qty=10
  • Rohre, Stangen & Halbzeuge /online/profiles: art=<Artikelnummer> öffnet den Artikel direkt im Zuschnitt. Beispiel: /online/profiles?art=37000
  • Teile-Designer /ausschnitte: tpl=rechteck|ronde|ring|flansch|montage|langlasche|lasche|dogear|rahmen|vent|polygon|gusset|eckrund|trapez|zprofil|wanne, Maße wie in der Maße-Karte (L, B, D, d, …), t, mat, qty, phase=ausschnitte|fertig.
    Beispiel: /ausschnitte?tpl=rechteck&L=400&B=250&t=3&mat=stahl-s235jr&qty=2
  • Werkstoff (mat=): lesbarer Code aus GET /api/materials (Feld code), z. B. stahl-s235jr, edelstahl-1.4301, aluminium-almg3, Lochbleche edelstahl-1.4301-lochblech-rv5-8 (Rv = Rundloch versetzt, Qg = Quadratloch gerade, Zahlen = Lochweite-Teilung in mm). Die interne material_id (mat_001 …) bleibt als Alias gültig; alle API-Felder material_id akzeptieren beides. Lochbleche gibt es nur im Rechteckzuschnitt, der Preis gilt immer je ganze Tafel.
  • Gespeicherter Stand: ?s=<token> auf /online/sheets|cutting|profiles und /ausschnitte — der Token kommt aus dem Knopf „Teilen" oder POST /api/online/share ({"kind","state"}); ?s= hat Vorrang vor den lesbaren Parametern.

Preis abfragen

Eine ebene Platte 200 × 150 mm aus 2 mm Aluminium AlMg3, fünf Stück — die material_id nimmt den lesbaren Code aus /api/materials:

curl -s https://metallgesellschaft.org/api/pricing/calculate \
  -H 'content-type: application/json' -d '{
  "items": [{
    "type": "sheet",
    "cart_item_id": 1,
    "quantity": 5,
    "material_id": "aluminium-almg3",
    "thickness_mm": 2.0,
    "depth_mm": 150,
    "profile": { "thickness_mm": 2.0, "center": { "length_mm": 200 } }
  }]
}'

Zurück kommt der Netto- und Bruttopreis je Position und für den gesamten Warenkorb — derselbe Preis, den ein Kunde im Browser sieht. Es gibt keinen zweiten Preis für Maschinen. Zusätzlich liefert jede Position unter scale_prices die gesamte Mengenstaffel von 1 bis 100 Stück mit, sodass ein Agent die wirtschaftliche Losgröße in einem einzigen Aufruf bestimmen kann.

Ein Kantteil entsteht aus demselben Aufruf, indem das profile um Segmente und Biegungen ergänzt wird — right_segments/right_joints und left_segments/left_joints beschreiben den Querschnitt, depth_mm die Länge der Biegelinie.

Was der Preis enthält

Material, Zuschnitt, Kantungen und Entgraten sind im Positionspreis enthalten; der Preis gilt netto in Euro zuzüglich 19 % Umsatzsteuer. Die Preisantwort liefert je Position den Aufriss (breakdown) und die Mengenstaffel (scale_prices). Alle Kosten sind im Positionspreis enthalten, auch das Einrichten der Maschinen: Auftrags- oder Rüstkosten als eigene Zeile gibt es nicht (ruest_zeilen, kleinmengen_zuschlag und auftragspauschale bleiben null). Teilen sich mehrere Positionen einen Rüstvorgang (gleicher Werkstoff und gleiche Dicke), sinkt ihr Stückpreis — rechnen Sie den Auftrag deshalb immer als Ganzes. Jede Position geht auf: Menge × Einzelpreis = Positionsbetrag. Versandkosten stammen aus der Versandquote, die Abholung in Frankfurt ist kostenfrei. Maßgefertigte Teile sind vom Widerrufsrecht ausgenommen. Die Grenzen, innerhalb derer ein Teil überhaupt fertigbar ist, stehen in den Konstruktionsrichtlinien.

Faire Nutzung

Rechenintensive Endpunkte sind mengenbegrenzt, je aufrufender Adresse und Minute: 20 Anfragen für die Kalkulation hochgeladener Dateien (STEP, DXF), 120 für Preis, Optimierung, Schachtelung und Versandquote. Darüber antworten wir mit HTTP 429 und einem Retry-After-Kopf. Lesende Abrufe wie Katalog und Werkstoffe sind nicht begrenzt. Ein Preisaufruf trägt höchstens 200 Positionen. Wer regelmäßig größere Volumina braucht — etwa für eine CAD-Integration, ein Beschaffungssystem oder einen Einkaufsagenten — schreibt uns unter info@mvg-frankfurt.de; dann heben wir das Kontingent an.

Für KI-Agenten

Unter /llms.txt steht eine kurze, maschinenlesbare Übersicht mit allen Einstiegen; /llms-full.txt enthält denselben Stoff vollständig: Leistungen, Werkstoffe, Fertigungsgrenzen, Preisregeln und Versandbedingungen in einer Datei. Beides ist bewusst öffentlich — ein Agent soll ohne Umweg über gerendertes HTML herausfinden können, was wir fertigen und was es kostet.

OpenAPI-Spec öffnen →