# Merkle Checkpoints
Source: https://docs.treeship.dev/api/merkle-checkpoint

> Retrieve and publish Merkle tree checkpoints. Checkpoints are signed snapshots of the append-only artifact tree.

<Callout type="warn">
  Merkle checkpoints are a new addition. The endpoint is live but the response format may evolve before stabilizing.
</Callout>

## Get a specific checkpoint

```
GET /v1/merkle/checkpoint/:id
```

| Parameter | Type    | Description                                               |
| --------- | ------- | --------------------------------------------------------- |
| `:id`     | integer | The checkpoint ID (auto-incrementing integer, e.g., `42`) |

No authentication required.

## Get the latest checkpoint

```
GET /v1/merkle/checkpoint/latest
```

Accepts an optional `hub_id` query parameter to scope the result to a specific hub connection.

```
GET /v1/merkle/checkpoint/latest?hub_id=hub_abc123
```

## Publish a checkpoint

```
POST /v1/merkle/checkpoint
```

Requires DPoP authentication. The CLI publishes a locally-signed checkpoint to Hub.

### Request body

```json
{
  "root": "sha256:7e3a...",
  "tree_size": 4096,
  "height": 12,
  "signed_at": "2026-03-25T10:00:00Z",
  "signer": "ship_abc123",
  "signature": "base64url-encoded-ed25519-signature",
  "public_key": "base64url-encoded-public-key",
  "rekor_index": 12345,
  "index": 3
}
```

| Field         | Type            | Required | Description                                               |
| ------------- | --------------- | -------- | --------------------------------------------------------- |
| `root`        | string          | Yes      | SHA-256 root hash of the tree in `sha256:<hex>` format    |
| `tree_size`   | integer         | Yes      | Number of leaves in the Merkle tree at this checkpoint    |
| `height`      | integer         | No       | Height of the Merkle tree                                 |
| `signed_at`   | string          | Yes      | RFC 3339 timestamp of when the checkpoint was signed      |
| `signer`      | string          | Yes      | Key ID of the signer                                      |
| `signature`   | string          | Yes      | Base64url-encoded Ed25519 signature of the canonical form |
| `public_key`  | string          | Yes      | Base64url-encoded public key bytes                        |
| `rekor_index` | integer or null | No       | Rekor transparency log index, if anchored                 |
| `index`       | integer         | No       | Checkpoint sequence number                                |

### Publish response

```json
{
  "id": 42,
  "root": "sha256:7e3a...",
  "hub_received_at": "2026-03-25T10:00:01Z"
}
```

## GET response

Both GET endpoints return the same format -- the `MerkleCheckpoint` object stored by Hub:

```json
{
  "id": 42,
  "root": "sha256:7e3a...",
  "tree_size": 4096,
  "height": 12,
  "signed_at": "2026-03-25T10:00:00Z",
  "signer": "ship_abc123",
  "signature": "base64url-encoded-ed25519-signature",
  "public_key": "base64url-encoded-public-key",
  "rekor_index": 12345,
  "hub_id": "hub_abc123"
}
```

| Field         | Type            | Description                                                 |
| ------------- | --------------- | ----------------------------------------------------------- |
| `id`          | integer         | Auto-incrementing checkpoint ID                             |
| `root`        | string          | SHA-256 root hash of the tree in `sha256:<hex>` format      |
| `tree_size`   | integer         | Number of leaves in the Merkle tree at this checkpoint      |
| `height`      | integer         | Height of the Merkle tree                                   |
| `signed_at`   | string          | RFC 3339 timestamp of when the checkpoint was signed        |
| `signer`      | string          | Key ID of the signer                                        |
| `signature`   | string          | Base64url-encoded Ed25519 signature over the canonical form |
| `public_key`  | string          | Base64url-encoded public key bytes                          |
| `rekor_index` | integer or null | Rekor transparency log index (null if not anchored)         |
| `hub_id`      | string or null  | Hub connection that published this checkpoint               |

## How checkpoints work

The CLI builds a local Merkle tree from all artifacts, signs a checkpoint over the root, and publishes it to Hub via `POST /v1/merkle/checkpoint`. The canonical form signed is: `{index}|{root}|{tree_size}|{height}|{signer}|{signed_at}`.

You can verify that:

1. A checkpoint signature is valid using the included `public_key`
2. The tree root matches the claimed tree size
3. An artifact's Merkle proof resolves against a specific checkpoint's root

## Errors

| Status | Body                                              | Cause                                                                                            |
| ------ | ------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| `400`  | `{"error": "invalid checkpoint id"}`              | The `:id` parameter is not a valid integer                                                       |
| `400`  | `{"error": "missing required checkpoint fields"}` | POST request is missing `root`, `tree_size`, `signed_at`, `signer`, `signature`, or `public_key` |
| `401`  | DPoP error                                        | POST request failed DPoP authentication                                                          |
| `404`  | `{"error": "checkpoint not found"}`               | No checkpoint with this ID                                                                       |
| `404`  | `{"error": "no checkpoints found"}`               | No checkpoints have been created yet                                                             |

## Examples

```bash
# Get a specific checkpoint by integer ID
curl https://api.treeship.dev/v1/merkle/checkpoint/42

# Get the latest checkpoint
curl https://api.treeship.dev/v1/merkle/checkpoint/latest

# Get the latest checkpoint for a specific hub connection
curl "https://api.treeship.dev/v1/merkle/checkpoint/latest?hub_id=hub_abc123"
```