Skip to content

AI translation

This page was translated from German with AI. If in doubt, the German original applies.

Signing with the WebSigner

The WebSigner brings qualified electronic signatures into your application without it having to know about signature cards, PINs, or authorization apps. Your system creates a signing process with the documents and receives a link. The person who signs opens it, chooses their signature device, and authorizes the signature with their trust service provider. Your system then retrieves the signed documents.

Preview

The WebSigner is not yet available in production. ZEDAL Support enables you for the test environment (erp-tools@zedal.de). The SDK methods shown here ship with the next release of Zedal.Sdk after 1.2.0.

When you need it

  • German electronic waste record procedure (eANV): Every consignment note (Begleitschein) and acceptance note (Übernahmeschein) requires a qualified signature from each party (Section 19 of the German ordinance on waste records, Nachweisverordnung (NachwV)). How this fits into the flow of a consignment note is described under Consignment note by role; what already works there today is described under BMU consignment notes.
  • PDF: delivery notes, contracts, reports, optionally with a visible signature.

The flow

Your system needs five calls. Everything in between is done by the person in the WebSigner’s web interface.

sequenceDiagram
    autonumber
    participant App as Your application
    participant S as WebSigner (SignerApi)
    actor M as Person
    participant V as Trust service provider

    App->>S: CreateSigningProcess (documents)
    App->>S: SubmitSigningProcess
    S-->>App: signing_url
    App->>M: Show link (browser, WebView, QR code)
    M->>S: opens the link, chooses the signature device
    M->>V: authorizes the signature (second factor)
    V-->>S: Signature
    opt Visual review enabled
        M->>S: checks the result and approves it
    end
    App->>S: GetSigningProcess until a final state is reached
    App->>S: GetResults
    S-->>App: signed documents with validation result

Device selection, authorization, and visual review deliberately belong to the web interface: your application sees neither the signature device nor the authorization, and it doesn’t need to.

States

A signing process has exactly one state (SigningProcessState) plus a machine-readable reason (state_reason). You display the text in state_detail; you should not branch on it.

stateDiagram-v2
    direction TB
    [*] --> BUILD: CreateSigningProcess
    BUILD --> PENDING_DEVICE: SubmitSigningProcess
    PENDING_DEVICE --> PENDING_AUTHORIZATION: signature device chosen
    PENDING_AUTHORIZATION --> SIGNING: authorized
    SIGNING --> REVIEW: visual review enabled
    SIGNING --> COMPLETED: visual review disabled
    REVIEW --> COMPLETED: approved
    COMPLETED --> [*]

That is the regular path. Besides it, a process ends in PARTIALLY_COMPLETED if only some of the documents could be signed, in REJECTED if the person refuses authorization, in FAILED on a technical error, in CANCELLED if someone cancels it or discards it in the visual review, and in EXPIRED if its time limit expires.

State Meaning Results retrievable
BUILD assembly; documents can be added and removed no
PENDING_DEVICE submitted, waiting for the signature device to be chosen no
PENDING_AUTHORIZATION waiting for authorization with the trust service provider no
SIGNING the signature is being applied no
REVIEW signed, waiting for the person’s visual review no
COMPLETED all documents signed yes
PARTIALLY_COMPLETED some signed, the rest with an individual error (SOME_DOCUMENTS_FAILED) yes, check each document
REJECTED the person refused authorization (AUTHORIZATION_DENIED) no
CANCELLED canceled by you (CANCELLED_BY_CREATOR), by the person (CANCELLED_BY_SIGNER), or discarded in the visual review (DISCARDED_IN_REVIEW) no
EXPIRED deadline expired (DEADLINE_REACHED) no
FAILED technical error without a usable result, for example provider disrupted (PROVIDER_UNAVAILABLE) or unexpected certificate (CERTIFICATE_MISMATCH) no

The final states are COMPLETED, PARTIALLY_COMPLETED, REJECTED, CANCELLED, EXPIRED, and FAILED. Whether the visual review runs is decided by the person in their settings, not by your call; so always plan for REVIEW. Treat an unknown reason like UNSPECIFIED: new reasons are added without the version changing.

With the .NET SDK

The code for this guide is shown in Signing with the SDK.

Via gRPC and REST

The service is called infotech.signer.sign.v1.api.SignerApi. Via REST, every operation except WatchSigningProcess is reachable as POST /infotech.signer.sign.v1.api.SignerApi/<Operation> with a JSON body; login and headers as described under REST / JSON.

Operation Purpose
CreateSigningProcess create a process with documents (state BUILD)
AddDocuments, RemoveDocument, ListDocuments change the assembly, only in BUILD
SubmitSigningProcess submit; returns the signing_url
GetSigningProcess current state
WaitForSigningProcess query the state like GetSigningProcess; this is how SignAsync in the SDK waits
WatchSigningProcess state stream, gRPC only
GetResults signed documents with validation result, after completion
CancelSigningProcess cancel, as long as no final state has been reached

The remaining operations of the service are used by the WebSigner’s web interface; your application doesn’t need them. You may repeat SubmitSigningProcess: a second call returns the same signing_url. CreateSigningProcess creates a new process on every repetition. That costs nothing as long as the process is not submitted; it expires when its time limit is reached.

Documents and options

Each document is a DocumentInput with display_name, kind, and the content in content.

DocumentKind Signature
DOCUMENT_KIND_PDF PDF signature; with or without a visible signature
DOCUMENT_KIND_BMU_XML XML signature for eANV documents, see BMU consignment notes
DOCUMENT_KIND_XML XML signature over the entire document

Options apply to the entire process (CreateSigningProcessRequest.options) or per document (DocumentInput.options). reason is the reason for the signature in plain text.

The visible signature of a PDF is defined by PdfSigningOptions.visible_signature: page (page, 0 means the last page), position, and size in PDF points (1/72 inch) with the origin at the bottom left. In the SDK, VisibleSignatures.Create(page, x, y, width, height) builds the value. The appearance comes from one of the person’s stamp templates: stamp_template_id selects one; if it is not specified, their default template applies. With invisible = true, you sign without a visible signature.

Integrating it into your application

  • Show the link: in the browser, in a WebView of your application, or as a QR code so that the person signs on their phone. Authorization with the trust service provider takes place on the provider’s own page; a WebView must allow this change of page.
  • Treat the link as confidential. Anyone who has it can view the process until its deadline expires, cancel it, and retrieve the signed documents. They cannot sign without the person’s signature device and second factor. Don’t write the link to logs, and send it only through channels you would also accept for passwords.
  • Poll the state: There is no redirect back into your application after signing yet. So poll GetSigningProcess at intervals of a few seconds while the person is signing, or use WatchSigningProcess via gRPC. Leave redirect_url empty when creating the process.
  • Plan for deadlines: Without deadline_at, a process runs for 24 hours. The service retains the signed documents only for a limited time after completion, typically 48 hours. Retrieve them right after completion and store them in your system.

The person sets up the A-Trust remote signature once; the manual A-Trust CSC describes how.

BMU consignment notes

For eANV documents, what matters is which layer is signed in which role: each party completes its own layer (Procedure and roles).

Layer-specific signatures to follow

Today, the WebSigner signs a DOCUMENT_KIND_BMU_XML as a whole. It does not yet apply a signature that completes exactly one layer for a specific role; BmuSigningOptions in the contract is intended for this and is not evaluated so far. You therefore don’t yet use the WebSigner to sign consignment notes that you need to sign for the eANV. This page will be extended as soon as this is released.

Errors

Errors arrive as gRPC status, and via REST as HTTP status according to the table under REST.

Status Typical cause
INVALID_ARGUMENT required field missing, unknown document kind, redirect_url not approved
UNAUTHENTICATED missing or expired access token
PERMISSION_DENIED someone else’s process, or your account is not enabled for this feature
NOT_FOUND process unknown
FAILED_PRECONDITION call in the wrong phase, for example GetResults before completion or RemoveDocument after submitting
UNIMPLEMENTED option not yet supported, for example documents by reference (object_reference) instead of inline

An expired deadline is not an error: GetSigningProcess then returns the state EXPIRED. Likewise, a negative validation result is not an error but a successful call with a negative result.

Next