Démarrage rapide
En 10 minutes : lecture, écriture et réception d'un webhook.
Prérequis :
MCM.ApiProxyinstallé (Installation) + clé API configurée (Configuration).
1. Lire — premier appel
using MCM.ApiProxy.Contracts;
using MCM.B2B.Contracts;
public class EmployeService(IEmployesClient employesClient, ILogger<EmployeService> logger)
{
public async Task<List<B2BEmployeItem>> GetAllEmployesAsync()
{
var result = await employesClient.GetAllEmployes();
if (result.IsError)
{
logger.LogError("Erreur récupération employés: {Error}", result.FirstError.Description);
return [];
}
return result.Value.ToList();
}
public async Task<B2BEmployeItem?> GetEmployeAsync(string idExterne)
{
var result = await employesClient.GetEmployeById(idExterne);
return result.IsError ? null : result.Value;
}
}
using MCM.ApiProxy;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddMcmApiClient(builder.Configuration); // tous les clients en une seule fois
builder.Services.AddScoped<EmployeService>();
var app = builder.Build();
[ApiController]
[Route("api/[controller]")]
public class EmployesController(EmployeService service) : ControllerBase
{
[HttpGet]
public async Task<IActionResult> GetAll() => Ok(await service.GetAllEmployesAsync());
[HttpGet("{idExterne}")]
public async Task<IActionResult> GetById(string idExterne)
{
var e = await service.GetEmployeAsync(idExterne);
return e is null ? NotFound() : Ok(e);
}
}
2. Comprendre ErrorOr<T>
Toutes les méthodes du SDK retournent ErrorOr<T>. Aucune ne lance d'exception sur erreur métier ou HTTP.
var result = await employesClient.GetEmployeById("EMP-123");
if (result.IsError)
{
var e = result.FirstError;
// e.Code → "Employe.NotFound"
// e.Description → "Aucun employé n'existe avec cet identifiant."
// e.Type → ErrorType.NotFound
// e.Metadata → { "Url": "…", "StatusName": "NotFound", … } selon l'erreur
return;
}
var employe = result.Value;
| Aspect | ErrorOr | Exceptions |
|---|---|---|
| Performance | Pas de stack unwinding | Coûteux à lancer |
| Lisibilité | Flux explicite | Flux caché |
| Compilation | result.Value non accessible sans vérifier IsError (avec Match/pattern matching) | Risque d'oublier le try |
Référence complète des codes : catalogue d'erreurs. Patterns de gestion : Gestion des erreurs.
3. Écrire — créer un employé
public async Task<bool> CreateEmployeAsync(B2BUpdateEmployeDto dto)
{
var result = await employesClient.AddEmploye(dto);
if (result.IsError)
{
logger.LogError("Échec création {Id}: [{Code}] {Desc}",
dto.IdExterne, result.FirstError.Code, result.FirstError.Description);
return false;
}
logger.LogInformation("Employé créé: {IdExterne}", dto.IdExterne);
return true;
}
// Appel
await CreateEmployeAsync(new B2BUpdateEmployeDto
{
IdExterne = "PERSON-123",
Prenom = "Alice",
Nom = "Tremblay",
Courriel = "alice@example.com",
NoMembre = "NM-2026-001",
IdentifiantExterneEmployeur = "EMP001",
Matricule = "A123"
});
Pour un import groupé, ne bouclez pas sur
AddEmploye. UtilisezISyncClient.Sync— un seul appel pour des milliers d'employés. Voir Synchronisation des employés.
4. Recevoir un webhook
Quand un événement métier intéressant se produit côté MCM (adhésion signée, liste électorale créée, …), MCM peut envoyer les données à votre application au lieu de vous obliger à les interroger périodiquement.
4.1 Configurer le récepteur
{
"McmApi": {
"BaseUrl": "https://mcm-dev.neosapiens.com/",
"ApiKey": "<votre-cle>",
"WebhookSecret": "<base64-fourni-par-mcm>"
}
}
using MCM.ApiProxy.Webhooks;
using MCM.B2B.Contracts.V2;
using MCM.B2B.Contracts.Webhooks;
builder.Services.AddMcmWebhookReceiver(builder.Configuration)
.AddHandler<AdhesionSigneeHandler, B2BAdhesionItemV2>(WebhookEventTypes.AdhesionSignee);
var app = builder.Build();
app.MapMcmWebhooks("/webhooks/mcm");
4.2 Écrire le handler
using MCM.B2B.Contracts.V2;
using MCM.B2B.Contracts.Webhooks;
public class AdhesionSigneeHandler(ILogger<AdhesionSigneeHandler> logger)
: IMcmWebhookHandler<B2BAdhesionItemV2>
{
public Task HandleAsync(B2BWebhookPayload<B2BAdhesionItemV2> p, CancellationToken ct)
{
logger.LogInformation(
"Adhésion {Id} signée pour {Employe} (syndicat {Syndicat})",
p.Data.IdUniqueAdhesion, p.Data.EmployeIdExterne, p.Data.SyndicatIdExterne);
return Task.CompletedTask;
}
}
C'est tout. Le middleware fourni par le SDK :
- valide la signature
HMAC-SHA256(X-MCM-Signature), - vérifie l'âge du timestamp (
X-MCM-Timestamp, fenêtre 5 min), - désérialise typé vers
B2BWebhookPayload<TData>, - résout votre handler depuis le DI.
Tester localement : exposez votre service via
ngrok http 5050et donnez l'URL à l'admin MCM. Détails : Webhooks.
5. Code complet (récapitulatif)
using MCM.ApiProxy;
using MCM.ApiProxy.Webhooks;
using MCM.B2B.Contracts.V2;
using MCM.B2B.Contracts.Webhooks;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddMcmApiClient(builder.Configuration);
builder.Services.AddScoped<EmployeService>();
builder.Services.AddMcmWebhookReceiver(builder.Configuration)
.AddHandler<AdhesionSigneeHandler, B2BAdhesionItemV2>(WebhookEventTypes.AdhesionSignee);
builder.Services.AddControllers();
var app = builder.Build();
app.MapControllers();
app.MapMcmWebhooks("/webhooks/mcm");
app.Run();
Prochaines étapes
- Synchronisation des employés —
ISyncClient.Syncpour les imports - Gestion des erreurs — patterns ErrorOr avancés
- Webhooks — catalogue d'événements et bonnes pratiques
- API Reference — toutes les méthodes
- Sandbox / client de test — pour vos tests d'intégration
Voir un exemple complet
L'application CLI MCM.ApiProxy.Cli couvre tous les clients du SDK avec un menu interactif (Spectre.Console). C'est la référence vivante pour explorer l'API.