ReflowPDF API api.reflowpdf.com/v1

    SDKs

    Typed clients that retry, wait and verify for you.

    JavaScript and TypeScript#

    npm install @reflowpdf/sdk

    ESM and CommonJS, Node 18+, Deno, Bun and edge runtimes; types included.

    import { ReflowPDF, ReflowPDFError, attachment } from '@reflowpdf/sdk'
    
    const reflow = new ReflowPDF({ apiKey: process.env.REFLOWPDF_API_KEY, maxRetries: 3 })
    
    try {
      const pdf = await reflow.templates.pdf('invoice', { data })   // { bytes, pages, filename, missingVariables, requestId }
      const link = await reflow.pdf.createLink({ html })             // { url, expires_at, pages, … }
      const job = await reflow.jobs.create({ html, webhook_url })
      const { images } = await reflow.images.create({ html, pages: '1-2', dpi: 200 })   // [{ page, bytes, filename, width, height }]
      const layout = await reflow.layout.create({ html })                             // { pages, elements }
      const { data: recent } = await reflow.jobs.list({ status: 'failed' })
      const usage = await reflow.usage.get()                                          // { plan, pages_without_mark, files, rate }
      const archive = await reflow.pdf.create({ html, options: { pdf_a: '3a', attachments: [attachment('data.csv', csv, { relationship: 'data' })] } })
    } catch (e) {
      if (e instanceof ReflowPDFError) console.error(e.status, e.code, e.detail, e.requestId)
    }

    Python#

    pip install reflowpdf

    Python 3.9+; a synchronous and an asynchronous client (the asynchronous one runs each request in a thread of the standard library: cancelling it stops the waiting, not a print already sent).

    from reflowpdf import ReflowPDF, AsyncReflowPDF, APIError, attachment
    
    client = ReflowPDF(max_retries=3)  # REFLOWPDF_API_KEY from the environment
    
    try:
        pdf = client.templates.pdf("invoice", data=data)   # .content, .pages, .filename, .missing_variables
        job = client.jobs.create(html=html, webhook_url=hook)
        client.images.create(html=html, pages="1-2", dpi=200).save("previews/")  # page PNGs
        layout = client.layout.create(html=html)                                # .pages, .elements
        recent = client.jobs.list(status="failed").data
        usage = client.usage.get()                                              # .plan, .pages_without_mark, .files, .rate
        client.pdf.create(html=html, options={"pdf_a": "3a", "attachments": [attachment("data.csv", csv, relationship="data")]})
    except APIError as e:
        print(e.status, e.code, e.detail, e.request_id)
    
    async with AsyncReflowPDF() as reflow:
        pdf = await reflow.pdf.create(html=html)

    What they do#

    • Retry 429 and 5xx answers and network failures (2 times by default), waiting Retry-After, with an Idempotency-Key so a retried request prints once; but not a 5xx that would only repeat: a print over its time (render_timeout), a store that cannot keep files (storage_full), an account whose files fill its space (429 storage_quota). A 409 idempotency_in_progress of their own key is waited out; other 4xx answers are not retried.
    • Raise one error type with status, code, title, detail and request_id.
    • jobs.wait(id) polls a job until it is done; verifyWebhook (async, Web Crypto) / verify_webhook checks a webhook's signature.
    • Every endpoint: pdf (with merge, split, compress and their …Link forms), images (a ZIP of several pages is opened for you, in page order), layout, templates (with pdf, images, layout of each), jobs (create, get, list, redeliver, wait), webhooks (secret, rotate), files.delete, usage.get, engines.list, outputIntents / output_intents; every option typed (TypeScript) or documented (Python); attachment() makes an attachment of bytes or text; on each result what the print went without: missingVariables, skippedResources, missingGlyphs, missingFonts (missing_… in Python).
    • No dependencies: the JavaScript SDK uses the platform's fetch and Web Crypto, the Python SDK only the standard library.

    Any other language#

    The API is described by OpenAPI 3.1: generate a client with openapi-generator, or import it into Postman or Insomnia.