Web - Documents

Free HTML to PDF API Endpoint

The free HTML to PDF API endpoint takes a string of markup and hands back a URL to a rendered PDF. No file bytes come back on that first call. Rendering and collecting are two separate requests, and the link stops serving the document 24 hours later.

  • No API key
  • Two step flow
  • Six page sizes
  • Link expires in 24 hours

Render a PDF

POST/html2pdf

https://aisenseapi.com/services/v1/html2pdf

Render, then download

Post your markup as the data field of a JSON body. The service lays out the document, writes it into temporary storage, and replies with JSON describing where it landed.

curl -X POST https://aisenseapi.com/services/v1/html2pdf \
  -H "Content-Type: application/json" \
  -d '{"data":"<h1>Invoice 4817</h1><p>Paid</p>"}'
{"storage_id":"c853f556-e898-4078-b216-49e58bfe728b","storage_url":"https://aisenseapi.com/services/v1/storage/c853f556-e898-4078-b216-49e58bfe728b","expire_timestamp":1787266021}

That identifier came from one real call and has already expired. Yours will differ on every request, so read the id out of the response and never paste a fixed one into a script.

STORAGE_ID="the storage_id from the response above"
curl -o invoice.pdf "https://aisenseapi.com/services/v1/storage/$STORAGE_ID"

The second request answers with Content-Type: application/pdf and the file itself. The two line invoice above came back as 12766 bytes. No header, token or cookie is needed to collect it.

Every example on this page came from a live call to the free HTML to PDF API endpoint, including the page dimensions further down.

What the free HTML to PDF API endpoint returns

FieldTypeDescription
storage_idstringUUID of the stored file. Useful as a key if you track renders in your own system.
storage_urlstringAbsolute URL of the PDF. A plain GET returns the file with Content-Type: application/pdf.
expire_timestampintegerUnix timestamp in seconds, 24 hours after the render. Past that moment the file is gone and the URL stops serving it.

Nothing else comes back. There is no page count, no byte size and no echo of your markup, so the response keeps the same shape whatever you send it.

Why the answer is a URL and not a file

  1. Render

    The POST returns as soon as the document is written, and the JSON body stays small no matter how large the PDF is. Your code can log the id, queue the download, or hand the link to another process entirely.

  2. Collect

    GET the storage_url whenever you are ready, as often as you like inside the window. This is the same store the Storage API endpoint exposes, so the PDF behaves like any other stored object.

  3. Keep it yourself

    The URL is for collection, not hosting. Anything that must outlive the day it was made has to be downloaded and written somewhere you control. Do not put a storage URL in an invoice email or a database row you expect to still work next week.

Page size, orientation and margins

An optional options object controls the page setup. It sits alongside html, which is an alias for data. Both name the markup to render, and either one works.

curl -X POST https://aisenseapi.com/services/v1/html2pdf \
  -H "Content-Type: application/json" \
  -d '{"html":"<h1>Quarterly report</h1>","options":{"page-size":"A5","orientation":"Landscape","margin-top":"20mm"}}'
OptionAccepted valuesEffect
page-sizeA3, A4, A5, Letter, Legal, TabloidPaper size. Measured from real renders: A4 is 595 by 842 points, A5 landscape 595 by 420, Letter 612 by 792, A3 842 by 1191, Legal 612 by 1008 and Tabloid 792 by 1224.
orientationPortrait, LandscapePage orientation. Landscape swaps the two dimensions of the chosen paper size.
margin-top, margin-bottom, margin-left, margin-rightUp to three digits with an optional mm, cm or in suffix, for example 20mmPage margin on that edge. A bare number is accepted too.

The free HTML to PDF API endpoint checks every value against the list above before the renderer sees it, and anything unrecognised is dropped rather than passed through. Posting {"page-size":"A9","orientation":"Sideways"} renders a normal A4 portrait page instead of failing.

Margins really do repaginate. The same sixty paragraph document rendered with 80mm top and bottom margins produces a longer file than the 5mm version, because less text fits on each page.

One caveat found in testing: millimetre and centimetre values render cleanly, but an inch value such as 1in comes back as an error object rather than a storage_id. Stick to mm or cm.

The renderer never fetches remote assets

Rendering happens in a sandbox with no network access. Anything your markup points at by URL is simply not retrieved.

The proof is easy to reproduce. An <img> aimed at a live 272 by 92 pixel PNG produced a 16 by 16 placeholder inside the PDF. The same trick with a 64 by 64 PNG supplied inline as a data: URI embedded the real image at full size.

So inline everything. Images become data: URIs, styles go in a <style> block in the head, and web fonts are off the table. Structural markup carries the design here: headings, bold, paragraphs and tables all come through.

One more thing worth knowing. An empty or missing markup field is not an error. The call returns HTTP 200 and a valid PDF holding a blank page, so a broken template shows up as an empty document rather than a failed request. Check that your markup is non empty before you post it.

Where the free HTML to PDF API endpoint fits

Invoices and receipts

Fill a template with line items and totals, render it, and file the PDF against the order the moment it is paid.

Printable reports

Take the table a dashboard already renders and turn it into a fixed page a colleague can print, sign or archive.

Email attachments

Convert generated markup into a document before sending, so the recipient opens a file rather than a message that reflows in their client.

Output from an agent

Let a language model write the markup for a summary or a form, then hand back something a human can open and keep.

Privacy and limits

The PDF URL is unauthenticated and holds whatever you rendered. Anyone with the link can read the document until it expires. Do not send personal, financial or confidential material through a public service.

Your markup travels in the POST body rather than the URL, so it never lands in request paths or the logs of intermediate proxies. The rendered file still sits in shared temporary storage for a full day.

The service-wide limit is 5000 requests per IP per 24 hours, with no key and no account behind it. Budget two against that ceiling for every document, since the render and the collect each count.

Every route on the service is catalogued in the free public REST APIs reference. If a render ever looks slow, the Ping API endpoint tells you in one round trip whether the service or your own network is the problem, and the Health Check API endpoint reports the state of the wider platform. Short storage URLs are ugly in printed material, so pass one through the URL Shortener API endpoint if a human has to type it.