Skip to main content

Digital Signing Integration

DocuDesk provides a complete digital signing workflow — create signing requests, collect signatures from multiple signers, verify document integrity, and maintain an immutable audit trail. Signing can be performed natively within Nextcloud or delegated to an external provider such as ValidSign.

Overview

The signing feature supports:

  • Signing requests — Create a request that routes a document to one or more signers
  • Signer actions — Sign or decline; bulk signing for multiple requests
  • Cancellation — Cancel an open request at any time
  • Verification — Verify the signature integrity of a signed document
  • Audit trail — Immutable log of all signing events per request
  • Pluggable providers — Native (local) signing or ValidSign external service

API Endpoints

Create Signing Request

POST /apps/docudesk/api/signing/requests

Request body (JSON):

FieldTypeRequiredDescription
fileIdintYesNextcloud file ID of the document to sign
signersarrayYesList of signer objects { userId, email, name, level }
titlestringHuman-readable title for the request
messagestringMessage shown to signers
dueDatestringISO 8601 due date for completion
providerstringSigning provider: native (default) or validsign

Response:

{
"id": "request-uuid",
"status": "pending",
"fileId": 42,
"signers": [ { "id": "signer-uuid", "userId": "john", "status": "pending" } ],
"createdAt": "2025-01-15T10:00:00Z"
}

List Signing Requests

GET /apps/docudesk/api/signing/requests

Returns all signing requests visible to the current user.


Get Signing Request

GET /apps/docudesk/api/signing/requests/{id}

Cancel Signing Request

DELETE /apps/docudesk/api/signing/requests/{id}

Cancels an open request. Any pending signers are notified.


Sign Document

POST /apps/docudesk/api/signing/requests/{id}/sign

Records a signature for the current user on the given request.

Request body (JSON):

FieldTypeRequiredDescription
signerIdstringYesUUID of the signer entry within the request
pinstringPIN for native signing (if required)

Decline Signing

POST /apps/docudesk/api/signing/requests/{id}/decline

Request body:

FieldTypeRequiredDescription
signerIdstringYesUUID of the signer
reasonstringYesReason for declining

Bulk Sign

POST /apps/docudesk/api/signing/bulk

Sign multiple requests in a single call.

Request body:

{ "requestIds": ["uuid-1", "uuid-2"] }

Verify Document

GET /apps/docudesk/api/signing/verify/{fileId}

Verifies signature integrity of a signed document file.

Response:

{
"valid": true,
"signers": [
{ "name": "John Doe", "signedAt": "2025-01-16T09:00:00Z", "level": "AES" }
],
"verifiedAt": "2025-01-16T10:00:00Z"
}

Get Audit Trail

GET /apps/docudesk/api/signing/requests/{id}/audit

Returns the full audit trail for a signing request.

Response:

[
{ "event": "created", "userId": "admin", "timestamp": "2025-01-15T10:00:00Z" },
{ "event": "signed", "userId": "john", "timestamp": "2025-01-16T09:00:00Z" }
]

Signing Providers

DocuDesk uses a provider abstraction (SigningProviderInterface) to support multiple backend signing implementations.

Native Provider (native)

Signs documents within Nextcloud using a local key pair. No external service is required. Suitable for internal workflows and Basic/AES signatures.

ValidSign Provider (validsign)

Delegates signing to the ValidSign external service. Suitable for QES/AES signatures with legal weight under eIDAS.

Required configuration:

Config keyDescription
docudesk_validsign_api_urlValidSign API base URL
docudesk_validsign_api_keyValidSign API key
docudesk_validsign_sender_emailSender email for invitation notifications

Set via DocuDesk admin settings or:

docker exec nextcloud php occ config:app:set docudesk docudesk_validsign_api_key --value="your-key"

Signature Levels

LevelNameDescription
BESBasic Electronic SignatureSimple click-to-sign, no certificate required
AESAdvanced Electronic SignatureIdentity-linked, supports local key pairs
QESQualified Electronic SignatureLegally equivalent to handwritten (eIDAS Art. 25)

Request State Machine

pending → in-progress → completed

declined

cancelled

isValidTransition() enforces allowed state transitions.


Audit Trail

SigningAuditService records every lifecycle event (created, signed, declined, cancelled, verified) as an immutable entry in OpenRegister's native audit trail (openregister_audit_trails). Events are stored with action types of the form docudesk.signing.{ACTION} (e.g. docudesk.signing.SIGNED). The audit trail is hash-chained and natively immutable — update and delete operations are rejected by OR with HTTP 405.

Signing audit events are discoverable via:

GET /api/audit-trails?objectUuid={signRequestId}

Supported action types

Action typeTriggered when
docudesk.signing.CREATEDSigning request is created
docudesk.signing.STARTSigner starts a signing session
docudesk.signing.SIGNEDSigner signs the document
docudesk.signing.DECLINEDSigner declines to sign
docudesk.signing.CANCELLEDInitiator cancels the request
docudesk.signing.EXPIREDRequest expires before completion
docudesk.signing.COMPLETEDAll signers have signed
docudesk.signing.VIEWEDSigner views the document

Each entry's changed JSON field carries: signRequestId, actorUserId, actorDisplayName, ipAddress, signatureLevel, provider.

Archiefwet 1995 retention configuration (required)

Administrators MUST configure OR's retention for the signing register to ≥ 3650 days (10 years) to comply with Archiefwet 1995.

This is a deploy-time configuration in OpenRegister — not enforced by DocuDesk application code. Configure via:

  • OR Admin UI: Navigate to Settings → OpenRegister → Registers → signing register → set retention period to 3650 days or higher.
  • occ command (if available in your OR version):
    php occ openregister:register:set-retention <registerId> --days 3650

The legal basis is Archiefwet 1995, which requires a minimum 10-year retention period for signing audit records relating to official documents. Failure to configure this setting may result in audit entries being purged before the mandatory retention period expires.

Legacy signingAuditEntry records

Prior to the migrate-signing-audit-to-or-audit release, signing events were stored in the signingAuditEntry OR schema. These records remain readable (read-only) for one major release. No new events are written to signingAuditEntry; all new events go to OR's native audit trail.


Services

SigningService

Orchestrates the signing request lifecycle.

MethodDescription
createRequest(data)Validate and create a new signing request
getRequest(id)Retrieve a signing request by ID
listRequests()List requests visible to the current user
sign(id, signerId)Record a signature action
decline(id, signerId, reason)Decline a signing request
cancelRequest(id)Cancel an open request
bulkSign(requestIds)Sign multiple requests at once
isValidTransition()Check whether a status transition is allowed

SigningVerificationService

MethodDescription
verifyDocument(fileId, userId)Verify signature integrity for a file

SigningAuditService

MethodDescription
logEvent()Record a signing lifecycle event
getAuditTrail(id)Retrieve all events for a signing request

SigningProviderFactory

Resolves the configured signing provider instance.

SigningProviderInterface

MethodDescription
getIdentifier()Provider identifier string
initiateSigning()Start a signing session with the provider
checkStatus(externalId)Poll external provider for signing status
downloadSignedDocument()Retrieve the signed document binary
cancelSigning(externalId)Cancel an external signing session
supportsLevel(level)Check if provider supports a signature level

Dependencies

DependencyPurpose
OpenRegisterStorage for signing requests and audit entries
INotificationManagerNotify signers of pending requests
IUserSessionIdentify the current signing user
IAppConfigRead provider configuration