Zum Hauptinhalt springen

PDF-Tools

Formfeed kann ein PDF nach dem Rendern fertigstellen: weitere Dokumente anhängen, ein Wasserzeichen über jede Seite legen und es mit einem Passwort verschließen. Dafür gibt es zwei Wege.

  • Im Rendering: Ergänzen Sie POST /v1/renders um einen post-Block. Sie erhalten ein Rendering und einen Download.
  • Nachträglich: Die Endpunkte /pdf/merge, /pdf/protect und /pdf/watermark arbeiten mit PDFs, die Sie bereits haben. Jeder Aufruf liefert ein neues Rendering. /pdf/info liest Seitenzahl, Seitengrößen und Metadaten.

Ein dritter Endpunkt erzeugt das PDF erst: /pdf/convert wandelt eine Word-, Excel-, PowerPoint-, OpenDocument-, RTF- oder HTML-Datei oder die Ausgabe einer Word- oder PowerPoint-Vorlage in ein PDF-Rendering um.

Quellen​

Überall, wo ein vorhandenes PDF gelesen wird (post.merge_after sowie sources oder source der Tools), sind zwei Arten von Verweisen möglich, in beliebiger Mischung:

  • Eine Rendering-ID (rnd_…) eines erfolgreichen PDF-Renderings desselben Workspaces, dessen Datei weder abgelaufen noch gelöscht ist. Eine UUID ohne Präfix gilt ebenfalls als Rendering-ID.
  • Ein PDF aus der Dateibibliothek, über seinen Namen, etwa terms.pdf oder legal/terms.pdf, oder seine Datei-ID (fil_…). Eine Datei der Bibliothek läuft nicht ab — feste AGB gehören dorthin. Ein Wasserzeichen-image ist ein PNG oder JPEG der Bibliothek und wird genauso benannt.

Formfeed löst jeden Verweis innerhalb Ihres Workspaces auf, bevor etwas läuft. Eine URL ist nie eine Quelle, ein Rendering eines anderen Workspaces ebenso wenig. Renderings, deren Dateien in verschiedenen Regionen liegen, lassen sich nicht gemeinsam verarbeiten, und merge_after kann keine Dateien aus einer anderen Region anhängen als der, in der das Rendering läuft (beides 400 invalid_request). Dateien der Bibliothek haben keine Region und lassen sich mit allem kombinieren.

Kosten und Pläne​

VorgangEinheiten (Live-Schlüssel)PläneScope
Jeder post-Schritt (merge, watermark, password)0,5 zusätzlich zum Renderingab Starter-Planrender:create
/pdf/merge, /pdf/protect, /pdf/watermark0,5 pro Aufruf, unabhängig von der Seitenzahlab Starter-Planrender:create
/pdf/convert1 je angefangene 5 Seiten des PDFs, wie ein gerendertes PDFab Starter-Planrender:create
/pdf/infokostenlosalle Plänerender:read

Test-Schlüssel kosten wie beim Rendern nichts; siehe Einheiten. Im Free-Plan antworten die Tools mit 403 forbidden und "feature": "post_processing", /pdf/convert mit "feature": "office", auch für Test-Schlüssel. Eine E-Rechnung (post.einvoice) ist ein eigener Schritt mit eigenem Preis und eigener Planregel; siehe unten.

Die /pdf/*-Endpunkte zählen wie POST /renders gegen die Anfragen pro Sekunde Ihres Plans (darüber 429 rate_limited), und ein Live-Schlüssel, dessen Einheiten aufgebraucht sind, erhält wie beim Rendern 402 quota_exceeded.

Post-Processing im Rendering​

{
"template": "invoice",
"data": { "invoice": { "number": "2026-0042" } },
"post": {
"merge_after": ["rnd_3b52891defac4cea87d80abc195d2d3f", "terms.pdf"],
"watermark": { "text": "KOPIE", "opacity": 0.2 },
"password": { "user": "sesam-oeffne-dich", "permissions": ["print"] }
}
}
SchlüsselTypWirkung
merge_afterArray aus 1 bis 49 QuellenWird in der angegebenen Reihenfolge an das gerenderte Dokument angehängt.
watermarkObjektDie Felder von /pdf/watermark ohne source: text oder image, opacity, rotation, color.
passwordObjektuser (zum Öffnen nötig), owner (hebt die Beschränkungen auf) und permissions, entsprechend user_password, owner_password und permissions von /pdf/protect. Beachten Sie die kürzeren Namen hier.
einvoiceObjekt oder falseMacht das PDF zu einer ZUGFeRD- oder Factur-X-E-Rechnung; siehe unten.

Die Schritte laufen immer in derselben Reihenfolge, egal in welcher Reihenfolge Sie sie angeben:

  1. merge_after: Die PDFs werden an das gerenderte Dokument angehängt (bis zu 49, also höchstens 50 Dokumente in einer Datei). Das Seitenlimit des Plans gilt für das zusammengeführte Ergebnis, und page_count des Renderings zählt die angehängten Seiten mit.
  2. watermark: Wird mittig über jede Seite gelegt, angehängte Seiten eingeschlossen.
  3. password: Das fertige Dokument wird mit AES-256 verschlüsselt. Dieser Schritt kommt zuletzt, weil sich ein verschlüsseltes PDF nicht mehr bearbeiten lässt.
  4. einvoice, falls vorhanden: Die E-Rechnung entsteht aus dem Dokument, wie es ausgeliefert wird.

Ein Rendering mit post kostet seine normalen Einheiten plus 0,5 pro Schritt; die Einheiten des Renderings selbst richten sich nach den gerenderten Seiten, nicht nach den angehängten. Das Beispiel oben rendert eine Seite (1 Einheit) und führt drei Schritte aus (1,5 Einheiten), zusammen 2,5 Einheiten. post funktioniert nur mit output: "pdf"; ein unbekannter Schlüssel in post wird mit 400 invalid_request abgelehnt statt ignoriert. Renderings mit Post-Processing kommen nie aus dem Deduplizierungs-Cache, weil sich ihre Quellen ändern können.

Asynchrone Renderings und Batch-Einträge nehmen post ebenfalls an. Die Verweise werden beim Absenden der Anfrage aufgelöst; wird eine Quelle gelöscht oder läuft sie ab, bevor das Rendering startet, schlägt es mit source_not_found fehl.

Mit E-Rechnung oder PDF/UA-1​

  • E-Rechnung. post.einvoice (oder eine Vorlage, die eine E-Rechnung deklariert) läuft nach den anderen Schritten und kostet 1 Einheit zusätzlich. Live-E-Rechnungen brauchen den Starter-Plan; Test-Renderings erzeugen in jedem Plan eine begrenzte Zahl pro Tag (Pläne und Einheiten). Ein Wasserzeichen ist damit möglich, als Text oder als Bild. Ein Passwort nicht: post.password zusammen mit einer E-Rechnung ergibt 400 invalid_request mit "field": "post.password", weil PDF/A Verschlüsselung verbietet. Angehängte PDFs müssen ebenfalls PDF/A erfüllen; eines, dessen Schriften nicht eingebettet sind, lässt das Rendering mit pdfa_conversion_failed scheitern.
  • PDF/UA-1. merge_after lässt sich nicht mit settings.pdf.ua verbinden (400 invalid_request, "field": "post.merge_after"): Ein Zusammenführen verwirft die Tags der Dokumente, die es anhängt. Wasserzeichen und Passwort sind damit möglich; das Wasserzeichen ist als Artefakt markiert und stört die Tags nicht, und das Passwort wird nach der Prüfung der Datei gesetzt.
  • Die Tools prüfen nicht. Die Ergebnisse von /pdf/merge, /pdf/watermark und /pdf/protect werden nie erneut validiert: Ihr einvoice und accessibility sind null. Das Zusammenführen von PDF/UA-Dateien ergibt keine PDF/UA-Datei, und eine zusammengeführte E-Rechnung trägt kein XML mehr.

Die PDF-Tools​

# ein früheres Rendering und ein PDF der Bibliothek zu einer Datei zusammenführen
curl https://api-eu.formfeed.dev/v1/pdf/merge \
-H "Authorization: Bearer $FORMFEED_API_KEY" \
-H "content-type: application/json" \
-d '{"sources": ["rnd_7da09ab6cd9946b798c187c2a9350852", "terms.pdf"], "filename": "paket.pdf"}'

# das zusammengeführte Rendering (seine ID steht in der Antwort oben) mit Wasserzeichen versehen, dann das Ergebnis schützen
curl https://api-eu.formfeed.dev/v1/pdf/watermark \
-H "Authorization: Bearer $FORMFEED_API_KEY" -H "content-type: application/json" \
-d '{"source": "rnd_745a62a800e44beeb3993bb03c8956a3", "text": "ENTWURF", "color": "#cc0000"}'
curl https://api-eu.formfeed.dev/v1/pdf/protect \
-H "Authorization: Bearer $FORMFEED_API_KEY" -H "content-type: application/json" \
-d '{"source": "rnd_50136336b95245628f661fdc527bbf8a", "user_password": "sesam-oeffne-dich", "permissions": ["print"]}'

Die SDKs nehmen ein Rendering-Objekt oder seine ID an und ein PDF der Bibliothek über seinen Namen ('terms.pdf'). Sie senden bei jedem Aufruf, der ein Rendering erzeugt, einen Idempotency-Key und nutzen ihn bei einer Wiederholung wieder; eine Wiederholung nach der ersten Antwort wird also nicht noch einmal berechnet. Den einen Fall, den das nicht abdeckt, eine Wiederholung, während der erste Aufruf noch läuft, beschreibt Idempotenz.

Merge, Watermark und Protect liefern ein Rendering wie POST /v1/renders, synchron und mit Status 200: download_url, page_count, units (0,5, mit Test-Schlüssel 0), template: null. Es erscheint im Render-Log und unter GET /v1/renders/{id}. Die Quellen bleiben unverändert. Die neue Datei wird in der Region ihrer Quellen gespeichert, oder in der Region Ihres Schlüssels, wenn alle Quellen Dateien der Bibliothek sind.

Ausgabeoptionen​

Jedes Tool, das ein Rendering erzeugt, /pdf/convert eingeschlossen, nimmt neben seinen eigenen diese optionalen Felder an:

FeldTypStandardBedeutung
filenameString, bis 200 Zeichenmerged.pdf, watermarked.pdf, protected.pdf; für Convert siehe untenName des Downloads.
accesssigned oder publicdie Einstellung des WorkspacesEin signierter Link läuft ab; ein öffentlicher lebt so lange wie die Datei. Siehe Download-Links.
expires_inSekundendie Aufbewahrung Ihres Plans und WorkspacesBewahrt das Ergebnis kürzer auf; die Aufbewahrung wird nie verlängert. Ergebnisse von Test-Schlüsseln bleiben höchstens 24 Stunden.
metaObjekt{}Eigene Werte, die mit dem Rendering und in seinen Webhooks zurückkommen.
storagefalse oder { "key": "…" }die Verbindung des WorkspacesDie Kopie in Ihrem eigenen Bucket, wie bei einem Rendering.

merge​

sources nimmt 2 bis 50 Quellen: Rendering-IDs und PDFs der Bibliothek, beliebig gemischt. Sie werden in der angegebenen Reihenfolge verbunden; dieselbe Quelle darf mehrfach vorkommen. Titel und andere Metadaten, Tags und Dateianhänge der Quellen werden nicht übernommen; benennen Sie den Download mit filename.

watermark​

FeldTypStandardBedeutung
sourceStringPflichtEine Quelle: Rendering-ID oder PDF der Bibliothek.
textString, 1 bis 200 Zeichenentweder text oder imageIn Noto Sans Bold gesetzt, die in die Datei eingebettet wird. Die Schrift deckt lateinische, griechische und kyrillische Buchstaben ab; Text mit anderen Zeichen ergibt 400 invalid_request, nehmen Sie dafür ein Bild.
imageStringentweder text oder imageDer Name eines PNG oder JPEG der Dateibibliothek. Ein anderer Typ ergibt 422 source_invalid, ein unbekannter Name 422 source_not_found.
opacityZahl, 0 bis 10.20 ist unsichtbar, 1 deckend.
rotationZahl, −360 bis 360Text -45, Bild 0Grad im Uhrzeigersinn wie in CSS. -45 verläuft von links unten nach rechts oben, 0 ist waagerecht.
colorHex-Farbe #rrggbb (das # ist optional)ein neutrales GrauDie Farbe des Textes, etwa #cc0000. Gilt nicht für ein Bild.

Der Text wird so groß gesetzt, dass er etwa 70 % der Seitendiagonale überspannt, aber nie größer als 160 pt; ein kurzes Wort wie KOPIE bleibt also bei 160 pt. Er wird auf jeder Seite zentriert, Hoch- und Querformat im selben Dokument sehen also beide richtig aus. Ein Bild wird so skaliert, dass es in 60 % der Seitenbreite und -höhe passt, unter Beibehaltung des Seitenverhältnisses, und genauso zentriert. Geben Sie text oder image an: beides oder keines ergibt 400 invalid_request. Text und Bild sind als Artefakte markiert, ein getaggtes PDF bleibt also getaggt.

protect​

FeldTypStandardBedeutung
sourceStringPflichtEine Quelle: Rendering-ID oder PDF der Bibliothek.
user_passwordString, 1 bis 127 Zeichen, ohne ZeilenumbruchkeinesWird zum Öffnen des Dokuments gebraucht. Ohne dieses Passwort kann jeder das PDF öffnen, und es gelten nur die Berechtigungen.
owner_passwordString, 1 bis 127 Zeichen, ohne Zeilenumbruchein zufälligesHebt die Beschränkungen in Programmen auf, die sie beachten. Fehlt es, wird ein zufälliges verwendet, das niemand kennt.
permissionsArray aus print, copy, modify, annotatealle vier erlaubtWas Lesende dürfen. Alles, was Sie nicht aufführen, ist verboten; eine leere Liste [] erlaubt nichts.

Senden Sie mindestens eines der drei Felder; eine leere Anfrage ergibt 400 invalid_request. Verschlüsselt wird mit AES-256. Übliche PDF-Programme halten sich an die Berechtigungen, sie sind aber keine Sicherheitsgrenze gegenüber jemandem, der die Datei öffnen kann. Für Vertraulichkeit setzen Sie ein user_password. Ein geschütztes PDF lässt sich nicht mehr zusammenführen, mit Wasserzeichen versehen oder erneut schützen (422 source_encrypted); schützen Sie also als letzten Schritt.

info​

curl https://api-eu.formfeed.dev/v1/pdf/info \
-H "Authorization: Bearer $FORMFEED_API_KEY" -H "content-type: application/json" \
-d '{"source": "rnd_50136336b95245628f661fdc527bbf8a"}'
{
"source": "rnd_50136336b95245628f661fdc527bbf8a",
"page_count": 3,
"pages": [
{
"width_pt": 595.28,
"height_pt": 841.89,
"width_mm": 210,
"height_mm": 297
}
],
"encrypted": true,
"metadata": {
"title": null,
"author": null,
"subject": null,
"producer": null,
"creator": null
}
}

Liefert die Seitenzahl, die Größe jeder Seite in Punkt und Millimetern (ein Eintrag pro Seite; das Beispiel ist gekürzt), ob das PDF verschlüsselt ist, und seine Metadaten: Titel, Autor, Betreff, Produzent und Ersteller. Ein verschlüsseltes PDF meldet seine Seiten, aber jedes Metadatenfeld ist null. source nimmt eine Rendering-ID oder ein PDF der Bibliothek. Der Aufruf ist in jedem Plan kostenlos, braucht nur render:read und erzeugt kein Rendering.

Office-Dokumente umwandeln​

POST /v1/pdf/convert wandelt eine Word-, Excel-, PowerPoint-, OpenDocument-, RTF- oder HTML-Datei in ein PDF-Rendering um. Die Umwandlung läuft in LibreOffice, nicht in der Chromium-Engine, die Vorlagen rendert. Sie nimmt eine von zwei Quellen:

  • Eine hochgeladene Datei. Senden Sie multipart/form-data mit dem Dokument als file (bis 20 MB) und den Optionen als Formularfelder. Die Datei wird umgewandelt und nicht gespeichert; abgelegt wird nur das PDF, wie bei jedem Rendering. Die Umwandlung läuft in der Region Ihres Schlüssels.
  • Die Ausgabe einer Word- oder PowerPoint-Vorlage. Senden Sie JSON mit source, der ID eines erfolgreichen Renderings mit der Ausgabe docx oder pptx (siehe Word- und PowerPoint-Vorlagen). Jedes andere Rendering beantwortet die API mit 422 source_invalid. Die Umwandlung läuft in der Region, in der diese Ausgabe liegt.
# eine hochgeladene Datei
curl https://api-eu.formfeed.dev/v1/pdf/convert \
-H "Authorization: Bearer $FORMFEED_API_KEY" \
-F file=@angebot.docx \
-F page_ranges=1-3 \
-F filename=angebot.pdf

# die Ausgabe eines Renderings einer Word-Vorlage
curl https://api-eu.formfeed.dev/v1/pdf/convert \
-H "Authorization: Bearer $FORMFEED_API_KEY" -H "content-type: application/json" \
-d '{"source": "rnd_7da09ab6cd9946b798c187c2a9350852", "filename": "angebot.pdf"}'

Auf der Kommandozeile lädt npx formfeed pdf convert angebot.docx --page-ranges 1-3 die Datei hoch und speichert angebot.pdf; eine Rendering-ID statt der Datei wandelt die Ausgabe dieses Renderings um. In der App wandelt Office zu PDF auf der Seite Renderings eine hochgeladene Datei um.

FeldTypStandardBedeutung
fileDateieines von file, sourceDas Dokument, bis 20 MB (darüber 413 file_too_large). Nur Multipart.
sourceStringeines von file, sourceRendering-ID eines erfolgreichen Renderings mit der Ausgabe docx oder pptx. Nur JSON.
page_rangesString, bis 100 Zeichenalle SeitenUmzuwandelnde Seiten, etwa 1-3,5: Zahlen, Bereiche mit -, getrennt durch ,, ohne Leerzeichen.
landscapeBooleanfalseQuerformat für Tabellen und andere Dokumente ohne eigene Seiteneinrichtung.
single_page_sheetsBooleanfalseJedes Tabellenblatt auf einer Seite.
filenameString, bis 200 Zeichender hochgeladene Name mit .pdf; bei source <Rendering-ID>.pdfName des PDFs.
access, expires_in, meta, storageDie Ausgabeoptionen. In einer Multipart-Anfrage ist meta ein JSON-Objekt als Text (bis 16.000 Zeichen), storage ebenfalls JSON-Text (false oder {"key": "…"}), und die booleschen Felder sind true oder false.

Angenommene Formate. Der Typ wird aus dem Inhalt der Datei gelesen, nie aus ihrem Namen:

  • Textverarbeitung: DOCX, DOC, ODT, RTF
  • Tabellen: XLSX, XLS, ODS
  • Präsentationen: PPTX, PPT, ODP
  • HTML, auch Words „Als Webseite speichern“ und Berichtsexporte mit einem .doc-Namen. Der Konverter lädt nichts aus dem Web: Verweise auf Bilder, Stylesheets und andere Dateien außerhalb des Dokuments werden vor der Umwandlung entfernt und bleiben also leer. Für HTML, das Sie selbst erzeugen, liefert ein Rendering mit einer html-Quelle das bessere Ergebnis.

Dateien mit Makros, Office-Vorlagen und Bildschirmpräsentationen (.dotx, .xltx, .potx, .ppsx), binäre Arbeitsmappen (.xlsb) und jeder andere Typ ergeben 415 file_type_unsupported. Passwortgeschützte Dokumente ergeben 422 source_encrypted, beschädigte Dateien 422 office_document_invalid, und ein Dokument, das entpackt mehr ergibt, als der Konverter annimmt (mehr als 2.000 Teile, mehr als 200 MB insgesamt oder ein einzelner Teil über 20 MB), 422 office_document_too_large.

Schriften. Eine Schrift, die das Dokument verwendet, aber weder einbettet noch unter den Schriften des Konverters findet, wird ersetzt. Für Calibri, Cambria, Arial und Times New Roman gibt es metrisch kompatible Ersatzschriften (Carlito, Caladea, Liberation), Zeilen und Seiten brechen also gleich um; andere Schriften können das Layout verändern. Für ein exaktes Ergebnis betten Sie die Schriften in Word ein (Datei › Optionen › Speichern › Schriftarten in der Datei einbetten).

Synchron. Die Antwort ist das fertige Rendering (output: "pdf", page_count, units); eine Umwandlung antwortet nie mit 202. Sie darf bis zu 60 Sekunden dauern; ein Dokument, das länger braucht, ergibt 504 render_timeout. Hängen Sie /pdf/protect, /pdf/watermark oder /pdf/merge mit der zurückgegebenen ID an.

Ist der Konverter ausgelastet, antwortet die API mit 503 office_unavailable und einem Retry-After-Header; berechnet wird nichts. Wiederholen Sie die Anfrage nach so vielen Sekunden mit demselben Idempotency-Key; die SDKs erledigen das für Sie.

Fehler​

CodeStatusWann
invalid_request400Falsches oder fehlendes Feld, zu wenige Quellen, Quellen in verschiedenen Regionen, post bei einer Ausgabe, die kein PDF ist, text und image zusammen (oder keines), Wasserzeichentext, den die Schrift nicht darstellen kann, protect ohne Passwort und Berechtigungen, ein Passwort über 127 Zeichen oder mit Zeilenumbruch, post.password mit E-Rechnung, merge_after mit pdf.ua.
quota_exceeded402Ein Live-Schlüssel, dessen Einheiten aufgebraucht sind, wie beim Rendern.
forbidden403Der Plan enthält kein Post-Processing ("feature": "post_processing") oder keine Office-Umwandlung ("feature": "office"), oder dem Schlüssel fehlt der Scope.
file_too_large413Das hochgeladene Dokument ist größer als 20 MB.
file_type_unsupported415Der Upload ist kein angenommenes Dokument, oder er enthält Makros.
source_not_found422Eine Rendering-ID gibt es in diesem Workspace nicht, ihre Datei wurde gelöscht oder ist abgelaufen, oder keine Datei der Bibliothek hat diesen Namen. Das Problem nennt das Feld field, die Position in index und bei einem Rendering seine render_id.
source_invalid422Das Rendering ist fehlgeschlagen oder noch nicht fertig, es hat etwas anderes als ein PDF erzeugt, die Datei der Bibliothek ist kein PDF (bei einem Wasserzeichen kein PNG oder JPEG), oder die Datei lässt sich nicht als PDF lesen. Bei /pdf/convert: Die Ausgabe des Renderings ist weder docx noch pptx, oder der Konverter hat das Dokument abgelehnt.
source_encrypted422Die Quelle ist passwortgeschützt. Schützen Sie als letzten Schritt.
page_limit_exceeded422Das zusammengeführte oder umgewandelte Dokument hat mehr Seiten, als der Plan erlaubt.
output_too_large422Das Ergebnis ist größer als die Ausgabegröße des Plans.
office_document_invalid422Das Dokument ist beschädigt oder besteht die Sicherheitsprüfungen nicht.
office_document_too_large422Das Dokument ergibt entpackt mehr, als der Konverter annimmt.
office_conversion_failed422LibreOffice konnte das Dokument nicht umwandeln. Öffnen Sie es in seiner Anwendung, speichern Sie es erneut und versuchen Sie es noch einmal.
tool_failed500Das PDF ließ sich nicht verarbeiten. Versuchen Sie es erneut oder wenden Sie sich mit der request_id an den Support.
office_unavailable503Der Konverter ist ausgelastet oder nicht erreichbar. Wiederholen Sie nach Retry-After Sekunden.
region_unavailable503Die Region ist ausgelastet oder startet neu. Wiederholen Sie nach Retry-After Sekunden.
render_timeout504Eine Umwandlung ist nicht innerhalb von 60 Sekunden fertig geworden.

Ein Aufruf, der während der Verarbeitung des PDFs scheitert, wird als fehlgeschlagenes Rendering im Render-Log erfasst und kostet nichts. Eine Anfrage, die schon vorher abgelehnt wird (ein falsches Feld, eine unbekannte Quelle, der Plan), hinterlässt kein Rendering.