ncantu 26a53327a4 Enhance: Complete dashboard documentation and new services integration
**Motivations:**
- Complete documentation for dashboard, domains, ports and environment configuration
- Add new services (ClamAV API, Watermark API) to the infrastructure
- Enhance dashboard with new pages and improved functionality
- Improve deployment scripts and service configurations

**Root causes:**
- Missing comprehensive documentation for infrastructure setup
- Need for antivirus scanning service integration
- Need for watermark service integration
- Dashboard required additional pages and features

**Correctifs:**
- Added comprehensive documentation in docs/ (DASHBOARD.md, DOMAINS_AND_PORTS.md, ENVIRONMENT.md)
- Updated systemd service files with proper environment variables
- Enhanced nginx proxy configuration script
- Updated maintenance documentation

**Evolutions:**
- Added new ClamAV API service (api-clamav) for file scanning
- Added new Watermark API service (api-filigrane) for document watermarking
- Enhanced signet-dashboard with new learn.html page
- Improved dashboard UI with better styles and navigation
- Enhanced app.js with new functionality and better error handling
- Updated API documentation page with complete endpoint descriptions
- Added deployment scripts for watermark and nginx configuration
- Updated hash and UTXO lists with latest data
- Enhanced server.js with new routes and improved Bitcoin RPC integration

**Pages affectées:**
- docs/DASHBOARD.md: New comprehensive dashboard documentation
- docs/DOMAINS_AND_PORTS.md: New infrastructure domains and ports documentation
- docs/ENVIRONMENT.md: New environment variables documentation
- docs/MAINTENANCE.md: Updated maintenance procedures
- docs/README.md: Updated main documentation
- signet-dashboard/public/app.js: Enhanced with new features
- signet-dashboard/public/styles.css: Improved styling
- signet-dashboard/public/index.html: Enhanced main page
- signet-dashboard/public/learn.html: New educational page
- signet-dashboard/public/api-docs.html: Enhanced API documentation
- signet-dashboard/public/hash-list.html: Updated hash list page
- signet-dashboard/public/utxo-list.html: Updated UTXO list page
- signet-dashboard/public/join-signet.html: Updated join signet page
- signet-dashboard/src/server.js: Enhanced server with new routes
- signet-dashboard/start.sh: Updated startup script
- signet-dashboard/signet-dashboard.service: Updated systemd service
- api-anchorage/anchorage-api.service: Updated systemd service
- api-faucet/faucet-api.service: Updated systemd service
- configure-nginx-proxy.sh: Enhanced nginx configuration script
- add-watermark-certificate.sh: New watermark certificate script
- deploy-watermark-nginx.sh: New deployment script
- api-clamav/: New ClamAV API service
- api-filigrane/: New Watermark API service
- hash_list.txt, utxo_list.txt: Updated with latest data
- anchor_count.txt: Updated anchor count
2026-01-25 17:43:05 +01:00

1063 lines
44 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documentation API d'Ancrage - Bitcoin Ancrage</title>
<link rel="stylesheet" href="styles.css">
<style>
.api-docs-section {
margin-bottom: 40px;
}
.endpoint-card {
background: var(--card-background);
padding: 30px;
border-radius: 10px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
margin-bottom: 30px;
}
.endpoint-header {
display: flex;
align-items: center;
margin-bottom: 20px;
padding-bottom: 15px;
border-bottom: 2px solid var(--border-color);
}
.method-badge {
display: inline-block;
padding: 5px 15px;
border-radius: 5px;
font-weight: bold;
font-size: 0.9em;
margin-right: 15px;
min-width: 70px;
text-align: center;
}
.method-get {
background: #28a745;
color: white;
}
.method-post {
background: #007bff;
color: white;
}
.endpoint-path {
font-family: 'Courier New', monospace;
font-size: 1.2em;
color: var(--primary-color);
font-weight: bold;
}
.endpoint-description {
margin: 20px 0;
color: var(--text-color);
line-height: 1.6;
}
.endpoint-params {
margin: 20px 0;
}
.endpoint-params h4 {
color: var(--primary-color);
margin-bottom: 10px;
}
.param-table {
width: 100%;
border-collapse: collapse;
margin: 15px 0;
}
.param-table th,
.param-table td {
padding: 12px;
text-align: left;
border-bottom: 1px solid var(--border-color);
}
.param-table th {
background: #f5f5f5;
font-weight: bold;
}
.param-name {
font-family: 'Courier New', monospace;
color: var(--primary-color);
font-weight: bold;
}
.param-required {
color: var(--error-color);
font-weight: bold;
}
.param-optional {
color: #666;
}
.code-block {
background: #1e1e1e;
color: #d4d4d4;
padding: 20px;
border-radius: 5px;
font-family: 'Courier New', monospace;
font-size: 0.9em;
line-height: 1.6;
overflow-x: auto;
margin: 20px 0;
}
.code-block pre {
margin: 0;
white-space: pre-wrap;
word-wrap: break-word;
}
.response-example {
margin: 20px 0;
}
.response-example h4 {
color: var(--primary-color);
margin-bottom: 10px;
}
.info-box {
background: #e7f3ff;
border-left: 4px solid #2196F3;
padding: 15px;
margin: 20px 0;
border-radius: 5px;
}
.warning-box {
background: #fff3cd;
border-left: 4px solid #ffc107;
padding: 15px;
margin: 20px 0;
border-radius: 5px;
}
.error-box {
background: #f8d7da;
border-left: 4px solid #dc3545;
padding: 15px;
margin: 20px 0;
border-radius: 5px;
}
.auth-section {
background: var(--card-background);
padding: 30px;
border-radius: 10px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
margin-bottom: 30px;
}
.copy-button {
background: var(--primary-color);
color: white;
border: none;
padding: 8px 15px;
border-radius: 5px;
cursor: pointer;
font-size: 0.9em;
margin-top: 10px;
transition: background 0.3s;
}
.copy-button:hover {
background: #e0820d;
}
.status-code {
display: inline-block;
padding: 3px 8px;
border-radius: 3px;
font-size: 0.85em;
font-weight: bold;
margin-right: 10px;
}
.status-200 {
background: #28a745;
color: white;
}
.status-400 {
background: #ffc107;
color: #000;
}
.status-401 {
background: #dc3545;
color: white;
}
.status-402 {
background: #ff9800;
color: white;
}
.status-500 {
background: #dc3545;
color: white;
}
.status-503 {
background: #ff9800;
color: white;
}
</style>
</head>
<body>
<div class="container">
<a href="/" class="back-link">← Retour au Dashboard</a>
<header>
<h1>Documentation API d'Ancrage</h1>
<p class="subtitle">API REST pour ancrer et vérifier des documents sur Bitcoin Signet, et utiliser le faucet</p>
</header>
<main>
<!-- Section Authentification -->
<section class="api-docs-section">
<div class="auth-section">
<h2>🔐 Authentification</h2>
<p>Toutes les requêtes vers l'API d'ancrage (sauf les endpoints publics) nécessitent une clé API dans le header <code>X-API-Key</code>.</p>
<div class="code-block">
<pre>X-API-Key: votre-clé-api-ici</pre>
</div>
<div class="info-box">
<p><strong>Endpoints publics (sans authentification) :</strong></p>
<ul style="margin-left: 20px; margin-top: 10px;">
<li><code>GET /health</code> - Vérification de santé (API d'ancrage)</li>
<li><code>GET /api/anchor/locked-utxos</code> - Liste des UTXO verrouillés</li>
<li><code>GET /health</code> - Vérification de santé (API faucet)</li>
</ul>
<p style="margin-top: 10px;"><strong>Endpoints nécessitant une clé API :</strong></p>
<ul style="margin-left: 20px; margin-top: 10px;">
<li><code>POST /api/anchor/document</code> - Ancrer un document</li>
<li><code>POST /api/anchor/verify</code> - Vérifier un hash</li>
<li><code>POST /api/faucet/request</code> - Demander des sats</li>
<li><code>POST /api/watermark/document</code> - Ajouter un filigrane et ancrer un document</li>
</ul>
</div>
<div class="warning-box">
<p><strong>⚠️ Important :</strong> Conservez votre clé API secrète et ne la partagez jamais publiquement.</p>
</div>
</div>
</section>
<!-- Endpoint: Health -->
<section class="api-docs-section">
<div class="endpoint-card">
<div class="endpoint-header">
<span class="method-badge method-get">GET</span>
<span class="endpoint-path">/health</span>
</div>
<div class="endpoint-description">
<p>Vérifie l'état de santé de l'API. Cet endpoint est public et ne nécessite pas d'authentification.</p>
</div>
<div class="response-example">
<h4>Réponse (200 OK)</h4>
<div class="code-block">
<pre>{
"ok": true,
"service": "anchor-api",
"bitcoin": {
"connected": true,
"blocks": 12345
},
"timestamp": "2026-01-25T12:00:00.000Z"
}</pre>
</div>
</div>
<div class="response-example">
<h4>Réponse (503 Service Unavailable) - Bitcoin non connecté</h4>
<div class="code-block">
<pre>{
"ok": false,
"service": "anchor-api",
"error": "Bitcoin RPC connection failed",
"timestamp": "2026-01-25T12:00:00.000Z"
}</pre>
</div>
</div>
</div>
</section>
<!-- Endpoint: Anchor Document -->
<section class="api-docs-section">
<div class="endpoint-card">
<div class="endpoint-header">
<span class="method-badge method-post">POST</span>
<span class="endpoint-path">/api/anchor/document</span>
</div>
<div class="endpoint-description">
<p>Ancre un document sur la blockchain Bitcoin Signet en créant une transaction qui inclut le hash du document dans un OP_RETURN.</p>
</div>
<div class="endpoint-params">
<h4>Paramètres (Body JSON)</h4>
<table class="param-table">
<thead>
<tr>
<th>Paramètre</th>
<th>Type</th>
<th>Requis</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="param-name">hash</td>
<td>string</td>
<td><span class="param-required">Oui</span></td>
<td>Hash SHA256 du document en hexadécimal (64 caractères)</td>
</tr>
<tr>
<td class="param-name">documentUid</td>
<td>string</td>
<td><span class="param-optional">Non</span></td>
<td>Identifiant optionnel du document (pour le logging)</td>
</tr>
</tbody>
</table>
</div>
<div class="response-example">
<h4>Exemple de requête</h4>
<div class="code-block">
<pre>curl -X POST https://certificator.4nkweb.com/api/anchor/document \
-H "Content-Type: application/json" \
-H "X-API-Key: votre-clé-api" \
-d '{
"hash": "a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456",
"documentUid": "doc-12345"
}'</pre>
</div>
<button class="copy-button" onclick="copyCode(this)">📋 Copier</button>
</div>
<div class="response-example">
<h4>Réponse (200 OK)</h4>
<div class="code-block">
<pre>{
"txid": "abc123def456...",
"status": "pending",
"confirmations": 0,
"block_height": null
}</pre>
</div>
</div>
<div class="response-example">
<h4>Codes de statut possibles</h4>
<ul style="margin-left: 20px;">
<li><span class="status-code status-200">200</span> Succès - Transaction créée et envoyée au mempool</li>
<li><span class="status-code status-400">400</span> Requête invalide - Hash manquant ou format incorrect</li>
<li><span class="status-code status-401">401</span> Non autorisé - Clé API manquante ou invalide</li>
<li><span class="status-code status-402">402</span> Solde insuffisant - Pas assez de fonds pour créer la transaction</li>
<li><span class="status-code status-500">500</span> Erreur serveur - Erreur interne lors de la création de la transaction</li>
</ul>
</div>
<div class="error-box">
<h4>Exemple d'erreur (402 Payment Required)</h4>
<div class="code-block">
<pre>{
"error": "Insufficient Balance",
"message": "Insufficient balance to create anchor transaction"
}</pre>
</div>
</div>
</div>
</section>
<!-- Endpoint: Verify -->
<section class="api-docs-section">
<div class="endpoint-card">
<div class="endpoint-header">
<span class="method-badge method-post">POST</span>
<span class="endpoint-path">/api/anchor/verify</span>
</div>
<div class="endpoint-description">
<p>Vérifie si un hash est ancré sur la blockchain Bitcoin Signet. Recherche dans les transactions OP_RETURN pour trouver le hash.</p>
</div>
<div class="endpoint-params">
<h4>Paramètres (Body JSON)</h4>
<table class="param-table">
<thead>
<tr>
<th>Paramètre</th>
<th>Type</th>
<th>Requis</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="param-name">hash</td>
<td>string</td>
<td><span class="param-required">Oui</span></td>
<td>Hash SHA256 à vérifier (64 caractères hex)</td>
</tr>
<tr>
<td class="param-name">txid</td>
<td>string</td>
<td><span class="param-optional">Non</span></td>
<td>ID de transaction optionnel pour accélérer la recherche</td>
</tr>
</tbody>
</table>
</div>
<div class="response-example">
<h4>Exemple de requête</h4>
<div class="code-block">
<pre>curl -X POST https://certificator.4nkweb.com/api/anchor/verify \
-H "Content-Type: application/json" \
-H "X-API-Key: votre-clé-api" \
-d '{
"hash": "a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456",
"txid": "abc123def456..."
}'</pre>
</div>
<button class="copy-button" onclick="copyCode(this)">📋 Copier</button>
</div>
<div class="response-example">
<h4>Réponse (200 OK) - Hash trouvé</h4>
<div class="code-block">
<pre>{
"found": true,
"txid": "abc123def456...",
"block_height": 12345,
"confirmations": 100,
"timestamp": "2026-01-25T10:00:00.000Z"
}</pre>
</div>
</div>
<div class="response-example">
<h4>Réponse (200 OK) - Hash non trouvé</h4>
<div class="code-block">
<pre>{
"found": false,
"txid": null,
"block_height": null,
"confirmations": null,
"timestamp": null
}</pre>
</div>
</div>
<div class="response-example">
<h4>Codes de statut possibles</h4>
<ul style="margin-left: 20px;">
<li><span class="status-code status-200">200</span> Succès - Vérification effectuée</li>
<li><span class="status-code status-400">400</span> Requête invalide - Hash manquant ou format incorrect</li>
<li><span class="status-code status-401">401</span> Non autorisé - Clé API manquante ou invalide</li>
<li><span class="status-code status-500">500</span> Erreur serveur - Erreur interne lors de la vérification</li>
</ul>
</div>
</div>
</section>
<!-- Endpoint: Locked UTXOs -->
<section class="api-docs-section">
<div class="endpoint-card">
<div class="endpoint-header">
<span class="method-badge method-get">GET</span>
<span class="endpoint-path">/api/anchor/locked-utxos</span>
</div>
<div class="endpoint-description">
<p>Retourne la liste des UTXO actuellement verrouillés par le mutex de l'API. Cet endpoint est public et ne nécessite pas d'authentification.</p>
</div>
<div class="response-example">
<h4>Exemple de requête</h4>
<div class="code-block">
<pre>curl -X GET https://certificator.4nkweb.com/api/anchor/locked-utxos</pre>
</div>
<button class="copy-button" onclick="copyCode(this)">📋 Copier</button>
</div>
<div class="response-example">
<h4>Réponse (200 OK)</h4>
<div class="code-block">
<pre>{
"locked": [
{
"txid": "abc123def456...",
"vout": 0
},
{
"txid": "def456abc123...",
"vout": 1
}
],
"count": 2
}</pre>
</div>
</div>
</div>
</section>
<!-- Endpoint: Faucet Request -->
<section class="api-docs-section">
<div class="endpoint-card">
<div class="endpoint-header">
<span class="method-badge method-post">POST</span>
<span class="endpoint-path">/api/faucet/request</span>
</div>
<div class="endpoint-description">
<p>Demande des sats (testnet coins) via le faucet. Distribue 50 000 sats (0.0005 BTC) par défaut sur une adresse Bitcoin Signet valide. Nécessite une clé API valide dans le header <code>x-api-key</code>.</p>
</div>
<div class="endpoint-params">
<h4>Paramètres (Body JSON)</h4>
<table class="param-table">
<thead>
<tr>
<th>Paramètre</th>
<th>Type</th>
<th>Requis</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="param-name">address</td>
<td>string</td>
<td><span class="param-required">Oui</span></td>
<td>Adresse Bitcoin Signet valide (commence par <code>tb1</code>, <code>bcrt1</code>, <code>2</code> ou <code>3</code>)</td>
</tr>
</tbody>
</table>
</div>
<div class="response-example">
<h4>Exemple de requête</h4>
<div class="code-block">
<pre>curl -X POST https://certificator.4nkweb.com/api/faucet/request \
-H "Content-Type: application/json" \
-H "x-api-key: votre-clé-api" \
-d '{
"address": "tb1qwe0nv3s0ewedd63w20r8kwnv22uw8dp2tnj3qc"
}'</pre>
</div>
<button class="copy-button" onclick="copyCode(this)">📋 Copier</button>
</div>
<div class="response-example">
<h4>Réponse (200 OK)</h4>
<div class="code-block">
<pre>{
"success": true,
"txid": "a1b2c3d4e5f6789012345678901234567890123456789012345678901234567890",
"address": "tb1qwe0nv3s0ewedd63w20r8kwnv22uw8dp2tnj3qc",
"amount": 0.0005,
"amount_sats": 50000,
"status": "pending",
"confirmations": 0,
"block_height": null
}</pre>
</div>
</div>
<div class="response-example">
<h4>Codes de statut possibles</h4>
<ul style="margin-left: 20px;">
<li><span class="status-code status-200">200</span> Succès - Transaction créée et envoyée au mempool</li>
<li><span class="status-code status-400">400</span> Requête invalide - Adresse manquante ou format incorrect</li>
<li><span class="status-code status-401">401</span> Non autorisé - Clé API manquante ou invalide</li>
<li><span class="status-code status-503">503</span> Service indisponible - Solde insuffisant dans le wallet du faucet</li>
<li><span class="status-code status-500">500</span> Erreur serveur - Erreur interne lors de la création de la transaction</li>
</ul>
</div>
<div class="error-box">
<h4>Exemple d'erreur (401 Unauthorized)</h4>
<div class="code-block">
<pre>{
"error": "Unauthorized",
"message": "Invalid or missing API key"
}</pre>
</div>
</div>
<div class="error-box">
<h4>Exemple d'erreur (503 Service Unavailable)</h4>
<div class="code-block">
<pre>{
"error": "Insufficient Balance",
"message": "Insufficient balance to send coins"
}</pre>
</div>
</div>
<div class="info-box">
<h4> Notes importantes</h4>
<ul style="margin-left: 20px; margin-top: 10px;">
<li>Le montant par défaut est de 50 000 sats (0.0005 BTC)</li>
<li>L'adresse doit être une adresse Bitcoin Signet valide</li>
<li>La transaction est envoyée au mempool immédiatement</li>
<li>Le statut "pending" signifie que la transaction est dans le mempool mais pas encore confirmée</li>
<li>Les confirmations augmentent à mesure que les blocs sont minés</li>
</ul>
</div>
</div>
</section>
<!-- Endpoint: Watermark Document -->
<section class="api-docs-section">
<div class="endpoint-card">
<div class="endpoint-header">
<span class="method-badge method-post">POST</span>
<span class="endpoint-path">/api/watermark/document</span>
</div>
<div class="endpoint-description">
<p>Ajoute un filigrane à un document, le convertit en PDF, et l'ancre sur la blockchain Bitcoin Signet. Les fichiers sont automatiquement scannés avec ClamAV avant traitement.</p>
</div>
<div class="endpoint-params">
<h4>Paramètres (Body JSON)</h4>
<table class="param-table">
<thead>
<tr>
<th>Paramètre</th>
<th>Type</th>
<th>Requis</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="param-name">apiKey</td>
<td>string</td>
<td><span class="param-required">Oui</span></td>
<td>Clé API pour l'authentification (peut aussi être dans le header <code>X-API-Key</code>)</td>
</tr>
<tr>
<td class="param-name">fileData</td>
<td>string</td>
<td><span class="param-optional">Conditionnel</span></td>
<td>Fichier encodé en base64 (requis si <code>textContent</code> n'est pas fourni)</td>
</tr>
<tr>
<td class="param-name">fileName</td>
<td>string</td>
<td><span class="param-optional">Non</span></td>
<td>Nom du fichier (requis si <code>fileData</code> est fourni)</td>
</tr>
<tr>
<td class="param-name">mimeType</td>
<td>string</td>
<td><span class="param-optional">Non</span></td>
<td>Type MIME du fichier (requis si <code>fileData</code> est fourni)</td>
</tr>
<tr>
<td class="param-name">textContent</td>
<td>string</td>
<td><span class="param-optional">Conditionnel</span></td>
<td>Contenu texte à convertir en PDF (requis si <code>fileData</code> n'est pas fourni)</td>
</tr>
<tr>
<td class="param-name">watermarkOptions</td>
<td>object</td>
<td><span class="param-required">Oui</span></td>
<td>Options de filigrane (voir détails ci-dessous)</td>
</tr>
</tbody>
</table>
</div>
<div class="info-box">
<h4>Structure de watermarkOptions</h4>
<table class="param-table">
<thead>
<tr>
<th>Paramètre</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="param-name">enabled</td>
<td>boolean</td>
<td>Doit être <code>true</code></td>
</tr>
<tr>
<td class="param-name">text</td>
<td>string</td>
<td>Texte libre du filigrane (optionnel)</td>
</tr>
<tr>
<td class="param-name">signature</td>
<td>string</td>
<td>Signature cryptographique (optionnel)</td>
</tr>
<tr>
<td class="param-name">depositor</td>
<td>string</td>
<td>Nom du dépositaire (optionnel)</td>
</tr>
<tr>
<td class="param-name">dateUTC</td>
<td>boolean</td>
<td>Ajouter la date UTC dans le filigrane</td>
</tr>
<tr>
<td class="param-name">dateLocal</td>
<td>boolean</td>
<td>Ajouter la date locale dans le filigrane</td>
</tr>
<tr>
<td class="param-name">blockNumber</td>
<td>boolean</td>
<td>Ajouter le numéro de bloc dans le filigrane</td>
</tr>
<tr>
<td class="param-name">blockHash</td>
<td>boolean</td>
<td>Ajouter le hash du bloc dans le filigrane</td>
</tr>
<tr>
<td class="param-name">documentHash</td>
<td>boolean</td>
<td>Ajouter le hash du document d'origine dans le filigrane</td>
</tr>
</tbody>
</table>
</div>
<div class="response-example">
<h4>Exemple de requête</h4>
<div class="code-block">
<pre>curl -X POST https://watermark.certificator.4nkweb.com/api/watermark/document \
-H "Content-Type: application/json" \
-H "X-API-Key: votre-clé-api" \
-d '{
"apiKey": "votre-clé-api",
"fileData": "base64_encoded_file_data",
"fileName": "document.pdf",
"mimeType": "application/pdf",
"watermarkOptions": {
"enabled": true,
"text": "Document confidentiel",
"depositor": "John Doe",
"dateUTC": true,
"dateLocal": true,
"blockNumber": true,
"documentHash": true
}
}'</pre>
</div>
<button class="copy-button" onclick="copyCode(this)">📋 Copier</button>
</div>
<div class="response-example">
<h4>Réponse (200 OK)</h4>
<div class="code-block">
<pre>{
"success": true,
"antivirusScan": {
"scanned": true,
"clean": true,
"infected": false,
"viruses": [],
"error": null
},
"original": {
"txid": "abc123def456...",
"status": "pending",
"confirmations": 0,
"hash": "a1b2c3d4e5f6...",
"file": {
"name": "document.pdf",
"extension": "pdf",
"data": "base64_encoded_pdf"
}
},
"watermarked": {
"txid": "def456abc123...",
"status": "pending",
"confirmations": 0,
"hash": "b2c3d4e5f6a1...",
"file": {
"name": "document.pdf",
"extension": "pdf",
"data": "base64_encoded_pdf"
}
},
"certificate": {
"name": "certificat-document.pdf",
"extension": "pdf",
"data": "base64_encoded_pdf"
},
"merged": {
"name": "document-avec-certificat.pdf",
"extension": "pdf",
"data": "base64_encoded_pdf"
}
}</pre>
</div>
</div>
<div class="response-example">
<h4>Codes de statut possibles</h4>
<ul style="margin-left: 20px;">
<li><span class="status-code status-200">200</span> Succès - Document filigrané et ancré</li>
<li><span class="status-code status-400">400</span> Requête invalide - Fichier infecté, paramètres manquants ou incorrects</li>
<li><span class="status-code status-401">401</span> Non autorisé - Clé API manquante ou invalide</li>
<li><span class="status-code status-500">500</span> Erreur serveur - Erreur interne lors du traitement</li>
</ul>
</div>
<div class="error-box">
<h4>Exemple d'erreur (400 Bad Request) - Fichier infecté</h4>
<div class="code-block">
<pre>{
"error": "Bad Request",
"message": "File contains viruses",
"viruses": ["Trojan.Example"],
"antivirusScan": {
"scanned": true,
"clean": false,
"infected": true,
"viruses": ["Trojan.Example"],
"error": null
}
}</pre>
</div>
</div>
<div class="info-box">
<h4> Notes importantes</h4>
<ul style="margin-left: 20px; margin-top: 10px;">
<li>Tous les fichiers sont automatiquement scannés avec ClamAV avant traitement</li>
<li>Les fichiers infectés sont rejetés avec une erreur 400</li>
<li>Si ClamAV est indisponible, le traitement continue en mode dégradé (antivirusScan.scanned = false)</li>
<li>Le résultat inclut 4 fichiers PDF : original, filigrané, certificat, et fusionné (filigrané + certificat)</li>
<li>Les fichiers sont retournés en base64 dans le champ <code>data</code></li>
<li>Les TXID sont des liens cliquables vers mempool.4nkweb.com dans les résultats</li>
</ul>
</div>
</div>
</section>
<!-- Endpoint: ClamAV Scan -->
<section class="api-docs-section">
<div class="endpoint-card">
<div class="endpoint-header">
<span class="method-badge method-post">POST</span>
<span class="endpoint-path">/api/scan/buffer</span>
</div>
<div class="endpoint-description">
<p>Scanne un buffer de données (base64) pour détecter les virus avec ClamAV. Cette API est utilisée en interne par l'API filigrane.</p>
<p><strong>Base URL :</strong> <code>https://antivir.certificator.4nkweb.com</code></p>
</div>
<div class="endpoint-params">
<h4>Paramètres (Body JSON)</h4>
<table class="param-table">
<thead>
<tr>
<th>Paramètre</th>
<th>Type</th>
<th>Requis</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="param-name">data</td>
<td>string</td>
<td><span class="param-required">Oui</span></td>
<td>Données encodées en base64 à scanner</td>
</tr>
<tr>
<td class="param-name">filename</td>
<td>string</td>
<td><span class="param-optional">Non</span></td>
<td>Nom du fichier (pour le logging)</td>
</tr>
</tbody>
</table>
</div>
<div class="response-example">
<h4>Exemple de requête</h4>
<div class="code-block">
<pre>curl -X POST https://antivir.certificator.4nkweb.com/api/scan/buffer \
-H "Content-Type: application/json" \
-d '{
"data": "base64_encoded_data",
"filename": "document.pdf"
}'</pre>
</div>
<button class="copy-button" onclick="copyCode(this)">📋 Copier</button>
</div>
<div class="response-example">
<h4>Réponse (200 OK) - Fichier propre</h4>
<div class="code-block">
<pre>{
"clean": true,
"infected": false,
"viruses": [],
"filename": "document.pdf",
"size": 12345
}</pre>
</div>
</div>
<div class="response-example">
<h4>Réponse (200 OK) - Fichier infecté</h4>
<div class="code-block">
<pre>{
"clean": false,
"infected": true,
"viruses": ["Trojan.Example"],
"filename": "document.pdf",
"size": 12345
}</pre>
</div>
</div>
<div class="response-example">
<h4>Codes de statut possibles</h4>
<ul style="margin-left: 20px;">
<li><span class="status-code status-200">200</span> Succès - Scan effectué (fichier propre ou infecté)</li>
<li><span class="status-code status-400">400</span> Requête invalide - Données manquantes ou format incorrect</li>
<li><span class="status-code status-503">503</span> Service indisponible - ClamAV non disponible</li>
<li><span class="status-code status-500">500</span> Erreur serveur - Erreur interne lors du scan</li>
</ul>
</div>
<div class="info-box">
<h4> Notes importantes</h4>
<ul style="margin-left: 20px; margin-top: 10px;">
<li>Cette API est principalement utilisée en interne par l'API filigrane</li>
<li>Le port fixe est 3023</li>
<li>Si ClamAV est indisponible, l'API retourne une erreur 503</li>
<li>Les fichiers sont scannés en mémoire (pas de fichiers temporaires sur disque)</li>
</ul>
</div>
</div>
</section>
<!-- Section Informations -->
<section class="api-docs-section">
<div class="endpoint-card">
<h2> Informations Complémentaires</h2>
<div class="info-box">
<h4>Format du Hash</h4>
<p>Le hash doit être un hash SHA256 en format hexadécimal, exactement 64 caractères.</p>
<div class="code-block">
<pre>Exemple valide: a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456
Longueur: 64 caractères
Format: hexadécimal (0-9, a-f, A-F)</pre>
</div>
</div>
<div class="info-box">
<h4>Format de la Transaction</h4>
<p>Les transactions d'ancrage incluent :</p>
<ul style="margin-left: 20px; margin-top: 10px;">
<li>Un output OP_RETURN contenant "ANCHOR:" suivi du hash</li>
<li>Un output d'ancrage de 2500 sats</li>
<li>7 outputs de provisionnement de 2500 sats chacun</li>
<li>Un output de change (si nécessaire)</li>
</ul>
</div>
<div class="info-box">
<h4>Base URLs</h4>
<p>Les APIs sont accessibles aux adresses suivantes :</p>
<div class="code-block">
<pre>API d'Ancrage : https://certificator.4nkweb.com
API Filigrane : https://watermark.certificator.4nkweb.com
API ClamAV : https://antivir.certificator.4nkweb.com</pre>
</div>
</div>
<div class="info-box">
<h4>Ports fixes</h4>
<p>Tous les ports sont fixes et ne peuvent pas être modifiés :</p>
<ul style="margin-left: 20px; margin-top: 10px;">
<li>API d'Ancrage : Port 3010</li>
<li>API Faucet : Port 3021</li>
<li>API Filigrane : Port 3022</li>
<li>API ClamAV : Port 3023</li>
<li>Dashboard : Port 3020</li>
</ul>
</div>
<div class="warning-box">
<h4>⚠️ Notes importantes</h4>
<ul style="margin-left: 20px; margin-top: 10px;">
<li>Les transactions sont envoyées au mempool immédiatement</li>
<li>Le statut "pending" signifie que la transaction est dans le mempool mais pas encore confirmée</li>
<li>Les confirmations augmentent à mesure que les blocs sont minés</li>
<li>En cas d'erreur 402 (Solde insuffisant), vous devez approvisionner le wallet de l'API</li>
</ul>
</div>
</div>
</section>
</main>
<footer>
<p>Bitcoin Ancrage Dashboard - Équipe 4NK</p>
<a href="https://git.4nkweb.com/4nk/anchorage_layer_simple.git" target="_blank" rel="noopener noreferrer" class="git-link" title="Voir le code source sur Git">
<svg class="git-icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
</svg>
</a>
</footer>
</div>
<script>
function copyCode(button) {
const codeBlock = button.previousElementSibling;
const code = codeBlock.querySelector('pre')?.textContent || codeBlock.textContent;
navigator.clipboard.writeText(code).then(() => {
const originalText = button.textContent;
button.textContent = '✅ Copié !';
setTimeout(() => {
button.textContent = originalText;
}, 2000);
}).catch(err => {
console.error('Erreur lors de la copie:', err);
alert('Erreur lors de la copie. Veuillez sélectionner et copier manuellement.');
});
}
</script>
</body>
</html>