Server API for Instant Comments
Since version 2020.1, PSPDFKit for Web and PSPDFKit Server allow users to collaborate on uploaded documents in real time by adding and viewing comments.
PSPDFKit Server enables automatic comment synchronization powered by our Instant engine. It also provides a set of server-to-server APIs that you can use to create and fetch comments in documents and individual Instant layers. You can use these APIs to import entire comment threads from your existing systems.
Any comments added through the APIs are instantly picked up by the PSPDFKit for Web viewer, and any comments users create through the UI can be retrieved using the API.
This guide covers the following:
For a more general overview of this feature, see our introduction to Instant Comments guide.
Data Model
Each comment is attached to a root annotation. Comments under the same root annotation form a single comment thread. The root annotation serves as an anchor for comments, marking their position in a document. Currently, only comment marker annotations and markup annotations can be used as root annotations.
Working with Root Annotations
Root annotations are regular annotations stored on PSPDFKit Server. They can be fetched, created, updated, and deleted using our server-to-server annotation APIs. However, there are a couple rules that apply only to root annotations:
-
When they’re deleted, all comments attached to them are deleted as well.
-
When the last comment under the root annotation is deleted, the annotation itself is removed.
Comment Markers
pspdfkit/comment-marker
is an annotation type used for marking a comment thread’s position in the document. It can be manipulated using the annotation APIs, just like any other annotation can. However, it’s only available if the Instant Comments component is enabled in the license.
Adding Comments to an Existing Root Annotation
You can use the following API to add multiple comments to the existing root annotation.
Request
Send a POST
request to /api/documents/:document_id/annotations/:annotation_id/comments
with a payload containing the comments you want to add. This request adds comments to the annotation in the document’s default layer. To target a named layer, use the /api/documents/:document_id/layers/:layer_name/annotations/:annotation_id/comments
path:
POST /api/documents/my-document/annotations/my-annotation/comments HTTP/1.1 Content-Type: application/json Authorization: Token token=<secret token> { "comments": [ { "id": "my-comment", "user_id": "user-1", "group": "discussion", "content": { "text": "I like it!", "creatorName": "Jane Doe", "createdAt": "2020-01-17T19:17:36.579151Z", "updatedAt": "2020-01-17T19:28:36.579151Z", "customData": { "key": "value" } } }, { "content": { "text": "Thanks! I appreciate it." } } ] }
curl -X POST http://localhost:5000/api/documents/my-document/annotations/my-annotation \ -H "Content-Type: application/json" -H "Authorization: Token token=<secret token>" -d '{"comments": [{"content": {"text": "I like it!", ...}}, ...]}'
If you don’t provide an id
for a comment, the ID will be autogenerated by the server. A few other parameters are optional as well:
-
user_id
sets thecreatedBy
attribute of the retrieved comments. It defaults tonull
. -
group
is the group of the created comment. It defaults tonull
. -
Inside
content
:-
creatorName
is the name displayed by the comment in the PSPDFKit for Web UI. It defaults tonull
. -
createdAt
is the time the comment was created. Comments in the UI are ordered by their creation time. This defaults to the current timestamp. -
updatedAt
is the time the comment was updated. It defaults tonull
. -
customData
is an arbitrary object you can attach to the comment. It defaults tonull
.
-
Response
On success, the server responds with the status 200 and an array of newly created comment IDs:
HTTP/1.1 200 OK Content-Type: application/json {"data": {"comments": [{"id": "7KPV2Z667S9V2CYNHZAA5P6984"}, {"id": "my-comment"}]}}
If the selected root annotation doesn’t have a correct type (i.e. it’s neither a comment marker nor a markup annotation), the server responds with the status 400. If the root annotation with a given ID doesn’t exist in the specified document and layer, the 404 response is returned. If any of the comment parameters are invalid, the response status code is 422.
Adding Comments along with the Root Annotation
You can leverage the following API to create an entire comment thread at once — i.e. a root annotation with multiple comments attached to it.
Request
Send a POST
request to /api/documents/:document_id/comments
with a body containing a root annotation and comments. If you want to add the comment thread in the named layer, send a request to the /api/documents/:document_id/layers/:layer_name/comments
path:
POST /api/documents/my-document/comments HTTP/1.1 Content-Type: application/json Authorization: Token token=<secret token> { "annotation": { "id": "my-annotation", "content": { "v": 1, "type": "pspdfkit/comment-marker", "opacity": 1, "bbox": [100, 100, 50, 50], "pageIndex": 0, "createdAt": "2020-01-17T19:08:22.741791Z", "updatedAt": "2020-01-17T19:08:22.741791Z" } }, "comments": [ { "id": "my-comment", "user_id": "user-1", "group": "group-1", "content": { "text": "I like it!", "creatorName": "Jane Doe", "createdAt": "2020-01-17T19:17:36.579151Z", "updatedAt": "2020-01-17T19:28:36.579151Z", "customData": { "key": "value" } } }, { "content": { "text": "Thanks! I appreciate it." } } ] }
curl -X POST http://localhost:5000/api/documents/my-document/annotations/my-annotation \ -H "Content-Type: application/json" -H "Authorization: Token token=<secret token>" -d '{"annotation": {"content": {"bbox": [100, 100, 50, 50], ...}}, "comments": [...]}'
The annotation data needs to be the same as it would be if the annotation were created using the annotation APIs. If the annotation id
isn’t supplied, it’ll be generated by the server.
Response
When the request is successful, the server returns the IDs of the created root annotation and comments:
HTTP/1.1 200 OK Content-Type: application/json { "data": { "annotation": { "id": "my-annotation" }, "comments": [ { "id": "7KQ0ZASA8RRB0FXBEGXVPF43YH" }, { "id": "my-comment" } ] } }
If the annotation doesn’t have a correct type (i.e. it’s neither a comment marker nor a markup annotation), the server responds with the status 400. If any of the annotation or comment parameters are invalid, the response status code is 422.
Retrieving Comments under the Root Annotation
The following endpoint can be used to retrieve all comments on the given root annotation.
Request
Send a GET
request to /api/documents/:document_id/annotations/:annotation_id/comments
to fetch comments under the root annotation from the default layer, or use the /api/documents/:document_id/layer/:layer_name/annotations/:annotation_id/comments
path to target a named layer:
GET /api/documents/my-document/annotations/my-annotation/comments Accept: application/json Authorization: Token token=<secret token>
curl http://localhost:5000/api/documents/my-document/annotations/my-annotation/comments \ -H "Content-Type: application/json" \ -H "Authorization: Token token=secret"
Response
On success, the server returns all the comments attached to the specified root annotation:
HTTP/1.1 200 OK Content-Type: application/json { "data": { "comments": [ { "id": "my-comment", "group": "group-1", "content": { "createdAt": "2020-01-17T19:17:36.579Z", "creatorName": "Jane Doe", "customData": { "key": "value" }, "text": "I like it!", "updatedAt": "2020-01-17T19:28:36.579Z" }, "createdBy": "user-1", "updatedBy": null }, { "id": "7KPV2Z667S9V2CYNHZAA5P6984", "group": null, "content": { "createdAt": "2020-01-17T19:23:27.078Z", "creatorName": null, "customData": null, "text": "Thanks! I appreciate it.", "updatedAt": null }, "createdBy": null, "updatedBy": null } ] } }
Just like how when comments are created, if the selected root annotation doesn’t have a correct type (i.e. it’s neither a comment marker nor a markup annotation), the server responds with the status 400. If the root annotation with a given ID doesn’t exist in the specified document and layer, the response status code is 404.
Importing and Exporting
When you download a document’s or layer’s PDF file, the comments will be visible in compatible PDF viewers. If you upload the exported file again, the comments will be extracted from it automatically and available in PSPDFKit Server and the Web viewer.
Currently, it isn’t possible to export or import comments using Instant JSON files.