Skip to content

About

Verify digital signatures in any PDF. One API call. No API key. Free.

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Latest commit

Β 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

API Status No Auth Rate Limit License

πŸ” verify-pdf

Verify digital signatures in any PDF. One API call. No API key. Free.

Check who signed a document, when it was signed, and whether it's been tampered with.

POST https://api.econtract.online/verify-pdf

🌐 Try it now β€” verify.econtract.online


⚑ Quick Start

curl -X POST https://api.econtract.online/verify-pdf \
  -F "file=@contract.pdf"

Response:

{
  "document": {
    "filename": "contract.pdf",
    "hash": "sha256:a11f904a0b23f1c8...",
    "size": 245780,
    "tampered": false
  },
  "signatures": [
    {
      "signer": {
        "name": "John Doe",
        "email": "john@acme.com",
        "organization": "Acme Corp",
        "country": "US"
      },
      "signed_at": "2026-03-21T10:54:51.000Z",
      "verdict": "valid",
      "integrity": true,
      "signature": true,
      "chain": true,
      "expired": false,
      "certificate": {
        "issuer": "CN=eContract CA,O=eContract",
        "serial": "7A3B...",
        "valid_from": "2025-03-21",
        "valid_until": "2029-03-21"
      },
      "timestamp": {
        "time": "2026-03-21T10:54:52.000Z",
        "tsa": "DigiCert Timestamp Authority"
      }
    }
  ],
  "summary": {
    "total": 1,
    "valid": 1,
    "invalid": 0,
    "verdict": "all_valid"
  },
  "verified_at": "2026-03-21T15:15:55.123Z",
  "verified_by": "eContract - https://verify.econtract.online"
}

πŸ“¦ Language Examples

JavaScript / Node.js

const form = new FormData();
form.append("file", fileInput.files[0]);

const res = await fetch("https://api.econtract.online/verify-pdf", {
  method: "POST",
  body: form,
});

const data = await res.json();

if (data.summary.verdict === "all_valid") {
  console.log("βœ… All signatures valid");
} else {
  console.log("❌ Verification failed");
}

Python

import requests

with open("contract.pdf", "rb") as f:
    res = requests.post(
        "https://api.econtract.online/verify-pdf",
        files={"file": f}
    )

data = res.json()
print(f"Verdict: {data['summary']['verdict']}")
print(f"Tampered: {data['document']['tampered']}")

for sig in data["signatures"]:
    print(f"  {sig['signer']['name']} β€” {sig['verdict']}")

PHP

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://api.econtract.online/verify-pdf");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, [
    "file" => new CURLFile("contract.pdf")
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = json_decode(curl_exec($ch));
echo "Verdict: " . $response->summary->verdict . "\n";
echo "Tampered: " . ($response->document->tampered ? "YES" : "No") . "\n";

Go

file, _ := os.Open("contract.pdf")
defer file.Close()

body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
part, _ := writer.CreateFormFile("file", "contract.pdf")
io.Copy(part, file)
writer.Close()

resp, _ := http.Post(
    "https://api.econtract.online/verify-pdf",
    writer.FormDataContentType(),
    body,
)
defer resp.Body.Close()

var result map[string]interface{}
json.NewDecoder(resp.Body).Decode(&result)
fmt.Println(result["summary"])

πŸ” What It Checks

Check Description
Integrity SHA-256 hash verification β€” has the document been modified after signing?
Signature RSA cryptographic signature validation
Certificate Chain Validates signer cert β†’ intermediate CA β†’ root CA
Certificate Expiry Are all certificates in the chain still valid?
Timestamp RFC 3161 TSA timestamp verification (when present)

Verdict Values

Verdict Meaning
all_valid All signatures verified, document intact
has_invalid One or more signatures failed verification
no_signatures PDF has no digital signatures

πŸ“‹ Supported Formats

  • βœ… PAdES β€” PDF Advanced Electronic Signatures (EU standard)
  • βœ… CMS / PKCS#7 β€” Embedded CMS signatures
  • βœ… RSA + SHA-256 β€” Standard cryptographic signatures
  • βœ… RFC 3161 β€” Trusted timestamps from any TSA
  • βœ… Multi-signature β€” Documents with multiple signers
  • βœ… Any signing tool β€” DocuSign, Adobe Sign, GlobalSign, eContract, or any PKI-based signer

πŸ€– AI Agent Integration

verify-pdf is built for AI agents that need to make trust decisions about contracts.

# AI agent workflow: verify before processing
result = requests.post(API_URL, files={"file": pdf}).json()

if result["document"]["tampered"]:
    return "REJECT: Document has been tampered with"

if result["summary"]["verdict"] != "all_valid":
    return "REJECT: Invalid signatures detected"

# Extract signer info for downstream processing
signers = [s["signer"]["name"] for s in result["signatures"]]
return f"APPROVED: Signed by {', '.join(signers)}"

From an MCP client (Claude, ChatGPT, Cursor, …)

The same check is the verify_pdf tool of the eContract MCP server, so an assistant can verify a PDF the user attaches without any code:

https://api.econtract.online/mcp

Setup for each client: contractlayer/contractlayer β†’ mcp. Connecting to the MCP server needs a free eContract account; verify_pdf itself needs no extra permission scope. The plain HTTP API above needs no account at all.

Use cases for AI agents:

  • Contract review automation β€” verify before analyzing content
  • CRM integrations β€” auto-validate incoming signed documents
  • HR systems β€” verify offer letters and employment contracts
  • Legal workflows β€” chain-of-custody signature validation

βš™οΈ API Reference

POST /verify-pdf

Request:

  • Content-Type: multipart/form-data
  • Field: file (PDF binary, max 50 MB)
  • Authentication: None required
  • Rate limit: 50 requests/day per IP

Response fields:

Field Type Description
document.filename string Original filename
document.hash string SHA-256 hash (sha256:...)
document.size number File size in bytes
document.tampered boolean true if document was modified after signing
signatures[] array List of signature objects
signatures[].signer.name string Signer common name
signatures[].signer.email string Signer email (if available)
signatures[].signer.organization string Signer organization
signatures[].signer.country string Signer country code
signatures[].signed_at string ISO 8601 signing timestamp
signatures[].verdict string "valid" or "invalid"
signatures[].integrity boolean Document integrity check
signatures[].signature boolean Cryptographic signature check
signatures[].chain boolean Certificate chain check
signatures[].expired boolean Certificate expiry check
signatures[].certificate object Certificate details
signatures[].timestamp object RFC 3161 timestamp (if present)
summary.total number Total signatures found
summary.valid number Valid signature count
summary.invalid number Invalid signature count
summary.verdict string "all_valid", "has_invalid", or "no_signatures"

Error responses:

// 400 β€” Invalid file
{ "statusCode": 400, "message": "No PDF file provided" }

// 413 β€” File too large
{ "statusCode": 413, "message": "File size exceeds 50MB limit" }

// 429 β€” Rate limited
{ "statusCode": 429, "message": "Rate limit exceeded. Try again tomorrow." }

πŸ—οΈ Self-Hosting

Coming soon. We're working on a Docker image for self-hosted deployment.

In the meantime, use the free hosted API at api.econtract.online.


πŸ—ΊοΈ Roadmap

  • PAdES / CMS signature verification
  • Certificate chain validation
  • RFC 3161 timestamp verification
  • Free hosted API (live)
  • Web UI at verify.econtract.online
  • Trust Store v2 (Mozilla CA bundle + Adobe AATL)
  • CRL / OCSP revocation checking
  • Docker image for self-hosting
  • npm / pip packages
  • Webhook notifications
  • Batch verification endpoint

πŸ”— Related Projects

Project Description
contractlayer The eContract MCP server and a config for every AI client
contract-manager Send contracts for e-signature with the REST API (Node.js, Python)

πŸ“„ License

MIT β€” free for commercial and personal use.


Built by eContract
Tamper-proof digital signatures for the modern web.

About

Verify digital signatures in any PDF. One API call. No API key. Free.

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors