Developers

API Reference

v1 · Updated April 2026 · openapi.json

The ProofLedger API lets integrators submit SHA-256 hashes for dual-chain anchoring (Polygon and Bitcoin), retrieve proof status, and verify proofs independently. Authentication-required endpoints are available on the PRO and BUSINESS plans; a public, no-auth verify endpoint is available to any third party who needs to confirm a proof.

01 Overview

All requests are made against https://proofledger.io. All responses are JSON, UTF-8 encoded. The API is versioned under /api/v1/; breaking changes will ship under a new version prefix.

MethodPathPurposeAuth
POST /api/v1/proof Submit a SHA-256 hash for anchoring PRO or BUSINESS key
GET /api/v1/proof/:id Retrieve proof status and anchor details PRO or BUSINESS key
GET /api/v1/verify Verify any proof by SHA-256 hash Public

The API is intended for integrations where evidence is produced at scale — claims-intake systems, forensic pipelines, inspection apps, CMS watermarking hooks. For occasional single-file work, the web dashboard is usually simpler.

02 Authentication & Access

a. API keys require PRO or BUSINESS plan

Proof submission and retrieval require an API key. Keys are issued from the Account page, and are available to accounts on the Elevated (PRO) and Formal (BUSINESS) plans. Free, Creator, and pay-as-you-go accounts cannot generate keys.

PRO plans get rate-limited API access for prototyping and small-scale production. BUSINESS plans get higher rate limits and dedicated support for high-volume integrations.

Upgrade at Pricing or contact support@proofledger.io for enterprise volumes.

b. Creating a key
  1. Sign in to your account.
  2. Scroll to the API Keys section.
  3. Enter a label (e.g. "Claims Intake") and click Create Key.
  4. Copy the key immediately — it is shown once and cannot be retrieved later.

Keys look like sk_ab12cd34_.... Store them as you would any secret: environment variable, secrets manager, or vault. Never commit keys to source control or send them in query strings.

c. Sending the key

Pass the key as a Bearer token in the Authorization header:

Authorization: Bearer sk_ab12cd34_yourLongSecretHere
d. Revoking a key

Keys can be revoked at any time from the Account page. Revoked keys stop authenticating within a few seconds. If a key is compromised, revoke it immediately and issue a new one — past proofs remain valid regardless.

03 Submit a Proof

POST
/api/v1/proof

Submit a SHA-256 hex digest for anchoring. Returns immediately with a proof ID; chain confirmation happens asynchronously.

Request body
FieldTypeRequiredDescription
sha256stringyes64-character SHA-256 hex digest (lowercase or uppercase).
filenamestringnoOptional label (≤500 chars). Helps identify the proof in your dashboard.
bitcoin_requestedbooleannoIf true, queue for Bitcoin anchoring (daily Merkle batch). Consumes one Bitcoin anchor credit (100/month included).
Example request
# 1. Hash the file locally — never send the file itself.
sha256sum site-inspection.pdf
# a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2

# 2. Submit the hash.
curl -X POST https://proofledger.io/api/v1/proof \
  -H "Authorization: Bearer sk_YOUR_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{
    "sha256": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
    "filename": "site-inspection.pdf",
    "bitcoin_requested": true
  }'
Example response 201 Created
{
  "id": 42,
  "sha256": "a1b2c3d4...f0a1b2",
  "filename": "site-inspection.pdf",
  "status": "approved",
  "created_at": "2026-04-21T14:22:03.000Z",
  "bitcoin_requested": true,
  "btc_payment_status": "PAID",
  "duplicate_of": null,
  "certificate_url": "/cert/42",
  "verification_url": "/verify.html?hash=a1b2c3d4...f0a1b2"
}

The proof is accepted and queued for on-chain anchoring. Poll GET /api/v1/proof/:id or call the public verify endpoint to see the Polygon tx hash (typically under a minute) and Bitcoin txid (daily batched anchor).

Idempotency: If the same SHA-256 hash has already been submitted by any ProofLedger user, your submission still records a separate proof under your account, but the response includes a duplicate_of pointer to the earliest known record. This is the expected behavior for evidence use cases where the first anchor time is the legally significant one.

04 Retrieve a Proof

GET
/api/v1/proof/{id}

Returns the proof's full anchor state, including blockchain transaction hashes and public explorer URLs. Callers can only retrieve proofs they own.

Example request
curl https://proofledger.io/api/v1/proof/42 \
  -H "Authorization: Bearer sk_YOUR_KEY_HERE"
Example response
{
  "id": 42,
  "sha256": "a1b2c3d4...f0a1b2",
  "filename": "site-inspection.pdf",
  "status": "approved",
  "polygon_status": "ANCHORED",
  "bitcoin_status": "PENDING",
  "evidence_readiness": "PENDING_BITCOIN",
  "created_at": "2026-04-21T14:22:03.000Z",
  "chain_tx": "0xabc123...",
  "chain_name": "polygon-mainnet",
  "bitcoin_txid": null,
  "btc_payment_status": "INCLUDED",
  "certificate_url": "/cert/42",
  "explorer_url": "https://polygonscan.com/tx/0xabc123...",
  "bitcoin_explorer_url": null
}
Status field reference
FieldPossible values
statusapproved, pending, pending_review, denied, contested
polygon_statusANCHORED · PENDING
bitcoin_statusNOT_REQUESTED · AWAITING_PAYMENT · PENDING · ANCHORED · FAILED
evidence_readinessREADY_BITCOIN · READY_POLYGON · PENDING_BITCOIN · PENDING_POLYGON · NEEDS_REVIEW · DENIED
btc_payment_statusNONE · REQUIRED · PAID · PENDING

Immediately after submission, polygon_status is PENDING and chain_tx is null. The signer service picks up the job within ~30 seconds and broadcasts the transaction. Bitcoin anchors follow a daily batch cycle, so bitcoin_status may remain PENDING for up to 24 hours.

05 Verify a Proof Public

GET
/api/v1/verify?hash=<sha256>

Public, no-auth endpoint. Returns whether a proof exists for a given hash. Designed for opposing counsel, auditors, expert witnesses, and any third party independently corroborating a ProofLedger record.

Example request
curl "https://proofledger.io/api/v1/verify?hash=a1b2c3d4...f0a1b2"
Response — found
{
  "found": true,
  "proof": {
    "id": 42,
    "sha256": "a1b2c3d4...f0a1b2",
    "filename": "site-inspection.pdf",
    "created_at": "2026-04-21T14:22:03.000Z",
    "polygon_status": "ANCHORED",
    "bitcoin_status": "ANCHORED",
    "evidence_readiness": "READY_BITCOIN",
    "chain_tx": "0xabc123...",
    "bitcoin_txid": "def456...",
    "user_email": "a***@example.com"
  },
  "certificate_url": "/cert/42",
  "explorer_url": "https://polygonscan.com/tx/0xabc123...",
  "bitcoin_explorer_url": "https://blockstream.info/tx/def456..."
}
Response — not found
{ "found": false, "sha256": "a1b2c3d4...f0a1b2" }
Why the email is masked: The owner's email is surfaced as a masked form (a***@example.com) so a verifier can corroborate ownership without leaking the full address. The full email is never exposed through the public verify endpoint.

06 Rate Limits & Quotas

EndpointScopeLimitWindow
POST /api/v1/proofPer account (PRO)500Calendar month
POST /api/v1/proofPer account (BUSINESS)5,000Calendar month
POST /api/v1/proof + bitcoinPer proofCharged per proofRate varies by plan; btc_payment_status reflects payment state
GET /api/v1/proof/:idUncapped
GET /api/v1/verifyPer IP120Hourly (rolling)

Higher monthly caps are available on request — contact support@proofledger.io with your expected volume and use case.

07 Error Codes

All errors return a JSON body of the form {"error": "..."}. Use the HTTP status code for programmatic decisions.

StatusMeaningTypical cause
400Bad RequestMissing or malformed sha256; invalid proof ID.
401UnauthorizedAPI key missing, malformed, or does not match a known key.
403ForbiddenKey belongs to an account below PRO tier, or account is disabled.
404Not FoundProof ID does not exist or is not owned by the authenticated account.
429Too Many RequestsMonthly proof cap reached or hourly IP rate limit tripped.
500Server ErrorTransient server fault. Retry with exponential backoff.

08 Independent Verification

Every ProofLedger proof can be verified entirely offline — without contacting ProofLedger's servers — using the verify-proof Python package.

pip install verify-proof

# Hash a file:
verify-proof hash ./evidence.pdf

# Verify against a proof JSON downloaded from ProofLedger:
verify-proof verify ./evidence.pdf --proof ./proof.json

This is the recommended path for court-submission workflows: a party challenging admissibility can run verify-proof on their own machine against the public blockchain record, independently of whether ProofLedger is online. Source: github.com/Fulcrum-Enterprises/verify-proof.

Ready to integrate?

PRO plan includes 500 API proofs/month for prototyping and small-scale integrations. BUSINESS plan unlocks 5,000 proofs/month, higher rate limits, and per-proof Bitcoin anchoring at the best rate.

View pricing

09 Support

For API questions, integration help, or to request a higher rate limit, contact:

ProofLedger LLC
support@proofledger.io

Related: FAQ & Support · Enterprise