account/docs/api.md
GnomeZworc 8a11a1d5ea
add pending path
Signed-off-by: GnomeZworc <nicolas.boufidjeline@g3e.fr>
2026-06-14 22:29:35 +02:00

13 KiB

API Reference

Base URL : http://localhost:8080

Toutes les réponses sont en application/json. Les erreurs retournent {"error": "message"}.


Authentification

Toutes les routes (sauf GET /health) requièrent le header :

X-Owner-ID: <integer>

En dev, c'est l'ID numérique de l'owner. Les comptes, transactions et snapshots sont strictement filtrés par owner — un owner ne peut ni voir ni modifier les ressources d'un autre.

Réponse 401 — header absent ou invalide

{ "error": "missing X-Owner-ID header" }

À remplacer par JWT en production.


Health

GET /health

Vérifie la disponibilité du serveur et de la base de données.

Réponse 200

{ "status": "ok" }

Réponse 503 — base indisponible


Instruments

Un instrument représente tout actif coté : devise (EUR), action, ETF, crypto. Le prix EUR vaut toujours 1 et est inséré automatiquement au démarrage.

GET /instruments

Liste tous les instruments.

Réponse 200

[
  { "id": 1, "type": "devise", "code": "EUR", "name": "Euro", "devise_cotation": "EUR" },
  { "id": 2, "type": "etf",    "code": "LU1681043599", "name": "Amundi MSCI World", "devise_cotation": "EUR" }
]

GET /instruments/{id}

Réponse 200

{ "id": 2, "type": "etf", "code": "LU1681043599", "name": "Amundi MSCI World", "devise_cotation": "EUR" }

Réponse 404 — instrument introuvable


POST /instruments

Corps

Champ Type Requis Description
type string devise, action, etf, crypto
code string ISIN (actions/ETF), ticker (crypto), code devise
name string Nom lisible
devise_cotation string Devise de cotation (défaut : EUR)

Réponse 201

{ "id": 3, "type": "crypto", "code": "BTC", "name": "Bitcoin", "devise_cotation": "EUR" }

Pipeline de prix : le ticker Yahoo Finance (actions/ETF) est résolu automatiquement via OpenFIGI au prochain cycle. L'ID CoinGecko (crypto) est résolu via l'API search CoinGecko. Les résolutions sont mises en cache dans instrument_ticker_cache.


PUT /instruments/{id}

Même corps que POST. Retourne l'instrument mis à jour.


DELETE /instruments/{id}

Réponse 204 — supprimé


Comptes

Un compte est un conteneur de positions. Son solde est entièrement dérivé des transactions (aucun solde stocké).

Les enveloppes sont des sous-comptes monétaires liés à un compte maître (voir section Enveloppes). GET /accounts/{id} retourne toujours le compte avec sa liste d'enveloppes.

GET /accounts

Liste les comptes maîtres (sans les enveloppes).

Réponse 200

[
  {
    "id": 1,
    "nom": "Livret A",
    "type": "livret",
    "devise_reference": "EUR",
    "plafond": 22950
  }
]

GET /accounts/{id}

Retourne le compte et ses enveloppes.

Réponse 200

{
  "id": 1,
  "nom": "Livret A",
  "type": "livret",
  "devise_reference": "EUR",
  "plafond": 22950,
  "envelopes": [
    {
      "id": 3,
      "nom": "Vacances",
      "type": "livret",
      "devise_reference": "EUR",
      "master_account_id": 1,
      "objectif": "Road trip USA"
    }
  ]
}

Réponse 404 — compte introuvable


POST /accounts

Crée un compte maître.

Corps

Champ Type Requis Description
nom string Nom du compte
type string courant, livret, pea, cto, crypto, ...
devise_reference string Devise de référence (défaut : EUR)
plafond number Plafond réglementaire (indicatif)

Réponse 201

{ "id": 1, "nom": "Livret A", "type": "livret", "devise_reference": "EUR", "plafond": 22950 }

PUT /accounts/{id}

Met à jour un compte maître. Même corps que POST.


DELETE /accounts/{id}

Supprime le compte et toutes ses enveloppes (CASCADE).

Réponse 204


Enveloppes

Une enveloppe est un sous-compte monétaire rattaché à un compte maître. Elle hérite automatiquement du type et de la devise_reference de son maître. Le solde est dérivé des transactions, comme pour tout compte.

Règles :

  • Un compte maître ne peut pas lui-même être une enveloppe (pas de chaînage)
  • Supprimée automatiquement avec son compte maître

GET /accounts/{id}/envelopes

Liste les enveloppes d'un compte.

Réponse 200

[
  {
    "id": 3,
    "nom": "Vacances",
    "type": "livret",
    "devise_reference": "EUR",
    "master_account_id": 1,
    "objectif": "Road trip USA"
  }
]

POST /accounts/{id}/envelopes

Crée une enveloppe sous le compte {id}.

Corps

Champ Type Requis Description
nom string Nom de l'enveloppe
objectif string Description libre de l'objectif

Réponse 201

{
  "id": 3,
  "nom": "Vacances",
  "type": "livret",
  "devise_reference": "EUR",
  "master_account_id": 1,
  "objectif": "Road trip USA"
}

Réponse 400 — le compte est lui-même une enveloppe (chaînage interdit) Réponse 404 — compte introuvable


PUT /envelopes/{id}

Met à jour le nom et/ou l'objectif d'une enveloppe.

Corps

Champ Type Requis Description
nom string Nouveau nom
objectif string Nouvel objectif

Réponse 200 — enveloppe mise à jour Réponse 404 — enveloppe introuvable


DELETE /envelopes/{id}

Supprime l'enveloppe.

Réponse 204


Transactions

Une transaction est un échange atomique entre deux participants (comptes ou enveloppes) via des instruments. Chaque côté (source, dest) est soit entièrement renseigné soit entièrement null. Au moins un côté doit exister.

Cas couverts :

Cas Source Dest
Flux entrant (salaire, dépôt) null compte + instrument + quantité
Flux sortant (dépense) compte + instrument + quantité null
Virement / allocation enveloppe compte + instrument + quantité compte + instrument + quantité
Achat de titres compte, EUR, montant compte, ETF, nb parts
Swap crypto wallet, BTC, qté wallet, ETH, qté

Le champ validated indique si la transaction est réelle (true) ou prévisionnelle (false). Les transactions non validées à date dépassée remontent dans ?pending=true (liste "à traiter").


GET /accounts/{id}/transactions

Vue centrée sur le compte : le montant est signé (positif = crédit, négatif = débit). instrument_id est celui du côté du compte concerné. contrepartie_account_id est le compte en face (null si flux externe).

Paramètres de filtre

Paramètre Type Description
validated boolean true ou false
pending boolean true → non validées avec date ≤ aujourd'hui
from string Date de début YYYY-MM-DD
to string Date de fin YYYY-MM-DD

Réponse 200 — triée par date DESC

[
  {
    "id": 1,
    "date": "2026-06-13",
    "montant": 2800.00,
    "instrument_id": 1,
    "tiers": "Employeur",
    "label": "Salaire juin",
    "categorie": "salaire",
    "validated": true
  },
  {
    "id": 2,
    "date": "2026-06-10",
    "montant": -50.00,
    "instrument_id": 1,
    "label": "Courses",
    "categorie": "alimentation",
    "validated": true
  }
]

GET /transactions/{id}

Retourne la transaction brute (tous les champs source/dest).

Réponse 200

{
  "id": 1,
  "date": "2026-06-13",
  "account_dest_id": 1,
  "instrument_dest_id": 1,
  "quantite_dest": 2800,
  "tiers": "Employeur",
  "label": "Salaire juin",
  "categorie": "salaire",
  "validated": true
}

Réponse 404 — introuvable


POST /transactions

Corps

Champ Type Requis Description
date string YYYY-MM-DD
label string Libellé
validated boolean Défaut false
account_source_id integer Compte source
instrument_source_id integer Instrument source
quantite_source number Quantité source
account_dest_id integer Compte dest
instrument_dest_id integer Instrument dest
quantite_dest number Quantité dest
tiers string Tiers externe (employeur, commerçant…)
categorie string Catégorie libre

Les trois champs de chaque côté (account, instrument, quantite) doivent être tous renseignés ou tous null.

Réponse 201 — transaction créée (format brut) Réponse 400 — body invalide, label manquant, date manquante, ou violation de la contrainte source/dest


PUT /transactions/{id}

Mise à jour complète. Même corps que POST.

Réponse 200 — transaction mise à jour (format brut) Réponse 404 — introuvable


PATCH /transactions/{id}/validate

Valide ou dé-valide une transaction.

Corps

{ "validated": true }

Réponse 200 — transaction avec le nouveau statut Réponse 404 — introuvable


DELETE /transactions/{id}

Réponse 204


Snapshots

Les snapshots capturent la valorisation de chaque compte sur une fenêtre glissante :

  • Passé : transactions validées uniquement
  • Futur : toutes les transactions (validées ou non) — projection basée sur les transactions planifiées

Deux tables sont alimentées :

  • position_snapshot — quantité + valeur par instrument et par compte
  • account_snapshot — valeur totale agrégée par compte

Fenêtre : de la première transaction jusqu'à today + SNAPSHOT_HORIZON_DAYS (défaut : 30 jours). Configurable via la variable d'environnement SNAPSHOT_HORIZON_DAYS.

Toutes les transactions sont comptées quelle que soit leur validation. Le snapshot représente toujours l'état envisagé complet du compte : transactions confirmées (validated = true) et planifiées (validated = false). La liste ?pending=true (transactions non validées à date dépassée) reste distincte — c'est un outil de suivi, pas un filtre de calcul.

Job daily-snapshot (toutes les 24h) :

  1. Traite les invalidations en attente
  2. Recalcule hier (consolide les transactions de la veille)
  3. Calcule le nouveau jour entrant dans la fenêtre (today + horizon)

GET /accounts/{id}/snapshots

Liste la valorisation totale du compte jour par jour.

Paramètres de filtre

Paramètre Type Description
from string Date de début YYYY-MM-DD (optionnel, défaut : première date disponible)
to string Date de fin YYYY-MM-DD (optionnel, défaut : dernier jour calculé dans la fenêtre)

Réponse 200 — triée par date ASC

[
  { "date": "2026-06-01", "valeur": 2750.00 },
  { "date": "2026-06-02", "valeur": 2800.00 },
  { "date": "2026-07-13", "valeur": 2950.00 }
]

GET /accounts/{id}/snapshots/positions

Liste les positions détaillées (par instrument) du compte jour par jour.

Paramètres de filtre — mêmes que /snapshots (from, to)

Réponse 200 — triée par date ASC puis instrument_id

[
  {
    "date": "2026-06-01",
    "instrument_id": 1,
    "quantite": 2750.00,
    "prix_cloture": 1.0,
    "valeur": 2750.00
  },
  {
    "date": "2026-06-01",
    "instrument_id": 2,
    "quantite": 5.0,
    "pru": 350.00,
    "prix_cloture": 360.00,
    "valeur": 1800.00
  }
]

GET /snapshots/pending

Liste tous les comptes de l'owner ayant une invalidation en attente (i.e. snapshots non à jour suite à une mutation de transaction).

Utile pour savoir quels comptes doivent être recalculés avant de consulter leurs snapshots, ou pour déclencher un recompute ciblé.

Réponse 200 — liste vide si tout est à jour

[
  { "account_id": 1, "recompute_from": "2026-06-10" },
  { "account_id": 3, "recompute_from": "2026-05-01" }
]
Champ Description
account_id Identifiant du compte à recalculer
recompute_from Date la plus ancienne depuis laquelle les snapshots sont invalides

Les invalidations sont insérées automatiquement à chaque create / update / delete / validate de transaction. Le job daily-snapshot les consomme toutes les 24h ; cet endpoint permet de les inspecter sans attendre.


POST /accounts/{id}/snapshots/recompute

Recalcule immédiatement les snapshots d'un compte depuis sa date d'invalidation jusqu'à today + horizon.

Chaque mutation de transaction (create, update, delete, validate/dévalider) marque automatiquement les comptes concernés comme dirty avec recompute_from = MIN(date_existante, date_transaction). Cet endpoint consomme ce flag sans attendre le job nocturne.

Réponse 200 — recalcul effectué

{ "account_id": 1, "from": "2026-06-01", "to": "2026-07-13", "status": "ok" }

Réponse 204 — aucune invalidation en attente, rien à faire Réponse 404 — compte introuvable