Server API for Documents
PSPDFKit Server provides the following API endpoints for working with documents:
Overview
Document Creation
Document Editing
Document Deletion
Retrieving Document Information
Importing and Exporting
-
Importing Instant JSON and Downloading the Resulting PDF File
-
Importing Instant JSON and Persisting the Resulting PDF File
Other Endpoints
Document Creation
Uploading a Document
To create a new document from a PDF file, POST
its contents to /api/document
, specifying the application/pdf
content type:
Request
POST /api/documents Content-Type: application/pdf Authorization: Token token="<secret token>" <PDF data>
$ curl http://localhost:5000/api/documents \ -X POST \ -H "Authorization: Token token=<secret token>" \ -H "Content-Type: application/pdf" \ -T document.pdf
Response
HTTP/1.1 200 OK Content-Type: application/json { "data": { "document_id": ..., "errors": [], "sourcePdfSha256": ..., "title": "..." } }
PSPDFKit Server will extract the title of the document from the PDF metadata if it is present.
The errors
list will be non-empty if errors were encountered when importing annotations from the document. Each error will have the format {"reason": "Error description"}
.
If you need to upload a large file (e.g. one more than 50 MB), you should consider streaming the file contents using chunked transfer encoding to avoid potential issues resulting from the request body size:
Request
POST /api/documents Content-Type: application/pdf Authorization: Token token="<secret token>" Transfer-Encoding: chunked Content-Length: 105255200 <PDF data>
$ curl http://localhost:5000/api/documents \ -X POST \ -H "Authorization: Token token=<secret token>" \ -H "Content-Type: application/pdf" \ -H "Transfer-Encoding: chunked" \ -H "Content-Length: 105255200" \ -T document.pdf
Response
HTTP/1.1 200 OK Content-Type: application/json { "data": { "document_id": ..., "errors": [], "sourcePdfSha256": ..., "title": "..." } }
PSPDFKit Server also supports uploading files as multipart/form-data
. The part of the body containing the PDF file must be called file
. When using this method, the server will try reading the title from the PDF metadata and fall back to the file name if the metadata isn’t available.
Request
POST /api/documents Content-Type: multipart/form-data; boundary=customboundary Authorization: Token token="<secret token>" --customboundary Content-Disposition: form-data; name="file"; filename="Example Document.pdf" Content-Type: application/pdf <PDF data> --customboundary--
Providing Your Own ID for Documents
As of version 2018.6, PSPDFKit Server supports providing an arbitrary document_id
on upload. This can be useful when you want to use your own identifiers for documents. This feature can also be used to migrate from an existing document management solution on demand, as we explained in the document migration guide:
Request
POST /api/documents Content-Type: multipart/form-data; boundary=customboundary Authorization: Token token="<secret token>" --customboundary Content-Disposition: form-data; name="document_id" your_document_identifier_1 --customboundary Content-Disposition: form-data; name="file"; filename="Example Document.pdf" Content-Type: application/pdf <PDF data> --customboundary--
$ curl -X POST http://localhost:5000/api/documents/ \ -H "Authorization: Token token=<secret token>" \ -F "file=@example.pdf" \ -F "document_id=your_document_identifier_1"
Providing Your Own Title for Documents
As of version 2019.2, PSPDFKit Server supports providing an arbitrary title
on upload, which will override the title included in the PDF document (if present):
Request
POST /api/documents Content-Type: multipart/form-data; boundary=customboundary Authorization: Token token="<secret token>" --customboundary Content-Disposition: form-data; name="title" My custom title --customboundary Content-Disposition: form-data; name="file"; filename="Example Document.pdf" Content-Type: application/pdf <PDF data> --customboundary--
$ curl -X POST http://localhost:5000/api/documents/ \ -H "Authorization: Token token=<secret token>" \ -F "file=@example.pdf" \ -F "title=My custom title"
ℹ️ Note: The title specified here will not be embedded in the PDF. If you download the PDF, the original title will still be shown. In place of the
title
upload parameter, you can supply anupdateMetadata
operation during document upload. This will actually embed the title in the PDF.
Applying Operations on Document Upload
As of version 2020.4, PSPDFKit Server supports providing a list of document operations that will be applied on upload:
POST /api/documents Content-Type: multipart/form-data; boundary=customboundary Authorization: Token token="<secret token>" --customboundary Content-Disposition: form-data; name="operations" { "operations": [ { "type": "performOcr", "language": "english", "pageIndexes": [0] } ] } --customboundary Content-Disposition: form-data; name="file"; filename="Example Document.pdf" Content-Type: application/pdf <PDF data> --customboundary--
If you apply operations on upload, you will be able to download the unmodified PDF using the source=true
parameter, as described here. Keep in mind that after applying the operations, the PDF will be stored in your selected storage backend. This means that when uploading a document from a URL like what’s described in the next section, a modified copy of the document will be stored. This could lead to higher storage use than would normally be expected when using remote documents.
Adding a Document from a URL
You can also add a document to PSPDFKit Server by specifying the URL the document can be fetched from. By default, a document added by a URL isn’t persistently stored in PSPDFKit Server and will be fetched from the URL when necessary. This is useful when you already have a document storage solution and you want PSPDFKit Server to fetch the documents from your document storage. You can override the default storage behavior and store the document persistently by setting the copy_asset_to_storage_backend
option to true
.
To add a document from a URL, POST
its URL — and optionally, its SHA256 hash, your document_id
, and your title
— to /api/document
, specifying the application/json
content type:
Request
POST /api/documents Content-Type: application/json Authorization: Token token="<secret token>" { "url": "http://exampleserver/sample.pdf", "sha256": "d37b9395c2baf168f977ce9ff9ec007d7270fc84cbf1549324bfc8dfc34333a9", "copy_asset_to_storage_backend": false }
$ curl http\://127.0.0.1\:5000/api/documents \ -X POST \ -H "Authorization: Token token=<secret token>" \ -H "Content-type: application/json" \ -d '{"url": "http://exampleserver/sample.pdf", "sha256": "d37b9395c2baf168f977ce9ff9ec007d7270fc84cbf1549324bfc8dfc34333a9", "title": "My custom title"}'
Response
HTTP/1.1 200 OK Content-Type: application/json { "data": { "createdAt": ..., "document_id": ..., "errors": [], "sourcePdfSha256": ..., "title": "...", } }
If a title
attribute is not provided, PSPDFKit Server will extract the title of the document from the PDF metadata (if present).
The errors
list will be non-empty if errors were encountered when importing annotations from the document. Each error will have the format {"reason": "Error description"}
.
When the SHA256 is specified but the hash does not match the calculated hash from the document downloaded from the URL, the following response is returned by the server:
Response
HTTP/1.1 409 Conflict Content-Type: application/json { "error": { "reason": "hash_mismatch", "description": "The provided hash does not match the calculated hash from the document." } }
When using the API to add a document from a URL, your backend storage must always deliver the same file, since the SHA256 will never be recalculated after the document is created. If the file on your storage backend changes and PSPDFKit Server needs to refetch the file (e.g. because it’s no longer cached), this will result in a hash_mismatch
error on PSPDFKit Server.
Including Annotations via the XFDF/Instant JSON File
PSPDFKit Server supports importing an XFDF or Instant JSON file when adding a new document. This replaces all existing annotations in the uploaded PDF with the annotations from the uploaded XFDF or Instant JSON file. If you want to add annotations to already existing ones instead of replacing them when you import an XFDF file, you can set keep_current_annotations
to true
. Then POST
either the PDF file or the document URL, along with the XFDF or Instant JSON file, as part of a multipart/form-data
request:
To upload a PDF file with an Instant JSON or XFDF file:
Request
POST /api/documents Content-Type: multipart/form-data; boundary=customboundary Authorization: Token token="<secret token>" --customboundary Content-Disposition: form-data; name="file"; filename="Example Document.pdf" Content-Type: application/pdf <PDF data> --customboundary Content-Disposition: form-data; name="attachment"; filename="attachment.xfdf" Content-Type: application/json <annotations data> --customboundary Content-Disposition: form-data; name="keep_current_annotations" true --customboundary--
To add a document from a URL with an Instant JSON or XFDF file:
Request
POST /api/documents Content-Type: multipart/form-data; boundary=customboundary Authorization: Token token="<secret token>" --customboundary Content-Disposition: form-data; name="url"; http://exampleserver/sample.pdf --customboundary Content-Disposition: form-data; name="attachment"; filename="attachment.xfdf" Content-Type: application/json <annotations data> --customboundary Content-Disposition: form-data; name="keep_current_annotations" true --customboundary--
Overwriting an Existing Document
If you want to replace a document with a given ID with a new document, you can set the overwrite_existing_document
parameter to true
. This will delete all data related to the existing document and create a new document using the uploaded file:
Request
POST /api/documents Content-Type: multipart/form-data; boundary=customboundary Authorization: Token token="<secret token>" --customboundary Content-Disposition: form-data; name="document_id" your_document_identifier_1 --customboundary Content-Disposition: form-data; name="overwrite_existing_document" true --customboundary Content-Disposition: form-data; name="file"; filename="Example Document.pdf" Content-Type: application/pdf <PDF data> --customboundary--
$ curl -X POST http://localhost:5000/api/documents/ \ -H "Authorization: Token token=<secret token>" \ -F "file=@example.pdf" \ -F "overwrite_existing_document=true" \ -F "document_id=your_document_identifier_1"
Creating a Document from Scratch
Instead of uploading existing PDF documents, PSPDFKit Server allows you to generate documents from scratch based on HTML files, stylesheets, and other assets. Head over to the PDF Generation guide for a detailed walkthrough, usage examples, and things to watch out for.
To generate a document, you need to supply a PDF generation schema under a generation
key in the multipart request and attach any files referenced in the schema as multipart attachments. For example, to generate a PDF document from an HTML file without any additional assets, you’d use the following request:
curl -X POST http://localhost:5000/api/documents \ -H "Authorization: Token token=<secret token>" \ -F generation='{ "html": "index.html" }' \ -F index.html=@/path/to/index.html
When you generate a document, you can pass any options allowed by the other document creation methods: document_id
, attachment
, operations
, etc
Efficiently Copying a Document
It is often useful to be able to create a new document using a previously uploaded PDF file and share it with a different set of users. In order to avoid repeating the upload, PSPDFKit Server provides a copy_document
endpoint.
This will copy all layers and their latest annotations from the document, so if annotations were already modified by a user, the copied document will include those changes:
Request
POST /api/copy_document Content-Type: application/json Authorization: Token token="<secret token>" { "document_id": "abc", }
$ curl http://localhost:5000/api/copy_document \ -X POST \ -H "Authorization: Token token=<secret token>" \ -H "Content-Type: application/json" \ -d '{"document_id": "abc"}'
Response
HTTP/1.1 200 OK Content-Type: application/json { "data": { "document_id": <ID of the new document> } }
It’s also possible to pass the ID of the new document:
Request
POST /api/copy_document Content-Type: application/json Authorization: Token token="<secret token>" { "document_id": "abc", "new_document_id": "def" }
$ curl http://localhost:5000/api/copy_document \ -X POST \ -H "Authorization: Token token=<secret token>" \ -H "Content-Type: application/json" \ -d '{"document_id": "abc", "new_document_id": "def"}'
Response
HTTP/1.1 200 OK Content-Type: application/json { "data": { "document_id": "def" } }
Common Use Case for Copying a Document
If you want to share a document with multiple users who should not see one another’s annotations, you can use copy_document
to create an individual document for each user.
Prerendering a Document
You can now let PSPDFKit Server render and cache documents ahead of time via the prerender
endpoint. This speeds up loading times when opening documents via PSPDFKit for Web. The rendering will be done asynchronously, and future clients asking for the document will receive the already rendered and cached pages. For more details about how PSPDFKit Server caches work, please check out our Cache guide.
Check out the configuration overview for more information on how to configure PSPDFKit Server to use Redis as an additional cache.
Please note that the prerendering feature requires setting up the Redis cache.
Request
POST /api/documents/abc/prerender Authorization: Token token="<secret token>"
$ curl http://localhost:5000/api/documents/:document_id/prerender \ -X POST \ -H "Authorization: Token token=<secret token>"
Response
If a document with the given ID exists, the server will return an HTTP response with the status 200. Usually this endpoint returns immediately, but if PSPDFKit Server is under a very high load, the call might block for a long time. Note that this doesn’t mean that all pages are prerendered, but only that the process of prerendering has successfully started:
HTTP/1.1 200 OK Content-Type: application/json
If there’s no such document, an HTTP response with the status 404 will be returned:
HTTP/1.1 404 Not Found Content-Type: application/json
It’s also possible to customize prerendering by passing the following options:
Request
$ curl http://localhost:5000/api/documents/:document_id/prerender \ -X POST \ -H "Authorization: Token token=<secret token>" \ -H "Content-Type: application/json" \ -D '{"scales": [1,2,4,6,8,12,16], "start_page": 0, "end_page": 10}'
Notes:
-
You can add as few or as many values in “scales” as you want as long as they are the values listed above.
-
If the end page value is higher than the number of pages in the PDF, it will automatically be adjusted.
Response
If a document with the given ID exists, the server will immediately return an HTTP response with the status 200. Note that this doesn’t mean that all pages are prerendered, but only that the process of prerendering has successfully started:
HTTP/1.1 200 OK Content-Type: application/json
If there’s no such document, an HTTP response with the status 404 will be returned:
HTTP/1.1 404 Not Found Content-Type: application/json
If the parameters are invalid (e.g. a non-integer page number or a non-allowed scale value), an HTTP response with the status 422 will be returned:
HTTP/1.1 422 Unprocessable Entity Content-Type: application/json
Persisting the Default Layer as a New Document
To persist the current content of the default layer as a new document, send a POST
request to the /copy_with_instant_json
endpoint. This will create a new PDF containing the latest annotations of the default layer, import the uploaded Instant JSON, and persist the resulting PDF as a new document. The response will include the document_id
of the new document:
Request
POST /api/documents/:document_id/copy_with_instant_json Content-Type: application/json Authorization: Token token="<secret token>"
$ curl -X POST http://localhost:5000/api/documents/:document_id/copy_with_instant_json \ -H "ContentType: application/json" \ -H "Authorization: Token token=<secret token>"
Response
HTTP/1.1 200 OK Content-Type: application/json { "data": { "document_id": ..., "errors": [], "sourcePdfSha256": ..., "title": "..." } }
Document Editing
Editing a Document’s PDF and Downloading the Resulting File
Document Editor is a separate component of PSPDFKit for Web, and it’s available for licenses with the document editing component. It provides you and your users with a whole host of page editing features, including new page creation, page duplication, reordering, merging imported documents, rotation, and deletion.
This endpoint will apply a list of operations to an existing document and return the resulting PDF file without persisting it in the system.
You can find a list of supported operations in the JSON Format guide.
For example, you can rotate all pages of a document 90 degrees clockwise:
Request
POST /api/documents/:document_id/pdf_with_operations Content-Type: application/json Authorization: Token token="<secret token>" { "operations": [ { "type": "rotatePages", "pageIndexes": "all", "rotateBy": 90 } ] }
Response
HTTP/1.1 200 OK Content-Type: application/pdf <PDF data>
$ curl http://localhost:5000/api/documents/:document_id/pdf_with_operations \ -X POST \ -H "Authorization: Token token=<secret token>" \ -H "Content-Type: application/json" \ -d '{"operations": [{"type": "rotatePages", "pageIndexes": "all", rotateBy": 90}]}'
To support the importDocument
operation, it’s sometimes necessary to use the multipart/form
content type, as the operation requires attaching a PDF file to be imported into an existing document.
For example, you can rotate all pages of a document and then add the contents of another PDF directly after:
POST /api/documents/:document_id/pdf_with_operations Content-Type: multipart/form-data; boundary=customboundary Authorization: Token token="<secret token>" --customboundary Content-Disposition: attachment; name="operations"; filename="operations.json" Content-Type: application/json { "operations": [ { "type": "rotatePages", "pageIndexes": "all", "rotateBy": 90 }, { "type": "importDocument", "document": "5ce11b7c-0726-48a2-a493-1cf4f92f26c5" "afterPageIndex": "first" }, ] } --customboundary Content-Disposition: attachment; name="5ce11b7c-0726-48a2-a493-1cf4f92f26c5"; filename="imported.pdf" Content-Type: application/pdf <PDF data> --customboundary--
$ curl http://localhost:5000/api/documents/:document_id/pdf_with_operations \ -H "Authorization: Token token=<secret token>" \ -F "operations=<operations.json" \ -F "5ce11b7c-0726-48a2-a493-1cf4f92f26c5=@imported.pdf;type=application/pdf"
Response
HTTP/1.1 200 OK Content-Type: application/pdf <PDF data>
This also applies to applyInstantJson
and applyXfdf
operations: the Instant JSON or XFDF file needs to be included in the multipart request, along with the dataFilePath
property set to the attachment’s name.
As you can pass more than one operation requiring an attachment in a single request, it’s necessary to assign a unique ID to the name of each attachment so that it can be referenced in the corresponding operation’s body.
However, the importDocument
operation also allows you to import existing documents stored on the Server simply by providing their IDs. See details in the JSON Format guide.
To target a specific Instant layer, you can modify the endpoint path from /api/documents/:document_id/pdf_with_operations
to /api/documents/:document_id/layers/:layer_name/pdf_with_operations
.
Editing a Document’s PDF and Persisting the Resulting File
This endpoint will apply a list of operations to an existing document and store the resulting PDF file at the document’s base layer.
Applying a document operation will affect both the data stored by PSPDFKit Server and the responses returned by other endpoints. For example, if you remove a page from a document, all annotations belonging to that page will be deleted as well. Similarly, other functionality (e.g. searching in a document) will return different results.
If you need to preserve the original document, PDF file, and related data, we recommend leveraging Instant layers and always using named layers.
You can find a list of supported operations in the JSON Format guide.
For example, you can rotate all pages of a document 90 degrees clockwise:
Request
POST /api/documents/:document_id/apply_operations Content-Type: application/json Authorization: Token token="<secret token>" { "operations": [ { "type": "rotatePages", "pageIndexes": "all", "rotateBy": 90 } ] }
Response
HTTP/1.1 200 OK Content-Type: application/json { "data": {"sourcePdfSha256": "...", "title": "...", "passwordProtected": ..., "storage": {"type": "built-in"}} }
$ curl http://localhost:5000/api/documents/:document_id/apply_operations \ -X POST \ -H "Authorization: Token token=<secret token>" \ -H "Content-Type: application/json" \ -d '{"operations": [{"type": "rotatePages", "pageIndexes": "all", "rotateBy": 90}]}'
To support the importDocument
operation, it’s sometimes necessary to use the multipart/form
content type, as the operation requires attaching a PDF file to be imported into an existing document.
For example, you can rotate all pages of a document and then add the contents of another PDF directly after:
POST /api/documents/:document_id/apply_operations Content-Type: multipart/form-data; boundary=customboundary Authorization: Token token="<secret token>" --customboundary Content-Disposition: attachment; name="operations"; filename="operations.json" Content-Type: application/json { "operations": [ { "type": "rotatePages", "pageIndexes": "all", "rotateBy": 90 }, { "type": "importDocument", "document": "5ce11b7c-0726-48a2-a493-1cf4f92f26c5" "afterPageIndex": "first" }, ] } --customboundary Content-Disposition: attachment; name="5ce11b7c-0726-48a2-a493-1cf4f92f26c5"; filename="imported.pdf" Content-Type: application/pdf <PDF data> --customboundary--
$ curl http://localhost:5000/api/documents/:document_id/apply_operations \ -H "Authorization: Token token=<secret token>" \ -F "operations=<operations.json" \ -F "5ce11b7c-0726-48a2-a493-1cf4f92f26c5=@imported.pdf;type=application/pdf"
Response
HTTP/1.1 200 OK Content-Type: application/json { "data": {"sourcePdfSha256": "...", "title": "...", "passwordProtected": ..., "storage": {"type": "built-in"}} }
This also applies to applyInstantJson
and applyXfdf
operations: the Instant JSON or XFDF file needs to be included in the multipart request, along with the dataFilePath
property set to the attachment’s name.
As you can pass more than one operation requiring an attachment in a single request, it’s necessary to assign a unique ID to the name of each attachment so that it can be referenced in the corresponding operation’s body.
However, the importDocument
operation also allows you to import existing documents stored on the Server simply by providing their IDs. See details in the JSON Format guide.
To target a specific Instant layer, you can modify the endpoint path from /api/documents/:document_id/apply_operations
to /api/documents/:document_id/layers/:layer_name/apply_operations
.
Document Deletion
Deleting a Document
To delete a document, use the DELETE
method:
Request
DELETE /api/documents/:document_id Authorization: Token token="<secret token>"
$ curl http://localhost:5000/api/documents/abc \ -H "Authorization: Token token=<secret token>" \ -XDELETE
Response
HTTP/1.1 200 OK content-length: 2 cache-control: max-age=0, private, must-revalidate OK
If the deletion fails, a response with an error
field will be returned. For example, when trying to delete a non-existing document, the response looks like this:
HTTP/1.1 404 Not Found content-length: 41 cache-control: max-age=0, private, must-r Content-Type: application/json { "error": { "reason": "document_not_found" } }
Deleting a document removes the document and all its annotations from the database. It also removes the PDF files and all attachments that are not needed by other documents.
Fetching Requests
Fetching Document Properties
Request
GET /api/documents/:document_id/properties Authorization: Token token="<secret token>"
$ curl http://localhost:5000/api/documents/abc/properties \ -H "Authorization: Token token=<secret token>"
Response
If a document with the given ID exists, PSPDFKit Server will return an HTTP response with the status 200 and the following JSON payload:
HTTP/1.1 200 OK Content-Type: application/json { "data": { "sourcePdfSha256": "...", "title": "...", "passwordProtected": ..., "byteSize": ..., "storage": {"type": "built-in"} } }
The fields sourcePdfSha256
, passwordProtected
, byteSize
, and title
are assigned by PSPDFKit Server when a document is uploaded.
The storage
key includes information about the storage mechanism used for the underlying PDF document:
-
When the
type
isbuilt-in
, it uses the built-in database-backed storage. -
When the
type
iss3
, it uses the S3 asset storage. The response also includes the S3 bucket used. -
When the
type
isremote
, it indicates a remote PDF file. The response includes the URL of the file.
For more information about how assets are stored, please see the Asset Storage guide.
If there’s no such document, an HTTP response with the status 404 and the following JSON payload will be returned:
HTTP/1.1 404 Not Found Content-Type: application/json { "error": {"reason": "document_not_found"} }
Fetching Page Text
You can fetch all text contained in a page via the /pages/:page_index/text
endpoint:
Request
GET /api/documents/:document_id/pages/:page_index/text Authorization: Token token="<secret token>"
$ curl http://localhost:5000/api/documents/abc/pages/1/text \ -H "Authorization: Token token=<secret token>"
Response
If a document with the given ID exists, the server will return an HTTP response with the status 200 and the following JSON payload:
HTTP/1.1 200 OK Content-Type: application/json { "textLines": [ { "contents": "Demo", "height": 43.73602294921875, "left": 502.89151000976562, "top": 108.1837158203125, "width": 82.712005615234375 } ] }
If there’s no such document, an HTTP response with the status 404 will be returned:
HTTP/1.1 404 Not Found Content-Type: application/json
If the page index is invalid or out of bounds, an HTTP response with the status 404 will be returned:
HTTP/1.1 404 Not Found Content-Type: application/json Parameter 'page_index' is invalid or out of bounds.
Fetching Highlighted Page Text
You can fetch all highlighted text contained in a page via the /pages/:page_index/highlighted
endpoint. Highlighted text refers to all text that is highlighted via one of the text markup annotations like underline, strikethrough, or highlight.
Please note that this is an approximation, and highlighted text might not always represent the text in the document exactly:
Request
GET /api/documents/:document_id/pages/:page_index/highlighted Authorization: Token token="<secret token>"
$ curl http://localhost:5000/api/documents/abc/pages/1/highlighted \ -H "Authorization: Token token=<secret token>"
Response
If a document with the given ID exists, the server will return an HTTP response with the status 200 and the following JSON payload:
HTTP/1.1 200 OK Content-Type: application/json { "data": [ { "annotation": { "id": ..., "content": {..}, "createdBy": "...", "updatedBy": "...", "group": "...", .. } "text": "This is a sample PDF document used to show the functionality of \r\n." } ] }
If there’s no such document, an HTTP response with the status 404 will be returned:
HTTP/1.1 404 Not Found Content-Type: application/json
If the page index is invalid or out of bounds, an HTTP response with the status 404 will be returned:
HTTP/1.1 404 Not Found Content-Type: application/json Parameter 'page_index' is invalid or out of bounds.
Fetching Document Outlines
You can fetch the outline (table of contents) of a document via the outline.json
endpoint:
Request
GET /api/documents/abc/outline.json Authorization: Token token="<secret token>"
$ curl http://localhost:5000/api/documents/:document_id/outline.json \ -X POST \ -H "Authorization: Token token=<secret token>"
Response
If a document with the given ID exists, the server will return an HTTP response with the status 200 and the following JSON payload:
HTTP/1.1 200 OK Content-Type: application/json { "data": { "outline": [ { "action": { "pageIndex": 0, "type": "goTo" }, "isExpanded": true, "level": 0, "title": "Page 1", "type": "pspdfkit/outline-element" } ] } }
If there’s no such document, an HTTP response with the status 404 will be returned:
HTTP/1.1 404 Not Found Content-Type: application/json
Fetching Document Information
You can fetch information about page count, the dimensions of pages, and permissions of a document via the document_info
endpoint:
Request
GET /api/documents/abc/document_info Authorization: Token token="<secret token>"
$ curl http://localhost:5000/api/documents/:document_id/document_info \ -H "Authorization: Token token=<secret token>"
You can also scope the request to the document_info
endpoint to a specific layer if the PDF was modified on that layer, for example, due to document operations:
Request
GET /api/documents/abc/layer/def/document_info Authorization: Token token="<secret token>"
$ curl http://localhost:5000/api/documents/:document_id/layer/:layer_id/document_info \ -H "Authorization: Token token=<secret token>"
Response
If a document with the given ID exists, the server will return an HTTP response with the status 200 and the following JSON payload:
HTTP/1.1 200 OK Content-Type: application/json { "data": { { "pageCount": 10, "pages" : [ { "height": 792, "pageIndex": 0, "pageLabel": "Frontpage", "rotation": 0, "width": 612 }, ... ], "permissions": { "printing": true, ... }, "title": "Document title" } } }
If there’s no such document, an HTTP response with the status 404 will be returned:
HTTP/1.1 404 Not Found Content-Type: application/json
Importing and Exporting
Fetching a Document’s PDF File
You can download the latest version of a document as a PDF, with annotations included, via the /pdf
endpoint. Include source=true
in the query to download the version of the document that was originally uploaded.
For formats other than PDF, the file is returned in its original format. For example, if you uploaded a Microsoft Office document, using source=true
will return the exact same Microsoft Office document.
For more information about formats other than PDF, please refer to the Supported File Formats section.
Request
GET /api/documents/:document_id/pdf?source=true Authorization: Token token="<secret token>"
$ curl "http://localhost:5000/api/documents/abc/pdf?source=true" \ -H "Authorization: Token token=<secret token>"
Response
HTTP/1.1 200 OK Content-Type: application/pdf <PDF data>
To target a specific Instant layer, you can modify the endpoint path from /api/documents/:document_id/pdf
to /api/documents/:document_id/layers/:layer_name/pdf
.
Fetching a Document’s Flattened PDF
Include flatten=true
in the query to download a document as a flattened PDF:
Request
GET /api/documents/:document_id/pdf?flatten=true Authorization: Token token="<secret token>"
$ curl "http://localhost:5000/api/documents/abc/pdf?flatten=true" \ -H "Authorization: Token token=<secret token>"
Response
HTTP/1.1 200 OK Content-Type: application/pdf <PDF data>
To target a specific Instant layer, you can modify the endpoint path from /api/documents/:document_id/pdf?flatten=true
to /api/documents/:document_id/layers/:layer_name/pdf?flatten=true
.
Rendering a Page
You can render a page via the /pages/:page_index/image
endpoint by providing the following parameters:
-
width
orheight
— dimensions for the rendered image. Exactly one dimension is required. -
(optional)
render_ap_streams
(default:false
) — usetrue
to render annotation AP streams.
Request
GET /api/documents/:document_id/pages/:page_index/image?width=400 Accept: image/png Authorization: Token token="<secret token>"
$ curl http://localhost:5000/api/documents/abc/pages/1/image?width=400 \ -H "Accept: image/png" -H "Authorization: Token token=<secret token>"
The rendered image format depends on the value of the Accept
header. Supported content types are image/png
(default) and image/webp
.
Response
If a document and a page with the given ID exists, the server will return an HTTP response with the status 200 and the rendered image as a payload:
HTTP/1.1 200 OK Content-Type: image/png <image data>
If there’s no such document, an HTTP response with the status 404 will be returned:
HTTP/1.1 404 Not Found Content-Type: application/json
If the page index is invalid or out of bounds, an HTTP response with the status 404 will be returned:
HTTP/1.1 404 Not Found Content-Type: application/json Parameter 'page_index' is invalid or out of bounds.
If both the width
and height
parameters are missing or were provided at the same time, an HTTP response with the status 400 will be returned:
HTTP/1.1 400 Bad Request One of `width` or `height` is required.
Exporting a Document’s XFDF File
Export the current annotations of a document as an XFDF file:
Request
GET /api/documents/abc/document.xfdf Authorization: Token token="<secret token>"
$ curl "http://localhost:5000/api/documents/abc/document.xfdf" \ -H "Authorization: Token token=<secret token>"
Response
HTTP/1.1 200 OK Content-Type: application/vnd.adobe.xfdf <XFDF data>
Exporting a Document’s Instant JSON File
Export the current annotations of a document as an Instant JSON file:
Request
GET /api/documents/:document_id/document.json Authorization: Token token="<secret token>"
$ curl "http://localhost:5000/api/documents/abc/document.json" \ -H "Authorization: Token token=<secret token>"
Response
HTTP/1.1 200 OK Content-Type: application/json <JSON data>
Importing Instant JSON on Existing Documents
To import an Instant JSON file and apply it to an existing document, you can POST
a multipart/form
request including an instant.json
file. This will modify the default layer of the document in place. In case of success, the endpoint will respond with an empty JSON object:
Request
POST /api/documents/:document_id/apply_instant_json Content-Type: multipart/form-data; boundary=customboundary Authorization: Token token="<secret token>" --customboundary Content-Disposition: form-data; name="instant.json"; filename="instant.json" Content-Type: application/json <instant.json data> --customboundary--
Response
HTTP/1.1 200 OK Content-Type: application/json {}
Importing Instant JSON and Downloading the Resulting PDF File
To import an Instant JSON file and download the resulting PDF, you can POST
a multipart/form
request including an instant.json
file. This will create a new PDF containing the latest annotations of the default layer, import the uploaded Instant JSON, and respond with the resulting PDF. Please note that this action will not modify the existing document, but rather only import the Instant JSON on a temporary file that will be downloaded in the process:
Request
POST /api/documents/:document_id/pdf_with_instant_json Content-Type: multipart/form-data; boundary=customboundary Authorization: Token token="<secret token>" --customboundary Content-Disposition: form-data; name="instant.json"; filename="instant.json" Content-Type: application/json <instant.json data> --customboundary--
Response
HTTP/1.1 200 OK Content-Type: application/pdf <PDF data>
Importing Instant JSON and Persisting the Resulting PDF File
To import an Instant JSON file and persist the resulting PDF as a new document, you can POST
a multipart/form
request including an instant.json
file. This will create a new PDF containing the latest annotations of the default layer, import the uploaded Instant JSON, and persist the resulting PDF as a new document. The response will include the document_id
of the new document:
Request
POST /api/documents/:document_id/copy_with_instant_json Content-Type: multipart/form-data; boundary=customboundary Authorization: Token token="<secret token>" --customboundary Content-Disposition: form-data; name="instant.json"; filename="instant.json" Content-Type: application/json <instant.json data> --customboundary--
$ curl http://localhost:5000/api/documents/:document_id/pdf_with_instant_json \ -o document-with-imported-data.pdf \ -X POST \ -H "Authorization: Token token=secret" \ -F "instant.json=@instant.json;type=application/json"
Response
HTTP/1.1 200 OK Content-Type: application/json { "data": { "document_id": ..., "errors": [], "sourcePdfSha256": ..., "title": "..." } }
Common Options
Supported File Formats
PSPDFKit Server supports importing documents in different file formats:
-
PDF (available for all licenses)
-
Image documents (JPEG, PNG, and TIFF — requires a specific component in your license)
-
Office files (Word, Excel, and PowerPoint — requires a specific component in your license)
Uploaded files do not need to have a specific extension, as PSPDFKit Server automatically detects the document MIME type.
The following table shows all supported MIME types:
File Extension | MIME Type |
---|---|
application/pdf | |
DOC | application/msword |
DOCX | application/vnd.openxmlformats-officedocument.wordprocessingml.document |
XLS | application/vnd.ms-excel |
XLSX | application/vnd.openxmlformats-officedocument.spreadsheetml.sheet |
PPT, PPS | application/vnd.ms-powerpoint |
PPTX | application/vnd.openxmlformats-officedocument.presentationml.presentation |
PPSX | application/vnd.openxmlformats-officedocument.presentationml.slideshow |
JPG/JPEG | image/jpeg |
PNG | image/png |
TIFF | image/tiff |
Request
POST /api/documents Content-Type: application/msword Authorization: Token token="<secret token>" <doc data>
$ curl http://localhost:5000/api/documents \ -X POST \ -H "Authorization: Token token=<secret token>" \ -H "Content-Type: application/msword" \ -T document.doc
Response
HTTP/1.1 200 OK Content-Type: application/json { "data": { "document_id": ..., "errors": [], "sourcePdfSha256": ..., "title": "..." } }
All additional parameters — like your own document ID, a custom title, or an Instant JSON or XFDF attachment — are supported. For example, you can attach an Instant JSON file:
Request
POST /api/documents Content-Type: multipart/form-data; boundary=customboundary Authorization: Token token="<secret token>" --customboundary Content-Disposition: form-data; name="file"; filename="example.doc" Content-Type: application/msword <doc data> --customboundary Content-Disposition: form-data; name="attachment"; filename="attachment.json" Content-Type: application/json <annotations data> --customboundary--
Accessing Password-Protected Documents
To access password-protected documents via the upstream API, you need to include the pspdfkit-pdf-password
header in all requests that work on a password-protected document. The exception to this is uploading or deleting a document or accessing the properties of a document via the /properties
endpoint.