Datoka API

Signed receipts for your API exchanges.

# Datoka API — démarrage rapide

Production : https://datoka-api.bhazarstudio.workers.dev
Prix d’émission : 0,002 USDC sur Base. Préparation et vérification gratuites.
Les reçus attestent une déclaration du client, pas une observation indépendante.

## Installation locale (Node.js 24+)

Télécharger une version du SDK et la conserver dans votre projet :

```sh
curl --fail https://datoka-api.bhazarstudio.workers.dev/sdk/datoka-api.js -o datoka-api.js
```

Conserver également son empreinte SHA-256 pour épingler cette version. Le SDK
est un module ES autonome ; aucun paquet npm « datoka-api » n’est publié.
Ne pas importer à chaque exécution une version distante susceptible de changer.

## Capturer un échange sans payer

```js
import { captureExchange } from './datoka-api.js';
const captured = await captureExchange('https://votre-api.example/data', {
  method: 'GET',
  signal: AbortSignal.timeout(30_000),
}, { apiId: 'mon-api', maxBodyBytes: 1024 * 1024 });
const data = await captured.response.text();
if (captured.event) {
  // Sauvegarder cet événement pour demander un reçu ultérieurement.
  console.log(captured.event);
} else {
  // L’appel métier a eu lieu. Ne pas le relancer pour une erreur de capture.
  console.error(captured.captureError);
}
```

La capture appelle seulement votre API. Aucun paiement ni appel Datoka n’est
fait. Les corps sont hachés localement ; aucun en-tête n’est capturé par défaut.
La réponse reste lisible. Limite par corps : 1 Mio par défaut, 16 Mio maximum.
Une requête trop volumineuse est refusée avant envoi. Une réponse trop volumineuse
reste disponible mais sans événement. Les redirections sont refusées. Les flux
continus ne conviennent pas : fournir un délai d’expiration. Les octets sont
ceux de Fetch après décodage HTTP, pas les octets réseau ou TLS.

## Acheter un reçu

Utiliser PaidApiClient avec un signataire EOA compatible viem, financé en USDC
natif sur Base. Conserver la clé privée dans votre environnement sécurisé.

```js
import { PaidApiClient } from './datoka-api.js';
const client = new PaidApiClient({
  origin: 'https://datoka-api.bhazarstudio.workers.dev',
  network: 'eip155:8453',
  recipient: '0x4a7A972F84E2A64b3B9B64AC1383Df5c413c0E59',
  maximumAtomic: 2000n,
});
// signer : signataire de votre portefeuille ; captured.event : événement ci-dessus.
const pending = await client.prepare({
  event: captured.event,
  idempotencyKey: crypto.randomUUID(),
}, signer);
// OBLIGATOIRE : sauvegarder pending durablement AVANT la ligne suivante.
// Exemple complet avec fsync et verrou : examples/purchase.ts dans les sources.
const paid = await client.resume(pending);
// Sauvegarder paid, vérifier sa signature avec une clé publique de confiance.
```

prepare signe une autorisation mais ne la soumet pas. resume peut effectuer le
paiement. Après un délai dépassé ou un paiement en attente, réutiliser le même
pending ; ne jamais recréer une autorisation automatiquement. Le budget est par
achat : l’application doit aussi imposer son plafond global.

## MCP et HTTP

Point d’accès MCP Streamable HTTP :
https://datoka-api.bhazarstudio.workers.dev/mcp

Configuration pour les clients acceptant mcpServers/url :
```json
{"mcpServers":{"datoka-api":{"url":"https://datoka-api.bhazarstudio.workers.dev/mcp"}}}
```

Un client MCP ordinaire peut préparer et vérifier. L’émission exige un client
compatible x402 et un portefeuille ; connecter le serveur ne suffit pas à payer.
Outils : prepare_api_exchange, issue_api_receipt, verify_api_receipt,
get_api_public_keys. Pour payer : params._meta["x402/payment"].
Contrats HTTP complets : /openapi.json. Exemple synthétique : /example.json.

## Vérification et confiance

Vérifier la signature avec une clé d’émetteur obtenue par un canal de confiance,
puis comparer les empreintes aux données originales avec verifyExchangePayloads.
Une simple correspondance d’empreintes ne vérifie pas la signature.
Conserver les données originales et le reçu chez vous. Ne pas transmettre de
contenus ou de secrets au service. Une empreinte n’est pas un chiffrement.

## Vérificateur dans le navigateur

Ouvrir /verify/ : sélectionner le reçu (ou le résultat payé complet), une clé
publique de confiance obtenue séparément, puis éventuellement le corps de réponse
original. Le contrôle se fait localement, sans paiement ni envoi des fichiers.
Le corps de réponse est comparé octet par octet par son empreinte ; les autres
contenus ne sont pas comparés par cette interface. Le SDK permet la vérification
complète des contenus. Un navigateur compatible Web Crypto Ed25519 est requis.