CommunityRédaction et éditiongithub.com

FIZ Facturation

Émettre des factures au Portugal avec l'IA — Compétence Claude Code / Agent pour l'API de facturation FIZ (TVA, exonération, CAE, NIF, AT)

Qu'est-ce que FIZ Facturation ?

Cette compétence permet d'émettre des factures juridiquement contraignantes au Portugal via l'API publique FIZ. Elle guide l'utilisateur tout au long du cycle de vie complet : recherche ou création du client, recherche ou création des articles, construction d'un brouillon, émission (étape légalement contraignante) et téléchargement du PDF. Elle est conçue pour fonctionner avec Claude Code, Cursor, Codex et d'autres environnements d'agents IA. La compétence insiste sur la conformité fiscale portugaise : taux de TVA corrects, codes d'exonération (M-codes), CAE, NIF et validation des champs avant émission. Elle offre des helpers curl prêts à l'emploi, demande une confirmation explicite avant toute action irréversible et gère les erreurs en vérifiant les codes HTTP plutôt que les codes de sortie des commandes.

Compatible avec✓Claude Code✓Codex CLI~Cursor
npx skills add FIZ-co/fiz-invoicing-skill

Installed? Explore more Rédaction et édition skills: steipete/notion, langchain-ai/langchain, bytedance/podcast-generation · View all 6 →

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Facturation FIZ

Émettre des factures avec l'API publique FIZ — une passerelle REST à https://api.fiz.co. Cette compétence parcourt le cycle de vie complet : trouver ou créer le client, trouver ou créer les articles, construire un brouillon de facture, l'émettre (c'est l'étape juridiquement contraignante), et éventuellement télécharger le PDF.

Configuration

Chaque requête nécessite la clé API du client dans l'en-tête x-api-key. Obtenez une clé sur https://app.fiz.co/settings/integrations.

Stockez-la dans une variable d'environnement afin qu'elle ne soit jamais codée en dur dans les commandes :

export FIZ_API_KEY="fiz_api_..."     # la clé de l'utilisateur depuis app.fiz.co
export FIZ_API_URL="https://api.fiz.co"   # facultatif ; c'est la valeur par défaut

Tous les exemples ci-dessous utilisent $FIZ_API_KEY et $FIZ_API_URL. Si FIZ_API_URL n'est pas défini, utilisez https://api.fiz.co. Si FIZ_API_KEY n'est pas défini, arrêtez-vous et dites à l'utilisateur de le définir dans son environnement (export FIZ_API_KEY=… dans son terminal, ou un gestionnaire de secrets) — ne lui demandez pas de coller la clé dans le chat, et n'imprimez ou n'affichez jamais la valeur de la clé. Une clé API est un identifiant ; gardez-la hors du transcript de la conversation.

Un helper curl réutilisable est fourni dans scripts/fiz.sh. Les commandes sont exécutées depuis le répertoire de travail de la session (la racine de votre projet), pas le répertoire de la compétence, donc sourcez le helper par son chemin absolu via ${CLAUDE_SKILL_DIR} (Claude Code définit ceci au répertoire propre de la compétence) :

source "${CLAUDE_SKILL_DIR}/scripts/fiz.sh"   # se résout depuis n'importe quel répertoire de travail
fiz GET /invoices

Sur un runtime qui ne fournit pas CLAUDE_SKILL_DIR, remplacez ce chemin par le chemin équivalent du répertoire de compétence de ce runtime (un simple scripts/fiz.sh relatif ne se résoudra pas depuis la racine du projet).

Le helper imprime le statut HTTP et retourne non-nul sur les 4xx/5xx, donc une réponse d'erreur n'est jamais confondue avec un succès — voir "Gestion des erreurs" ci-dessous. Des exemples de curl simple sont également donnés en ligne ; si vous utilisez curl brut, vérifiez toujours le statut HTTP, pas seulement si la commande s'est terminée avec le code 0.

Le modèle mental

  • Une facture fait référence à un client (par son id) et à un ou plusieurs articles (par leur id). Les clients et les articles doivent donc exister avant que vous puissiez construire la facture.
  • POST /invoices crée un brouillon. Un brouillon n'est pas encore un document légal — il n'est pas envoyé à l'administration fiscale et peut être modifié ou supprimé librement.
  • POST /invoices/:id/issue l'émet — attribue le numéro officiel et l'ATCUD, synchronise avec l'administration fiscale portugaise (AT) et le rend définitif. L'émission est irréversible ; confirmez avec l'utilisateur avant d'émettre. Une facture émise ne peut pas être supprimée — la seule façon de l'annuler est une note de crédit.
  • La seule exception à "créer puis émettre" : si vous passez un objet payment lors de la création pour les types INVOICE_RECEIPT ou SIMPLIFIED_INVOICE, le document enregistre le paiement — mais vous devez toujours l'émettre pour finaliser.

Confirmation avant les écritures

Ces points de terminaison modifient l'état sur le compte de l'utilisateur. Deux niveaux de vigilance :

  • Planifiez, puis prévisualisez toutes les écritures avant la première. Une fois que vous savez ce que la requête nécessite, listez chaque écriture que vous avez l'intention d'effectuer pour cette tâche — chaque point de terminaison plus son payload JSON (le client à créer, chaque article, le brouillon de facture) — et montrez ce lot à l'utilisateur en une seule prévisualisation. Procédez aux écritures une fois qu'il approuve le plan. Si le plan change en cours de route (par exemple, la recherche d'un article échoue et vous devez maintenant en créer un), prévisualisez la nouvelle écriture avant de l'envoyer. N'inventez jamais de données client, de champs fiscaux ou de montants — utilisez uniquement ce que l'utilisateur vous a donné.
  • Avant POST /invoices/:id/issue — c'est irréversible et déclaré à l'administration fiscale. Obtenez toujours une confirmation explicite et séparée (au-delà de l'approbation du plan ci-dessus), montrant le client du brouillon, les lignes d'articles, la TVA et le total. N'émettez pas de votre propre initiative.

Politique d'invocation (délibérée) : cette compétence maintient l'auto-invocation du modèle activée — la description est la surface de découverte, et le vrai filet de sécurité est la prévisualisation-de-toutes-les-écritures + la confirmation d'émission séparée ci-dessus, pas le blocage de la découverte. Le manifeste Codex (agents/openai.yaml) est configuré pour correspondre (allow_implicit_invocation: true). Un opérateur qui souhaite une utilisation manuelle uniquement peut définir disable-model-invocation: true dans le frontmatter (se charge uniquement sur /fiz-invoicing).

Il s'agit de facturation fiscale portugaise — pourquoi l'exactitude est importante

FIZ émet des documents fiscaux juridiquement contraignants qui sont déclarés à l'administration fiscale portugaise (Autoridade Tributária, "AT"). Un taux de TVA incorrect ou une raison d'exonération manquante n'est pas un bug esthétique — cela produit un document fiscal incorrect qui, une fois émis, ne peut être corrigé que par une note de crédit. Assurez-vous que les champs fiscaux sont corrects avant d'émettre.

Les deux choses les plus susceptibles d'être erronées, et sur lesquelles vous devez raisonner :

1. Taux de TVA (vatRate sur chaque article) — ne le devinez jamais. La bande de taux (NORMAL | INTERMEDIATE | REDUCED | EXEMPT) et le pourcentage auquel elle correspond dépendent du territoire (Continental / Açores / Madeira). Par défaut, utilisez NORMAL — REDUCED/INTERMEDIATE s'appliquent uniquement à des catégories spécifiques définies par la loi (certains aliments, restaurants, événements culturels…). Si l'utilisateur n'a pas nommé une telle catégorie, utilisez NORMAL et dites-le, ou demandez ; n'appliquez jamais silencieusement un taux réduit. Le tableau des pourcentages par territoire se trouve dans domain.md.

2. L'exonération de TVA nécessite un code de raison (vatExemptionReason). Si vatRate est EXEMPT, la loi portugaise exige un motivo de isenção — un code M énonçant la base légale. Définissez-en toujours un ; un article exonéré sans raison valable est un document invalide et peut être rejeté lors de l'émission. Le code doit refléter la raison réelle : régime des petites entreprises → M10, activité exonérée par nature (santé/éducation) → M07, B2B UE / autoliquidation → M40/M16/M19. Si l'utilisateur est exonéré mais ne connaît pas le code, demandez pourquoi et faites la correspondance — ne choisissez pas arbitrairement. La liste complète des codes avec références légales se trouve dans domain.md.

Autres règles du domaine à connaître (détails dans domain.md) :

  • CAE est un code d'activité économique portugais à 5 chiffres qui doit être l'un de ceux enregistrés par l'entreprise. Ne l'inventez pas — demandez à l'utilisateur, ou réutilisez le CAE d'une facture précédente. Il doit s'agir d'un code actuel (Rév. 4).
  • NIF (taxpayerNumber) est un numéro de taxe portugais à 9 chiffres avec une somme de contrôle ; obligatoire pour le B2B, facultatif pour les consommateurs finaux. Pour le B2B intra-UE, le numéro de TVA du client est important pour le traitement de l'autoliquidation.
  • Retenue à la source (retenção na fonte : IRS/IRC/IS) est configurée sur l'article ; le taux courant est de 25% pour les services de travailleurs indépendants. Elle est retenue par le payeur, réduisant le montant effectivement payé.
  • Le type de document affecte les règles : une SIMPLIFIED_INVOICE est pour les petites ventes au détail et peut omettre les données complètes du client ; une INVOICE à une entreprise pour plus de 1 000 € nécessite le NIF du client.

Flux de travail

Suivez ces étapes. Sautez les étapes 1–2 si l'utilisateur vous donne déjà un identifiant client et des identifiants d'articles.

Étape 1 — Résoudre le client

Recherchez d'abord pour éviter les doublons, puis créez si nécessaire.

Les exemples utilisent le helper fiz (voir Configuration) — il vérifie le statut HTTP pour vous. Le curl brut équivalent se trouve dans l'annexe.

Rechercher par terme (nom, numéro de taxe, email) :

fiz GET "/customers?search=Joao"

Créer un client (seul name est obligatoire) :

fiz POST /customers '{
  "name": "João Silva",
  "email": "[email protected]",
  "taxpayerNumber": "303741791",
  "country": "PT"
}'

Conservez l'id retourné — c'est le customerId pour la facture.

Étape 2 — Résoudre les articles (produits / services)

Rechercher des articles existants :

fiz GET "/items?search=consulting"

Ne réutilisez un article existant que si ses champs fiscaux correspondent à la vente. Un résultat de recherche avec le bon nom ne suffit pas — pour un document fiscal, les champs vatRate, vatTerritory, vatExemptionReason, taxRate et de retenue de l'article doivent correspondre au traitement que vous avez prévu pour ce client et cette vente. Si l'un d'eux diffère (par exemple, même service mais le client est exonéré, dans un autre territoire, ou soumis à une retenue), créez un nouvel article avec les champs corrects plutôt que de réutiliser celui qui ne correspond pas. En cas de doute, inspectez les champs de l'article trouvé et confirmez avec l'utilisateur.

Créer un article. Obligatoires : name, type (PRODUCT | SERVICE), unitPrice, vatRate (NORMAL | INTERMEDIATE | REDUCED | EXEMPT) :

fiz POST /items '{
  "name": "Consulting hour",
  "type": "SERVICE",
  "unitPrice": 80,
  "vatRate": "NORMAL"
}'

Conservez chaque id retourné — ce sont les identifiants des articles pour la facture.

unitPrice est le prix unitaire ; les totaux par ligne sont calculés par FIZ à partir de la quantity que vous donnez dans la facture. Choisissez vatRate délibérément — voir la section domaine ci-dessus ; par défaut, utilisez NORMAL sauf si la catégorie justifie clairement un taux réduit. Si vatRate est EXEMPT, définissez toujours un code M vatExemptionReason qui correspond à pourquoi la vente est exonérée (par exemple M10 pour le régime des petites entreprises). Le champ est techniquement facultatif lors de la création d'un article, mais un article exonéré sans raison valable est incorrect et peut être rejeté ultérieurement lors de l'émission de la facture. Voir domain.md pour la liste complète des codes.

Étape 3 — Créer le brouillon de facture

Champs obligatoires : dueDate (ISO 8601), cae (code d'activité économique portugais), type, customerId, et items (au moins un { id, quantity }).

fiz POST /invoices '{
  "dueDate": "2026-07-18T00:00:00.000Z",
  "cae": "62010",
  "type": "INVOICE",
  "customerId": "6863b1513117c5892ff55296",
  "items": [
    { "id": "68483e978073231c3947077c", "quantity": 10 }
  ]
}'

La réponse inclut le nouvel id de facture (nécessaire pour émettre) et le status (DRAFT). La date de la facture est définie à maintenant et la currency est EUR par l'API — vous ne les envoyez pas.

En option — remise globale (summary) :

"summary": { "globalDiscountType": "PERCENT", "globalDiscountPercent": 10 }

Utilisez "AMOUNT" avec globalDiscountAmount pour une remise d'un montant fixe à la place.

En option — paiement à la création (payment) : autorisé uniquement lorsque type est INVOICE_RECEIPT ou SIMPLIFIED_INVOICE ; l'API retourne 400 sinon.

"payment": { "method": "mbWay", "date": "2026-07-18T00:00:00.000Z" }

method est l'un des suivants : cash, card, bankTransfer, mbWay, multibanco, spin, other.

Étape 4 — Émettre la facture

C'est l'étape contraignante. Confirmez avec l'utilisateur, puis :

fiz POST /invoices/{id}/issue

La réponse contient le number officiel, status: ISSUED, et un bloc syncWithAt. Vérifiez syncWithAt.status — s'il est FAILED, la facture a été créée localement mais n'a pas été synchronisée avec l'administration fiscale ; signalez atMessage et si isRetriable est vrai à l'utilisateur au lieu de prétendre que c'est un succès.

Étape 5 — Télécharger le PDF (facultatif)

fiz GET /invoices/{id}/pdf

Retourne { id, name, url } ; l'url est un lien téléchargeable vers le PDF. Ajoutez ?format=A4 ou ?format=RECEIPT pour choisir la mise en page.

Types de documents (type)

Valeurs : INVOICE · INVOICE_RECEIPT · SIMPLIFIED_INVOICE · RECEIPT · CREDIT_NOTE · DEBIT_NOTE. Par défaut, utilisez INVOICE sauf si l'utilisateur demande un reçu ou une facture simplifiée. Seuls INVOICE_RECEIPT et SIMPLIFIED_INVOICE acceptent un objet payment lors de la création. Voir domain.md pour la signification de chaque type et quand l'utiliser.

Référence des opérations courantes

ActionMéthode et chemin
Lister/rechercher clientsGET /customers?search=…
Créer un clientPOST /customers
Lister/rechercher articlesGET /items?search=…
Créer un articlePOST /items
Créer un brouillonPOST /invoices
ÉmettrePOST /invoices/:id/issue
Lister les facturesGET /invoices
Obtenir une factureGET /invoices/:id
Télécharger le PDFGET /invoices/:id/pdf
Supprimer (brouillon)DELETE /invoices/:id

Gestion des erreurs

Vérifiez toujours le statut HTTP, pas seulement que la commande s'est exécutée. En cas d'erreur, l'API renvoie un corps JSON d'apparence normale — { "statusCode": 400, "message": "...", "timestamp": "..." } — avec le statut HTTP correspondant. Avec curl -s brut, ce corps s'affiche et curl se termine toujours avec le code 0, il est donc facile de confondre une erreur avec un résultat. Le helper fiz protège contre cela : il imprime une ligne HTTP <code> et retourne non-nul sur les 4xx/5xx. Si vous devez utiliser curl brut, ajoutez -w '\n%{http_code}' (ou -o body -w '%{http_code}') et inspectez le code.

Codes courants :

  • 401 — clé API manquante/invalide. Dites à l'utilisateur de définir FIZ_API_KEY dans son environnement (pas dans le chat).
  • 400 — erreur de validation ; le message indique quel champ. Cas courants : items vide, payment sur un type non pris en charge, un champ inconnu/supplémentaire (liste blanche stricte), dueDate mal formé (doit être en ISO 8601 complet avec fuseau horaire, par ex. 2026-07-18T00:00:00.000Z).
  • 5xx — problème serveur/AT ; remontez-le, ne réessayez pas aveuglément la même écriture (une création peut avoir partiellement réussi — vérifiez d'abord avec un GET).

Renvoie toujours le message de l'API à l'utilisateur plutôt que de réessayer aveuglément.

Le contrat complet et faisant autorité de requête/réponse est l'interface Swagger en direct à l'adresse https://api.fiz.co/ — consultez-la si un champ ici semble obsolète.

Quand vous avez besoin de plus de détails

Deux fichiers complémentaires dans ce répertoire de compétence :

  • domain.md — le domaine fiscal portugais : taux de TVA par territoire, la liste complète des codes d'exonération (M) et quand chacun s'applique, types de documents, règles CAE/NIF, retenue à la source, et comment fonctionnent la synchronisation AT / l'irréversibilité de l'émission. Lisez-le chaque fois qu'une décision fiscale n'est pas évidente (en particulier pour choisir un vatRate ou une raison d'exonération).
  • reference.md — la référence API complète champ par champ (chaque champ client/article/facture, toutes les valeurs d'énumération, les formes complètes de requête/réponse).

Annexe — curl brut (sans le helper)

Préférez le helper fiz ci-dessus ; il vérifie le statut HTTP. S'il n'est pas disponible, utilisez curl brut avec -w '\n%{http_code}' :

curl -s -w '\n%{http_code}' -H "x-api-key: $FIZ_API_KEY" $FIZ_API_URL/customers?search=Joao

Extrayez la dernière ligne pour le code de statut et les lignes précédentes pour le corps. Ne traitez pas le corps comme valide avant d'avoir confirmé un code 2xx.

Skills associés