Use the PDF rotate API to rotate pages in a PDF document. The /build endpoint handles the rotate operation. Add the source PDF as a parts item, and add a rotate action.
For signup, pricing, and task-level examples, refer to the PDF rotate API task page.
Rotate a PDF by 90 degrees
The following example rotates all pages in document.pdf clockwise by 90 degrees and writes the output to result.pdf:
curl -X POST https://api.nutrient.io/build \ -H "Authorization: Bearer your_api_key_here" \ -o result.pdf \ --fail \ -F document=@document.pdf \ -F instructions='{ "parts": [ { "file": "document" } ], "actions": [ { "type": "rotate", "rotateBy": 90 } ] }'curl -X POST https://api.nutrient.io/build ^ -H "Authorization: Bearer your_api_key_here" ^ -o result.pdf ^ --fail ^ -F document=@document.pdf ^ -F instructions="{\"parts\": [{\"file\": \"document\"}], \"actions\": [{\"type\": \"rotate\", \"rotateBy\": 90}]}"package com.example.pspdfkit;
import java.io.File;import java.io.IOException;import java.nio.file.FileSystems;import java.nio.file.Files;import java.nio.file.StandardCopyOption;
import org.json.JSONArray;import org.json.JSONObject;
import okhttp3.MediaType;import okhttp3.MultipartBody;import okhttp3.OkHttpClient;import okhttp3.Request;import okhttp3.RequestBody;import okhttp3.Response;
public final class PspdfkitApiExample { public static void main(final String[] args) throws IOException { final RequestBody body = new MultipartBody.Builder() .setType(MultipartBody.FORM) .addFormDataPart( "document", "document.pdf", RequestBody.create( MediaType.parse("application/pdf"), new File("document.pdf") ) ) .addFormDataPart( "instructions", new JSONObject() .put("parts", new JSONArray() .put(new JSONObject() .put("file", "document") ) ) .put("actions", new JSONArray() .put(new JSONObject() .put("type", "rotate") .put("rotateBy", 90) ) ).toString() ) .build();
final Request request = new Request.Builder() .url("https://api.nutrient.io/build") .method("POST", body) .addHeader("Authorization", "Bearer your_api_key_here") .build();
final OkHttpClient client = new OkHttpClient() .newBuilder() .build();
final Response response = client.newCall(request).execute();
if (response.isSuccessful()) { Files.copy( response.body().byteStream(), FileSystems.getDefault().getPath("result.pdf"), StandardCopyOption.REPLACE_EXISTING ); } else { // Handle the error throw new IOException(response.body().string()); } }}using System;using System.IO;using System.Net;using RestSharp;
namespace PspdfkitApiDemo{ class Program { static void Main(string[] args) { var client = new RestClient("https://api.nutrient.io/build");
var request = new RestRequest(Method.POST) .AddHeader("Authorization", "Bearer your_api_key_here") .AddFile("document", "document.pdf") .AddParameter("instructions", new JsonObject { ["parts"] = new JsonArray { new JsonObject { ["file"] = "document" } }, ["actions"] = new JsonArray { new JsonObject { ["type"] = "rotate", ["rotateBy"] = 90 } } }.ToString());
request.AdvancedResponseWriter = (responseStream, response) => { if (response.StatusCode == HttpStatusCode.OK) { using (responseStream) { using var outputFileWriter = File.OpenWrite("result.pdf"); responseStream.CopyTo(outputFileWriter); } } else { var responseStreamReader = new StreamReader(responseStream); Console.Write(responseStreamReader.ReadToEnd()); } };
client.Execute(request); } }}// This code requires Node.js. Do not run this code directly in a web browser.
const axios = require('axios')const FormData = require('form-data')const fs = require('fs')
const formData = new FormData()formData.append('instructions', JSON.stringify({ parts: [ { file: "document" } ], actions: [ { type: "rotate", rotateBy: 90 } ]}))formData.append('document', fs.createReadStream('document.pdf'))
;(async () => { try { const response = await axios.post('https://api.nutrient.io/build', formData, { headers: formData.getHeaders({ 'Authorization': 'Bearer your_api_key_here' }), responseType: "stream" })
response.data.pipe(fs.createWriteStream("result.pdf")) } catch (e) { const errorString = await streamToString(e.response.data) console.log(errorString) }})()
function streamToString(stream) { const chunks = [] return new Promise((resolve, reject) => { stream.on("data", (chunk) => chunks.push(Buffer.from(chunk))) stream.on("error", (err) => reject(err)) stream.on("end", () => resolve(Buffer.concat(chunks).toString("utf8"))) })}import requestsimport json
response = requests.request( 'POST', 'https://api.nutrient.io/build', headers = { 'Authorization': 'Bearer your_api_key_here' }, files = { 'document': open('document.pdf', 'rb') }, data = { 'instructions': json.dumps({ 'parts': [ { 'file': 'document' } ], 'actions': [ { 'type': 'rotate', 'rotateBy': 90 } ] }) }, stream = True)
if response.ok: with open('result.pdf', 'wb') as fd: for chunk in response.iter_content(chunk_size=8096): fd.write(chunk)else: print(response.text) exit()<?php
$FileHandle = fopen('result.pdf', 'w+');
$curl = curl_init();
curl_setopt_array($curl, array( CURLOPT_URL => 'https://api.nutrient.io/build', CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => '', CURLOPT_POSTFIELDS => array( 'instructions' => '{ "parts": [ { "file": "document" } ], "actions": [ { "type": "rotate", "rotateBy": 90 } ] }', 'document' => new CURLFILE('document.pdf') ), CURLOPT_HTTPHEADER => array( 'Authorization: Bearer your_api_key_here' ), CURLOPT_FILE => $FileHandle,));
$response = curl_exec($curl);
curl_close($curl);
fclose($FileHandle);POST https://api.nutrient.io/build HTTP/1.1Content-Type: multipart/form-data; boundary=--customboundaryAuthorization: Bearer your_api_key_here
--customboundaryContent-Disposition: form-data; name="instructions"Content-Type: application/json
{ "parts": [ { "file": "document" } ], "actions": [ { "type": "rotate", "rotateBy": 90 } ]}--customboundaryContent-Disposition: form-data; name="document"; filename="document.pdf"Content-Type: application/pdf
(document data)--customboundary--Rotate by 180 or 270 degrees
The rotateBy value controls the clockwise rotation angle. Supported values are 90, 180, and 270.
Use this instructions object to rotate all pages by 180 degrees:
{ "parts": [ { "file": "document" } ], "actions": [ { "type": "rotate", "rotateBy": 180 } ]}Use this instructions object to rotate all pages by 270 degrees:
{ "parts": [ { "file": "document" } ], "actions": [ { "type": "rotate", "rotateBy": 270 } ]}Rotate a PDF from a URL
For remotely hosted source files, send a JSON request and pass the source URL in parts[].file.url. Use this instructions object:
{ "parts": [ { "file": { "url": "https://example.com/document.pdf" } } ], "actions": [ { "type": "rotate", "rotateBy": 90 } ]}Shell
Run this request to rotate a PDF from a URL:
curl -X POST https://api.nutrient.io/build \ -H "Authorization: Bearer $NUTRIENT_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "parts": [ { "file": { "url": "https://example.com/document.pdf" } } ], "actions": [ { "type": "rotate", "rotateBy": 90 } ] }' \ -o result.pdfRotate selected page ranges
The rotate action applies to the assembled PDF in the request. To rotate only a range of pages, first extract the pages you want to rotate with parts[].pages. Then rotate that output and merge it back into the final document if needed.
The following example extracts pages three through five from document.pdf and rotates only those extracted pages in the output PDF:
{ "parts": [ { "file": "document", "pages": { "start": 3, "end": 5 } } ], "actions": [ { "type": "rotate", "rotateBy": 90 } ]}To create a final PDF that contains both rotated and unrotated sections, process the rotated section first, and then merge it with the other page ranges. For merge workflows, refer to the PDF merge API guide.
Rotate password-protected PDFs
If the source PDF is password-protected, include the password on the part. Use this instructions object:
{ "parts": [ { "file": "protected_document", "password": "document-password" } ], "actions": [ { "type": "rotate", "rotateBy": 90 } ]}Nutrient DWS Processor API uses the password only to open the source document for processing. To set a password on the output PDF, configure output.user_password, output.owner_password, and output.user_permissions.
Combine rotation with other actions
The /build endpoint can assemble a document, rotate it, and then apply additional actions. Actions run in the order specified in the actions array.
The following example merges two PDFs, rotates the assembled document, and then adds a watermark:
{ "parts": [ { "file": "first_half" }, { "file": "second_half" } ], "actions": [ { "type": "rotate", "rotateBy": 90 }, { "type": "watermark", "text": "REVIEW", "width": "50%", "height": "20%", "opacity": 0.3, "rotation": 45 } ]}For workflows that include signing, rotate pages before signing the final PDF.
Reference
A PDF rotate request uses the Build API actions array with a rotate action:
type RotateAction = { type: "rotate",
// Clockwise rotation angle. Supported values are 90, 180, and 270. rotateBy: 90 | 180 | 270,};
type FilePart = { // Multipart field name, or a remote URL object. file: string | { url: string },
// Optional password for encrypted input PDFs. password?: string,
// Optional page range to extract before rotating. pages?: { start?: number, end?: number, },};
type BuildInstructions = { parts: FilePart[], actions: RotateAction[], output?: { type?: "pdf", },};Related API reference operations
- Refer to the build document endpoint API reference for rotating PDFs, selecting page ranges, assembling documents, and applying follow-up actions in a single request.
Related guides
- Refer to the PDF merge API guide.
- Refer to the PDF split API guide.
- Refer to the PDF flatten API guide.
- Refer to the PDF watermark API guide.
- Refer to the PDF security API guide.
- Refer to the tools and APIs guide.