Facturino / Documentation / Authentification

Authentification

L'API Facturino utilise une authentification par clé API via le header Authorization: Bearer. Chaque clé est associée à une entreprise, un environnement (test ou live) et un ensemble de scopes de permission.

Clés API

Vos clés sont disponibles depuis la page Paramètres → Clés API de votre tableau de bord. Deux types de clés coexistent :

Préfixe Environnement Données accessibles
fac_test_ Test (sandbox) Données isolées, jamais transmises à la PA, factures factices
fac_live_ Production Données réelles, déposées sur la Plateforme Agréée, numéros opposables

Isolation stricte. Une clé fac_test_ ne peut jamais lire ou écrire des données fac_live_, et inversement. Les deux environnements partagent uniquement le compte utilisateur et l'entreprise — toutes les ressources (factures, clients, devis…) sont cloisonnées par le champ livemode.

Mode test (sandbox)

Une clé fac_test_ ouvre un bac à sable complet : le flux est identique à la production, mais cloisonné et sans effet réel. Ce que le sandbox garantit :

  • Numérotation distincte — factures, avoirs et devis test ont leur propre série ; un document test ne consomme jamais un numéro de la série légale live.
  • Jamais archivé — les documents test génèrent bien leurs fichiers (Factur-X, XML, PDF téléchargeables), mais n'entrent pas dans la chaîne d'archivage légale : GET /v1/invoices/:id/verify renvoie not archived.
  • E-mails non envoyés — tout e-mail déclenché en test est journalisé mais jamais expédié (aucun message ne part vers vos clients de test).
  • Paiement en ligne refusé — le portail de paiement et POST /v1/invoices/:id/payment-link renvoient sandbox_payment_unavailable (les paiements par carte sont 100 % live).
  • Notifications silencieuses — aucune notification in-app / push / e-mail n'est émise pour un événement de document test.
  • PA simulée — les dépôts et statuts de la Plateforme Agréée sont mockés, sans aucun envoi réel à l'administration.

POST /v1/sandbox/reset réinitialise le bac à sable : il purge les données test, ré-injecte un jeu de fixtures (clients, produits, factures d'exemple) et repositionne les compteurs de numérotation au-delà des fixtures — la première facture test finalisée après un reset ne peut donc pas entrer en collision avec un numéro de fixture.

Utilisation

Incluez la clé dans le header Authorization de chaque requête :

$ curl https://facturino.com/api/v1/account \
  -H "Authorization: Bearer fac_test_a1b2c3d4e5f6..."

Exemples par SDK

Node.js :

import Facturino from '@facturino/node'

// Lue depuis l'environnement — jamais en dur dans le code
const facturino = new Facturino(process.env.FACTURINO_API_KEY)

const account = await facturino.account.retrieve()
console.log(account.livemode) // false (test) ou true (live)

Python :

import os
from facturino import Facturino

client = Facturino(os.environ["FACTURINO_API_KEY"])
account = client.account.retrieve()
print(account.livemode)

PHP :

\Facturino\Facturino::setApiKey(getenv('FACTURINO_API_KEY'));

$account = \Facturino\Account::retrieve();
echo $account['livemode'];

Go :

import (
  "os"
  "github.com/facturino/facturino-go"
)

client := facturino.New(os.Getenv("FACTURINO_API_KEY"))
account, _ := client.Account.Retrieve()
fmt.Println(account.Livemode)

Scopes de permission

À la création d'une clé, vous pouvez restreindre ses permissions. Une clé sans scope déclaré dispose d'un accès complet (équivalent root). Pour les intégrations de production, restreignez systématiquement les scopes au minimum nécessaire.

ScopeEffet
invoices:read / invoices:writeLecture / création-modification des factures
customers:read / customers:writeLecture / création-modification des clients
quotes:read / quotes:writeLecture / création-modification des devis
credit_notes:read / credit_notes:writeLecture / création-modification des avoirs
products:read / products:writeLecture / création-modification des produits
webhooks:read / webhooks:writeLecture / création-modification des endpoints webhook
payments:read / payments:writeLecture / enregistrement des paiements

Une requête sortant du scope autorisé retourne 403 Forbidden avec error.type = "permission_error" et error.code = "scope_insufficient".

Sécurité

  • Ne jamais exposer une clé côté client (navigateur, application mobile, code source public). Toutes les requêtes API doivent passer par votre backend.
  • Stockez les clés dans un coffre de secrets (AWS Secrets Manager, GCP Secret Manager, HashiCorp Vault) ou dans des variables d'environnement de votre plateforme d'hébergement.
  • Faites tourner régulièrement vos clés en production. La révocation est instantanée.
  • L'API n'accepte que les connexions HTTPS (TLS 1.2+) ; les requêtes HTTP sont redirigées.
  • Les clés stockées en base sont hachées (SHA-256) — Facturino ne peut pas afficher la clé en clair après sa génération initiale.

Réponses d'erreur

Une clé manquante, invalide, expirée ou révoquée retourne 401 Unauthorized :

HTTP/1.1 401 Unauthorized

{
  "error": {
    "type": "authentication_error",
    "code": "missing_api_key",
    "message": "No API key provided. Include an Authorization: Bearer <key> header.",
    "hint": "Get your API key from the Facturino dashboard.",
    "request_id": "req_a1b2c3d4"
  }
}

Codes possibles :

CodeCause
missing_api_keyLe header Authorization est absent
invalid_api_keyFormat invalide ou clé inconnue
api_key_revokedLa clé a été révoquée depuis le tableau de bord
api_key_expiredLa date expiresAt de la clé est dépassée
scope_insufficientLa clé n'a pas le scope nécessaire — code 403 avec type: permission_error
captcha_requiredTrop d'échecs depuis cette IP — résoudre le captcha avant de retenter

Protection brute-force

Après plusieurs tentatives d'authentification invalides depuis la même IP, l'API renvoie 429 Too Many Requests avec type: rate_limit_error, code: rate_limit_exceeded et un header Retry-After. Le déblocage est automatique après la durée indiquée. En cas de blocage légitime (clé en rotation, mauvaise configuration), attendez ou contactez le support — ne tentez pas de contourner via une nouvelle IP.

Étapes suivantes