PDF-to-Office API
Use the PDF-to-Office API to convert PDF documents to editable Office files. Nutrient DWS Processor API supports these output formats:
- DOCX for Microsoft Word
- XLSX for Microsoft Excel
- PPTX for Microsoft PowerPoint
The /build endpoint handles PDF-to-Office conversion. Add the source PDF as a parts item, and set output.type to the Office format you want.
For signup, pricing, and task-level examples, refer to the PDF-to-Office API task page.
Convert a PDF to Word
The following example converts document.pdf to result.docx:
curl -X POST https://api.nutrient.io/build \ -H "Authorization: Bearer your_api_key_here" \ -o result.docx \ --fail \ -F document=@document.pdf \ -F instructions='{ "parts": [ { "file": "document" } ], "output": { "type": "docx" } }'curl -X POST https://api.nutrient.io/build ^ -H "Authorization: Bearer your_api_key_here" ^ -o result.docx ^ --fail ^ -F document=@document.pdf ^ -F instructions="{\"parts\": [{\"file\": \"document\"}], \"output\": {\"type\": \"docx\"}}"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("output", new JSONObject() .put("type", "docx") ).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.docx"), 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" } }, ["output"] = new JsonObject { ["type"] = "docx" } }.ToString());
request.AdvancedResponseWriter = (responseStream, response) => { if (response.StatusCode == HttpStatusCode.OK) { using (responseStream) { using var outputFileWriter = File.OpenWrite("result.docx"); 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" } ], output: { type: "docx" }}))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.docx")) } 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' } ], 'output': { 'type': 'docx' } }) }, stream = True)
if response.ok: with open('result.docx', 'wb') as fd: for chunk in response.iter_content(chunk_size=8096): fd.write(chunk)else: print(response.text) exit()<?php
$FileHandle = fopen('result.docx', '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" } ], "output": { "type": "docx" } }', '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" } ], "output": { "type": "docx" }}--customboundaryContent-Disposition: form-data; name="document"; filename="document.pdf"Content-Type: application/pdf
(document data)--customboundary--Convert a PDF to Excel
Set output.type to xlsx to convert a PDF to an Excel workbook. Use this instructions object:
{ "parts": [ { "file": "document" } ], "output": { "type": "xlsx" }}curl -X POST https://api.nutrient.io/build \ -H "Authorization: Bearer your_api_key_here" \ -o result.xlsx \ --fail \ -F document=@document.pdf \ -F instructions='{ "parts": [ { "file": "document" } ], "output": { "type": "xlsx" } }'curl -X POST https://api.nutrient.io/build ^ -H "Authorization: Bearer your_api_key_here" ^ -o result.xlsx ^ --fail ^ -F document=@document.pdf ^ -F instructions="{\"parts\": [{\"file\": \"document\"}], \"output\": {\"type\": \"xlsx\"}}"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("output", new JSONObject() .put("type", "xlsx") ).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.xlsx"), 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" } }, ["output"] = new JsonObject { ["type"] = "xlsx" } }.ToString());
request.AdvancedResponseWriter = (responseStream, response) => { if (response.StatusCode == HttpStatusCode.OK) { using (responseStream) { using var outputFileWriter = File.OpenWrite("result.xlsx"); 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" } ], output: { type: "xlsx" }}))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.xlsx")) } 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' } ], 'output': { 'type': 'xlsx' } }) }, stream = True)
if response.ok: with open('result.xlsx', 'wb') as fd: for chunk in response.iter_content(chunk_size=8096): fd.write(chunk)else: print(response.text) exit()<?php
$FileHandle = fopen('result.xlsx', '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" } ], "output": { "type": "xlsx" } }', '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" } ], "output": { "type": "xlsx" }}--customboundaryContent-Disposition: form-data; name="document"; filename="document.pdf"Content-Type: application/pdf
(document data)--customboundary--Convert a PDF to PowerPoint
Set output.type to pptx to convert a PDF to a PowerPoint presentation. Use this instructions object:
{ "parts": [ { "file": "document" } ], "output": { "type": "pptx" }}curl -X POST https://api.nutrient.io/build \ -H "Authorization: Bearer your_api_key_here" \ -o result.pptx \ --fail \ -F document=@document.pdf \ -F instructions='{ "parts": [ { "file": "document" } ], "output": { "type": "pptx" } }'curl -X POST https://api.nutrient.io/build ^ -H "Authorization: Bearer your_api_key_here" ^ -o result.pptx ^ --fail ^ -F document=@document.pdf ^ -F instructions="{\"parts\": [{\"file\": \"document\"}], \"output\": {\"type\": \"pptx\"}}"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("output", new JSONObject() .put("type", "pptx") ).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.pptx"), 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" } }, ["output"] = new JsonObject { ["type"] = "pptx" } }.ToString());
request.AdvancedResponseWriter = (responseStream, response) => { if (response.StatusCode == HttpStatusCode.OK) { using (responseStream) { using var outputFileWriter = File.OpenWrite("result.pptx"); 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" } ], output: { type: "pptx" }}))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.pptx")) } 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' } ], 'output': { 'type': 'pptx' } }) }, stream = True)
if response.ok: with open('result.pptx', 'wb') as fd: for chunk in response.iter_content(chunk_size=8096): fd.write(chunk)else: print(response.text) exit()<?php
$FileHandle = fopen('result.pptx', '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" } ], "output": { "type": "pptx" } }', '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" } ], "output": { "type": "pptx" }}--customboundaryContent-Disposition: form-data; name="document"; filename="document.pdf"Content-Type: application/pdf
(document data)--customboundary--Convert 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" } } ], "output": { "type": "docx" }}Shell
Run this request to convert 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" } } ], "output": { "type": "docx" } }' \ -o result.docxConvert selected PDF pages
Use parts[].pages to convert only a page range from the source PDF. Page indexes are zero-based, and negative values count from the end of the document.
The following example converts only the first three pages to Word:
{ "parts": [ { "file": "document", "pages": { "start": 0, "end": 2 } } ], "output": { "type": "docx" }}The end value is inclusive, so { "start": 0, "end": 2 } includes pages zero, one, and two.
Convert 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" } ], "output": { "type": "docx" }}Nutrient DWS Processor API uses the password only to open the source document for processing.
Choose an output format
Choose the Office output format that matches your downstream workflow.
| Output type | File extension | Use when |
|---|---|---|
docx | .docx | You need editable text, paragraphs, headings, or general document layout in Microsoft Word. |
xlsx | .xlsx | You need spreadsheet-style output, tables, or tabular content in Microsoft Excel. |
pptx | .pptx | You need slide-based output in Microsoft PowerPoint. |
PDF-to-Office conversion reconstructs editable Office content from a fixed-layout PDF. Complex layouts, scanned pages, or image-only PDFs may require OCR or manual review, depending on your quality requirements.
Combine PDF-to-Office with other processing
The /build endpoint can assemble or prepare a PDF before it converts the file to Office. For example, you can merge two PDF files and convert the merged output to DOCX.
Use this instructions object to merge two PDFs and convert them to Word:
{ "parts": [ { "file": "cover" }, { "file": "body" } ], "output": { "type": "docx" }}You can also extract selected pages before conversion with parts[].pages.
Reference
A PDF-to-Office request uses the Build API output object with an Office output type:
type OfficeOutput = { // Office output file type. type: "docx" | "xlsx" | "pptx",};
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 convert. pages?: { start?: number, end?: number, },};
type BuildInstructions = { parts: FilePart[], output: OfficeOutput,};Related API reference operations
- Refer to the build document endpoint API reference to convert PDFs to DOCX, XLSX, or PPTX and combine conversion with page selection or document assembly.
Related guides
- Refer to the Office-to-PDF API guide.
- Refer to the PDF-to-image API guide.
- Refer to the PDF-to-HTML API guide.
- Refer to the PDF-to-Markdown API guide.
- Refer to the PDF OCR API guide.
- Refer to the PDF merge API guide.
- Refer to the PDF split API guide.
- Refer to the tools and APIs guide.