Datoka API

Signed receipts for your API exchanges.

# Obtenir et vérifier son premier reçu

Node.js 24+. Exemple autonome : aucune installation npm, aucun compte Datoka.
Un dossier représente un seul achat, plafonné à 0,002 USDC sur Base.
Les commandes preview, init et prepare ne soumettent aucun paiement.
Seule resume avec --approve-payment peut payer. verify fonctionne hors ligne.

## 1. Télécharger et contrôler l'exemple

```sh
curl --fail https://datoka-api.bhazarstudio.workers.dev/examples/0.3.8/first-receipt.mjs -o first-receipt.mjs
curl --fail https://datoka-api.bhazarstudio.workers.dev/examples/0.3.8/manifest.json -o example-manifest.json
node --input-type=module -e "import fs from 'node:fs'; import crypto from 'node:crypto'; const m=JSON.parse(fs.readFileSync('example-manifest.json')); if(crypto.createHash('sha256').update(fs.readFileSync('first-receipt.mjs')).digest('hex')!==m.sha256)process.exit(1); console.log('SHA-256 OK');"
node first-receipt.mjs preview
```

Sous Windows PowerShell, utiliser curl.exe. Conserver le manifeste accepté.
Une empreinte provenant du même site assure la correspondance de fichiers,
pas une preuve d'origine indépendante du site. Lire l'exemple avant de lui
confier un signataire ; sa source est incluse dans l'archive Datoka API.

## 2. Fixer les clés publiques de confiance

Télécharger les clés de l'émetteur :

```sh
curl --fail -X POST https://datoka-api.bhazarstudio.workers.dev/v1/operations/get_api_public_keys -H "Content-Type: application/json" --data "{}" -o trusted-keys.json
```

Confirmer l'émetteur et la clé auprès d'une source de confiance, puis conserver
ce fichier. Le téléchargement seul établit une confiance dans ce site HTTPS ;
il n'apporte pas de confirmation indépendante de l'identité de l'émetteur.
L'exemple copie ces clés une fois et ne les remplace pas lors d'une reprise.
N'utiliser que des clés publiques : aucune clé privée d'émetteur n'est requise.

## 3. Initialiser un dossier privé

```sh
node first-receipt.mjs init ./achat-prive trusted-keys.json
```

Par défaut, l'exemple effectue un véritable appel HTTP vers un petit serveur
local temporaire, avec une réponse synthétique clairement identifiée. Il
conserve la déclaration et les octets pour vérifier ensuite le reçu et le contenu.
Ce test ne représente pas l'appel à un fournisseur extérieur.

Pour un échange réel déjà capturé avec captureExchange, sauvegarder uniquement
captured.event dans event.json puis utiliser :

```sh
node first-receipt.mjs init ./autre-achat-prive trusted-keys.json event.json
```

Le dossier conserve input.json et trust.json. Gardez-le hors du dépôt et des
dossiers partagés. Pour l'exemple synthétique, payloads.json contient les
octets originaux en base64 et l'URL locale ; ce fichier reste chez vous.
Avec event.json importé, la commande verify contrôle la signature et indique
payloadsVerified: null ; comparez séparément vos originaux avec le SDK.

## 4. Préparer puis envoyer une seule autorisation

Fournir DATOKA_BUYER_PRIVATE_KEY par votre gestionnaire de secrets, sans
l'inscrire dans le script, le terminal partagé ou le dépôt. Utiliser un
portefeuille EOA dédié financé en USDC natif sur Base. Cet exemple en ligne
de commande nécessite un signataire logiciel ; pour un portefeuille matériel,
intégrer son signataire avec PaidApiClient plutôt que d'exporter sa clé privée.

```sh
node first-receipt.mjs prepare ./achat-prive
node first-receipt.mjs resume ./achat-prive --approve-payment
node first-receipt.mjs verify ./achat-prive
```

prepare vérifie l'origine, le réseau, le bénéficiaire et le plafond de l'offre,
signe hors chaîne puis sauvegarde pending.json avec écriture exclusive et
synchronisation sur disque. L'autorisation expire rapidement : lancer resume
juste après. La clé privée de l'acheteur n'est pas enregistrée dans le dossier.
pending.json contient une autorisation sensible : gardez-le privé et intact.

resume utilise uniquement l'autorisation sauvegardée. Il sauvegarde receipt.json
avant de vérifier signature, émetteur, portefeuille, événement et contexte.
Si receipt.json existe déjà, il le vérifie localement sans envoyer de paiement.
Il ne crée jamais une nouvelle autorisation. Le plafond s'applique à ce dossier ;
votre application doit imposer son propre budget global si elle crée plusieurs achats.

## Reprendre après une interruption

Relancer uniquement resume avec le même dossier. Ne pas relancer prepare,
modifier pending.json, supprimer le dossier ou changer d'identifiant pour
contourner une erreur. Une réponse perdue peut cacher un règlement réussi.
Un refus 402 après envoi ne justifie pas de recréer une autorisation.

Un fichier partiel ou un verrou purchase.lock bloque volontairement la reprise.
Vérifier que le processus précédent est arrêté avant de retirer manuellement
un verrou résiduel. Restaurer les fichiers depuis leur sauvegarde si nécessaire ;
ne pas tenter un nouvel achat tant que le règlement précédent est incertain.
Les fichiers sont synchronisés ; le dossier est aussi synchronisé sur POSIX.
Sous Windows, protégez le dossier par les permissions du compte utilisateur ;
les modes POSIX ne remplacent pas les ACL et la résistance aux coupures dépend
du système de fichiers. Conservez une sauvegarde du dossier privé.

verify ne contacte aucun service. La signature du reçu est contrôlée, puis
les corps originaux s'ils ont été conservés par l'exemple. Les métadonnées de
règlement sont comparées au contexte sauvegardé ; la transaction blockchain
n'est pas interrogée à nouveau (chainTransactionRechecked: false).

La vérification d'une déclaration ne prouve ni l'observation indépendante de
l'échange ni la vérité de son contenu. Voir /use-cases pour la portée exacte.

## English command map

preview: free pricing. init DIRECTORY TRUST_FILE [EVENT_FILE]: save trusted
public keys and one declared exchange. prepare DIRECTORY: sign and persist,
without submitting payment. resume DIRECTORY --approve-payment: submit or
recover the saved purchase. verify DIRECTORY: offline signature and optional
original-byte verification. Never replace an uncertain saved authorization.