> You are reading the Docusign Developer Documentation. For clean Markdown of any page, append .md to the page URL.
>
> Documentation indexes by section:
> - APIs and SDKs: https://docusign.docs.buildwithfern.com/docs/llms.txt
> - Platform 101: https://docusign.docs.buildwithfern.com/platform/llms.txt
> - Extension Apps: https://docusign.docs.buildwithfern.com/extension-apps/llms.txt
> - Docusign CLI: https://docusign.docs.buildwithfern.com/docusign-cli/llms.txt
>
> Authentication (OAuth, JWT Grant, M2M): https://docusign.docs.buildwithfern.com/platform/auth
> Webhooks and Connect: https://docusign.docs.buildwithfern.com/platform/webhooks
>
> OpenAPI specifications: https://docusign.docs.buildwithfern.com/openapi.json
> MCP server: https://docusign.docs.buildwithfern.com/_mcp/server

# Long term validation of PDF signatures

PAdES (PDF Advanced Electronic Signatures) is an [ETSI](https://www.etsi.org/) standard for applying and verifying PDF signatures. The TSP API supports the following PAdES security levels for ensuring long-term validation of your document signatures:

* **PAdES B-LT**. This profile includes verification information such as the chain of trust of the generated certificates and methods for checking revoked certificates.

* **PAdES B-LTA**. The PAdES B-LTA profile supports the PAdES B-LT profile. It also adds timestamping information and methods for checking the timestamping authority.

## PAdES B-LT example>

Code sample 1 generates a signed PDF document compliant with the PAdES B-LT security level. This example assumes that you built a CMS to support PAdES B-LT. The TSP API requires that you set the following parameters in
`completesignhash` to enable PAdES B-LT:

* `documentSecurityStore`. Embeds the verification information.

* `certificates`. Holds the certificate chain from the user

* `crls`. Holds the CRLs (certificate revocation lists) corresponding to the certificate chain.

* `ocsps`. Returns an array of OCSP servers that TSPs can use alternatively to CRLs to verify the revocation status of certificates.

```text
  public async Task SignDocuments(Dictionary<string, byte[]> cmsDictionary, List<byte[]> certs, List<byte> ocsps, List<byte> crls)
{
    // Call the /signhashsession endpoint
    var signHashInfo = await tspApiClient.SignHashSessionInfo();

    var docUpdateInfos = new List<DocumentUpdateInfo>();
    foreach (var contentInfo in _contentInfoDict)
    {
        docUpdateInfos.Add(
            new DocumentUpdateInfo()
            {
                Data = contentInfo.Value,
                DocumentId = contentInfo.Key,
                ReturnFormat = "CMS",
                DocumentSecurityStore = new DocumentSecurityStore()
                {
                    Certificates = certs,
                    Ocsps = ocsps,
                    Crls = crls,
                },
            }
        );
    }

    var completeSignHashRequest = new CompleteSignRequest()
    {
        DocumentUpdateInfos = docUpdateInfos,
        CorrelationId = Guid.NewGuid(),
    };

    // Call the /completesignhash endpoint
    var completeSignHashResponse = await this._tspApiClient.CompleteSignHashSessionInfo(completeSignHashRequest);
}
```

**Code sample 1**: sign a PDF document with PAdES using the B-LT security level

## PAdES B-LTA example

Code sample 2 generates a signed PDF document compliant with the PAdES B-LTA security level. This example assumes that you built a CMS to support PAdES B-LT.

PAdES B-LTA adds timestamping verification to the PAdES B-LT level. The TSP API uses the
`completesignhash` request to generate timestamping information. You must submit the timestamping generation request after creating the last signature in the transaction.

To trigger timestamping, you must first set the
`timeStampField` field parameter to an empty JSON object value (“\{}”) in the
`completesignhash` request that creates the last signature of the transaction. Next, you must submit a new
`completesignhash`request for generating the timestamping information. The value of the
`documentId` parameter must correspond to the value of the
`documentId` parameter returned by the response to the previous
`completesignhash`, which is the request that generates the last signature of the transaction. Note also that the
`remainingSignatureRequests` parameter of the response returns 1, which designates one remaining
`completesignhash` request.

```text
  public async Task SignDocuments(Dictionary<string, byte[]> cmsDictionary, List<byte[]> certs, List<byte> ocsps, List<byte> crls)
{
    // Call the /signhashsession endpoint
    var signHashInfo = await tspApiClient.SignHashSessionInfo();

var docUpdateInfos = new List<DocumentUpdateInfo>();
foreach (var contentInfo in _contentInfoDict)
{
    docUpdateInfos.Add(
        new DocumentUpdateInfo()
        {
            Data = contentInfo.Value,
            DocumentId = contentInfo.Key,
            ReturnFormat = "CMS",
            DocumentSecurityStore = new DocumentSecurityStore()
            {
                Certificates = certs,
                Ocsps = ocsps,
                Crls = crls,
            },
            TimeStampField = "", // Ask the TSP API to allow a timestamp after the signature.
        }
    );
}
var completeSignHashRequest = new CompleteSignRequest()
{
    DocumentUpdateInfos = docUpdateInfos,
    CorrelationId = Guid.NewGuid(),
};

// Call the /completesignhash endpoint
var completeSignHashResponse = await this._tspApiClient.CompleteSignHashSessionInfo(completeSignHashRequest);

// Because we asked the TSP API to allow a timestamp after the signature,
// we expect there to be 1 remaining signature request in
// completeSignHashResponse.RemainingSignatureRequests
var documentUpdateInfos = new List<DocumentUpdateInfo>();
foreach (var doc in completeSignHashResponse.Documents)
{
    var hashToTimestamp = doc.Data;

    // Call the timestamper
    var timestamp = await _timestampClient.TimestampHash(hashToTimestamp);

    documentUpdateInfos.Add(new DocumentUpdateInfo()
    {
        Data = timestamp,
        ReturnFormat = "CMS",
        DocumentId = doc.DocumentId,
    });
}

var completeSignHashReqeuest = new CompleteSignRequest()
{
    DocumentUpdateInfos = documentUpdateInfos,
    CorrelationId = Guid.NewGuid(),
};

// Call the /completesignhash endpoint a second time to complete the timestamp
await _tspApiClient.CompleteSignHashSessionInfo(completeSignHashReqeuest);
}
```

**Code sample 2**: sign a PDF document with PAdES using the B-LTA security level

## Related links

[What is long term validation?](https://support.docusign.com/s/articles/What-is-Long-Term-Validation-LTV?language=en_US\&rsc_301)