Aller au contenu principal

Conventions de l'API

Cette page regroupe ce qui s'applique à tous les endpoints : URL de base, en-têtes, format des réponses, codes d'erreur, pagination et règles sur les montants. Les pages suivantes ne le répètent pas.

URL de base​

https://efn.efaina.com/api/public/v1

Tous les endpoints publics sont préfixés par /api/public/{version}. La version courante est v1.

Environnement sandbox

En sandbox, l'URL de base est https://sandback.efaina.com/api/public/v1. Une clé API générée en sandbox ne fonctionne pas en production, et inversement.

En-têtes​

En-têteObligatoireRôle
Authorization: Bearer {jeton}OuiAuthentifie le compte. Voir Jeton d'accès.
Accept: application/jsonOuiSans lui, les erreurs peuvent être renvoyées en HTML.
Content-Type: application/jsonSur POST/PUTSauf en multipart/form-data (création de wallet avec pièces jointes).
X-App-Id: {app_id}NonDésigne l'application appelante : webhook et liste blanche d'IP dédiés.

Format des réponses​

Toutes les réponses de l'API publique utilisent la même enveloppe :

{
"statusHttp": "success",
"message": "",
"response": { }
}
  • statusHttp : success ou error. C'est le statut applicatif, à ne pas confondre avec le code HTTP.
  • message : message lisible, éventuellement vide en cas de succès.
  • response : la charge utile — objet, tableau ou structure paginée selon l'endpoint.
  • errorCode : présent uniquement en cas d'erreur (la clé est retirée des réponses en succès).

Exemple d'erreur :

{
"statusHttp": "error",
"errorCode": "PAYLOAD_VALIDATION",
"message": "Invalid payload",
"response": {
"amount": ["The amount must be at least 300."]
}
}

Codes d'erreur applicatifs​

errorCodeCode HTTP usuelSignification
PAYLOAD_VALIDATION422Le corps de la requête est invalide. response contient le détail champ par champ.
NOT_FOUND_DATA404La ressource visée n'existe pas.
UNAUTHORIZED403La ressource existe mais n'appartient pas à votre compte.
SERVER_ERROR500Erreur inattendue de notre côté. L'incident est journalisé chez nous.

Erreurs sans enveloppe​

Les rejets qui interviennent avant le contrôleur — authentification, autorisation, liste blanche d'IP, X-App-Id invalide — sont renvoyés au format Laravel standard, sans enveloppe :

{
"message": "Unauthenticated."
}

Un second cas échappe à l'enveloppe : une ressource introuvable résolue avant l'exécution du contrôleur, lorsque l'identifiant de l'URL ne correspond à aucun enregistrement. La réponse est alors un 404 Laravel brut, sans statusHttp ni errorCode :

{
"message": "No query results for model [App\\Models\\Transaction] 9a6c9375-210b-4c6b-8ac9-41dcdf640213"
}

Votre client doit donc gérer les deux formes, et ne jamais supposer qu'errorCode est présent dès que le statut est en erreur. En pratique : fiez-vous d'abord au code HTTP, puis lisez response/message si l'enveloppe est présente.

Code HTTPQuand
200Lecture réussie.
201Création réussie (checkout, retrait, remboursement, wallet).
202Traitement accepté et mis en file (opérations de masse).
401Jeton absent, invalide ou expiré.
403Adhésion non réglée, ressource d'un autre compte, IP non autorisée, ou application désactivée.
404Ressource inexistante, ou donnée pas encore disponible (voir amount-commission-transaction).
422Payload invalide.
500Erreur serveur.

Pagination et filtres​

Les endpoints de listing (wallets, get-transactions, refunds, cash-outs) renvoient une structure paginée Laravel dans response :

{
"statusHttp": "success",
"message": "",
"response": {
"current_page": 1,
"data": [],
"per_page": 15,
"last_page": 2,
"total": 20,
"from": 1,
"to": 15,
"path": "https://efn.efaina.com/api/public/v1/get-transactions",
"first_page_url": "…?page=1",
"last_page_url": "…?page=2",
"next_page_url": "…?page=2",
"prev_page_url": null,
"links": []
}
}

Les éléments demandés se trouvent dans response.data ; tout ce qui l'entoure décrit la page courante. Pour construire une navigation, current_page, last_page, per_page et total suffisent. Le tableau links reprend les numéros de page prêts à afficher, chaque entrée portant url, label et active ; il inclut les libellés « précédent » et « suivant », dont l'url vaut null aux extrémités.

Une liste vide reste une structure paginée

Sans résultat, response conserve la même forme, avec data à [] et total à 0. Ce n'est jamais un 404.

Paramètres communs, en query string :

ParamètreDescription
paginationNombre de résultats par page. Défaut 15, plafonné à 100.
pageNuméro de page, à partir de 1.
searchRecherche globale de type LIKE sur les colonnes principales de la ressource.
sortChamps de tri séparés par des virgules, préfixés de - pour l'ordre décroissant. Exemple : sort=-created_at,amount.
filter[champ]Filtre exact sur un champ, ou partiel sur un champ de relation. Exemple : filter[status.slug]=pending.
between[champ]Filtre d'intervalle min,max. Exemple : between[amount]=1000,500000.

Les champs acceptés varient selon la ressource ; la référence API générée en donne la liste exhaustive pour chaque endpoint.

Montants​

  • Les montants sont exprimés en ariary (MGA), en nombres entiers. Les décimales sont refusées.
  • Minimum : 300 MGA. Maximum : 20 000 000 MGA.
  • Ces bornes s'appliquent aux paiements, transferts P2P, remboursements et retraits.

Statuts​

Les ressources financières partagent le même jeu de statuts, exposé sous forme de slug :

SlugSignification
pendingEn attente : créée, pas encore confirmée par l'opérateur.
successConfirmée et définitive.
errorÉchouée.
canceledAnnulée.
Ne jamais conclure depuis une réponse HTTP seule

Un checkout ou un retrait est créé en pending. La confirmation arrive de l'opérateur mobile ensuite, de façon asynchrone. C'est le webhook — ou une relecture de la transaction — qui fait foi, jamais la réponse à votre appel de création.

Champs de rapprochement​

Plusieurs endpoints acceptent un identifiant côté marchand pour rapprocher nos ressources de vos enregistrements internes :

  • custom_id — sur les transferts P2P et les remboursements.
  • comment / description — libellé métier, 100 caractères maximum.
  • X-App-Id — l'intégration à l'origine de l'appel, si vous utilisez les applications.