How Instant JSON works
Instant JSON stores PDF changes like annotations in a separate JSON file. This means that a PDF document will only need to be transferred once and all changes will be added as an overlay to the existing PDF. This approach significantly reduces the bandwidth, since you only need to transfer the JSON instead of the complete PDF.
Conceptually, Instant JSON defines a list of skippedPdfObjectIds. These point to the PDF’s internal object IDs for annotations. Whenever an object ID is marked as skipped, it’ll no longer be loaded from the original PDF. Instead, it could be defined inside the annotations array with the same pdfObjectId. If this is the case, the PDF viewer will display the new annotation, which signals an update to the original one. If an object ID is marked as skipped but the annotations array doesn’t contain an annotation with the same pdfObjectId, it’ll be interpreted as a deleted annotation. An annotation inside the annotations array without the pdfObjectId property is interpreted as a newly created annotation.
All annotations in the annotations array have a unique id field. For updated annotations that were in the original PDF, this field will be the stringified pdfObjectId. Newly created annotations will get a newly generated ULID(opens in a new tab).
An “empty” Instant JSON contains neither skippedPdfObjectIds nor annotations, which means the original PDF is untouched. All annotations in the initial PDF are still shown.
The table below illustrates how Instant JSON manages annotation updates, deletions, and creations in a PDF using a list of skipped object IDs and an annotations array.
| Scenario | skippedPdfObjectIds | Annotations array | Interpretation by PDF viewer |
|---|---|---|---|
| Annotation to be updated | Contains object ID | Contains an object with the same pdfObjectId | Display the new annotation from the array |
| Annotation to be deleted | Contains object ID | Does not contain an object with the same pdfObjectId | Treat the annotation as deleted |
| New annotation to be created | Does not contain ID | Contains an object without the pdfObjectId property | Display the newly created annotation |
| Original annotation to be loaded without changes | Does not contain ID | May or may not contain related objects | Load and display the original annotation |
Understanding pdfId
Instant JSON includes a pdfId property that acts like a fingerprint for your PDF document. This property uniquely identifies a specific version of the document, which is helpful when you need to ensure annotations are applied to the correct version of a PDF.
The pdfId consists of two parts:
- permanent — Based on the PDF’s original content when it was first created
- changing — Updates whenever the document structure is modified
How pdfId changes affect compatibility
The pdfId changes when you modify the document structure. When this happens, the permanent part stays the same (because it’s still fundamentally the same PDF file), but the changing part gets updated to reflect the structural modifications you’ve made.
The pdfId changes when you:
- Perform document operations (rotate, add, remove, or move pages)
- Modify the PDF structure in any way
- Resave or reprocess the document
Best practices for storing pdfId
For most web applications, remove pdfId before persisting Instant JSON:
// When exporting — exclude `pdfId`.var instantJSON = document.exportInstantJSON()instantJSON.removeValue(forKey: "pdfId")saveToDatabase(instantJSON)
// When importing — remove `pdfId` if present.var storedJSON = loadFromDatabase()storedJSON.removeValue(forKey: "pdfId")When to keep pdfId:
- If you need strict version control, such as in legal document workflows where annotations must only apply to exact document versions
- If you want to prevent annotations from being applied to the wrong document version
Removing pdfId enables your annotations to work across document versions, which gives you more flexibility when the PDF gets modified over time.