Authentification à l'API 4invoices

Échangez client_id et client_secret contre un token Bearer valable une heure, de serveur à serveur uniquement.

Échangez client_id et client_secret contre un token Bearer valable une heure, de serveur à serveur uniquement.

← Retour à la documentation API

Votre première facture en 6 étapes

  1. Créez l’identifiant dans le panneau, sous Facturation → Paramètres → Accès API, et copiez immédiatement le client_secret — il n’est affiché qu’une seule fois.
  2. Envoyez POST /v1/auth/token avec grant_type client_credentials, client_id et client_secret.
  3. Vous recevez access_token, token_type Bearer, expires_in 3600 et la liste des scopes accordés.
  4. Placez le jeton dans un en-tête Authorization: Bearer <access_token> sur tous les autres appels.
  5. Vérifiez ce que vous avez réellement obtenu avec GET /v1/me : tenant, scopes et quotas de débit actuels.

Tous les endpoints

MéthodeEndpointScopeIdempotency-KeyRequêtes / minute
POST/auth/token
Échanger les identifiants contre un token d'accès
——120
GET/me
Tenant, scopes et limites actuelles
invoices:read—120

Ce qu'est l'API 4invoices

bash
curl -sS -X POST https://api.4invoices.net/v1/auth/token \
  -H 'Content-Type: application/json' \
  -d '{
    "grant_type": "client_credentials",
    "client_id": "cli_XXXXXXXXXXXX",
    "client_secret": "sec_XXXXXXXXXXXXXXXXXXXX"
  }'

# → {"access_token":"eyJ...","token_type":"Bearer","expires_in":3600,
#    "scope":"invoices:read invoices:write efactura:submit"}
bash
curl -sS https://api.4invoices.net/v1/me \
  -H "Authorization: Bearer $ACCESS_TOKEN"

# → tenant, scopes accordés et quotas de débit actuels
javascript
// Mettez le token en cache ; n'en générez pas un par requête.
let cached = { token: "", expiresAt: 0 };

async function getToken() {
  if (cached.token && Date.now() < cached.expiresAt - 60_000) return cached.token;

  const res = await fetch("https://api.4invoices.net/v1/auth/token", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      grant_type: "client_credentials",
      client_id: process.env.FOURINVOICES_CLIENT_ID,
      client_secret: process.env.FOURINVOICES_CLIENT_SECRET,
    }),
  });
  if (!res.ok) throw new Error(`token ${res.status}`);

  const data = await res.json();
  cached = { token: data.access_token, expiresAt: Date.now() + data.expires_in * 1000 };
  return cached.token;
}

https://api.4invoices.net/v1 · https://api.4invoices.net/v1/openapi.json

Scopes

  • invoices:read
  • invoices:write
  • clients:read
  • clients:write
  • efactura:read
  • efactura:submit
Serveur à serveur uniquement. N'appelez jamais l'API depuis du JavaScript de navigateur : le client_secret serait exposé au visiteur, et CORS bloque de toute façon toute origine.

Erreurs

StatutTypeCode
401authentication_errorinvalid_client
401authentication_errortoken_expired
401authentication_errorinvalid_token
403permission_errorinsufficient_scope

Erreurs fréquentes

  • L’endpoint de jeton a sa propre limite par IP. Un jeton par processus, renouvelé avant expiration — et non un par requête.
  • Le client_secret n’est stocké que sous forme de hash ; si vous le perdez, créez un nouvel identifiant et révoquez l’ancien.
  • Créez des identifiants distincts pour l’ERP, la boutique et les scripts internes, chacun avec des scopes minimaux. Révoquer l’un n’affecte pas les autres.
  • CORS n’autorise aucune origine navigateur : l’API est conçue pour le serveur à serveur.

Questions et réponses pour développeurs

Que se passe-t-il si le client_secret est incorrect ?

Vous recevez une 401 avec le code invalid_client. Un secret trop court échoue plus tôt, dès la validation, avec 422 validation_failed et param client_secret.

Existe-t-il un environnement de test séparé ?

Non. Il n’y a qu’un seul hôte de production. Testez avec des factures pro forma (document_kind proforma) et avec /invoices/preview-totals, qui ne consomme aucun numéro fiscal.

Puis-je restreindre les scopes d’un identifiant existant ?

Oui, depuis le panneau. Les jetons déjà émis conservent les scopes avec lesquels ils ont été créés jusqu’à leur expiration, dans un délai d’une heure.