**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
1063 lines
44 KiB
HTML
1063 lines
44 KiB
HTML
<!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>
|