Aller au contenu

Démarrage rapide

Cinq étapes, environ dix minutes. À la fin, vous avez fait votre premier appel facturé contre la production.

  1. Ce que ExaTrust vous a envoyé

    Vous avez reçu de votre référent commercial :

    • Un identifiant de clé key_id au format pk_<slug>_<6hex> — exemple : pk_orange_8a3b.
    • L’URL de base à utiliser : https://partner.exatrust.cg/v1.
    • Optionnellement, pour les partenaires mTLS : ca.crt (notre autorité de certification), <slug>.crt (votre certificat client) et <slug>.key (la clé privée associée).

    La clé privée Ed25519 utilisée pour signer les requêtes, c’est vous qui la générez à l’étape suivante. ExaTrust n’a jamais accès à votre clé privée — seulement à votre clé publique.

  2. Générer votre keypair Ed25519

    Une commande openssl suffit. Stockez ces deux fichiers à un emplacement sécurisé (gestionnaire de secrets, vault, dossier chmod 600).

    Fenêtre de terminal
    openssl genpkey -algorithm ed25519 -out partner.priv.pem
    openssl pkey -in partner.priv.pem -pubout -out partner.pub.pem

    Transmettez uniquement partner.pub.pem à votre référent ExaTrust (gestionnaire de secrets, message chiffré, jamais par email en clair). Sous 24 h votre key_id est actif côté serveur.

  3. Signer une requête (RFC 9421)

    Chaque appel doit porter deux en-têtes : Signature-Input (la liste des champs signés et les métadonnées) et Signature (la signature Ed25519 en base64). Champs signés recommandés : @method, @path, @query. Métadonnées requises : created, keyid, alg=ed25519, nonce.

    main.go
    package main
    import (
    "crypto/ed25519"
    "fmt"
    "io"
    "net/http"
    "github.com/remitly-oss/httpsig-go"
    "github.com/remitly-oss/httpsig-go/keyutil"
    "github.com/remitly-oss/httpsig-go/sigtypes"
    )
    func main() {
    priv, err := keyutil.ReadPrivateKeyFile("partner.priv.pem")
    if err != nil {
    panic(err)
    }
    req, _ := http.NewRequest("GET",
    "https://partner.exatrust.cg/v1/me", nil)
    if err := httpsig.Sign(req,
    httpsig.SigningProfile{
    Algorithm: sigtypes.Algo_ED25519,
    Fields: httpsig.Fields("@method", "@path", "@query"),
    Metadata: []httpsig.Metadata{
    httpsig.MetaCreated,
    httpsig.MetaKeyID,
    httpsig.MetaAlgorithm,
    httpsig.MetaNonce,
    },
    Nonce: httpsig.NonceRandom32,
    Label: "sig1",
    },
    httpsig.SigningKey{
    Key: priv.(ed25519.PrivateKey),
    MetaKeyID: "pk_orange_8a3b",
    },
    ); err != nil {
    panic(err)
    }
    resp, err := http.DefaultClient.Do(req)
    if err != nil {
    panic(err)
    }
    defer resp.Body.Close()
    body, _ := io.ReadAll(resp.Body)
    fmt.Printf("%d %s\n%s\n", resp.StatusCode, resp.Status, body)
    }

    Détails complets de la signature (base de signature, format des en-têtes, gestion mTLS) sur la page Authentification.

  4. Premier appel : GET /v1/me

    Cet endpoint ne consomme aucun crédit. Il sert à valider que votre signature est correcte et à voir votre solde.

    Réponse attendue (200) :

    {
    "user_id": 42,
    "email": "tech@orange.cg",
    "key_id": "pk_orange_8a3b",
    "credits": {
    "mode": "prepaid",
    "balance": 5000,
    "total_consumed": 0
    }
    }

    Si vous voyez un 200 et votre solde, l’intégration cryptographique est fonctionnelle. Si vous obtenez 401 INVALID_SIGNATURE, vérifiez que votre clé publique a bien été remontée côté serveur, que votre horloge est synchronisée (NTP, fenêtre ±5 min), et que le label de la signature est bien sig1.

  5. Premier appel facturé : GET /v1/resultats/candidats/EANB260094

    Reprenez votre code et changez simplement l’URL. Cet appel consomme 1 crédit sur votre solde — y compris si le matricule n’existe pas (la requête est exécutée).

    Fenêtre de terminal
    GET https://partner.exatrust.cg/v1/resultats/candidats/EANB260094

    Réponse attendue (200) :

    {
    "matricule": "EANB260094",
    "session_id": 26,
    "session_name": "2025",
    "examen_id": 3,
    "examen_name": "BEPC",
    "candidat": {
    "nom": "LOUMOUAMOU",
    "prenom": "Mignon Marcel Petith",
    "date_naissance": "2009-09-30",
    "sexe": "M",
    "mention": "AB",
    "serie": null
    },
    "etablissement": {
    "code": "ETS001",
    "name": "École Charles Mynyngou",
    "region": "Brazzaville"
    },
    "meta": {
    "request_id": "01HXY...",
    "credit_mode": "prepaid",
    "credits_remaining": 4285
    }
    }

    Notez le meta.credits_remaining : votre solde décrémenté en temps réel. Notez aussi le meta.request_id : c’est l’identifiant à fournir au support ExaTrust en cas de dispute ou d’incident.

Et après