Utility Endpoints
The six stateless utility endpoints under /api/json/utilities (hash, verify-hash, uuidv7-timestamp, ulid-timestamp, resolve-id, jcs-canonicalize) and their GraphQL query twins, with request and response shapes, the result envelope, bearer auth and OAuth scopes, and resolve-id visibility gating.
Overview
Alongside its resource endpoints, Truestamp exposes six small, stateless utility
operations: computing a hash, verifying a hash, extracting the time embedded in a
UUIDv7 or a ULID, resolving what an opaque id refers to, and canonicalizing a JSON
object. Five are pure compute with no data access; one (resolve-id) reads data and
is gated by what the caller is allowed to see. None of them creates or changes any
record. Each operation is available in two equivalent forms: as a POST route under
/api/json/utilities on the JSON:API surface, and as a query twin
on the GraphQL surface. The same operations are also reachable by
LLM agents through the MCP server. Use them to
reproduce Truestamp’s hashing locally, to sanity-check inputs before submitting an
item, or to identify an unknown identifier before fetching its full record.
Calling conventions
All six operations require authentication: present an
API key or an OAuth 2.1 access token as an
Authorization: Bearer header, exactly as on the rest of the API. An anonymous
request is rejected with 401 Unauthorized.
For OAuth callers the required scope differs by surface. The JSON:API forms are
POST routes, and the REST surface grants scopes by HTTP method, so calling them
with an OAuth token requires the api:write scope even though nothing is written.
The GraphQL twins are queries, so they require only api:read. API-key callers are
not scope-limited on either surface. Requests count against the same per-caller rate
limits as the rest of each surface.
JSON:API form
Send the operation’s arguments as a JSON object under a top-level data key. The
response wraps the operation’s result under a top-level result key (these routes
use a result envelope rather than a JSON:API resource document):
curl -X POST https://www.truestamp.com/api/json/utilities/hash \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/vnd.api+json" \
-d '{"data": {"text": "hello"}}'
{
"result": {
"algorithm": "sha256",
"hex": "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824",
"input_byte_length": 5
}
}
Argument keys are snake_case (hash_type). The six routes appear in the OpenAPI
specification at /api/json/open_api (and in the Swagger UI and ReDoc pages) under
the operation names hash, verifyHash, uuidv7Timestamp, ulidTimestamp,
resolveId, and jcsCanonicalize.
GraphQL form
The twins are the queries hash, verifyHash, uuidv7Timestamp, ulidTimestamp,
resolveId, and jcsCanonicalize, with camelCase arguments (hashType). Each
returns the same result object serialized as a JSON string, which the client parses:
query {
hash(text: "hello")
}
The returned hash value is the JSON string
{"algorithm":"sha256","hex":"2cf24...","input_byte_length":5}.
Expected failures are structured results
Bad input a caller can fix (an unsupported algorithm name, a malformed ULID, an unrecognized id) does not surface as an HTTP error. The operation succeeds and its result is a structured failure object:
{"ok": false, "code": "invalid", "message": "Not a valid ULID", "retryable": false}
A successful result never carries an ok key, so check for "ok": false before
using the result. A missing required argument, by contrast, is a normal request
error on each surface.
hash: compute a digest
POST /api/json/utilities/hash / GraphQL hash. Computes a hash of the given UTF-8
text and returns it as a lowercase hex string.
Arguments:
text(required): the text to hash.hash_type(optional, defaultsha256): one of the same twelve algorithms accepted for item claims:md5,sha1,sha224,sha256,sha384,sha512,sha3_224,sha3_256,sha3_384,sha3_512,blake2s,blake2b.domain(optional): a Truestamp domain-separation name. When set, the result is SHA-256 over a single registered prefix byte followed by the text, reproducing a Truestamp internal domain-separated hash (see the byte-prefix registry);hash_typeis ignored. One of:items_claims,items_metadata,item,entropy,entropy_metadata,observation,block,block_genesis,block_metadata,commitment_data,commitment,proof.
Returns hex, algorithm, and input_byte_length; in domain mode also domain and
prefix (the prefix byte in 0x11 form). Omit domain for an ordinary hash.
verify-hash: check a digest
POST /api/json/utilities/verify-hash / GraphQL verifyHash. Hashes the given text
and compares it to an expected hex value using a constant-time comparison. This is a
plain hash check only, never a domain-separated one.
Arguments: text (required), hash (required, the expected hex digest; surrounding
whitespace and letter case are normalized before comparison), and hash_type
(optional, default sha256, same twelve algorithms as hash).
Returns matches (boolean), computed (the hex digest of text), and algorithm.
uuidv7-timestamp: read a UUIDv7’s embedded time
POST /api/json/utilities/uuidv7-timestamp / GraphQL uuidv7Timestamp. Extracts the
time embedded in a UUIDv7 identifier when it was generated. Truestamp uses UUIDv7 for
blocks, entropy observations, memberships, and most other ids (see
ULID and UUIDv7 identifiers).
Arguments: uuid (required, a 36-character UUIDv7 string).
Returns iso8601, unix_ms, and the echoed uuid. An invalid UUIDv7 returns the
structured "ok": false failure. Note that an identifier’s embedded time is
informational: the timing Truestamp actually proves is
the submission window established by a verified
proof, not a timestamp parsed out of an id.
ulid-timestamp: read a ULID’s embedded time
POST /api/json/utilities/ulid-timestamp / GraphQL ulidTimestamp. Extracts the
time embedded in a ULID identifier when it was generated. Item
ids are the only ULIDs in Truestamp.
Arguments: ulid (required, a 26-character ULID string).
Returns iso8601, unix_ms, and the echoed ulid, with the same informational-time
caveat as uuidv7-timestamp. An invalid ULID returns the structured "ok": false
failure.
resolve-id: identify an opaque id (visibility-gated)
POST /api/json/utilities/resolve-id / GraphQL resolveId. Given a bare ULID or
UUIDv7, reports what it refers to so you can decide what to do with it. This is the
one utility that reads data, and it honors your authorization: a ULID can only be an
item, and it resolves only if the item is visible to you across your teams; a UUIDv7
may resolve to a block or an entropy observation (public ledger data, visible to any
authenticated caller) or to a team, but only one you are a member of. An id you
cannot see returns no match and its existence is never revealed.
Arguments: id (required, a 26-character ULID or 36-character UUIDv7).
Returns id, normalized_id, id_format ("ulid" or "uuidv7"), and matches, a
list where each entry has:
kind:"item","block","entropy_observation", or"team".verifiable: whether this kind of subject supports proofs at all. This is a property of the kind, not of the record’s current readiness: a freshly submitted item readsverifiable: truehere but cannot be proven until it is committed, so check its lifecycle state before generating a proof.proof_type: thetypeto pass when generating a proof (for example"item","block", or an entropy source type), or null for a non-verifiable kind.also_verifiable_as: alternate proof subjects, for example a block is also verifiable as a"beacon".summary: a compact, non-sensitive description of the match (id, state, and a few kind-specific fields).
A well-formed id that matches nothing you can access returns "matches": []. A
value that is neither a ULID nor a UUIDv7 returns the structured "ok": false
failure with "code": "invalid".
jcs-canonicalize: canonical JSON
POST /api/json/utilities/jcs-canonicalize / GraphQL jcsCanonicalize.
Canonicalizes a JSON object with JCS (RFC 8785): keys sorted,
insignificant whitespace removed, numbers and strings in canonical form. The
canonical string is the exact serialization Truestamp hashes, so this is the tool for
predicting hashes such as an item’s claims hash.
Arguments: json (required, the JSON object to canonicalize).
Returns canonical (the canonical JSON string) and byte_length.
One caveat when predicting a claims hash: pure JCS preserves null-valued keys, but
Truestamp drops null keys from item claims before hashing (see
the item’s composite fingerprint). To predict a
claims hash, remove null fields from the object first, canonicalize it here, then
hash the canonical string with the hash operation using domain items_claims.
Citations
- RFC 8785: JSON Canonicalization Scheme (JCS). The canonicalization applied by
jcs-canonicalize. - RFC 9562: Universally Unique IDentifiers (UUIDs). Defines UUIDv7 and its embedded Unix-epoch millisecond timestamp, which
uuidv7-timestampextracts. - ULID Specification. Defines the ULID format and its 48-bit embedded timestamp, which
ulid-timestampextracts. - RFC 6962: Certificate Transparency. Origin of the byte-prefix domain-separation style reproduced by the
hashoperation’sdomainmode.