DEV Community

Cover image for Rotating One Page 90 Degrees Without Rotating the Other Seventy-Nine
PDF4me
PDF4me

Posted on

Rotating One Page 90 Degrees Without Rotating the Other Seventy-Nine

Somewhere in your document pipeline is an 80-page PDF where page 47 is sideways. Maybe it came off a scanner that fed one sheet in landscape by mistake. Maybe a contractor emailed you a signed page as a photo and someone slotted it into the packet without checking orientation. Whatever the cause, the fix looks trivial until you go looking for the endpoint to do it, and find two that both promise to rotate a PDF.

That's not a documentation accident. PDF4me ships two separate rotation endpoints on purpose, because "rotate this PDF" is actually two different jobs that only look like one.

Two endpoints, one word

Rotate Document takes a PDF and a rotation direction, and applies that rotation to every page in the file. There's no page selector, because there doesn't need to be one. This endpoint exists for when the whole document came in wrong: a batch scan that fed sideways from the first sheet to the last, or an entire report exported in the wrong orientation.

Rotate Page takes the same file and rotation direction, plus one more field: a page selector. It accepts individual page numbers, ranges, or a mix of both, and page indices start from 1. This is the endpoint for the 80-page contract with one sideways page, or any job where "rotate the whole thing" would introduce 79 new orientation problems to fix the one you actually had.

The docs and the sample code don't quite agree, and it's worth knowing why

A quick, honest note before any code: the docs pages for both endpoints describe rotationType as a numeric angle (90, 180, 270, -90), and Rotate Page's selector field as pages (plural). The actual working Python samples in pdf4me/pdf4me-api-samples tell a different story: rotationType takes a named string (Clockwise, CounterClockwise, UpsideDown, NoRotation), the page selector is page (singular), and Rotate Document's sample posts to /api/v2/Rotate, not the /api/v2/RotateDocument path the docs page states.

This piece follows the sample repo's field names throughout, since that's what a copy-pasted, running request actually needs. Both discrepancies are worth flagging to your own team if you're referencing the docs page directly instead of starting from the sample code.

Rotate Page, the code

This is trimmed from the official sample repo's Rotate Page Python sample, keeping the request shape intact:

import base64, requests, json

api_key = "get the API key from https://dev.pdf4me.com/dashboard/#/api-keys"
url = "https://api.pdf4me.com/api/v2/RotatePage"

with open("sample.pdf", "rb") as f:
    pdf_base64 = base64.b64encode(f.read()).decode("utf-8")

payload = {
    "docContent": pdf_base64,
    "docName": "output.pdf",
    "rotationType": "Clockwise",   # NoRotation, Clockwise, CounterClockwise, UpsideDown
    "page": "47",                  # e.g. "1", "1,3,5", or "2-4"
    "isAsync": True
}
headers = {"Content-Type": "application/json", "Authorization": api_key}

response = requests.post(url, headers=headers, data=json.dumps(payload))

if response.status_code == 200:
    with open("Rotate_page_PDF_output.pdf", "wb") as out:
        out.write(response.content)
elif response.status_code == 202:
    # Async job accepted, poll the Location header until it returns 200
    location_url = response.headers.get("Location")
Enter fullscreen mode Exit fullscreen mode

One page targeted, 79 left alone.

Rotate Document, the code

Same shape, no page selector, and note the endpoint path difference called out above:

import base64, requests, json

api_key = "get the API key from https://dev.pdf4me.com/dashboard/#/api-keys"
url = "https://api.pdf4me.com/api/v2/Rotate"  # not /RotateDocument, see note above

with open("sample.pdf", "rb") as f:
    pdf_base64 = base64.b64encode(f.read()).decode("utf-8")

payload = {
    "docContent": pdf_base64,
    "docName": "output.pdf",
    "rotationType": "UpsideDown",  # NoRotation, Clockwise, CounterClockwise, UpsideDown
    "isAsync": True
}
headers = {"Content-Type": "application/json", "Authorization": api_key}

response = requests.post(url, headers=headers, data=json.dumps(payload))

if response.status_code == 200:
    with open("Rotate_document_PDF_output.pdf", "wb") as out:
        out.write(response.content)
Enter fullscreen mode Exit fullscreen mode

Same direction values, same async pattern, every page instead of one.

Reading the parameters correctly

Both endpoints need a valid API key in the Authorization header, the same key you'd use for any other PDF4me REST call. Where they diverge is scope of effect: Rotate Document's rotation applies uniformly, once, to the entire file. Rotate Page's rotation applies only to the pages you list in page, every other page passes through untouched. Both sample scripts set isAsync: true, which is worth keeping: PDF4me returns a 202 with a polling Location header while it processes, rather than making the request hang open until the file is ready.

Where this fits in a real pipeline

Rotation rarely happens in isolation. It's usually one step in a document intake pipeline: a scan comes in, PDF4me straightens the orientation, then downstream steps handle OCR, data extraction, or filing. If you're already using PDF4me's low-code connectors, both rotation endpoints are available as native actions, not just REST calls you have to wire up yourself.

In Power Automate, Rotate Document and Rotate Page are separate flow actions, so the same whole-document-versus-selective-page decision applies there too. In Make, the equivalent modules are Rotate Pages (document-wide) and Rotate a Single Page (selective). Zapier splits the same way, with Rotate all Pages of a PDF for the whole-document case and Rotate a Single PDF Page in Zapier built specifically for the one-page fix. In n8n, both Rotate Document and Rotate PDF Page are nodes you can drop straight into a workflow.

If you want to see either endpoint's request and response shape before wiring it into a flow, the API Tester docs cover both: Rotate Document in the API Tester and Rotate PDF Page in the API Tester walk through sending a live request and inspecting what comes back.

The response, and what rotation does and doesn't touch

Both endpoints return the rotated PDF as binary output when the request completes synchronously (status 200), which is exactly what the samples above write straight to disk. Neither endpoint re-renders or re-compresses page content to perform the rotation. It's a page-level transform, not a re-flatten, so rotation on its own shouldn't introduce visible quality loss the way a lossy image re-encode would.

That said, rotation is often the first step in a chain, not the last. If your pipeline follows rotation with OCR, keep in mind that OCR accuracy depends on the page being right-side-up at the time it runs, not eventually. Rotate before you extract text, not after. An OCR pass against a sideways page will produce garbage regardless of how correct the final stored file looks.

One more place this distinction matters: images, not just PDFs

If your intake pipeline handles scanned images before they're ever assembled into a PDF, PDF4me has an equivalent pair for image files. Rotate Image rotates a standalone image by a specified angle, and Rotate Image by EXIF Data auto-corrects orientation using the EXIF metadata a camera or scanner already embedded in the file, useful when you're processing photos of documents rather than clean scans. Both are available in Make (Rotate an Image, Auto-Rotate Images by EXIF Data), Zapier (Rotate Image), and n8n (Rotate Image, Rotate Image By EXIF Data), and documented in the API Tester too (Rotate Image by EXIF Data).

The actual decision

Strip away the parameter tables and it comes down to one question, asked before you write a line of integration code: is the whole document wrong, or is one page wrong? Whole document, Rotate Document, one direction, applied uniformly, done in a single call. One page, or a handful scattered through a longer file, Rotate Page, with the page field doing the targeting so you're not rotating, re-splitting, or re-merging anything by hand.

It's a small distinction. It's also the difference between a one-call fix and an unnecessary multi-step workaround, and that gap matters more the larger your document volume gets. A pipeline processing a handful of PDFs a day can absorb an inefficient rotation step without anyone noticing. One processing thousands can't.


Website: pdf4me.com
Documentation: docs.pdf4me.com
Developer portal: dev.pdf4me.com

Top comments (0)