---
title: "Sent to your endpoint when a proof is anchored"
method: POST
path: "proofAnchored"
---

# Sent to your endpoint when a proof is anchored

`POST proofAnchored` (webhook)

Headers: ProofLedger-Signature (t=<unix seconds>,v1=<hex HMAC-SHA256 of "t.body" with your secret>) and ProofLedger-Event-Id. Answer 2xx within 10 s. Failed deliveries are retried after 1, 5, 30, 120, 360, 720 and 1,440 minutes (almost two days), then the endpoint is switched off and the account emailed. At-least-once: dedupe by event id. Since 2026-10-15 the payload also carries data.bundle, the proof bundle for the chain this event is about (see GET /api/v1/proof/{id}/bundle).

## Payload

- WebhookEvent: The JSON body ProofLedger POSTs to a registered endpoint.
  - `id` string
  - `type` 'proof.polygon.anchored' | 'proof.bitcoin.anchored' | 'webhook.test'
  - `created_at` string, date-time
  - `data` object
    - `proof` ProofSummary: A proof as returned by the batch and lookup/list endpoints (a shorter view than GET /api/v1/proof/{id}).
      - `id` integer
      - `sha256` string
      - `external_id` string, nullable
      - `filename` string
      - `status` string
      - `polygon_status` 'PENDING' | 'ANCHORED'
      - `bitcoin_status` 'NOT_REQUESTED' | 'AWAITING_PAYMENT' | 'PENDING' | 'ANCHORED' | 'FAILED': Legacy field: carries a value only on proofs anchored on Bitcoin before 2026-10-15, when Bitcoin anchoring was discontinued. Null or NOT_REQUESTED on every newer proof.
      - `created_at` string, date-time
      - `polygon_anchored_at` string, date-time, nullable: When the Polygon transaction was recorded.
      - `chain_tx` string, nullable
      - `chain_name` string, nullable
      - `bitcoin_txid` string, nullable: Legacy field: carries a value only on proofs anchored on Bitcoin before 2026-10-15, when Bitcoin anchoring was discontinued. Null on every newer proof.
      - `certificate_url` string, uri: Absolute link to the public certificate page.
      - `verification_url` string, uri: Absolute link to the public verification page for this hash.
      - `explorer_url` string, nullable
      - `already_existed` boolean: Create responses only: false on a new proof (201); true when the external_id was already recorded and the existing proof is returned (200).
      - `issued_via` string, nullable: Approved partner name copied onto the proof when it was created ("Recorded through <name> · Anchored by ProofLedger"). Null when not branded.
    - `bundle` Bundle: Everything needed to verify one proof without ProofLedger. Top-level fields are the verify-proof file format. `anchors` holds the Polygon anchor and a legacy `bitcoin` block, which carries data only on proofs anchored on Bitcoin before 2026-10-15.
      - `format` string
      - `service` string
      - `generated_at` string, date-time
      - `hash` string: SHA-256 of the file, lowercase hex.
      - `algorithm` string
      - `blockchain` 'polygon' | 'bitcoin': The chain in the top-level fields (?chain=).
      - `tx_id` string, nullable
      - `anchored_at` string, date-time, nullable
      - `merkle_path` object[]: Empty: Polygon anchors are one transaction per hash. (Non-empty only on the legacy Bitcoin anchor of proofs anchored before 2026-10-15.)
        - `hash` string
        - `position` 'left' | 'right'
      - `anchored` boolean
      - `proof_id` integer
      - `external_id` string, nullable
      - `public_cert_id` string, nullable
      - `filename` string, nullable
      - `created_at` string, date-time
      - `issued_via` string, nullable
      - `certificate_url` string, uri: Absolute link to the public certificate page.
      - `verification_url` string, uri: Absolute link to the public verification page for this hash.
      - `anchors` object
        - `polygon` object
          - `blockchain` string
          - `network` string, nullable
          - `anchored` boolean
          - `tx_id` string, nullable
          - `anchored_at` string, nullable
          - `explorer_url` string, nullable
        - `bitcoin` object: Legacy block: carries Bitcoin data only on proofs anchored on Bitcoin before 2026-10-15. On every newer proof it reads anchored: false, status NOT_REQUESTED.
          - `blockchain` string
          - `anchored` boolean
          - `status` string
          - `tx_id` string, nullable
          - `anchored_at` string, nullable
          - `merkle_root` string, nullable
          - `merkle_root_verified` boolean
          - `batch_size` integer
          - `merkle_path` unknown
          - `explorer_url` string, nullable
      - `how_to_verify` string[]

## Acknowledgement `200`

Any 2xx acknowledges the event.

---

[API](https://skmtc.dev/proofledger/apis/proofledger-api.md) · [All operations](https://skmtc.dev/proofledger/apis/proofledger-api/llms.txt) · [OpenAPI document](https://skmtc.dev/proofledger/apis/proofledger-api/revisions/6b9565b296a2?raw)
