Getting a Wialon report as a PDF over the API
Two calls, and four details that quietly break the export: the format bitmask, compress defaulting to 1, errors arriving as JSON at HTTP 200, and one report result per session.

Exporting a report from Wialon by hand is six screens: open Reports, pick the template, pick the unit or the group, set the interval, execute, then Export and choose PDF. Nobody minds doing it once. People mind doing it every Monday for the same four templates.
Over the API it is two calls — and four details that turn a working export into a corrupt file, an empty one, or yesterday's report under today's name.
The two calls
A report is executed with report/exec_report and the result is fetched with report/export_result. The first takes the resource, the template id, the object to run over and the interval; the second takes the format and hands back the bytes of the document Wialon renders itself.
report/exec_report
reportResourceId, reportTemplateId, reportObjectId,
interval: { from, to, flags }
report/export_result
format: 2 // PDF
compress: 0Format is a bitmask, not a name
format is a number, and the numbers are not in an obvious order: 1 is HTML, 2 is PDF, 4 is XLS, 8 is XLSX, 16 is XML and 32 is CSV. Sending the string pdf does not fail loudly; it comes back as something else.
compress defaults to 1
This is the one that costs an afternoon. If compress is not in the request, Wialon zips the document. The response still has a sensible length and still looks like a file, so it lands on disk as report.pdf and every PDF reader refuses it. Send compress: 0 explicitly — a default you did not choose is not a default you can rely on.
A failure arrives as JSON, at HTTP 200
The export endpoint answers with the file's bytes on success and with a JSON error body on failure, both at status 200. A client that trusts the status code writes the error message into a file with a .pdf extension. Read the content type first: if it contains json, parse it, pull out the error code, and report that instead of storing anything.
The same response usually carries no content-disposition header either — and if your request goes through a proxy, the proxy may have dropped it. Build a file name from the template and the interval rather than hoping for one.
One result per session
Wialon holds exactly one report result per session. Execute a second report and the first one is gone. This is why running and exporting has to be a single operation: if anything runs in between — a scheduled job, another tab, an agent exploring — the export hands back whatever ran last, with the file name you asked for. It looks right, and it is the wrong report.
In FleetAI this is one tool rather than two. The assistant cannot run a report and export it as separate steps, because there is no step in between it could survive.
What it is worth
Wialon's own renderer produces the document, so the export is not a table redrawn by somebody else's code — it is the file the Export button produces, with the account's columns, totals and formatting. Asking for it in a sentence instead of six screens does not change the document at all, which is the point.


