Spool files and fixed-width text, converted to PDF
Your business system still prints column-aligned reports that were written for a line printer loaded with headed paper. This renders that output as a PDF on the same grid, with the headed paper underneath it. One HTTP call, nothing to install.
Invoices, statements, delivery notes, picking lists, usage reports. From SCO OpenServer, AIX, HP-UX, Solaris, AS/400, Linux, or anything else that can pipe text.
What it actually does
Same grid, your stationery
Every character keeps the column it was printed in. The letterhead sits underneath as a separate layer, registered 1:1, so nothing shifts by a fraction of a millimetre against a pre-printed form.
Built for legacy print output
The awkward parts, handled
Converting text to PDF is easy. Converting thirty year old print output and having it still line up is the part that takes work.
Exact fixed-width geometry
Point size, leading, margins and lines per page are yours to set, in points. Columns land where the original put them, so a form overlay registers instead of nearly registering.
Geometry referenceYour letterhead as a canvas
Supply a PDF and the text is laid over it. A two-page canvas gives letterhead on page one and continuation stationery after it, with nothing to configure.
How the canvas worksCode pages that predate Unicode
Box drawing, currency symbols and accented names in cp850, cp437 or anything else. Decoding happens server side, and a wrong code page fails loudly rather than scattering question marks through an invoice.
Encoding optionsForm feeds and page markers
0x0c breaks a page. Ejects at the start and end of the file are understood as ejects, not as blank sheets. You can also start a page at every line carrying a marker, literal or regex.
Pagination optionsPasswords and permissions
AES-256 with user and owner passwords, and per-document control over printing, copying, editing and annotation. Assistive extraction is never withheld.
Security optionsNothing to install
No binary per platform, no licence per CPU, no Perl, no runtime on the host. If the box can reach an HTTPS endpoint with curl, it can produce PDFs.
Code examplesNo account, no key
Paste a report, get a PDF
Edit the text or the settings and render it. This is the same endpoint the examples below call.
Start here
One call, from wherever the report lives
# Attach the report and your letterhead curl -X POST https://api.spool2pdf.app/api/render \ -H 'X-Api-Key: YOUR_KEY' \ -F text=@invoice.txt \ -F canvas=@letterhead.pdf \ -F encoding=cp850 \ -F pointSize=9 \ -o invoice.pdf
# The body is the document; options go in the query string. # Anything that can print to stdout can produce a PDF. acctrpt -m 08 -y 26 | curl --data-binary @- \ 'https://api.spool2pdf.app/api/render?paper=A4&pointSize=9&encoding=cp850' \ -H 'X-Api-Key: YOUR_KEY' \ -o statements.pdf
$form = @{ text = Get-Item '.\invoice.txt' canvas = Get-Item '.\letterhead.pdf' encoding = 'cp850' pointSize = 9 } Invoke-RestMethod 'https://api.spool2pdf.app/api/render' -Method Post ` -Headers @{ 'X-Api-Key' = $env:SPOOL2PDF_KEY } ` -Form $form -OutFile 'invoice.pdf'
import requests files = { "text": open("invoice.txt", "rb"), "canvas": open("letterhead.pdf", "rb"), } r = requests.post( "https://api.spool2pdf.app/api/render", headers={"X-Api-Key": KEY}, files=files, data={"encoding": "cp850", "pointSize": "9"}, ) r.raise_for_status() open("invoice.pdf", "wb").write(r.content)
$ch = curl_init('https://api.spool2pdf.app/api/render'); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ['X-Api-Key: ' . $key], CURLOPT_POSTFIELDS => [ 'text' => new CURLFile('invoice.txt'), 'canvas' => new CURLFile('letterhead.pdf'), 'encoding' => 'cp850', 'pointSize' => '9', ], ]); file_put_contents('invoice.pdf', curl_exec($ch));
// For connector and low-code platforms that cannot post raw bytes. POST https://api.spool2pdf.app/api/render Content-Type: application/json { "textBase64": "<base64 of the raw file bytes>", "canvasBase64": "<base64 of the letterhead PDF>", "encoding": "cp850", "options": { "paper": "A4", "pointSize": 9, "splitOn": "STATEMENT NO", "title": "August statements" } }
The response is the PDF itself, with the page count in an
X-Pdf-Pages header. Ask for ?response=json if you
would rather have it base64 encoded in an envelope.
Full reference.
Who this is for
People who inherited the system
The last person who understands it
The report generator was written before you arrived and nobody wants to touch it. You do not need to. Pipe its output somewhere else and leave the program alone.
Anyone getting off pre-printed stationery
Boxes of headed continuous paper are expensive, and the printer that takes it is one failure from retirement. Scan the stationery once, use it as the canvas, print on plain paper or email the PDF.
Teams replacing a per-CPU licence
Conversion tools in this space are still sold per physical core, with an annual maintenance percentage on top, and a binary to install on every machine. This is an HTTP call.
Anyone automating around a green screen
Power Automate, Logic Apps, cron, a shell script on the ERP box. The API is stateless, so it does not care which of those is calling or in what order.
Questions people actually ask
Converting legacy print output
What is a spool file?
The print stream a program produces before it reaches a printer, held in a
queue. On UNIX it is what lp or lpr receives; on
IBM midrange systems it is a spooled file in an output queue. It is plain
text laid out in fixed columns, usually with form feed characters marking
page breaks and often with printer control codes mixed in. It is designed
to be printed, not read on screen, which is why converting it naively
looks wrong.
Why does my report lose its alignment when converted to PDF?
Because most converters treat the text as prose and set it in a proportional font, where an "i" is narrower than an "m". Fixed-width reports encode meaning in the column a character sits in, so the moment the font stops being monospaced the columns fan out and the totals stop lining up with their headings. The fix is a monospace font plus explicit control of point size, leading and margins, so a character lands where the line printer would have put it.
How do I put our letterhead behind existing print output?
Supply the letterhead as a PDF and it becomes the canvas the text is drawn over. Nothing about the report changes: the text is a separate layer, placed 1:1, so it registers against a pre-printed design instead of floating near it. If the canvas has two pages, the first backs page one and the second backs everything after it, which is the usual invoice shape.
My report has box-drawing characters that come out as garbage. Why?
Older print streams are single-byte and usually cp850 in Europe or cp437
in the US, not UTF-8. The bytes that draw boxes and print currency symbols
in those code pages mean something else entirely elsewhere, so decoding
them as UTF-8 produces either replacement characters or an error. Set the
encoding option to the code page the system actually emits.
Box-drawing characters additionally need a monospace font that contains
those glyphs, which you can supply as a font file.
How do I convert AS/400, SCO, AIX or HP-UX print output?
The same way in every case: get the text out of the queue and post it. On UNIX that is usually a pipe from the program or a copy of the spool file; on IBM midrange systems it is a spooled file copied to a stream file first. Nothing is installed on the host, so an operating system that no longer receives updates is not a blocker, provided it can make an HTTPS request or hand the file to something that can.
Can I split one print run into separate documents?
Yes. Set splitOn to the marker each document starts with, for
example a statement number heading, and a new page begins at every line
carrying it. Combined with page selection you can render a slice of a run
and merge the parts downstream, and the page numbering stays stable across
those calls so the pieces fit back together.
What happens to form feeds and blank pages?
A form feed character starts a new page. Ejects at the very start and end of a file are treated as what they are, an instruction to move the paper, rather than as blank sheets, so a file that begins by ejecting to top of form does not gain an empty page in front of it. Blank pages in the middle are kept, because those are usually deliberate.
Is my data stored?
No. The renderer is stateless. The text, the canvas and the options all arrive with the request, the PDF goes back in the response, and nothing is written to disk or kept afterwards. There are no stored templates to manage, which also means there is nothing to migrate if you move.
Pricing
Free while it is in beta
The service is new. It is free to use while that is true, and there is no card and no account to create. If you are planning to depend on it, say so and we will talk about what that should look like.
Beta
- No account, no card
- Every option available
- Fair-use rate limiting
- Best effort, no SLA
Production
- Committed availability
- Higher rate limits
- Help tuning your templates
- Named contact