- SDK members
- LastError Licensekey
- Code samples
- VB.NET, C#, VB6 / VBScript (COM)
- Published
In short: With SignPDFRemote the Aloaha ZUGFeRD SDK (version 11.0.0.2 and later) signs a PDF – including a hybrid ZUGFeRD/Factur-X invoice – via the CodeB Remote Signature Service, part of the CodeB EUID Wallet software. The SDK sends the PDF to the service over HTTPS and receives it back with a PAdES signature (level B-B to B-LTA). No local certificate, smartcard or card reader is needed; signing also works unattended in batch jobs and from VB6/VBA via COM.
When to sign remotely?
- Servers and batch jobs: invoices are created and signed automatically without a certificate or card having to be installed on the server.
- Central key management: the signing key is held by the signing service, not on every workstation.
- Long-term verifiability: with level B-LTA the PDF contains timestamps and validation data for later verification.
CodeB EUID Wallet – now also for ZUGFeRD
The CodeB Remote Signature Service is part of the CodeB EUID Wallet software. The EUID Wallet is therefore now also used for ZUGFeRD: the Aloaha ZUGFeRD SDK (SignPDFRemote), the ZUGFeRD GUI, the PDF Viewer and the command-line tool zugcmd sign e-invoices directly via the EUID Wallet's signing service – without a certificate or smartcard on your own computer.
The software includes the CodeB Wallet – an EUDI wallet under eIDAS 2.0 for Android phones: identity data (PID), mobile driving licence, ID checks and PDF signing on the phone, advanced (AdES) via the signing service or qualified (QES) with the Maltese eID or a D-Trust card via NFC. All functions, video and access: CodeB Wallet – Aloaha's EU identity wallet and myeuid.app.
You do not need the app to sign invoices with the SDK: SignPDFRemote, the ZUGFeRD GUI, the PDF Viewer and zugcmd talk to the signing service directly, server to server.
Requirements
- Aloaha ZUGFeRD SDK version 11.0.0.2 or later with a valid licence.
- A user account on a production CodeB server (Remote Signature Service of the CodeB EUID Wallet); for the server-to-server call, sign-in with user name and password must be enabled for the tenant.
Important: https://phone.codeb.io is only CodeB's test server. It is suitable for trying things out but must not be used for production environments. For production you need your own CodeB server or tenant – contact us: info@aloaha.com. The examples therefore use the placeholder https://YOUR-CODEB-SERVER.
- Internet access via HTTPS from the calling computer to the signing service.
- The PDF is at most 10 MiB in size and not encrypted.
VB.NET
Dim LicenseKey As String = "YOUR-LICENCE-KEY"
Dim alo As New Aloaha_ZUGFeRD.XML(Aloaha_ZUGFeRD.iXML.ZUGFeRDProfile.comfort, False, LicenseKey)
' Arguments: input PDF, output ("" = replace input), your CodeB server, user, password,
' PAdES level, reason, location, contact, overwrite, licence, actual level (returned)
Dim level As String = ""
If alo.SignPDFRemote("C:\Rechnungen\RE-2026-0001_zugferd.pdf", "C:\Rechnungen\RE-2026-0001_signiert.pdf", _
"https://YOUR-CODEB-SERVER", "benutzer@firma.de", "YOUR-PASSWORD", "B-LTA", _
"Invoice approval", "Musterstadt", "", True, LicenseKey, level) Then
Console.WriteLine("Signed, level: " & level)
Else
Console.WriteLine("Error: " & alo.LastError)
End If
C#
var alo = new Aloaha_ZUGFeRD.XML();
alo.Licensekey = licenseKey;
string level = "";
bool ok = alo.SignPDFRemote(@"C:\Rechnungen\RE-2026-0001_zugferd.pdf", @"C:\Rechnungen\RE-2026-0001_signiert.pdf",
"https://YOUR-CODEB-SERVER", "benutzer@firma.de", "YOUR-PASSWORD",
"B-T", "Invoice approval", "Musterstadt", "", true, licenseKey, ref level);
Console.WriteLine(ok ? "Signed, level: " + level : "Error: " + alo.LastError);
VBA / VB6 (COM)
Dim alo As Object, level As String
Set alo = CreateObject("Aloaha_ZUGFeRD.XML")
alo.Licensekey = "YOUR-LICENCE-KEY"
If alo.SignPDFRemote("C:\Rechnungen\RE-2026-0001_zugferd.pdf", "C:\Rechnungen\RE-2026-0001_signiert.pdf", _
"https://YOUR-CODEB-SERVER", "benutzer@firma.de", "YOUR-PASSWORD", "B-LTA", _
"Invoice approval", "Musterstadt", "", True, "", level) Then
Debug.Print "Signed, level: " & level
Else
Debug.Print "Error: " & alo.LastError
End If
After updating to 11.0.0.2, re-register the type library so that COM clients see the new function.
Without files: SignPDFRemoteBytes
For web services and database applications, SignPDFRemoteBytes works directly with bytes and returns the signed PDF (or Nothing on error):
Dim signiert() As Byte = alo.SignPDFRemoteBytes(pdfBytes, "https://YOUR-CODEB-SERVER", "benutzer@firma.de", "YOUR-PASSWORD", "B-T")
If signiert Is Nothing Then Console.WriteLine(alo.LastError)
With a minimum level: the RemoteSigner class (from 11.0.0.3)
For servers and batch processing, version 11.0.0.3 and later provide a separate COM class Aloaha_ZUGFeRD.RemoteSigner. It signs just like SignPDFRemote (company seal via signDocBasic), but additionally offers:
- Minimum level (
MinLevel, defaultB-B): if the service delivers a lower level, the signature counts as failed and no file is written. - Reason for a downgrade (
LevelNote) as well as requested and produced level (RequestedLevel,EffectiveLevel). - Retry on rate limit (
MaxRetries): on HTTP 429 the class waits for the time given by the service and tries again. - Settings from the registry (
LoadSettings) for servers:HKLM\Software\Aloaha\ZUGFeRD\CSCwithBaseURL,User,PasswordProtected(encrypted for the machine with Windows DPAPI viaProtectPassword),Level,MinLevel,Reason,Location,Contact,TimeoutSeconds,MaxRetries.
Dim rs As New Aloaha_ZUGFeRD.RemoteSigner
rs.LicenseKey = "YOUR-LICENCE-KEY"
rs.ServerURL = "https://YOUR-CODEB-SERVER"
rs.UserName = "rechnungssiegel"
rs.Password = "YOUR-PASSWORD"
rs.Level = "B-LTA"
rs.MinLevel = "B-T" ' no signing without a timestamp
rs.Reason = "Invoice approval"
rs.MaxRetries = 2 ' batch processing: on HTTP 429 wait and retry
If rs.SealFile("C:\Rechnungen\RE-2026-0001_zugferd.pdf", "C:\Rechnungen\RE-2026-0001_signiert.pdf") Then
Console.WriteLine("Signed, level: " & rs.EffectiveLevel & " " & rs.LevelNote)
Else
Console.WriteLine("Error: " & rs.LastError)
End If
From VBA/VB6: Set rs = CreateObject("Aloaha_ZUGFeRD.RemoteSigner"), then the same properties. The class does not follow redirects – user name and password are only sent to the configured server URL. The password is never output.
Signature levels (PAdES)
| Level | Content | Use |
|---|---|---|
B-B | Basic signature (CMS with signing certificate) | simple integrity protection |
B-T | plus a timestamp from a time-stamping service (RFC 3161) | provable signing time |
B-LT | plus validation data (certificates, OCSP) in the PDF | validation without an online query |
B-LTA (default) | plus an archive timestamp | long-term archiving |
If the service cannot produce a higher level at the moment (e.g. because the time-stamping service is unreachable), it signs with the next lower level instead of aborting. The level actually produced is returned in the parameter EffectiveLevel (e.g. AdES-B-T). Always check it against your minimum requirement – most easily with RemoteSigner.MinLevel, the GUI setting minimum level or zugcmd -minlevel.
Signing a ZUGFeRD invoice: the order
- Create the invoice data and save it as XML (quick start VB.NET).
- Embed the XML into the PDF/A-3 with
MergeXMLIntoPDF. - Sign with
SignPDFRemotelast. The signature is appended as an incremental update; the content and the embedded XML remain unchanged. Any later change to the PDF invalidates the signature. - In your tests, check the signed PDF with a PDF/A checker (e.g. veraPDF) and an e-invoice validator. B-LT adds a
/DSSdictionary, B-LTA a document timestamp – both are permitted under PAdES.
Error handling
If the function returns False (or Nothing), the reason is in LastError. The password never appears in error messages.
| LastError | Meaning |
|---|---|
HTTP 401 … invalid_credentials | User name or password wrong, or password sign-in is not enabled for the tenant. |
HTTP 400 … pdf_encrypted_unsupported | The PDF is encrypted – decrypt it first. |
HTTP 429 … (Retry-After: 30 s) | Too many calls in a short time (limit: 30 per minute); try again after the time given – RemoteSigner.MaxRetries does this automatically. |
service delivered B-T, below the minimum B-LT | Only with RemoteSigner: the service could not reach the minimum level (e.g. validation data not available); no file was written. |
HTTP 301/302 … (redirect not followed) | The server URL redirects. For security reasons the SDK does not follow redirects – enter the final https address. |
PDF larger than 10 MiB | Limit of the signing service; the SDK checks it before sending. |
ServerURL must start with https:// | Unencrypted connections are not supported. |
License Problem | No valid SDK licence set. |
Without programming: ZUGFeRD GUI, PDF Viewer and zugcmd
The same remote signing is built into the Aloaha ZUGFeRD GUI (tab Sign PDF) and the Aloaha ZUGFeRD PDF Viewer (Tools > Sign PDF / ZUGFeRD PDF) from version 11.0.0.2. Enter server URL, user, password and signature level once under signature settings; test connection checks the credentials with a test PDF; during signing a progress window shows that the service is working. From version 11.0.0.3 the command-line tool zugcmd also signs remotely (-remoteurl, -remoteuser, -remotepw, -level) – ideal for batch processing.
Legal framework
The CodeB Remote Signature Service creates advanced electronic signatures (AdES) within the meaning of the eIDAS Regulation, not qualified signatures (QES). Qualified signatures (QES) are only created with a qualified signature card such as the Maltese eID or the D-Trust Card 5.1 – in the CodeB Wallet via NFC on the phone. An electronic signature is not required for e-invoices in Germany; it does, however, provide verifiable proof of the authenticity and integrity of the document. Whether a validator displays the signature as "trusted" depends on whether it trusts the issuing certificate.
Technical background
The function uses the endpoint signatures/signDocBasic of the CSC v2 interface (Cloud Signature Consortium): an HTTPS POST with basic authentication, the PDF in the request, the signed PDF in the response. More about the service: Remote signatures at CodeB.
Frequently asked questions
How do I sign a PDF via an API without a local certificate?
With SignPDFRemote of the Aloaha ZUGFeRD SDK: the function sends the PDF via HTTPS to the CodeB Remote Signature Service and saves the returned PAdES-signed PDF. A certificate or smartcard on the computer is not needed.
Does a ZUGFeRD invoice remain valid after signing?
Yes, if the XML is embedded first and the PDF is signed afterwards. The signature is appended incrementally; the content and the embedded invoice data remain unchanged.
Which signature level should I choose?
B-LTA (default) for archiving, otherwise at least B-T with a timestamp. The level actually produced is in the parameter EffectiveLevel after the call.
What does the CodeB EUID Wallet have to do with ZUGFeRD?
The CodeB Remote Signature Service used by SignPDFRemote is part of the CodeB EUID Wallet software. The EUID Wallet is therefore now also used for ZUGFeRD: the SDK, ZUGFeRD GUI, PDF Viewer and zugcmd sign e-invoices via its signing service.
What is the CodeB Wallet?
The app for the CodeB EUID Wallet: a wallet for the European Digital Identity (EUDI) under eIDAS 2.0 for Android phones. It stores identity data, the mobile driving licence and a membership card, checks IDs and signs PDFs. It is not certified; access is by invitation.
Do I need the CodeB Wallet to sign invoices with the SDK?
No. SignPDFRemote, the ZUGFeRD GUI, the PDF Viewer and zugcmd use the EUID Wallet's signing service directly, server to server. The app is intended for signing on the phone.
Can I use phone.codeb.io in production?
No. https://phone.codeb.io is only CodeB's test server and is not intended for production environments. For production, enter the URL of your own CodeB server.
Is this a qualified electronic signature?
No. The service, and therefore SignPDFRemote, creates advanced electronic signatures (AdES) under eIDAS. A qualified signature (QES) is created with a qualified signature card such as the Maltese eID or the D-Trust Card 5.1, for example in the CodeB Wallet. No signature is required for e-invoices in Germany.
Can I call SignPDFRemote from VBA or VB6?
Yes. The function is part of the COM interface iXML and available via CreateObject("Aloaha_ZUGFeRD.XML"); re-register the type library after the update.