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.
- 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 /v1 | Selbstbeschreibung: Einheiten, Berechtigungen, Regeln |
|---|---|
GET /v1/materials | Blech-Werkstoffe: Name, Varianten-Code, Stärken (Anzeige „2,0/3,5“), Formate mit Tafelgewicht, REACH-Hinweis |
GET /v1/profiles | Halbzeuge 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/rules | Konstruktionsgrenzen (Format, Loch, Steg, Rand, Kanten) |
POST /v1/uploads | signierter Upload-Link für eine CAD-Datei |
POST /v1/designs | Datei prüfen, dauerhafte design_id erhalten |
POST /v1/quotes | verbindliches Angebot rechnen (24 Stunden gültig) |
POST /v1/orders | gegen die quote_id bestellen; Antwort enthält die checkout_url |
GET /v1/orders/… | Status der Bestellung |
POST /v1/webhooks | Adresse 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/ordersliefert einecheckout_url, die ein Mensch öffnet. - Kein stilles Annehmen von Risiken. Jedes Angebot trägt
requirementsaus der Fertigbarkeitsprüfung.blockist nicht bestellbar;warnmuss beim Bestellen inaccepted_requirementsgenannt 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_idund 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_materials | Blech-Werkstoffe mit lesbarem Code, Stärken, Tafelformaten, REACH-Hinweis; Halbzeug-Suche mit Maßen |
get_price | Richtpreis für Blech-Zuschnitt, Kantteil, Halbzeug-Zuschnitt und Zubehör, netto und brutto |
check_manufacturability | Konstruktionsgrenzen und Prüfung eines Kantteils (mit Datei: Anmeldung) |
get_lead_time | Termine je Stufe, Schnellversand-Regel |
get_shipping_estimate | Packstücke und Versandkosten (Richtwert) |
search_docs | Magazin, Konstruktionsrichtlinien, FAQ, Preise, Versand |
get_agent_guidance | Leitfaden: Reihenfolge, Einheiten, Verbote |
| Mit Anmeldung (OAuth-Zustimmung oder Schlüssel) | |
create_upload | signierter Link für eine STEP- oder DXF-Datei |
create_quote | Angebot (24 Stunden) mit checkout_url in den Warenkorb |
get_quote, update_quote_parts | Angebot lesen; Mengen/Positionen ändern ergibt eine neue Fassung, die alte bleibt unverändert |
list_orders, check_order_status | Bestellungen 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_request | Anfrage ist unvollstaendig oder widerspruechlich — HTTP 422, nicht wiederholbar |
|---|---|
unauthorized | Zugangsschluessel fehlt — HTTP 401, nicht wiederholbar |
invalid_token | Zugangsschluessel ist ungueltig oder widerrufen — HTTP 401, nicht wiederholbar |
insufficient_scope | Der Schluessel hat diese Berechtigung nicht — HTTP 403, nicht wiederholbar |
upload_not_found | Upload nicht gefunden oder abgelaufen — HTTP 404, nicht wiederholbar |
upload_expired | Der Upload-Link ist abgelaufen — HTTP 410, nicht wiederholbar |
not_found | Objekt nicht gefunden — HTTP 404, nicht wiederholbar |
design_not_found | Design nicht gefunden — HTTP 404, nicht wiederholbar |
quote_not_found | Angebot nicht gefunden — HTTP 404, nicht wiederholbar |
quote_expired | Angebot ist abgelaufen — HTTP 409, nicht wiederholbar |
price_changed | Der Preis hat sich geaendert — HTTP 409, nicht wiederholbar |
not_manufacturable | Teil ist so nicht fertigbar — HTTP 422, nicht wiederholbar |
requirements_open | Offene Hinweise wurden nicht bestaetigt — HTTP 409, nicht wiederholbar |
file_too_large | Datei ist zu gross — HTTP 413, nicht wiederholbar |
unsupported_file | Dateiformat wird nicht unterstuetzt — HTTP 422, nicht wiederholbar |
idempotency_reuse | Idempotenz-Schluessel mit anderen Daten benutzt — HTTP 409, nicht wiederholbar |
idempotency_pending | Gleicher Idempotenz-Schluessel wird gerade verarbeitet — HTTP 409, wiederholbar |
shipping_unavailable | Versand an diese Adresse ist nicht buchbar — HTTP 409, nicht wiederholbar |
payment_unavailable | Zahlungsseite konnte nicht geoeffnet werden — HTTP 502, wiederholbar |
pricing_unavailable | Preis derzeit nicht ermittelbar — HTTP 503, wiederholbar |
rate_limited | Zu viele Anfragen — HTTP 429, wiederholbar |
internal_error | Unerwarteter Fehler — HTTP 500, wiederholbar |
Der Bestellpfad des Browsers
GET /api/materials | Werkstoffe, Blechstärken und die je Stärke bestellbaren Tafelformate |
|---|---|
GET /api/profiles/catalog | Halbzeug-Katalog: Rohre, Profile, Flach- und Rundmaterial |
POST /api/pricing/calculate | Preis für Zuschnitte, Kantteile und Halbzeug-Abschnitte inklusive Mengenstaffel |
POST /api/pricing/step-quickcalc | Preis zu einer hochgeladenen STEP-Datei |
POST /api/feasibility/check | Fertigbarkeitsprüfung gegen die Maschinengrenzen — vor dem Bestellen |
POST /api/online/shipping-quote | Versandkosten zu Postleitzahl und Warenkorb |
POST /api/online/orders | Bestellung 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|Cmita(Mittelschenkel),b,c,winkel(Vorgabe 90) oder generischa,rechts=50,30,wr=90,45,sr=-1,-1,links=40,wl=90,sl=1; dazut(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 ausGET /api/materials(Feldcode), z. B.stahl-s235jr,edelstahl-1.4301,aluminium-almg3, Lochblecheedelstahl-1.4301-lochblech-rv5-8(Rv = Rundloch versetzt, Qg = Quadratloch gerade, Zahlen = Lochweite-Teilung in mm). Die internematerial_id(mat_001…) bleibt als Alias gültig; alle API-Feldermaterial_idakzeptieren beides. Lochbleche gibt es nur im Rechteckzuschnitt, der Preis gilt immer je ganze Tafel. - Gespeicherter Stand:
?s=<token>auf/online/sheets|cutting|profilesund/ausschnitte— der Token kommt aus dem Knopf „Teilen" oderPOST /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 →