Passer au contenu principal

API Era

Découvre les points de terminaison disponibles, les en-têtes d'authentification, la pagination et les limites de l'API Era.

Dernière mise à jour : 29 septembre 2026

Encore en bêta

Ces points de terminaison fonctionnent dès aujourd'hui, mais l'API continue d'évoluer, alors certains détails peuvent changer. Consulte la date de dernière mise à jour en haut de la page pour savoir quand elle a été révisée pour la dernière fois.

Démarrage rapide

Avant de commencer, il te faut un compte Era avec au moins une institution branchée — sans connexion, ces points de terminaison n'ont rien à retourner.

  1. 1

    Connecte-toi à Era et branche une institution, si ce n'est pas déjà fait.

  2. 2

    Ouvre tes clés d'API dans le tableau de bord et crée une clé. Toutes les portées sont cochées au départ, alors décoche celles dont tu n'as pas besoin : pour ces points de terminaison, il reste banking:read. Tu choisis aussi une expiration ; il n'y a pas d'option « jamais ».

  3. 3

    Copie la clé. Elle s'affiche une seule fois, et on ne peut pas la réafficher. Copie-la et conserve-la en lieu sûr, par exemple dans un gestionnaire de secrets. Si tu perds une clé, tu ne peux plus la consulter. Crée-en une nouvelle à la place.

  4. 4

    Envoie-la dans un en-tête avec ta requête.

cURL
curl "https://forge.era.app/api/banking/transactions?page=1&pageSize=20" \
  -H "X-API-Key: fmk_your_key_here"
Réponse · 200
{
  "transactions": [ … ],
  "pagination": {
    "currentPage": 1,
    "pageSize": 20,
    "totalItems": 412,
    "totalPages": 21
  },
  "historyWindowApplied": true,
  "historyWindowFloorDate": "2026-06-28",
  "historyWindowHiddenCount": 137,
  "historyWindowEarliestDate": "2024-03-02",
  "historyWindowDegraded": false
}

API disponibles

L'API Era comprend les API suivantes :

Authentification

Envoie ta clé de l'une de ces deux façons :

Méthodes d'authentification
En-tête
X-API-Key: fmk_your_key_here
Jeton bearer
Authorization: Bearer fmk_your_key_here

Chaque requête est chiffrée avec TLS.

Les clés expirent, et tu choisis dans combien de temps à la création. Le maximum est de 90 jours sur le forfait gratuit et de 365 sur un forfait payant — il n'existe pas d'option « n'expire jamais », alors ce que tu bâtis là-dessus a besoin d'un plan pour faire tourner la clé avant qu'elle tombe.

En-têtes de réponse

Un ID de requête revient sur chaque réponse. Les en-têtes de limite reviennent sur les appels qu'Era a mesurés par rapport à un budget quotidien, et sur un 429 seulement quand ce budget quotidien a refusé l'appel : un 429 du plafond de rafale par minute ne porte que Retry-After. Pour l'instant, seul le forfait gratuit a un budget quotidien. Si Era ne peut pas mesurer ton usage, l'appel est servi sans aucun de ces en-têtes.

En-têtes de réponse
fly-request-id
Un identifiant unique pour la requête. Indique-le quand tu contactes le support à propos d'une requête précise — voir ID de requête
X-RateLimit-Limit
Le budget quotidien de ton forfait. Envoyé uniquement sur les forfaits qui ont un budget quotidien, et jamais sur un 429 du plafond de rafale par minute.
X-RateLimit-Remaining
Ce qu'il reste de ton budget quotidien. Jamais en dessous de zéro. Envoyé uniquement sur les forfaits qui ont un budget quotidien, et jamais sur un 429 du plafond de rafale par minute.
X-RateLimit-Reset
Quand ton budget quotidien libère sa prochaine requête, une seule, en horodatage Unix en secondes. Ce n'est pas le moment où tout le budget se renouvelle : le budget roule, donc les requêtes reviennent une à une. Envoyé uniquement sur les forfaits qui ont un budget quotidien, et jamais sur un 429 du plafond de rafale par minute. Le plafond de rafale par minute n'a pas d'en-tête à lui. Voir Limites
Retry-Afterseulement sur un 429
Le nombre de secondes à attendre avant de réessayer, selon la limite qui a refusé la requête. Un 429 qui porte aussi X-RateLimit-* a été refusé par le budget quotidien ; sans eux, par le plafond de rafale par minute. Voir Limites

Erreurs

L'API renvoie ces codes de statut d'erreur :

  • 400

    Entrée invalide : un paramètre incorrect, une mise à jour groupée vide ou de plus de 100 éléments, ou une écriture qui définit et efface le même champ dans le même appel.

  • 401

    Pas de clé, ou une clé qui ne s'analyse pas. Envoie-la dans l'en-tête X-API-Key ou comme jeton bearer.

  • 402

    Un quota de forfait fait obstacle — aujourd'hui, ça ne concerne que la création de catégories. Il s'agit de ce que tu crées, pas de la vitesse à laquelle tu appelles : attendre n'y change rien, un forfait supérieur oui. Appeler trop vite, c'est un 429.

  • 403

    La clé ne porte pas la portée dont cet appel a besoin — ou, sur l'une des deux écritures de transactions, l'id appartient à quelqu'un d'autre ou n'existe pas. L'API ne distingue pas ces deux cas.

  • 404

    Un compte qui n'existe pas. Seul l'endpoint de solde le renvoie : un accountGroupKey qui ne désigne aucun compte, ou qui n'a même pas la forme d'une clé, revient en 404 sans corps. Les transactions ne renvoient jamais 404 — voir 403.

  • 409

    Autre chose a modifié la ligne pendant que tu écrivais. Relis-la et renvoie ton écriture.

  • 429

    Trop de requêtes. Tu as atteint le plafond de rafale par minute ou, sur le forfait gratuit, épuisé ton budget quotidien. Un 429 avec les en-têtes X-RateLimit-* vient du budget quotidien, et un 429 sans eux, du plafond de rafale. Retry-After indique combien de temps attendre et, contrairement à un 402, attendre libère ta prochaine requête. Voir Limites pour les chiffres par forfait.

Formes d'erreur

La plupart des erreurs reviennent sous la même forme : statusCode, message et un objet errors qui nomme ce qui n'allait pas. Pas toutes : un 401 et un 404 reviennent sans corps du tout, alors lis le statut avant de lire le corps.

Exemple
{
  "statusCode": 403,
  "message": "One or more errors occurred!",
  "errors": {
    "generalErrors": ["Transaction does not belong to the authenticated user"]
  }
}

ID de requête

Chaque réponse porte un en-tête fly-request-id. Indique-le quand tu contactes le support à propos d'une requête précise.

cURL
# Print the response headers, including fly-request-id; discard the body
curl -sS -D - -o /dev/null "https://forge.era.app/api/banking/transactions?page=1&pageSize=20" \
  -H "X-API-Key: fmk_your_key_here"
cURL (écriture)
# A write call: same header, plus a JSON body
curl -sS -D - -X PUT "https://forge.era.app/api/banking/transactions/utgr_your_transaction_id" \
  -H "X-API-Key: fmk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"categoryKey": "fcat_dining", "merchantName": "Corner Cafe"}'

Erreurs courantes

  • Définir un champ et l'effacer dans la même écriture — 400.

  • Plus de 100 id dans une mise à jour groupée — 400, et rien n'est modifié. Moins d'un id donne le même résultat.

  • Une transaction qui n'est pas la tienne, ou qui n'existe pas — 403, jamais 404. La réponse ne te dit donc jamais si un id existe, seulement qu'il n'est pas à toi.

  • Autre chose a modifié la ligne en premier — 409.

Limites

Deux des dix endpoints documentés plafonnent ce que tu peux demander en un seul appel. Les huit autres non.

Pas de plafond par appel ne veut pas dire illimité. Les clés expirent toujours, les écritures ont toujours des limites de longueur de champ, la création d'une catégorie peut atteindre un quota de forfait, ton forfait peut toujours masquer l'historique ancien, et chaque appel compte dans les limites de débit de ton forfait, décrites plus bas.

  • Comptes, solde, résumé, les listes de catégories et de tags, la création d'une catégorie, la création d'un tag et l'écriture d'une seule transaction n'ont aucun plafond de volume par appel. Tu reçois l'ensemble au complet, ou la seule ligne que tu as nommée.

  • pageSize est plafonné à 100, jamais refusé. Demande-en plus et tu reçois 100 lignes avec un 200 — lis pagination.pageSize dans la réponse plutôt que de faire confiance à ce que tu as envoyé.

  • L'écriture groupée de transactions est plafonnée à 100 id, et contrairement à pageSize elle est refusée plutôt que plafonnée : envoie 101 et tu reçois un 400, rien ne change.

  • Les clés expirent selon un calendrier que tu choisis à la création — jusqu'à 90 jours sur le forfait gratuit, 365 sur un forfait payant. Il n'existe pas d'option sans expiration.

  • Ton forfait peut appliquer un plancher de fenêtre d'historique qui masque les transactions plus anciennes. La réponse des transactions porte les champs historyWindow qui indiquent si un plancher s'est appliqué et où il se situe.

Limites de débit

L'API applique deux limites de débit. Chaque forfait a un plafond de rafale : une limite de requêtes sur toute minute glissante. Le forfait gratuit a en plus un budget quotidien : une limite de requêtes sur toute période glissante de 24 heures. Une requête cesse de compter dans le plafond de rafale une minute après que tu l'as faite, et dans le budget quotidien un jour après. Les forfaits payants n'ont pas de budget quotidien pour l'instant : sur un forfait payant, le plafond de rafale est donc la seule limite. Dépasse l'une ou l'autre et l'appel revient en 429.

Les limites appartiennent à ton compte, pas à une clé. Chaque clé REST que tu crées puise dans le même plafond de rafale et, sur le forfait gratuit, dans le même budget quotidien : une deuxième clé ne te donne donc pas plus d'appels. Les appels d'outils MCP sont comptés à part : les appels REST et les appels MCP n'entament jamais les limites des uns des autres.

Limites de débit par forfait
ForfaitBudget quotidienPlafond de rafale
De base100 par jour10 par minute
OrganizeAucun30 par minute
AutomateAucun60 par minute
OptimizeAucun60 par minute
OperateAucun120 par minute

Pour l'instant, les forfaits payants n'ont pas de budget quotidien.

Les forfaits payants fonctionnent aussi selon l'utilisation raisonnable. C'est une politique, pas un compteur : l'API ne refuse donc jamais un appel pour ça. L'API est faite pour des scripts, des tableaux de bord et des intégrations sur tes propres données financières, à un volume qui convient à une personne. Si on pense que ton utilisation va au-delà, on ne coupera pas ton compte sans te contacter d'abord. Sur la page des prix, ça s'appelle « Illimité (utilisation raisonnable) pour l'instant ».

Sur le forfait gratuit, chaque réponse servie indique ton budget quotidien dans les en-têtes X-RateLimit-* décrits sous En-têtes de réponse. Les réponses d'un forfait payant n'en portent aucun. Aucun en-tête n'indique le plafond de rafale, sur aucun forfait : règle donc ton rythme sur le tableau. Sur le forfait gratuit, Remaining peut être bien au-dessus de zéro juste avant qu'une rafale revienne en 429. Si Era ne peut pas mesurer ton utilisation, il sert l'appel sans les en-têtes : sur le forfait gratuit, lis une réponse sans en-têtes comme un compte inconnu, pas comme une erreur.

Ce que dit un 429

Quelle limite t'a refusé. Un 429 qui porte les en-têtes X-RateLimit-* vient du budget quotidien; un 429 sans eux, du plafond de rafale. C'est vrai sur tous les forfaits. Le corps est au format problem-details, et son champ detail précise la limite, ce qu'elle permet, quand ta prochaine requête se libère et le forfait qui la relève ou la retire, ou que tu es déjà sur le plus élevé. Il est écrit pour des humains : lis les en-têtes plutôt que de l'analyser.

Réponse 429, budget quotidien
{
  "type": "https://httpstatuses.com/429",
  "title": "Too Many Requests",
  "status": 429,
  "detail": "You've used up your daily budget of 100 requests. Your next request frees up at 2026-09-16T09:00:00Z. The Organize plan removes it."
}

Chaque 429 porte aussi Retry-After : un nombre entier de secondes, jamais moins d'une. C'est jusqu'à une minute pour le plafond de rafale et jusqu'à 24 heures pour le budget quotidien du forfait gratuit. Un appel refusé ne compte dans aucune des deux limites, mais une nouvelle tentative avant la fin de Retry-After est refusée à son tour : attends donc. Ensuite, une requête se libère, pas toute la limite. Envoie-la et lis ce qui revient : un autre Retry-After si elle est refusée ou, sur le forfait gratuit, les en-têtes une fois qu'elle est servie.

Les limites de débit ne protègent pas une clé que tu as perdue de vue. Une clé qui a fuité puise dans les mêmes limites que toutes les autres clés de ton compte, et elle peut faire tout ce que ses portées permettent. La révoquer ne rembourse pas les appels qu'elle a déjà faits. Si tu as un doute sur une clé, révoque-la. Voir Sécurité et gestion des clés plus bas.

Conventions

Les champs de réponse sont en camelCase. Les paramètres de requête, eux, ne sont pas sensibles à la casse, alors le camelCase marche là aussi — la spec publiée les écrit en PascalCase, c'est pour ça que tu verras les deux formes circuler.

Un champ qui nomme un jour de calendrier est en YYYY-MM-DD. Un champ qui nomme un instant précis est en ISO 8601 avec un décalage horaire.

Les tailles de page sont ramenées dans les bornes, pas refusées. Demande un pageSize de 500 et tu obtiens 100 lignes et un 200, pas une erreur — alors relis pagination.pageSize dans la réponse plutôt que de te fier à ce que tu as envoyé.

Une réponse peut porter des champs que cette page ne liste pas. Ignore ceux que tu ne reconnais pas plutôt que de planter dessus — c'est ce qui garde ton client fonctionnel à mesure que l'API s'étoffe.

REST est du HTTP ordinaire, donc aucun SDK n'est nécessaire pour l'appeler — n'importe quel langage avec un client HTTP fait l'affaire. Rien à installer.

Versionnage et changements

Tout ce qui est documenté ici relève de cette politique.

Il n'y a pas de numéro de version dans le chemin ni d'en-tête de version. Chaque point de terminaison a une seule version active, et c'est celle documentée ici.

Ce que nous pouvons changer sans préavis

Rien de tout cela ne casse un client qui suit les conventions ci-dessus.

  • Ajouter un point de terminaison, ou une opération sur un point existant.

  • Ajouter un champ à une réponse.

  • Ajouter un paramètre facultatif. Omets-le et rien ne change.

  • Ajouter une valeur à un ensemble fixe, comme un statut ou un type.

  • Ajouter un en-tête de réponse.

Ce que nous ne changeons pas sans préavis

Chacun de ces changements peut casser un client qui fonctionne.

  • Retirer un point de terminaison, ou changer son chemin ou sa méthode.

  • Retirer ou renommer un champ de réponse.

  • Changer le type d'un champ ou sa signification.

  • Rendre obligatoire un paramètre aujourd'hui facultatif.

  • Refuser une entrée acceptée aujourd'hui.

  • Changer la portée dont un point de terminaison a besoin.

Avant chacun de ces changements, le changelog l'annonce au moins 90 jours à l'avance et te dit quoi modifier. Ce qui fonctionne aujourd'hui continue de fonctionner jusque-là.

Les changements sont annoncés dans le changelog, dont le lien se trouve dans la section Changelog ci-dessous. Il n'y a pas encore de courriel ni de flux, alors consulte-le quand tu planifies du travail sur l'API.

Tant que l'API est en bêta, l'ensemble documenté continuera de s'étoffer. Ce qui est déjà là ne cassera rien chez toi sans préavis.

Changelog

Les nouveautés de l'Era Developer Platform, dont l'API Era, du plus récent au plus ancien. La politique ci-dessus dit ce qui est annoncé à l'avance et avec quel délai ; le changelog est l'endroit où ces annonces paraissent.

Sécurité et gestion des clés

Approuver un agent crée une clé

Quand tu approuves un agent en OAuth, Era lui crée une clé d'API. Elle atterrit dans la même liste du tableau de bord que celles que tu crées, sous un nom qu'Era compose à partir du nom du client lui-même.

Comment elle s'appelle

Auto -- Claude

Elle porte exactement les portées que tu as approuvées sur cet écran, et rien d'autre. Révoque-la depuis le tableau de bord et l'agent ne peut plus obtenir de nouvel accès tant que tu ne l'as pas approuvé à nouveau. Un jeton qu'il détient déjà reste valable jusqu'à son expiration, une heure au plus.

Les écritures apparaissent dans ton journal d'activité, pas les lectures

Créer et révoquer une clé apparaissent tous les deux dans ton journal d'activité, tout comme chaque appel d'outil qu'un agent fait en MCP. Une écriture REST y apparaît aussi — comme le changement qu'elle a fait, une étiquette créée ou une transaction modifiée. Une lecture REST ne crée aucune entrée. Era inscrit ces entrées sur tous les forfaits, mais lire le journal complet demande Organize ou plus — en dessous, tu ne vois que les entrées les plus récentes. Même pour une écriture, REST ne tient aucun journal requête par requête : ce qui est noté, c'est le changement, pas l'appel, et il est inscrit sous ton compte, pas sous la clé qui l'a fait.

Si jamais tu doutes d'une clé, révoque-la. Une clé que tu as créée toi-même cesse de fonctionner en REST comme en MCP dès sa requête suivante. La clé d'un agent cesse aussitôt d'obtenir de nouveaux accès, et tout jeton qu'il détient déjà expire en moins d'une heure. En refaire une te prend une minute.

D'autres choses à savoir avant de te fier à une clé.
Les portées sont larges
banking:read couvre bien plus que les six lectures de cette page — la même portée couvre aussi le reste des lectures de ton compte : soldes, positions, connexions, dépenses. Une seule portée, il n'y a pas plus étroit. Celles d'écriture sont aussi au menu, comme celles de lecture — alors traite n'importe quelle clé comme un mot de passe. Elle agit comme ton compte, pas juste une partie de celui-ci. banking:write peut modifier des catégories, des étiquettes et les métadonnées d'une transaction, gérer des comptes et des soldes manuels, et connecter ou déconnecter des institutions — aucune portée de cette page ne peut déplacer de l'argent entre tes comptes bancaires.
Les portées ne se mettent pas à jour
Les portées d'une clé sont fixées à sa création et ne changent jamais ensuite. Ça compte pour tout ce qu'une portée couvre et qui n'est pas encore activé : accorde social:write aujourd'hui et la clé l'aura encore le jour où les vues partagées arriveront. Accorde ce que tu utilises maintenant, pas ce que tu utiliseras peut-être.
Aucune approbation requise
Tu es déjà connecté à ton propre compte, alors créer une clé n'a besoin de l'accord de personne d'autre — il n'y a ni revue ni liste d'attente, et personne chez Era n'approuve la demande. C'est inscrit dans ton journal d'activité dès que tu la crées, alors une clé que tu ne reconnais pas est facile à repérer.
L'accès bancaire reste hors de portée
Une clé n'atteint pas ton accès bancaire, parce qu'Era ne l'a jamais. Tu le saisis dans le flux de connexion géré par le fournisseur de données, pas sur un écran d'Era — ce qu'Era conserve ensuite, c'est un jeton d'accès par connexion, chiffré au repos avec AES-256, que tu peux jeter en débranchant l'institution.
Les clés sont hachées, pas stockées
Ta clé, c'est 256 bits de données aléatoires, hachées en SHA-256 avant d'être stockées. On garde le haché, pas la clé. Si tu la perds, révoque-la et crées-en une autre.

Ressources principales

Comptes

GET/banking/accounts
Portée requisebanking:read

Tous les comptes que tu peux voir, à travers chaque institution branchée, avec à côté le nombre de ceux qui sont laissés de côté : excludedAccountCount, séparé en tierExcludedAccountCount pour les comptes que la limite de comptes de ton forfait laisse de côté et userExcludedAccountCount pour ceux que tu as masqués. accountLimit, c'est le nombre de comptes que ton forfait montre à la fois, toutes connexions confondues. accountLimitLift nomme le forfait le moins cher qui a de la place pour tous les comptes que tu n'as pas masqués, et vaut null quand ton forfait ne laisse rien de côté. Chaque compte porte son accountGroupKey — la valeur que le point de terminaison de solde prend dans son chemin — et le connectionId auquel il appartient, alors c'est le premier appel à faire. Accepte connectionId pour se limiter à une seule connexion (les nombres se limitent avec lui, accountLimit et accountLimitLift non), et includeExcluded pour ramener les comptes que ton forfait laisse de côté et ceux que tu as masqués.

Paramètres de requête
connectionIdoptionnel
Limite la liste aux comptes d'une seule connexion.
includeExcludedoptionnel
Inclut aussi les comptes que ton forfait laisse de côté et ceux que tu as masqués, avec leurs soldes retenus. Le champ visibility de chaque ligne te dit lequel : tierExcluded ou userExcluded, et visible pour les autres. Le point de terminaison de solde écrit ces valeurs autrement, alors n'utilise pas le même analyseur pour les deux. excludedAccountCount revient quand même quand c'est true, et ces comptes sont déjà dans la liste, alors n'additionne pas les deux. Par défaut, false.
Réponse · 200
{
  "accounts": [
    {
      "accountGroupKey": "uagr_7f3c9a21",
      "connectionId": "ucon_4b19e02c",
      "name": "Everyday Checking",
      "currentBalance": 4820.16,
      "supportsTransactions": true,
      …
    }
  ],
  "excludedAccountCount": 1
}

Sur un compte que tu as masqué ou que ton forfait exclut, les champs de solde reviennent à null plutôt qu'à zéro — null veut dire retenu, pas vide. supportsTransactions vaut null dans le même esprit : ça veut dire qu'Era ne peut pas se prononcer, jamais que la réponse est non. Même chose pour les champs du forfait : si Era n'a pas pu lire ton forfait sur cet appel, tierExcludedAccountCount, userExcludedAccountCount, accountLimit et accountLimitLift reviennent tous à null. accountLimit vaut aussi null sur un forfait sans limite de comptes, et accountLimitLift quand aucun forfait n'a plus de place ou quand ton forfait ne laisse rien de côté.

Solde d'un compte

GET/banking/accounts/{accountId}/balance
Portée requisebanking:read

One account's balance, with the credit fields filled in when the account is a liability. The path takes that account's accountGroupKey — the same value /banking/accounts returns for it. The key is not checked for shape before the lookup, so a malformed key and an unknown one answer the same way.

Réponse · 200
{
  "accountGroupKey": "uagr_7f3c9a21",
  "currentBalance": 4820.16,
  "availableBalance": 4712.03,
  "creditLimit": null,
  "currencyCode": "USD",
  "availableCredit": null,
  "asOf": "2026-08-11T09:32:00Z",
  "visibility": null
}

Un compte masqué, ou un compte dont la connexion a été coupée, répond quand même 200 — avec les champs de solde à null. Un 404 signifie que le compte n'existe vraiment pas, ou que la clé n'avait pas la forme d'une clé. Surveille le champ visibility ici : il vaut null quand le compte est visible, tier_excluded quand la limite de comptes de ton forfait le laisse de côté, user_excluded quand tu l'as masqué, et connection_severed quand sa connexion a été coupée. Avec tier_excluded, accountLimit est la limite de ton forfait et accountLimitLift nomme le forfait le moins cher qui a de la place pour tous les comptes que tu n'as pas masqués, celui-ci compris. accountLimitLift vaut null dans tous les autres états, et avec connection_severed, accountLimit vaut null aussi.

Sommaire des comptes

GET/banking/accounts/summary
Portée requisebanking:read

Les totaux sur les comptes que tu peux voir : totalAssets, totalLiabilities et netWorthHint, qui est le premier moins le second. N'accepte aucun paramètre.

Réponse · 200
{
  "userId": "7d1c0b93a8e24f60",
  "accounts": [ … ],
  "totalVisibleCount": 6,
  "totalHiddenCount": 2,
  "totalAssets": 48210.75,
  "totalLiabilities": 9327.40,
  "netWorthHint": 38883.35,
  "computedAt": "2026-08-11T09:32:00Z"
}

netWorthHint ne compte que les comptes présents dans cette réponse, alors totalHiddenCount te dit ce qui lui manque : tierExcludedAccountCount d'entre eux sont laissés de côté par la limite de comptes de ton forfait, et userExcludedAccountCount, tu les as masqués toi-même. accountLimitLift nomme le forfait le moins cher qui ramène les premiers, et vaut null quand il n'y en a aucun. Prends netWorthHint comme un chiffre de départ plutôt que comme une valeur nette faisant autorité.

Transactions

GET/banking/transactions
Portée requisebanking:read

Tes transactions, une page à la fois, enveloppées avec les compteurs de pagination à côté. Accepte page et pageSize (100 au maximum), plus des filtres optionnels par compte, plage de dates, règles appliquées et étiquettes assignées.

Paramètres de requête
accountIdoptionnel
Limite aux transactions d'un compte, par son accountGroupKey.
fromDateoptionnel
Seulement les transactions à cette date ou après.
toDateoptionnel
Seulement les transactions à cette date ou avant.
pageoptionnel
Numéro de page, à partir de 1. Par défaut, 1.
pageSizeoptionnel
Lignes par page. Par défaut, 50, plafonné à 100.
sortByoptionnel
Champ de tri : transactionDate, amount, description, category ou merchantName.
sortDirectionoptionnel
asc ou desc. Par défaut, décroissant.
categoryKeysoptionnel
Only transactions in these categories, by their fcat_ keys. Takes a list, not a single key, and a transaction matches if its effective category is any one of them. Send the literal "uncategorized" to select the transactions that have no category at all.
searchoptionnel
Recherche plein texte sur le commerçant, la description, la catégorie, le nom du compte et le montant.
ruleIdsoptionnel
Seulement les transactions qu'une règle d'automatisation a touchées, par la clé de la règle.
tagKeysoptionnel
Seulement les transactions qui portent l'une de ces étiquettes.
reviewStatusesoptionnel
needs_review, reviewed ou flagged. Accepte une liste ; une transaction correspond si son statut de révision est l’un d’eux.
includeChildrenoptionnel
With a category filter set, also include transactions in the subcategories of every key you passed. Defaults to false.
includePendingoptionnel
Retourne aussi les transactions en attente des 7 derniers jours, marquées isPending. Par défaut, false. Les lignes en attente sont en lecture seule.
Réponse · 200
{
  "transactions": [ … ],
  "pagination": {
    "currentPage": 1,
    "pageSize": 20,
    "totalItems": 412,
    "totalPages": 21
  },
  "historyWindowApplied": true,
  "historyWindowFloorDate": "2026-06-28",
  "historyWindowHiddenCount": 137,
  "historyWindowEarliestDate": "2024-03-02",
  "historyWindowDegraded": false
}

Ton forfait peut appliquer un plancher de fenêtre d'historique, qui cache les transactions plus anciennes que lui. C'est pour ça que la réponse porte les champs historyWindow : historyWindowApplied te dit qu'un plancher a bel et bien caché quelque chose, historyWindowFloorDate indique où il tombe, historyWindowHiddenCount combien de lignes sont derrière, et historyWindowEarliestDate jusqu'où ton historique remonte vraiment. Sans eux, un résultat court est impossible à distinguer d'un compte sans transactions plus anciennes. Deux d'entre eux changent ce que tu écris : historyWindowHiddenCount peut valoir null même quand un plancher s'est appliqué, alors lis null comme une valeur inconnue plutôt que comme un zéro; et quand historyWindowDegraded vaut true, Era n'a pas pu confirmer ton forfait sur cette lecture, donc la date du plancher est une supposition et non un fait. Sur une lecture payante confirmée, aucun plancher ne s'applique et historyWindowApplied revient à false. La limite de comptes de ton forfait laisse aussi des transactions de côté : tierExcludedAccountCount te dit combien de tes comptes elle garde hors de cette lecture, et userExcludedAccountCount combien tu en as masqué — les deux limités au compte sur lequel tu filtres, si tu en filtres un. Les deux valent null quand Era n'a pas pu lire ton forfait sur cet appel.

Parcourir un long historique page par page consomme des requêtes. Ton forfait plafonne la vitesse à laquelle tu peux appeler et, sur le forfait gratuit, le nombre d'appels par jour. Limites donne les chiffres par forfait, les en-têtes de limite et ce que dit un 429.

Modifier une transaction

Quatre choses sur une transaction sont à toi de redéfinir : sa catégorie, le nom du commerçant, une note de ton choix, et son statut de révision. Envoie seulement celles que tu changes — tout ce que tu omets reste tel quel. L'id dans le chemin est la clé utgr_ de la transaction. Ça modifie des données, alors ça prend banking:write plutôt que banking:read.

PUT/banking/transactions/{id}
Portée requisebanking:write
Corps de la requête
categoryKeyoptionnel
La clé fcat_ de la catégorie à assigner. Omets ce paramètre et la transaction garde la catégorie qu'elle a déjà.
merchantNameoptionnel
Un nom de commerçant de ton choix, jusqu'à 1000 caractères. Omets ce paramètre et le nom actuel reste.
descriptionoptionnel
Une note de ton choix sur cette transaction, jusqu'à 5000 caractères. Omets ce paramètre et la note actuelle reste.
clearCategoryoptionnel
Retire ta redéfinition de catégorie, pour que la catégorisation d'Era reprenne le dessus. Par défaut, false.
clearMerchantNameoptionnel
Retire ta redéfinition du nom de commerçant, pour que le nom envoyé par ta banque revienne. Par défaut, false.
clearDescriptionoptionnel
Retire ta redéfinition de la description, pour que la description envoyée par ta banque revienne. Par défaut, false.
reviewStatusoptionnel
Marque-la needs_review, reviewed ou flagged.
clearReviewStatusoptionnel
Retire ta redéfinition du statut de révision. Par défaut, false.
Réponse · 200
{
  "transaction": { … }
}

Tu récupères la transaction mise à jour au complet, dans la même forme que retourne la liste ci-dessus — non reproduite ici, parce que c'est un gros objet encore en mouvement. Définir un champ et le vider dans le même appel te donne 400. Une transaction qui n'est pas la tienne, ou qui n'existe pas du tout, te donne 403 — l'API ne fait pas la différence entre les deux. Et si autre chose a changé la même ligne pendant que tu écrivais, tu obtiens 409 : relis-la et renvoie-la.

Modifier jusqu'à 100 à la fois

Les quatre mêmes redéfinitions, appliquées à une liste de transactions en un seul appel. Chaque id de la liste reçoit les mêmes changements — il n'y a pas de variation par transaction. Ça modifie des données, alors ça prend banking:write plutôt que banking:read.

PUT/banking/transactions/bulk
Portée requisebanking:write
Corps de la requête
transactionIds
Les clés utgr_ des transactions à modifier. Au moins une, et au plus 100. Au-delà de 100, c'est refusé plutôt que tronqué — contrairement à pageSize plus haut, tu obtiens un 400 et rien n'est modifié.
categoryKeyoptionnel
La clé fcat_ de la catégorie à assigner. Omets ce paramètre et la transaction garde la catégorie qu'elle a déjà.
merchantNameoptionnel
Un nom de commerçant de ton choix, jusqu'à 1000 caractères. Omets ce paramètre et le nom actuel reste.
descriptionoptionnel
Une note de ton choix sur cette transaction, jusqu'à 5000 caractères. Omets ce paramètre et la note actuelle reste.
clearCategoryoptionnel
Retire ta redéfinition de catégorie, pour que la catégorisation d'Era reprenne le dessus. Par défaut, false.
clearMerchantNameoptionnel
Retire ta redéfinition du nom de commerçant, pour que le nom envoyé par ta banque revienne. Par défaut, false.
clearDescriptionoptionnel
Retire ta redéfinition de la description, pour que la description envoyée par ta banque revienne. Par défaut, false.
reviewStatusoptionnel
Marque-la needs_review, reviewed ou flagged.
clearReviewStatusoptionnel
Retire ta redéfinition du statut de révision. Par défaut, false.
Réponse · 200
{
  "transactions": [ … ]
}

Tu récupères les transactions mises à jour, dans la même forme que retourne la liste ci-dessus. Définir un champ et le vider dans le même appel te donne 400, tout comme une liste vide. Une liste contenant une transaction qui n'est pas la tienne, ou qui n'existe pas du tout, te donne 403 pour l'appel entier — rien n'est modifié. Si autre chose a changé l'une de ces lignes pendant que tu écrivais, tu obtiens 409 : relis-les et renvoie-les.

Catégories

GET/banking/categories
Portée requisebanking:read

Toute la taxonomie des catégories : chaque ensemble de catégories, avec ses sous-catégories imbriquées dedans. La taxonomie est partagée, pas propre à un compte.

Réponse · 200
{
  "packs": [
    {
      "packSlug": "default",
      "packName": "Era default categories",
      "isDefault": true,
      "categories": [
        {
          "projectionKey": "fcat_food_dining",
          "categoryName": "Food & dining",
          "isTopLevel": true,
          "children": [ … ]
        }
      ]
    }
  ],
  "meterLimit": 25,
  "canCreateCustomCategories": true
}

Ajouter une catégorie

Une catégorie définie par l'utilisateur, sous un parent existant. Ça modifie des données, alors ça prend banking:write plutôt que banking:read.

POST
Portée requisebanking:write
Corps de la requête
slug
Identifiant compatible URL — lettres minuscules, chiffres et traits d'union, de 2 à 50 caractères.
parentCategoryKey
La clé fcat_ de la catégorie sous laquelle celle-ci s'imbrique.
name
Nom affiché.
descriptionoptionnel
Description optionnelle.
iconNameoptionnel
Nom d'icône optionnel.
spendingTypeoptionnel
Classification de dépense optionnelle.
displayOrderoptionnel
Position de tri optionnelle parmi ses catégories sœurs.
assignmentEligibilityoptionnel
Règle optionnelle sur les transactions auxquelles cette catégorie peut être assignée.
sourceSystemKeysoptionnel
Liste optionnelle de clés de catégories existantes dont les transactions doivent être redirigées ici à partir de maintenant.
applyRetroactivelyoptionnel
Si true, réévalue aussi les transactions passées selon le nouvel acheminement. Par défaut, false.
Réponse · 201
{
  "categoryKey": "fcat_side_hustle_9f2a",
  "overlayProjectionKey": "fcov_9f2a1c",
  "action": "created",
  "isQuotaExceeded": false,
  "createdMappingRuleKeys": [ … ],
  …
}

La réponse porte aussi retroactiveAffectedCount, mergeSourcesHiddenCount et mergeSourcesTotalCount — des champs que cet appel partage avec les fusions de catégories, non montrés ici — ainsi qu'isQuotaExceeded, quotaExceededMessage et meterGate, qui valent toujours false, null et null sur une catégorie créée. Si le quota de ton forfait refuse la création, tu reçois plutôt un 402 sans aucun de ces champs : son corps contient statusCode, message et errors.generalErrors, dont l'unique entrée te dit quelle limite tu as atteinte.

Étiquettes

GET/banking/tags
Portée requisebanking:read

Toutes les étiquettes de ton compte, en une seule liste. Pas de pagination — une seule réponse te les retourne toutes.

Paramètres de requête
tagTypeoptionnel
Filtre par origine de l'étiquette : user, system ou auto.
includeDeletedoptionnel
Inclut les étiquettes supprimées. Par défaut, false.
Réponse · 200
{
  "tags": [
    {
      "tagKey": "utag_9c2f01ab",
      "name": "business-expense",
      "displayName": "Business expense",
      "tagType": "user",
      "color": "#6DC6BA",
      "transactionCount": 42
    }
  ]
}

Créer une étiquette

A new tag, canonicalized to lowercase. Mutating, so it needs banking:write rather than banking:read. System tags cannot be created through the API; user and auto tags can.

POST
Portée requisebanking:write
Corps de la requête
name
Le nom canonique de l'étiquette.
displayNameoptionnel
Nom affiché optionnel. Par défaut, le nom canonique.
tagTypeoptionnel
user or auto. Defaults to user. system is refused — it is reserved for tags Era creates itself.
coloroptionnel
Couleur hexadécimale optionnelle pour l'affichage.
iconoptionnel
Nom d'icône optionnel.
Réponse · 201
{
  "tag": {
    "tagKey": "utag_9c2f01ab",
    "name": "business-expense",
    "displayName": "Business expense",
    "tagType": "user",
    "version": 1,
    "createdAt": "2026-08-26T09:15:00Z"
  }
}

Era Financial Advisors LLC est un conseiller en placement inscrit auprès de la SEC (CRD #334404). L'inscription n'implique pas un niveau particulier de compétence ou de formation. Les services de conseil en placement sont discrétionnaires et assistés par l'IA; ils ne remplacent pas les conseils financiers personnalisés. Les services de courtage et de garde sont fournis par Alpaca Securities LLC, une entité distincte et membre de la FINRA/SIPC. Les comptes Era Thesis et Era Agency ne sont offerts pour l'instant qu'aux résidents des États-Unis; Era Context relie des comptes aux États-Unis, au Royaume-Uni, au Canada, en France, en Allemagne, en Espagne et dans plus de 40 pays au total. Rien sur ce site ne constitue une offre ou une sollicitation d'achat ou de vente de titres. Les rendements passés ne garantissent pas les résultats futurs. Veuillez consulter notre Form ADV, Form CRS avant d'investir.

era© 2026 Tinwell Labs Inc. DBA Era