Aller au contenu principal

Fournir votre propre PDF

Votre produit génère déjà des factures PDF à votre charte graphique, et vos clients y sont habitués. Cette page montre comment conserver ce rendu comme couche visible du Factur-X : vous transmettez votre PDF à la création de la facture, Scribee y embarque le XML CII généré depuis les données et produit un Factur-X (PDF/A-3 avec XML embarqué). Sans pdf_base64, Scribee génère lui-même la couche visible - c'est le chemin par défaut, aucun champ supplémentaire n'est requis.

Ce que Scribee fait pour vous​

  • Génération du XML : le fichier factur-x.xml (CII) est produit depuis les données JSON de la facture. Vous n'écrivez jamais de XML.
  • Assemblage PDF/A-3 : Scribee embarque ce XML dans votre PDF et y écrit les couches structurelles exigées - métadonnées XMP Factur-X, OutputIntent, arbre des fichiers associés. Un OutputIntent déjà présent dans votre PDF est conservé tel quel, sans que son profil colorimétrique soit revalidé : c'est à vous de fournir un PDF dont le profil est conforme.
  • Remplacement du XML existant : si votre PDF est déjà un Factur-X, son factur-x.xml est remplacé par celui généré depuis les données de la facture. Les données envoyées à l'API font foi.
  • Justificatifs : les pièces jointes de la facture sont embarquées dans le même fichier (Pièces jointes).
  • Validation de conformité : le fichier assemblé est vérifié contre PDF/A-3b et le résultat est exposé sur la facture (facturx_conformance).

Ce que Scribee ne fait pas : corriger le contenu de vos pages. Polices, couleurs et transparence relèvent de votre générateur PDF ; un contenu non conforme est détecté par la validation, jamais réparé.

Votre PDF, côté générateur​

Points à vérifier sur le fichier que produit votre générateur, avant le premier appel :

  • un document PDF - l'API cherche l'en-tête %PDF- dans le premier kilo-octet du fichier, pas nécessairement au tout premier octet ;
  • non chiffré, sans mot de passe ;
  • moins de 50 Mo une fois décodé ;
  • encodé en base64 - les retours à la ligne et un préfixe data:application/pdf;base64, sont acceptés ;
  • polices embarquées dans le fichier, transparence et espace colorimétrique conformes PDF/A-3b (couleurs device-independent), aucun JavaScript intégré - ces points ne sont pas contrôlés à l'appel mais par la validation de conformité qui suit, et Scribee ne les corrige pas.

Les quatre premiers points sont vérifiés de façon synchrone : un fichier non conforme est rejeté en 422 avant toute création. Le dernier se règle dans la configuration de votre générateur, une fois pour toutes.

Étape 1 : créer la facture avec votre PDF​

Cet appel crée une facture en brouillon dans votre workspace de production : tant qu'elle n'est pas déposée, elle ne transmet rien au destinataire, ni au PPF (Portail Public de Facturation), ni au réseau Peppol. Validez la conformité PDF/A-3b de votre générateur avant cet appel : une fois la facture créée, aucun endpoint ne permet de remplacer le PDF fourni ni, dans la plupart des cas, de supprimer le brouillon (voir Erreurs et cas limites, section "Le PDF ne se remplace pas").

Le champ pdf_base64 se place dans l'objet invoice, au même niveau que les autres champs de la facture. Le payload ci-dessous est réduit aux champs propres à cette page ; parties, lignes et totaux se construisent comme décrit dans Émettre une facture.

PDF_BASE64=$(base64 < facture-INV-2026-042.pdf | tr -d '\n')

cat > payload.json <<EOF
{
"invoice": {
"direction": "sales",
"invoice_number": "INV-2026-042",
"issue_date": "2026-07-31",
"type_code": "invoice",
"currency_code": "EUR",
"pdf_base64": "$PDF_BASE64"
}
}
EOF

curl -X POST https://app.scribee.tech/api/v1/workspaces/YOUR_WORKSPACE_ID/invoices \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d @payload.json

Réponse 201, abrégée aux champs qui concernent cette page :

{
"data": {
"id": 12345,
"invoice_number": "INV-2026-042",
"lifecycle_state": "draft",
"provided_pdf": true,
"facturx_conformance": "pending"
}
}

Les quatre champs invoice_number, issue_date, type_code et currency_code conditionnent la prise en compte du PDF : s'il en manque un, la facture est créée avec une valeur provisoire et une erreur d'import bloquante, et votre PDF est ignoré - provided_pdf vaut alors false dans la réponse. Vérifiez provided_pdf: true avant de passer à l'étape 2.

Étape 2 : lire le résultat de conformité​

L'assemblage et la validation s'exécutent après la réponse, en tâche de fond. Relisez la facture jusqu'à ce que facturx_conformance quitte pending.

curl https://app.scribee.tech/api/v1/invoices/12345 \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
{
"data": {
"id": 12345,
"invoice_number": "INV-2026-042",
"lifecycle_state": "draft",
"provided_pdf": true,
"facturx_conformance": "compliant"
}
}
facturx_conformanceSignificationConséquence
pendingLa validation n'a pas encore rendu son verdict, ou son traitement a échoué.Le dépôt reste possible dans le cas général - il relance la génération et la validation - sauf si le traitement du PDF a définitivement échoué (voir "pending qui persiste" plus bas). La transmission est bloquée.
compliantLe fichier assemblé est conforme PDF/A-3b.Dépôt et transmission autorisés.
non_compliantAu moins une règle PDF/A-3b est violée par le fichier.Dépôt et transmission bloqués.

facturx_conformance vaut null quand vous n'avez pas fourni de PDF : la couche visible générée par Scribee est conforme par construction et n'est pas soumise à cette validation. Une facture de vente importée sous forme de Factur-X fait exception : son fichier est jugé au dépôt, et le champ porte ce verdict (Importer des factures existantes).

Le dépôt est bloqué par non_compliant, et par un pending qui provient d'un refus du PDF au traitement, plutôt que d'une validation encore en attente ou d'un traitement qui n'a pas pu aboutir côté Scribee. Le dépôt n'envoie par lui-même rien vers le PPF ni sur le réseau Peppol.

Ce tableau décrit une facture de vente, celle que vous émettez. Sur une facture d'achat, le PDF est celui de votre fournisseur et Scribee n'émet rien : facturx_conformance prend la même valeur et les conséquences ci-dessus restent en place, mais le verdict non_compliant y est inscrit comme avertissement au lieu d'une erreur d'import bloquante. Il ne s'oppose donc pas au traitement de la facture reçue. Seul l'émetteur du PDF peut lever la non-conformité.

Étape 3 : récupérer le Factur-X assemblé​

Une fois la génération terminée, téléchargez le fichier final : votre rendu, complété du factur-x.xml, des métadonnées XMP et des justificatifs embarqués.

curl -o INV-2026-042-facturx.pdf \
"https://app.scribee.tech/api/v1/invoices/12345/download?format=facturx" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Les autres formats d'export (pdf, ubl, cii) sont décrits dans Formats et téléchargements.

Ce qui se passe ensuite​

  • La création de la facture déclenche une notification vers vos endpoints configurés (Webhooks).
  • La génération des fichiers d'export part en tâche de fond ; c'est elle qui assemble le Factur-X, exécute la validation de conformité et met à jour facturx_conformance.
  • Chaque dépôt (deposit) relance la génération et la validation. Un pending se résout le plus souvent de lui-même, mais pas toujours : quand le validateur est indisponible ou tombe en erreur, le champ est réécrit à pending. Un pending qui persiste sur plusieurs relectures est à signaler au support, pas à attendre.
  • Aucun document n'est transmis à un destinataire ni au réseau réglementaire tant que la facture est en brouillon. Vos propres endpoints de webhook, eux, reçoivent bien invoice.created dès la création (Webhooks). Le dépôt et le suivi des statuts sont couverts par Émettre une facture.

Erreurs et cas limites​

422 à la création : PDF rejeté​

Quatre contrôles synchrones rejettent l'appel avant toute création. Le corps suit l'enveloppe d'erreur de l'API (Conventions de l'API), avec le code operation_failed et sans clé details :

{
"error": "unprocessable_entity",
"code": "operation_failed",
"message": "Le PDF fourni est chiffré et ne peut pas être traité."
}
messageCauseCe que vous faites
Le PDF fourni n'est pas encodé en base64 valide.La chaîne ne se décode pas en base64.Ré-encodez le fichier ; retours à la ligne et préfixe data-URI sont acceptés, pas les caractères hors alphabet base64.
Le fichier fourni n'est pas un document PDF valide.L'en-tête %PDF- est absent du premier kilo-octet du fichier, ou le fichier ne peut pas être analysé.Vérifiez que vous encodez le PDF final, pas un autre format ni une archive.
Le PDF fourni dépasse la taille maximale autorisée de 50 Mo.Le fichier décodé atteint 50 Mo.Réduisez le poids du fichier, en général par compression des images.
Le PDF fourni est chiffré et ne peut pas être traité.Le PDF est protégé par mot de passe ou chiffré.Générez le fichier sans protection.

provided_pdf à false dans la réponse 201​

Deux causes, indiscernables dans la réponse. La première : un des quatre champs invoice_number, issue_date, type_code, currency_code manquait, et la charge utile n'a jamais atteint l'étape d'attachement. La seconde : l'attachement lui-même a échoué (stockage indisponible, par exemple) ; l'erreur est alors avalée en avertissement d'import et la création répond quand même 201. Les deux cas ne se comportent pas de la même façon. Champs manquants : la charge utile n'atteint jamais l'étape d'attachement, rien n'est conservé. Échec de l'attachement : le fichier peut avoir été stocké avant l'erreur, et la génération des exports est lancée quand même - la facture existe alors sans provided_pdf, avec des exports rendus par Scribee. Dans les deux cas votre PDF n'est pas celui qui sera servi. Un PATCH des champs manquants ne rattache pas le PDF après coup (voir "Le PDF ne se remplace pas" plus bas) : contrôlez provided_pdf dans la réponse et recréez la facture si besoin.

Dépôt refusé sur non_compliant​

La transition deposit est refusée tant que le fichier est non conforme. Le verdict de non-conformité est inscrit sur la facture comme erreur d'import bloquante, mais c'est le contrôle de conformité - le premier évalué au dépôt - qui nomme le refus :

{
"error": "unprocessable_entity",
"code": "operation_failed",
"message": "Le PDF Factur-X joint n'est pas conforme. Remplacez-le par un fichier conforme avant de déposer la facture.",
"details": {}
}

Le message nomme donc le PDF, mais pas la règle en échec. Le détail des règles en échec est visible sur la facture depuis l'interface Scribee. Corrigez la configuration de votre générateur PDF (polices, couleurs, transparence) pour vos prochains envois : ce brouillon-ci ne peut ni recevoir un nouveau PDF ni, dans la plupart des cas, être supprimé (voir "Le PDF ne se remplace pas" plus bas).

pending qui persiste​

  • Avec dépôt refusé : le traitement a refusé le fichier (un PDF malformé, ou trop coûteux à traiter : son assemblage a dépassé le budget de calcul qui lui est alloué) ; le dépôt reste bloqué même si facturx_conformance affiche encore pending. L'échec de traitement est enregistré comme erreur d'import bloquante, et faute de verdict de non-conformité, le refus porte cette fois le message générique La facture comporte des erreurs d'import bloquantes. Corrigez-les avant de changer son statut. (Émettre une facture). Aucun endpoint ne permet de corriger le PDF sur ce brouillon (voir "Le PDF ne se remplace pas").
  • Avec dépôt accepté : la validation n'a pas encore conclu ; le dépôt la relance. C'est aussi le cas quand le traitement dépasse son délai global d'exécution côté Scribee, ce qui est distinct d'un PDF qui épuise son budget de calcul : il s'agit d'un incident côté Scribee, pas d'un verdict sur votre PDF, et il est enregistré comme avertissement, qui ne bloque pas le dépôt. facturx_conformance repasse alors à pending. La transmission attend compliant.

Le PDF ne se remplace pas​

PATCH /api/v1/invoices/{id} ignore pdf_base64 et purge le PDF déjà fourni dès qu'un brouillon est modifié, même sur un autre champ : provided_pdf repasse à false et facturx_conformance à null, la facture repart sur la couche visible générée par Scribee. DELETE /api/v1/invoices/{id} ne résout la situation que dans un cas : le brouillon est supprimable quand son numéro est vide ou commence par DRAFT-. C'est le cas du numéro temporaire que Scribee génère lui-même, et de tout numéro que vous fournissez avec ce préfixe. Tout autre invoice_number fourni consomme un numéro définitif et la suppression échoue en 403. Validez la conformité PDF/A-3b de votre générateur avant le premier appel : une fois la facture créée, aucun endpoint ne permet de corriger ou de remplacer le PDF fourni.

Pages liées​