TimeLayer Engineering Notes API Reference
Reference REST One endpoint ~6 min read

TimeLayer API: one call, one receipt

The whole API is a single HTTP call. You hash an action or a document locally, send only the hash, and get back a self-contained receipt your user keeps and anyone verifies offline. Your content never leaves your machine.

1. Two minutes to your first receipt

  1. Create a free account at cabinet.timelayer-os.com — you get free receipts to start.
  2. Copy your API token from the cabinet.
  3. Hash anything and notarize it:
# hash a string (or a file with: shasum -a 256 file)
HASH=$(printf 'invoice #4471 approved by alex@acme.com' | shasum -a 256 | cut -d' ' -f1)

curl -X POST https://api.timelayer-os.com/v1/notarize \
  -H "Authorization: Bearer $TL_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"action_hex\": \"$HASH\"}"

You get back a cert_hex and a bundle_hex. Decode them to bytes, save as .tlcert and .tlbundle, and you hold a verifiable receipt.

2. Base URL & authentication

Base URL: https://api.timelayer-os.com. Every request carries your token as a bearer header:

Authorization: Bearer <your API token>

Keep the token server-side

The token spends your receipt balance. Put it in an environment variable, never in client-side code or a public repo. You can see (and rotate) it in your cabinet.

3. POST /v1/notarize

The one endpoint. It takes the hash of whatever you want to prove and returns a receipt attesting exactly that hash.

FieldMeaning
action_hexHex of the hash of your action or document. SHA-256 is the common choice; the binding is algorithm-neutral (SHA-256, BLAKE3, SHA-3…). Lowercase hex, no 0x prefix.

Request body:

{ "action_hex": "b557d79ce260ed0edb9e548a9b3fe417967b6174f0e9c99ea28bfa1f27561c1e" }

Only the hash is sent. TimeLayer never sees your action or document — that is the point (Zero-Data): the network attests a fingerprint, not the contents.

4. The receipt: cert + bundle

A successful call returns two hex strings:

{
  "cert_hex":   "…",   // the certificate, ~415 bytes decoded
  "bundle_hex": "…"    // its supporting evidence, ~1 KB decoded
}

These are raw bytes encoded as hex, not text. Decode each from hex and write the bytes to a file — the verifier reads the decoded bytes:

# bash
echo "$CERT_HEX"   | xxd -r -p > receipt.tlcert
echo "$BUNDLE_HEX" | xxd -r -p > receipt.tlbundle

The pair travels with the action. Hand it to your user, embed it in a document, or store it in your database — there is no central log to keep, and nothing to trust us about later.

5. Verify offline

Anyone checks the receipt on their own machine, with no network and no account, using the open-source verifier:

timelayer-verifier verify receipt.tlcert receipt.tlbundle
# -> VALID FINAL        authentic and complete
# -> UNVERIFIABLE        forged, divergent, or tampered

To prove the receipt is about your exact action, pass the expected hash — a receipt that is valid in itself but attests something else is refused:

timelayer-verifier verify receipt.tlcert receipt.tlbundle --expect "$HASH"

6. Errors

Errors return a JSON body { "error": "…" }. On any doubt the API fails closed — it never returns a half-valid receipt.

StatusBodyMeaning & fix
401(none)No Authorization header. Add Bearer <token>.
401AUTH FAILToken missing, wrong, or revoked. Copy a fresh token from the cabinet.
401NOTARIZE FAIL reason=empty_actionaction_hex is missing, empty, or not valid hex. Send lowercase hex of a real hash.

7. Python & Node

# Python (stdlib only)
import hashlib, json, urllib.request, os

h = hashlib.sha256(b"invoice #4471 approved").hexdigest()
req = urllib.request.Request(
    "https://api.timelayer-os.com/v1/notarize",
    data=json.dumps({"action_hex": h}).encode(),
    headers={"Authorization": f"Bearer {os.environ['TL_TOKEN']}",
             "Content-Type": "application/json"}, method="POST")
r = json.load(urllib.request.urlopen(req))
open("receipt.tlcert",  "wb").write(bytes.fromhex(r["cert_hex"]))
open("receipt.tlbundle","wb").write(bytes.fromhex(r["bundle_hex"]))
// Node 18+ (global fetch)
import { createHash } from "node:crypto";
import { writeFileSync } from "node:fs";

const hash = createHash("sha256").update("invoice #4471 approved").digest("hex");
const res = await fetch("https://api.timelayer-os.com/v1/notarize", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.TL_TOKEN}`,
             "Content-Type": "application/json" },
  body: JSON.stringify({ action_hex: hash }),
});
const r = await res.json();
writeFileSync("receipt.tlcert",   Buffer.from(r.cert_hex,   "hex"));
writeFileSync("receipt.tlbundle", Buffer.from(r.bundle_hex, "hex"));

8. Balance & limits

Each successful notarization spends one receipt from your balance. New accounts start with a free allowance; after that you top up with a subscription or a one-time pack from your plans page — one-time packs never expire. Verifying receipts is always free and offline: it costs nothing and needs no token.