Documentation API NINA

Introduction

L'API NINA permet d'accéder aux données NINA de manière sécurisée et performante. Cette API REST utilise JSON pour les réponses et requiert une authentification HMAC-SHA256 pour chaque requête.

URL de base
https://nina.gouv.ml/api/v1
Format des réponses

Toutes les réponses sont au format JSON avec la structure suivante:

{
    "success": true,
    "data": { ... }
}

Authentification

L'API utilise une authentification basée sur HMAC-SHA256. Chaque requête doit inclure les headers suivants:

Header Description Exemple
X-API-Key Votre clé API pk_xxxxxxxxxxxx
X-Timestamp Timestamp Unix actuel 1635789012
X-Nonce Valeur unique (32 caractères hex) a1b2c3d4...
X-Signature Signature HMAC-SHA256 f7bc83f4...
Génération de la signature

La signature est générée en suivant ces étapes:

  1. Concaténer: api_key + timestamp + nonce + request_body
  2. Calculer le HMAC-SHA256 avec votre API Secret
  3. Convertir en hexadécimal
$payload = $apiKey . $timestamp . $nonce . $requestBody;
$signature = hash_hmac('sha256', $payload, $apiSecret);

Endpoints

POST /nina/search

Recherche un numéro NINA unique.

Paramètres de requête
Paramètre Type Requis Description
nina string Oui Numéro NINA (15 caractères alphanumériques)
Exemple de requête
{
    "nina": "12345678901234A"
}
Réponse succès (200)
{
    "success": true,
    "data": {
        "NINA": "12345678901234A",
        "PRENOM": "Famoro",
        "NOM": "Karakoro",
        "DATE_NAISSANCE": "15/01/1990",
        "LIEU_NAISSANCE": "Bamako",
        "SEXE": "M",
        "PROFESSION": "Ingénieur",
        "PERE": "N'Tji Karakoro",
        "MERE": "Tifon Korokara"
    }
}
Réponse non trouvé (404)
{
    "success": false,
    "message": "NINA non trouvé"
}

Exemples de code

PHP

<?php
$apiKey = 'pk_xxxxxxxxxxxx';
$apiSecret = 'sk_xxxxxxxxxxxx';
$nina = '12345678901234A';

$timestamp = time();
$nonce = bin2hex(random_bytes(16));
$body = json_encode(['nina' => $nina]);

$payload = $apiKey . $timestamp . $nonce . $body;
$signature = hash_hmac('sha256', $payload, $apiSecret);

$ch = curl_init('https://nina.gouv.ml/api/v1/nina/search');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    'X-API-Key: ' . $apiKey,
    'X-Timestamp: ' . $timestamp,
    'X-Nonce: ' . $nonce,
    'X-Signature: ' . $signature
]);

$response = curl_exec($ch);
curl_close($ch);

$result = json_decode($response, true);

Python

import requests
import hashlib
import hmac
import time
import secrets
import json

api_key = 'pk_xxxxxxxxxxxx'
api_secret = 'sk_xxxxxxxxxxxx'
nina = '12345678901234A'

timestamp = str(int(time.time()))
nonce = secrets.token_hex(16)
body = json.dumps({'nina': nina})

payload = api_key + timestamp + nonce + body
signature = hmac.new(
    api_secret.encode(),
    payload.encode(),
    hashlib.sha256
).hexdigest()

headers = {
    'Content-Type': 'application/json',
    'X-API-Key': api_key,
    'X-Timestamp': timestamp,
    'X-Nonce': nonce,
    'X-Signature': signature
}

response = requests.post(
    'https://nina.gouv.ml/api/v1/nina/search',
    headers=headers,
    data=body
)

result = response.json()

JavaScript (Node.js)

const crypto = require('crypto');
const axios = require('axios');

const apiKey = 'pk_xxxxxxxxxxxx';
const apiSecret = 'sk_xxxxxxxxxxxx';
const nina = '12345678901234A';

const timestamp = Math.floor(Date.now() / 1000);
const nonce = crypto.randomBytes(16).toString('hex');
const body = JSON.stringify({ nina });

const payload = apiKey + timestamp + nonce + body;
const signature = crypto
    .createHmac('sha256', apiSecret)
    .update(payload)
    .digest('hex');

axios.post('https://nina.gouv.ml/api/v1/nina/search', 
    { nina },
    {
        headers: {
            'Content-Type': 'application/json',
            'X-API-Key': apiKey,
            'X-Timestamp': timestamp,
            'X-Nonce': nonce,
            'X-Signature': signature
        }
    }
).then(response => {
    console.log(response.data);
}).catch(error => {
    console.error(error.response.data);
});

Codes d'erreur

Code Message Description
400 Bad Request Requête invalide (paramètres manquants ou mal formatés)
401 Unauthorized Authentification échouée (clé invalide ou signature incorrecte)
403 Forbidden Accès refusé (IP non autorisée ou clé désactivée)
404 Not Found Ressource non trouvée
429 Too Many Requests Limite de requêtes dépassée
500 Internal Server Error Erreur serveur interne

Limites et quotas

Rate Limiting

Les limites de requêtes sont configurées par compte:

  • 60 requêtes/minute
Headers de réponse

Chaque réponse inclut des headers indiquant votre utilisation:

  • X-RateLimit-Limit: Limite totale
  • X-RateLimit-Remaining: Requêtes restantes
  • Retry-After: Secondes avant réinitialisation (si limite atteinte)