Référence de l’API
API v2 de Sellat
Tout ce que fait l’application web, depuis votre propre système : enregistrer l’empreinte SHA-256 d’un fichier, l’ancrer sur Polygon et Bitcoin, demander l’horodatage qualifié de la FNMT, télécharger le certificat et le dossier de preuves, et conserver l’original. REST et JSON, avec une clé d’API.
https://sellat.app/api/v2 Introduction
L’API travaille avec l’empreinte du fichier, pas avec le fichier : vous calculez le SHA-256 chez vous et n’envoyez que ces 64 caractères. L’original ne quitte pas votre machine, sauf si vous choisissez de le confier en conservation.
Chaque preuve entre dans un lot Merkle ancré sur Polygon, et le même lot est attesté sur Bitcoin. Si vous le demandez, l’empreinte reçoit aussi l’horodatage qualifié de la FNMT-RCM, prestataire qualifié de la liste de confiance de l’UE.
Toutes les routes partent de l’URL de base et parlent JSON. Les preuves créées par l’API et sur le web appartiennent au même compte et apparaissent dans le même tableau de bord.
Elle est faite pour être appelée depuis un serveur : elle n’envoie pas d’en-têtes CORS, donc un navigateur ne peut pas l’appeler depuis un autre site, et votre clé ne doit jamais se trouver dans du code qui arrive au navigateur.
Authentification
Chaque requête porte votre clé dans l’en-tête Authorization: Bearer sellat_.... Les clés se créent et se révoquent depuis votre tableau de bord ; un compte peut avoir jusqu’à 5 clés actives, une par intégration.
Sans clé, ou avec une clé révoquée, l’API répond 401 unauthorized avec l’en-tête WWW-Authenticate: Bearer. La seule route publique est la preuve portable (/proof/{id}.json).
curl https://sellat.app/api/v2/account \
-H "Authorization: Bearer sellat_3f9c..." Démarrage rapide
Calculez l’empreinte, créez la preuve avec l’horodatage qualifié et gardez l’id renvoyé. En quelques minutes elle passe à anchored et toutes ses URL fonctionnent.
Sans "qualified": true, la preuve est tout aussi vérifiable (Polygon et Bitcoin) et ne consomme pas d’horodatage. Vous pouvez le demander plus tard avec POST /proofs/{id}/qualified.
# Your key, from the dashboard
export SELLAT_API_TOKEN=sellat_...
# The fingerprint: the file stays on your machine
HASH=$(sha256sum contract.pdf | cut -d' ' -f1)
# The proof, with the FNMT qualified seal
curl https://sellat.app/api/v2/proofs \
-H "Authorization: Bearer $SELLAT_API_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"hash\":\"$HASH\",\"name\":\"contract.pdf\",\"qualified\":true}" États d’une preuve
Le champ state dit ce que Sellat sait à chaque instant : il ne présente jamais comme confirmée une transaction qu’il n’a pas encore vérifiée.
L’attestation Bitcoin (bitcoin) suit son propre chemin : pending jusqu’à ce qu’OpenTimestamps l’inclue dans un bloc, puis confirmed avec sa hauteur. L’horodatage qualifié (qualified) ne dépend pas de l’état : il est émis tout de suite.
| État | Signification |
|---|---|
queued | Reçue. Attend d’entrer dans un lot, deux minutes environ au plus. |
batched | Dans un lot Merkle, chemin fixé. Attend l’ancrage sur Polygon. |
anchored | Ancrée : la transaction est dans un bloc Polygon. proof.json est disponible. |
confirmed | Le bloc a 12 confirmations. |
Erreurs
Une erreur est toujours un JSON avec error.code (stable, pour votre code) et error.message (pour les personnes). Certaines ajoutent des champs, comme seals_remaining et buy_url sur un 402. La preuve portable, publique, répond {"error": "..."}.
Si la passerelle coupe une requête avant l’API (trop de requêtes depuis une IP, ou un corps de plus de 25 Mo), ce 429 ou ce 413 n’a pas ce format.
| Code | HTTP | Ce qui s’est passé |
|---|---|---|
invalid_request | 400 | Un champ manque ou n’a pas le format attendu. Le message dit lequel. |
unauthorized | 401 | Pas de clé, clé mal formée ou révoquée. |
payment_required | 402 | Plus d’horodatages qualifiés. Contient seals_remaining et buy_url. |
key_without_account | 403 | La clé n’est rattachée à aucun compte (anciennes clés). |
not_found | 404 | La preuve n’existe pas ou appartient à un autre compte. |
conflict | 409 | Un autre compte a enregistré ces octets en premier, ou l’original n’est pas encore stocké. |
hash_mismatch | 409 | Le fichier envoyé n’a pas l’empreinte de la preuve. |
file_too_large | 413 | Le fichier dépasse la limite par fichier de votre offre (max_file_bytes). |
rate_limited | 429 | Trop de requêtes par minute. Respectez Retry-After. |
quota_exceeded | 429 | Limite quotidienne de preuves atteinte. Retry-After jusqu’à 00:00 UTC. |
download_quota_exceeded | 429 | Limite quotidienne de téléchargements de l’original atteinte. |
integrity_failed | 500 | L’original stocké ne correspond plus à son empreinte ; il n’est pas servi. |
unavailable | 502 · 503 | Un service interne ne répond pas. Réessayez plus tard. |
seal_unavailable | 503 | L’autorité d’horodatage n’est pas disponible pour le moment. |
custody_unavailable | 503 | La conservation n’est pas disponible pour le moment. |
custody_quota_exceeded | 507 | Plus d’espace de conservation sur votre compte. |
{
"error": {
"code": "payment_required",
"message": "No qualified seals left on this account.",
"seals_remaining": 0,
"buy_url": "https://sellat.app/precios"
}
} Limites
Chaque compte peut créer un nombre de preuves par API et par jour, toutes clés confondues. Les preuves faites sur le web ne comptent pas, ni le renvoi d’octets qui vous appartiennent déjà. La journée repart à 00:00 UTC.
À la limite, POST /proofs répond 429 quota_exceeded avec un objet quota et Retry-After. Chaque route a aussi un frein par minute (par exemple 60 créations et 10 horodatages par minute) qui répond 429 rate_limited, et la passerelle accepte jusqu’à 120 requêtes par minute et par IP. Un corps de requête fait 25 Mo au plus.
Les horodatages qualifiés n’ont pas de limite quotidienne : chacun consomme un horodatage de votre solde. Consultez ce qu’il vous reste à tout moment avec GET /account, et pour plus de volume, écrivez à [email protected].
| Compte gratuit | Compte Pro | |
|---|---|---|
| Preuves par API et par jour | 10 | 5 000 |
| Clés actives | 5 | 5 |
| Original en conservation, par fichier | 10 MB | 50 MB |
| Conservation au total | 50 MB | 5 GB |
| Téléchargements de l’original par jour | 10 | 50 |
HTTP/1.1 429 Too Many Requests
Retry-After: 41231
{
"error": {
"code": "quota_exceeded",
"message": "Daily limit reached: 10 proofs per account per UTC day across all its keys.",
"quota": {
"limit": 10,
"used": 10,
"resets_in_seconds": 41231
}
}
} Idempotence
Envoyez un en-tête Idempotency-Key (jusqu’à 200 caractères) avec POST /proofs et vous pourrez réessayer sans risque : si vous l’avez déjà utilisé avec la même clé d’API, vous recevez la preuve d’origine avec 200 et "created": false, quel que soit le nouveau corps, et aucun horodatage n’est émis.
Sans l’en-tête, renvoyer des octets qui appartiennent déjà à votre compte renvoie aussi la preuve existante (200), sans changer son nom ni ses métadonnées. Mais si un autre compte a enregistré ces octets en premier, chaque requête crée une nouvelle preuve avec limitations : si vous pouvez réessayer, utilisez toujours Idempotency-Key.
L’horodatage n’est jamais dupliqué non plus : une preuve en a un seul, et le redemander renvoie le même sans en consommer un autre.
Vérifier sans Sellat
Une preuve Sellat n’a pas besoin de Sellat pour être vérifiée. Avec le fichier et son proof.json, le vérificateur open source recalcule l’empreinte et le chemin Merkle, et lit l’ancrage sur la blockchain publique.
L’horodatage qualifié se vérifie avec OpenSSL, avec le fichier, le .tsr et le certificat de l’autorité, fourni dans le dossier de preuves. -partial_chain est nécessaire parce que la liste de confiance publie le certificat de l’autorité elle-même, pas celui d’une CA.
# 1. The proof: file + proof.json + the public blockchain
curl https://sellat.app/api/v2/proof/6f2c9b1e-0d1a-4b9f-8e7c-2a4d5b6c7d8e.json -o proof.json
npx sellat-verify contract.pdf proof.json
# 2. The qualified seal: file + .tsr + the authority's certificate
# (autoridad-sellado.pem comes inside evidence.zip)
openssl ts -verify -in seal.tsr -data contract.pdf \
-CAfile autoridad-sellado.pem -partial_chain Preuves
Créer une preuve
POST /proofs
Enregistre l’empreinte SHA-256 d’un fichier et renvoie la preuve. Avec "qualified": true, elle émet aussi l’horodatage qualifié de la FNMT dans le même appel, en consommant un horodatage du compte.
Paramètres
-
hashobligatoire - L’empreinte SHA-256 du fichier : 64 caractères hexadécimaux.
-
namefacultatif - Le nom affiché dans le tableau de bord et sur le certificat. Seul le nom du fichier est gardé, sans le chemin. Par défaut, les 12 premiers caractères du hash.
-
metadatafacultatif - Un objet JSON à vous, jusqu’à 4 Ko. Stocké avec la preuve, jamais renvoyé ni publié.
-
sizefacultatif - Taille du fichier en octets. Informatif.
-
mime_typefacultatif - Type du fichier, utilisé pour servir l’original si vous le conservez. Par défaut,
application/octet-stream. -
qualifiedfacultatif -
trueémet aussi l’horodatage qualifié de la FNMT. -
Idempotency-Keyfacultatif - Réessayer sans dupliquer (voir Idempotence).
Réponses
- 201
- Preuve créée.
- 200
- Elle existait déjà : ces octets appartiennent déjà à votre compte, ou vous avez répété une
Idempotency-Key. Contient"created": false. - 400
invalid_request: un champ manque ou n’est pas valide.- 401
unauthorized.- 402
payment_required: horodatage demandé, mais il ne vous en reste plus. Rien n’est écrit.- 409
conflict: horodatage demandé sur des octets qu’un autre compte a enregistrés en premier.- 429
quota_exceeded(limite quotidienne) ourate_limited(par minute).- 503
seal_unavailableouunavailable. Si la preuve a été créée, l’erreur contient sonproof_id.
Si l’autorité tarde à répondre, la preuve est quand même créée et qualified arrive comme {"state": "pending"} : redemandez-le avec POST /proofs/{id}/qualified, sans frais.
Si un autre compte a enregistré ces octets en premier, la preuve est créée et ancrée, mais sans certificat propre : les URL du certificat sont null et la réponse contient "limitations": ["hash_registered_by_another_account"].
curl https://sellat.app/api/v2/proofs \
-H "Authorization: Bearer $SELLAT_API_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: contract-2026-0142" \
-d '{
"hash": "9f3c2a5e0b7d1c4f8a6e2d9b3c7f1a5e8d2c6b0f4a9e3d7c1b5f8a2e6d0c4b9f",
"name": "contract.pdf",
"qualified": true,
"metadata": { "ref": "case-2026-0142" }
}' {
"id": "6f2c9b1e-0d1a-4b9f-8e7c-2a4d5b6c7d8e",
"created": true,
"hash": "9f3c2a5e0b7d1c4f8a6e2d9b3c7f1a5e8d2c6b0f4a9e3d7c1b5f8a2e6d0c4b9f",
"algorithm": "SHA-256",
"name": "contract.pdf",
"state": "queued",
"received_at": "2026-09-30T09:12:03.418Z",
"anchors": [],
"bitcoin": {
"state": "pending",
"block_height": null
},
"qualified": {
"state": "issued",
"authority": "FNMT-RCM",
"time": "2026-09-30T09:12:05.000Z",
"serial_number": "175755C77B4239226AA0428FE1C107C1",
"policy_oid": "0.4.0.2023.1.1",
"tsr_url": "https://sellat.app/api/v2/proofs/6f2c9b1e-0d1a-4b9f-8e7c-2a4d5b6c7d8e/qualified.tsr"
},
"original": null,
"urls": {
"self": "https://sellat.app/api/v2/proofs/6f2c9b1e-0d1a-4b9f-8e7c-2a4d5b6c7d8e",
"proof_json": "https://sellat.app/api/v2/proof/6f2c9b1e-0d1a-4b9f-8e7c-2a4d5b6c7d8e.json",
"certificate": "https://sellat.app/certificate/3b1d7e42-9c5a-4f0e-b8d6-1a2c3e4f5a6b",
"certificate_pdf": "https://sellat.app/api/v2/proofs/6f2c9b1e-0d1a-4b9f-8e7c-2a4d5b6c7d8e/certificate.pdf",
"evidence_zip": "https://sellat.app/api/v2/proofs/6f2c9b1e-0d1a-4b9f-8e7c-2a4d5b6c7d8e/evidence.zip"
}
} Consulter une preuve
GET /proofs/{id}
Renvoie la preuve avec son état, ses ancrages, l’attestation Bitcoin, l’horodatage s’il existe, l’original s’il est conservé, et toutes ses URL.
Paramètres
-
idobligatoire - L’
idde la preuve.
Réponses
- 200
- La preuve.
- 401
unauthorized.- 404
not_found: elle n’existe pas ou appartient à un autre compte.
curl https://sellat.app/api/v2/proofs/6f2c9b1e-0d1a-4b9f-8e7c-2a4d5b6c7d8e \
-H "Authorization: Bearer $SELLAT_API_TOKEN" {
"id": "6f2c9b1e-0d1a-4b9f-8e7c-2a4d5b6c7d8e",
"hash": "9f3c2a5e0b7d1c4f8a6e2d9b3c7f1a5e8d2c6b0f4a9e3d7c1b5f8a2e6d0c4b9f",
"algorithm": "SHA-256",
"name": "contract.pdf",
"state": "anchored",
"received_at": "2026-09-30T09:12:03.418Z",
"anchors": [
{
"network": "Polygon Mainnet",
"chain_id": 137,
"state": "anchored",
"tx_hash": "0xa4195d4ea808610dee92a1caa221d35f289e61674f451c82f7428e29813f9d6a",
"block_number": 94653624,
"block_timestamp": "2026-09-30T09:14:36.000Z",
"explorer_url": "https://polygonscan.com/tx/0xa4195d4ea808610dee92a1caa221d35f289e61674f451c82f7428e29813f9d6a"
}
],
"bitcoin": {
"state": "pending",
"block_height": null
},
"qualified": {
"state": "issued",
"authority": "FNMT-RCM",
"time": "2026-09-30T09:12:05.000Z",
"serial_number": "175755C77B4239226AA0428FE1C107C1",
"policy_oid": "0.4.0.2023.1.1",
"tsr_url": "https://sellat.app/api/v2/proofs/6f2c9b1e-0d1a-4b9f-8e7c-2a4d5b6c7d8e/qualified.tsr"
},
"original": null,
"urls": {
"self": "https://sellat.app/api/v2/proofs/6f2c9b1e-0d1a-4b9f-8e7c-2a4d5b6c7d8e",
"proof_json": "https://sellat.app/api/v2/proof/6f2c9b1e-0d1a-4b9f-8e7c-2a4d5b6c7d8e.json",
"certificate": "https://sellat.app/certificate/3b1d7e42-9c5a-4f0e-b8d6-1a2c3e4f5a6b",
"certificate_pdf": "https://sellat.app/api/v2/proofs/6f2c9b1e-0d1a-4b9f-8e7c-2a4d5b6c7d8e/certificate.pdf",
"evidence_zip": "https://sellat.app/api/v2/proofs/6f2c9b1e-0d1a-4b9f-8e7c-2a4d5b6c7d8e/evidence.zip"
}
} Lister les preuves
GET /proofs
Les preuves de votre compte, les plus récentes d’abord : celles créées par l’API et celles créées sur le web. Chaque élément de data est une preuve complète, comme GET /proofs/{id}.
Pour la page suivante, passez le next_cursor renvoyé par la précédente. Quand il vaut null, il n’y en a plus.
Paramètres
-
limitfacultatif - Preuves par page, de 1 à 100. Par défaut, 25.
-
cursorfacultatif - Le
next_cursorde la page précédente.
Réponses
- 200
dataetnext_cursor.- 400
invalid_request:limitoucursorinvalide.- 401
unauthorized.
curl "https://sellat.app/api/v2/proofs?limit=25" \
-H "Authorization: Bearer $SELLAT_API_TOKEN" {
"data": [
{
"id": "6f2c9b1e-0d1a-4b9f-8e7c-2a4d5b6c7d8e",
"hash": "9f3c2a5e0b7d1c4f8a6e2d9b3c7f1a5e8d2c6b0f4a9e3d7c1b5f8a2e6d0c4b9f",
"name": "contract.pdf",
"state": "confirmed",
"received_at": "2026-09-30T09:12:03.418Z"
}
],
"next_cursor": "1843"
} Horodatage qualifié (eIDAS)
Demander l’horodatage qualifié
POST /proofs/{id}/qualified
Émet un horodatage RFC 3161 de la FNMT-RCM sur l’empreinte du fichier. Selon l’article 41, paragraphe 2, du règlement eIDAS, un horodatage électronique qualifié bénéficie d’une présomption d’exactitude de la date et de l’heure qu’il indique et d’intégrité des données.
Il consomme un horodatage du compte : celui de bienvenue ou l’un de vos packs. L’API ne débite jamais de carte et n’ouvre aucun paiement ; les packs s’achètent sur la page des tarifs.
Paramètres
-
idobligatoire - L’
idde la preuve.
Réponses
- 200
- Horodatage émis, ou il existait déjà (
"created": false, rien consommé). Contientseals_remaining. - 202
- L’horodatage est payé, mais l’autorité n’a pas répondu. Rappelez (
Retry-After: 30) : il se termine sans frais. - 401
unauthorized.- 402
payment_required: plus d’horodatages. Contientseals_remainingetbuy_url.- 404
not_found.- 409
conflict: un autre compte a enregistré ces octets en premier.- 503
seal_unavailable.
Une preuve a un seul horodatage, pour toujours. Si l’émission échoue définitivement, l’horodatage revient à votre solde.
curl -X POST https://sellat.app/api/v2/proofs/6f2c9b1e-0d1a-4b9f-8e7c-2a4d5b6c7d8e/qualified \
-H "Authorization: Bearer $SELLAT_API_TOKEN" {
"proof_id": "6f2c9b1e-0d1a-4b9f-8e7c-2a4d5b6c7d8e",
"created": true,
"qualified": {
"state": "issued",
"authority": "FNMT-RCM",
"time": "2026-09-30T09:12:05.000Z",
"serial_number": "175755C77B4239226AA0428FE1C107C1",
"policy_oid": "0.4.0.2023.1.1",
"tsr_url": "https://sellat.app/api/v2/proofs/6f2c9b1e-0d1a-4b9f-8e7c-2a4d5b6c7d8e/qualified.tsr"
},
"seals_remaining": 4
} Consulter l’horodatage
GET /proofs/{id}/qualified
Renvoie seulement l’horodatage de la preuve, ou null s’il n’y en a pas encore. N’émet rien et ne consomme rien.
Paramètres
-
idobligatoire - L’
idde la preuve.
Réponses
- 200
proof_idetqualified.- 401
unauthorized.- 404
not_found.
curl https://sellat.app/api/v2/proofs/6f2c9b1e-0d1a-4b9f-8e7c-2a4d5b6c7d8e/qualified \
-H "Authorization: Bearer $SELLAT_API_TOKEN" {
"proof_id": "6f2c9b1e-0d1a-4b9f-8e7c-2a4d5b6c7d8e",
"qualified": {
"state": "issued",
"authority": "FNMT-RCM",
"time": "2026-09-30T09:12:05.000Z",
"serial_number": "175755C77B4239226AA0428FE1C107C1",
"policy_oid": "0.4.0.2023.1.1",
"tsr_url": "https://sellat.app/api/v2/proofs/6f2c9b1e-0d1a-4b9f-8e7c-2a4d5b6c7d8e/qualified.tsr"
}
} Télécharger le jeton (.tsr)
GET /proofs/{id}/qualified.tsr
L’horodatage tel que l’autorité l’a renvoyé : une TimeStampResp RFC 3161 en DER. C’est le fichier qu’un expert ou un tribunal peut valider sans Sellat.
Paramètres
-
idobligatoire - L’
idde la preuve.
Réponses
- 200
- Le
.tsr(application/timestamp-reply). - 401
unauthorized.- 404
not_found: la preuve n’existe pas ou n’a pas encore d’horodatage.
curl https://sellat.app/api/v2/proofs/6f2c9b1e-0d1a-4b9f-8e7c-2a4d5b6c7d8e/qualified.tsr \
-H "Authorization: Bearer $SELLAT_API_TOKEN" \
-o seal.tsr HTTP/1.1 200 OK
Content-Type: application/timestamp-reply
Content-Disposition: attachment; filename="sellat-6f2c9b1e-0d1a-4b9f-8e7c-2a4d5b6c7d8e-qualified-timestamp.tsr"
<RFC 3161 TimeStampResp, DER> Certificat et preuves
Certificat PDF
GET /proofs/{id}/certificate.pdf
Le certificat de la preuve, pour les personnes : l’empreinte, la date, les ancrages et l’horodatage qualifié s’il existe, avec les instructions pour le vérifier.
Paramètres
-
idobligatoire - L’
idde la preuve. -
langfacultatif - Langue du certificat :
es,en,deoufr. Toute autre valeur donneen.
Réponses
- 200
- Le PDF.
- 401
unauthorized.- 404
not_found.- 409
conflict: un autre compte a enregistré ces octets en premier et la preuve n’a pas de certificat propre.
curl "https://sellat.app/api/v2/proofs/6f2c9b1e-0d1a-4b9f-8e7c-2a4d5b6c7d8e/certificate.pdf?lang=es" \
-H "Authorization: Bearer $SELLAT_API_TOKEN" \
-o certificate.pdf HTTP/1.1 200 OK
Content-Type: application/pdf
Content-Disposition: attachment; filename="certificado-3b1d7e42-9c5a-4f0e-b8d6-1a2c3e4f5a6b.pdf"
<PDF> Dossier de preuves
GET /proofs/{id}/evidence.zip
Un ZIP avec ce qu’il faut pour défendre la preuve sans Sellat : le certificat, le proof.json, l’horodatage et le certificat de l’autorité s’il existe, les instructions et, s’il est conservé, l’original.
Paramètres
-
idobligatoire - L’
idde la preuve. -
langfacultatif - Langue des textes du dossier :
es,en,deoufr.
Réponses
- 200
- Le ZIP.
- 401
unauthorized.- 404
not_found.- 409
conflict: un autre compte a enregistré ces octets en premier.
Joindre l’original consomme l’un des téléchargements du jour. S’il n’en reste plus, le dossier sort sans lui et le README le dit.
curl "https://sellat.app/api/v2/proofs/6f2c9b1e-0d1a-4b9f-8e7c-2a4d5b6c7d8e/evidence.zip?lang=es" \
-H "Authorization: Bearer $SELLAT_API_TOKEN" \
-o evidence.zip HTTP/1.1 200 OK
Content-Type: application/zip
Content-Disposition: attachment; filename="sellat-evidencia-3b1d7e42-9c5a-4f0e-b8d6-1a2c3e4f5a6b.zip"
<ZIP> Conservation de l’original
Déposer l’original
PUT /proofs/{id}/original
Stocke le fichier à côté de sa preuve, sur des serveurs de l’Union européenne. Sellat recalcule l’empreinte de ce qu’il reçoit et le refuse s’il ne correspond pas à la preuve.
Envoyez les octets bruts avec le Content-Type du fichier, ou en multipart/form-data dans le champ file. POST fonctionne comme PUT.
Paramètres
-
idobligatoire - L’
idde la preuve. -
fileobligatoire - Le fichier. Jusqu’à 10 MB avec le compte gratuit et 50 MB avec le compte Pro, et 25 Mo par requête au plus.
Réponses
- 201
- Stocké. Renvoie la preuve avec
original. - 200
- Il était déjà stocké.
- 400
invalid_request: corps vide ou illisible.- 401
unauthorized.- 404
not_found.- 409
hash_mismatch(ce n’est pas le fichier de la preuve) ouconflict(octets d’un autre compte).- 413
file_too_large: au-delà de la limite par fichier de votre offre. Contientmax_file_bytes.- 502
unavailable: le stockage n’a pas répondu.- 503
custody_unavailable.- 507
custody_quota_exceeded: plus d’espace sur votre compte. Contientused_bytesetmax_account_bytes.
La conservation est facultative : la preuve vaut autant sans l’original. Conserver ajoute la préservation ; cela ne conditionne pas la preuve.
curl -X PUT https://sellat.app/api/v2/proofs/6f2c9b1e-0d1a-4b9f-8e7c-2a4d5b6c7d8e/original \
-H "Authorization: Bearer $SELLAT_API_TOKEN" \
-H "Content-Type: application/pdf" \
--data-binary @contract.pdf {
"id": "6f2c9b1e-0d1a-4b9f-8e7c-2a4d5b6c7d8e",
"state": "anchored",
"original": {
"stored": true,
"file_name": "contract.pdf",
"size_bytes": 184320,
"mime_type": "application/pdf",
"stored_at": "2026-09-30T09:15:10.000Z",
"url": "https://sellat.app/api/v2/proofs/6f2c9b1e-0d1a-4b9f-8e7c-2a4d5b6c7d8e/original"
}
} Télécharger l’original
GET /proofs/{id}/original
Renvoie le fichier conservé. Sellat recalcule son empreinte à la sortie et refuse de le servir s’il ne correspond plus. Chaque téléchargement compte dans la limite quotidienne de votre offre ; l’en-tête X-Sellat-Custody-Downloads-Remaining indique combien il en reste.
Paramètres
-
idobligatoire - L’
idde la preuve.
Réponses
- 200
- Le fichier, avec son type et son nom.
- 401
unauthorized.- 404
- Aucun original en conservation.
- 409
conflict: l’original n’est pas encore stocké.- 429
download_quota_exceeded: limite quotidienne de téléchargements. Repart à 00:00 UTC.- 500
integrity_failed: ce qui est stocké ne correspond plus à l’empreinte.- 502
unavailable.
curl https://sellat.app/api/v2/proofs/6f2c9b1e-0d1a-4b9f-8e7c-2a4d5b6c7d8e/original \
-H "Authorization: Bearer $SELLAT_API_TOKEN" \
-o contract.pdf HTTP/1.1 200 OK
Content-Type: application/pdf
Content-Disposition: attachment; filename="contract.pdf"
X-Sellat-Custody-Downloads-Remaining: 9
<the original bytes> Mettre fin à la conservation
DELETE /proofs/{id}/original
Supprime l’original conservé. La preuve ne change pas : elle reste ancrée, horodatée et vérifiable.
Paramètres
-
idobligatoire - L’
idde la preuve.
Réponses
- 200
"original": nullet"proof_unaffected": true."purged": falsesignifie que la suppression physique est en file d’attente.- 401
unauthorized.- 404
- Aucun original en conservation.
curl -X DELETE https://sellat.app/api/v2/proofs/6f2c9b1e-0d1a-4b9f-8e7c-2a4d5b6c7d8e/original \
-H "Authorization: Bearer $SELLAT_API_TOKEN" {
"proof_id": "6f2c9b1e-0d1a-4b9f-8e7c-2a4d5b6c7d8e",
"original": null,
"purged": true,
"proof_unaffected": true
} Compte
Votre compte
GET /account
Ce que peut faire la clé qui appelle : l’offre, les horodatages qu’il vous reste (bienvenue et packs), l’espace et les téléchargements de conservation, les preuves du jour et leur limite, et les clés actives. Consultez-le avant un gros lot.
Le bloc connector contient les limites des boutiques connectées (WooCommerce, bientôt disponible).
Réponses
- 200
- Le compte.
- 401
unauthorized.
curl https://sellat.app/api/v2/account \
-H "Authorization: Bearer $SELLAT_API_TOKEN" {
"plan": "free",
"plan_name": "Free",
"seals": {
"available": true,
"remaining": 1,
"welcome_remaining": 1,
"pack_remaining": 0,
"price_eur": 6,
"buy_url": "https://sellat.app/precios"
},
"custody": {
"available": true,
"used_bytes": 0,
"max_account_bytes": 52428800,
"max_file_bytes": 10485760,
"downloads_used_today": 0,
"max_downloads_per_day": 10
},
"proofs": {
"daily_limit": 10,
"used_today": 3,
"resets_in_seconds": 41231
},
"connector": {
"mode_available": "daily",
"eidas_available": false,
"custody_available": false,
"operations": {
"daily_limit": 2000,
"resets_in_seconds": 41231
}
},
"keys": {
"active": 1
},
"urls": {
"dashboard": "https://sellat.app/dashboard",
"plans": "https://sellat.app/precios#pricing-business",
"seals": "https://sellat.app/precios#pricing-seal-title",
"docs": "https://sellat.app/developers/docs",
"connect": "https://sellat.app/connect/woocommerce"
}
} Preuve portable
Preuve portable (proof.json)
GET /proof/{id}.json Sans clé
Le document qui permet à chacun de vérifier la preuve sans Sellat, au format public sellat-proof/2 : l’empreinte, la feuille, le chemin Merkle, la racine, l’ancrage Polygon et les attestations (Bitcoin et l’horodatage qualifié). Il est public exprès : qui le détient peut vérifier la preuve sans compte.
Paramètres
-
idobligatoire - L’
idde la preuve.
Réponses
- 200
- Le
proof.json. - 202
- Pas encore ancrée :
{"ready": false, "state": "..."}avecRetry-After: 60. - 400
- L’
idn’est pas un UUID. - 404
- Elle n’existe pas.
curl https://sellat.app/api/v2/proof/6f2c9b1e-0d1a-4b9f-8e7c-2a4d5b6c7d8e.json -o proof.json {
"schema": "sellat-proof/2",
"proof_id": "6f2c9b1e-0d1a-4b9f-8e7c-2a4d5b6c7d8e",
"content": {
"algorithm": "SHA-256",
"hash": "9f3c2a5e0b7d1c4f8a6e2d9b3c7f1a5e8d2c6b0f4a9e3d7c1b5f8a2e6d0c4b9f"
},
"leaf": {
"formula": "SHA-256('sellat-leaf:v2:' + proof_id + ':' + content.hash)",
"value": "31668b4d846680cd920a1cb5be200ab0562909e8778223087c1738746a1cbb26"
},
"merkle": {
"index": 1,
"path": [
{
"position": "left",
"hash": "9e246a6d6dda91ee3916e149d834cd9a140e3470fbf5b6ec67824705dbbc82d4"
}
],
"root": "88fa1c4c3587d86d6f713e438c7ae745a91a6e03a5dd1b8282f17f35f30bfa14"
},
"anchors": [
{
"chain_id": 137,
"network": "Polygon Mainnet",
"tx_hash": "0xa4195d4ea808610dee92a1caa221d35f289e61674f451c82f7428e29813f9d6a",
"block_number": 94653624,
"payload": "sellat:v2:88fa1c4c3587d86d6f713e438c7ae745a91a6e03a5dd1b8282f17f35f30bfa14"
}
],
"attestations": [
{
"type": "opentimestamps",
"state": "submitted"
},
{
"type": "rfc3161-qualified-timestamp",
"state": "issued"
}
]
} Il vous manque quelque chose, ou vous avez besoin de plus de volume ? Écrivez à [email protected] : vous parlerez avec ceux qui ont écrit le code.