Apply changes
Apply user actions to a layer, each a change whose ops apply in order, all or none, or the undo of an earlier change.
Each change stands on its own and names itself by `opId`: a refused change rolls back alone, and the answer lists every change in order, applied with its result or refused with its error. Asked again under its `opId`, a change gets the same answer, refusals included; a different change under an answered `opId` is refused (IdempotencyKeyReused). `{ opId, undoOf }` undoes an earlier change of the caller, here or in an earlier request; an undo leaves alone what was changed since, and the undo of an undo redoes. A redaction, a flatten, a form repair or a completed signature ends undo for the changes before it (UndoUnavailable). Each op is checked against its own capability: annotation ops need `doc.annotate.modify`, form values `doc.forms.fill`, form structure `doc.forms.modify`, metadata `doc.metadata.modify`. Bytes (a stamp's drawing, an attached file, a signature's artwork) travel as multipart: a JSON `body` part, each op naming its files by role as `resources: { <role>: '<key>' }`, and each file as the part `resource:<key>`. At most 64 changes per request and 512 ops per change.
Authentication#
Any one of these credentials is accepted.
The deployment's static root credential (CLOUDPDF_API_AUTH_TOKENS), valid on every surface.
Doc-scoped JWT, valid only on the /v1/docs/{docId} subtree it names, gated by the capability scopes it carries (each operation's x-required-capability).
Parameters#
docIdpathstringrequiredlayerNamepathstringrequiredX-Document-PasswordheaderstringBase64-encoded password for an encrypted document. Valid only with the API token (403 anywhere else). An encrypted document answers 422 DocPasswordRequired when the header is absent. Viewer doc JWTs use the SDK password-session flow instead.
Request body#
application/jsonDocChangesRequestrequiredchangesobject[]requiredopIdstringrequiredopsChangeOp[]type"annotations.create"requiredpagePageRefrequiredkind"objectNumber"requiredobjectNumberintegerrequireddataAnnotationDraftrequiredsubtype"highlight"requiredrefunknownpageunknownhasAppearanceunknownappearanceStateunknownnmstringrectobjectcontentsstringsubjectstringblendMode"normal" | "multiply" | "screen" | "overlay" | "darken" | "lighten" | "color-dodge" | "color-burn" | "hard-light" | "soft-light" | "difference" | "exclusion" | "hue" | "saturation" | "color" | "luminosity"invisiblebooleanhiddenbooleanprintbooleannoZoombooleannoRotatebooleannoViewbooleanreadOnlybooleanlockedbooleantoggleNoViewbooleanlockedContentsbooleanreplyobjectpopupunknowngroupIdstringauthorunknowncreatedAtunknownmodifiedAtunknownuserIdunknowncreatedByunknownmodifiedByunknownimportedByunknownactionsunknowncolorstringopacitynumberquadPointsobject[]requiredobjectNumberintegerresourcesobjectappearancestringfilestringundoOfstringmultipart/form-dataDocChangesRequestrequiredchangesobject[]requiredopIdstringrequiredopsChangeOp[]type"annotations.create"requiredpagePageRefrequiredkind"objectNumber"requiredobjectNumberintegerrequireddataAnnotationDraftrequiredsubtype"highlight"requiredrefunknownpageunknownhasAppearanceunknownappearanceStateunknownnmstringrectobjectcontentsstringsubjectstringblendMode"normal" | "multiply" | "screen" | "overlay" | "darken" | "lighten" | "color-dodge" | "color-burn" | "hard-light" | "soft-light" | "difference" | "exclusion" | "hue" | "saturation" | "color" | "luminosity"invisiblebooleanhiddenbooleanprintbooleannoZoombooleannoRotatebooleannoViewbooleanreadOnlybooleanlockedbooleantoggleNoViewbooleanlockedContentsbooleanreplyobjectpopupunknowngroupIdstringauthorunknowncreatedAtunknownmodifiedAtunknownuserIdunknowncreatedByunknownmodifiedByunknownimportedByunknownactionsunknowncolorstringopacitynumberquadPointsobject[]requiredobjectNumberintegerresourcesobjectappearancestringfilestringundoOfstringA complete body with every required field. Strings stand in for your own values.
{
"changes": [
{
"opId": "opId"
}
]
}SDK examples#
The selected SDK is remembered across the API reference. Values are examples; replace them with identifiers and input from your application.
import { CloudPDFClient } from "@cloudpdf/sdk";
const client = new CloudPDFClient({
baseUrl: "https://yourhost.com/path/to/api",
token: "<token>",
});
await client.doc.changes({
docId: "docId",
layerName: "layerName",
changes: [{
opId: "opId"
}]
});Responses#
application/jsonDocChanges200Responsechanges("applied" | "refused")[]opIdstringstatus"applied"resultChangeResultitemsChangeItem[]type"skipped"op"annotations.create" | "annotations.update" | "annotations.delete" | "annotations.reorder" | "forms.setValue" | "forms.setDisplay" | "forms.setAppearanceText" | "forms.reset" | "forms.create" | "forms.update" | "forms.delete" | "forms.addWidget" | "forms.removeWidget" | "forms.deleteWidget" | "forms.reorderCalculations" | "forms.reorderWidgets" | "forms.updateWidget" | "forms.setSignatureAppearance" | "metadata.update" | "metadata.updateCustom" | "annotations.restore" | "forms.restore"metaMutationMetametaMutationMetaaffectedPagesPageRef[]cacheDeltaCacheDeltaopIdstringundoablebooleanapplication/jsonDocChanges400Responseapplication/jsonDocChanges404Responseapplication/jsonDocChanges409Responseapplication/jsonDocChanges413Responseapplication/jsonEngineErrorPayloadname"EngineError"code"Unknown" | "InvalidArg" | "DocNotOpen" | "DocOpenFailed" | "DocPasswordRequired" | "DocPasswordIncorrect" | "SharePasswordRequired" | "Aborted" | "Network" | "Unauthenticated" | "Forbidden" | "NotFound" | "WireFormat" | "RuntimeUnavailable" | "LayerVersionConflict" | "NotImplemented" | "MalformedPdf" | "SigningPending" | "SigningExpired" | "SigningVersionMismatch" | "SignatureRefused" | "ProtectedDocument" | "StaleBase" | "PayloadTooLarge" | "ObjectNumberUnavailable" | "LayerFull" | "ChangeConflict" | "UndoUnavailable" | "IdempotencyKeyReused"messagestringdetailsobjectoptional