ReflowPDF API api.reflowpdf.com/v1

    API reference

    Every endpoint with its parameters, body and responses, from the OpenAPI description.

    Every request carries Authorization: Bearer rpdf_… unless an endpoint says it is public; every response carries Request-Id and the account's RateLimit-* headers (Pricing and limits).

    POST /v1/pdf#

    HTML to PDF

    Prints a whole HTML document. With data, the HTML is a template ({{ … }}, {% for %}, {% if %}) filled first.

    Parameters

    Idempotency-Key header · string
    A key of yours (a UUID) that makes the request safe to repeat: within 24 hours the same key and body get the first result back, with nothing printed or charged twice. Another body under the same key is 422 idempotency_key_reused.
    Accept header · "application/pdf" | "application/json"
    application/pdf (the default): the PDF itself. application/json: the PDF's link and facts (Pdf), the file kept 24 hours.

    Body

    html string
    The whole HTML document, with its <style>. Images and fonts by https URL or data: URI. Up to 15 MB.
    url string
    Instead of html: the page's public http(s) address (ports 80/443). It is fetched anonymously (redirects followed, each checked; 20 s, 15 MB) and printed from where it was found (its relative addresses resolve there).
    data object
    When given, html is a template filled with these values first.
    filename string
    The PDF's file name (else the document's <title>).
    options Options
    engine string
    Pin the print to an engine version (GET /v1/engines): the current one, or a previous one, kept printing until three newer engines have shipped and 30 days at most. Without it, the current engine.

    Needs a key with the print scope (scopes).

    Responses

    200
    The PDF.
    • X-Page-Count Pages printed (and counted to the plan).
    • Content-Disposition The file's name: filename, else the document's <title>.
    • X-ReflowPDF-Mark free-allowance-used when a Free account's pages without the mark are used up for the month.
    • ReflowPDF-Missing-Variables The template's variables the data did not give (comma-separated, URL-encoded); printed empty.
    • ReflowPDF-Missing-Glyphs The characters no font had a glyph for (UTF-8, percent-encoded): printed as empty boxes; add a font that covers them.
    • ReflowPDF-Missing-Fonts The font families the document named that no face answered (each percent-encoded, comma-separated): their text took the next family of its list.
    • ReflowPDF-Skipped-Resources The addresses the print went without (space-separated; as many as 2 KB holds, then +N for the rest; the JSON response lists them all).
    • Idempotent-Replayed true when this is the answer of an earlier request with the same Idempotency-Key.
    • ReflowPDF-Engine The engine version that printed it (GET /v1/engines).
    • ReflowPDF-Scripts With options.javascript: what the document's scripts did: the scripts object of the JSON response, as percent-encoded JSON (run, errors, error_count, skipped, modules, stopped, console).
    201
    With Accept: application/json: the PDF's link and facts.
    400
    The request is not valid: the problem names the field (invalid_request); or a template that does not read: an expression, a tag or a filter it cannot parse (template_error).
    401
    No API key, or one not valid.
    403
    A claim of the Pro and Max plans (PDF/A, PDF/X, PDF/UA-2) on another plan (plan_required); a key without the scope the route asks for (insufficient_scope), or used from an address it is not kept to (ip_not_allowed).
    410
    The answer of an Idempotency-Key is no longer kept: a PDF or images an hour, a link 24 hours (file_expired).
    413
    The body is over 15 MB, the document over the print's size, or a result over the 1 GB a file stored for a link may be (result_too_large).
    415
    The body is not JSON.
    422
    Not possible for this document (a claim it cannot keep, a page it does not have), a PDF that cannot be read (invalid_pdf) or is encrypted without its password (pdf_encrypted), the layout did not settle, the Idempotency-Key was used with another request, or the page of url could not be fetched (document_unreachable: not public, not HTML, over 15 MB or 20 s, or it answered an error), or the engine named prints here no more (engine_unavailable).
    429
    Too many requests of this account at once, or in the last minutes, or jobs not finished (rate_limited); or the files it stores for links fill its plan's space: Free 256 MB, Pro and Max 2 GB (storage_quota).
    500
    Our error (internal_error): give the request_id to support.
    502
    The engine failed on our side (render_failed): tried again, it may print.
    503
    The engine is busy (engine_busy), the print took over its time limit (90 s for a request, 3 minutes for a job: render_timeout), or files cannot be stored for links right now (storage_full). See Retry-After.
    Request
    curl -X POST https://api.reflowpdf.com/v1/pdf \
      -H "Authorization: Bearer $REFLOWPDF_API_KEY" \
      -H "Accept: application/json" \
      -H "Content-Type: application/json" \
      -d @- <<'JSON'
    {
      "html": "<!doctype html><html><head><title>Hello</title><style>@page { size: A4; margin: 20mm } h1 { font: 700 28pt Georgia }</style></head><body><h1>Hello, PDF</h1></body></html>"
    }
    JSON
    201 response
    {
      "id": "Hq8vR2cT9xKmL4pW",
      "object": "pdf",
      "url": "https://api.reflowpdf.com/v1/files/Hq8vR2cT9xKmL4pW/Hello.pdf",
      "expires_at": "2026-11-03T10:22:31.000Z",
      "filename": "Hello.pdf",
      "pages": 1,
      "bytes": 9612,
      "mark": null,
      "missing_variables": [],
      "skipped_resources": []
    }

    POST /v1/pdf/merge#

    Merge PDFs

    The parts' pages one after another in a new PDF. Each part is a PDF (stored for a link, in base64 or at an address) or a document printed first, all its pages or some (pages). Pages keep their content, links and form fields; the parts' outlines, tags and standard claims (PDF/A, PDF/UA) do not carry over — the result claims none.

    Parameters

    Idempotency-Key header · string
    A key of yours (a UUID) that makes the request safe to repeat: within 24 hours the same key and body get the first result back, with nothing printed or charged twice. Another body under the same key is 422 idempotency_key_reused.
    Accept header · "application/pdf" | "application/json"
    application/pdf (the default): the PDF itself. application/json: the PDF's link and facts (Pdf), the file kept 24 hours.

    Body

    parts array of PdfPart required
    The PDFs, in order: up to 50.
    filename string
    The merged PDF's file name (merged.pdf when omitted).

    Needs a key with the print scope (scopes).

    Responses

    200
    The merged PDF.
    • X-Page-Count Its pages.
    201
    With Accept: application/json: the PDF's link and facts.
    400
    The request is not valid: the problem names the field (invalid_request); or a template that does not read: an expression, a tag or a filter it cannot parse (template_error).
    401
    No API key, or one not valid.
    403
    A claim of the Pro and Max plans (PDF/A, PDF/X, PDF/UA-2) on another plan (plan_required); a key without the scope the route asks for (insufficient_scope), or used from an address it is not kept to (ip_not_allowed).
    404
    A part names a file stored for a link that is not there, or expired (file_not_found); or a template that is not (template_not_found).
    410
    The answer of an Idempotency-Key is no longer kept: a PDF or images an hour, a link 24 hours (file_expired).
    413
    The body is over 15 MB, the document over the print's size, or a result over the 1 GB a file stored for a link may be (result_too_large).
    415
    The body is not JSON.
    422
    Not possible for this document (a claim it cannot keep, a page it does not have), a PDF that cannot be read (invalid_pdf) or is encrypted without its password (pdf_encrypted), the layout did not settle, the Idempotency-Key was used with another request, or the page of url could not be fetched (document_unreachable: not public, not HTML, over 15 MB or 20 s, or it answered an error), or the engine named prints here no more (engine_unavailable).
    429
    Too many requests of this account at once, or in the last minutes, or jobs not finished (rate_limited); or the files it stores for links fill its plan's space: Free 256 MB, Pro and Max 2 GB (storage_quota).
    500
    Our error (internal_error): give the request_id to support.
    502
    The engine failed on our side (render_failed): tried again, it may print.
    503
    The engine is busy (engine_busy), the print took over its time limit (90 s for a request, 3 minutes for a job: render_timeout), or files cannot be stored for links right now (storage_full). See Retry-After.
    Request
    curl -X POST https://api.reflowpdf.com/v1/pdf/merge \
      -H "Authorization: Bearer $REFLOWPDF_API_KEY" \
      -H "Accept: application/json" \
      -H "Content-Type: application/json" \
      -d @- <<'JSON'
    {
      "filename": "Invoice with terms",
      "parts": [
        {
          "template_id": "invoice"
        },
        {
          "pdf_url": "https://example.com/terms.pdf",
          "pages": "1-2"
        }
      ]
    }
    JSON
    201 response
    {
      "id": "Hq8vR2cT9xKmL4pW",
      "object": "pdf",
      "url": "https://api.reflowpdf.com/v1/files/Hq8vR2cT9xKmL4pW/Invoice%20with%20terms.pdf",
      "expires_at": "2026-11-03T10:22:31.000Z",
      "filename": "Invoice with terms.pdf",
      "pages": 4,
      "bytes": 241687,
      "mark": null,
      "missing_variables": [],
      "skipped_resources": []
    }

    POST /v1/pdf/split#

    Split a PDF

    A PDF's pages by ranges (each a new file), or every every pages: their links, and a ZIP of them, stored 24 hours.

    Parameters

    Idempotency-Key header · string
    A key of yours (a UUID) that makes the request safe to repeat: within 24 hours the same key and body get the first result back, with nothing printed or charged twice. Another body under the same key is 422 idempotency_key_reused.

    Body

    file string
    A PDF of yours stored for a link: its id from a JSON response (24 hours).
    pdf string
    A PDF's bytes, in base64 (within the 15 MB of a request).
    pdf_url string
    A public address of a PDF, fetched (up to 100 MB, 60 s).
    html string
    Instead of a PDF: a document printed first, then split.
    url string
    Instead of html: a public page, fetched and printed.
    template_id string
    Instead of html: a template of the gallery or of your library, by its id.
    data object
    The template's data (JSON); without it, the template's own sample data.
    options Options
    password string
    The password of an encrypted PDF.
    ranges array of string
    Each a new file: ["1-2", "3-"].
    every integer
    A new file every so many pages.
    filename string
    The files' base name.

    Needs a key with the print scope (scopes).

    Responses

    201
    The files.
    400
    The request is not valid: the problem names the field (invalid_request); or a template that does not read: an expression, a tag or a filter it cannot parse (template_error).
    401
    No API key, or one not valid.
    403
    A claim of the Pro and Max plans (PDF/A, PDF/X, PDF/UA-2) on another plan (plan_required); a key without the scope the route asks for (insufficient_scope), or used from an address it is not kept to (ip_not_allowed).
    404
    A part names a file stored for a link that is not there, or expired (file_not_found); or a template that is not (template_not_found).
    413
    The body is over 15 MB, the document over the print's size, or a result over the 1 GB a file stored for a link may be (result_too_large).
    415
    The body is not JSON.
    422
    Not possible for this document (a claim it cannot keep, a page it does not have), a PDF that cannot be read (invalid_pdf) or is encrypted without its password (pdf_encrypted), the layout did not settle, the Idempotency-Key was used with another request, or the page of url could not be fetched (document_unreachable: not public, not HTML, over 15 MB or 20 s, or it answered an error), or the engine named prints here no more (engine_unavailable).
    429
    Too many requests of this account at once, or in the last minutes, or jobs not finished (rate_limited); or the files it stores for links fill its plan's space: Free 256 MB, Pro and Max 2 GB (storage_quota).
    500
    Our error (internal_error): give the request_id to support.
    503
    The engine is busy (engine_busy), the print took over its time limit (90 s for a request, 3 minutes for a job: render_timeout), or files cannot be stored for links right now (storage_full). See Retry-After.
    Request
    curl -X POST https://api.reflowpdf.com/v1/pdf/split \
      -H "Authorization: Bearer $REFLOWPDF_API_KEY" \
      -H "Content-Type: application/json" \
      -d @- <<'JSON'
    {
      "file": "Hq8vR2cT9xKmL4pW",
      "ranges": [
        "1",
        "2-"
      ]
    }
    JSON
    201 response
    {
      "id": "spl_N3wq8sHkT2xV9mRp4LcB1a",
      "object": "split",
      "files": [
        {
          "id": "Hq8vR2cT9xKmL4pW",
          "pages": "1",
          "page_count": 1,
          "url": "https://api.reflowpdf.com/v1/files/Hq8vR2cT9xKmL4pW/report-pages-1.pdf",
          "filename": "report-pages-1.pdf",
          "bytes": 48213
        }
      ],
      "archive": null,
      "expires_at": "2026-11-03T10:22:31.000Z"
    }

    POST /v1/pdf/compress#

    Compress a PDF

    The PDF written again losslessly: its streams compressed anew, its objects in object streams, resources no page uses removed. It is never larger than it was, unless linearized for fast web view (its hint tables, a few KB). Its images stay as they are.

    Parameters

    Idempotency-Key header · string
    A key of yours (a UUID) that makes the request safe to repeat: within 24 hours the same key and body get the first result back, with nothing printed or charged twice. Another body under the same key is 422 idempotency_key_reused.
    Accept header · "application/pdf" | "application/json"
    application/pdf (the default): the PDF itself. application/json: the PDF's link and facts (Pdf), the file kept 24 hours.

    Body

    file string
    A PDF of yours stored for a link: its id from a JSON response (24 hours).
    pdf string
    A PDF's bytes, in base64 (within the 15 MB of a request).
    pdf_url string
    A public address of a PDF, fetched (up to 100 MB, 60 s).
    html string
    Instead of a PDF: a document printed first, then compressed.
    url string
    Instead of html: a public page, fetched and printed.
    template_id string
    Instead of html: a template of the gallery or of your library, by its id.
    data object
    The template's data (JSON); without it, the template's own sample data.
    options Options
    password string
    The password of an encrypted PDF.
    linearize boolean
    Fast web view: its first page shows before the rest has arrived. Default false.
    filename string
    The compressed file's name.

    Needs a key with the print scope (scopes).

    Responses

    200
    The compressed PDF.
    • X-Page-Count Its pages.
    • ReflowPDF-Bytes-Before Its size before.
    201
    With Accept: application/json: the PDF's link and facts.
    400
    The request is not valid: the problem names the field (invalid_request); or a template that does not read: an expression, a tag or a filter it cannot parse (template_error).
    401
    No API key, or one not valid.
    403
    A claim of the Pro and Max plans (PDF/A, PDF/X, PDF/UA-2) on another plan (plan_required); a key without the scope the route asks for (insufficient_scope), or used from an address it is not kept to (ip_not_allowed).
    404
    A part names a file stored for a link that is not there, or expired (file_not_found); or a template that is not (template_not_found).
    410
    The answer of an Idempotency-Key is no longer kept: a PDF or images an hour, a link 24 hours (file_expired).
    413
    The body is over 15 MB, the document over the print's size, or a result over the 1 GB a file stored for a link may be (result_too_large).
    415
    The body is not JSON.
    422
    Not possible for this document (a claim it cannot keep, a page it does not have), a PDF that cannot be read (invalid_pdf) or is encrypted without its password (pdf_encrypted), the layout did not settle, the Idempotency-Key was used with another request, or the page of url could not be fetched (document_unreachable: not public, not HTML, over 15 MB or 20 s, or it answered an error), or the engine named prints here no more (engine_unavailable).
    429
    Too many requests of this account at once, or in the last minutes, or jobs not finished (rate_limited); or the files it stores for links fill its plan's space: Free 256 MB, Pro and Max 2 GB (storage_quota).
    500
    Our error (internal_error): give the request_id to support.
    502
    The engine failed on our side (render_failed): tried again, it may print.
    503
    The engine is busy (engine_busy), the print took over its time limit (90 s for a request, 3 minutes for a job: render_timeout), or files cannot be stored for links right now (storage_full). See Retry-After.
    Request
    curl -X POST https://api.reflowpdf.com/v1/pdf/compress \
      -H "Authorization: Bearer $REFLOWPDF_API_KEY" \
      -H "Accept: application/json" \
      -H "Content-Type: application/json" \
      -d @- <<'JSON'
    {
      "pdf_url": "https://example.com/report.pdf",
      "linearize": true
    }
    JSON
    201 response
    {
      "id": "Hq8vR2cT9xKmL4pW",
      "object": "pdf",
      "url": "https://api.reflowpdf.com/v1/files/Hq8vR2cT9xKmL4pW/report.pdf",
      "expires_at": "2026-11-03T10:22:31.000Z",
      "filename": "report.pdf",
      "pages": 12,
      "bytes": 812044,
      "mark": null,
      "missing_variables": [],
      "skipped_resources": [],
      "bytes_before": 1290311
    }

    GET /v1/templates#

    List templates

    The gallery's templates and your account's own (made in the editor and saved as templates), newest first among yours.

    Parameters

    q query · string
    Words in the name, description or category.
    category query · "Finance" | "Sales" | "Business" | "HR & Legal" | "Government" | "Personal" | "Logistics" | "Health" | "Events" | "Marketing" | "Showcase"
    Only this category (gallery).
    source query · "gallery" | "library"
    gallery or library (yours) only.
    limit query · integer
    Templates per page.
    starting_after query · string
    The id of the last template of the previous page.

    Needs a key with the templates scope (scopes).

    Responses

    200
    A page of templates.
    400
    The request is not valid: the problem names the field (invalid_request); or a template that does not read: an expression, a tag or a filter it cannot parse (template_error).
    401
    No API key, or one not valid.
    403
    A claim of the Pro and Max plans (PDF/A, PDF/X, PDF/UA-2) on another plan (plan_required); a key without the scope the route asks for (insufficient_scope), or used from an address it is not kept to (ip_not_allowed).
    429
    Too many requests of this account at once, or in the last minutes, or jobs not finished (rate_limited); or the files it stores for links fill its plan's space: Free 256 MB, Pro and Max 2 GB (storage_quota).
    Request
    curl https://api.reflowpdf.com/v1/templates \
      -H "Authorization: Bearer $REFLOWPDF_API_KEY"
    200 response
    {
      "object": "list",
      "data": [
        {
          "id": "invoice",
          "object": "template",
          "source": "gallery",
          "name": "B2B Invoice",
          "description": "Professional B2B invoice with line items, VAT breakdown, totals, payment terms and bank details.",
          "category": "Finance",
          "paper": {
            "size": "A4",
            "orientation": "portrait"
          }
        },
        {
          "id": "lib_Kp3xQ9mT2vLa8RcW",
          "object": "template",
          "source": "library",
          "name": "Our invoice",
          "description": null,
          "category": null,
          "updated_at": "2026-10-30T14:02:11.000Z"
        }
      ],
      "has_more": false
    }

    GET /v1/templates/{id}#

    Get a template

    A template's source, its sample data and the JSON Schema of its data: the shape to fill.

    Parameters

    id path · string required
    A gallery template's id (invoice) or yours (lib_…).

    Needs a key with the templates scope (scopes).

    Responses

    200
    The template.
    401
    No API key, or one not valid.
    403
    A claim of the Pro and Max plans (PDF/A, PDF/X, PDF/UA-2) on another plan (plan_required); a key without the scope the route asks for (insufficient_scope), or used from an address it is not kept to (ip_not_allowed).
    404
    No such template (template_not_found).
    429
    Too many requests of this account at once, or in the last minutes, or jobs not finished (rate_limited); or the files it stores for links fill its plan's space: Free 256 MB, Pro and Max 2 GB (storage_quota).
    Request
    curl https://api.reflowpdf.com/v1/templates/invoice \
      -H "Authorization: Bearer $REFLOWPDF_API_KEY"
    200 response
    {
      "id": "donation-receipt",
      "object": "template",
      "source": "gallery",
      "name": "Donation Receipt",
      "description": "Charitable tax-deductible donation receipt with donor and statement.",
      "category": "Finance",
      "paper": {
        "size": "A4",
        "orientation": "portrait"
      },
      "fillable": true,
      "html": "<!doctype html>\n<html lang=\"en\">…<h1>{{ org }}</h1>…",
      "sample_data": {
        "org": "Riverbank Children’s Foundation",
        "receiptNo": "DR-2027-00418",
        "date": "2027-03-30",
        "donor": "Aoife Donnelly",
        "amount": "250.00",
        "currency": "EUR"
      },
      "data_schema": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "type": "object",
        "properties": {
          "org": {
            "type": "string"
          },
          "receiptNo": {
            "type": "string"
          },
          "date": {
            "type": "string",
            "format": "date"
          },
          "donor": {
            "type": "string"
          },
          "amount": {
            "type": "string"
          },
          "currency": {
            "type": "string"
          }
        },
        "required": [
          "org",
          "receiptNo",
          "date",
          "donor",
          "amount",
          "currency"
        ]
      }
    }

    POST /v1/templates/{id}/pdf#

    Fill a template and print it

    Fills the template with data (its sample data when none is given) and prints it on its paper. A template of yours designed on the page (not in Code) takes no data: it prints as designed.

    Parameters

    id path · string required
    The template's id: a gallery template's name, or lib_… for one of your library.
    Idempotency-Key header · string
    A key of yours (a UUID) that makes the request safe to repeat: within 24 hours the same key and body get the first result back, with nothing printed or charged twice. Another body under the same key is 422 idempotency_key_reused.
    Accept header · "application/pdf" | "application/json"
    application/pdf (the default): the PDF itself. application/json: the PDF's link and facts (Pdf), the file kept 24 hours.

    Body

    data object
    The values the template reads, in the shape of data_schema (its sample data when omitted).
    filename string
    The file's name: yours, else the document's <title>, else document.
    options Options
    engine string
    Pin the print to an engine version (GET /v1/engines): the current one, or a previous one, kept printing until three newer engines have shipped and 30 days at most. Without it, the current engine.

    Needs a key with the print scope (scopes).

    Responses

    200
    The PDF.
    • X-Page-Count Pages printed (and counted to the plan).
    • Content-Disposition The file's name: filename, else the document's <title>.
    • X-ReflowPDF-Mark free-allowance-used when a Free account's pages without the mark are used up for the month.
    • ReflowPDF-Missing-Variables The template's variables the data did not give (comma-separated, URL-encoded); printed empty.
    • ReflowPDF-Missing-Glyphs The characters no font had a glyph for (UTF-8, percent-encoded): printed as empty boxes; add a font that covers them.
    • ReflowPDF-Missing-Fonts The font families the document named that no face answered (each percent-encoded, comma-separated): their text took the next family of its list.
    • ReflowPDF-Skipped-Resources The addresses the print went without (space-separated; as many as 2 KB holds, then +N for the rest; the JSON response lists them all).
    • Idempotent-Replayed true when this is the answer of an earlier request with the same Idempotency-Key.
    • ReflowPDF-Engine The engine version that printed it (GET /v1/engines).
    • ReflowPDF-Scripts With options.javascript: what the document's scripts did: the scripts object of the JSON response, as percent-encoded JSON (run, errors, error_count, skipped, modules, stopped, console).
    201
    With Accept: application/json: the PDF's link and facts.
    400
    The request is not valid: the problem names the field (invalid_request); or a template that does not read: an expression, a tag or a filter it cannot parse (template_error).
    401
    No API key, or one not valid.
    403
    A claim of the Pro and Max plans (PDF/A, PDF/X, PDF/UA-2) on another plan (plan_required); a key without the scope the route asks for (insufficient_scope), or used from an address it is not kept to (ip_not_allowed).
    404
    No such template (template_not_found).
    410
    The answer of an Idempotency-Key is no longer kept: a PDF or images an hour, a link 24 hours (file_expired).
    413
    The body is over 15 MB, the document over the print's size, or a result over the 1 GB a file stored for a link may be (result_too_large).
    415
    The body is not JSON.
    422
    Not possible for this document (a claim it cannot keep, a page it does not have), a PDF that cannot be read (invalid_pdf) or is encrypted without its password (pdf_encrypted), the layout did not settle, the Idempotency-Key was used with another request, or the page of url could not be fetched (document_unreachable: not public, not HTML, over 15 MB or 20 s, or it answered an error), or the engine named prints here no more (engine_unavailable).
    429
    Too many requests of this account at once, or in the last minutes, or jobs not finished (rate_limited); or the files it stores for links fill its plan's space: Free 256 MB, Pro and Max 2 GB (storage_quota).
    500
    Our error (internal_error): give the request_id to support.
    502
    The engine failed on our side (render_failed): tried again, it may print.
    503
    The engine is busy (engine_busy), the print took over its time limit (90 s for a request, 3 minutes for a job: render_timeout), or files cannot be stored for links right now (storage_full). See Retry-After.
    Request
    curl -X POST https://api.reflowpdf.com/v1/templates/invoice/pdf \
      -H "Authorization: Bearer $REFLOWPDF_API_KEY" \
      -H "Accept: application/json" \
      -H "Content-Type: application/json" \
      -d @- <<'JSON'
    {
      "filename": "INV-1042"
    }
    JSON
    201 response
    {
      "id": "Hq8vR2cT9xKmL4pW",
      "object": "pdf",
      "url": "https://api.reflowpdf.com/v1/files/Hq8vR2cT9xKmL4pW/INV-1042.pdf",
      "expires_at": "2026-11-03T10:22:31.000Z",
      "filename": "INV-1042.pdf",
      "pages": 2,
      "bytes": 184213,
      "mark": null,
      "missing_variables": [],
      "skipped_resources": []
    }

    POST /v1/images#

    HTML to page images

    The document printed, its pages as images made from the PDF itself, on white paper. One page returns the image; several return a ZIP (page-001.png, …); with Accept: application/json, their links (24 hours). Pages count to your plan as the images delivered.

    Parameters

    Idempotency-Key header · string
    A key of yours (a UUID) that makes the request safe to repeat: within 24 hours the same key and body get the first result back, with nothing printed or charged twice. Another body under the same key is 422 idempotency_key_reused.
    Accept header · string
    application/json: links to the images instead of their bytes.

    Body

    html string
    The whole HTML document.
    url string
    Instead of html: the page's public http(s) address (ports 80/443). It is fetched anonymously (redirects followed, each checked; 20 s, 15 MB) and printed from where it was found (its relative addresses resolve there).
    data object
    When given, html is a template filled with these values first.
    filename string
    The images' base name (else the document's <title>).
    options Options
    engine string
    Pin the print to an engine version (GET /v1/engines): the current one, or a previous one, kept printing until three newer engines have shipped and 30 days at most. Without it, the current engine.
    format "png" | "webp"
    Both lossless; WebP is usually smaller. Default "png".
    pages array of integer | string
    The pages, [1, 3] or "1-3,5"; every page when omitted (up to 200).
    dpi number
    Pixels per inch (72 is one per point). Default 150.

    Needs a key with the print scope (scopes).

    Responses

    200
    One page: the image. Several: a ZIP of them (page-001.png, …).
    • X-Page-Count Images delivered (and counted to the plan).
    • X-Document-Pages The pages of the document.
    • X-ReflowPDF-Mark free-allowance-used when a Free account's pages without the mark are used up for the month.
    • ReflowPDF-Missing-Variables The template's variables the data did not give (comma-separated, URL-encoded); printed empty.
    • ReflowPDF-Missing-Glyphs The characters no font had a glyph for (UTF-8, percent-encoded): printed as empty boxes; add a font that covers them.
    • ReflowPDF-Missing-Fonts The font families the document named that no face answered (each percent-encoded, comma-separated): their text took the next family of its list.
    • ReflowPDF-Skipped-Resources The addresses the print went without (space-separated; as many as 2 KB holds, then +N for the rest; the JSON response lists them all).
    • Idempotent-Replayed true when this is the answer of an earlier request with the same Idempotency-Key.
    • ReflowPDF-Engine The engine version that printed it (GET /v1/engines).
    • ReflowPDF-Scripts With options.javascript: what the document's scripts did: the scripts object of the JSON response, as percent-encoded JSON (run, errors, error_count, skipped, modules, stopped, console).
    201
    With Accept: application/json: the images' links.
    400
    The request is not valid: the problem names the field (invalid_request); or a template that does not read: an expression, a tag or a filter it cannot parse (template_error).
    401
    No API key, or one not valid.
    403
    A claim of the Pro and Max plans (PDF/A, PDF/X, PDF/UA-2) on another plan (plan_required); a key without the scope the route asks for (insufficient_scope), or used from an address it is not kept to (ip_not_allowed).
    410
    The answer of an Idempotency-Key is no longer kept: a PDF or images an hour, a link 24 hours (file_expired).
    413
    The body is over 15 MB, the document over the print's size, or a result over the 1 GB a file stored for a link may be (result_too_large).
    415
    The body is not JSON.
    422
    Not possible for this document (a claim it cannot keep, a page it does not have), a PDF that cannot be read (invalid_pdf) or is encrypted without its password (pdf_encrypted), the layout did not settle, the Idempotency-Key was used with another request, or the page of url could not be fetched (document_unreachable: not public, not HTML, over 15 MB or 20 s, or it answered an error), or the engine named prints here no more (engine_unavailable).
    429
    Too many requests of this account at once, or in the last minutes, or jobs not finished (rate_limited); or the files it stores for links fill its plan's space: Free 256 MB, Pro and Max 2 GB (storage_quota).
    500
    Our error (internal_error): give the request_id to support.
    502
    The engine failed on our side (render_failed): tried again, it may print.
    503
    The engine is busy (engine_busy), the print took over its time limit (90 s for a request, 3 minutes for a job: render_timeout), or files cannot be stored for links right now (storage_full). See Retry-After.
    Request
    curl -X POST https://api.reflowpdf.com/v1/images \
      -H "Authorization: Bearer $REFLOWPDF_API_KEY" \
      -H "Accept: application/json" \
      -H "Content-Type: application/json" \
      -d @- <<'JSON'
    {
      "html": "<h1>Hello</h1>",
      "format": "png",
      "pages": [
        1
      ],
      "dpi": 150
    }
    JSON
    201 response
    {
      "id": "img_9Qm2xT8vLp4rWs1dYbZaKa",
      "object": "images",
      "format": "png",
      "dpi": 150,
      "document_pages": 1,
      "images": [
        {
          "page": 1,
          "url": "https://api.reflowpdf.com/v1/files/Hq8vR2cT9xKmL4pW/document-page-1.png",
          "filename": "document-page-1.png",
          "width": 1241,
          "height": 1754,
          "bytes": 21877
        }
      ],
      "archive": null,
      "expires_at": "2026-11-03T10:22:31.000Z",
      "mark": null,
      "missing_variables": [],
      "skipped_resources": []
    }

    POST /v1/templates/{id}/images#

    Fill a template, its pages as images

    Fills the template with data (its sample data when none is given) and returns its pages as images, as POST /v1/images does for HTML.

    Parameters

    id path · string required
    The template's id: a gallery template's name, or lib_… for one of your library.
    Idempotency-Key header · string
    A key of yours (a UUID) that makes the request safe to repeat: within 24 hours the same key and body get the first result back, with nothing printed or charged twice. Another body under the same key is 422 idempotency_key_reused.

    Body

    data object
    The template's data (JSON); without it, the template's own sample data.
    filename string
    The file's name: yours, else the document's <title>, else document.
    options Options
    engine string
    Pin the print to an engine version (GET /v1/engines): the current one, or a previous one, kept printing until three newer engines have shipped and 30 days at most. Without it, the current engine.
    format "png" | "webp"
    png (default) or webp, lossless. Default "png".
    pages array of integer | string
    Pages to draw: [1, 3] or "1-3,5"; all when left out.
    dpi number
    Pixels per inch, 18 to 600 (150 by default; 72 is one pixel per point). Default 150.

    Needs a key with the print scope (scopes).

    Responses

    200
    One page: the image. Several: a ZIP of them (page-001.png, …).
    • X-Page-Count Images delivered (and counted to the plan).
    • X-Document-Pages The pages of the document.
    • X-ReflowPDF-Mark free-allowance-used when a Free account's pages without the mark are used up for the month.
    • ReflowPDF-Missing-Variables The template's variables the data did not give (comma-separated, URL-encoded); printed empty.
    • ReflowPDF-Missing-Glyphs The characters no font had a glyph for (UTF-8, percent-encoded): printed as empty boxes; add a font that covers them.
    • ReflowPDF-Missing-Fonts The font families the document named that no face answered (each percent-encoded, comma-separated): their text took the next family of its list.
    • ReflowPDF-Skipped-Resources The addresses the print went without (space-separated; as many as 2 KB holds, then +N for the rest; the JSON response lists them all).
    • Idempotent-Replayed true when this is the answer of an earlier request with the same Idempotency-Key.
    • ReflowPDF-Engine The engine version that printed it (GET /v1/engines).
    • ReflowPDF-Scripts With options.javascript: what the document's scripts did: the scripts object of the JSON response, as percent-encoded JSON (run, errors, error_count, skipped, modules, stopped, console).
    201
    With Accept: application/json: the images' links.
    400
    The request is not valid: the problem names the field (invalid_request); or a template that does not read: an expression, a tag or a filter it cannot parse (template_error).
    401
    No API key, or one not valid.
    403
    A claim of the Pro and Max plans (PDF/A, PDF/X, PDF/UA-2) on another plan (plan_required); a key without the scope the route asks for (insufficient_scope), or used from an address it is not kept to (ip_not_allowed).
    404
    No such template (template_not_found).
    410
    The answer of an Idempotency-Key is no longer kept: a PDF or images an hour, a link 24 hours (file_expired).
    413
    The body is over 15 MB, the document over the print's size, or a result over the 1 GB a file stored for a link may be (result_too_large).
    415
    The body is not JSON.
    422
    Not possible for this document (a claim it cannot keep, a page it does not have), a PDF that cannot be read (invalid_pdf) or is encrypted without its password (pdf_encrypted), the layout did not settle, the Idempotency-Key was used with another request, or the page of url could not be fetched (document_unreachable: not public, not HTML, over 15 MB or 20 s, or it answered an error), or the engine named prints here no more (engine_unavailable).
    429
    Too many requests of this account at once, or in the last minutes, or jobs not finished (rate_limited); or the files it stores for links fill its plan's space: Free 256 MB, Pro and Max 2 GB (storage_quota).
    500
    Our error (internal_error): give the request_id to support.
    502
    The engine failed on our side (render_failed): tried again, it may print.
    503
    The engine is busy (engine_busy), the print took over its time limit (90 s for a request, 3 minutes for a job: render_timeout), or files cannot be stored for links right now (storage_full). See Retry-After.
    Request
    curl -X POST https://api.reflowpdf.com/v1/templates/invoice/images \
      -H "Authorization: Bearer $REFLOWPDF_API_KEY" \
      -H "Accept: application/json" \
      -H "Content-Type: application/json" \
      -d @- <<'JSON'
    {
      "pages": "1",
      "dpi": 150
    }
    JSON
    201 response
    {
      "id": "img_9Qm2xT8vLp4rWs1dYbZaKa",
      "object": "images",
      "format": "png",
      "dpi": 150,
      "document_pages": 3,
      "images": [
        {
          "page": 1,
          "url": "https://api.reflowpdf.com/v1/files/Hq8vR2cT9xKmL4pW/Invoice%20INV-1042-page-1.png",
          "filename": "Invoice INV-1042-page-1.png",
          "width": 1241,
          "height": 1754,
          "bytes": 182344
        }
      ],
      "archive": null,
      "expires_at": "2026-11-03T10:22:31.000Z",
      "mark": null,
      "missing_variables": [],
      "skipped_resources": []
    }

    POST /v1/layout#

    Where everything lands

    The document printed, and where everything landed: every page's box, and every element with an id on each page it is drawn on (a table split across pages is on each). Build an index, place a stamp, check that a block fits, from the engine's own placement. Counted as the print.

    Parameters

    Idempotency-Key header · string
    A key of yours (a UUID) that makes the request safe to repeat: within 24 hours the same key and body get the first result back, with nothing printed or charged twice. Another body under the same key is 422 idempotency_key_reused.

    Body

    html string
    A whole HTML document, its CSS inline or linked.
    url string
    Instead of html: the page's public http(s) address (ports 80/443). It is fetched anonymously (redirects followed, each checked; 20 s, 15 MB) and printed from where it was found (its relative addresses resolve there).
    data object
    The template's data (JSON); without it, the template's own sample data.
    options Options
    engine string
    Pin the print to an engine version (GET /v1/engines): the current one, or a previous one, kept printing until three newer engines have shipped and 30 days at most. Without it, the current engine.

    Needs a key with the print scope (scopes).

    Responses

    200
    The layout.
    400
    The request is not valid: the problem names the field (invalid_request); or a template that does not read: an expression, a tag or a filter it cannot parse (template_error).
    401
    No API key, or one not valid.
    403
    A claim of the Pro and Max plans (PDF/A, PDF/X, PDF/UA-2) on another plan (plan_required); a key without the scope the route asks for (insufficient_scope), or used from an address it is not kept to (ip_not_allowed).
    413
    The body is over 15 MB, the document over the print's size, or a result over the 1 GB a file stored for a link may be (result_too_large).
    415
    The body is not JSON.
    422
    Not possible for this document (a claim it cannot keep, a page it does not have), a PDF that cannot be read (invalid_pdf) or is encrypted without its password (pdf_encrypted), the layout did not settle, the Idempotency-Key was used with another request, or the page of url could not be fetched (document_unreachable: not public, not HTML, over 15 MB or 20 s, or it answered an error), or the engine named prints here no more (engine_unavailable).
    429
    Too many requests of this account at once, or in the last minutes, or jobs not finished (rate_limited); or the files it stores for links fill its plan's space: Free 256 MB, Pro and Max 2 GB (storage_quota).
    500
    Our error (internal_error): give the request_id to support.
    502
    The engine failed on our side (render_failed): tried again, it may print.
    503
    The engine is busy (engine_busy), the print took over its time limit (90 s for a request, 3 minutes for a job: render_timeout), or files cannot be stored for links right now (storage_full). See Retry-After.
    Request
    curl -X POST https://api.reflowpdf.com/v1/layout \
      -H "Authorization: Bearer $REFLOWPDF_API_KEY" \
      -H "Content-Type: application/json" \
      -d @- <<'JSON'
    {
      "html": "<h1 id=\"intro\">Intro</h1><p id=\"totals\">…</p>"
    }
    JSON
    200 response
    {
      "object": "layout",
      "unit": "pt",
      "document_pages": 2,
      "pages": [
        {
          "number": 1,
          "width": 595.28,
          "height": 841.89
        },
        {
          "number": 2,
          "width": 595.28,
          "height": 841.89
        }
      ],
      "elements": [
        {
          "id": "totals",
          "page": 2,
          "x": 56.69,
          "y": 120.5,
          "width": 481.89,
          "height": 64
        }
      ],
      "missing_variables": [],
      "skipped_resources": []
    }

    POST /v1/templates/{id}/layout#

    Fill a template, where everything lands

    Fills the template with data (its sample data when none is given), prints it, and returns where everything landed, as POST /v1/layout does for HTML.

    Parameters

    id path · string required
    The template's id: a gallery template's name, or lib_… for one of your library.
    Idempotency-Key header · string
    A key of yours (a UUID) that makes the request safe to repeat: within 24 hours the same key and body get the first result back, with nothing printed or charged twice. Another body under the same key is 422 idempotency_key_reused.

    Body

    data object
    The template's data (JSON); without it, the template's own sample data.
    options Options
    engine string
    Pin the print to an engine version (GET /v1/engines): the current one, or a previous one, kept printing until three newer engines have shipped and 30 days at most. Without it, the current engine.

    Needs a key with the print scope (scopes).

    Responses

    200
    The layout.
    400
    The request is not valid: the problem names the field (invalid_request); or a template that does not read: an expression, a tag or a filter it cannot parse (template_error).
    401
    No API key, or one not valid.
    403
    A claim of the Pro and Max plans (PDF/A, PDF/X, PDF/UA-2) on another plan (plan_required); a key without the scope the route asks for (insufficient_scope), or used from an address it is not kept to (ip_not_allowed).
    404
    No such template (template_not_found).
    413
    The body is over 15 MB, the document over the print's size, or a result over the 1 GB a file stored for a link may be (result_too_large).
    422
    Not possible for this document (a claim it cannot keep, a page it does not have), a PDF that cannot be read (invalid_pdf) or is encrypted without its password (pdf_encrypted), the layout did not settle, the Idempotency-Key was used with another request, or the page of url could not be fetched (document_unreachable: not public, not HTML, over 15 MB or 20 s, or it answered an error), or the engine named prints here no more (engine_unavailable).
    429
    Too many requests of this account at once, or in the last minutes, or jobs not finished (rate_limited); or the files it stores for links fill its plan's space: Free 256 MB, Pro and Max 2 GB (storage_quota).
    503
    The engine is busy (engine_busy), the print took over its time limit (90 s for a request, 3 minutes for a job: render_timeout), or files cannot be stored for links right now (storage_full). See Retry-After.
    Request
    curl -X POST https://api.reflowpdf.com/v1/templates/invoice/layout \
      -H "Authorization: Bearer $REFLOWPDF_API_KEY"
    200 response
    {
      "object": "layout",
      "unit": "pt",
      "document_pages": 2,
      "pages": [
        {
          "number": 1,
          "width": 595.28,
          "height": 841.89
        },
        {
          "number": 2,
          "width": 595.28,
          "height": 841.89
        }
      ],
      "elements": [
        {
          "id": "totals",
          "page": 2,
          "x": 56.69,
          "y": 120.5,
          "width": 481.89,
          "height": 64
        }
      ],
      "missing_variables": [],
      "skipped_resources": []
    }

    GET /v1/output-intents#

    List print conditions

    The print conditions PDF/X can claim here (options.pdf_x.output_intent). Your own printer's profile goes with the request instead (options.pdf_x.profile).

    Needs a key with the print scope (scopes).

    Responses

    200
    The print conditions.
    401
    No API key, or one not valid.
    403
    A claim of the Pro and Max plans (PDF/A, PDF/X, PDF/UA-2) on another plan (plan_required); a key without the scope the route asks for (insufficient_scope), or used from an address it is not kept to (ip_not_allowed).
    Request
    curl https://api.reflowpdf.com/v1/output-intents \
      -H "Authorization: Bearer $REFLOWPDF_API_KEY"
    200 response
    {
      "object": "list",
      "data": [
        {
          "id": "FOGRA39",
          "object": "output_intent",
          "info": "ISO Coated v2 (ECI)",
          "color_space": "CMYK"
        }
      ],
      "has_more": true
    }

    GET /v1/output-intents/{id}/profile#

    Download a print condition's profile

    The ICC profile of a print condition, as its publisher made it (ETag: its SHA-256), for an API key or a licensed @reflowpdf/engine (its license's token), from any page (CORS): the engine fetches the one a document names.

    Parameters

    id path · string required
    A print condition, as GET /v1/output-intents lists it: FOGRA39.

    An API key with the print scope, or a licensed engine's token.

    Responses

    200
    The profile.
    401
    Neither an API key nor a license's token.
    404
    No such print condition.
    Request
    curl https://api.reflowpdf.com/v1/output-intents/FOGRA39/profile \
      -H "Authorization: Bearer $REFLOWPDF_API_KEY" \
      -o FOGRA39.icc

    GET /v1/fonts/{family}#

    A family of the font catalogue

    ReflowPDF's catalogue, the Google Fonts the API and the editor print with, for a licensed @reflowpdf/engine or an API key: a family's faces, each with its header (its OpenType header tables, cmap and hmtx, as a small sfnt) and where its bytes are. The engine asks for the families its document names that no face of its own answers, and fetches the faces its text draws with.

    Parameters

    family path · string required
    A family of the catalogue, as font-family names it: Inter, Noto Sans JP.

    An API key with the print scope, or a licensed engine's token.

    Responses

    200
    The family.
    401
    Neither an API key nor a license's token.
    404
    No such family in the catalogue.
    Request
    curl https://api.reflowpdf.com/v1/fonts/Inter \
      -H "Authorization: Bearer $REFLOWPDF_API_KEY"
    200 response
    {
      "object": "font_family",
      "family": "string",
      "header_format": 1,
      "faces": [
        {
          "id": "string",
          "weight": 1,
          "style": "normal",
          "sha256": "string",
          "bytes": 1,
          "header": "string",
          "url": "https://api.reflowpdf.com/v1/files/…"
        }
      ]
    }

    GET /v1/fonts/files/{id}#

    A face of the font catalogue

    A face's bytes (TrueType or WOFF2, ETag: its SHA-256), as its foundry publishes it; its licence (SIL OFL 1.1, Apache 2.0 or the Ubuntu Font Licence) is in its own name table.

    Parameters

    id path · string required
    A face's id, from its family's faces.

    An API key with the print scope, or a licensed engine's token.

    Responses

    200
    The face.
    401
    Neither an API key nor a license's token.
    404
    No such face.
    Request
    curl https://api.reflowpdf.com/v1/fonts/files/aff10562c603409a49b7ef65 \
      -H "Authorization: Bearer $REFLOWPDF_API_KEY" \
      -o font.woff2

    POST /v1/jobs#

    Print asynchronously

    The same print as POST /v1/pdf or POST /v1/templates/{id}/pdf, done in the background: answers 202 at once; poll GET /v1/jobs/{id} or receive the job.succeeded / job.failed webhook.

    Parameters

    Idempotency-Key header · string
    A key of yours (a UUID) that makes the request safe to repeat: within 24 hours the same key and body get the first result back, with nothing printed or charged twice. Another body under the same key is 422 idempotency_key_reused.

    Body

    html string
    The document to print (or url, or template_id).
    url string
    Instead of html: the page's public http(s) address (ports 80/443). It is fetched anonymously (redirects followed, each checked; 20 s, 15 MB) and printed from where it was found (its relative addresses resolve there).
    template_id string
    Instead of html: a template of the gallery or of your library, by its id.
    data object
    The template's data (JSON); without it, the template's own sample data.
    filename string
    The file's name: yours, else the document's <title>, else document.
    options Options
    engine string
    Pin the print to an engine version (GET /v1/engines): the current one, or a previous one, kept printing until three newer engines have shipped and 30 days at most. Without it, the current engine.
    webhook_url string
    An https URL that receives job.succeeded / job.failed.
    metadata object
    Your own keys, returned with the job and its webhook.
    upload object
    Into your own storage: the job PUTs its file to this signed address once printed: an S3 presigned URL, a Google Cloud Storage signed URL, an Azure Blob SAS, R2, any https endpoint that takes a PUT. No credential of your storage is given to us.
    output object
    What the job delivers: a PDF (the default), its pages as images, or the layout.

    Needs a key with the print scope (scopes).

    Responses

    202
    The job, queued.
    • Location The job's address.
    400
    The request is not valid: the problem names the field (invalid_request); or a template that does not read: an expression, a tag or a filter it cannot parse (template_error).
    401
    No API key, or one not valid.
    403
    A claim of the Pro and Max plans (PDF/A, PDF/X, PDF/UA-2) on another plan (plan_required); a key without the scope the route asks for (insufficient_scope), or used from an address it is not kept to (ip_not_allowed).
    404
    No such template (template_not_found).
    409
    A request with this Idempotency-Key is still being done.
    415
    The body is not JSON.
    422
    Not possible for this document (a claim it cannot keep, a page it does not have), a PDF that cannot be read (invalid_pdf) or is encrypted without its password (pdf_encrypted), the layout did not settle, the Idempotency-Key was used with another request, or the page of url could not be fetched (document_unreachable: not public, not HTML, over 15 MB or 20 s, or it answered an error), or the engine named prints here no more (engine_unavailable).
    429
    Too many requests of this account at once, or in the last minutes, or jobs not finished (rate_limited); or the files it stores for links fill its plan's space: Free 256 MB, Pro and Max 2 GB (storage_quota).
    Request
    curl -X POST https://api.reflowpdf.com/v1/jobs \
      -H "Authorization: Bearer $REFLOWPDF_API_KEY" \
      -H "Content-Type: application/json" \
      -d @- <<'JSON'
    {
      "template_id": "invoice",
      "webhook_url": "https://example.com/hooks/reflowpdf",
      "metadata": {
        "order": "42"
      }
    }
    JSON
    202 response
    {
      "id": "job_Qm9xT2nV8cLp4rWs1dYbZa",
      "object": "job",
      "status": "queued",
      "created_at": "2026-11-02T10:22:30.114Z",
      "started_at": null,
      "finished_at": null,
      "template_id": "invoice",
      "webhook_url": "https://example.com/hooks/reflowpdf",
      "metadata": {
        "order": "42"
      },
      "result": null,
      "error": null
    }

    GET /v1/jobs#

    List jobs

    The account's jobs of the last 24 hours, newest first.

    Parameters

    status query · "queued" | "running" | "succeeded" | "failed"
    Only the jobs in this state.
    limit query · integer
    How many to a page (1–100).
    starting_after query · string
    The last job id of the previous page.

    Needs a key with the print scope (scopes).

    Responses

    200
    A page of jobs.
    400
    The request is not valid: the problem names the field (invalid_request); or a template that does not read: an expression, a tag or a filter it cannot parse (template_error).
    401
    No API key, or one not valid.
    403
    A claim of the Pro and Max plans (PDF/A, PDF/X, PDF/UA-2) on another plan (plan_required); a key without the scope the route asks for (insufficient_scope), or used from an address it is not kept to (ip_not_allowed).
    Request
    curl https://api.reflowpdf.com/v1/jobs \
      -H "Authorization: Bearer $REFLOWPDF_API_KEY"
    200 response
    {
      "object": "list",
      "data": [
        {
          "id": "job_Qm9xT2nV8cLp4rWs1dYbZa",
          "object": "job",
          "status": "succeeded",
          "created_at": "2026-11-02T10:22:30.114Z",
          "started_at": "2026-11-02T10:22:30.120Z",
          "finished_at": "2026-11-02T10:22:31.402Z",
          "template_id": "invoice",
          "webhook_url": "https://example.com/hooks/reflowpdf",
          "metadata": {
            "order": "42"
          },
          "result": {
            "id": "Hq8vR2cT9xKmL4pW",
            "object": "pdf",
            "url": "https://api.reflowpdf.com/v1/files/Hq8vR2cT9xKmL4pW/Invoice%20INV-1042.pdf",
            "expires_at": "2026-11-03T10:22:31.000Z",
            "filename": "Invoice INV-1042.pdf",
            "pages": 2,
            "bytes": 184213,
            "mark": null,
            "missing_variables": [],
            "skipped_resources": []
          },
          "error": null
        }
      ],
      "has_more": true
    }

    GET /v1/jobs/{id}#

    Get a job

    A job of this account from the last 24 hours: its status, and when it is done its result (the PDF's link and facts, the images or the layout) or its error.

    Parameters

    id path · string required
    The job's id (job_…).

    Needs a key with the print scope (scopes).

    Responses

    200
    The job.
    401
    No API key, or one not valid.
    403
    A claim of the Pro and Max plans (PDF/A, PDF/X, PDF/UA-2) on another plan (plan_required); a key without the scope the route asks for (insufficient_scope), or used from an address it is not kept to (ip_not_allowed).
    404
    No such job in this account, or it is over 24 hours old.
    Request
    curl https://api.reflowpdf.com/v1/jobs/job_Qm9xT2nV8cLp4rWs1dYbZa \
      -H "Authorization: Bearer $REFLOWPDF_API_KEY"
    200 response
    {
      "id": "job_Qm9xT2nV8cLp4rWs1dYbZa",
      "object": "job",
      "status": "succeeded",
      "created_at": "2026-11-02T10:22:30.114Z",
      "started_at": "2026-11-02T10:22:30.120Z",
      "finished_at": "2026-11-02T10:22:31.402Z",
      "template_id": "invoice",
      "webhook_url": "https://example.com/hooks/reflowpdf",
      "metadata": {
        "order": "42"
      },
      "result": {
        "id": "Hq8vR2cT9xKmL4pW",
        "object": "pdf",
        "url": "https://api.reflowpdf.com/v1/files/Hq8vR2cT9xKmL4pW/Invoice%20INV-1042.pdf",
        "expires_at": "2026-11-03T10:22:31.000Z",
        "filename": "Invoice INV-1042.pdf",
        "pages": 2,
        "bytes": 184213,
        "mark": null,
        "missing_variables": [],
        "skipped_resources": []
      },
      "error": null
    }

    POST /v1/jobs/{id}/webhook#

    Deliver a job's webhook again

    Send a finished job's event to its webhook_url again now, after your receiver was down or lost it. The response is the job, its webhook saying how the delivery went.

    Parameters

    id path · string required
    The job's id (job_…).

    Needs a key with the print scope (scopes).

    Responses

    200
    The job after the delivery.
    401
    No API key, or one not valid.
    403
    A claim of the Pro and Max plans (PDF/A, PDF/X, PDF/UA-2) on another plan (plan_required); a key without the scope the route asks for (insufficient_scope), or used from an address it is not kept to (ip_not_allowed).
    404
    No such job in this account, or it is over 24 hours old.
    409
    The job has no webhook (no_webhook), is not finished (job_not_finished), or an attempt to deliver its event is under way (delivery_in_progress).
    429
    Too many requests of this account at once, or in the last minutes, or jobs not finished (rate_limited); or the files it stores for links fill its plan's space: Free 256 MB, Pro and Max 2 GB (storage_quota).
    Request
    curl -X POST https://api.reflowpdf.com/v1/jobs/job_Qm9xT2nV8cLp4rWs1dYbZa/webhook \
      -H "Authorization: Bearer $REFLOWPDF_API_KEY"
    200 response
    {
      "id": "job_Qm9xT2nV8cLp4rWs1dYbZa",
      "object": "job",
      "status": "succeeded",
      "created_at": "2026-11-02T10:22:30.114Z",
      "started_at": "2026-11-02T10:22:30.120Z",
      "finished_at": "2026-11-02T10:22:31.402Z",
      "template_id": "invoice",
      "webhook_url": "https://example.com/hooks/reflowpdf",
      "metadata": {
        "order": "42"
      },
      "result": {
        "id": "Hq8vR2cT9xKmL4pW",
        "object": "pdf",
        "url": "https://api.reflowpdf.com/v1/files/Hq8vR2cT9xKmL4pW/Invoice%20INV-1042.pdf",
        "expires_at": "2026-11-03T10:22:31.000Z",
        "filename": "Invoice INV-1042.pdf",
        "pages": 2,
        "bytes": 184213,
        "mark": null,
        "missing_variables": [],
        "skipped_resources": []
      },
      "error": null
    }

    GET /v1/webhook-secret#

    Get the webhook secret

    The secret with which your account's webhooks are signed (ReflowPDF-Signature). For 24 hours after a rotation, deliveries are signed with the previous secret too (a second v1).

    Needs a key with the account scope (scopes).

    Responses

    200
    The secret.
    401
    No API key, or one not valid.
    403
    A claim of the Pro and Max plans (PDF/A, PDF/X, PDF/UA-2) on another plan (plan_required); a key without the scope the route asks for (insufficient_scope), or used from an address it is not kept to (ip_not_allowed).
    Request
    curl https://api.reflowpdf.com/v1/webhook-secret \
      -H "Authorization: Bearer $REFLOWPDF_API_KEY"
    200 response
    {
      "object": "webhook_secret",
      "secret": "whsec_3vK9…",
      "rotated_at": null,
      "previous_expires_at": null
    }

    POST /v1/webhook-secret/rotate#

    Rotate the webhook secret

    A new secret now. For 24 hours deliveries carry a signature with each (the new and the previous) while your receivers move to the new one.

    Needs a key with the account scope (scopes).

    Responses

    200
    The new secret.
    401
    No API key, or one not valid.
    403
    A claim of the Pro and Max plans (PDF/A, PDF/X, PDF/UA-2) on another plan (plan_required); a key without the scope the route asks for (insufficient_scope), or used from an address it is not kept to (ip_not_allowed).
    Request
    curl -X POST https://api.reflowpdf.com/v1/webhook-secret/rotate \
      -H "Authorization: Bearer $REFLOWPDF_API_KEY"
    200 response
    {
      "object": "webhook_secret",
      "secret": "whsec_3vK9…",
      "rotated_at": null,
      "previous_expires_at": null
    }

    GET /v1/usage#

    Get usage

    The account's plan and this period: pages printed without the mark and what is left, AI pages, the files stored for links, and the rate of prints (also on every response as RateLimit-*).

    Needs a key with the account scope (scopes).

    Responses

    200
    The usage.
    401
    No API key, or one not valid.
    403
    A claim of the Pro and Max plans (PDF/A, PDF/X, PDF/UA-2) on another plan (plan_required); a key without the scope the route asks for (insufficient_scope), or used from an address it is not kept to (ip_not_allowed).
    Request
    curl https://api.reflowpdf.com/v1/usage \
      -H "Authorization: Bearer $REFLOWPDF_API_KEY"
    200 response
    {
      "object": "usage",
      "plan": "free",
      "status": null,
      "period_resets_at": "2026-12-01T00:00:00+00:00",
      "pages_printed": 12,
      "pages_without_mark": {
        "limit": 50,
        "used": 12,
        "remaining": 38
      },
      "api_pages": null,
      "ai_pages": {
        "quota": 10,
        "used": 0,
        "top_up": 0,
        "remaining": 10
      },
      "files": {
        "bytes": 1048576,
        "limit_bytes": 268435456
      },
      "rate": {
        "limit": 300,
        "remaining": 298,
        "reset": 431,
        "window": 600,
        "concurrent": 2,
        "active": 0
      }
    }

    GET /v1/engines#

    List engine versions

    The engine versions a print may be pinned to (engine): the current one, and the previous ones, each kept printing until three newer engines have shipped, 30 days at most. Public, from any page.

    Public: no key needed, from any page.

    Responses

    200
    The versions.
    Request
    curl https://api.reflowpdf.com/v1/engines
    200 response
    {
      "object": "list",
      "has_more": false,
      "data": [
        {
          "object": "engine",
          "version": "af4ba3e3b",
          "status": "current",
          "available_until": null
        },
        {
          "object": "engine",
          "version": "866470307",
          "status": "previous",
          "superseded_at": "2026-11-01T06:13:22.000Z",
          "available_until": "2026-12-01T06:13:22.000Z"
        }
      ]
    }

    GET /v1/status#

    The status of the service

    What was measured every minute: each part of the service (the API, printing, the editor, the MCP server, the docs) now, its last 90 days day by day, and its incidents: two minutes or more of failed checks in a row. Public, from any page. The page: https://api.reflowpdf.com/docs/status/.

    Public: no key needed, from any page.

    Responses

    200
    The status.
    Request
    curl https://api.reflowpdf.com/v1/status
    200 response
    {
      "object": "status",
      "checked_at": "2026-11-01T10:22:31.000Z",
      "interval_seconds": 1,
      "status": "operational",
      "components": [
        {
          "id": "string",
          "name": "string",
          "description": "string",
          "status": "operational",
          "uptime_90d": null,
          "latency_ms_24h": {
            "p50": 1,
            "p95": 1
          },
          "days": [
            {
              "date": "string",
              "measured": 1,
              "up": 1,
              "uptime": null
            }
          ]
        }
      ],
      "incidents": [
        {
          "component": "string",
          "name": "string",
          "started_at": "2026-11-01T10:22:31.000Z",
          "ended_at": "2026-11-01T10:22:31.000Z",
          "minutes": 1,
          "error": "string",
          "no_data_after": "2026-11-01T10:22:31.000Z"
        }
      ]
    }

    GET /v1/engine/license#

    Get an engine license token

    The signed token of an engine license, which @reflowpdf/engine checks offline (setLicense). By the license's key alone (public, written into your page; the engine package asks for it itself) the token is valid on the license's sites. With the API key of the license's owner it is also valid where there is no page (Node, Deno, Bun, a desktop app). A token lasts until the paid period ends and a week's grace, 42 days at most: ask again when it nears its end. Allowed from any origin (CORS).

    Parameters

    key query · string required
    The license's key (rpdfl_…), given with the license.

    Public: no key needed, from any page.

    Responses

    200
    The token.
    401
    No API key, or one not valid.
    402
    The license is not paid for, or its subscription has ended.
    404
    No license has this key.
    Request
    curl "https://api.reflowpdf.com/v1/engine/license?key=rpdfl_…" \
      -H "Authorization: Bearer $REFLOWPDF_API_KEY"
    200 response
    {
      "object": "engine_license_token",
      "token": "rpdfl1.eyJ2IjoxLCJraWQiOiJrMSIsImlkIjoibGljXzh…",
      "license": "lic_8Jq2vX0mT4nR7pW1sYc3Ka",
      "licensee": "Northwind Studio Ltd",
      "domains": [
        "northwind.studio",
        "*.northwind.studio"
      ],
      "server": false,
      "expires_at": "2026-12-09T10:00:00.000Z"
    }

    GET /v1/files/{id}/{filename}#

    Download a file

    A PDF, an image or a ZIP of images stored for a link (Accept: application/json, a job, an Idempotency-Key). Its address is its key: keep it private; it works for 24 hours, unless its account deletes it.

    Parameters

    id path · string required
    The file's id, from its link.
    filename path · string required
    The file's name, as its link gives it.

    Needs a key with the print scope (scopes).

    Responses

    200
    The file.
    404
    No such file of this account, or it expired (a file is kept 24 hours).
    Request
    curl https://api.reflowpdf.com/v1/files/Hq8vR2cT9xKmL4pW/Q3%20report.pdf \
      -o "Q3 report.pdf"

    DELETE /v1/files/{id}#

    Delete a file

    Delete a file of your account before its 24 hours: its link stops working, and its space counts no more.

    Parameters

    id path · string required
    The file's id, from its link.

    Needs a key with the print scope (scopes).

    Responses

    200
    Deleted.
    401
    No API key, or one not valid.
    403
    A claim of the Pro and Max plans (PDF/A, PDF/X, PDF/UA-2) on another plan (plan_required); a key without the scope the route asks for (insufficient_scope), or used from an address it is not kept to (ip_not_allowed).
    404
    No such file of this account, or it expired (a file is kept 24 hours).
    Request
    curl -X DELETE https://api.reflowpdf.com/v1/files/Hq8vR2cT9xKmL4pW \
      -H "Authorization: Bearer $REFLOWPDF_API_KEY"
    200 response
    {
      "id": "string",
      "object": "file",
      "deleted": true
    }

    Objects

    FontFamily

    object "font_family" required
    Always font_family.
    family string required
    The family's name, as a document's font-family names it.
    header_format integer required
    1: the faces' headers as small sfnt files.
    faces array of object required
    Its faces: each with its weight, style, SHA-256 and its header (the OpenType tables an engine needs to lay text out before it fetches the face).

    Options

    How the document is printed: every capability of the engine. Each is optional; a wrong value is a 400 naming it.

    paper Paper
    pdf_ua 1 | 2
    Claim PDF/UA: 1 (ISO 14289-1, PDF 1.7) or 2 (ISO 14289-2, PDF 2.0; Pro and Max). Every PDF is tagged unless tagged: false.
    pdf_a "3a" | "1b"
    Claim PDF/A (Pro and Max): 3a: ISO 19005-3, level A (tagged, with PDF/UA-1); 1b: ISO 19005-1, level B (PDF 1.4: transparency flattened to opaque images, text stays selectable). A document that cannot keep the claim is a 422 with the reason.
    pdf_x PdfX
    tagged boolean
    A tagged PDF (structure for screen readers and reflow). false: a smaller untagged file; not with pdf_ua or pdf_a: "3a". Default true.
    title string
    The PDF's title (else the document's <title>, else its first <h1>).
    lang string
    The document's language when its <html lang> names none (BCP 47).
    metadata object
    Over the document's own <meta name="author|description|keywords">.
    header_footer HeaderFooter
    watermark Watermark
    encryption Encryption
    attachments array of Attachment
    Files embedded in the PDF (up to 10 MB together). With pdf_a: "3a" they are PDF/A-3 associated files; not with pdf_a: "1b" or pdf_x, whose standards forbid embedded files.
    compression "fast" | "default" | "smallest"
    Lossless: how hard streams are compressed. Images are never resampled. Default "default".
    object_streams boolean
    Pack objects into object streams (smaller files). false: a classic cross-reference table for readers older than PDF 1.5. Default true.
    color_scheme "light" | "dark"
    The answer to prefers-color-scheme. Default "light".
    default_font_size string
    The size of CSS medium: the document's base font size. Default "12pt".
    print_scale number
    Print the document shrunk by this factor.
    shrink_to_fit boolean
    Shrink a document wider than the paper to fit it, as browsers do. Off by default: lengths stay physical. Default false.
    base_css string
    CSS of yours below the document's own (user-agent origin): defaults the document may override.
    input_format "html" | "xhtml"
    xhtml: parse the document as XML. Default "html".
    base_url string
    Where the document's relative addresses point (an http(s) URL): the document's <base href> unless it names its own.
    javascript boolean
    Run the document's scripts before it prints, over the engine's own document, its layout answering what they measure; the response's scripts says what they did. https://api.reflowpdf.com/docs/javascript/ Default false.
    allow_remote boolean
    Fetch the document's https/http images, stylesheets and fonts (public addresses only). false: print with what it carries. Default true.
    max_pages integer
    Print at most this many pages; the rest is left out.

    PdfX

    Claim PDF/X for a print condition (Pro and Max): its colours, boxes and output intent: a print-ready file.

    standard "x-4" | "x-1a"
    x-4: ISO 15930-7 (PDF 1.6, transparency and RGB kept); x-1a: ISO 15930-4 (PDF 1.4, all colour converted to the condition's inks, transparency flattened; with a CMYK condition). Default "x-4".
    output_intent string required
    A print condition of GET /v1/output-intents (e.g. FOGRA39), or the name of your own profile.
    profile string
    Your printer's characterization: an ICC output profile (class prtr; gray, RGB or CMYK; up to 8 MB), in base64.

    HeaderFooter

    A line of text in the top and bottom margins of every page. CSS @page margin boxes (@top-center { content: … counter(page) }) do the same in the document itself, with full styling.

    header string
    {pageNum} and {totalPages} are replaced on each page.
    footer string
    A line at the foot of each page; {pageNum} and {totalPages} are replaced.
    header_align "left" | "center" | "right"
    Where the header line stands. Default "center".
    footer_align "left" | "center" | "right"
    Where the footer line stands. Default "center".
    font_size string
    A CSS length. Default "7.5pt".
    color string
    A CSS colour.

    Watermark

    A stamp on every page: a text, or an image. Drawn behind the content unless above; marked as an artifact in a tagged PDF.

    text string
    The watermark's text.
    image string
    An https URL or a data: URL of an image (instead of text).
    image_width number
    The image's drawn size in points, with image_height (else its natural size at 96 dpi).
    image_height number
    The image's drawn height in points, with image_width.
    font_size number
    Points. Default 60.
    color string
    A CSS colour.
    opacity number
    From 0 (invisible) to 1 (opaque). Default 0.08.
    angle number
    Degrees, counter-clockwise. Default -45.
    above boolean
    Over the content instead of under it. Default false.
    tile boolean
    Repeat the stamp across the page. Default false.
    tile_spacing array of number
    [x, y] pitch of the tiles, points.
    position object
    One stamp here (points from the page's top-left) instead of the centre.

    Encryption

    Encrypt the PDF (AES-256 by default, ISO 32000-2). Not with PDF/A or PDF/X, whose standards forbid it.

    user_password string
    Asked to open the file; empty or omitted, it opens without one, with the permissions below.
    owner_password string required
    Lifts the permissions.
    permissions array of "print" | "print-high" | "modify" | "copy" | "annotate" | "fill-forms" | "assemble"
    What a reader may do; what is not listed is not allowed. Extraction for accessibility (screen readers) is always allowed (ISO 32000-2, PDF/UA).
    algorithm "aes-256" | "rc4-128"
    rc4-128 only for readers older than Acrobat 9. Default "aes-256".

    Attachment

    filename string required
    The attached file's name.
    content string required
    The file's bytes, base64.
    mime_type string
    Its media type.
    description string
    A line a PDF reader shows beside it.
    relationship "data" | "source" | "alternative" | "supplement" | "unspecified"
    How the file relates to the document (PDF/A-3 AFRelationship). Default "unspecified".
    element string
    The id of the element the file belongs to (a table's data, say); the document when omitted.

    Paper

    The paper where the document's CSS names none, as a user-agent @page rule: each property the document's own @page declares wins over it (its size, its margins). Without either: A4 portrait, 20 mm.

    size string
    A3, A4, A5, B4, B5, Letter, Legal, Ledger, Tabloid, or two lengths, "210mm 297mm". Default "A4".
    orientation "portrait" | "landscape"
    portrait or landscape. Default "portrait".
    margin string
    A CSS margin of lengths. Default "20mm".

    PdfRequest

    html string
    The whole HTML document, with its <style>. Images and fonts by https URL or data: URI. Up to 15 MB.
    url string
    Instead of html: the page's public http(s) address (ports 80/443). It is fetched anonymously (redirects followed, each checked; 20 s, 15 MB) and printed from where it was found (its relative addresses resolve there).
    data object
    When given, html is a template filled with these values first.
    filename string
    The PDF's file name (else the document's <title>).
    options Options
    engine string
    Pin the print to an engine version (GET /v1/engines): the current one, or a previous one, kept printing until three newer engines have shipped and 30 days at most. Without it, the current engine.

    TemplatePdfRequest

    data object
    The values the template reads, in the shape of data_schema (its sample data when omitted).
    filename string
    The file's name: yours, else the document's <title>, else document.
    options Options
    engine string
    Pin the print to an engine version (GET /v1/engines): the current one, or a previous one, kept printing until three newer engines have shipped and 30 days at most. Without it, the current engine.

    ImagesRequest

    html string
    The whole HTML document.
    url string
    Instead of html: the page's public http(s) address (ports 80/443). It is fetched anonymously (redirects followed, each checked; 20 s, 15 MB) and printed from where it was found (its relative addresses resolve there).
    data object
    When given, html is a template filled with these values first.
    filename string
    The images' base name (else the document's <title>).
    options Options
    engine string
    Pin the print to an engine version (GET /v1/engines): the current one, or a previous one, kept printing until three newer engines have shipped and 30 days at most. Without it, the current engine.
    format "png" | "webp"
    Both lossless; WebP is usually smaller. Default "png".
    pages array of integer | string
    The pages, [1, 3] or "1-3,5"; every page when omitted (up to 200).
    dpi number
    Pixels per inch (72 is one per point). Default 150.

    TemplateImagesRequest

    data object
    The template's data (JSON); without it, the template's own sample data.
    filename string
    The file's name: yours, else the document's <title>, else document.
    options Options
    engine string
    Pin the print to an engine version (GET /v1/engines): the current one, or a previous one, kept printing until three newer engines have shipped and 30 days at most. Without it, the current engine.
    format "png" | "webp"
    png (default) or webp, lossless. Default "png".
    pages array of integer | string
    Pages to draw: [1, 3] or "1-3,5"; all when left out.
    dpi number
    Pixels per inch, 18 to 600 (150 by default; 72 is one pixel per point). Default 150.

    LayoutRequest

    html string
    A whole HTML document, its CSS inline or linked.
    url string
    Instead of html: the page's public http(s) address (ports 80/443). It is fetched anonymously (redirects followed, each checked; 20 s, 15 MB) and printed from where it was found (its relative addresses resolve there).
    data object
    The template's data (JSON); without it, the template's own sample data.
    options Options
    engine string
    Pin the print to an engine version (GET /v1/engines): the current one, or a previous one, kept printing until three newer engines have shipped and 30 days at most. Without it, the current engine.

    TemplateLayoutRequest

    data object
    The template's data (JSON); without it, the template's own sample data.
    options Options
    engine string
    Pin the print to an engine version (GET /v1/engines): the current one, or a previous one, kept printing until three newer engines have shipped and 30 days at most. Without it, the current engine.

    Images

    The pages as images, each stored for a link for 24 hours, and the ZIP of them when there are several.

    scripts Scripts
    engine string
    The engine version that printed it.
    id string
    Its id.
    object "images" required
    Always images.
    format "png" | "webp" required
    The images' format.
    dpi number
    The pixels per inch they were drawn at.
    document_pages integer required
    The pages of the document.
    images array of object required
    Each page drawn: its number, link, file name, size in pixels and bytes.
    archive object | null
    With several pages, a ZIP of them: its link and name; else null.
    expires_at string | null
    When the files stop answering at their links (24 hours after they were made), unless deleted first.
    mark string | null
    free-allowance-used when the pages carry the ReflowPDF mark (a Free account past its 50 a month); else null.
    missing_variables array of string
    The template's variables the data did not give, printed empty.
    skipped_resources array of string
    The addresses the print went without: an image, stylesheet or font that could not be fetched.
    missing_glyphs string
    The characters no font had a glyph for, printed as empty boxes; add a font that covers them (@font-face).
    missing_fonts array of string
    The font families the document named that no face here answered: their text took the next family of its list. Give them with @font-face.

    Layout

    Where everything landed: every page's box and every element with an id on each page it is drawn on: its rectangle there, from the page's top-left corner.

    scripts Scripts
    engine string
    The engine version that printed it.
    object "layout" required
    Always layout.
    unit "pt" required
    Every length is in points (1/72 inch), from the page's top-left corner.
    document_pages integer
    The pages of the document.
    pages array of object required
    Each page's number and size.
    elements array of object required
    Each element with an id, on each page it is drawn on: its rectangle there.
    mark string | null
    free-allowance-used when the pages carry the ReflowPDF mark (a Free account past its 50 a month); else null.
    missing_variables array of string
    The template's variables the data did not give, printed empty.
    skipped_resources array of string
    The addresses the print went without: an image, stylesheet or font that could not be fetched.
    missing_glyphs string
    The characters no font had a glyph for, printed as empty boxes; add a font that covers them (@font-face).
    missing_fonts array of string
    The font families the document named that no face here answered: their text took the next family of its list. Give them with @font-face.

    OutputIntent

    id string required
    The output_intent to name.
    object "output_intent" required
    Always output_intent.
    info string
    The profile's description (its ICC desc).
    color_space "Gray" | "RGB" | "CMYK" required
    The colour space of the condition's profile.
    profile_url string
    Its ICC profile, unaltered; public, from any page.

    OutputIntentList

    object "list" required
    Always list.
    data array of OutputIntent required
    The print conditions ReflowPDF provides, by name.
    has_more boolean
    Always false: the whole list is here.

    Scripts

    What the document's scripts did (options.javascript).

    run integer
    Classic scripts run, in the document's order.
    errors array of string
    Their uncaught errors, each with its script (script #3, or its address), up to 50.
    error_count integer
    How many uncaught errors there were (the list keeps 50).
    skipped array of string
    External scripts that could not be fetched (or with the network closed, allow_remote: false).
    modules array of string
    Module scripts (type="module"), which are not run.
    stopped string | null
    The limit that stopped them: their steps, their processor time or 30 s.
    console array of string
    What they wrote to the console, level: text, up to 100.

    EngineList

    object "list" required
    Always list.
    has_more boolean
    Always false: the whole list is here.
    data array of object required
    The current engine and the previous ones a print may be pinned to.

    Status

    object "status" required
    Always status.
    checked_at string | null
    When the last check ran.
    interval_seconds integer
    How often the parts are checked.
    status "operational" | "degraded" | "unknown" required
    unknown: nothing measured in the last 3 minutes.
    components array of object required
    Each part: its state now and its days.
    incidents array of object required
    Two minutes or more of failed checks in a row, newest first.

    PdfPart

    One PDF: file (the id of a PDF of yours stored for a link), pdf (its bytes in base64, within the 15 MB of a request), pdf_url (a public http(s) address of one, up to 100 MB), or a document printed first, as POST /v1/pdf prints it (html, url or template_id, with data, options, filename).

    file string
    A PDF of yours stored for a link: its id from a JSON response (24 hours).
    pdf string
    A PDF's bytes, in base64 (within the 15 MB of a request).
    pdf_url string
    A public address of a PDF, fetched (up to 100 MB, 60 s).
    html string
    A document printed first, as POST /v1/pdf prints it.
    url string
    Instead of html: a public page, fetched and printed.
    template_id string
    Instead of html: a template of the gallery or of your library, by its id.
    data object
    The data of html or template_id as a template.
    options Options
    filename string
    The name the printed part takes.
    pages string
    Some of its pages, in this order: "1-3,5,8-" (8-: to the end).
    password string
    An encrypted PDF's password.
    engine string
    Pin the print to an engine version (GET /v1/engines): the current one, or a previous one, kept printing until three newer engines have shipped and 30 days at most. Without it, the current engine.

    MergeRequest

    parts array of PdfPart required
    The PDFs, in order: up to 50.
    filename string
    The merged PDF's file name (merged.pdf when omitted).

    SplitRequest

    The PDF (as a PdfPart, without pages) and either ranges or every.

    file string
    A PDF of yours stored for a link: its id from a JSON response (24 hours).
    pdf string
    A PDF's bytes, in base64 (within the 15 MB of a request).
    pdf_url string
    A public address of a PDF, fetched (up to 100 MB, 60 s).
    html string
    Instead of a PDF: a document printed first, then split.
    url string
    Instead of html: a public page, fetched and printed.
    template_id string
    Instead of html: a template of the gallery or of your library, by its id.
    data object
    The template's data (JSON); without it, the template's own sample data.
    options Options
    password string
    The password of an encrypted PDF.
    ranges array of string
    Each a new file: ["1-2", "3-"].
    every integer
    A new file every so many pages.
    filename string
    The files' base name.

    CompressRequest

    The PDF (as a PdfPart, without pages), and linearize.

    file string
    A PDF of yours stored for a link: its id from a JSON response (24 hours).
    pdf string
    A PDF's bytes, in base64 (within the 15 MB of a request).
    pdf_url string
    A public address of a PDF, fetched (up to 100 MB, 60 s).
    html string
    Instead of a PDF: a document printed first, then compressed.
    url string
    Instead of html: a public page, fetched and printed.
    template_id string
    Instead of html: a template of the gallery or of your library, by its id.
    data object
    The template's data (JSON); without it, the template's own sample data.
    options Options
    password string
    The password of an encrypted PDF.
    linearize boolean
    Fast web view: its first page shows before the rest has arrived. Default false.
    filename string
    The compressed file's name.

    Split

    id string
    Its id.
    object "split" required
    Always split.
    files array of object required
    Each new file: its pages, link and name.
    archive object | null
    With several files, a ZIP of them; else null.
    expires_at string | null
    When the files stop answering at their links (24 hours after they were made), unless deleted first.
    engine string
    The engine version that printed its source, when it was printed in the same request.

    JobRequest

    Either html, url (with optional data) or template_id (with optional data).

    html string
    The document to print (or url, or template_id).
    url string
    Instead of html: the page's public http(s) address (ports 80/443). It is fetched anonymously (redirects followed, each checked; 20 s, 15 MB) and printed from where it was found (its relative addresses resolve there).
    template_id string
    Instead of html: a template of the gallery or of your library, by its id.
    data object
    The template's data (JSON); without it, the template's own sample data.
    filename string
    The file's name: yours, else the document's <title>, else document.
    options Options
    engine string
    Pin the print to an engine version (GET /v1/engines): the current one, or a previous one, kept printing until three newer engines have shipped and 30 days at most. Without it, the current engine.
    webhook_url string
    An https URL that receives job.succeeded / job.failed.
    metadata object
    Your own keys, returned with the job and its webhook.
    upload object
    Into your own storage: the job PUTs its file to this signed address once printed: an S3 presigned URL, a Google Cloud Storage signed URL, an Azure Blob SAS, R2, any https endpoint that takes a PUT. No credential of your storage is given to us.
    output object
    What the job delivers: a PDF (the default), its pages as images, or the layout.

    Pdf

    scripts Scripts
    engine string
    The engine version that printed it.
    bytes_before integer
    Compress: its size before.
    id string required
    Its id.
    object "pdf" required
    Always pdf.
    url string required
    The PDF, for 24 hours. Its address is its key.
    expires_at string required
    When the files stop answering at their links (24 hours after they were made), unless deleted first.
    filename string required
    The file's name: yours, else the document's <title>, else document.
    pages integer required
    Its pages (counted to the plan).
    bytes integer required
    Its size in bytes.
    mark string | null
    free-allowance-used when printed with the ReflowPDF mark.
    missing_variables array of string
    The template's variables the data did not give.
    skipped_resources array of string
    Images, fonts or stylesheets that could not be fetched (printed without them).
    missing_glyphs string
    The characters no font had a glyph for, printed as empty boxes; add a font that covers them (@font-face).
    missing_fonts array of string
    The font families the document named that no face here answered: their text took the next family of its list. Give them with @font-face.

    Template

    id string required
    The id to print it by: a gallery template's name, or lib_… for one of your library.
    object "template" required
    Always template.
    source "gallery" | "library" required
    library: made in your account's editor.
    name string required
    Its name.
    description string | null
    What it is, in a line (gallery templates).
    category string | null
    Its group in the gallery (gallery templates).
    paper object
    The paper it prints on.
    updated_at string
    When you last changed it (library templates).

    TemplateDetail

    id string required
    The id to print it by: a gallery template's name, or lib_… for one of your library.
    object "template" required
    Always template.
    source "gallery" | "library" required
    library: made in your account's editor.
    name string required
    Its name.
    description string | null
    What it is, in a line (gallery templates).
    category string | null
    Its group in the gallery (gallery templates).
    paper object
    The paper it prints on.
    updated_at string
    When you last changed it (library templates).
    fillable boolean required
    Whether it takes data (a template with {{ … }}); one designed on the page prints as designed.
    html string required
    The template's source.
    sample_data object | null
    Example data: the shape to fill.
    data_schema object | null
    The JSON Schema (2020-12) of its data, read from the sample.

    TemplateList

    object "list" required
    Always list.
    data array of Template required
    The templates of this page.
    has_more boolean required
    Whether more items follow this page: ask again with starting_after set to the last id.

    Job

    id string required
    Its id.
    object "job" required
    Always job.
    status "queued" | "running" | "succeeded" | "failed" required
    A job waits for its account's turn (queued, up to an hour) and survives our restarts; one that could not be run again fails with interrupted.
    created_at string required
    When it was made.
    started_at string
    When the print began; null while queued.
    finished_at string
    When it was done; null until then.
    template_id string | null
    The template it prints, if any.
    webhook_url string | null
    Where its event is sent, if anywhere.
    output object
    What the job delivers.
    webhook object
    How its event was delivered (a job with a webhook_url).
    metadata object
    Up to 20 keys of yours, returned with the job and its webhook.
    result Pdf | Images | Layout | null
    What the job delivered (output): a pdf, images or layout.
    error object | null
    Why it failed (code, title, detail); null unless it did.
    upload object
    How its file went into your storage (a job with an upload). The job stays running until it is there or has failed.

    EngineLicenseToken

    object "engine_license_token" required
    Always engine_license_token.
    token string required
    Give it to the engine: engine.setLicense(token). rpdfl1.<payload>.<Ed25519 signature>.
    license string required
    The license's id.
    licensee string required
    Who the license is billed to, as the token names them.
    domains array of string required
    The sites it prints on without the trial mark; *.example.com names the subdomains of example.com.
    server boolean required
    Also valid where there is no page (asked for with the owner's API key).
    expires_at string required
    When the token ends: the paid period, and a week's grace.

    WebhookSecret

    object "webhook_secret" required
    Always webhook_secret.
    secret string required
    The secret webhooks are signed with (HMAC-SHA256).
    rotated_at string | null
    When it was last rotated; null if never.
    previous_expires_at string | null
    Until when deliveries are also signed with the previous secret.

    JobList

    object "list" required
    Always list.
    data array of Job required
    The jobs of this page, newest first.
    has_more boolean required
    Whether more items follow this page: ask again with starting_after set to the last id.

    Usage

    object "usage" required
    Always usage.
    plan "free" | "pro" | "max" required
    The account's plan.
    status string | null
    The subscription's state (active, past_due, …); null on Free.
    period_resets_at string | null
    When the month's pages begin again.
    pages_printed integer
    Pages printed this period, the API's and the editor's.
    pages_without_mark object
    Of them, the ones without the ReflowPDF mark: a Free account's allowance (past it, pages carry the mark); a paid plan's are all.
    api_pages object | null
    The pages the API laid out this period on a paid plan: the plan's quota (Pro 1,000, Max 5,000), those used, those left, and those past the quota, billed at $5 per 1,000. A document's pages count, also when only some of them are asked as pictures. null on Free, whose API pages are its pages without the mark, and on a Pro or Max subscription started before 14 November 2026, which keeps every API page.
    ai_pages object
    The AI pages of the plan: the month's quota, those used, and those bought on top.
    files object
    The space the files stored for links take, and the plan's limit.
    rate object | null
    Where the account stands in its rate now: as the RateLimit-* headers say.

    WebhookEvent

    id string required
    The event's id: handle one you have seen as done (a delivery can be repeated).
    object "event" required
    Always event.
    type "job.succeeded" | "job.failed" required
    job.succeeded or job.failed.
    created integer required
    Unix seconds.
    data object required
    The job, as GET /v1/jobs/{id} gives it.

    Problem

    RFC 9457 problem details.

    type string required
    The page of the docs about this error.
    title string required
    The problem in a few words.
    status integer required
    The HTTP status.
    detail string
    What happened and what to do.
    code "invalid_request" | "invalid_json" | "template_not_fillable" | "invalid_html" | "template_error" | "unauthorized" | "invalid_api_key" | "license_inactive" | "plan_required" | "not_found" | "template_not_found" | "job_not_found" | "file_not_found" | "license_not_found" | "font_not_found" | "method_not_allowed" | "idempotency_in_progress" | "job_not_finished" | "no_webhook" | "delivery_in_progress" | "insufficient_scope" | "ip_not_allowed" | "license_required" | "document_unreachable" | "engine_unavailable" | "invalid_pdf" | "pdf_encrypted" | "file_expired" | "payload_too_large" | "document_too_large" | "result_too_large" | "unsupported_media_type" | "unfulfillable" | "render_failed" | "idempotency_key_reused" | "rate_limited" | "storage_quota" | "interrupted" | "internal_error" | "engine_busy" | "storage_full" | "render_timeout" required
    Stable, machine-readable: https://api.reflowpdf.com/docs/errors/.
    request_id string required
    Give it to support.