/// EDIT
FreeRotate PDF API — fix orientation in one call
Fix orientation on legacy scans in one call.
How does the Rotate PDF API work?
One HTTP request from any language. Every ASHDOCS endpoint uses the same X-API-Key header.
curl -X POST https://www.ashdocs.com/api/v1/tools/rotate \
-H "X-API-Key: ash_live_..." \
-F "files=@scan.pdf" \
-F 'options={"degrees":90}'import requests
r = requests.post(
"https://www.ashdocs.com/api/v1/tools/rotate",
headers={"X-API-Key": "ash_live_..."},
files=[("files", open("scan.pdf", "rb"))],
data={"options": '{"degrees":90}'},
)
job = r.json()
print(job["status"], job["output_files"][0]["url"])import { readFile } from "node:fs/promises";
const form = new FormData();
form.append("files", new Blob([await readFile("scan.pdf")]), "scan.pdf");
form.append("options", JSON.stringify({"degrees":90}));
const res = await fetch("https://www.ashdocs.com/api/v1/tools/rotate", {
method: "POST",
headers: { "X-API-Key": "ash_live_..." },
body: form,
});
const job = await res.json();
console.log(job.status, job.output_files[0].url);using var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-API-Key", "ash_live_...");
using var form = new MultipartFormDataContent();
form.Add(new ByteArrayContent(await File.ReadAllBytesAsync("scan.pdf")), "files", "scan.pdf");
form.Add(new StringContent("{\"degrees\":90}"), "options");
var res = await client.PostAsync("https://www.ashdocs.com/api/v1/tools/rotate", form);
var job = await res.Content.ReadAsStringAsync();
Console.WriteLine(job);import java.io.ByteArrayOutputStream;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
public class Sample {
static final String BOUNDARY = "AshdocsBoundary7MA4YWxkTrZu0gW";
public static void main(String[] args) throws Exception {
ByteArrayOutputStream body = new ByteArrayOutputStream();
addFile(body, "files", "scan.pdf");
addField(body, "options", "{\"degrees\":90}");
body.write(("--" + BOUNDARY + "--\r\n").getBytes(StandardCharsets.UTF_8));
HttpRequest req = HttpRequest.newBuilder(URI.create("https://www.ashdocs.com/api/v1/tools/rotate"))
.header("X-API-Key", "ash_live_...")
.header("Content-Type", "multipart/form-data; boundary=" + BOUNDARY)
.POST(HttpRequest.BodyPublishers.ofByteArray(body.toByteArray()))
.build();
HttpResponse<String> res = HttpClient.newHttpClient().send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(res.body());
}
static void addFile(ByteArrayOutputStream body, String name, String path) throws Exception {
body.write(("--" + BOUNDARY + "\r\nContent-Disposition: form-data; name=\"" + name + "\"; filename=\""
+ Path.of(path).getFileName() + "\"\r\nContent-Type: application/octet-stream\r\n\r\n").getBytes(StandardCharsets.UTF_8));
body.write(Files.readAllBytes(Path.of(path)));
body.write("\r\n".getBytes(StandardCharsets.UTF_8));
}
static void addField(ByteArrayOutputStream body, String name, String value) throws Exception {
body.write(("--" + BOUNDARY + "\r\nContent-Disposition: form-data; name=\"" + name + "\"\r\n\r\n"
+ value + "\r\n").getBytes(StandardCharsets.UTF_8));
}
}#include <stdio.h>
#include <curl/curl.h>
int main(void) {
CURL *curl = curl_easy_init();
if (!curl) return 1;
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "X-API-Key: ash_live_...");
curl_mime *mime = curl_mime_init(curl);
curl_mimepart *part;
part = curl_mime_addpart(mime);
curl_mime_name(part, "files");
curl_mime_filedata(part, "scan.pdf");
part = curl_mime_addpart(mime);
curl_mime_name(part, "options");
curl_mime_data(part, "{\"degrees\":90}", CURL_ZERO_TERMINATED);
curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
curl_easy_setopt(curl, CURLOPT_URL, "https://www.ashdocs.com/api/v1/tools/rotate");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
CURLcode rc = curl_easy_perform(curl);
printf("\n");
curl_mime_free(mime);
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
return rc == CURLE_OK ? 0 : 1;
}Common use cases
- →Scanned document cleanup
- →OCR pre-processing
RELATED TOOLS
Split PDF API — by page, range or count
By page, by range, by count. All headless.
Extract PDF Pages API — keep only what you need
Cherry-pick pages, get a new PDF.
Merge PDF API — combine up to 100 files
Order-preserving, metadata-aware, no page loss.
PDF to Image API — pixel-perfect page rendering
PNG or JPEG, per-page, at 72–600 DPI.