Authentification et signature
Chaque appel s'identifie avec votre clé API. Chaque écriture est en plus signée avec votre secret : une clé volée seule ne permet pas de souscrire.
Vos accès
| Valeur | Format | Rôle |
|---|---|---|
| Clé API de test | cvr_test_ | Sandbox : données et paiements fictifs, documents de test. |
| Clé API de production | cvr_live_ | Vrais contrats, vrais paiements. Remise après validation. |
| Secret de signature | cvr_sig_ | Un par clé. Sert à signer vos écritures. |
COVERAF ne conserve ni vos clés ni vos secrets en clair : ils ne vous sont montrés qu'une fois. En cas de perte ou de doute, demandez une nouvelle clé : l'ancienne reste active le temps de basculer, puis est révoquée.
Votre application mobile appelle VOTRE serveur, qui appelle l'API COVERAF. Une clé placée dans une application peut être extraite par n'importe qui. L'API refuse d'ailleurs les appels venant d'un navigateur.
Identification : toutes les requêtes
Authorization: Bearer cvr_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxL'environnement est déduit de la clé : une clé de test n'atteint jamais les données réelles. Chaque réponse rappelle l'environnement dans l'en-tête X-Coveraf-Environnement (test ou live).
Signature : toutes les écritures (POST)
Ajoutez deux en-têtes :
| En-tête | Valeur |
|---|---|
X-Coveraf-Timestamp | Heure actuelle en secondes (horodatage Unix). Une requête de plus de 5 minutes est refusée. |
X-Coveraf-Signature | v1= suivi du HMAC-SHA256 hexadécimal de la chaîne ci-dessous, avec votre secret. |
<timestamp>.<MÉTHODE>.<chemin>.<corps>
exemple :
1793790000.POST./v1/devis.{"offre":"securvie_500k","donnees":{"assure":{"date_naissance":"1985-06-15"}}}- chemin : le chemin appelé avec sa requête éventuelle (
/v1/devis,/v1/contrats?limite=10), sans le nom de domaine ; - corps : exactement les octets envoyés (même ordre des champs, mêmes espaces, UTF-8). Sérialisez le JSON une seule fois, signez cette chaîne, envoyez cette même chaîne.
Clients prêts à l'emploi
Plutôt que d'écrire la signature vous-même, partez de nos clients, une seule fonction à appeler :
// Client minimal de l'API COVERAF pour Node.js 18+ (aucune dépendance).
// À utiliser UNIQUEMENT côté serveur : la clé et le secret ne doivent jamais
// se trouver dans une application mobile ou une page web.
import crypto from 'node:crypto'
const BASE_URL = process.env.COVERAF_BASE_URL || 'https://api.coveraf.com'
const CLE_API = process.env.COVERAF_CLE_API // cvr_test_... ou cvr_live_...
const SECRET = process.env.COVERAF_SECRET // cvr_sig_...
export async function appelCoveraf(methode, chemin, donnees, { idempotencyKey } = {}) {
const corps = donnees === undefined ? '' : JSON.stringify(donnees)
const entetes = { Authorization: `Bearer ${CLE_API}`, 'Content-Type': 'application/json' }
if (methode !== 'GET') {
// Signature : HMAC-SHA256 de "<timestamp>.<MÉTHODE>.<chemin>.<corps>"
const timestamp = Math.floor(Date.now() / 1000).toString()
const signature = crypto.createHmac('sha256', SECRET)
.update(`${timestamp}.${methode}.${chemin}.${corps}`)
.digest('hex')
entetes['X-Coveraf-Timestamp'] = timestamp
entetes['X-Coveraf-Signature'] = `v1=${signature}`
if (idempotencyKey) entetes['Idempotency-Key'] = idempotencyKey
}
const reponse = await fetch(BASE_URL + chemin, { method: methode, headers: entetes, body: corps || undefined })
const resultat = await reponse.json()
if (!reponse.ok) {
// resultat.erreur.code est stable : votre code peut s'appuyer dessus.
throw Object.assign(new Error(resultat.erreur.message), { code: resultat.erreur.code, details: resultat.erreur.details, requeteId: resultat.requete_id })
}
return resultat
}
// Exemple :
// const devis = await appelCoveraf('POST', '/v1/devis', { offre: 'securvie_500k', donnees: { assure: { date_naissance: '1985-06-15' } } })
// const sous = await appelCoveraf('POST', '/v1/souscriptions', { devis_id: devis.id, souscripteur: { ... } }, { idempotencyKey: crypto.randomUUID() })Ces quatre clients sont testés contre l'API, accents compris. Téléchargez-les : coveraf.js, coveraf.py, coveraf.php, coveraf.sh.
Pour vérifier votre signature sans rien créer : POST /v1/ping avec n'importe quel corps JSON renvoie signature_verifiee: true.
Et ensuite
- Les appels qui engagent (souscription, paiement) exigent aussi un en-tête
Idempotency-Key: voir Idempotence. - Débit, taille des requêtes, restriction par adresse IP : voir Limites et restrictions.