---
title: "Créer un brouillon de facture"
method: POST
path: "/invoices/draft"
tags: ["Invoices"]
---

# Créer un brouillon de facture

`POST /invoices/draft`

## Request

- Base URL: `https://api.swipify.fr/api/v1`
- URL: `https://api.swipify.fr/api/v1/invoices/draft`
- Auth: API key in header `X-API-Key`

Crée une facture au statut brouillon (non numérotée, non émise, non transmise à la sphère publique), émise depuis l'organisation de la clé. Le client est optionnel (complété ensuite dans l'app). Scope requis : `invoices:draft`.

**curl**
```bash
curl -X POST https://api.swipify.fr/api/v1/invoices/draft \
  -H "X-API-Key: sk_live_..." -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"lines":[{"description":"Pose carrelage","quantity":3,"unit":"jour","unitPrice":280,"vatRate":10}]}'
```

**JavaScript**
```js
await fetch("https://api.swipify.fr/api/v1/invoices/draft", {
  method: "POST",
  headers: { "X-API-Key": "sk_live_...", "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID() },
  body: JSON.stringify({ lines: [{ description: "Pose carrelage", quantity: 3, unitPrice: 280, vatRate: 10 }] }),
}).then((r) => r.json());
```

## Headers

- `Idempotency-Key` string

## Request body

- InvoiceDraftCreate
  - `customer` Customer: Client d'un document ou de `POST /clients`. Quand son SIRET, son numéro de TVA ou son e-mail (particulier) désigne une fiche connue, l'appel la met à jour champ par champ : un champ absent garde la valeur de la fiche, un champ envoyé vide (chaîne vide ou `null`) l'efface. Les quatre champs d'adresse suivent la même règle, sur l'adresse par défaut du client. Le reste de la fiche (autres contacts, notes, autres adresses) n'est pas touché.
    - `type` 'company' | 'individual', required
    - `name` string, nullable
    - `firstName` string, required
    - `lastName` string, required
    - `email` string, email, nullable: Sans accent avant l'arobase ; un domaine accentué est accepté.
    - `phone` string, nullable: Numéro français (06…, +33…, outre-mer compris) ou étranger avec son indicatif, 8 à 15 chiffres en tout, comme +32 470 12 34 56.
    - `address` string, nullable
    - `zipCode` string, nullable
    - `city` string, nullable
    - `country` string, nullable
    - `siret` string, nullable
    - `vatNumber` string, nullable: Numéro de TVA intracommunautaire, français (FR, clé de deux caractères, SIREN) ou d'un autre pays (les deux lettres du pays puis 2 à 13 caractères, dont au moins un chiffre), comme FR32123456789 ou BE0123456789. Espaces, points et tirets sont acceptés, le numéro est enregistré sans eux.
    - `formeJuridique` string, nullable
  - `clientId` integer: Référence un client existant (exclusif avec customer).
  - `lines` InvoiceLine[], required
    - `description` string, required
    - `quantity` number, required
    - `unitPrice` number, required
    - `vatRate` number, required
    - `unit` string: Unité connue ou abréviation (h, m2, ml, ens) ramenée à sa forme de référence et à son code de facture électronique, toute autre unité gardée telle quelle (code C62).
    - `catalogItemId` integer, nullable: Réf. optionnelle à un article du catalogue. Persistée sur les brouillons ; ignorée (null) si l'article n'appartient pas à l'organisation.
  - `object` string, nullable
  - `paymentMode` string, nullable
  - `brandProfileKey` string: Profil de marque mémorisé sur le brouillon et relu à la validation dans l'app. Absent → profil par défaut. Voir GET /brand-profiles pour la clé (elle diffère du nom affiché). Clé inconnue → 400.

## Response `201`

Brouillon créé

- Invoice
  - `id` integer
  - `number` string, nullable
  - `draftNumber` string, nullable
  - `status` string
  - `object` string, nullable
  - `date` string, date-time, nullable
  - `dueDate` string, date-time, nullable
  - `paidDate` string, date-time, nullable
  - `totalHT` string
  - `totalVAT` string
  - `totalTTC` string
  - `einvoiceStatus` 'pending' | 'delivered' | 'accepted' | 'rejected' | 'paid' | 'reported' | 'error' | 'null', nullable: Statut de cycle de vie e-invoice (PA). null si pas de cycle (brouillon/non conforme). `rejected` = refusée par la plateforme. `reported` = vente à un particulier, transmise en e-reporting : pas d'e-facture, donc ni remise ni acceptation client.
  - `brandProfileKey` string, nullable: Profil de marque du document. `null` = profil par défaut.
  - `reminderCount` integer: Nombre de relances d'impayé envoyées (manuelles et automatiques). L'envoi d'une relance reste un geste dans l'application, jamais un appel API.
  - `reminderLastSentAt` string, date-time, nullable: Date de la dernière relance d'impayé, null si jamais relancée.
  - `remindersPaused` boolean: true si les relances automatiques sont suspendues pour cette facture.
  - `recurring` boolean: true si la facture a été générée par une facture récurrente.
  - `createdAt` string, date-time

## Other responses

- `400`: Données invalides
- `401`: Échec d'authentification : clé API manquante (`missing_api_key`) ou invalide/révoquée/expirée (`invalid_api_key`). Le client doit présenter une clé valide.
- `403`: Clé authentifiée mais non autorisée : scope insuffisant pour cette route (`scope_required`), ou organisation sans abonnement Pro actif (`pro_required`). `GET /me` reste accessible sans Pro pour diagnostiquer la clé.
- `409`: Conflit (ressource déjà existante, limite atteinte ; sur les routes idempotentes, Idempotency-Key déjà en cours)
- `422`: Idempotency-Key déjà utilisée pour une AUTRE requête (méthode/chemin divergents)
- `429`: Trop de requêtes (quota de la clé API, ou de l'organisation pour les analyses de document, dépassé pour la fenêtre courante)

---

[API](https://skmtc.dev/swipify/apis/swipify-api-publique.md) · [All operations](https://skmtc.dev/swipify/apis/swipify-api-publique/llms.txt) · [OpenAPI document](https://skmtc.dev/swipify/apis/swipify-api-publique/revisions/44c17201b479?raw)
