PDF annotations JSON format schema
This guide explains how to format JSON when you work with Instant annotations.
Types
This section explains how to use type declarations in Instant JSON records.
The optional keys are specified as follows:
{ optionalKey?: value; }
To save traffic, these keys shouldn’t be included in the record if the value is undefined.
Throughout this guide, the JSON tab shows an example of the format. Switch to the JavaScript tab to see complete type declarations, which document is each key’s expected type, whether the key is optional, and how the value is expected to be used.
Annotation types
The following annotation types are supported:
-
pspdfkit/image
-
pspdfkit/ink
-
pspdfkit/link
-
pspdfkit/markup/highlight
-
pspdfkit/markup/redaction
-
pspdfkit/markup/squiggly
-
pspdfkit/markup/strikeout
-
pspdfkit/markup/underline
-
pspdfkit/note
-
pspdfkit/comment-marker
-
pspdfkit/shape/ellipse
-
pspdfkit/shape/line
-
pspdfkit/shape/polygon
-
pspdfkit/shape/polyline
-
pspdfkit/shape/rectangle
-
pspdfkit/stamp
-
pspdfkit/text
Basic properties
Annotations can include many different properties, some of them shared among several annotation types. These properties are serialized in Instant JSON following the rules described in this guide.
Basic types
We define a number of low-level types that are used throughout all annotation types.
Geometry
Geometry always represents points inside a page. The coordinate space origin is the top-left corner of the page, with the x-axis increasing to the right, and the y-axis increasing downward. Rectangles are positioned at their top-left point:
// Examples of payloads for geometry data types: // Rect [100, 150, 200, 150][ // Point (120, 50) ][ // CloudyBorderInset (10, 10, 10, 10) ]
// [left, top, width, height] as a number in points. declare type Rect = [number, number, number, number]; // [x, y] in points. declare type Point = [number, number]; // Counterclockwise angle in degrees. Should be 0, 90, 180, or 270. declare type Rotation = number; // Inset used for drawing cloudy borders more precisely [left, top, right, bottom]. declare type CloudyBorderInset = [number, number, number, number];
Other
// Example of Instant JSON values: // Color "#ffcc00" // Lines { "intensities": [ [0.5, 0.5, 0.5] ], "points": [ [100, 120], [110, 121], [120, 122] ] } // LineCaps { "start": "openArrow", "end": "square" }
// "#RRGGBB" declare type Color = string; // 0.0 to 1.0. declare type Opacity = number; // 0.0 to 1.0; the default is 0.5. declare type Intensity = number; // ISO 8601 with full date, time, and time zone information. // e.g. "2012-04-23T18:25:43.511Z" // - https://en.wikipedia.org/wiki/ISO_8601 // - https://www.w3.org/TR/NOTE-datetime declare type Timestamp = string; declare type Lines = { // Intensities are used to weigh the point during natural // drawing. They are received by pressure-sensitive drawing // or touch devices. The default value should be used if // it's not possible to obtain the intensity. intensities: Array<Array<Intensity>>, // Points are grouped in segments. Points inside a segment // are joined to a line. There must be at least one segment // with at least one point. points: Array<Array<Point>> }; declare type LineCap = | "square" | "circle" | "diamond" | "openArrow" | "closedArrow" | "butt" | "reverseOpenArrow" | "reverseClosedArrow" | "slash"; declare type LineCaps = { start?: LineCap, end?: LineCap }; declare type BlendMode = | "normal" | "multiply" | "screen" | "overlay" | "darken" | "lighten" | "colorDodge" | "colorBurn" | "hardLight" | "softLight" | "difference" | "exclusion";
Action types
Please refer to the JSON format schema — actions guide.
Base annotation type
Every annotation shares a set of common values, which are formalized in the BaseAnnotation
type. Later in this guide, you’ll see all annotations extend this type using type intersection.
This means that a specific annotation needs to have all the properties of BaseAnnotation
and all the properties of its specific annotation type:
// Example of an Instant JSON schema for `BaseAnnotation`: { "v": 1, "pageIndex": 0, "bbox": [150, 75, 120, 70], "opacity": 1, "pdfObjectId": 100, "flags": ["noZoom", "noRotate"], "creatorName": "John Doe", "createdAt": "2012-04-23T18:25:43.511Z", "updatedAt": "2012-04-23T18:28:05.100Z", "id": "01F46S31WM8Q46MP3T0BAJ0F83", "name": "01F46S31WM8Q46MP3T0BAJ0F83" }
// See the PDF Reference for the below flags. One difference: Instead of a // `print` flag, like in PDF, we have `noPrint` so that we don't have // `print` enabled on almost all annotations. declare type Flags = Array< | "noPrint" | "noZoom" | "noRotate" | "noView" | "hidden" | "invisible" | "readOnly" | "locked" | "toggleNoView" | "lockedContents" >; declare type BaseAnnotation = { // The spec version that the record is compliant to. Always `1`. v: 1, // An annotation must always be inside a specific page. pageIndex: number, // The bounding box of the annotation within the page. bbox: Rect, // Modifies the transparency of the annotation. opacity: Opacity, // The object ID from the source PDF. pdfObjectId?: number; // PDF Flags. flags?: Flags; // Optional PDF Action. action?: Action; // The name of the creator of the annotation. creatorName?: string, // The date of the annotation creation. createdAt: Timestamp, // The date of the last annotation update. updatedAt: Timestamp // An identifier for the annotation that is unique within the document or Instant layer. When adding an annotation without an ID to Document Engine, an ID will be generated. id?: string; // Optional annotation name. This is used to identify the annotation. name?: string; // Optional. If not specified, the blend mode is `normal`. blendMode?: BlendMode; }; declare type Annotation = | MarkupAnnotation | TextAnnotation | NoteAnnotation | EllipseAnnotation | RectangleAnnotation | LineAnnotation | PolylineAnnotation | InkAnnotation | LinkAnnotation | ImageAnnotation | StampAnnotation | CommentMarkerAnnotation;
pspdfkit/markup/{highlight, squiggly, strikeout, underline}
Markup annotations include highlight, squiggly, strikeout, and underline. All of these require a list of rectangles that they’re drawn to. The highlight annotation will lay the color on top of the element and apply the multiply blend mode.
// Example of an Instant JSON schema for a markup annotation: { "v": 1, "pageIndex": 1, "bbox": [150, 275, 120, 70], "opacity": 1, "pdfObjectId": 200, "creatorName": "John Doe", "createdAt": "2012-04-23T18:25:43.511Z", "updatedAt": "2012-04-23T18:28:05.100Z", "id": "01F46S31WM8Q46MP3T0BAJ0F84", "name": "01F46S31WM8Q46MP3T0BAJ0F84", "type": "pspdfkit/markup/highlight", "rects": [[150, 275, 120, 70]], "blendMode": "multiply", "color": "#ffff00" }
declare type MarkupAnnotation = BaseAnnotation & { type: | "pspdfkit/markup/highlight" | "pspdfkit/markup/squiggly" | "pspdfkit/markup/strikeout" | "pspdfkit/markup/underline", // List of rectangles on the page where the markup is drawn. rects: Array<Rect>, blendMode?: BlendMode, color: Color, note?: string };
pspdfkit/markup/redaction
Redaction annotations are markup annotations, but they support some additional properties, so we have a specific type for them.
You have to have licensed the Redaction component to use redaction annotations.
// Example of an Instant JSON schema for a markup annotation: { "v": 1, "pageIndex": 1, "bbox": [150, 275, 120, 70], "opacity": 1, "pdfObjectId": 200, "creatorName": "John Doe", "createdAt": "2012-04-23T18:25:43.511Z", "updatedAt": "2012-04-23T18:28:05.100Z", "id": "01F46S31WM8Q46MP3T0BAJ0F84", "name": "01F46S31WM8Q46MP3T0BAJ0F84", "type": "pspdfkit/markup/redaction", "outlineColor": "#ff0000", "fillColor": "#000000", "overlayText": "REDACTED", "repeatOverlayText": true, "rotation": 0 }
declare type RedactionAnnotation = MarkupAnnotation & { type: "pspdfkit/markup/redaction" // Outline color is the border color of a redaction annotation when it hasn't yet been applied to the document. outlineColor?: Color, // Fill color is the background color that a redaction will have when applied to the document. fillColor?: Color, // The text that will be printed on top of an applied redaction annotation. overlayText?: string, // Specifies whether or not the `overlayText` will be repeated multiple times to fill the boundaries of the redaction annotation. repeatOverlayText?: boolean, rotation?: Rotation };
With redaction annotations, the rects
property determines the location of the area marked for redaction.
pspdfkit/text
A text annotation can be placed anywhere on the screen. Please keep in mind that fonts are client specific, so you should only use fonts you know are present in the browser where they should be displayed. If a font isn’t found, Nutrient will automatically fall back to a sans-serif font.
// Example of an Instant JSON schema for a text annotation: { "v": 1, "pageIndex": 1, "bbox": [150, 275, 120, 70], "opacity": 1, "pdfObjectId": 200, "creatorName": "John Doe", "createdAt": "2012-04-23T18:25:43.511Z", "updatedAt": "2012-04-23T18:28:05.100Z", "id": "01F46S31WM8Q46MP3T0BAJ0F85", "name": "01F46S31WM8Q46MP3T0BAJ0F85", "type": "pspdfkit/text", "text": "Content for a text annotation", "fontSize": 14, "fontStyle": ["bold"], "fontColor": "#000000", "horizontalAlign": "left", "verticalAlign": "center", "rotation": 0 }
declare type TextAnnotation = BaseAnnotation & { type: "pspdfkit/text", // The text contents. text: string, // A background that will fill the bounding box. backgroundColor?: Color, // Size of the text in px (this will scale when you zoom in). fontSize: number, // The font to render the text. A client will fall back to a sans-serif font // if it isn't supported or if none is defined. font?: string, // A text can be only italic, only bold, italic and bold, or none of these. fontStyle?: Array<"italic" | "bold">, // The color of the rendered glyphs. fontColor: Color, horizontalAlign: "left" | "center" | "right", verticalAlign: "top" | "center" | "bottom", // Specifies that the text is supposed to fit in the bounding box. // This will only be set on new annotations, as we can't easily figure // out if an appearance stream contains all the text for existing annotations. isFitting?: boolean, callout?: { start: Point, knee?: Point, end: Point, cap?: LineCap, // Inset applied to the box to size and position the rectangle for the text [left, top, right, bottom]. innerRectInset: [number, number, number, number] }, borderStyle?: BorderStyle, // Only set if there is a `borderStyle` too. borderWidth?: number rotation: Rotation; cloudyBorderIntensity?: number cloudyBorderInset?: CloudyBorderInset };
pspdfkit/ink
Ink annotations are used for freehand drawings on a page. They can contain multiple segments (see the definition of Lines
above). Points within a segment are connected to a line.
// Example of an Instant JSON schema for an ink annotation: { "v": 1, "pageIndex": 2, "bbox": [95, 115, 125, 127], "opacity": 1, "pdfObjectId": 250, "creatorName": "John Doe", "createdAt": "2012-04-23T18:05:43.511Z", "updatedAt": "2012-04-23T18:08:05.100Z", "id": "01F46S31WM8Q46MP3T0BAJ0F85", "name": "01F46S31WM8Q46MP3T0BAJ0F85", "type": "pspdfkit/ink", "lines": { "intensities": [[0.5, 0.5, 0.5]], "points": [ [ [100, 120], [110, 121], [120, 122] ] ] }, "lineWidth": 10, "isDrawnNaturally": false, "strokeColor": "#8080ff" }
declare type InkAnnotation = BaseAnnotation & { type: "pspdfkit/ink", // Refer to the above spec for the `Lines` type. lines: Lines, // The width of the line in px. lineWidth: number, // PSPDFKit's natural drawing mode. This value is only used by PSPDFKit // for iOS. isDrawnNaturally: boolean, // `true` if the annotation is an ink signature. isSignature?: boolean, // The color of the line. strokeColor: Color, // The color that fills the bounding box. backgroundColor?: Color, blendMode?: BlendMode, note?: string };
pspdfkit/link
A link can be used to trigger an action when clicked or pressed. The link will be drawn on the bounding box.
// Example of an Instant JSON schema for a link annotation: { "v": 1, "pageIndex": 1, "bbox": [95, 115, 125, 127], "opacity": 1, "pdfObjectId": 200, "creatorName": "John Doe", "createdAt": "2012-04-23T18:25:43.511Z", "updatedAt": "2012-04-23T18:28:05.100Z", "id": "01F46S31WM8Q46MP3T0BAJ0F86", "name": "01F46S31WM8Q46MP3T0BAJ0F86", "type": "pspdfkit/link", "action": { "type": "goTo", "pageIndex": 10 }, "note": "Text note for the annotation" }
declare type LinkAnnotation = BaseAnnotation & { type: "pspdfkit/link", // Refer to the spec for the `Action` type. action: Action, note?: string, borderStyle?: BorderStyle, // Only set if there is a `borderStyle` too. borderWidth?: number, // The common annotations dictionary says that the C entry should be used for // border color in the case of link annotations. borderColor?: Color };
pspdfkit/note
Note annotations are “sticky notes” attached to a point in the PDF document. They’re represented as markers, and each one has an icon associated with it. Its text content is revealed on selection.
// Example of an Instant JSON schema for a note annotation: { "v": 1, "pageIndex": 1, "bbox": [95, 115, 125, 127], "opacity": 1, "pdfObjectId": 200, "creatorName": "John Doe", "createdAt": "2012-04-23T18:25:43.511Z", "updatedAt": "2012-04-23T18:28:05.100Z", "id": "01F46S31WM8Q46MP3T0BAJ0F87", "name": "01F46S31WM8Q46MP3T0BAJ0F87", "type": "pspdfkit/note", "text": "Text for the note annotation", "icon": "circle", "color": "#80ff80" }
declare type NoteAnnotation = BaseAnnotation & { type: "pspdfkit/note", text: string, icon: | "comment" | "rightPointer" | "rightArrow" | "check" | "circle" | "cross" | "insert" | "newParagraph" | "note" | "paragraph" | "help" | "star" | "key", // Fills the note shape and its icon [canvas]. color: Color };
pspdfkit/comment-marker
Please refer to the JSON format schema — comments guide.
Shape annotations
Shape annotations are used to draw different shapes — lines, rectangles, ellipses, polylines, and polygons — on a page.
Shape annotations with a transparent fill color are only selectable around their visible lines. This means you can create a page full of shape annotations while annotations behind these shape annotations are still selectable:
// Example of a generic Instant JSON payload for shape annotations: { "v": 1, "pageIndex": 0, "bbox": [195, 215, 325, 427], "opacity": 0.7, "pdfObjectId": 300, "creatorName": "John Doe", "createdAt": "2012-05-23T18:25:43.511Z", "updatedAt": "2012-06-23T18:28:05.100Z", "id": "01F46S31WM8Q46MP3T0BAJ0F88", "name": "01F46S31WM8Q46MP3T0BAJ0F88", // "type": "pspdfkit/shape/{line, rectangle, ellipse, polyline, polygon}", "strokeDashArray": [3, 3], "strokeWidth": 5, "strokeColor": "#000000" }
declare type ShapeAnnotation = BaseAnnotation & { strokeDashArray?: Array<number>, strokeWidth: number, strokeColor: Color, note?: string };
pspdfkit/shape/ellipse
Ellipse annotations are used to draw ellipses on a page.
// Example of an Instant JSON schema for an ellipse annotation: { "v": 1, "pageIndex": 0, "bbox": [195, 215, 325, 427], "opacity": 1, "pdfObjectId": 120, "creatorName": "John Doe", "createdAt": "2012-05-23T18:25:43.511Z", "updatedAt": "2012-06-23T18:28:05.100Z", "id": "01F46S31WM8Q46MP3T0BAJ0F89", "name": "01F46S31WM8Q46MP3T0BAJ0F89", "type": "pspdfkit/shape/ellipse", "strokeWidth": 5, "strokeColor": "#0000ff", "fillColor": "#ffffff", "cloudyBorderIntensity": 1, "cloudyBorderInset": [10, 10, 10, 10] }
declare type EllipseAnnotation = ShapeAnnotation & { type: "pspdfkit/shape/ellipse", // Fills the inside of the shape. fillColor?: Color, cloudyBorderIntensity?: number cloudyBorderInset?: CloudyBorderInset };
pspdfkit/shape/rectangle
Rectangle annotations are used to draw rectangles on a page.
// Example of an Instant JSON schema for a rectangle: { "v": 1, "pageIndex": 0, "bbox": [195, 215, 325, 427], "opacity": 1, "pdfObjectId": 120, "creatorName": "John Doe", "createdAt": "2012-05-23T18:25:43.511Z", "updatedAt": "2012-06-23T18:28:05.100Z", "id": "01F46S31WM8Q46MP3T0BAJ0F8A", "name": "01F46S31WM8Q46MP3T0BAJ0F8A", "type": "pspdfkit/shape/rectangle", "strokeWidth": 5, "strokeColor": "#0000ff", "fillColor": "#ffffff" }
declare type RectangleAnnotation = ShapeAnnotation & { type: "pspdfkit/shape/rectangle", // Fills the inside of the shape. fillColor?: Color, cloudyBorderIntensity?: number cloudyBorderInset?: CloudyBorderInset };
pspdfkit/shape/line
Line annotations are used to draw straight lines on a page.
// Example of an Instant JSON schema for a line annotation: { "v": 1, "pageIndex": 0, "bbox": [195, 215, 325, 427], "opacity": 1, "pdfObjectId": 120, "creatorName": "John Doe", "createdAt": "2012-05-23T18:25:43.511Z", "updatedAt": "2012-06-23T18:28:05.100Z", "id": "01F46S31WM8Q46MP3T0BAJ0F8B", "name": "01F46S31WM8Q46MP3T0BAJ0F8B", "strokeWidth": 5, "strokeColor": "#0000ff", "fillColor": "#ffffff", "type": "pspdfkit/shape/line", "startPoint": [40, 60], "endPoint": [100, 200], "lineCaps": { "start": "openArrow" } }
declare type LineAnnotation = ShapeAnnotation & { type: "pspdfkit/shape/line", startPoint: Point, endPoint: Point, lineCaps?: LineCaps, // Fills the inside of the end/start caps. fillColor?: Color };
pspdfkit/shape/polyline
Polyline annotations are used to draw polylines on a page by hand. They can contain any number of sides, which are defined by the polyline vertices.
// Example of an Instant JSON schema for a polyline annotation: { "v": 1, "pageIndex": 5, "bbox": [15, 25, 90, 60], "opacity": 1, "pdfObjectId": 220, "creatorName": "John Doe", "createdAt": "2012-05-23T18:25:43.511Z", "updatedAt": "2012-06-23T18:28:05.100Z", "id": "01F46S31WM8Q46MP3T0BAJ0F8C", "name": "01F46S31WM8Q46MP3T0BAJ0F8C", "strokeWidth": 10, "strokeColor": "#0000ff", "fillColor": "#ffffff", "type": "pspdfkit/shape/polyline", "fillColor": "#ff0000", "lineCaps": { "start": "circle", "end": "circle" }, "points": [ [20, 30], [100, 70], [55, 80] ] }
declare type PolylineAnnotation = ShapeAnnotation & { type: "pspdfkit/shape/polyline", // Fills the inside of the line caps. fillColor?: Color, lineCaps?: LineCaps, points: Array<Point> };
pspdfkit/shape/polygon
Polygon annotations are used to draw polygons on a page by hand. They can contain any number of sides, which are defined by the polygon vertices.
// Example of an Instant JSON schema for a polygon annotation: { "v": 1, "pageIndex": 3, "bbox": [15, 25, 90, 60], "opacity": 1, "pdfObjectId": 230, "creatorName": "John Doe", "createdAt": "2012-05-23T18:25:43.511Z", "updatedAt": "2012-06-23T18:28:05.100Z", "id": "01F46S31WM8Q46MP3T0BAJ0F8D", "name": "01F46S31WM8Q46MP3T0BAJ0F8D", "strokeWidth": 10, "strokeColor": "#0000ff", "type": "pspdfkit/shape/polygon", "points": [ [20, 30], [100, 70], [55, 80] ] }
declare type PolygonAnnotation = ShapeAnnotation & { type: "pspdfkit/shape/polygon", // Fills the inside of a closed polygon. fillColor?: Color, points: Array<Point>, cloudyBorderIntensity?: number };
pspdfkit/image
Image annotations are used to annotate a PDF with images.
// Example of an Instant JSON schema for an image annotation: { "v": 1, "pageIndex": 3, "bbox": [15, 25, 90, 60], "opacity": 1, "pdfObjectId": 230, "creatorName": "John Doe", "createdAt": "2020-05-23T18:25:43.511Z", "updatedAt": "2020-06-23T18:28:05.100Z", "id": "01F46S31WM8Q46MP3T0BAJ0F8E", "name": "01F46S31WM8Q46MP3T0BAJ0F8E", "type": "pspdfkit/image", "description": "Company logo", "contentType": "image/jpeg", "imageAttachmentId": "800", "rotation": 0 }
declare type ImageAnnotation = BaseAnnotation & { type: "pspdfkit/image", // A description of the image, e.g. "PSPDFKit Logo." description?: string, // Only if one can be retrieved. fileName?: string, contentType?: "image/jpeg" | "image/png" | "application/pdf", // Either the SHA-256 hash of the attachment or the `pdfObjectId` of the attachment. imageAttachmentId?: string, rotation: Rotation, note?: string };
For more information on attachments, please refer to the JSON format schema — file attachments guide.
pspdfkit/stamp
A stamp annotation represents a stamp in a PDF. The image of the stamp depends upon the stampType
, which can be one of the following:
-
Accepted
-
Approved
-
AsIs
-
Completed
-
Confidential
-
Departmental
-
Draft
-
Experimental
-
Expired
-
Final
-
ForComment
-
ForPublicRelease
-
InformationOnly
-
InitialHere
-
NotApproved
-
NotForPublicRelease
-
PreliminaryResults
-
Rejected
-
Revised
-
SignHere
-
Sold
-
TopSecret
-
Void
-
Witness
-
Custom
If the stampType
is set to Custom, the title
, subtitle
, and color
will define the appearance of the stamp annotation.
// Example of an Instant JSON schema for a stamp annotation: { "v": 1, "pageIndex": 0, "bbox": [150, 250, 150, 100], "opacity": 1, "pdfObjectId": 300, "creatorName": "John Doe", "createdAt": "2020-05-23T18:25:43.511Z", "updatedAt": "2020-06-23T18:28:05.100Z", "id": "01F46S31WM8Q46MP3T0BAJ0F8F", "name": "01F46S31WM8Q46MP3T0BAJ0F8F", "type": "pspdfkit/stamp", "stampType": "Approved", "title": "Approved", "color": "#00ff00", "rotation": 0 }
declare type StampAnnotation = BaseAnnotation & { type: "pspdfkit/stamp", stampType: | "Accepted" | "Approved" | "AsIs" | "Completed" | "Confidential" | "Departmental" | "Draft" | "Experimental" | "Expired" | "Final" | "ForComment" | "ForPublicRelease" | "InformationOnly" | "InitialHere" | "NotApproved" | "NotForPublicRelease" | "PreliminaryResults" | "Rejected" | "Revised" | "SignHere" | "Sold" | "TopSecret" | "Void" | "Witness" // Not a standard stamp. Displays arbitrary text in the title and subtitle. | "Custom", title?: string, subtitle?: string, color?: Color, rotation: Rotation, note?: string };