Multi-signer workflow
Prerequisites
A pair of API key ID and API key secret.
Some credits for the Document Simple Forensic API or the Document Simple API workflow.
What? and Why?
What if instead of one signer whose signature is placed in some points inside the PDF document, we have more than one signer each signing the same PDF document?
That is indeed a multi-signer workflow, and it’s perfectly manageable using Web Trust.
How?
For the sake of simplicity, let’s assume we have two signers. The first signer-1 will sign in some of the signature fields, and the second signer-2 will sign the rest. Let’s also assume that we have a PDF document with two signature fields, one named sig-1 and the other sig-2. Our goal is to obtain a final PDF with signer-1’s signature in sig-1 and signer-2’s signature in sig-2.

Let’s first create the signature for signer-1.
Example// Creating the first signature
const resPostSig1 = await fetch("https://api.webtrust.kopjra.com/v1/signatures", {
headers: {
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": "Basic NjhiOTkxMjEtYWIxNC00YzUwLWFlMzItNDgzZmQ4MWVkNWJkOnlBRG1YTDZ6IzNjVm4tWURPNmJsTWkybGY0MEpNMEdUcFpLVH5+Ujc1eUNEN3ZZVGU2fmJTdTJEOUZwNHFEVjl4RWhtVmRZSw==",
},
method: "POST",
body: JSON.stringify({
"signerFullname": "signer-1", // For signer-1
"signatureType": "graphic",
"isForensic": true,
"locale": "en",
"documents": [
{
// PDF with sig-1 and sig-2 empty
"name": "document.pdf",
"contentBase64": "PDF_IN_BASE64",
"signatureFieldsType": "signature",
// Specifying the signature field to be used
"signatureFieldsName": ["sig-1"]
}
],
"otp": {
"sms": "+39555555554"
}
}),
});
const signature1 = await resPostSig1.json();Now we send signature1.fUrl to signer-1 in order for her to sign the document. When signer-1 opens the link, she will see that her signature will be applied only in one place, sig-1.
After signer-1 finishes the signature process, we will need to get the signed PDF in base64. It will be the input for signer-2.
Exampleconst resGetSig1 = await fetch(`https://api.webtrust.kopjra.com/v1/signatures/${signature_1.id}`, {
headers: {
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": "Basic NjhiOTkxMjEtYWIxNC00YzUwLWFlMzItNDgzZmQ4MWVkNWJkOnlBRG1YTDZ6IzNjVm4tWURPNmJsTWkybGY0MEpNMEdUcFpLVH5+Ujc1eUNEN3ZZVGU2fmJTdTJEOUZwNHFEVjl4RWhtVmRZSw==",
},
method: "GET",
});
const fullSignature1 = await resGetSig1.json();
// fullSignature1.currentStatus must be "CONCLUDED"
const resGetPDF1 = await fetch(fullSignature1.attachedFiles.signedDocuments[0].url);
const pdfBuffer = Buffer.from(await resGetPDF1.arrayBuffer());
const pdfB64 = pdfBuffer.toString("base64");Now pdfb64 contains the PDF that signer-2 needs to sign. Let’s do it.
Example// Creating the second signature
const resPostSig2 = await fetch("https://api.webtrust.kopjra.com/v1/signatures", {
headers: {
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": "Basic NjhiOTkxMjEtYWIxNC00YzUwLWFlMzItNDgzZmQ4MWVkNWJkOnlBRG1YTDZ6IzNjVm4tWURPNmJsTWkybGY0MEpNMEdUcFpLVH5+Ujc1eUNEN3ZZVGU2fmJTdTJEOUZwNHFEVjl4RWhtVmRZSw==",
},
method: "POST",
body: JSON.stringify({
"signerFullname": "signer-2", // For signer-2
"signatureType": "graphic",
"isForensic": true,
"locale": "en",
"documents": [
{
// PDF with sig-1 signed and sig-2 empty
"name": "document.pdf",
"contentBase64": pdfB64,
"signatureFieldsType": "signature",
// Specifying the signature field to be used
"signatureFieldsName": ["sig-2"]
}
],
"otp": {
"sms": "+3955555555"
}
}),
});
const signature2 = await resPostSig2.json();Then we send signature2.fUrl to signer-2 and wait for her to complete the process. Then we get the signature2.id after its currentStatus is CONCLUDED, and we will find a PDF with both signatures.
When implementing a multi-signer workflow, even though the signed PDF is the last one (the one with all the signatures), all the forensic evidence XMLs are needed, since each XML corresponds to one signer interaction. Therefore, all the XMLs form the forensic evidence of this multi-signer workflow.
And if there are form fields?
One extension to the previous use case is to add a form to be filled in to the mixture. Assuming there are fields that should be filled in by one signer and other fields by the other, we need to specify which field should fill in which signer in each signature creation. Very similarly to what we did with the signature fields.