Digital Signatures

Beginning with version 2020.1, PSPDFKit Server supports reading and applying digital signatures to PDF documents.

A digital signature is an electronic fingerprint uniquely identifying the signing person. A digital signature on a PDF document is both reliable proof of the document’s origin and protection against modification by third parties.

For a general overview, please consult our Introduction to Digital Signatures guide.

PSPDFKit Server exposes a few endpoints for applying and reading digital signatures, both for documents and for individual Instant layers:

Signing a Document

To sign a document, PSPDFKit Server requires you to set up a companion signing service and set the SIGNING_SERVICE_URL environment variable. Please also check the configuration guide for other instance-wide options you can change to customize the digital signature metadata.

Request

To sign a document, you can use the /api/documents/:document_id/sign endpoint, optionally passing a JSON request body containing a signing token. Its value is completely arbitrary and it will be forwarded to the signing service in the exact same format. You can use it to verify the request, identify the signing user, or perform a specific authorization workflow:

Copy
1
2
3
4
5
6
7
POST /api/documents/:document_id/sign
Content-Type: application/json
Authorization: Token token="<secret token>"

{
  "signingToken": "my-signing-token"
}
Copy
1
2
3
4
$ curl -XPOST http://localhost:5000/api/documents/my-document/sign \
   -H "ContentType: application/json" \
   -H "Authorization: Token token=<secret token>" \
   -d '{"signingToken": "my-signing-token"}'

Response

In the case of success, PSPDFKit Server will respond with the status 200 and the JSON body containing information about the newly generated signature:

Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
  "data": {
    "signature": {
      "certificateChainValidationStatus": "ok_but_self_signed",
      "creationDate": "2020-01-17T10:01:53Z",
      "documentIntegrityStatus": "ok",
      "documentModifiedSinceSignature": false,
      "isExpired": false,
      "isSelfSigned": true,
      "isTrusted": false,
      "signatureFormFQN": "Signature-61b574ae-8057-45f1-91a3-59f08b88120d",
      "signatureValidationStatus": "warning",
      "type": "pspdfkit/signature-info",
      "validFrom": "2019-11-06T12:44:04Z",
      "validUntil": "2020-11-05T12:44:04Z"
    }
  }
}

For more information about the properties of a digital signature, please see the relevant guide.

In the case of error, PSPDFKit Server will return:

  • A 400 status code when the request is either malformed or the signing server responds with a status code in the 4xx range.
  • A 500 status code when the signing server responds with a status code in the 3xx or 5xx error range.

Signing a Layer

You can apply a signature to a specific Instant layer. This lets you maintain independent versions of the same document with separate signatures. For example, if you’re working on a contract, you can maintain two layers: one for the original document, and one for a copy that will be digitally signed.

Request

You can sign an Instant layer using the parent document ID and the layer name. If you use a layer name that maps to a non-existing layer, it will be copied automatically from the document base layer and then signed:

Copy
1
2
3
4
5
6
7
POST /api/documents/:document_id/layers/my-layer/sign
Content-Type: application/json
Authorization: Token token="<secret token>"

{
  "signingToken": "my-signing-token"
}
Copy
1
2
3
4
$ curl -XPOST http://localhost:5000/api/documents/my-document/layers/my-layer/sign \
   -H "ContentType: application/json" \
   -H "Authorization: Token token=<secret token>" \
   -d '{"signingToken": "my-signing-token"}'

Response

In the case of success, PSPDFKit Server will respond with the status 200 and the JSON body containing information about the newly generated signature:

Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
  "data": {
    "signature": {
      "certificateChainValidationStatus": "ok_but_self_signed",
      "creationDate": "2020-01-17T10:01:53Z",
      "documentIntegrityStatus": "ok",
      "documentModifiedSinceSignature": false,
      "isExpired": false,
      "isSelfSigned": true,
      "isTrusted": false,
      "signatureFormFQN": "Signature-61b574ae-8057-45f1-91a3-59f08b88120d",
      "signatureValidationStatus": "warning",
      "type": "pspdfkit/signature-info",
      "validFrom": "2019-11-06T12:44:04Z",
      "validUntil": "2020-11-05T12:44:04Z"
    }
  }
}

For more information about the properties of a digital signature, please see the relevant guide.

In the case of error, PSPDFKit Server will return:

  • A 400 status code when the request is either malformed or the signing server responds with a status code in the 4xx range.
  • A 500 status code when the signing server responds with a status code in the 3xx or 5xx error range.

Fetching a Document’s Digital Signature Status

A document’s digital signature status is computed by looking at all the digital signatures included in the document. For more information about its properties and the flow that determines its final value, please see our guide about the status of digital signatures.

PSPDFKit Server takes care of automatically updating the digital signature status of a document after each change (e.g. adding a new annotation).

The validity of a signature is determined by the signing certificate used to create it: If you’re using a custom certificate, you need to set up PSPDFKit Server to use a corresponding certificate store in order to identify the signature as valid. Please check our guide article on how to set up custom certificates for digital signature validation.

Request

You can fetch a document’s digital signature status with the /api/documents/:document_id/signatures endpoint:

1
2
3
GET /api/documents/:document_id/signatures
Content-Type: application/json
Authorization: Token token="<secret token>"
Copy
1
2
3
$ curl http://localhost:5000/api/documents/my-document/signatures \
   -H "ContentType: application/json" \
   -H "Authorization: Token token=<secret token>"

Response

In the case of success, PSPDFKit Server will respond with the status 200 and the JSON body containing the digital signature status of the document:

Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
  "data": {
    "checkedAt": "2020-01-17T10:28:10.507Z",
    "documentModifiedSinceSignature": false,
    "signatures": [
      {
        "certificateChainValidationStatus": "ok_but_self_signed",
        "creationDate": "2020-01-17T10:01:53Z",
        "documentIntegrityStatus": "ok",
        "documentModifiedSinceSignature": false,
        "isExpired": false,
        "isSelfSigned": true,
        "isTrusted": false,
        "signatureFormFQN": "Signature-61b574ae-8057-45f1-91a3-59f08b88120d",
        "signatureValidationStatus": "warning",
        "type": "pspdfkit/signature-info",
        "validFrom": "2019-11-06T12:44:04Z",
        "validUntil": "2020-11-05T12:44:04Z"
      }
    ],
    "status": "warning"
  }
}

Please note that the response includes a checkedAt timestamp, which represents the exact time used by PSPDFKit Server to check the digital signature certificate’s validity. We strongly recommend never storing the digital signature status of a layer and always requesting it from PSPDFKit Server to have a reliable and up-to-date value.

Fetching a Layer’s Digital Signature Status

For a general overview of this endpoint, please check out the Fetching a Document’s Digital Signature Status section of this guide.

Request

You can fetch the digital signature status of an individual layer using the parent document ID and the layer name.

If you use a layer name that maps to a non-existing layer, PSPDFKit Server will report the status of the document base layer without creating a new one:

1
2
3
GET /api/documents/:document_id/layers/my-layer/signatures
Content-Type: application/json
Authorization: Token token="<secret token>"
Copy
1
2
3
$ curl http://localhost:5000/api/documents/my-document/layers/my-layer/signatures \
   -H "ContentType: application/json" \
   -H "Authorization: Token token=<secret token>"

Response

In the case of success, PSPDFKit Server will respond with the status 200 and the JSON body containing the digital signature status of the layer:

Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
  "data": {
    "checkedAt": "2020-01-17T10:28:10.507Z",
    "documentModifiedSinceSignature": false,
    "signatures": [
      {
        "certificateChainValidationStatus": "ok_but_self_signed",
        "creationDate": "2020-01-17T10:01:53Z",
        "documentIntegrityStatus": "ok",
        "documentModifiedSinceSignature": false,
        "isExpired": false,
        "isSelfSigned": true,
        "isTrusted": false,
        "signatureFormFQN": "Signature-61b574ae-8057-45f1-91a3-59f08b88120d",
        "signatureValidationStatus": "warning",
        "type": "pspdfkit/signature-info",
        "validFrom": "2019-11-06T12:44:04Z",
        "validUntil": "2020-11-05T12:44:04Z"
      }
    ],
    "status": "warning"
  }
}

Please note that the response includes a checkedAt timestamp, which represents the exact time used by PSPDFKit Server to check the digital signature certificate’s validity. We strongly recommend never storing the digital signature status of a layer and always requesting it from PSPDFKit Server to have a reliable and up-to-date value.