Proposition API REST SI Paiement
Proposition d'API REST avec naming anglais plus clair et schema unifie
Cette page propose une version plus REST de l'API actuelle Dépot / Retrait, avec un vocabulaire anglais plus clair, des routes homogènes et un schéma unifié.
Constats sur l'existant
- La ressource métier est dupliquée entre
deposit-requestsetwithdrawal-requests, alors que le cycle de vie est le même. - Plusieurs noms sont ambigus pour un consommateur externe :
externalId,payableId,requestPartnerId,partnerBillId. - La route de mise à jour sert uniquement à annuler une demande via
PATCH { "status": "CANCELED" }. - Certains champs mélangent format technique et métier :
amountInCents,serviceFeesInCents,authorizationIdconcaténé. - Les timestamps ne suivent pas une convention unique :
creationDate,expirationDate,processingDateTime,sentDate. - Les payloads exposent des codes internes peu lisibles comme
CSHetCBA.
Principes de design retenus
- Une seule ressource métier :
cash-requests - URLs en
kebab-case, payloads JSON encamelCase - Noms de ressources au pluriel
- Timestamps normalisés avec le suffixe
At - Références partenaire explicites avec le suffixe
Reference - Montants regroupés dans un objet
amount - Identifiants techniques séparés des identifiants métier
Resource model propose
La ressource principale devient une demande de mouvement d'especes :
DEPOSITpour un depot d'especesWITHDRAWALpour un retrait d'especes
Cette approche évite d'avoir deux familles d'endpoints presque identiques.
Routes proposees
API FDJ Services exposee au partenaire
| Method | Route | Usage |
|---|---|---|
POST | /v2/partners/{partnerId}/products/{productId}/cash-requests | Creer une demande de depot ou de retrait |
GET | /v2/partners/{partnerId}/products/{productId}/cash-requests | Lister les demandes |
GET | /v2/partners/{partnerId}/products/{productId}/cash-requests/{cashRequestId} | Consulter une demande |
DELETE | /v2/partners/{partnerId}/products/{productId}/cash-requests/{cashRequestId} | Annuler une demande |
API partenaire exposee a FDJ Services
| Method | Route | Usage |
|---|---|---|
POST | /v1/cash-authorizations | Valider la faisabilite d'une operation avant passage en point de vente |
POST | /v1/webhooks/cash-transactions | Recevoir la notification de transaction finalisee |
Pourquoi ces routes sont plus REST
cash-requestsrepresente une vraie ressource metier persistante.POSTcree une demande.GETliste ou retourne une ressource.DELETEannule la demande au lieu d'utiliser unPATCHuniquement pour changer le statut.- Le type d'operation est dans le payload, pas dans le nom de la route.
Schema propose
Create cash request
{
"partnerReference": "f7c78c0c-bf7b-4ec2-8a8e-acde52431111",
"operationType": "DEPOSIT",
"amount": {
"value": 25000,
"currency": "EUR"
},
"customer": {
"partnerCustomerReference": "customer_001",
"type": "INDIVIDUAL",
"firstName": "Jeanne",
"lastName": "Martin",
"birthDate": "1998-07-12",
"birthCity": "Paris",
"countryOfResidence": "FR"
}
}Cash request response
{
"id": "7dc272f2-b383-4d95-bbac-3b8db23d2c0d",
"partnerId": "123",
"productId": "45",
"partnerReference": "f7c78c0c-bf7b-4ec2-8a8e-acde52431111",
"operationType": "DEPOSIT",
"status": "PENDING",
"amount": {
"value": 25000,
"currency": "EUR"
},
"fee": {
"value": 0,
"currency": "EUR"
},
"customer": {
"partnerCustomerReference": "customer_001"
},
"qrCode": {
"format": "EMVCO",
"content": "000201010212..."
},
"createdAt": "2026-01-19T14:08:34.043Z",
"expiresAt": "2026-01-19T15:08:34.032Z"
}List cash requests response
{
"items": [
{
"id": "7dc272f2-b383-4d95-bbac-3b8db23d2c0d",
"partnerReference": "f7c78c0c-bf7b-4ec2-8a8e-acde52431111",
"operationType": "DEPOSIT",
"status": "PENDING",
"amount": {
"value": 25000,
"currency": "EUR"
},
"createdAt": "2026-01-19T14:08:34.043Z",
"expiresAt": "2026-01-19T15:08:34.032Z"
}
],
"nextCursor": "YXJyYXljb25uZWN0aW9uOjE5"
}Filtres recommandes pour le listing
| Query param | Type | Description |
|---|---|---|
cursor | string | Curseur de pagination |
limit | number | Nombre maximum d'elements |
partnerReference | string | Reference metier du partenaire |
operationType | string | DEPOSIT ou WITHDRAWAL |
status | string | PENDING, COMPLETED, CANCELLED, EXPIRED |
createdFrom | string | Date ISO 8601 de debut |
createdTo | string | Date ISO 8601 de fin |
Customer schema recommande
Individual customer
{
"partnerCustomerReference": "customer_001",
"type": "INDIVIDUAL",
"firstName": "Jeanne",
"lastName": "Martin",
"birthDate": "1998-07-12",
"birthCity": "Paris",
"countryOfResidence": "FR"
}Business customer
{
"partnerCustomerReference": "company_001",
"type": "BUSINESS",
"legalName": "ACME SAS",
"registrationNumber": "123456789",
"countryOfResidence": "FR"
}Authorization callback propose
Au lieu d'un endpoint generique et peu structure, la recommandation est de creer une ressource d'autorisation.
Request
POST /v1/cash-authorizations
{
"cashRequestId": "7dc272f2-b383-4d95-bbac-3b8db23d2c0d",
"partnerReference": "f7c78c0c-bf7b-4ec2-8a8e-acde52431111",
"operationType": "DEPOSIT",
"amount": {
"value": 25000,
"currency": "EUR"
},
"customer": {
"partnerCustomerReference": "customer_001"
},
"expiresAt": "2026-01-19T15:08:34.032Z"
}Response
{
"authorizationId": "0c9aabf7-f380-4ad7-a3fd-5e18f9365e30",
"status": "APPROVED",
"approvedAt": "2026-01-19T14:09:01.000Z",
"expiresAt": "2026-01-19T15:08:34.032Z"
}Recommendation de comportement
201 Createdsi l'autorisation est accordee409 Conflictsi l'operation n'est pas autorisee dans l'etat courant422 Unprocessable Entitysi une regle metier refuse l'operation
Webhook event propose
Le webhook actuel peut etre rendu plus lisible avec un event envelope stable et un objet metier explicite.
Route recommandee
POST /v1/webhooks/cash-transactions
Payload
{
"eventId": "5fed0137-a5d7-4ad2-a822-6ae4d768fa8f",
"eventType": "cash-transaction.completed",
"occurredAt": "2026-01-19T15:08:34.032Z",
"deliveredAt": "2026-01-19T15:08:36.000Z",
"data": {
"transactionId": "8ffea5f0-8796-4d12-a9fd-eb14c55dbfdb",
"cashRequestId": "7dc272f2-b383-4d95-bbac-3b8db23d2c0d",
"partnerId": "123",
"productId": "45",
"partnerReference": "f7c78c0c-bf7b-4ec2-8a8e-acde52431111",
"partnerCustomerReference": "customer_001",
"operationType": "DEPOSIT",
"amount": {
"value": 25000,
"currency": "EUR"
},
"fee": {
"value": 0,
"currency": "EUR"
},
"paymentMethod": "CASH",
"pointOfSaleId": "2f4fc4ee-d166-47e9-8e8c-1c0e8ed2d26a",
"processedAt": "2026-01-19T15:08:34.032Z",
"expectedSettlementAt": "2026-01-20T00:00:00.000Z",
"metadata": {}
}
}Mapping recommande entre l'existant et la proposition
| Existant | Proposition |
|---|---|
datamatrixPartnerId | partnerId |
datamatrixProductId | productId |
payableId | cashRequestId |
externalId | partnerReference |
customer.externalId | customer.partnerCustomerReference |
requestPartnerId | partnerReference |
customerExternalId | customer.partnerCustomerReference |
creationDate | createdAt |
expirationDate | expiresAt |
processingDateTime | processedAt |
sentDate | deliveredAt |
serviceFeesInCents | fee.value |
partnerBillId | partnerReference |
partnerCustomerId | partnerCustomerReference |
freeFields | metadata |
paymentMethod: CSH | paymentMethod: CASH |
paymentMethod: CBA | paymentMethod: CARD |
Points de schema a corriger en priorite
1. Ne plus concatener plusieurs identifiants dans authorizationId
Au lieu de :
{
"authorizationId": "serviceRequestId/qrCodeId"
}Utiliser :
{
"authorizationId": "0c9aabf7-f380-4ad7-a3fd-5e18f9365e30",
"serviceRequestId": "6d0e6a82-6d69-4f6d-9942-54bca4f2206d",
"qrCodeId": "a2c1d77b-b60f-4a52-8a1e-2bbeb2f0963b"
}2. Normaliser les montants
Au lieu de dupliquer amountInCents et serviceFeesInCents, utiliser un modele commun :
{
"amount": {
"value": 25000,
"currency": "EUR"
},
"fee": {
"value": 0,
"currency": "EUR"
}
}3. Homogeneiser les statuts
Statuts recommandes :
PENDINGCOMPLETEDCANCELLEDEXPIRED
4. Clarifier les codes d'erreur
Exemples de renommage :
| Existant | Proposition |
|---|---|
UNKNOWN_PAYABLE | CASH_REQUEST_NOT_FOUND |
BILL_ALREADY_PAID | REQUEST_ALREADY_COMPLETED |
PAYMENT_IN_PROGRESS | REQUEST_PROCESSING |
MAX_BILL_AMOUNT_KO | AMOUNT_ABOVE_MAXIMUM |
MIN_BILL_AMOUNT_KO | AMOUNT_BELOW_MINIMUM |
PAYER_ACCOUNT_KO | INVALID_CUSTOMER_ACCOUNT |
5. Uniformiser le format d'erreur
{
"error": {
"code": "REQUEST_ALREADY_COMPLETED",
"message": "The cash request has already been completed.",
"details": {},
"requestId": "0994b43f-1dbf-4f76-9d91-41f9f25cf5a6"
}
}Strategie de migration recommandee
- Conserver l'API actuelle en
/v1 - Exposer la nouvelle version en
/v2 - Garder le meme moteur metier cote back-end
- Mapper les anciens noms vers le nouveau contrat au niveau d'adaptation
- Deprecier ensuite les routes
deposit-requestsetwithdrawal-requests
Recommandation finale
Si l'objectif est d'ameliorer la lisibilite sans changer le metier, la meilleure evolution est :
- unifier
depositetwithdrawaldanscash-requests - renommer les identifiants avec un vocabulaire metier explicite
- remplacer l'annulation par
DELETE - normaliser les montants, timestamps, statuts et erreurs
Cette proposition reste proche de l'existant, donc elle limite le cout de migration tout en rendant l'API beaucoup plus claire pour une equipe externe.