Guides
Verification and evidence
Every completed document carries its own proof: per-signer PAdES signatures, a final sign.yt platform seal, a certificate of completion and a hash-chained audit trail. Anyone can verify it, without an account.
Legal positioning#
sign.yt produces simple electronic signatures (SES) under Regulation (EU) No 910/2014 (eIDAS), sealed by the platform. Under eIDAS an electronic signature cannot be denied legal effect or admissibility as evidence solely because it is electronic. The evidence features below (signer verification, consent, audit trail, sealing and time-stamping) make a signature easier to prove, but sign.yt does not guarantee classification as an advanced (AdES) signature, is not a qualified trust service provider, and does not itself create qualified electronic signatures (QES).
Where a qualified signature is required, the organization can configure signing through an external qualified trust service provider (recipient signing method QES, configured per organization in the app); the qualified signature is then created by that provider, not by sign.yt. Whether SES is sufficient for a given contract is a legal question for the parties.
What is in a signed PDF#
- Certificate of completion: a page appended before signing (so the signatures cover it) with a per-recipient timeline (verification steps, signing time, IP address, device, approximate location), the consent statement and its hash, and a QR code with the public verification link. Organizations can turn this page off in branding settings.
- One PAdES signature per signer, made with a per-signer certificate issued by the sign.yt platform CA.
- The sign.yt platform seal over the whole document, applied last. With a timestamp authority available, signatures are PAdES-B-T and the final seal is upgraded to PAdES-B-LTA (validation data plus a document timestamp). If every timestamp authority is unreachable the document is still sealed without a timestamp and a timestamp is added later automatically.
Any change to the file after sealing, other than long-term validation updates, breaks the seal and shows up in verification.
Audit trail and signatures#
GET /documents/{id}/audit(JSON) andGET /documents/{id}/audit.csvreturn every event: creation, sends, views, verification, signing, downloads, with actor, IP and metadata. The audit log is append-only and hash-chained.GET /documents/{id}/signatureslists each signature with signer, time, IP, user agent andevidence_hash; signatures form their own hash chain that is checked before a document completes.GET /documents/{id}/evidence.zip(completed documents only, else409) downloads an evidence bundle:signed.pdf,audit-trail.pdf, OpenTimestamps files,pq-seal.json, the platform seal certificate,manifest.json,SHA256SUMSand a README with offline verification steps.
curl -sS -o evidence.zip "https://api.sign.yt/v1/documents/$DOC_ID/evidence.zip" \
-H "Authorization: Bearer $SIGNYT_API_KEY"Identity verification (ID check)#
With verification_type: ID_VERIFIED each signer must prove their identity through an external identity provider before they can open and sign the document. The check is identity evidence recorded with the signature; it is not itself an electronic signature.
| Provider | How the signer verifies | Coverage |
|---|---|---|
| Didit | Photo of an ID document plus a selfie with liveness check, in Didit's hosted flow. Some cases go to manual review. | Worldwide |
| Authologic | The source chosen in the Authologic flow: mObywatel, bank login, e-ID or document plus selfie. | Mainly Poland and the EU |
| login.gov.pl (mObywatel) | Polish national login (Węzeł Krajowy): mObywatel, trusted profile or bank. | Poland |
Availability and setup#
- Plans: Professional, Business and Enterprise. Each completed verification is billed per your plan; attempts that expire without a provider decision are not billed.
- Platform providers are configured by the sign.yt operator in Admin → Identity checks. For Didit that is the API key, the webhook secret and the workflow ID. The page shows the callback URL to register in the provider console,
https://<app host>/api/v1/idv/callback/<provider>(for Didit:…/api/v1/idv/callback/didit). Keys are stored encrypted and never shown again. - Organization admins turn identity checks on in Settings → Identity verification, choose the allowed providers and methods, and set name matching. Senders then pick the ID check level when creating a document.
Flow and statuses#
- The signer opens their signing link and sees the verification step instead of the document.
- They choose a provider and complete its flow. sign.yt never passes the signing link to the provider.
- The provider reports the result by signed callback; while the signer's page is open, sign.yt also asks the provider directly, in case a callback is lost.
- When the attempt is
VERIFIED, the document opens and the signer can sign.
| Status | Signer sees | Sender sees / gets |
|---|---|---|
PENDING | Waiting for the result; the page refreshes itself. | “In progress”. |
IN_REVIEW | The provider is reviewing the case by hand; they can close the page and get an email with the result and their signing link. | “In manual review”. |
VERIFIED | Verified as their name; signing is unlocked. | “Verified”. |
MISMATCH | The verified name does not match the recipient; signing is blocked. | “Name mismatch” and an email. Correct the recipient and resend. |
FAILED | Verification did not complete; they can try again while attempts remain. | “Failed”. An email when the check was declined or abandoned, not when it simply expired. |
The sender's view is the document page in the app and recipients[].identity_verification in GET /documents/{id}: the latest attempt's status, provider, provider_label and updated_at (null when no attempt was made). Every status change also emits the recipient.identity_verification_updated webhook.
Retries and name matching#
- Up to 5 attempts per recipient (each attempt costs money). Only one attempt can be open at a time; an attempt with no decision after 2 hours expires, unless it is in manual review.
- Name matching compares the recipient name with the provider's verified first and last name: strict (the default; every part of the recipient name must appear and it must include a first and a last name), surname only, or off (record the identity without comparing). Case and diacritics are ignored, so “Łucja” matches “Lucja”. A failed match ends the attempt as
MISMATCH.
Evidence and data minimisation#
- The audit trail records the start, review, result and reason of every attempt. A verified signer's entry on the certificate of completion reads “Identity verified via <provider> (<method>) at <time>, ref <provider reference>”.
- sign.yt keeps only the verified name, date of birth and a masked PESEL (last 4 digits), encrypted at rest. It never stores the full PESEL, document number or document images; those stay with the provider. Senders and webhooks get the status only.
Public verification#
Completed documents get a 16-character verification code. The certificate of completion prints it as a QR code linking to https://verify.sign.yt/<code>, and the completion email includes the link. The page shows the status, masked signer names and signing times, the final PDF hash and the seals; it never shows the title, emails or phone numbers. Anyone can also upload a PDF at verify.sign.yt.
The same checks are available as public endpoints. They need no API key and are rate-limited per IP (10 requests per 10 minutes for /verify, 10 per minute for /pq/verify):
| Endpoint | Description |
|---|---|
POST /api/v1/verify | Multipart file (PDF, up to 30 MB). Validates every signature and returns a report. |
GET /api/v1/verify/code/{code} | Public summary for a verification code. |
POST /api/v1/pq/verify | Multipart file (PDF) and optional seal (JSON). Checks the post-quantum seal. |
GET /api/v1/pq/public-keys | Post-quantum seal public keys (current first). |
curl -sS -X POST "https://api.sign.yt/v1/verify" -F "[email protected];type=application/pdf" \
| jq '{verdict, signed_by_signyt, signatures: [.signatures[] | {signer_subject, signing_time, intact, trusted, is_platform_seal}]}'The report's verdict is one of:
| Verdict | Meaning |
|---|---|
trusted | All signatures are intact and made by the sign.yt seal, the sign.yt CA or a trusted root. |
untrusted | Intact, but at least one signer is not known to sign.yt. |
tampered | A signature is broken or the file was modified after sealing. |
unsigned | No signatures found. |
The report also lists every signature (signer_subject, signer_issuer, signing_time, intact, trusted, covers_whole_doc, modification_ok, is_platform_seal, is_timestamp), warnings, the Bitcoin anchor status and, when enabled, an independent validation by the European Commission's DSS validator (eidas). Because the PDFs are standard PAdES, any PAdES validator (for example Adobe Acrobat or the EU DSS demonstration) can check them too.
Post-quantum seal#
In addition to PAdES, completed documents can carry a supplementary hybrid ML-DSA-65 (FIPS 204) + Ed25519 seal over a manifest of the final PDF hashes (SHA-256 and SHA3-512), the original PDF hash, the audit and signature chain heads, the signers and the PAdES details. Both signatures must verify. It is extra evidence intended to stay verifiable if classical signatures are broken in the future; it is not itself a qualified or PAdES signature.
curl -sS -o seal.json "https://api.sign.yt/v1/documents/$DOC_ID/pq-seal" \
-H "Authorization: Bearer $SIGNYT_API_KEY"
curl -sS -X POST "https://api.sign.yt/v1/pq/verify" \
-F "[email protected];type=application/pdf" -F "[email protected];type=application/json" \
| jq '{valid, mldsa_valid, ed25519_valid, pdf_hash_match, key_certified}'OpenTimestamps anchoring#
When a document completes, sign.yt anchors a commitment (document ID, final PDF hash, audit-trail PDF hash and audit chain head) in the Bitcoin blockchain through public OpenTimestamps calendars. The proof is usually confirmed within hours; its status is PENDING, CONFIRMED (with block height) or FAILED. This gives an independent proof that the document existed in this form at that time.
GET /documents/{id}/timestamp: status, digest, commitment, block height, confirmation time.GET /documents/{id}/timestamp.ots: the.otsproof for use with the standard OpenTimestamps client (ots verify).GET /documents/{id}/timestamp/audit-trail.pdf: the standalone audit-trail PDF covered by the commitment.
All of these endpoints are under /documents and need documents:read.