API-Dokumentation
Alles, was der Editor mit deinen Projekten macht, geht auch aus einem Skript: Bild hochladen, warten, bis die Vektorisierung fertig ist, und das Ergebnis als SVG, DXF, PNG oder PDF abholen. Die API ist Teil von Pro; den Schlüssel dazu legst du in deinem Konto an.
Authentifizierung
Jede Anfrage trägt den Schlüssel im Authorization-Header. Der Schlüssel beginnt mit
sk_ und wird nach dem Anlegen genau einmal angezeigt — wer ihn verliert, widerruft ihn
und legt einen neuen an. Bis zu fünf Schlüssel sind gleichzeitig aktiv.
curl https://schnittklar.de/api/v1/entitlements \
-H "Authorization: Bearer sk_DEIN_SCHLUESSEL"
Ein Schlüssel darf alles mit deinen Projekten — anlegen, lesen, ändern, löschen, neu vektorisieren,
exportieren — aber nichts mit deinem Konto: kein Abo, kein Veröffentlichen einer Vorlage, kein
Konto löschen. Solche Anfragen antworten mit 403 not_available_for_api_keys. Ein
ungültiger, leerer oder widerrufener Schlüssel antwortet mit 401 invalid_api_key.
Sobald ein Authorization: Bearer-Header dabei ist, entscheidet allein der Schlüssel — ein
Browser-Cookie daneben zählt nicht. Ohne den Header gilt die Anmeldung im Browser (das ist der Weg des
Editors); ohne beides antwortet die API mit 401.
Alle Adressen liegen unter /api/v1/, alle Antworten sind JSON — außer den Exporten, die
die Datei selbst liefern. IDs sind Ganzzahlen.
Der Ablauf: Upload → Warten → Export
Drei Anfragen, mehr braucht ein Skript nicht.
1. Bild hochladen
curl -X POST https://schnittklar.de/api/v1/projects \
-H "Authorization: Bearer sk_DEIN_SCHLUESSEL" \
-F "image=@motiv.png" \
-F "name=Motiv" \
-F 'trace_params={"colors":4,"targetWidthMm":120}'
{"id":42,"conversion_id":77}
PNG, JPEG, WebP, HEIC, HEIF, AVIF oder PDF, bis 20 MB — vom PDF die erste Seite.
trace_params ist optional (JSON): colors
(Anzahl Farben), mode, engine (vtracer, potrace,
skeleton — und autotrace nur auf Servern, die dessen Binary haben;
welche gerade gehen, sagt engines in GET /api/v1/entitlements),
targetWidthMm (10–1200), background (white oder keep),
threshold (1–99, nur für die binarisierenden Engines potrace, autotrace und
skeleton), filterSpeckle, minAreaMm2
(0–100), hierarchy. Was fehlt, nimmt die Voreinstellung der Pipeline.
skeleton und autotrace schneiden die Mittellinie
einer Strichzeichnung statt ihrer Umrisse: das Ergebnis sind offene Pfade
(closed: false) in einer Ebene mit role: "stroke".
2. Auf die Vektorisierung warten
curl https://schnittklar.de/api/v1/conversions/77 \
-H "Authorization: Bearer sk_DEIN_SCHLUESSEL"
{"status":"tracing","error_message":null,"error_code":null,"timings":{},"mode":"replace","result_document":null}
status läuft durch pending, preprocessing, tracing,
postprocessing nach done — oder nach failed, dann steht in
error_message, warum. Frag alle zwei bis drei Sekunden nach; eine Vektorisierung dauert
meist unter zehn Sekunden.
Neben dem deutschen error_message liefert eine fehlgeschlagene Vektorisierung einen
error_code: einen von vier stabilen Strings für die vier erkannten Fehlerarten —
too_fine (Strichzeichnung zu fein für skeleton), too_many_points
(Ergebnis zu komplex fürs Schneiden), unfit_document (Postprocessing konnte kein
brauchbares Dokument bauen) und pdf_unreadable (die hochgeladene PDF-Seite ließ sich nicht
rendern). error_code ist null für einen technischen Fehler oder eine ältere,
vor dieser Zuordnung gespeicherte Meldung — dann bleibt nur error_message.
mode sagt, wohin das Ergebnis geht: replace schreibt es in das Projektdokument
(jeder Upload und jedes Retrace), insert legt es in result_document und lässt
das Projekt unberührt — so fügt der Editor eine Datei in ein offenes Projekt ein.
result_document ist null, solange der Lauf nicht done ist, und
trägt sonst dasselbe Dokument wie GET /api/v1/projects/:id.
3. Exportieren
curl -X POST https://schnittklar.de/api/v1/projects/42/export \
-H "Authorization: Bearer sk_DEIN_SCHLUESSEL" \
-H "Content-Type: application/json" \
-d '{"profile":"cricut","format":"svg","width_mm":120}' \
-o motiv-cricut.svg
profile ist cricut oder xtool, format ist
svg, dxf, png oder pdf. width_mm
(10–1200) skaliert das Motiv vor dem Export; ohne bleibt die Breite aus der Vektorisierung. Die Antwort
ist die Datei; Hinweise der Pipeline stehen als JSON-Liste deutscher Sätze im Header
X-Export-Warnings — sie sind zum Lesen gedacht, nicht zum Auswerten.
Endpunkte
| Methode und Pfad | Was sie tut |
|---|---|
GET /api/v1/entitlements | Was das Konto darf: Tarif, Tagesquote (used, limit), Exportformate. |
GET /api/v1/projects | Alle Projekte, neueste zuerst. Mit ?page=2 seitenweise (24 je Seite). |
POST /api/v1/projects | Bild hochladen und vektorisieren (siehe oben). Kostet einen Slot der Tagesquote. |
GET /api/v1/projects/:id | Ein Projekt mit seinem Dokument (Ebenen und Pfade in Millimetern), dem Stand der letzten Vektorisierung und share (Teilen-Link, {token, url, views} oder null). |
PATCH /api/v1/projects/:id | Dokument speichern: document und lock_version aus dem letzten GET. Ein veralteter lock_version ist 409 stale_object. |
PATCH /api/v1/projects/:id/rename | Umbenennen: {"name":"…"}, bis 120 Zeichen. |
POST /api/v1/projects/:id/retrace | Noch einmal vektorisieren, mit neuen trace_params. Kostet einen Slot. |
POST /api/v1/projects/:id/duplicate | Eine Kopie im selben Konto. Antwort: die neue Projektkarte. |
POST /api/v1/projects/:id/share | Teilen-Link aktivieren (idempotent). Antwort: {token, url, views}. |
DELETE /api/v1/projects/:id/share | Teilen-Link deaktivieren. Antwort: 204. |
POST /api/v1/projects/:id/share/rotate | Neuen Teilen-Link erzeugen; der alte wird sofort ungültig. Antwort: {token, url, views}. |
GET /api/v1/projects/:id/versions | Der Versionsverlauf, neueste zuerst: id, created_at, origin (autosave, manual, before_restore, retrace, import), label, size_bytes, lock_version. Ohne Dokumente. |
GET /api/v1/projects/:id/versions/:vid | Ein Eintrag samt document. |
POST /api/v1/projects/:id/versions | Den aktuellen Stand sichern: label (optional, bis 80 Zeichen), origin manual (Standard) oder import. Gleicher Inhalt wie der jüngste Eintrag → kein neuer. |
POST /api/v1/projects/:id/versions/:vid/restore | Auf diesen Stand zurück. Sichert vorher den jetzigen als before_restore, zählt lock_version hoch; Antwort wie GET /projects/:id. |
DELETE /api/v1/projects/:id | Projekt samt Bildern löschen. Antwort: 204. |
GET /api/v1/conversions/:id | Stand einer Vektorisierung (siehe oben): status, error_message, error_code (too_fine, too_many_points, unfit_document, pdf_unreadable oder null), timings, mode und result_document. |
POST /api/v1/projects/:id/export | Eine Datei (siehe oben). |
GET /api/v1/projects/:id/export/layers.zip?profile=cricut | Ein ZIP mit einer SVG je Ebene. |
POST /api/v1/projects/:id/export/print_cut.zip | Print & Cut: Druckbogen als PDF plus Schnittdatei, mit Passermarken. Body: profile, page (z. B. a4), orientation, bleed_mm, width_mm, dxf. |
GET /api/v1/export/registration_profiles | Die Passermarken-Layouts und Papierformate für Print & Cut. |
Nicht per Schlüssel erreichbar: das Beispielprojekt, die leere Leinwand, der SVG-Doktor
(POST /projects/from_svg), das Einfügen einer Datei
(POST /projects/:id/inserts), das Arbeitsbild des Editors, Schnittberichte und
das Veröffentlichen als Vorlage. Dafür braucht es die Anmeldung im Browser.
POST /api/v1/projects/from_svg — der SVG-Doktor
Der einzige Weg, auf dem eine fremde SVG-Datei zu einem Projekt wird. Gelesen, befundet und
repariert wird sie im Browser; zum Server geht nur noch das fertige Dokument:
{"name": "Motiv", "document": {…}}. Antwort 201 {"id":42,"name":"Motiv"}.
name ist optional (bis 120 Zeichen, sonst „SVG-Projekt"), document wird
gegen dasselbe Schema geprüft wie jedes gespeicherte Dokument: 422 invalid_document
mit details, wenn es nicht passt, 422 empty_document, wenn keine Ebene
darin steht. Es wird nichts vektorisiert, also kostet der Weg keinen Slot der
Tagesquote; stattdessen bremst er bei 30 Anfragen je Stunde und Konto.
Serverseitig wird dabei nie ein SVG gelesen — fremdes XML mit Entitäten und externen Referenzen zu parsen hieße XXE und Billion Laughs einzuladen.
Fehlercodes
Jeder Fehler ist JSON mit einem error-Feld; manche tragen Details daneben.
| Status | error | Bedeutung |
|---|---|---|
| 401 | invalid_api_key | Ein falscher, leerer oder widerrufener Schlüssel im Header. |
| 401 | (Devise-Meldung) | Kein Header und keine Browser-Anmeldung. |
| 402 | pro_required | Das Format gibt es nur mit Pro (kann nur nach Ablauf des Abos passieren). |
| 403 | not_available_for_api_keys | Diese Aktion bleibt dem Browser vorbehalten. |
| 404 | not_found | Gibt es nicht — oder gehört jemand anderem; die API unterscheidet das mit Absicht nicht. |
| 409 | stale_object | Jemand hat das Projekt seit deinem GET gespeichert. Neu laden, neu senden. |
| 413 | file_too_large | Mehr als 20 MB (max_bytes steht daneben). |
| 422 | unsupported_content_type | Kein PNG, JPEG, WebP, HEIC, HEIF, AVIF oder PDF. |
| 422 | invalid_param | Ein Parameter außerhalb seines Bereichs; param sagt welcher. |
| 422 | invalid | Ein Datensatz ließ sich nicht speichern; details listet die Gründe. |
| 422 | invalid_name | Leerer oder zu langer Projektname (max_length daneben). |
| 422 | invalid_document | Das Dokument hat nicht die Form, die der Export braucht — oder, beim SVG-Doktor, nicht die, die das Schema verlangt (details sagt was). |
| 422 | unsupported_raster | Print & Cut: das Rasterbild hat ein Format, das der Druckbogen nicht tragen kann. |
| 422 | empty_document, no_source_image | Noch nichts zu exportieren, zu teilen bzw. kein Bild, das sich vektorisieren ließe. |
| 422 | motif_too_large | Print & Cut: das Motiv passt nicht auf den Bogen (motif_mm, printable_mm daneben). |
| 429 | daily_limit_reached | Tagesquote des Kontos erreicht (used, limit). |
| 429 | too_many_requests | Zu viele Anfragen mit diesem Schlüssel; Retry-After sagt, wie lange. |
| 503 | writer_unavailable, export_timeout | Ein Werkzeug auf dem Server fehlt oder hat zu lange gebraucht. Später noch einmal. |
Limits und Quote
- 600 Anfragen pro Stunde je Schlüssel. Darüber antwortet alles mit
429 too_many_requestsundRetry-After. Anfragen mit einem ungültigen Schlüssel zählen getrennt: 60 pro Stunde je Adresse. - Die Tagesquote deines Kontos gilt auch hier. Pro hat keine — läuft das Abo aus, gelten fünf Vektorisierungen am Tag, wie im Browser. Ein Upload und ein Retrace kosten je einen Slot; Export, Lesen und Löschen kosten nichts.
- Uploads bis 20 MB, längste Kante bis 8000 Pixel.
- Fünf aktive Schlüssel je Konto.
- Ein Schlüssel öffnet Projekte, nicht das Konto. Halte ihn trotzdem wie ein Passwort: nicht in Repos, nicht in Screenshots.
MCP
Denselben Schlüssel versteht auch der MCP-Endpunkt /mcp (Model Context Protocol,
Streamable HTTP): ein KI-Agent — etwa Claude — bekommt dort dieselben Endpunkte als Werkzeuge,
mit denselben Grenzen; /api und /mcp teilen sich das eine Stundenbudget.
Verbinden zum Beispiel mit
claude mcp add --transport http schnittklar https://schnittklar.de/mcp --header "Authorization: Bearer sk_…".