Environnement & .env
Ce guide couvre comment porter vos credentials DZBuild API en sécurité dans votre application — dev local, staging, production. Que vous construisiez une vitrine Node.js, un back-office Laravel/Symfony, un pipeline Python, un microservice Go ou une fonction edge serverless, les règles sont les mêmes.
Ce que vous devez stocker
Pour une intégration vitrine / back-office typique :
| Variable | Exemple | Notes |
|---|---|---|
DZBUILD_API_KEY | dzpk_live_aB3xT9... | Secret de la clé plateforme. Traitez-la comme un mot de passe. |
DZBUILD_API_BASE | https://api.dzbuild.app/v1 | URL de base. En prod, utilisez l'edge host, jamais dzbuild.com/api/v1 (juste un alias). |
DZBUILD_WEBHOOK_SECRET | dzwh_sec_... | Secret par webhook retourné à l'enregistrement. Pour vérifier X-DZ-Signature. |
Pour le flow clé publique (signups / events depuis un client public) :
| Variable | Exemple | Notes |
|---|---|---|
DZBUILD_PUBLIC_KEY_ID | dzpub_live_... | Safe à shipper dans le code client (l'id est public, le secret non) |
DZBUILD_SIGNING_SECRET | sig_... | Server-side seulement — sert à HMAC-signer chaque body de requête |
Fichiers .env
Le pattern le plus simple :
# .env (à la racine, gitignored)
DZBUILD_API_KEY=dzpk_live_xxxxxxxxxxxxxxxx
DZBUILD_API_BASE=https://api.dzbuild.app/v1
DZBUILD_WEBHOOK_SECRET=dzwh_sec_xxxxxxxxxxxxxxxx
# .gitignore
.env
.env.local
.env.*.local
Committez un .env.example avec des placeholders pour que les autres devs sachent quelles vars définir :
# .env.example (committé)
DZBUILD_API_KEY=dzpk_live_REPLACE_ME
DZBUILD_API_BASE=https://api.dzbuild.app/v1
DZBUILD_WEBHOOK_SECRET=dzwh_sec_REPLACE_ME
Charger .env par langage
Node.js / Next.js / Express
// next.config.js — Next.js charge .env, .env.local, .env.production automatiquement
// Pour Node simple :
import 'dotenv/config';
const key = process.env.DZBUILD_API_KEY;
Python
# pip install python-dotenv
from dotenv import load_dotenv
import os
load_dotenv()
key = os.environ['DZBUILD_API_KEY']
PHP / Laravel
// Laravel charge .env auto
$key = env('DZBUILD_API_KEY');
// PHP simple :
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv->load();
$key = $_ENV['DZBUILD_API_KEY'];
Go
// go get github.com/joho/godotenv
godotenv.Load()
key := os.Getenv("DZBUILD_API_KEY")
Flutter / mobile
Ne shippez pas la clé plateforme dans votre app mobile. À la place :
- Votre app mobile appelle votre back-end.
- Votre back-end détient la clé et proxie vers DZBuild.
Si vous avez besoin que le client mobile parle directement à DZBuild (ex. pour signups), utilisez le flow clé publique — seul l'id de la clé publique est shipped, jamais le secret plateforme. Voir Endpoints clé publique.
Environnements de production
En prod, n'utilisez pas un fichier .env. Utilisez le secret store natif de la plateforme :
Vercel / Netlify / Cloudflare Pages
Projet → Settings → Environment Variables
DZBUILD_API_KEY = dzpk_live_...
DZBUILD_API_BASE = https://api.dzbuild.app/v1
DZBUILD_WEBHOOK_SECRET = dzwh_sec_...
Marquez les vars prod-only en scope « Production ». Les vars staging en « Preview » ou env séparé.
Cloudflare Workers
wrangler secret put DZBUILD_API_KEY
# (collez la valeur quand demandé)
Disponible dans le worker comme env.DZBUILD_API_KEY (avec [vars] déclaré dans wrangler.toml).
AWS Lambda / API Gateway
Utilisez AWS Secrets Manager ou Parameter Store :
import boto3, json
secret = json.loads(
boto3.client('secretsmanager').get_secret_value(SecretId='dzbuild/prod')['SecretString']
)
key = secret['DZBUILD_API_KEY']
Ne stockez pas la clé dans Lambda env vars en clair (ils apparaissent dans CloudTrail logs). Référencez le secret manager.
Docker / Docker Compose
# docker-compose.yml
services:
app:
image: yourapp:latest
env_file:
- .env.production # NON committé
environment:
- NODE_ENV=production
Pour Kubernetes, utilisez un Secret :
apiVersion: v1
kind: Secret
metadata:
name: dzbuild-creds
type: Opaque
stringData:
DZBUILD_API_KEY: dzpk_live_...
DZBUILD_WEBHOOK_SECRET: dzwh_sec_...
Référence dans le deployment :
envFrom:
- secretRef:
name: dzbuild-creds
GitHub Actions
# .github/workflows/deploy.yml
env:
DZBUILD_API_KEY: ${{ secrets.DZBUILD_API_KEY }}
Définissez le secret dans Repo → Settings → Secrets and variables → Actions.
Clés dev vs production
Créez toujours deux clés séparées :
- Une nommée
devoustaging— utilisée dans.env.local/ dev - Une nommée
production— utilisée seulement en prod réelle
Si la clé dev fuit, vous ne brûlez que dev. Les données prod restent intactes.
# Dashboard → Developer → API Keys
+ Créer clé plateforme → nom "myapp-dev", scopes: products:read, orders:read, orders:write
+ Créer clé plateforme → nom "myapp-prod", scopes: products:read, orders:read, orders:write
Mêmes scopes, juste des noms différents.
Secrets de webhooks
Quand vous enregistrez un webhook, la réponse inclut un secret :
curl -X POST 'https://api.dzbuild.app/v1/webhooks' \
-H "Authorization: Bearer $DZBUILD_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"url": "https://yourapp.com/webhook",
"events": ["order.created", "order.confirmed"]
}'
Réponse :
{
"data": {
"id": 42,
"url": "https://yourapp.com/webhook",
"secret": "dzwh_sec_aB3xT9...", ← stockez dans DZBUILD_WEBHOOK_SECRET
"events": ["order.created", "order.confirmed"]
}
}
Ce secret est affiché une fois — sauvez-le immédiatement dans votre coffre. Si vous le perdez, supprimez le webhook et enregistrez-en un autre.
Utilisez le secret pour vérifier chaque livraison webhook :
// Handler webhook Express
app.post('/webhook', (req, res) => {
const sig = req.headers['x-dz-signature'];
const ts = req.headers['x-dz-timestamp'];
const body = req.rawBody; // ⚠️ raw, pas parsé
const expected = crypto
.createHmac('sha256', process.env.DZBUILD_WEBHOOK_SECRET)
.update(`${ts}.${body}`)
.digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) {
return res.status(401).send('bad signature');
}
// ... traiter l'event
});
Voir Vérifier les signatures pour le code complet en 5 langages.
Flow clé publique (navigateur / mobile)
Si vous devez appeler DZBuild directement depuis le navigateur ou l'app mobile pour des endpoints à scope étroit (signup tracking, event tracking), utilisez le flow clé publique. Seul l'id de la clé publique est livré au client — le secret de signature reste sur votre back-end et signe chaque body.
// Code navigateur — sûr
const PUBLIC_KEY_ID = "dzpub_live_xxxx"; // ok à committer dans le client
// Obtenez une signature de votre serveur (qui détient DZBUILD_SIGNING_SECRET)
async function trackSignup(email, externalId) {
const nonce = crypto.randomUUID();
const body = JSON.stringify({ email, external_user_id: externalId, source: 'web', nonce });
const ts = Math.floor(Date.now() / 1000);
// Votre back-end signe (NE FAITES JAMAIS ça dans le navigateur)
const { signature } = await fetch('/sign-dz-event', {
method: 'POST',
body: JSON.stringify({ body_hash_input: body, ts, nonce })
}).then(r => r.json());
await fetch('https://api.dzbuild.app/v1/signups', {
method: 'POST',
headers: {
'Authorization': `DZ-Public ${PUBLIC_KEY_ID}`,
'X-DZ-Timestamp': ts.toString(),
'X-DZ-Nonce': nonce,
'X-DZ-Signature': signature,
'Content-Type': 'application/json'
},
body
});
}
Le secret de signature ne quitte jamais votre back-end. L'id de clé publique peut être inspecté par n'importe qui — c'est voulu.
Tunneling local pour les webhooks
Les webhooks DZBuild ont besoin d'une URL HTTPS publique. Pour tester localement :
# ngrok
ngrok http 3000
# Cloudflare Tunnel
cloudflared tunnel --url http://localhost:3000
# tailscale serve
tailscale serve https / http://localhost:3000
Enregistrez l'URL du tunnel comme cible webhook. Mettez à jour à chaque restart (ngrok free change d'URL ; payez 8$/mois pour un sous-domaine stable).
Politique de rotation
Faites tourner les clés :
- Trimestriellement pour les clés prod (mettez un rappel calendrier)
- Immédiatement si une clé peut avoir fuité (committée à git, screenshot, envoyée en chat)
- Au départ d'un membre d'équipe s'il avait accès au coffre
Procédure :
- Créez une nouvelle clé dans le dashboard avec mêmes scopes.
- Mettez à jour votre coffre / env vars vers la nouvelle clé.
- Déployez. Vérifiez le trafic via
GET /v1/usage. - Après 24 h de trafic propre sur la nouvelle, révoquez l'ancienne :
DELETE /v1/keys/{old_key_id}ou via dashboard.
Erreurs courantes
| Erreur | Conséquence | Fix |
|---|---|---|
.env committé à git | La clé est dans l'historique git pour toujours ; rotation immédiate | git filter-repo ne corrige pas les forks/clones ; considérez compromis |
| Clé plateforme dans le code navigateur | Les clients voient et volent la clé dans network tab | Move au back-end / serverless ; rotation |
dzpk_live_... hardcodé en source | Pareil | env vars ; rotation |
| Même clé pour dev et prod | Une boulette dev touche la prod | Deux clés ; ne jamais partager |
| Secret webhook perdu | Plus moyen de vérifier les livraisons | Supprimez le webhook, enregistrez-en un autre |
| Logguer la clé API dans les logs app | Auditeurs / log shippers / quiconque a accès aux logs voit | Redactez les secrets dans le logger ; rotation |
Checklist avant prod
-
.envest dans.gitignore(et n'a jamais été committé par accident) - Clé prod nommée
prodet utilisée seulement en prod - Clé dev nommée
devet seulement en dev/staging - Secrets webhooks dans secret manager, pas dans le code
- En-tête
Authorizationsur chaque appel API depuis le back-end - Le code navigateur ne voit jamais
dzpk_live_*(seulementdzpub_live_*si flow clé publique) - Vérification de signature activée sur l'endpoint webhook
- Rappel rotation de clés sur votre calendrier
- Logging qui ne capture PAS les bodies complets (peuvent contenir des clés API en client headers)