Vos votes et votre billetterie, dans votre backend.
Une API REST par clé d’organisation — créez une transaction de vote ou de billet, suivez son statut, éprouvez votre intégration en bac à sable. L’API héritée reste servie telle quelle pour les intégrations déjà construites contre l’ancienne plateforme.
Vue d’ensemble
Le SDK et le plugin affichent et encaissent depuis le navigateur de vos visiteurs. Si vous préférez tout maîtriser — votre propre interface, un canal de vente parallèle, un rapprochement comptable automatisé — appelez directement notre API, par clé d’organisation.
Quatre gestes, et quatre seulement : lire vos éditions et ce qu’elles contiennent, créer une transaction de vote ou d’achat de billet, accorder des votes avec un code de billet déjà payé, suivre le statut d’un paiement. Rien ne s’y crée ni ne s’y modifie côté configuration — pas d’édition, pas de nominé, pas de retrait : une clé qui fuite ne peut qu’engager des paiements que vous encaissez vous-même.
https://api.zekin.me/api/v1/public
Format des réponses
Le même partout dans cette API : un succès rend { success: true, message, data, meta? }, un refus { success: false, error: { code, message, details? } }. Les messages suivent l’en-tête X-Locale: fr|en (français par défaut).
Cloisonnement
Une clé ne voit que son organisation. Ce qui ne lui appartient pas est traité comme absent (404), jamais comme interdit — répondre « interdit » apprendrait déjà qu’une donnée existe ailleurs. Cela vaut en lecture comme en écriture : voter pour le nominé d’un autre organisateur ou consulter sa transaction rend 404, même avec une clé parfaitement valide.
Authentification
Votre clé se génère et se régénère depuis votre espace Zekin : Organisations → menu de la ligne → « Clé API ». Elle se transmet dans l’en-tête X-API-Key de chaque appel — jamais dans l’adresse, jamais dans un fichier JavaScript servi à vos visiteurs.
/public/meVérifier votre clé{
"success": true,
"message": "Clé API valide.",
"data": {
"organizationId": "00615193-0dbf-4537-872b-d59a424f26ba",
"organizationName": "Votre organisation"
}
}curl https://api.zekin.me/api/v1/public/me \ -H "X-API-Key: zk_votre_cle"
Authorization: ApiKey <clé> est aussi accepté, pour les clients HTTP qui l’imposent. Le schéma Bearer n’est jamais accepté : il désigne un jeton de session ailleurs dans cette API, et les deux doivent rester distincts dans nos journaux.Lire les éditions
Vos éditions, avec leurs catégories, phases, nominés et types de billets. Les mêmes données que la vitrine, jamais un instantané à part.
/public/editionsLister vos éditions| Champ | Note |
|---|---|
include | Séparés par des virgules : categories, phases, nominees, tickets ; ou vote, ticket, all. Défaut ici : none. |
eventId / eventSlug | Ne garder que les éditions de cet évènement |
status | draft, active, completed, inactive |
page, limit | Défaut 1 / 50 — limit plafonné à 200 |
GET /public/editions?status=active X-API-Key: zk_votre_cle
{
"success": true,
"message": "Éditions récupérées avec succès.",
"data": [
{
"id": "c14f4e90-…",
"slug": "tmpapi-festival/edition-2026",
"name": "TMPAPI Festival - 2026",
"status": "active",
"country": "BJ",
"currency": "XOF",
"votePrice": 100,
"startDate": "2026-08-19T23:05:08.477Z",
"endDate": "2026-09-19T23:05:08.477Z",
"coverUrl": null,
"features": { "vote": true, "ticket": true, "ticketVote": true, "candidature": false, "donation": false },
"event": { "id": "a72bb985-…", "name": "TMPAPI Festival", "slug": "tmpapi-festival" }
}
],
"meta": { "page": 1, "limit": 50, "total": 1, "totalPages": 1 }
}Toutes les adresses d’images sont absolues, domaine compris — couverture, bannière, photo d’un nominé, image d’un billet. Vous n’avez aucune page depuis laquelle résoudre une adresse relative.
/public/editions/{id|slug|évènement/edition-n}Une édition, avec son contenu| Champ | Note |
|---|---|
include | Mêmes valeurs que ci-dessus. Défaut ici : vote |
categoryId | Ne garder que les nominés de cette catégorie |
phaseId | Les nominés de cette phase plutôt que la phase en cours |
groupByCategory | true pour regrouper les nominés sous leur catégorie |
GET /public/editions/tmpapi-festival/edition-2026?include=vote X-API-Key: zk_votre_cle
{
"success": true,
"data": {
"id": "c14f4e90-…",
"slug": "tmpapi-festival/edition-2026",
"vote": {
"phase": { "id": "654c7e8b-…", "name": "Phase unique", "order": 1 },
"categories": [{ "id": "27494f30-…", "name": "TMPAPI Chant", "slug": "…/chant" }],
"nominees": {
"items": [
{
"id": "7d1e5322-…",
"pseudo": "TMPAPI Alpha",
"keyword": "tmpapi-alpha",
"category": { "id": "27494f30-…", "name": "TMPAPI Chant" },
"voteCount": 5
}
],
"pagination": { "page": 1, "limit": 50, "total": 3, "totalPages": 1 }
}
}
}
}Trois formes d’adresse acceptées, essayées dans l’ordre : l’identifiant, le slug de l’édition (deux segments, tmpapi-festival/edition-2026), ou le slug de l’évènement suivi de edition-{n}. Écrire l’adresse de mémoire fonctionne dans les deux cas.
voteCount suit le réglage « Afficher le résultat des votes » de l’édition : null = non communiqué, 0 = aucun vote — jamais confondus. Une catégorie ou une phase qui n’appartient pas à l’édition est refusée (400) plutôt que de rendre une liste vide qu’on lirait à tort comme « aucun nominé ».Créer un paiement
Deux façons de créer une transaction — vote ou billet. Le montant n’est jamais soumis : il est calculé côté serveur depuis le prix de vote réel de l’édition et ses paliers.
/public/votesCréer une transaction de vote| Champ | Note |
|---|---|
nomineerequis | Le mot-clé du nominé — pas son identifiant |
voteCountrequis | Entier ≥ 1 |
phoneNumberrequis | Numéro du payeur |
paymentMethodrequis | Voir le catalogue plus bas |
email | Exigé pour carte ou PayPal |
edition | Identifiant ou slug, pour départager un mot-clé porté par plusieurs éditions |
country | 2 lettres, transmis à la passerelle (défaut BJ) |
channel | website (défaut), mobile, whatsapp, autre |
referralCode | Code de parrainage — absent ou inconnu, il est ignoré |
POST /public/votes
X-API-Key: zk_votre_cle
Content-Type: application/json
{
"nominee": "tmpapi-alpha",
"voteCount": 5,
"phoneNumber": "+22997000001",
"paymentMethod": "mtn",
"email": "[email protected]"
}{
"success": true,
"message": "Transaction de vote créée avec succès.",
"data": {
"flow": "vote",
"transactionId": "eeac7363-…",
"reference": "VOTE-20260820-18F719",
"status": "pending",
"amount": 500,
"currency": "XOF",
"voteCount": 5,
"nominee": { "id": "7d1e5322-…", "keyword": "tmpapi-alpha", "pseudo": "TMPAPI Alpha" },
"edition": { "id": "c14f4e90-…", "slug": "tmpapi-festival/edition-2026" },
"redirectUrl": null,
"gatewayMessage": "Veuillez consulter votre téléphone pour valider le paiement…"
}
}redirectUrl — à ouvrir quand le moyen de paiement passe par une page (carte, Wave, PayPal), null sur un paiement mobile. gatewayMessage — l’instruction exacte de l’opérateur, à afficher telle quelle au payeur. Le paiement n’est pas terminé à ce stade : il faut suivre son statut.
/public/ticketsAcheter un ou plusieurs billets| Champ | Note |
|---|---|
editionrequis | Identifiant ou slug |
itemsrequis | Tableau de { ticket, quantity } — un ticket par type |
phoneNumberrequis | Numéro du payeur |
paymentMethodrequis | Voir le catalogue plus bas |
email | Exigé pour carte ou PayPal |
country | 2 lettres (défaut BJ) |
promoCode | Code de réduction, s'il y en a un |
POST /public/tickets
X-API-Key: zk_votre_cle
Content-Type: application/json
{
"edition": "c14f4e90-47d2-4f46-9a16-f3e6b96814da",
"items": [
{ "ticket": "2fd99ec5-7df0-437d-b442-f1fcccc484e2", "quantity": 2 },
{ "ticket": "18580ad5-2857-4319-b8e9-76cfef9462de", "quantity": 1 }
],
"phoneNumber": "+22997000002",
"email": "[email protected]",
"paymentMethod": "moov"
}{
"success": true,
"message": "Transaction de billet créée avec succès.",
"data": {
"flow": "ticket",
"transactionId": "2071e56c-…",
"reference": "TCK-20260820-D5477D",
"status": "pending",
"amount": 3000,
"currency": "XOF",
"quantity": 3,
"items": [
{ "id": "86e3913c-…", "ticketType": "TMPAPI Standard", "amount": 500, "status": "pending" },
{ "id": "c7d9b2a8-…", "ticketType": "TMPAPI Standard", "amount": 500, "status": "pending" },
{ "id": "39c0b036-…", "ticketType": "TMPAPI VIP", "amount": 2000, "status": "pending" }
],
"redirectUrl": null,
"gatewayMessage": null
}
}Une ligne par billet, un seul paiement. Un panier de plusieurs unités crée autant de lignes — chacune son propre code à scanner à l’entrée — mais un seul transactionId, celui qu’il faut présenter à la vérification.
Moyens de paiement acceptés
Ils dépendent du réglage de passerelle de votre espace — opérateurs du pays du payeur plus carte/Wave/PayPal, ou le catalogue direct de la passerelle active. Le catalogue exact se lit toujours sur GET /api/v1/payment-simulation/methods.
Voter avec un billet
Le billet a déjà été payé : aucun paiement ici, son code est présenté une fois et accorde le nombre de votes que son type déclare.
/public/votes/by-ticket-codeAccorder des votes sans paiement| Champ | Note |
|---|---|
nomineerequis | Le mot-clé du nominé, résolu comme sur /public/votes |
coderequis | Le code du billet, à usage unique |
edition | Pour lever une ambiguïté de mot-clé |
POST /public/votes/by-ticket-code
X-API-Key: zk_votre_cle
Content-Type: application/json
{ "nominee": "tmpapi-alpha", "code": "N7CW2UVJEZ" }{
"success": true,
"message": "Votes accordés avec succès grâce à votre ticket.",
"data": {
"flow": "vote",
"transactionId": "bcd08eae-…",
"reference": "VOTE-20260820-1F1BBD",
"status": "approved",
"voteCount": 3,
"nominee": { "id": "7d1e5322-…", "keyword": "tmpapi-alpha", "pseudo": "TMPAPI Alpha" },
"edition": { "id": "c14f4e90-…", "slug": "tmpapi-festival/edition-2026" },
"amount": 0,
"currency": "XOF"
}
}Se règle immédiatement (status: "approved") : rien à vérifier ensuite. Une seconde présentation du même code est refusée — la double dépense est fermée côté base de données, deux appels simultanés portant le même code n’en font aboutir qu’un.
Bac à sable
Éprouvez votre intégration sans jamais encaisser. Le mode se donne dans le corps de chaque appel, jamais dans un réglage : la même clé fait les deux, appel par appel, sans jamais rien couper.
{
"mode": "sandbox",
"nominee": "tmpapi-alpha",
"voteCount": 5,
"phoneNumber": "+22997000000",
"paymentMethod": "mobile_money"
}Sans ce champ, un appel encaisse pour de vrai — production est le défaut. Une simulation porte une référence SBX-…, vit dans sa propre table, et n’a aucun effet réel — aucun vote compté, aucun solde modifié, aucun billet capable d’ouvrir une porte.
Ce qui change entre les deux modes
| Production | Bac à sable | |
|---|---|---|
| Références | VOTE-…, TCK-… | SBX-VOTE-…, SBX-TCK-… |
| redirectUrl | page de paiement, ou null | toujours null |
| Bloc sandbox | absent | présent |
| Adresse de contrôle du billet | servie | toujours null |
| Total de votes du nominé | servi | toujours null |
Toute seule, une simulation aboutit après trois vérifications — deux passages restent « en attente », le troisième tranche au sort (85 % d’approbation), exactement comme un vrai paiement dont l’issue arrive d’ailleurs. Vous pouvez aussi la fixer d’avance :
{ "mode": "sandbox", "desiredStatus": "approved", … }| Valeur | Ce que vous obtenez |
|---|---|
approved | Approuvée d'emblée, avec sa référence d'opérateur et, pour un billet, son code. |
canceled | Refusée d'emblée, sans référence d'opérateur ni code de billet. |
pending | En attente pour toujours — le seul moyen d'éprouver un payeur qui ne valide jamais. |
(absent) | Comportement normal : deux vérifications en attente, la troisième tranche au sort. |
/public/sandbox/transactions/{référence}/settleTrancher une simulation à la demande| Champ | Note |
|---|---|
statusrequis | approved ou canceled — jamais pending, c'est l'état de départ |
POST /public/sandbox/transactions/SBX-VOTE-20260820-18F719/settle
X-API-Key: zk_votre_cle
Content-Type: application/json
{ "status": "approved" }// La réponse de GET /public/transactions/{référence}, avec le nouveau statut.À employer avant la troisième vérification automatique : un paiement déjà tranché ne se rejoue pas. Cette route ne connaît que le bac à sable — une référence de production y est simplement introuvable.
Suivi des paiements
Un paiement n’est jamais terminé au moment où il est créé : suivez-le jusqu’à ce que son statut cesse de valoir pending.
/public/transactions/{référence}Statut d'un paiement — fait avancer la vérificationGET /public/transactions/VOTE-20260820-18F719 X-API-Key: zk_votre_cle
{
"flow": "vote",
"transactionId": "eeac7363-…",
"reference": "VOTE-20260820-18F719",
"externalReference": "SIM-0B0F710373E6",
"status": "approved",
"amount": 500,
"currency": "XOF",
"paymentMethod": "mtn",
"edition": { "id": "c14f4e90-…", "slug": "tmpapi-festival/edition-2026" },
"nominee": { "id": "7d1e5322-…", "pseudo": "TMPAPI Alpha", "keyword": "tmpapi-alpha" },
"voteCount": 5,
"nomineeVoteCount": 5,
"createdAt": "2026-08-20T23:08:31.965Z",
"settledAt": "2026-08-20T23:08:41.768Z"
}Accepte n’importe laquelle des références que la création a rendues — transactionId, reference, ou celle de la passerelle. Cet appel interroge la passerelle et fait avancer le paiement — c’est lui qu’on rappelle en boucle après une création. Vote, billet, candidature et don s’y retrouvent tous ; candidature et don ne se créent pas par cette API mais restent suivables si vous les avez encaissés autrement.
/public/transactionsLister — pour un rapprochement comptable, sans rien faire avancer| Champ | Note |
|---|---|
flow | vote, ticket, candidature, donation — défaut : les quatre |
status | pending, approved, canceled — défaut : tous |
edition | Identifiant ou slug |
nominee | Le mot-clé — restreint au parcours vote |
from, to | Dates ISO, bornes incluses |
mode | sandbox pour lister vos simulations — absent : les vraies transactions |
page, limit | Défaut 1 / 200 — limit plafonné à 200 |
GET /public/transactions?flow=vote&status=approved X-API-Key: zk_votre_cle
{
"success": true,
"data": [
{
"flow": "vote",
"reference": "VOTE-20260824-18F719",
"status": "approved",
"amount": 500,
"currency": "XOF",
"paymentMethod": "mtn",
"payer": { "phoneNumber": "+22990000000", "email": null },
"edition": { "id": "c14f4e90-…", "slug": "tmpapi-festival/edition-2026" },
"organizationAmount": 300,
"voteCount": 5,
"nominee": { "pseudo": "TMPAPI Alpha", "keyword": "tmpapi-alpha" }
}
],
"meta": { "page": 1, "limit": 200, "total": 4, "totalPages": 1 }
}200 par page ici, contre 50 ailleurs dans cette API : on ne parcourt pas des transactions pour les lire une à une. Ce que la plateforme prélève (systemAmount, whiteLabelAmount) n’est servi qu’à une clé de super administrateur.
Statuts
| Valeur | Terminal | Signification |
|---|---|---|
pending | non | En attente de confirmation par la passerelle de paiement. |
approved | oui | Payé et son effet appliqué — votes crédités, billet valide. |
canceled | oui | Refusé ou abandonné par le payeur, aucun effet. |
Codes d’erreur
Le catalogue complet, groupé par sujet — retrouvez-le pendant que vous débogez plutôt que de le mémoriser à l’avance.
Authentification
| Code | HTTP | Cause |
|---|---|---|
PUBLIC_API_MISSING_KEY | 401 | En-tête X-API-Key absent |
PUBLIC_API_INVALID_KEY | 401 | Clé inconnue, ou organisation hors service |
Lecture des éditions
| Code | HTTP | Cause |
|---|---|---|
PUBLIC_API_EDITION_NOT_FOUND | 404 | Identifiant/slug inconnu, ou d'une autre organisation |
PUBLIC_API_CATEGORY_NOT_FOUND | 400 | categoryId hors de cette édition |
PUBLIC_API_PHASE_NOT_FOUND | 400 | phaseId hors de cette édition |
Créer un vote
| Code | HTTP | Cause |
|---|---|---|
PUBLIC_API_NOMINEE_NOT_FOUND | 404 | Mot-clé inconnu, ou d'une autre organisation |
PUBLIC_API_NOMINEE_AMBIGUOUS | 409 | Mot-clé porté par plusieurs éditions — précisez edition |
PAYMENT_VOTE_NOT_ACTIVE | 400 | Le vote n'est pas activé sur l'édition |
PAYMENT_VOTE_NOT_STARTED | 400 | Les votes n'ont pas encore commencé |
PAYMENT_EDITION_NOT_RUNNING | 400 | L'édition n'est pas « en cours » |
PAYMENT_NOMINEE_INACTIVE | 400 | Le nominé est désactivé |
PAYMENT_NOMINEE_PHASE_CLOSED | 400 | Le nominé appartient à une phase déjà close |
PAYMENT_EMAIL_REQUIRED | 400 | Carte ou PayPal sans adresse e-mail |
PAYMENT_GATEWAY_NOT_CONFIGURED | 400 | Aucune passerelle de paiement configurée |
Acheter un billet
| Code | HTTP | Cause |
|---|---|---|
PAYMENT_TICKET_NOT_ACTIVE | 400 | La billetterie n'est pas activée sur l'édition |
PAYMENT_UNKNOWN_TICKET | 400 | Type de billet inconnu de cette édition |
PAYMENT_PROMO_CODE_EXPIRED | 400 | Code de réduction expiré ou inconnu |
Voter avec un billet
| Code | HTTP | Cause |
|---|---|---|
PAYMENT_TICKET_VOTE_NOT_ACTIVE | 400 | Le vote par ticket n'est pas activé sur l'édition |
PAYMENT_TICKET_CODE_NOT_FOUND | 400 | Code inconnu pour cette édition |
PAYMENT_TICKET_CODE_NOT_APPROVED | 400 | Le billet n'est pas payé |
PAYMENT_TICKET_CODE_ALREADY_REDEEMED | 400 | Ce code a déjà servi à voter |
PAYMENT_TICKET_NO_VOTES_GRANTED | 400 | Ce type de billet n'accorde aucun vote |
Bac à sable
| Code | HTTP | Cause |
|---|---|---|
PUBLIC_API_DESIRED_STATUS_SANDBOX_ONLY | 400 | desiredStatus soumis en production |
PUBLIC_API_DESIRED_STATUS_NOT_APPLICABLE | 400 | desiredStatus sur /votes/by-ticket-code — rien à décider |
PUBLIC_API_SANDBOX_ALREADY_SETTLED | 409 | Cette simulation a déjà été tranchée |
Validation générale
| Code | HTTP | Cause |
|---|---|---|
VALIDATION_ERROR | 422 | Un champ mal orthographié — include, mode, flow, desiredStatus, dates |
API héritée
Réservée aux intégrations déjà construites contre l’ancienne plateforme Zekin. Elle reproduit son contrat exact, à l’adresse qu’elle servait déjà — aucune ligne à changer côté appelant. Pour une intégration nouvelle, préférez l’API publique moderne : plus complète, avec son propre bac à sable.
Les deux API sont servies par le même serveur et lisent les mêmes données — elles ne diffèrent que par le contrat qu’elles respectent.
https://api.zekin.me/api/request
Les huit routes, en un coup d’œil
| Méthode | Route | Auth | À quoi elle sert |
|---|---|---|---|
GET | /current/events | oui | Évènements groupés par statut |
GET, POST | /event/:keyword | oui | Détail d'une édition — catégories, nominés, tarifs |
POST | /create/vote/:nomineeKeyword | non | Créer une transaction de vote |
POST | /check/transaction | oui | Statut d'une transaction — fait avancer le paiement |
POST | /check/transactions | oui | Recherche de transactions — sans effet |
POST | /authenticate/:eventId | oui | Connexion par mot secret (portail nominé) |
GET | /laureate/:key | oui | Profil d'un nominé |
POST | /laureate/history/:key | oui | Historique des votes d'un nominé |
Authentification
La même clé que pour l’API publique moderne, transmise cette fois dans le schéma Bearer — celui que l’ancienne plateforme imposait, repris à l’identique.
Authorization: Bearer <clé>
POST /create/vote/:nomineeKeyword est publique — c’est le geste que fait le navigateur du votant lui-même, pas votre intégration.Format des réponses — différent de l’API moderne
Le contrat exact de l’ancienne plateforme, y compris ce qu’il a de particulier — jamais l’enveloppe { success, ... } du reste de ce projet.
{ "type": "success", "message": "...", "data": ... }{ "type": "error", "message": "Invalid laureate" }Les messages sont des littéraux exacts de l’ancienne plateforme (Invalid laureate, Invalid event, Invalid secret code, Invalid API key, Get idTransaction or phone valid, Le mot clé est incorrect., Keyword conflict (Please use ID)) — jamais reformulés, certains étant cités mot pour mot par du code d’intégration existant.
Évènements & éditions
/current/eventsÉvènements groupés par statutGET /current/events Authorization: Bearer <clé>
{
"type": "success",
"message": "Events retrieved",
"data": {
"Evènements en cours": [
{ "id": "a72bb985-…", "keyword": "tmpapi-festival-2026", "name": "TMPAPI Festival", "coverUrl": "https://…" }
],
"Evènements programés": []
}
}Deux groupes seulement, aux intitulés recopiés au caractère près de l’ancienne plateforme, faute d’orthographe comprise. Un évènement terminé sort de la liste ; sa fiche reste atteignable par /event/:keyword.
Détail d’un évènement
/event/:keywordDétail d'une édition — catégories, nominés, tarifs| Champ | Note |
|---|---|
keywordrequis | Dans l'adresse. Identifiant d'édition, identifiant d'évènement, slug, ou mot-clé hérité — dans cet ordre |
scope | Dans le corps, POST uniquement — "active" masque catégories et nominés désactivés, absent ou toute autre valeur rend tout |
POST /event/tmpapi-festival-2026
Authorization: Bearer <clé>
Content-Type: application/json
{ "scope": "active" }{
"type": "success",
"message": "Event retrieved",
"data": {
"id": "c14f4e90-…",
"categories": [{ "id": "27494f30-…", "name": "TMPAPI Chant" }],
"nominees": [{ "id": "7d1e5322-…", "pseudo": "TMPAPI Alpha", "score": 42.1 }],
"packs": [{ "name": "Pack 20", "number": 20, "numberMax": 50, "amount": 75, "include": true, "descript": "…" }],
"countryFlag": null
}
}GET n’a pas de corps — un simple GET /event/tmpapi-festival-2026 suffit, et rend tout (catégories et nominés désactivés compris). Un « event » hérité est une édition, pas un évènement. Le score d’un nominé (en pourcentage) se calcule par catégorie, pas sur l’édition entière — délibérément différent de la vitrine moderne. countryFlag vaut toujours null.
Créer un vote
/create/vote/:nomineeKeywordCréer une transaction de vote — route publique| Champ | Note |
|---|---|
phonerequis | Numéro du payeur |
processrequis | Moyen de paiement (mtn, wave, card, paypal…), transmis tel quel |
number | Nombre de votes. Vide ou 0 → 1 |
email | Facultatif |
canal | Facultatif — website par défaut |
bp, userId, fname, lname | Acceptés et ignorés (exigés par l'ancienne passerelle) |
POST /create/vote/tmpapi-alpha
Content-Type: application/json
(aucune clé requise — route publique)
{
"phone": "+22997000001",
"process": "mtn",
"number": 5
}{
"type": "success",
"message": "Vote transaction created",
"data": {
"refInterne": "VOTE-20260820-18F719",
"gatewayMessage": "Veuillez consulter votre téléphone pour valider le paiement…"
}
}La réponse porte gatewayMessage — l’instruction exacte à afficher au payeur (« consultez votre téléphone… ») — et refInterne, à repasser à /check/transaction pour suivre le paiement.
Suivi des paiements
/check/transactionStatut d'une transaction — fait avancer le paiement| Champ | Note |
|---|---|
idTransactionrequis | Le seul filtre accepté ici — pas de recherche par téléphone sur cette route |
POST /check/transaction?idTransaction=VOTE-20260820-18F719 Authorization: Bearer <clé> (corps vide)
{ "type": "success", "message": "Transaction status", "data": { "status": 16, "amount": 500 } }Le paramètre part en chaîne de requête, pas dans le corps JSON — une particularité de l’ancienne plateforme, reprise à l’identique (le corps est relu en repli si vous préférez l’y mettre). C’est la route qu’une page de statut rappelle en boucle jusqu’à ce que le paiement soit tranché. Sans filtre : Get idTransaction or phone valid (400).
/check/transactionsRecherche de transactions — sans effet de bord| Champ | Note |
|---|---|
idTransaction | idTransaction ou phone, l'un des deux au moins |
phone | idTransaction ou phone, l'un des deux au moins |
startDate | Facultatif — date ISO, borne basse |
endDate | Facultatif — date ISO, borne haute |
POST /check/transactions?phone=22997000001&startDate=2026-01-01&endDate=2026-12-31 Authorization: Bearer <clé> (corps vide)
{ "type": "success", "message": "Transactions found", "data": [{ "status": 16, "amount": 500 }] }Mêmes champs acceptés dans le corps JSON, en repli. Rend un tableau, sans jamais faire avancer aucun paiement — lister plusieurs transactions ne doit jamais trancher leur sort.
Portail nominé
/authenticate/:eventIdConnexion par mot secret| Champ | Note |
|---|---|
eventIdrequis | Dans l'adresse. Identifiant d'édition, ou mot-clé d'évènement/édition |
passcoderequis | Dans le corps. Comparé sans tenir compte de la casse — secretWord est aussi accepté, comme nom de champ alternatif |
POST /authenticate/tmpapi-festival-2026
Authorization: Bearer <clé>
Content-Type: application/json
{ "passcode": "fde23QA" }{ "type": "success", "message": "Authenticated", "data": { "id": "7d1e5322-…", "pseudo": "TMPAPI Alpha" } }Un refus est muet sur sa cause : édition inconnue ou mot secret faux rendent le même message. Tentatives limitées, partagées avec le portail nominé de la plateforme.
/laureate/:keyProfil d'un nominé| Champ | Note |
|---|---|
keyrequis | Mot-clé, ou identifiant hérité (l'_id Mongo, conservé tel quel) |
GET /laureate/tmpapi-alpha Authorization: Bearer <clé>
{ "type": "success", "message": "Laureate retrieved", "data": { "id": "7d1e5322-…", "pseudo": "TMPAPI Alpha", "score": 42.1 } }Un mot-clé porté par plusieurs nominés de la même édition (doublons hérités) rend Keyword conflict (Please use ID) plutôt qu’un choix arbitraire.
/laureate/history/:keyHistorique des votes reçus| Champ | Note |
|---|---|
keyrequis | Dans l'adresse. Mot-clé, ou identifiant hérité |
start | Facultatif — date ISO, borne basse |
end | Facultatif — date ISO, borne haute |
scope | Accepté et sans effet (l'historique servi ici n'est déjà que celui de ce nominé) |
POST /laureate/history/tmpapi-alpha
Authorization: Bearer <clé>
Content-Type: application/json
{ "start": "2026-01-01", "end": "2026-12-31" }{
"type": "success",
"message": "History retrieved",
"data": [
{ "phone": "+22994••••30", "amount": 100, "status": 16, "date": "2026-08-20T…" }
]
}Votes validés et annulés seulement, jamais ceux en attente. Le numéro du votant est masqué (mêmes six chiffres visibles que le portail nominé).
| Statut | Signification |
|---|---|
16 | Validé — voix comptée. |
7 | Annulé — paiement refusé ou abandonné. |
2 | En attente — jamais servi ici, un paiement non abouti n'est pas un fait. |
GET https://api.zekin.me/public/{clé}Sert les mêmes fichiers que /uploads/{clé}, sous un second préfixe — ce qui évite de faire apparaître le domaine de l’API dans votre propre HTML.
/stats/event/{id} n’est pas implémentée — inutilisable même sur l’ancienne plateforme, ne la cherchez pas.Limites
Ce que cette API ne fait pas :
- Aucune création de contenu — pas d’évènement, de catégorie, de candidat, de prix, de palier, de retrait.
- Pas de mode bac à sable, contrairement à l’API publique moderne.
- Pas de candidature ni de don — seulement le vote et, via
/check/transaction(s), ce qui a déjà été encaissé.
X-API-Key), enveloppe homogène, bac à sable, et lecture des transactions.Index des routes
Les neuf routes de l’API publique, en un coup d’œil.
| Méthode | Route | À quoi elle sert |
|---|---|---|
| GET | /public/me | Vérifier que la clé est valide |
| GET | /public/editions | Lister les éditions de l'organisation |
| GET | /public/editions/{id|slug} | Une édition, avec ses catégories, phases et nominés |
| POST | /public/votes | Créer une transaction de vote |
| POST | /public/tickets | Acheter un ou plusieurs billets |
| POST | /public/votes/by-ticket-code | Accorder des votes avec un billet déjà payé |
| GET | /public/transactions | Lister vos transactions — les 4 parcours réunis |
| GET | /public/transactions/{référence} | Suivre un paiement — fait avancer le statut |
| POST | /public/sandbox/transactions/{référence}/settle | Bac à sable : trancher une simulation à la demande |
Limites connues
Une bonne documentation dit aussi ce qu’elle ne fait pas :
- Aucune limitation de débit propre à cette API pour l’instant.
- Candidature et don ne peuvent pas être créés par cette API — ils sont lisibles et leur paiement suivable s’ils ont été encaissés autrement.
- Aucun total agrégé sur la liste des transactions : elle rend les lignes, pas leur somme par statut ou par devise.
- Le bac à sable ne couvre que le vote et le billet, les deux seuls parcours que cette API sait créer.
- Rien ne distingue une clé « de test » d’une clé de production — le mode se donne appel par appel, pas par la clé.
- Invitations, retraits et créances ne sont pas exposés par cette API.
Une question sur l’intégration ?
Notre équipe technique vous répond directement.
Contacter le support