Skip to main content
A Closing Passport is a room-level, versioned, sealed evidence manifest: one artifact that rolls up everything cryptographically true about the transaction at a point in time. Any party — or a downstream authority years later — can verify it at a public link without trusting SignSealShip. You mint one with a single call:
Seal the next passport version
curl -X POST https://signsealship.com/api/rooms/{roomCode}/passport \
  -H "Authorization: Bearer sss_pk_your_key_here"
Response
{
  "version": 3,
  "verifyCode": "b7e2c4a1d9f0e8b6a5c3d2e1f0a9b8c7",
  "verifyUrl": "/v/room/b7e2c4a1d9f0e8b6a5c3d2e1f0a9b8c7",
  "manifestSha256": "9d377b10ce778c4938b3c7e2c63a229a33884810d7743fbe4b5f2b7657b706da",
  "prevManifestSha256": "5f2b7657b706da9d377b10ce778c4938b3c7e2c63a229a33884810d7743fbe4b",
  "sealedSha256": "4f9a1c2b3d4e5f60718293a4b5c6d7e8f90123456789abcdef0123456789abcd",
  "createdAt": "2026-07-13T18:03:11Z"
}

Versions, not overwrites

Every call mints the next version — a dated snapshot, never a mutation of an earlier one. Sealing after two more documents complete gives you v2 alongside v1; both remain verifiable forever. This is deliberate: an evidence artifact that can be silently replaced is not evidence.
  • Versions are numbered per room, starting at 1.
  • Quota: 20 versions per room.
  • The room’s public view and GET /api/rooms/{roomCode} always point at the latest version; older versions stay reachable by their own verify codes.

The canonical manifest

The manifest is JSON serialized canonically — sorted object keys, no insignificant whitespace, UTF-8, invariant culture, lowercase hex hashes — so the same facts always produce byte-identical output and therefore the same SHA-256. Determinism is the whole point: it is what makes the hash, and the chain built on it, meaningful. The manifest has three parts:
Manifest structure (illustrative)
{
  "coverage": {
    "covers": [
      "cryptographic hashes of sealed artifacts attached to this room at snapshot time",
      "envelope verify codes and custody-certificate hashes where they exist"
    ],
    "doesNotCover": [
      "payment state",
      "delivery confirmation (unless a delivered shipment hash exists)",
      "any document not attached to this room at snapshot time"
    ]
  },
  "documents": [
    {
      "custodyCertSha256": "…",
      "envelopeVerifyCode": "…",
      "label": "Seller deed package",
      "orderCode": "…",
      "originalSha256": "…",
      "sealedSha256": "…",
      "statusAtSnapshot": "Completed"
    }
  ],
  "passport": {
    "generatedAtUtc": "2026-07-13T18:03:11Z",
    "prevManifestSha256": "…",
    "reference": "TC-88412",
    "roomCode": "…",
    "roomName": "1428 Maple St - Refinance",
    "version": 3
  }
}
Two honesty rules shape the documents array:
  • Hash fields appear only when the artifact exists. A document with no sealed artifact simply has no sealedSha256 key — the manifest never pads absence with placeholders.
  • statusAtSnapshot is a labeled attestation, not evidence. It records what our systems said at snapshot time. The hashes are independently verifiable; the status is our word, and the manifest says so.
The coverage block enumerates what the passport does and does not speak to. It is rendered verbatim on the public verify page — the artifact carries its own limits.

The hash chain

Each version’s manifest embeds prevManifestSha256 — the SHA-256 of the previous version’s manifest (null for v1). That forms a per-room chain:
Chain
v1: manifestSha256 = H(manifest_1), prev = null
v2: manifestSha256 = H(manifest_2), manifest_2 contains prev = H(manifest_1)
v3: manifestSha256 = H(manifest_3), manifest_3 contains prev = H(manifest_2)
Rewriting any historical version would change its hash and break every later link. When you verify a passport, the API recomputes the chain on that request — it re-hashes the stored manifest and checks the previous link against the prior version’s stored hash — and reports the result as chainOk. The verdict is never a stored flag; it is earned on every view.

The sealed artifact

Alongside the manifest, each version produces a Closing Passport certificate PDF: the room header, the version and chain line, a per-document hash table, the coverage statement, and the manifest SHA-256. The PDF is sealed with the same Google Cloud KMS signature that seals first-party orders — the private key never leaves KMS — so it verifies in any standard PDF signature viewer on its own, offline, with no SignSealShip involvement.

Verifying a passport

Every version has a public verification page:
Verify page
https://signsealship.com/v/room/{verifyCode}
The page shows the SEALED badge, a manifest summary, the chain status, the coverage statement verbatim, and a download link for the sealed PDF. The same facts are available as JSON:
Verify over the API
curl https://signsealship.com/api/verify/room/{verifyCode}
Response
{
  "manifest": { "...": "the full parsed manifest" },
  "manifestSha256": "9d377b10ce778c4938b3c7e2c63a229a33884810d7743fbe4b5f2b7657b706da",
  "sealedSha256": "4f9a1c2b3d4e5f60718293a4b5c6d7e8f90123456789abcdef0123456789abcd",
  "version": 3,
  "prevManifestSha256": "5f2b7657b706da9d377b10ce778c4938b3c7e2c63a229a33884810d7743fbe4b",
  "chainOk": true,
  "branding": null,
  "createdAt": "2026-07-13T18:03:11Z",
  "downloadUrl": "/api/verify/room/{verifyCode}/pdf"
}
The manifest is returned parsed alongside its hash so you can check it yourself:
1

Re-hash the manifest

Re-canonicalize the returned manifest (sorted keys, no whitespace, UTF-8) and SHA-256 it. It must equal manifestSha256.
2

Walk the chain

Fetch the prior version by its verify code and confirm its manifestSha256 equals this version’s prevManifestSha256.
3

Check the sealed PDF

Download the PDF from downloadUrl, confirm its SHA-256 equals sealedSha256, and open it in a PDF signature viewer to validate the KMS signature independently.
4

Cross-check document hashes

Any sealed document you hold can be hashed locally and compared against its sealedSha256 entry in the manifest.
None of these steps require trusting SignSealShip. The artifact proves itself.

Honest coverage — what a passport does not say

A Closing Passport is strong evidence with stated limits, and the limits are part of the artifact:
  • Statuses are attestation. statusAtSnapshot values are our records at snapshot time, explicitly labeled as not being independent evidence.
  • No payment claims. The passport says nothing about whether anyone was paid.
  • No delivery claims unless a delivered shipment’s hash is actually on record.
  • Nothing about absent documents. A document never attached to the room is simply outside the passport’s world — the coverage statement says so.
The verify code is a bearer credential for the passport, like the room link is for the room. Unknown or malformed codes return an identical generic not-found response, so codes cannot be enumerated.

Passports API reference

Full request and response shapes for sealing and verifying Closing Passports.

Evidence model

The locked vocabulary behind SEALED and RECORDED, and what each cryptographically means.