Electronic signatures
This page explains what an electronic signature produced by this platform is, what it is not, what rights a signer has, and how any third party can check a signed document for themselves.
The address of this page is printed inside every certificate of completion. It carries no reference to any particular agreement. To check a document, compute its SHA-256 and submit that value as described in Verify a signed document below.
What our electronic signatures are
Section titled “What our electronic signatures are”- Electronic signatures compliant with the US ESIGN Act and UETA.
- Valid electronic signatures under eIDAS Article 25(1): admissible, and not denied legal effect for being electronic.
- Tamper-evident. Every completed document is sealed and hash-verifiable, and any modification is detectable.
- Bound to a verified identity, with the verification evidence referenced in the certificate.
- Backed by a complete, timestamped audit trail, retained and reproducible on demand.
What our electronic signatures are not
Section titled “What our electronic signatures are not”We do not make any of the following claims, and you should not make them on our behalf.
| We do not claim | Why |
|---|---|
| “eIDAS Advanced Electronic Signature (AdES)” or “AdES-compliant” | Article 26(a) and 26(c) are not met with a platform key: the signature-creation data is under our sole control, not the signatory’s. What we apply is an electronic seal (Article 3(25)), not an advanced signature. |
| “Qualified Electronic Signature” or “legally equivalent to a handwritten signature” in the EU | Article 25(2) applies to qualified signatures only. |
| “Digitally signed with a trusted certificate”, or a green check mark in a PDF reader | That requires a certificate from a trust list we do not participate in. |
| “Notarized”, “witnessed” or “certified” | No notary or witness takes part in the ceremony. |
| “Legally binding” as an unqualified absolute | Whether an agreement binds depends on the underlying contract and the signer’s capacity, not on the signing platform. |
| 21 CFR Part 11 compliance | The platform is not validated against that rule. |
The signer’s rights before signing
Section titled “The signer’s rights before signing”Before a signer can sign, they are shown an electronic-records consent disclosure and must agree to it. The disclosure is written by us, is versioned, and is hashed. The signature record stores the version and the hash, so the exact text a signer agreed to can be identified afterward, and the certificate of completion records that they accepted it and when. Published text is never edited: a change of wording is a new version.
The disclosure states all seven items ESIGN section 101(c) requires:
- The right to receive the record on paper.
- The right to withdraw consent, and what happens if it is withdrawn.
- Whether the consent covers this transaction only or a category of transactions. Ours covers this transaction only.
- How to withdraw consent and how to update contact details.
- How to obtain a paper copy, and any fee. There is no fee.
- The hardware and software needed to read, sign and keep the records.
- Notice of changes to those requirements.
Each right has a stated procedure for both windows: one for while the signing session is live, and one for after it ends. Neither is a “contact support” dead end.
- Withdraw consent. Exercisable in-product for as long as the signing session is live, through a
control on the signing page. Withdrawing costs nothing and applies no penalty. What it does depends
on when it happens, and the product says which case a signer is in rather than leaving them to
guess:
- Before signing. The signing session ends, no electronic signature is recorded, and the business that sent the link is told the signer stopped using electronic records. Withdrawing does not request a paper copy: that is the separate right described below. A later attempt to sign on that same link is refused rather than quietly accepted.
- After signing. The document already signed still stands, because a signature cannot be taken back after the fact. The withdrawal is still recorded and the business that sent the link is still told. The product states that plainly instead of implying the signature was undone.
- Once the session has ended. The disclosure the signer read states the route for this window: contact the business that sent the link. The right does not lapse; it is exercised by that route rather than by a control on a page the signer no longer has open.
- Request a paper copy. The right to a paper record survives the signature. While the signing session is live, a control on the signing page requests one: the request is passed to the business that sent the link, which sends the paper copy, and a repeat request while one is still outstanding does not create a second obligation. Once the session has ended, the disclosure states the route for that window: contact the business that sent the link. There is no fee either way. Separately and immediately, the signer can save their own copy from the download control, and, if the business turned that on, the signed record is emailed to them when signing completes.
While the signing session is live, both controls are rendered by the platform on both delivery surfaces: the hosted signing page and the signing experience embedded in a customer’s own site. An integrator embedding the signing experience must not hide or suppress them. Once the session has ended neither control is rendered, on either surface: 15 U.S.C. section 7001(c)(1)(B) requires the disclosure to state the procedure, which it does for both windows, and the entitlement is undiminished by the absence of a button.
Document classes we do not sign
Section titled “Document classes we do not sign”ESIGN section 103 (15 U.S.C. section 7003) carves several classes of document out of electronic-signature coverage. Those classes cannot be created on this platform: they are not selectable values, and the platform stores only the class an operator actually chose from the permitted list. When a workflow author creates a document template they pick a permitted class and acknowledge the carve-out list.
The carved-out classes are:
- Wills, codicils and testamentary trusts.
- Adoption, divorce and other family law matters.
- The Uniform Commercial Code, except Articles 2 and 2A.
- Court orders and other official court documents.
- Notices canceling a utility service.
- Notices of default, acceleration, repossession, foreclosure or eviction from a primary residence.
- Notices canceling health or life insurance benefits.
- Product recall notices affecting health or safety.
- Documents required to accompany the transport of hazardous materials.
Two boundary cases read like carve-outs and are not. Leases and sales of goods fall under UCC Articles 2A and 2, which section 7003(a)(3) excepts back in, so a residential lease is a permitted class. It is the eviction notice on a primary residence that is carved out, not the tenancy itself.
The permitted classes are: rental or lease agreement, service or sales agreement, employment or contractor agreement, non-disclosure or confidentiality agreement, consent or authorization, disclosure or acknowledgment, waiver or release, and other. “Other” exists so an operator is never forced to mis-describe a permitted agreement to get it signed.
Verify a signed document
Section titled “Verify a signed document”Verification takes a hash, never the file. You compute the SHA-256 of the PDF you are holding and send that value. We never ask you to upload a signed contract in order to prove it was signed, and there is no variant of this endpoint that accepts bytes.
Check a document on this page
Section titled “Check a document on this page”The check below runs in your browser. It hashes the file locally, asks every region, and reports the combined answer, so you do not need to know which region produced the document. The file is never uploaded.
This check runs entirely in your browser, so it needs JavaScript. With scripting turned off, use the two steps above instead: hash the file with shasum -a 256, then send that value to each region's endpoint listed below.
Hashing the file, then asking every region.
Choose a file first, then select Check this document.
This browser cannot compute a SHA-256 on this page, which usually means the page was not loaded over HTTPS. Use the command line step above instead, then send the value with thecurl call.
That file could not be read. Try selecting it again, or hash it on the command line with the step above.
Verified. The hash matches a sealed document, and its seal verifies under a published key and covers that exact record.
Not verified. A region holds a record for this hash and its answer is not a match. Read that region's answer below, then look it up in the table further down this page.
We could not check every region. Do not read this as a result about your document, and do not record it as one. Try again in a few minutes, or send the hash to each region's endpoint yourself with the curl call above.
No signed document with that hash. Every region answered, and none of them holds a sealed document with this hash. The usual reasons are that the file was changed after it was signed, or that this is not the sealed copy. Ask the business that sent it for the sealed copy, then check that copy here.
.What this answer means.This page does not describe that answer yet, so treat it as not verified and ask the business that sent the document for a current copy.No usable answer came back from: . Until every region answers, this is not a complete check. Try again in a few minutes, or send the hash to that region's endpoint yourself with the curl call above.
This is a test-mode record. Test mode is free and produces synthetic records with no legal effect whatsoever. Do not accept it as a signed agreement.
The numbered steps that follow are the same check written out. They are the specification, not a shortcut: run them yourself, or build them into your own system, and you can confirm a signature without trusting anything on this page. That matters here, because a page that prints the word “Verified” is exactly the claim you are trying to check.
1. Hash the file you are holding
Section titled “1. Hash the file you are holding”In a browser or in any runtime with the Web Crypto API:
const bytes = new Uint8Array(await file.arrayBuffer());const digest = await crypto.subtle.digest('SHA-256', bytes);const sha256 = [...new Uint8Array(digest)].map((b) => b.toString(16).padStart(2, '0')).join('');On the command line:
shasum -a 256 signed-agreement.pdfEither way the value is 64 lowercase hexadecimal characters.
Every download of a signed file also carries the same digest as an RFC 9530 response header, so a system that fetched the file can compare without hashing it again:
Repr-Digest: sha-256=:<base64 of the same 32 bytes>:That header is base64, while the endpoint below takes hex. It is the same digest in two encodings, computed over the bytes of that response.
2. Submit the hash
Section titled “2. Submit the hash”curl -X POST https://api.us.checktiv.com/v1/esign/verify \
-H 'content-type: application/json' \
-d '{"sha256":"<the 64 hex characters>"}'
The endpoint needs no API key. It answers 200 for every verification outcome, including the
negative ones. A non-JSON body is 415, a value that is not a 64-character lowercase hex string is
422, and an oversized or unmeasurable body is 413.
3. Read the answer
Section titled “3. Read the answer”The response always carries three fields: protocol_version, match and status.
match is the stable one-bit answer. It is true exactly when status is verified, and it will
never gain a third value.
status |
match |
What it means | What to do |
|---|---|---|---|
verified |
true |
The hash resolves to a sealed document, and the seal verifies under a published key and covers that exact record. | Accept the document. |
not_found |
false |
This region holds no sealed document with that hash. | Try the other region before concluding. See One region is not the whole answer. |
not_signed |
false |
The agreement exists but has not been signed, so there is no signature to report. | Nothing is wrong with the file. There is simply no signature yet. |
unsealed |
false |
The signature was recorded, but the sealed artifact was not produced. | Ask the business that sent the document to complete it. This is not a sign of tampering. |
unknown_key |
false |
The seal names a key that is not in the published key set for this region. | Retry, and if it persists, contact the business that sent the document. |
revoked_key |
false |
The seal verifies, but the key that produced it has been revoked. | Treat the seal as no longer trustworthy and ask the business that sent the document for a re-issued copy. |
bad_signature |
false |
The signature itself does not verify under the published key. The file or the seal has been altered, or the seal was never ours. | Do not accept the document. Contact the business that sent it. |
claim_mismatch |
false |
The signature verifies and the seal is ours, but its claims name a different agreement, document, organization, mode or region. | Usually the wrong record was looked up. Re-check that the hash came from the file you mean. |
chain_unavailable |
false |
The signature verifies, the seal is ours, and it covers this exact document. The signing-ceremony record that the seal points to is not held in this region, so we cannot confirm that one last claim. | Do not read this as a negative result about the document. Try the other region, then ask the business that sent it for a current copy. |
unsupported_format |
false |
The document was sealed in a container format this region does not support. | Retry later, or try the other region. Do not read this as a negative result about the document. |
verification_unavailable |
false |
This region could not verify anything at all right now. This is a statement about us, not about your document. | Retry rather than conclude. Do not record a negative result from this status. |
Forward compatibility: two rules to build against
Section titled “Forward compatibility: two rules to build against”This endpoint is permanently public and permanently unauthenticated. There is no deprecation channel and no way to reach an integrator later, so the two rules below are published as instructions rather than as caveats. Following them is what lets us add a status without breaking your integration.
- Treat an unrecognized
statusas not verified. Readmatchfor the yes-or-no answer and readstatusonly for the explanation. A value you have never seen is never a match. - Treat
sealas optional before you treat it as a tagged union.sealis absent on five of the eleven statuses:not_found,not_signed,unsealed,unsupported_formatandverification_unavailable. Check that it is present, then branch onseal.format. An unfamiliarformatmeans “this region cannot check that seal”, not “this document is not genuine”.
Absent means the key is not on the wire at all. It is never null.
4. Check the seal yourself, offline
Section titled “4. Check the seal yourself, offline”You do not have to take our boolean for it. When seal is present it carries the seal token exactly
as we stored it, and our public keys are published as a standard JWK Set.
GET /.well-known/esign-keysEach entry is an Ed25519 verification key with kty: "OKP", crv: "Ed25519", alg: "EdDSA",
use: "sig", the base64url public key in x, its kid, a status of active, retired or
revoked, and a notBefore timestamp. Retired keys keep verifying and are never removed: a seal has
to stay checkable for the whole retained life of the document it covers.
The seal token is three dot-separated parts: <format>.<base64url payload>.<base64url signature>.
The signature covers the UTF-8 bytes of the first two parts joined by a dot, format prefix
included.
const res = await fetch('/v1/esign/verify', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ sha256 }),});const body = await res.json();
// Rule 2: optional first, tagged union second.if (!body.seal) throw new Error(`no seal to check (status: ${body.status})`);if (body.seal.format !== 'ed25519_detached_token_v1') { throw new Error('this deployment cannot check that seal format');}
// The kid lives inside the signed claims. `payload_json` is a JSON STRING.const claims = JSON.parse(body.seal.payload_json);
const jwks = await fetch('/.well-known/esign-keys').then((r) => r.json());const jwk = jwks.keys.find((k) => k.kid === claims.kid);if (!jwk) throw new Error('no published key for that kid');
const key = await crypto.subtle.importKey('jwk', jwk, { name: 'Ed25519' }, false, ['verify']);
// Verify over the TOKEN, never over a re-serialization of the parsed claims.const [format, payloadB64, signatureB64] = body.seal.token.split('.');const signingInput = new TextEncoder().encode(`${format}.${payloadB64}`);const fromBase64Url = (s) => Uint8Array.from(atob(s.replace(/-/g, '+').replace(/_/g, '/')), (c) => c.charCodeAt(0));
const ok = await crypto.subtle.verify( { name: 'Ed25519' }, key, fromBase64Url(signatureB64), signingInput,);Verify over seal.token, never over a re-serialization of the parsed claims. The signature covers
the exact payload string inside the token. Re-encoding a parsed object can reorder its keys, and a
re-encoded payload verifies only by accident. payload_json is published as a JSON string for the
same reason: it is byte-identical to the payload the signature covers.
The claims tell you which record the seal binds: the agreement and document ids, the final hash, the
signing region and mode, the position it pins in the document’s event chain, when it was sealed, and
which key signed it. A verifying signature over claims that name a different record is what the
claim_mismatch status reports.
What the response tells you, and what it does not
Section titled “What the response tells you, and what it does not”A caller who can present a matching hash already holds, or was handed, the document. The response therefore returns the identifiers that are readable off the file itself: the agreement and document ids, which document this is out of how many, the final hash, the signature methods used, whether the record is live or test, the current position of the event chain, and any attestation recorded after sealing.
Deliberately not returned: no party names, no email addresses, no phone numbers, no document title, and no short human-quotable agreement reference. Party details are encrypted at rest and this path never decrypts anything.
The organization is identifiable. The seal binds the owning organization’s identifier as one of its signed claims, and it has to: without that binding the same signature would validate against a different organization’s agreement. Because the endpoint publishes the seal token so that the seal can be checked independently, it publishes those claims with it. Treat the owning organization’s identifier as disclosed to anyone who holds the document. The claims deliberately carry nothing stronger: no signer name and no contact details ride in them.
One region is not the whole answer
Section titled “One region is not the whole answer”The platform runs as independent regional deployments and does not copy tenant data between them. Each
region answers only from its own database. A document sealed in one region returns not_found from
the other, because the record is not there.
A single region’s not_found is not a statement about whether the document exists. A third party
implementing this check should query every published region and report the union of the answers, and
should never report “not found” while a region has not answered. This page is region-less and the
check above already does it: it asks every region listed below and
reports the combined answer.
| Region | Verification endpoint |
|---|---|
| US | https://api.us.checktiv.com/v1/esign/verify |
| EU | https://api.eu.checktiv.com/v1/esign/verify |
Test-mode records have no legal effect
Section titled “Test-mode records have no legal effect”Test mode is free, and a test organization can drive the whole signing ceremony. Every response
reports mode, and a mode of test means the record is a synthetic test artifact with no legal
effect whatsoever, whatever else the response says. Do not accept a test-mode record as a signed
agreement.
Test-mode documents are also sealed under a key that the published live key set does not contain, so a test-mode seal can never verify as a live one.
Retention
Section titled “Retention”A signed document and its audit trail are kept for the retention period configured on the workflow that produced them, up to seven years. The certificate of completion records the retention policy that was applied and the region the record lives in. Deleting a signed agreement early would destroy the thing the signature exists to evidence, so the default sits at the ceiling in every region.
Once a signing-ceremony record is no longer held, the verification endpoint answers
chain_unavailable for the documents it covered. That is a statement about what we still hold, never
a finding about the file: the seal is still checked, and it still has to verify under a published key
and cover that exact document before you see that status at all. You can also check the seal yourself
offline, with no help from us, for as long as you keep the file.
Where to learn more
Section titled “Where to learn more”- Modes and regions for how test mode and regional isolation work.
- Compliance settings for data residency and the sub-processor list for your organization.