Explain PDF digital signature status and trust warnings
A PDF signature result can look contradictory: a signature may be cryptographically valid while the signer is unknown, or a certificate may be expired even though the document has not changed.
Run — free
This capability turns four common validation flags into a concise trust assessment, individual findings, and a practical next step. It does not recheck the PDF or certificate itself. Instead, it explains the evidence your validator already produced, helping readers distinguish document integrity from signer identity and certificate timing before deciding whether to rely on a signed file.
Read validity and document integrity as separate signals
The valid flag reports whether the signature passed the validator's cryptographic check. That is important, but it is not a complete verdict about every aspect of trust. The modified-since-signing flag answers a closely related question: whether the current bytes or permitted document state differ from what the signer originally covered. When modification is reported, the current PDF should not be treated as the signed version, even if another status says the signature itself is valid. The apparent contradiction usually means that a signature object can still be mathematically checked while the document now contains later changes. A false valid flag is also decisive: the signature cannot be relied on as proof of integrity. If validity is true and modification is false, the evidence supports integrity, but signer identity and certificate timing may still require review. The explanation therefore gives failed validity or reported modification priority over softer warnings. It describes what each supplied flag says rather than collapsing every condition into a vague green or red badge.
Distinguish an unknown signer from a damaged signature
Unknown-signer is an identity and trust-chain warning, not necessarily evidence that the PDF was altered. A validator may successfully confirm the cryptographic signature yet lack the root certificate, intermediate certificate, organizational policy, or local trust decision needed to recognize the signer. In that combination, the document may be intact while the person or organization behind the certificate remains unverified. The appropriate response is independent confirmation: inspect the certificate chain, compare signer details with a trusted source, and obtain the certificate or document through an authenticated channel. Do not assume that a familiar display name proves identity, because names shown in a PDF can be misleading without a trusted chain. Conversely, an unknown-signer flag does not by itself mean malicious tampering. This capability labels that situation as needing review unless a stronger integrity failure is also present. When the flag is explicitly false, the output records only that the validator did not report the signer as unknown; it does not invent details about the authority, revocation checks, or validation policy that were never supplied.
Interpret certificate expiration in the signing timeline
An expired certificate needs timing evidence. Expiration today does not automatically prove that a signature was invalid when it was created. A trusted timestamp can show that signing occurred while the certificate was within its validity period, and long-term validation data may preserve evidence about the certificate chain and revocation state. Without that evidence, an expired-cert warning leaves an important question unresolved. The explanation therefore recommends checking the timestamp, certificate dates, and revocation information instead of declaring every expired certificate fraudulent. Combinations matter: expiration plus an unknown signer creates both identity and timing concerns, while expiration plus a modified document is dominated by the integrity failure because the current file is not the state that was signed. Treat the result as guidance about the supplied flags, not a substitute for validation software or legal advice. For sensitive contracts, regulated records, or financial approvals, retain the original file and full validation report, confirm the validator's trust settings, and involve the responsible security or compliance team before accepting the document.
What you can do with it
Explain a confusing validator badge
Turn several technical warnings into one readable assessment without pretending to revalidate the PDF.
Triage signed documents
Identify files that should be rejected immediately and those that need signer or timestamp review.
Add context to an audit record
Store a deterministic explanation beside raw signature flags so later reviewers understand the decision.
FAQ
Does this capability verify the PDF itself?
No. It explains status flags produced by a PDF signature validator; it does not inspect a PDF, certificate, timestamp, or revocation service.
Can a signature be valid when the signer is unknown?
Yes. Cryptographic integrity can pass while the validator cannot build a trusted identity chain for the signer.
Does an expired certificate always make a signature invalid?
No. A trusted timestamp and preserved validation evidence may show that the certificate was valid at signing time, but that evidence must be checked.
What happens if the PDF was modified after signing?
The current document should not be trusted as the state covered by the signature. Obtain an original copy and validate it again.
What does the API request cost?
Each API request costs $0.002. The result is deterministic for the same supplied flags.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/pdf/signature-verify-status-explain \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"valid":true,"modified_since_signing":false}'const res = await fetch("https://api.kit.forhosting.com/pdf/signature-verify-status-explain", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"valid": true,
"modified_since_signing": false
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/pdf/signature-verify-status-explain",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"valid": true,
"modified_since_signing": false
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/pdf/signature-verify-status-explain", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"valid":true,"modified_since_signing":false}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"valid":true,"modified_since_signing":false}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/pdf/signature-verify-status-explain", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"valid": true,
"modified_since_signing": false
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "pdf.signature_verify_status_explain",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
max_mb | 25 |
max_pages | 200 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |