Accueil
ppush.

Documentation API

Créez des pushes par script — provisioning, onboarding, CI — tout en conservant le chiffrement de bout en bout.

Authentification

Générez un token personnel dans Compte → Tokens API (affiché une seule fois), puis passez-le en en-tête :

Authorization: Bearer ppush_xxxxxxxxxxxxxxxxxxxx

L'API n'accepte que des contenus déjà chiffrés. Le serveur ne chiffre jamais lui-même — c'est ce qui garantit le zéro-knowledge. Utilisez le CLI fourni (recommandé) ou implémentez le format ci-dessous.

Le CLI (recommandé)

tools/ppush-cli.mjs (dans le dépôt) chiffre localement puis appelle l'API. Node ≥ 20, aucune dépendance.

export PPUSH_URL=https://ppush.online
export PPUSH_TOKEN=ppush_xxx

# mot de passe, 3 vues max, 7 jours
ppush-cli.mjs --password "S3cret!" --views 3 --days 7

# texte depuis stdin
cat config.yml | ppush-cli.mjs --text -

# fichier avec passphrase et note privée
ppush-cli.mjs --file dump.sql.gz --passphrase "sesame" --note "backup pour Bob"

# → imprime l'URL complète, clé de déchiffrement incluse dans le fragment

Options : --days N · --views N · --passphrase X · --note "…" · --no-retrieval-step · --no-deletable

Endpoints

POST/api/pushesBearer ou session

Crée un push. Corps JSON :

{
  "kind": "PASSWORD" | "TEXT" | "FILE" | "URL",
  "ciphertext": "<base64>",          // payload chiffré (cf. format)
  "blobPath": "xxx.bin",             // FILE uniquement (cf. POST /api/blobs)
  "passphrase": "optionnelle",
  "expireAfterMinutes": 10080,       // 5..43200 (min 5 ; "expireAfterDays" en jours encore accepté)
  "expireAfterViews": 5,             // 1..50
  "retrievalStep": true,
  "deletableByViewer": true,
  "note": "référence privée optionnelle"
}

Réponse 201 : { "slug", "url", "expiresAt", … }. Le lien à transmettre est url + "#" + clé_base64url— la clé n'est connue que de vous.

POST/api/blobsBearer ou session

Upload du blob chiffré d'un fichier (corps brut, max ~90 Mo avec un compte). Réponse : { "blobPath": "xxx.bin", "size": 123 } à passer ensuite à POST /api/pushes.

GET/api/pushes?page=1&filter=activeBearer ou session

Liste paginée de vos pushes. filter : active | expired | (omis = tous).

GET/api/pushes/:slugBearer ou session

Détail d'un push + journal d'audit complet (events : CREATED, VIEW, FAILED_PASSPHRASE, EXPIRED, OWNER_DELETE, VIEWER_DELETE, avec IP et user-agent).

DELETE/api/pushes/:slugBearer ou session

Fait expirer le push immédiatement (purge définitive du payload).

GET/api/p/:slugpublic

Métadonnées publiques d'un push (type, expiré ou non, passphrase requise…). Ne consomme pas de vue.

POST/api/p/:slug/revealpublic

Révèle le ciphertext et consomme une vue. Corps : { "passphrase": "…" } si exigée. Pour un FILE, retourne aussi un viewToken à usage unique, à passer en en-tête X-View-Token sur GET /api/p/:slug/blob (jamais dans l’URL). Si le transfert est interrompu, rappeler reveal ré-émet un token sans consommer de vue supplémentaire, tant que le fichier n’a pas été livré en entier.

POST/api/p/:slug/burnpublic

Destruction par le destinataire (si autorisée à la création).

GET/api/storagepublic

Fair-use transparent du stockage fichiers : { "availableBytes", "upcoming": [{ "bytes", "at" }] } — upcomingliste les libérations d'espace à venir (cumulées, par date d'expiration au plus tard). Authentifié, ajoute "user": { "usedBytes", "availableBytes", "quotaBytes" } (quota personnel de fichiers actifs). Un upload refusé faute d'espace renvoie 507avec l'estimation de la prochaine fenêtre.

Format de chiffrement (v1)

Si vous n'utilisez pas le CLI, produisez le ciphertext ainsi (AES-256-GCM, WebCrypto ou équivalent) :

Clé      : 32 octets aléatoires → base64url → fragment du lien (#…)
Payload  : JSON { "t": "PASSWORD|TEXT|URL", "d": "<secret>" }
           (FILE : { "t":"FILE", "d":"", "name", "mime", "size" })

ciphertext = 0x01 ‖ IV(12 octets) ‖ AES-256-GCM(payload, AAD="ppush:v1:meta")
           → base64 dans le champ "ciphertext"

Fichiers (blob) : chunks de 8 Mio, chacun encadré :
  [longueur u32 BE] [IV 12 octets] [ct+tag]
  AAD du chunk i : "ppush:v1:<i>:<1 si dernier, sinon 0>"

Limites & erreurs

  • Réponses d'erreur : { "error": "message" } avec le statut HTTP approprié (400 validation, 401 auth, 403 interdit, 404 introuvable, 409 conflit, 410 expiré, 413 trop volumineux, 429 rate limit).
  • Rate limiting par IP sur les endpoints sensibles (login, passphrase, reveal). En cas de 429, attendez puis réessayez.
  • Payload texte chiffré : 1024 Ko max · fichiers : 90 Mo max (compte) · rétention : 30 jours / 50 vues max. Sans compte : 7 jours / 5 vues, fichiers 10 Mo.
  • Stockage fichiers fair-use : espace global partagé (voir GET /api/storage) + quota personnel de 3 Go de fichiers actifs par compte. Saturation → 507avec l'estimation des prochaines libérations d'espace.
  • Un token API a les droits de son propriétaire (création, listing, expiration de ses pushes). Révocable à tout moment depuis le compte.

Voir aussi la page À propos et la gestion des tokens.