from line 6
66 status: beta
77---
88
9Learn how to cryptographically verify that no [Access Transparency](https://platform.claude.com/docs/en/manage-claude/access-transparency) event was removed or altered after it was committed to your organization's transparency log.
9Learn how to cryptographically verify that no [Access Transparency](https://platform.claude.com/docs/en/manage-claude/access-transparency) event was removed or altered after it was committed to your organization’s transparency log.
1010
1111<Note>
1212 The transparency log is in beta, and its endpoints and response shapes may change during the beta. It is part of Access Transparency, which is available to eligible customers on request and is not self-serve (see [Access Transparency](https://platform.claude.com/docs/en/manage-claude/access-transparency)). Anthropic maintains one for your organization once Access Transparency is enabled. You read it through the Compliance API with the same key and scope you use for the [Activity Feed](https://platform.claude.com/docs/en/manage-claude/compliance-activity-feed).
from line 24
2424
2525When Access Transparency is enabled, Anthropic maintains a transparency log for your organization. It is an append-only, cryptographically signed record of Access Transparency events (`anthropic_access` and `cmek_preserve`). Each such event recorded for your organization after the log was created is appended to it. The log follows the C2SP tlog-tiles format, so tooling built for that standard can parse its checkpoints, tiles, and proofs.
2626
27* **One log for each organization.** Each organization's log has a fixed origin string: `axt.anthropic.com/<your organization UUID>`. The origin never changes for the life of the organization.
28* **Every new event becomes a leaf.** When an Access Transparency event becomes eligible to appear on your Activity Feed, it is first appended to your log as a leaf, and only then served on the feed. A leaf is a deterministic serialization of the event's documented fields. The event on your feed carries `transparency_log_leaf_index`, its zero-based position in your log.
29* **Checkpoints commit to the whole history.** The log is a Merkle tree. Whenever it grows, Anthropic publishes a signed checkpoint: a short text document stating the log's origin, its current size, and the root hash that commits to every leaf. Each checkpoint carries exactly one signature from the log's signing key.
27* **One log for each organization.** Each organization’s log has a fixed origin string: `axt.anthropic.com/<your organization UUID>`. The origin never changes for the life of the organization.
28* **Every new event becomes a leaf.** When an Access Transparency event becomes eligible to appear on your Activity Feed, it is first appended to your log as a leaf, and only then served on the feed. A leaf is a deterministic serialization of the event’s documented fields. The event on your feed carries `transparency_log_leaf_index`, its zero-based position in your log.
29* **Checkpoints commit to the whole history.** The log is a Merkle tree. Whenever it grows, Anthropic publishes a signed checkpoint: a short text document stating the log’s origin, its current size, and the root hash that commits to every leaf. Each checkpoint carries exactly one signature from the log’s signing key.
3030* **Two proofs follow.** An inclusion proof shows that a specific event is present at its position under a checkpoint. A consistency proof shows that a later checkpoint is an append-only extension of an earlier one you saved, so nothing between them was removed or changed.
3131* **Verification keys are served in-band.** The [verifier keys endpoint](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#read-the-verifier-keys) returns the public keys that sign checkpoints. In a planned key rotation, the new key is added to that list before it starts signing, and earlier keys stay listed. Checkpoints you already hold therefore keep verifying.
3232
from line 41
4141* It does not prove that every access was recorded, or that a recorded event accurately describes the access. It proves only that what Anthropic committed to the log has not changed since.
4242* It does not change [what Access Transparency covers](https://platform.claude.com/docs/en/manage-claude/access-transparency#what-access-transparency-covers) or when events arrive.
4343* Served fields that no [leaf version](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#how-an-event-becomes-a-leaf) includes, such as `workspace_uuid`, are not covered by the proof. A field added to events later is covered only once a leaf version includes it.
44* An inclusion proof speaks for an event you were served. It does not by itself prove that the feed listed every leaf the log holds. The log's [entry bundles](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#read-an-entry-bundle) contain every leaf, so you can read the complete set of committed events directly when you need it.
44* An inclusion proof speaks for an event you were served. It does not by itself prove that the feed listed every leaf the log holds. The log’s [entry bundles](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#read-an-entry-bundle) contain every leaf, so you can read the complete set of committed events directly when you need it.
4545* The presence of `transparency_log_leaf_index` on an event is a pointer, not a proof. Always verify inclusion before treating an event as committed in the log.
46* The protection against a rewritten history comes from the checkpoints you keep. A checkpoint's signature by a key listed in [Published key fingerprints](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#published-key-fingerprints) proves that it came from Anthropic's log. A consistency proof from the checkpoint you saved last time proves that the history you already observed only grew.
46* The protection against a rewritten history comes from the checkpoints you keep. A checkpoint’s signature by a key listed in [Published key fingerprints](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#published-key-fingerprints) proves that it came from Anthropic’s log. A consistency proof from the checkpoint you saved last time proves that the history you already observed only grew.
4747
4848## Before you start
4949
5050You need:
5151
52* A Compliance Access Key with the `read:compliance_activities` scope, the same key and scope you use for the [Activity Feed](https://platform.claude.com/docs/en/manage-claude/compliance-activity-feed). A parent-organization key can read each enrolled child organization's log by naming the child organization on every request.
53* Your organization's UUID. Find it on the [Organization](https://platform.claude.com/settings/organization) page (`platform.claude.com/settings/organization`) in the Claude Console. It is the same value the Activity Feed serves as `organization_uuid`, but take it from the Console. This value is what makes a checkpoint yours, so it must not come from the API you are verifying. You derive your log's origin from it as `axt.anthropic.com/<organization UUID>`. Derive this string yourself. Do not read it from an API response.
54* Somewhere durable to keep the last checkpoint you verified. That saved checkpoint is what turns "the log is consistent today" into "the log has been consistent since you started watching."
52* A Compliance Access Key with the `read:compliance_activities` scope, the same key and scope you use for the [Activity Feed](https://platform.claude.com/docs/en/manage-claude/compliance-activity-feed). A parent-organization key can read each enrolled child organization’s log by naming the child organization on every request.
53* Your organization’s UUID. Find it on the [Organization](https://platform.claude.com/settings/organization) page (`platform.claude.com/settings/organization`) in the Claude Console. It is the same value the Activity Feed serves as `organization_uuid`, but take it from the Console. This value is what makes a checkpoint yours, so it must not come from the API you are verifying. You derive your log’s origin from it as `axt.anthropic.com/<organization UUID>`. Derive this string yourself. Do not read it from an API response.
54* Somewhere durable to keep the last checkpoint you verified. That saved checkpoint is what turns “the log is consistent today” into “the log has been consistent since you started watching.”
5555
5656## Timing
5757
5858* **Events:** Access Transparency events appear on your Activity Feed within 2 business days of the access. An event enters the log only once it is eligible to be served, so the log never reveals an event early. Because the log is written before the feed serves the event, an entry can briefly appear in the log before its event appears on your feed. That gap is not a discrepancy.
5959* **Checkpoints:** A new checkpoint is published whenever your log grows.
60* **Inclusion proofs:** A proof for a newly served event is available once a checkpoint covering the event's position is published, normally very shortly after the event appears. If you request one sooner, you receive a `404` and retry after a short delay.
60* **Inclusion proofs:** A proof for a newly served event is available once a checkpoint covering the event’s position is published, normally very shortly after the event appears. If you request one sooner, you receive a `404` and retry after a short delay.
6161* **Verification cadence:** Run your verification at least daily. Hourly is reasonable.
6262* **Disenrollment:** If your organization stops using Access Transparency, nothing is deleted. Your log stays readable through the same endpoints. If Access Transparency is enabled again later, the same log continues.
6363
from line 64
6464## Retention and deletion
6565
6666* **Transparency log:** Anthropic does not delete entries from your log, and the log has no expiry. It is kept if your organization stops using Access Transparency and after your organization is deleted, because removing entries is the change the log exists to detect. [Entry bundles](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#read-an-entry-bundle) hold the [leaf fields](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#how-an-event-becomes-a-leaf) of each event, so those fields are kept for as long as the log is.
67* **Activity Feed:** Access Transparency events on the Activity Feed follow the feed's retention. Activities are retained for 6 years. See [Query the Activity Feed](https://platform.claude.com/docs/en/manage-claude/compliance-activity-feed).
67* **Activity Feed:** Access Transparency events on the Activity Feed follow the feed’s retention. Activities are retained for 6 years. See [Query the Activity Feed](https://platform.claude.com/docs/en/manage-claude/compliance-activity-feed).
6868* **No deletion by you:** The transparency log endpoints are read-only. There is no way to delete or amend an entry.
6969
7070## Transparency log endpoints
from line 80
8080| [`GET /tile/{level}/{index}`](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#read-a-hash-tile) | A Merkle hash tile |
8181| [`GET /tile/entries/{index}`](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#read-an-entry-bundle) | An entry bundle of leaf bytes |
8282
83Checkpoints, tiles, and entry bundles follow the C2SP tlog-tiles wire format exactly. The two proof endpoints are conveniences: every proof is also computable from tiles, so you never have to trust a proof endpoint's output. You verify the hashes it returns against a signed checkpoint.
83Checkpoints, tiles, and entry bundles follow the C2SP tlog-tiles wire format exactly. The two proof endpoints are conveniences: every proof is also computable from tiles, so you never have to trust a proof endpoint’s output. You verify the hashes it returns against a signed checkpoint.
8484
8585### Authentication and scoping
8686
8787Send your Compliance Access Key in the `x-api-key` header and the `anthropic-version` header, as for every Compliance API request (see [Versioning](https://platform.claude.com/docs/en/manage-claude/compliance-api#versioning)). The Compliance API must be enabled for your organization.
8888
89There is no separate transparency log permission. Any key that can read your organization's Activity Feed, for your organization or its parent, can read your whole log, including the event fields in its entry bundles.
89There is no separate transparency log permission. Any key that can read your organization’s Activity Feed, for your organization or its parent, can read your whole log, including the event fields in its entry bundles.
9090
91Every request reads exactly one organization's log:
91Every request reads exactly one organization’s log:
9292
93* An organization-level key reads its own organization's log. The `organization_id` query parameter is optional. If present, it must name the key's own organization.
93* An organization-level key reads its own organization’s log. The `organization_id` query parameter is optional. If present, it must name the key’s own organization.
9494* A parent-organization-level key must pass `organization_id`, naming one child organization.
9595* `organization_id` accepts the `org_...` tagged ID or the organization UUID.
9696
97A `404` means there is no log this key can read. An organization outside the key's scope, a nonexistent organization, and an organization whose log has not been created yet are deliberately indistinguishable. The log of an organization that has since stopped using Access Transparency is not this case: it continues to be served.
97A `404` means there is no log this key can read. An organization outside the key’s scope, a nonexistent organization, and an organization whose log has not been created yet are deliberately indistinguishable. The log of an organization that has since stopped using Access Transparency is not this case: it continues to be served.
9898
9999### Errors
100100
from line 105
105105| `400` | `organization_id` is malformed or is omitted with a parent-organization key, the Compliance API is not enabled, a query parameter is unknown, or a per-endpoint validation failed |
106106| `401` | The API key is missing or not valid |
107107| `403` | The key lacks the required scope |
108| `404` | No log readable by this key, or the per-endpoint "not covered" and "beyond the tree" cases |
109| `429` | Rate limited. These endpoints share the Compliance API's per-parent-organization [rate limit](https://platform.claude.com/docs/en/manage-claude/compliance-api). Honor `retry-after` |
108| `404` | No log readable by this key, or the per-endpoint “not covered” and “beyond the tree” cases |
109| `429` | Rate limited. These endpoints share the Compliance API’s per-parent-organization [rate limit](https://platform.claude.com/docs/en/manage-claude/compliance-api). Honor `retry-after` |
110110| `503` | The log is temporarily unavailable. Retry with backoff |
111111
112112### Caching
from line 134
134134— axt.anthropic.com/25f6429a-3293-49bf-afed-cb312911554b q83vATBFAiEAvL8m…(base64)…
135135```
136136
137* The first 4 bytes of the decoded signature value are the signing key's `key_hash`, which tells you which entry in the [verifier key set](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#read-the-verifier-keys) to verify with. The remaining bytes are an ASN.1 DER ECDSA P-256 signature over the SHA-256 of the note body: every byte before the blank line, including the body's trailing newline.
137* The first 4 bytes of the decoded signature value are the signing key’s `key_hash`, which tells you which entry in the [verifier key set](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#read-the-verifier-keys) to verify with. The remaining bytes are an ASN.1 DER ECDSA P-256 signature over the SHA-256 of the note body: every byte before the blank line, including the body’s trailing newline.
138138* A checkpoint can carry additional lines after the root hash. Ignore lines you do not understand. They are covered by the signature.
139139* Ignore a signature line whose name is not your origin or whose key hash you do not hold.
140* Never cache a checkpoint. A stale one hides the log's current size, so newly served events look uncovered.
140* Never cache a checkpoint. A stale one hides the log’s current size, so newly served events look uncovered.
141141
142142### Read the verifier keys
143143
from line 172
172172| `origin` | string | The origin line every checkpoint of this log carries. Informational: compare checkpoints against the origin you derive yourself, not against this field |
173173| `log_keys` | array | The key that signs new checkpoints first, then every other key the log serves, newest first. Never empty |
174174| `log_keys[].verifier_key` | string | The key as a C2SP note-verifier string, `<origin>+<key_hash>+<base64 key>`, accepted by tlog-tiles tooling that supports ECDSA note keys (for example, the Go `github.com/transparency-dev/formats` module). The base64 part decodes to the algorithm byte `0x02` followed by the DER-encoded public key |
175| `log_keys[].key_hash` | string | Eight lowercase hex digits. The 4-byte selector that matches this key to a checkpoint's signature line. It is the first 4 bytes of `fingerprint` and is not an identity |
175| `log_keys[].key_hash` | string | Eight lowercase hex digits. The 4-byte selector that matches this key to a checkpoint’s signature line. It is the first 4 bytes of `fingerprint` and is not an identity |
176176| `log_keys[].fingerprint` | string | 64 lowercase hex digits: the SHA-256 of the DER `SubjectPublicKeyInfo` |
177177| `log_keys[].algorithm` | string | The key type, currently `ecdsa_p256_sha256`. Values may be added. Skip a key whose algorithm you do not support |
178178| `log_keys[].public_key` | string | The public key as base64 DER `SubjectPublicKeyInfo` |
179179
180The `key_hash` covers only the key bytes: it is the first 4 bytes of SHA-256 over the DER `SubjectPublicKeyInfo`, which is the rule the ECDSA note-verifier encoding uses. It is not the name-dependent key ID that the base signed-note format defines for Ed25519 keys, so it does not change with the origin. A valid signature by a key listed in [Published key fingerprints](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#published-key-fingerprints) proves the checkpoint came from Anthropic's transparency log service. The origin line inside the signed checkpoint is what binds it to your organization. That is why you compare that line against the origin you derive yourself.
180The `key_hash` covers only the key bytes: it is the first 4 bytes of SHA-256 over the DER `SubjectPublicKeyInfo`, which is the rule the ECDSA note-verifier encoding uses. It is not the name-dependent key ID that the base signed-note format defines for Ed25519 keys, so it does not change with the origin. A valid signature by a key listed in [Published key fingerprints](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#published-key-fingerprints) proves the checkpoint came from Anthropic’s transparency log service. The origin line inside the signed checkpoint is what binds it to your organization. That is why you compare that line against the origin you derive yourself.
181181
182182Keys can rotate:
183183
from line 195
195195
196196A planned rotation is announced on this page at least 30 days before the new key signs its first checkpoint. During that notice period the new key is listed in `log_keys` and in this table with its switch date. Retired keys stay listed with their service dates. A key that does not appear in this table is not legitimate, whatever `GET /keys` returns. Treat a checkpoint that verifies under no listed key as a verification failure, and report it to your Anthropic account representative or [Anthropic support](https://support.claude.com).
197197
198`axt-verify` carries the current key in each release and never reads a key from the API (see [Verify with axt-verify](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#verify-with-axt-verify)). Each release carries exactly one key. On the switch date, Anthropic starts signing with the new key and publishes the `axt-verify` release that carries it. On the same date Anthropic re-issues every organization's latest checkpoint under the new key, even for a log that has not grown. Upgrade on the switch date. Running the old release after the switch fails with exit status `1`, and so does running the new release before it. Either failure clears once you run the matching release. A verifier you maintain yourself needs the new fingerprint, with its switch date, added before that date.
198`axt-verify` carries the current key in each release and never reads a key from the API (see [Verify with axt-verify](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#verify-with-axt-verify)). Each release carries exactly one key. On the switch date, Anthropic starts signing with the new key and publishes the `axt-verify` release that carries it. On the same date Anthropic re-issues every organization’s latest checkpoint under the new key, even for a log that has not grown. Upgrade on the switch date. Running the old release after the switch fails with exit status `1`, and so does running the new release before it. Either failure clears once you run the matching release. A verifier you maintain yourself needs the new fingerprint, with its switch date, added before that date.
199199
200200### Fetch an inclusion proof
201201
from line 203
203203
204204| Parameter | Type | Description |
205205| ----------------- | ----------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
206| `leaf_index` | integer, required | The event's position in the log: the `transparency_log_leaf_index` the Activity Feed served on the event. Must be zero or greater |
206| `leaf_index` | integer, required | The event’s position in the log: the `transparency_log_leaf_index` the Activity Feed served on the event. Must be zero or greater |
207207| `organization_id` | string, optional | See [Authentication and scoping](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#authentication-and-scoping) |
208208
209209```bash
from line 230
230230| Field | Type | Description |
231231| ------------ | ---------------- | ------------------------------------------------------------------------------------------ |
232232| `type` | string | Always `transparency_log_inclusion_proof` |
233| `leaf_index` | integer | The event's position in the log, echoed from the request |
233| `leaf_index` | integer | The event’s position in the log, echoed from the request |
234234| `hashes` | array of strings | The base64 sibling hashes of the audit path, ordered from the leaf up to the root |
235235| `checkpoint` | string | The latest signed checkpoint, the one the proof verifies against. It carries the tree size |
236236
from line 249
249249
250250| Parameter | Type | Description |
251251| ----------------- | ----------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
252| `from` | integer, required | The tree size of the earlier checkpoint you hold. Must be at least 1 and at most the latest checkpoint's tree size |
252| `from` | integer, required | The tree size of the earlier checkpoint you hold. Must be at least 1 and at most the latest checkpoint’s tree size |
253253| `organization_id` | string, optional | See [Authentication and scoping](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#authentication-and-scoping) |
254254
255255```bash
from line 279
279279| `checkpoint` | string | The latest signed checkpoint, the one the proof extends to. It carries the tree size |
280280
281281* The proof always extends to the latest published checkpoint. This API never serves historical checkpoints: you keep the ones you are served.
282* A `from` equal to the latest checkpoint's tree size returns the empty proof.
282* A `from` equal to the latest checkpoint’s tree size returns the empty proof.
283283* A held checkpoint of tree size 0 needs no consistency proof, because every log extends the empty log. Adopt the latest checkpoint directly in that case.
284* A `from` less than 1, or greater than the latest checkpoint's tree size, returns `400`.
284* A `from` less than 1, or greater than the latest checkpoint’s tree size, returns `400`.
285285* If the log can no longer prove that it extends a checkpoint it once signed for you, treat that as a verification failure, not a usage error.
286286
287287### Read a hash tile
from line 291
291291Returns `application/octet-stream`: concatenated 32-byte SHA-256 hashes, as tlog-tiles specifies. Tile addressing follows tlog-tiles exactly, including the `{level}` and `{index}` path grammar, the `x001/234` index form for large trees, and the partial-tile suffix `.p/{width}`. Hash tiles are the unit from which tlog-tiles clients compute proofs themselves.
292292
293293* Full tiles are immutable and are served with `Cache-Control: private, max-age=604800, immutable`.
294* Partial tiles are superseded as the tree grows and are served with `Cache-Control: private, no-store`. Once a tile fills, a request for its earlier partial form can return `404` even though the full tile exists. Falling back from the partial tile to the full tile is the client's job, as tlog-tiles specifies, and standard clients already do it.
294* Partial tiles are superseded as the tree grows and are served with `Cache-Control: private, no-store`. Once a tile fills, a request for its earlier partial form can return `404` even though the full tile exists. Falling back from the partial tile to the full tile is the client’s job, as tlog-tiles specifies, and standard clients already do it.
295295* A malformed `level`, `index`, or partial-tile width returns `400`. A tile position beyond the current tree size returns `404`.
296296
297297### Read an entry bundle
from line 298
298298
299299`GET /v1/compliance/transparency_log/tile/entries/{index}`
300300
301Returns `application/octet-stream`: consecutive leaf entries, each prefixed with its big-endian `uint16` length, as tlog-tiles specifies. Entry bundles contain event plaintext: the [canonical bytes](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#how-an-event-becomes-a-leaf) of each Access Transparency event. That is why the whole surface requires the Activity Feed's scope. Addressing, the partial form, caching, and errors are identical to hash tiles.
301Returns `application/octet-stream`: consecutive leaf entries, each prefixed with its big-endian `uint16` length, as tlog-tiles specifies. Entry bundles contain event plaintext: the [canonical bytes](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#how-an-event-becomes-a-leaf) of each Access Transparency event. That is why the whole surface requires the Activity Feed’s scope. Addressing, the partial form, caching, and errors are identical to hash tiles.
302302
303303## The `transparency_log_leaf_index` field on Activity Feed events
304304
from line 305
305305`anthropic_access` and `cmek_preserve` events on `GET /v1/compliance/activities` carry `transparency_log_leaf_index`, an integer, whenever the event has a leaf. Other activity types never carry it.
306306
307307* **The key is absent, not `null`, when the event has no leaf.** A robust verifier treats an absent key and a `null` value the same way.
308* **An event is served without `transparency_log_leaf_index` in only two cases.** The first is while your organization is not enrolled in Access Transparency, that is, before enrollment or between an un-enrollment and a re-enrollment. The second is when the event was recorded before your organization's log was created. For an organization enrolled before the transparency log was introduced, that includes its earlier history. Once your log exists and while you are enrolled, every event is appended to the log before the feed serves it. If a fault prevents the feed from obtaining the index, the feed delays the event rather than serving it without one. The event is not lost: it is already in the log and appears on the feed, index included, once the fault is remediated. An index-less event is not expected when it is dated after your log was created and falls inside a period when you were enrolled.
308* **An event is served without `transparency_log_leaf_index` in only two cases.** The first is while your organization is not enrolled in Access Transparency, that is, before enrollment or between an un-enrollment and a re-enrollment. The second is when the event was recorded before your organization’s log was created. For an organization enrolled before the transparency log was introduced, that includes its earlier history. Once your log exists and while you are enrolled, every event is appended to the log before the feed serves it. If a fault prevents the feed from obtaining the index, the feed delays the event rather than serving it without one. The event is not lost: it is already in the log and appears on the feed, index included, once the fault is remediated. An index-less event is not expected when it is dated after your log was created and falls inside a period when you were enrolled.
309309* **A present index is a pointer, not a proof.** Verify inclusion before treating the event as committed in the log. The anomaly worth escalating is a present index whose inclusion proof still cannot be fetched long after a covering checkpoint should have been published.
310310* The index is assigned when the event is appended to the log and is not one of the fields that make up the leaf.
311311
312312## How an event becomes a leaf
313313
314A leaf entry is one schema-version byte followed by canonical JSON of that version's fields. The JSON follows [RFC 8785](https://www.rfc-editor.org/rfc/rfc8785) (JSON Canonicalization Scheme), and the fields are taken from the event exactly as the Activity Feed serves it.
314A leaf entry is one schema-version byte followed by canonical JSON of that version’s fields. The JSON follows [RFC 8785](https://www.rfc-editor.org/rfc/rfc8785) (JSON Canonicalization Scheme), and the fields are taken from the event exactly as the Activity Feed serves it.
315315
316316A leaf version is a fixed set of fields, and each field is either required or optional.
317317
from line 325
325325
326326* `user_profile_id`, the ID of the [user profile](https://platform.claude.com/docs/en/api/beta/user_profiles) the accessed or preserved data was created under
327327
328Once your log starts writing a version, it writes every new leaf under that version until it starts writing the next one, even when the event has none of the version's optional fields. [Upgrade for a new leaf version](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#upgrade-for-a-new-leaf-version) says when your log can start writing a new version. A leaf never changes once it is written, so it keeps its version for good. One log can therefore hold leaves of more than one version. Nothing the Activity Feed or the proof endpoints serve says which version a leaf has (only the leaf's own bytes in an [entry bundle](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#read-an-entry-bundle) do), and you do not need to know: the last of the following rules says which entries to rebuild for an event.
328Once your log starts writing a version, it writes every new leaf under that version until it starts writing the next one, even when the event has none of the version’s optional fields. [Upgrade for a new leaf version](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#upgrade-for-a-new-leaf-version) says when your log can start writing a new version. A leaf never changes once it is written, so it keeps its version for good. One log can therefore hold leaves of more than one version. Nothing the Activity Feed or the proof endpoints serve says which version a leaf has (only the leaf’s own bytes in an [entry bundle](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#read-an-entry-bundle) do), and you do not need to know: the last of the following rules says which entries to rebuild for an event.
329329
330330The rules:
331331
332* Served fields outside a version's set, such as `workspace_uuid` and `transparency_log_leaf_index` itself, are ignored.
332* Served fields outside a version’s set, such as `workspace_uuid` and `transparency_log_leaf_index` itself, are ignored.
333333
334334* A required field that the served event omits, or serves as `null`, enters the leaf as `null`. An empty string is distinct from `null`.
335335
from line 345
345345
346346* Canonical JSON means object keys sorted, no insignificant whitespace, and minimal string escaping. No numbers appear anywhere in the leaf.
347347
348* The leaf hash is RFC 6962's `SHA-256(0x00 || entry)`. Interior nodes hash as `SHA-256(0x01 || left || right)`.
348* The leaf hash is RFC 6962’s `SHA-256(0x00 || entry)`. Interior nodes hash as `SHA-256(0x01 || left || right)`.
349349
350350* A verifier that reads leaf entries, for example from an [entry bundle](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#read-an-entry-bundle), rejects an unknown version byte, and a leaf whose `type` is not one of the two Access Transparency types. New fields, new event types, and rule changes ship under a new version byte. Existing leaves never re-hash.
351351
352* Rebuild a served event's entry under each leaf version whose fields include every optional field the served event has as a string (every version, when it has none), and under no other version. The event verifies if its inclusion proof matches the leaf hash of any one of them. If an optional field is removed from, added to, or changed in the event you are served, the event fails verification on any verifier that rebuilds a leaf version with that field, whichever leaf the log holds.
352* Rebuild a served event’s entry under each leaf version whose fields include every optional field the served event has as a string (every version, when it has none), and under no other version. The event verifies if its inclusion proof matches the leaf hash of any one of them. If an optional field is removed from, added to, or changed in the event you are served, the event fails verification on any verifier that rebuilds a leaf version with that field, whichever leaf the log holds.
353353
354354For example, this access event as the Activity Feed serves it:
355355
from line 391
391391
392392Verification runs on your own infrastructure. Everything the API returns is untrusted until it verifies against two things you hold yourself. The first is the origin you derive from your organization UUID. The second is the checkpoint you saved on your last run. A complete verification run does the following, in order:
393393
3941. Fetch the [verifier key set](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#read-the-verifier-keys). Compute each key's fingerprint yourself as the SHA-256 of its base64-decoded `public_key`. Keep only the keys whose fingerprint appears in [Published key fingerprints](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#published-key-fingerprints), together with each key's status there. Verify a newly fetched checkpoint only under a key that table lists as current on that date. Accept a retired key only for a checkpoint you saved before its retirement date.
3941. Fetch the [verifier key set](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#read-the-verifier-keys). Compute each key’s fingerprint yourself as the SHA-256 of its base64-decoded `public_key`. Keep only the keys whose fingerprint appears in [Published key fingerprints](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#published-key-fingerprints), together with each key’s status there. Verify a newly fetched checkpoint only under a key that table lists as current on that date. Accept a retired key only for a checkpoint you saved before its retirement date.
3953952. Establish the latest checkpoint. On the first run, fetch it from the [checkpoint endpoint](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#read-the-latest-checkpoint). On every later run, request a [consistency proof](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#fetch-a-consistency-proof) from the tree size you saved. The response carries the latest checkpoint together with the proof.
3963. Check the checkpoint's origin line first. Compare its first line, byte for byte, with the origin you derived. Reject any checkpoint whose origin differs, before doing anything else.
3974. Verify the checkpoint's signature. Find the signature line named for your origin whose first four decoded bytes equal the `key_hash` of a currently valid key you kept. Verify the remaining bytes as an ECDSA P-256 signature over the SHA-256 of the note body, using that key's `public_key`. If no signature line matches such a key, or the signature does not verify, reject the checkpoint.
3963. Check the checkpoint’s origin line first. Compare its first line, byte for byte, with the origin you derived. Reject any checkpoint whose origin differs, before doing anything else.
3974. Verify the checkpoint’s signature. Find the signature line named for your origin whose first four decoded bytes equal the `key_hash` of a currently valid key you kept. Verify the remaining bytes as an ECDSA P-256 signature over the SHA-256 of the note body, using that key’s `public_key`. If no signature line matches such a key, or the signature does not verify, reject the checkpoint.
3983985. Prove append-only. If the new tree size is smaller than the one you saved, fail. If it is equal, the root hashes must match. If it is larger, verify the RFC 9162 consistency proof from your saved size and root hash to the new size and root hash.
3996. Prove each event is included. Read every Access Transparency event the Activity Feed serves. For each new one, rebuild each [leaf to rebuild for it](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#how-an-event-becomes-a-leaf), hash each, and fetch its [inclusion proof](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#fetch-an-inclusion-proof). Walk the audit path from each leaf hash at the event's index up to the checkpoint's root hash. The event verifies if one of them reproduces the root hash. If none does, the event you were served is not the event the log committed. The proof response can carry a different checkpoint from the one you hold. Check its origin line and signature (steps 3 and 4), and link it into your history with a consistency proof (step 5), before you verify anything against it.
3996. Prove each event is included. Read every Access Transparency event the Activity Feed serves. For each new one, rebuild each [leaf to rebuild for it](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#how-an-event-becomes-a-leaf), hash each, and fetch its [inclusion proof](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#fetch-an-inclusion-proof). Walk the audit path from each leaf hash at the event’s index up to the checkpoint’s root hash. The event verifies if one of them reproduces the root hash. If none does, the event you were served is not the event the log committed. The proof response can carry a different checkpoint from the one you hold. Check its origin line and signature (steps 3 and 4), and link it into your history with a consistency proof (step 5), before you verify anything against it.
4004007. Re-check what you saw before. Whenever you read an event again, it must be served with the same index and the same leaf bytes as when you verified it. No event may lose the index it had, and while you are enrolled no event may newly appear without one. The events served without an index on your first run are your pre-log history. A run that re-reads only recent events re-checks only those. To re-check older ones, verify the copies you kept (step 8) again.
4014018. Save the checkpoint you verified and a record of each event you verified. They are your evidence and your starting point for the next run.
402402
from line 409
409409| `0x01` | Every release |
410410| `0x02` | `v0.2.0` and later |
411411
412`axt-verify version` prints the release you run. A new installation gets the newest release. If the table's last row does not include your release, upgrade to a release in that row. If none is published yet, upgrade as soon as one is:
412`axt-verify version` prints the release you run. A new installation gets the newest release. If the table’s last row does not include your release, upgrade to a release in that row. If none is published yet, upgrade as soon as one is:
413413
4144141. Install the newest release the way you installed before (the `go install` line in [Verify with axt-verify](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#verify-with-axt-verify)).
4154152. Keep running it as before: same `--org`, same `--state` file, same schedule.
from line 417
417417What to expect:
418418
419419* **Before your log starts writing the new version.** The newer release verifies your log as before, because it also rebuilds the earlier leaf versions.
420* **After your log starts writing the new version, on a release that does not rebuild it.** The release reports every event whose leaf has that version as a verification failure, with exit status `1`, even when the event has none of the version's optional fields. Leaves of the versions your release rebuilds are not affected. They verify as they did before. The failures clear once you run a release that rebuilds the version on the same `--state` file, and the append-only check continues from where your last run ended.
420* **After your log starts writing the new version, on a release that does not rebuild it.** The release reports every event whose leaf has that version as a verification failure, with exit status `1`, even when the event has none of the version’s optional fields. Leaves of the versions your release rebuilds are not affected. They verify as they did before. The failures clear once you run a release that rebuilds the version on the same `--state` file, and the append-only check continues from where your last run ended.
421421* **If you return to an earlier release.** Do not give an earlier release a state file that a newer release has saved. The earlier release reports every event that was waiting for a checkpoint as a verification failure. If you may need to return to the earlier release, copy the state file before the first run of the newer one, and give the earlier release that copy.
422422
423A verifier you maintain yourself needs a new version's fields, and the rule for which entries to rebuild, from [How an event becomes a leaf](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#how-an-event-becomes-a-leaf) before your log starts writing that version.
423A verifier you maintain yourself needs a new version’s fields, and the rule for which entries to rebuild, from [How an event becomes a leaf](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#how-an-event-becomes-a-leaf) before your log starts writing that version.
424424
425425### Verify with axt-verify
426426
427427If you already run `axt-verify` on a schedule, read [Upgrade for a new leaf version](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#upgrade-for-a-new-leaf-version) first.
428428
429[`axt-verify`](https://github.com/anthropics/axt-verify) is Anthropic's open-source verifier for this log. It is a single Go binary that you run on your own infrastructure. Each release has exactly one log signing key from [Published key fingerprints](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#published-key-fingerprints) built in, so it never asks the API which key to trust. When Anthropic rotates the key, you upgrade to the release that carries the new one on the switch date. `axt-verify` derives your origin from the organization UUID you pass with `--org`, which is the one you took from the Console in [Before you start](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#before-you-begin). It rejects any checkpoint whose origin line differs.
429[`axt-verify`](https://github.com/anthropics/axt-verify) is Anthropic’s open-source verifier for this log. It is a single Go binary that you run on your own infrastructure. Each release has exactly one log signing key from [Published key fingerprints](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#published-key-fingerprints) built in, so it never asks the API which key to trust. When Anthropic rotates the key, you upgrade to the release that carries the new one on the switch date. `axt-verify` derives your origin from the organization UUID you pass with `--org`, which is the one you took from the Console in [Before you start](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#before-you-begin). It rejects any checkpoint whose origin line differs.
430430
431431Install it with Go 1.26 or newer. It reads your Compliance Access Key from the `ANTHROPIC_COMPLIANCE_ACCESS_KEY` environment variable, never from a flag or a file. The `run` command is the one to schedule:
432432
from line 439
439439 run
440440```
441441
442Each `run` fetches the latest checkpoint and verifies its signature and origin line. It then proves the log is an append-only extension of the checkpoint the previous run saved. Next it pages through the Access Transparency events on your Activity Feed. It starts 7 days (by `created_at`) before the newest event the previous run read, so that events listed late or out of order are still picked up. It rebuilds each [leaf to rebuild for the event](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#how-an-event-becomes-a-leaf), verifies an inclusion proof against them, and compares any event it verified before against what it recorded then. Finally, it saves the new checkpoint and its progress to the `--state` file, which the next run starts from. Run it at least daily. Hourly is reasonable. With a parent-organization key, run one copy for each child organization, each with its own `--org` and `--state` file. Each child organization's UUID also comes from the Claude Console, not from the Compliance API responses you are verifying. To find it, switch to the child organization in the account menu at the bottom of the Console sidebar, then open the [Organization](https://platform.claude.com/settings/organization) page (`platform.claude.com/settings/organization`). You can also find it in your parent organization's list of organizations in the Console. `axt-verify checkpoint` does only the checkpoint and append-only steps. `axt-verify events FILE` verifies events you already hold, such as an auditor's sample or your own export. It proves that each event in the file is still committed in the log under the current checkpoint. It does not read the feed or touch the state file.
442Each `run` fetches the latest checkpoint and verifies its signature and origin line. It then proves the log is an append-only extension of the checkpoint the previous run saved. Next it pages through the Access Transparency events on your Activity Feed. It starts 7 days (by `created_at`) before the newest event the previous run read, so that events listed late or out of order are still picked up. It rebuilds each [leaf to rebuild for the event](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#how-an-event-becomes-a-leaf), verifies an inclusion proof against them, and compares any event it verified before against what it recorded then. Finally, it saves the new checkpoint and its progress to the `--state` file, which the next run starts from. Run it at least daily. Hourly is reasonable. With a parent-organization key, run one copy for each child organization, each with its own `--org` and `--state` file. Each child organization’s UUID also comes from the Claude Console, not from the Compliance API responses you are verifying. To find it, switch to the child organization in the account menu at the bottom of the Console sidebar, then open the [Organization](https://platform.claude.com/settings/organization) page (`platform.claude.com/settings/organization`). You can also find it in your parent organization’s list of organizations in the Console. `axt-verify checkpoint` does only the checkpoint and append-only steps. `axt-verify events FILE` verifies events you already hold, such as an auditor’s sample or your own export. It proves that each event in the file is still committed in the log under the current checkpoint. It does not read the feed or touch the state file.
443443
444One limit follows from that window: `run` re-reads only the last 7 days of events, so it re-checks recently served events (step 7), not your whole history. Keep the events you export (see [Keep your own checkpoint archive](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#keep-your-own-checkpoint-archive)). `axt-verify events FILE` proves at any later date that those copies are still committed in the log, but it does not re-read the feed. To detect an older event removed from or rewritten on the feed, re-export that range from the Activity Feed and compare it with the copies you kept. You can also verify the re-export itself with `axt-verify events FILE`. The 7-day overlap is longer than the feed's 2-business-day delivery time, so a late-arriving event still falls inside a later run's window. `--overlap` changes the duration if you need to.
444One limit follows from that window: `run` re-reads only the last 7 days of events, so it re-checks recently served events (step 7), not your whole history. Keep the events you export (see [Keep your own checkpoint archive](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#keep-your-own-checkpoint-archive)). `axt-verify events FILE` proves at any later date that those copies are still committed in the log, but it does not re-read the feed. To detect an older event removed from or rewritten on the feed, re-export that range from the Activity Feed and compare it with the copies you kept. You can also verify the re-export itself with `axt-verify events FILE`. The 7-day overlap is longer than the feed’s 2-business-day delivery time, so a late-arriving event still falls inside a later run’s window. `--overlap` changes the duration if you need to.
445445
446446If you need your own implementation instead, follow the preceding checklist with a tlog-tiles library that supports ECDSA note keys.
447447
from line 449
449449
450450`axt-verify` prints your origin, the tree size and root hash of the checkpoint it verified, the tree size the append-only check started from, and a count of events by outcome. Pass `--json` to get the same report as one JSON object on each line. Each event has one of four outcomes:
451451
452* **Verified:** a leaf rebuilt from the served event is committed at the event's index in the signed log.
453* **Pending:** the event's index is beyond the latest published checkpoint. This is normal for a short time after an event appears. In `run`, `axt-verify` records the event, verifies it on a later run once a checkpoint covers it, and fails it if that takes longer than 24 hours. `events FILE` has no later run to settle it, so it waits up to a minute for a covering checkpoint to be published. If none arrives, it reports the event as not yet covered and ends with exit status `3`. Run it again later. If `events FILE` reports the same event as not yet covered on two runs at least a day apart, treat it as a verification failure and escalate as for exit status `1`.
454* **Not logged:** the event was served without an index. An event is served without `transparency_log_leaf_index` only while your organization is not enrolled in Access Transparency, or when it was recorded before your organization's log was created (see [The `transparency_log_leaf_index` field on Activity Feed events](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#the-transparency-log-leaf-index-field-on-activity-feed-events)). `axt-verify` reports such events as not logged and does not fail the run on them. An index-less event is not expected when it is dated after your log was created and falls inside a period when you were enrolled. Review the not-logged list in the run's summary or `--json` output rather than relying on the exit status alone.
452* **Verified:** a leaf rebuilt from the served event is committed at the event’s index in the signed log.
453* **Pending:** the event’s index is beyond the latest published checkpoint. This is normal for a short time after an event appears. In `run`, `axt-verify` records the event, verifies it on a later run once a checkpoint covers it, and fails it if that takes longer than 24 hours. `events FILE` has no later run to settle it, so it waits up to a minute for a covering checkpoint to be published. If none arrives, it reports the event as not yet covered and ends with exit status `3`. Run it again later. If `events FILE` reports the same event as not yet covered on two runs at least a day apart, treat it as a verification failure and escalate as for exit status `1`.
454* **Not logged:** the event was served without an index. An event is served without `transparency_log_leaf_index` only while your organization is not enrolled in Access Transparency, or when it was recorded before your organization’s log was created (see [The `transparency_log_leaf_index` field on Activity Feed events](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#the-transparency-log-leaf-index-field-on-activity-feed-events)). `axt-verify` reports such events as not logged and does not fail the run on them. An index-less event is not expected when it is dated after your log was created and falls inside a period when you were enrolled. Review the not-logged list in the run’s summary or `--json` output rather than relying on the exit status alone.
455455* **Failed:** see exit status `1`.
456456
457457The exit status tells your scheduler what occurred:
from line 458
458458
459459* **`0`:** Nothing failed. Not-logged events are reported, not failed, and so are pending events in `run`.
460460
461* **`1`:** A verification failure. If every new event fails because its inclusion proof does not reproduce the signed root hash, first rule out a release that does not rebuild your log's newest leaf version, as that item in this list describes. If that is not the cause, and for any other failure, treat it as a security finding, not a transient error. Keep the state file and the output, and report it to your Anthropic account representative or [Anthropic support](https://support.claude.com). The causes are:
461* **`1`:** A verification failure. If every new event fails because its inclusion proof does not reproduce the signed root hash, first rule out a release that does not rebuild your log’s newest leaf version, as that item in this list describes. If that is not the cause, and for any other failure, treat it as a security finding, not a transient error. Keep the state file and the output, and report it to your Anthropic account representative or [Anthropic support](https://support.claude.com). The causes are:
462462
463 * A checkpoint with the wrong origin, or a signature that does not verify under the key built into your `axt-verify` release. Compare the `key_hash` on the failing checkpoint's signature line with [Published key fingerprints](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#published-key-fingerprints). A key listed there with a switch date you have not upgraded for means you need the matching release. A key not listed there is a security finding, whatever release you run. On this failure `axt-verify` prints the key hash of every signature on the served checkpoint and the key hash of the key it trusts, as eight hex digits each. That output is enough to make the comparison.
463 * A checkpoint with the wrong origin, or a signature that does not verify under the key built into your `axt-verify` release. Compare the `key_hash` on the failing checkpoint’s signature line with [Published key fingerprints](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#published-key-fingerprints). A key listed there with a switch date you have not upgraded for means you need the matching release. A key not listed there is a security finding, whatever release you run. On this failure `axt-verify` prints the key hash of every signature on the served checkpoint and the key hash of the key it trusts, as eight hex digits each. That output is enough to make the comparison.
464464 * A checkpoint that is not a well-formed signed note, for example one whose root hash is not 32 bytes.
465465 * A log that shrank, or that cannot prove it extends the checkpoint you saved. The output then carries both checkpoints and the proof, so the evidence stands on its own.
466466 * Two signed checkpoints for the same tree size with different root hashes. The output carries both checkpoints.
467467 * A checkpoint file passed with `--from` whose signature does not verify under the key built into your `axt-verify` release, or a `--from` or `--from-trusted` file whose origin is not yours. For an archive signed before a key rotation, see [Keep your own checkpoint archive](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#keep-your-own-checkpoint-archive).
468468 * An inclusion proof that does not reproduce the signed root hash for the event you were served. A release that does not rebuild a leaf version reports this for every event whose leaf has that version. If every new event fails this way at once, check first that you run the newest `axt-verify` release (see [Upgrade for a new leaf version](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#upgrade-for-a-new-leaf-version)). If you do not, copy the state file, keep the copy and the output, and run the newest release on the original `--state` file. The failures clear once you run a release that rebuilds the version. If you already run the newest release, or the failures remain after you upgrade, it is a security finding.
469 * An event inside the run's window served differently from how an earlier run recorded it: different leaf bytes, a different index, or no index where it had one.
469 * An event inside the run’s window served differently from how an earlier run recorded it: different leaf bytes, a different index, or no index where it had one.
470470 * An event still pending 24 hours after the run first saw it.
471471 * A refused inclusion proof (`400`, `401`, or `403`) for an event the feed served you.
472472 * An inclusion proof returned for a different `leaf_index` from the one requested.
473473 * In `events FILE`, an event at an index the latest checkpoint already covered when the check started, for which no inclusion proof is served before the wait runs out.
474 * An event whose `organization_uuid` is not the organization UUID you passed with `--org`. When a parent organization runs `events FILE` on an export that covers several child organizations, every other organization's event fails this way, so split the export by organization first and verify each part with its own `--org`.
474 * An event whose `organization_uuid` is not the organization UUID you passed with `--org`. When a parent organization runs `events FILE` on an export that covers several child organizations, every other organization’s event fails this way, so split the export by organization first and verify each part with its own `--org`.
475475 * The same activity `id` at two different indices, or twice at one index with different content, within one run or one `events FILE` input.
476476 * An event whose leaf cannot be rebuilt: for example, a documented field that is not a string, a field name that appears twice, or a `type` that is missing or is an unrecognized variant of an Access Transparency type. `events FILE` skips rows of other activity types and does not fail them.
477477
from line 493
493493
494494### Keep your own checkpoint archive
495495
496The strongest evidence you can hold is your own record of what the log said on a given day. `axt-verify --save FILE` writes the checkpoint a run verified, verbatim, and `--from FILE` on a later run makes the log prove it still extends that checkpoint. Archive a saved checkpoint in storage you control, for example daily. Months later, a [consistency proof](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#fetch-a-consistency-proof) from that archived checkpoint's tree size must still lead to whatever checkpoint the log serves, or verification fails. Earlier keys stay listed in the [verifier key set](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#read-the-verifier-keys) after a planned rotation, so an archived checkpoint keeps verifying. With `axt-verify`, if the key that signed an archived checkpoint has since rotated out, pass that archive with `--from-trusted` instead of `--from`. Keep the events too. The Access Transparency events you export from the feed are valid input to `axt-verify events FILE`, which proves at any later date that those copies are still committed in the log under its current checkpoint. Because `events FILE` does not re-read the feed, your kept export is also the reference you compare a later re-export of the same range against.
496The strongest evidence you can hold is your own record of what the log said on a given day. `axt-verify --save FILE` writes the checkpoint a run verified, verbatim, and `--from FILE` on a later run makes the log prove it still extends that checkpoint. Archive a saved checkpoint in storage you control, for example daily. Months later, a [consistency proof](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#fetch-a-consistency-proof) from that archived checkpoint’s tree size must still lead to whatever checkpoint the log serves, or verification fails. Earlier keys stay listed in the [verifier key set](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#read-the-verifier-keys) after a planned rotation, so an archived checkpoint keeps verifying. With `axt-verify`, if the key that signed an archived checkpoint has since rotated out, pass that archive with `--from-trusted` instead of `--from`. Keep the events too. The Access Transparency events you export from the feed are valid input to `axt-verify events FILE`, which proves at any later date that those copies are still committed in the log under its current checkpoint. Because `events FILE` does not re-read the feed, your kept export is also the reference you compare a later re-export of the same range against.
497497
498498## Frequently asked questions
499499
from line 507
507507 </Accordion>
508508
509509 <Accordion title="What happens when Anthropic rotates the signing key?">
510 Planned rotations are announced in [Published key fingerprints](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#published-key-fingerprints) at least 30 days ahead, with a switch date. On the switch date Anthropic starts signing with the new key and publishes the `axt-verify` release that carries it. On the same date Anthropic re-issues every organization's latest checkpoint under the new key, even for a log that has not grown. Each `axt-verify` release carries one key, so upgrade on the switch date. Running the old release after the switch fails with exit status `1`, and so does running the new release before it. Either failure clears once you run the matching release. Checkpoints you saved under the old key stay valid starting points, because the append-only proof from a saved checkpoint to a new one does not depend on which key signed the old one. The new key appears at the front of the [verifier key set](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#read-the-verifier-keys) and earlier keys stay listed. Checkpoints you already verified or archived therefore keep verifying against that set. A verifier of your own that pins the published fingerprints needs the new fingerprint, with its switch date, added before that date. A verifier that holds the key set locally re-fetches it when it meets a signature whose key hash it does not hold. A checkpoint commits to the whole history. Once one checkpoint signed by the new key verifies, and a consistency proof from your saved checkpoint leads to it, every earlier entry is re-established as well.
510 Planned rotations are announced in [Published key fingerprints](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#published-key-fingerprints) at least 30 days ahead, with a switch date. On the switch date Anthropic starts signing with the new key and publishes the `axt-verify` release that carries it. On the same date Anthropic re-issues every organization’s latest checkpoint under the new key, even for a log that has not grown. Each `axt-verify` release carries one key, so upgrade on the switch date. Running the old release after the switch fails with exit status `1`, and so does running the new release before it. Either failure clears once you run the matching release. Checkpoints you saved under the old key stay valid starting points, because the append-only proof from a saved checkpoint to a new one does not depend on which key signed the old one. The new key appears at the front of the [verifier key set](https://platform.claude.com/docs/en/manage-claude/access-transparency-log#read-the-verifier-keys) and earlier keys stay listed. Checkpoints you already verified or archived therefore keep verifying against that set. A verifier of your own that pins the published fingerprints needs the new fingerprint, with its switch date, added before that date. A verifier that holds the key set locally re-fetches it when it meets a signature whose key hash it does not hold. A checkpoint commits to the whole history. Once one checkpoint signed by the new key verifies, and a consistency proof from your saved checkpoint leads to it, every earlier entry is re-established as well.
511511 </Accordion>
512512
513513 <Accordion title="What is a leaf version, and do I need to track which one a leaf has?">
from line 523
523523 </Accordion>
524524
525525 <Accordion title="Can I verify all of my child organizations with one key?">
526 Yes. A parent-organization key reads any enrolled child organization's log by passing `organization_id`. Each child organization has its own log, origin, and saved checkpoint. Run a separate verification, with its own state, for each child organization.
526 Yes. A parent-organization key reads any enrolled child organization’s log by passing `organization_id`. Each child organization has its own log, origin, and saved checkpoint. Run a separate verification, with its own state, for each child organization.
527527 </Accordion>
528528</AccordionGroup>
529529
from line 533
533533* [Query the Activity Feed](https://platform.claude.com/docs/en/manage-claude/compliance-activity-feed)
534534* [Compliance API overview](https://platform.claude.com/docs/en/manage-claude/compliance-api)
535535* [Handle Compliance API errors](https://platform.claude.com/docs/en/manage-claude/compliance-errors)
536* [axt-verify](https://github.com/anthropics/axt-verify), Anthropic's open-source verifier for the transparency log
536* [axt-verify](https://github.com/anthropics/axt-verify), Anthropic’s open-source verifier for the transparency log
537537* [C2SP tlog-tiles](https://c2sp.org/tlog-tiles) and [C2SP signed note](https://c2sp.org/signed-note), the wire formats for tiles, entry bundles, and checkpoints
538538* [RFC 9162](https://www.rfc-editor.org/rfc/rfc9162), the Merkle tree, inclusion proof, and consistency proof algorithms
539539* [RFC 8785](https://www.rfc-editor.org/rfc/rfc8785), the JSON Canonicalization Scheme used for leaves