🧭 TimeProofs API (v0.1)
Envoyez un hash SHA-256. Recevez un timestamp signé et une URL de vérification publique. Pas d’upload. Pas de blockchain.
🌐 Base URL
https://api.timeproofs.io/api
Production. CORS ouvert pour https://timeproofs.io
.
⚡ Endpoints
Endpoint | Method | Description | Auth |
---|---|---|---|
/ping | GET | Healthcheck. | — |
/admin/timestamp | POST | Crée une preuve pour un hash SHA-256. | Bearer |
⚙️ Quickstart
1) cURL — ping
curl -s https://api.timeproofs.io/api/ping
2) cURL — créer une preuve
curl -s -X POST https://api.timeproofs.io/api/admin/timestamp \
-H "Authorization: Bearer <ADMIN_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"hash":"<64-hex-sha256>","meta":{"source":"docs"},"env":"prod"}'
Exemple de réponse
{
"ok": true,
"hash": "7c040f8633b8823d72ed63da9b3b2dfe9846e912c66a64c9433ec9c4815d76c2",
"ts": "2025-10-22T12:34:56.789Z",
"sig": "hmac_sha256(secret, `${hash}|${ts}`)",
"verify_url": "https://timeproofs.io/verify.html?hash=7c04...&ts=...&sig=...",
"meta": { "source": "docs" }
}
🔐 Hash local (browser)
const buf = new TextEncoder().encode(text);
const digest = await crypto.subtle.digest('SHA-256', buf);
const hash = [...new Uint8Array(digest)].map(b => b.toString(16).padStart(2,'0')).join('');
Envoyez uniquement le hash hexadécimal (64 chars).
🧾 Vérifier une preuve
Utilisez la page Verify pour valider publiquement une preuve (hash, timestamp, signature).
La signature serveur est un HMAC-SHA256 de ${hash}|${ts}
.
Node.js
import crypto from "node:crypto";
function verify({ hash, ts, sig }, secret){
const msg = `${hash}|${ts}`;
const expect = crypto.createHmac("sha256", secret).update(msg).digest("hex");
return crypto.timingSafeEqual(Buffer.from(expect,'hex'), Buffer.from(sig,'hex'));
}
Python
import hmac, hashlib
def verify(payload, secret: bytes) -> bool:
msg = f"{payload['hash']}|{payload['ts']}".encode()
sig = hmac.new(secret, msg, hashlib.sha256).hexdigest()
return hmac.compare_digest(sig, payload["sig"])
📦 Schémas JSON
POST /admin/timestamp — request
{
"type":"object",
"required":["hash"],
"properties":{
"hash":{"type":"string","pattern":"^[a-f0-9]{64}$"},
"meta":{"type":"object","maxProperties":32,"additionalProperties":true},
"env":{"type":"string","maxLength":16}
},
"additionalProperties": false
}
POST /admin/timestamp — response
{
"type":"object",
"required":["ok","hash","ts","sig","verify_url"],
"properties":{
"ok":{"type":"boolean"},
"hash":{"type":"string"},
"ts":{"type":"string","format":"date-time"},
"sig":{"type":"string"},
"verify_url":{"type":"string","format":"uri"},
"meta":{"type":"object"}
}
}
🚦 Status & erreurs
Status | Quand | Body |
---|---|---|
200 | Succès | Objet JSON |
400 | JSON invalide / hash invalide | { "ok":false, "error":"..." } |
401 | Bearer manquant/erroné | { "ok":false, "error":"unauthorized" } |
404 | Route inconnue | { "ok":false, "error":"not_found" } |
429 | Rate limit (si activée) | { "ok":false, "error":"rate_limited" } |
500 | Erreur serveur | { "ok":false, "error":"internal" } |