TimeLayer Инженерные записки Справочник API
Справочник REST Один эндпоинт ~6 мин чтения

TimeLayer API: один вызов — одна квитанция

Весь API — это один HTTP-вызов. Вы локально хешируете действие или документ, отправляете только хеш и получаете самодостаточную квитанцию: пользователь держит её у себя, а проверить может любой офлайн. Ваш контент не покидает вашу машину.

1. Две минуты до первой квитанции

  1. Заведите бесплатный аккаунт на cabinet.timelayer-os.com — на старте дают бесплатные квитанции.
  2. Скопируйте API-токен из кабинета.
  3. Захешируйте что угодно и заверьте:
# хеш строки (или файла: shasum -a 256 file)
HASH=$(printf 'счёт #4471 одобрен 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\"}"

В ответ придут cert_hex и bundle_hex. Раскодируйте их в байты, сохраните как .tlcert и .tlbundle — и у вас на руках проверяемая квитанция.

2. Базовый URL и аутентификация

Базовый URL: https://api.timelayer-os.com. Каждый запрос несёт токен в заголовке:

Authorization: Bearer <ваш API-токен>

Держите токен на сервере

Токен тратит ваш баланс квитанций. Держите его в переменной окружения, никогда — в клиентском коде или публичном репозитории. Посмотреть и перевыпустить его можно в кабинете.

3. POST /v1/notarize

Единственный эндпоинт. Принимает хеш того, что вы хотите доказать, и возвращает квитанцию, заверяющую именно этот хеш.

ПолеЗначение
action_hexHex хеша вашего действия или документа. Обычно SHA-256; привязка алгоритмо-нейтральна (SHA-256, BLAKE3, SHA-3…). Строчный hex, без префикса 0x.

Тело запроса:

{ "action_hex": "b557d79ce260ed0edb9e548a9b3fe417967b6174f0e9c99ea28bfa1f27561c1e" }

Отправляется только хеш. TimeLayer никогда не видит ваше действие или документ — в этом и смысл (Zero-Data): сеть заверяет отпечаток, а не содержимое.

4. Квитанция: cert + bundle

Успешный вызов возвращает две hex-строки:

{
  "cert_hex":   "…",   // сертификат, ~415 байт после декода
  "bundle_hex": "…"    // доказательная часть, ~1 КБ после декода
}

Это сырые байты в hex, не текст. Раскодируйте каждую из hex и запишите байты в файл — верификатор читает именно декодированные байты:

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

Пара путешествует вместе с действием. Отдайте её пользователю, вложите в документ или храните в своей базе — центрального лога держать не нужно, и верить нам потом ни в чём не придётся.

5. Проверка офлайн

Любой проверяет квитанцию на своей машине, без сети и без аккаунта, открытым верификатором:

timelayer-verifier verify receipt.tlcert receipt.tlbundle
# -> VALID FINAL        подлинна и полна
# -> UNVERIFIABLE        подделка, расхождение или порча

Чтобы доказать, что квитанция про именно ваше действие, передайте ожидаемый хеш — квитанцию, валидную саму по себе, но заверяющую другое, верификатор отвергнет:

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

6. Ошибки

Ошибки возвращают JSON { "error": "…" }. При любом сомнении API падает закрыто — он никогда не вернёт полу-валидную квитанцию.

СтатусТелоЗначение и что делать
401(нет)Нет заголовка Authorization. Добавьте Bearer <токен>.
401AUTH FAILТокен отсутствует, неверный или отозван. Скопируйте свежий токен из кабинета.
401NOTARIZE FAIL reason=empty_actionaction_hex пуст, отсутствует или не hex. Пришлите строчный hex настоящего хеша.

7. Python и Node

# Python (только стандартная библиотека)
import hashlib, json, urllib.request, os

h = hashlib.sha256("счёт #4471 одобрен".encode()).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+ (глобальный fetch)
import { createHash } from "node:crypto";
import { writeFileSync } from "node:fs";

const hash = createHash("sha256").update("счёт #4471 одобрен").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. Баланс и лимиты

Каждое успешное заверение тратит одну квитанцию с баланса. Новые аккаунты стартуют с бесплатным лимитом; дальше пополняете подпиской или разовым пакетом со страницы тарифов — разовые пакеты не сгорают. Проверка квитанций всегда бесплатна и офлайн: не стоит ничего и не требует токена.