---
title: GET /v1/merkle/:artifactId
description: Retrieve a self-contained Merkle inclusion proof for an artifact.
---

import { Callout } from 'fumadocs-ui/components/callout';

## Request

```
GET /v1/merkle/:artifactId
```

| Parameter | Type | Description |
|-----------|------|-------------|
| `:artifactId` | string | The artifact ID (e.g., `art_f7e6d5c4b3a2f7e6`) |

No authentication required. Proofs are public so anyone can verify.

## Response

Returns a self-contained `ProofFile` JSON. This includes everything needed to verify that the artifact is included in a specific Merkle tree checkpoint -- no further requests to Hub required.

```json
{
  "artifact_id": "art_f7e6d5c4b3a2f7e6",
  "artifact_summary": {
    "actor": "agent://ci",
    "action": "test suite",
    "timestamp": "2026-03-28T14:30:00Z",
    "key_id": "ship_a1b2c3d4"
  },
  "inclusion_proof": {
    "leaf_index": 2048,
    "leaf_hash": "9d2fa1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0",
    "path": [
      { "direction": "Right", "hash": "1a2b3c4d..." },
      { "direction": "Left", "hash": "5e6f7a8b..." },
      { "direction": "Right", "hash": "9c0d1e2f..." }
    ],
    "algorithm": "sha256-rfc9162"
  },
  "checkpoint": {
    "index": 42,
    "root": "sha256:7e3a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0",
    "tree_size": 4096,
    "height": 12,
    "signed_at": "2026-03-28T15:00:00Z",
    "signer": "ship_a1b2c3d4",
    "public_key": "base64url-encoded-ed25519-public-key",
    "signature": "base64url-encoded-ed25519-signature",
    "algorithm": "sha256-rfc9162"
  }
}
```

### ProofFile fields

| Field | Type | Description |
|-------|------|-------------|
| `artifact_id` | string | The artifact this proof covers |
| `artifact_summary` | object | Human-readable context about the artifact |
| `artifact_summary.actor` | string | Actor URI that created the artifact |
| `artifact_summary.action` | string | Label describing the action |
| `artifact_summary.timestamp` | string | RFC 3339 timestamp of the artifact |
| `artifact_summary.key_id` | string | Key ID of the signer |
| `inclusion_proof` | object | Merkle inclusion proof from leaf to root |
| `inclusion_proof.leaf_index` | integer | Position of the artifact in the tree |
| `inclusion_proof.leaf_hash` | string | Hex-encoded SHA-256 hash of the artifact ID |
| `inclusion_proof.path` | array | Sibling hashes forming the path from leaf to root |
| `inclusion_proof.path[].direction` | string | `Left` or `Right` -- position of the sibling relative to the current node |
| `inclusion_proof.path[].hash` | string | Hex-encoded hash of the sibling node |
| `inclusion_proof.algorithm` | string | Merkle algorithm: `sha256-rfc9162` (current) or `sha256-duplicate-last` (v1 legacy) |
| `checkpoint` | object | Signed snapshot of the Merkle tree at proof time |
| `checkpoint.index` | integer | Checkpoint sequence number |
| `checkpoint.root` | string | Root hash in `sha256:<hex>` format |
| `checkpoint.tree_size` | integer | Number of leaves in the tree |
| `checkpoint.height` | integer | Tree height (ceil of log2 of tree_size) |
| `checkpoint.signed_at` | string | RFC 3339 timestamp of the checkpoint |
| `checkpoint.signer` | string | Key ID of the checkpoint signer |
| `checkpoint.public_key` | string | Base64url-encoded Ed25519 public key |
| `checkpoint.signature` | string | Base64url-encoded Ed25519 signature |
| `checkpoint.algorithm` | string | Merkle algorithm used to build the tree |

## How to verify

The proof is self-contained. To verify locally:

1. Recompute the leaf hash: `sha256(artifact_id)` and compare to `inclusion_proof.leaf_hash`
2. Walk the `inclusion_proof.path` from leaf to root, combining hashes at each level based on `direction`
3. Compare the computed root against `checkpoint.root`
4. Verify the checkpoint signature using the embedded `public_key`

### CLI verification

```bash
treeship merkle verify proof.json
```

You can also fetch and verify in one step:

```bash
treeship merkle proof art_f7e6d5c4b3a2f7e6 --verify
```

## Errors

| Status | Body | Cause |
|--------|------|-------|
| `400` | `{"error": "missing artifact id"}` | No artifact ID in the URL path |
| `404` | `{"error": "proof not found"}` | No proof exists for this artifact |

## Example

```bash
curl https://api.treeship.dev/v1/merkle/art_f7e6d5c4b3a2f7e6
```
