Profil utilisateur (/me)
Base URL : /api/v1/me
Endpoints d'auto-service pour l'utilisateur connecté (agent, plateforme ou porteur de carte). L'accès aux fonctionnalités parent-enfant est conditionné par org.settings.parent_features_enabled.
Solde et historique
GET /me/balance
Cartes et solde de l'utilisateur connecté.
Permissions : card.read
{
"cards": [
{
"id": "uuid",
"code": "CL-EL-0008",
"card_number": "6287940000123456",
"status": "active",
"balance_cents": 5000,
"balance": 5000,
"balance_formatted": "5 000 FCFA",
"currency": "XOF"
}
],
"active_card": { "id": "uuid", "status": "active", "balance_cents": 5000 },
"currency": "XOF"
}
active_card correspond à la première carte au statut active (opérationnelle).
GET /me/history
Historique des transactions de l'utilisateur.
Permissions : card.read
| Param | Type | Défaut | Description |
|---|---|---|---|
limit | integer | 20 | Max 100 |
offset | integer | 0 | Décalage |
search | string | — | Recherche |
Comportement selon kind :
- Agent / Plateforme → transactions effectuées par l'utilisateur.
- Porteur → transactions de toutes ses cartes, fusionnées et triées par date.
Réponse (200) :
{
"items": [
{
"id": "uuid",
"card_id": "uuid",
"type": "debit_purchase",
"is_voided": false,
"amount_cents": 1500,
"balance_before_cents": 5000,
"balance_after_cents": 3500,
"performed_by_user_id": "uuid",
"performed_by_name": "Jean Mbeki",
"point_of_sale_id": "uuid",
"site_id": "uuid",
"reference_order_id": null,
"created_at": "2025-06-01T10:00:00Z",
"amount": 1500,
"amount_formatted": "1 500 FCFA",
"balance_before": 5000,
"balance_before_formatted": "5 000 FCFA",
"balance_after": 3500,
"balance_after_formatted": "3 500 FCFA",
"currency": "XOF",
"purchase_items": [
{ "name": "Café", "quantity": 1, "unit_price_cents": 1500 }
]
}
],
"total": 42,
"currency": "XOF"
}
GET /me/operations
Récapitulatif des opérations de la journée pour un agent (ventes, recharges). Réservé aux agents et plateformes.
Permissions : transaction.read + appelant tenant ou platform
| Param | Type | Défaut | Description |
|---|---|---|---|
date | date | aujourd'hui | Date des opérations |
limit | integer | 100 | Éléments par page |
offset | integer | 0 | Décalage |
type | string | — | Types à inclure (défaut : ventes + recharges) |
Réponse (200) :
{
"agent": { "id": "uuid", "name": "Jean Mbeki" },
"date": "2025-06-21",
"currency": "XOF",
"summary": {
"ventes_count": 12,
"ventes_total_cents": 18000,
"recharges_count": 5,
"recharges_total_cents": 25000,
"grand_total_cents": 43000
},
"total": 17,
"transactions": [ ]
}
Les totaux du summary sont agrégés sur toute la journée, indépendamment de la pagination.
Réservations
GET /me/reservations
Réservations de l'utilisateur connecté.
Permissions : card.read
| Param | Type | Défaut | Description |
|---|---|---|---|
limit | integer | 20 | Max 100 |
offset | integer | 0 | Décalage |
Réponse (200) : { items: [Reservation], total, currency } — voir la forme d'une réservation dans Réservations.
Fonctionnalités parent-enfant
Ces endpoints nécessitent org.settings.parent_features_enabled = true, sinon 404 "Fonctionnalité parent désactivée".
GET /me/children
Liste des enfants liés au porteur parent.
Permissions : child.balance.read ou child.recharge
{
"items": [
{
"id": "uuid",
"establishment_name": null,
"last_name": "Diallo",
"first_name": "Aïcha",
"holder_type": "student",
"code": "CL-EL-0012"
}
],
"total": 2
}
GET /me/children/{child_id}/balance
Solde des cartes d'un enfant.
Permissions : card.read + lien parent vérifié
{
"child_id": "uuid",
"cards": [
{
"id": "uuid",
"code": "CL-EL-0012",
"card_number": "6287940000123460",
"status": "active",
"balance_cents": 2500,
"holder_first_name": "Aïcha",
"holder_last_name": "Diallo",
"balance": 2500,
"balance_formatted": "2 500 FCFA",
"currency": "XOF"
}
],
"active_card": null,
"currency": "XOF"
}
GET /me/children/{child_id}/history
Historique des transactions d'un enfant.
Permissions : child.balance.read ou child.recharge + card.read
| Param | Type | Défaut | Description |
|---|---|---|---|
limit | integer | 20 | Max 100 |
offset | integer | 0 | Décalage |
Réponse (200) : { items: [Transaction], total } — sans champ currency.
Dans cet endpoint, type est le nom de la variante Rust ("DebitPurchase") et performed_by est un objet { id, kind }. Les montants sont des entiers bruts (pas de *_formatted).
PUT /me/children/{child_id}/cards/{card_id}/daily-limit
Définit le plafond journalier d'une carte enfant.
Permissions : child.recharge
PUT /api/v1/me/children/{child_id}/cards/{card_id}/daily-limit
Content-Type: application/json
{
"daily_limit_cents": 2000
}
| Champ | Type | Requis | Description |
|---|---|---|---|
daily_limit_cents | integer | Oui | Plafond (0 = pas de plafond) |
Réponse (200) :
{
"card_id": "uuid",
"daily_limit_cents": 2000
}
POST /me/children/{child_id}/recharge
Recharge la carte d'un enfant.
Permissions : child.recharge
En-tête : Idempotency-Key (obligatoire)
POST /api/v1/me/children/{child_id}/recharge
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440003
Content-Type: application/json
{
"amount_cents": 3000,
"method": "cash"
}
| Champ | Type | Requis | Description |
|---|---|---|---|
amount_cents | integer | Oui | Montant |
method | string | Oui | "cash" ou "mobile_money" |
site_id | uuid | Non | Site |
customer_phone | string | Cond. | Requis si mobile_money |
Réponse (cash) : { "message": "Rechargement effectué", "transaction": {...} }
Réponse (mobile_money) : { "payment_url": "...", "session_id": "uuid", "provider_tx_id": null }
POST /me/children/{child_id}/reservations
Crée une réservation pour un enfant.
Permissions : reservation.create
En-tête : Idempotency-Key (obligatoire)
{
"items": [{ "product_id": "uuid", "quantity": 1 }],
"for_date": "2025-06-21",
"notes": null
}
Réponse (200) : { "message": "Réservation effectuée", "reservation": {...} }
GET /me/children/{child_id}/reservations
Réservations d'un enfant.
Permissions : card.read + lien parent vérifié
Réponse (200) : { items: [Reservation], total, currency }
POST /me/children/{child_id}/reservations/{reservation_id}/status
Annule la réservation d'un enfant.
Permissions : reservation.cancel
En-tête : Idempotency-Key (obligatoire)
{
"status": "cancelled",
"reason": "Enfant absent"
}
status doit valoir "cancelled", sinon 400.
Réponse (200) : { "reservation": {...} }
Tickets de support
GET /me/tickets
Tickets créés par l'utilisateur.
Permissions : ticket.read
| Param | Type | Défaut | Description |
|---|---|---|---|
status | string | — | Filtrer par statut |
limit | integer | 20 | Max 100 |
offset | integer | 0 | Décalage |
Réponse (200) : { items: [Ticket], total }
POST /me/tickets
Crée un ticket.
Permissions : ticket.create
{
"title": "Problème de rechargement",
"description": "Ma carte n'a pas été créditée."
}
Le ticket est créé avec priority = "medium" et category = "other". La description devient le premier message.
Réponse (201) : { "message": "Ticket créé", "ticket": {...} }
GET /me/tickets/{id}
Détail d'un ticket et ses messages.
Permissions : ticket.read + propriété du ticket
Réponse (200) : { "ticket": {...}, "messages": [TicketMessage] }
POST /me/tickets/{id}/messages
Ajoute un message à un ticket.
Permissions : ticket.create + propriété du ticket
{
"content": "Des nouvelles ?"
}
Réponse (200) : { "message": "Message ajouté", "msg": {...} }
Préférences de notification
GET /me/notification-preferences
Permissions : notification.read
Cet endpoint est un stub : il retourne toujours un objet vide.
{ "notification_preferences": {} }
PUT /me/notification-preferences
Met à jour les préférences de notification.
Permissions : notification.update
{
"notification_preferences": {
"email": true,
"sms": false
}
}
Réponse (200) : { "message": "Préférences mises à jour" }
POST /me/notifications
Envoie un message au support.
Permissions : notification.create
{
"subject": "Question sur ma facture",
"body": "Bonjour, ..."
}
Réponse (200) : { "message": "Message envoyé" }