Notes de frais et titres restaurant

Deux lectures qu'une intégration financière consomme ensemble : ce que les salariés ont demandé en remboursement (lignes de frais) et combien de titres restaurant chacun a acquis (décomptes).

Ni l'une ni l'autre ne retire quoi que ce soit. Il n'y a aucun bloc restricted sur ces deux lectures — un champ manquant y est donc un défaut, pas un refus, et mérite d'être signalé comme tel.

Lignes de frais

GET /api/v1/client/expense-reports (scopes : expenses:read)

{
  "items": [
    {
      "id": "eV7dMJ",
      "requestId": "ePlQXN",
      "employeeId": "GNnBNO",
      "companyId": "1VaKPa",
      "functionalNumber": "NDF-2026-0042",
      "amount": 42.50,
      "currency": "EUR",
      "isForeignExpense": false,
      "expenseDate": "2026-03-12",
      "createdOn": "<generated>",
      "natureCode": "TRANSPORT",
      "natureName": "Transport",
      "status": "Completed"
    },
    {
      "id": "0V6Y0N",
      "requestId": "ePlQXN",
      "employeeId": "GNnBNO",
      "companyId": "1VaKPa",
      "functionalNumber": "NDF-2026-0042",
      "amount": 180,
      "currency": "GBP",
      "isForeignExpense": true,
      "expenseDate": "2026-03-13",
      "createdOn": "<generated>",
      "natureCode": "HEBERGEMENT",
      "natureName": "Hebergement",
      "status": "Completed"
    }
  ],
  "nextCursor": "qq9Ygc1ab"
}
Paramètre Ce qu'il fait
from, to Dates ISO filtrant la date de dépense par inclusion.
establishmentId Restreint la page à UN établissement de votre périmètre. Omis, elle les lit tous.
cursor, limit Pagination. Renvoyez nextCursor ; n'arrêtez que lorsqu'il vaut null.

Le chemin dit expense-reports ; la lecture sert des lignes de frais. Une entrée, c'est une dépense — un salarié, un jour, une nature, un montant — pas une note entière. Les lignes sortent de la date de dépense la plus ancienne à la plus récente.

Il n'y a pas de total de note, et il ne peut pas y en avoir

Le montant vit sur la ligne, avec sa propre currency, et une même note peut en mêler deux — un taxi en euros et un hôtel en livres sur la même demande, ce que montre précisément l'exemple ci-dessus.

Un total au niveau de la note serait donc une somme de devises différentes : un nombre faux qui a l'air juste. Groupez sur requestId pour regrouper les lignes d'une note, puis totalisez vous-même par devise.

amount ne veut rien dire sans currency. Les deux sont toujours servis ensemble. N'additionnez jamais des montants sans lire la devise, ne rapportez jamais un total sans dire en quelle devise il est, et ne convertissez jamais de vous-même : vous ne connaissez pas le taux auquel le client comptabilise.

isForeignExpense dit que le salarié a déclaré la dépense comme engagée à l'étranger. C'est ce qui vous indique qu'une ligne dans une autre devise est attendue plutôt qu'une erreur de saisie.

Deux identifiants, deux usages

Champ À utiliser pour
requestId Regrouper les lignes d'une note.
functionalNumber Parler d'une note — c'est le numéro lisible imprimé sur les écrans que lit votre client.

Citez le numéro fonctionnel à un utilisateur ; groupez sur requestId.

Deux dates, deux usages

expenseDate est le jour où la dépense a été engagée. createdOn est le moment où la ligne a été saisie, ce qui peut être des semaines plus tard. Rapprochez sur expenseDate, interrogez sur createdOn.

Aucun texte libre n'est servi, par conception

La note, la ligne, le paiement et chaque changement de statut portent tous un commentaire dans Staff & Go, et aucun ne traverse. Ils sont saisis par des salariés, non relus, et peuvent nommer un tiers ou expliquer un déplacement médical.

Ne les demandez pas, et n'inférez pas une justification qui ne vous a pas été donnée. Aucune identité interne ne traverse non plus — qui a créé la note, qui l'a payée.

status est celui de la note, répété sur chaque ligne

ActionPending, ActionTerminated, Completed, ActionFailed, Aborted. Les lignes d'une même note sont soumises, approuvées et payées ensemble : elles portent donc le même code — ce n'est pas un état par ligne.

Les brouillons non soumis ne sont jamais servis. Un brouillon est l'intention non envoyée d'un salarié : rien de ce que vous recevez ici n'est une demande qui n'a pas été déposée.

Décomptes de titres restaurant

GET /api/v1/client/meal-voucher-counts (scopes : meal-vouchers:read)

{
  "items": [
    {
      "id": "YJb51V",
      "employeeId": "GNnBNO",
      "companyId": "1VaKPa",
      "periodFrom": "2026-03-01",
      "periodTo": "2026-03-31",
      "vouchersCount": 19,
      "status": "Validated"
    },
    {
      "id": "OVD2pP",
      "employeeId": "rPX1No",
      "companyId": "1VaKPa",
      "periodFrom": "2026-03-01",
      "periodTo": "2026-03-31",
      "vouchersCount": 0,
      "status": "Aborted"
    }
  ],
  "nextCursor": "gx2YbiGpG"
}
Paramètre Ce qu'il fait
from, to Dates ISO filtrant la période par recouvrement.
establishmentId Restreint la page à UN établissement de votre périmètre. Omis, elle les lit tous.
cursor, limit Pagination. Renvoyez nextCursor ; n'arrêtez que lorsqu'il vaut null.

Une entrée, c'est un salarié pour une période calculée : combien de titres il a acquis. C'est le nombre sur lequel un émetteur de titres passe commande. Les décomptes sortent de la période la plus ancienne à la plus récente.

La fenêtre filtre par recouvrement — contrairement aux lignes de frais juste au-dessus, et contrairement au temps travaillé. Une période de calcul est un intervalle, et une période allant du 26 au 25 appartient aux deux mois. Commander sur une frontière de mois sans en tenir compte fait manquer un calcul.

status est celui du salarié, pas celui du lot

Un calcul peut être transmis alors qu'un salarié en a été écarté. Commandez donc sur les lignes dont le statut propre dit qu'elles sont arrêtées — Validated ou Transmitted — plutôt que sur tout ce qu'une période renvoie.

L'ensemble complet est Created, InTreatment, InProgress, InTransmission, Validated, Transmitted, Treated, InError, InTransmissionError et Aborted.

L'exemple ci-dessus montre le piège directement : deux salariés, une période, un Validated à 19 titres et un Aborted à 0. Commander 19 est juste ; commander 19 et traiter la seconde ligne comme un vrai zéro ne l'est pas.

vouchersCount est un résultat, pas un calcul détaillé

Staff & Go le calcule à partir de quatre coefficients — la dotation, un ajustement, et ce que les absences et les frais ont retiré — et aucun n'est servi. Il n'y a rien à recalculer ici, et rien qui totaliserait un nombre différent.

periodFrom et periodTo sont la fenêtre du calcul : tous les salariés d'une même période portent donc la même. Ce ne sont pas des dates par salarié et elles ne disent rien de la présence de ce salarié.

Le salarié n'est désigné que par employeeId — ni nom, ni matricule, ni fonction. Résolvez-le avec la lecture des salariés s'il vous faut afficher une personne.

Cette lecture ne commande rien et n'émet rien. Elle rapporte ce que Staff & Go a calculé.

Quand la page est plus courte

Un établissement auquel le module notes de frais ou titres restaurant manque est absent de ces lectures sans être nommé, et la réponse le dit par le bloc partial — voir Quand une liste est plus courte que votre mandat dans Découvrir ce que vous pouvez appeler.

Aucune des deux lectures n'offre de filtre modifiedSince : aucune colonne maintenue et indexée ne le porte. Relisez la fenêtre à la place. Une ligne qui disparaît entre deux lectures est absente, pas supprimée — il n'y a ni flux de delta ni pierre tombale.