Skip to content

yawo/onefacture

Repository files navigation

Logo onefacture
onefacture

La passerelle API Open Source unifiée pour la Facturation Électronique Française (Réforme 2026)

Quick StartProblemSolutionProject StructureConfigurationAPI ReferencePlans & PricingData ModelDevelopmentTestingTroubleshootingArchitectureContributingLicense


Quick Start

Prerequisites

Tool Version Purpose
Go 1.23+ API Gateway binary
Docker & Docker Compose Latest Postgres, Redis, sidecar services
Python 3.10+ 3.10+ Factur-X validation sidecar
Make any Task runner

1. Clone and start infrastructure

git clone https://github.com/yawo/onefacture.git
cd onefacture

Copy the default environment file and edit if needed:

cp .env.example .env

Start all services:

make dev

This launches:

Service Port Purpose
onefacture API 8080 Main API Gateway
PostgreSQL 5432 Primary data store
Redis 6379 Event bus / streams
Validation sidecar 9091 Factur-X XML validation (Python)

2. Run database migrations

make migrate-up

3. Create an API key (sandbox)

# The sandbox route provisions credentials automatically
curl -X POST http://localhost:8080/v1/sandbox/credentials

# Or manually via the API with an admin key
curl -X POST http://localhost:8080/v1/admin/api-keys \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"organization_id": "org-uuid-here", "label": "my-key"}'

The response includes an X-API-Key value — use this for all subsequent requests.

4. Send your first invoice

curl -X POST http://localhost:8080/v1/invoices \
  -H "X-API-Key: $ONEFACTURE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "profile": "EN16931",
    "type_code": "380",
    "number": "INV-2026-0001",
    "currency": "EUR",
    "issue_date": "2026-06-01T00:00:00Z",
    "due_date": "2026-07-01T00:00:00Z",
    "seller": {
      "name": "Acme SAS",
      "siren": "732829320",
      "address": { "line1": "1 rue Cler", "postal_code": "75007", "city": "Paris", "country_code": "FR" }
    },
    "buyer": {
      "name": "Globex SAS",
      "siren": "552120222",
      "address": { "line1": "2 avenue Foch", "postal_code": "75116", "city": "Paris", "country_code": "FR" }
    },
    "lines": [
      { "description": "Consulting services", "quantity": 10, "unit_code": "HUR", "unit_price": 150, "tax_rate": 20, "tax_category": "S" }
    ]
  }'

5. Browse the interactive docs

Open http://localhost:8080/docs for the Scalar API reference.


Problem

Starting September 1st, 2026, French law mandates that all domestic B2B transactions subject to VAT must be issued, transmitted, and received in electronic format. This isn't simply exchanging PDFs — it requires strict data formats (Factur-X, UBL, CII) and routing through a complex network of Plateformes de Dématérialisation Partenaires (PDP) and the Portail Public de Facturation (PPF) (the "Y-scheme").

For ERP vendors, SaaS platforms, and in-house systems, this creates:

  • Fragmentation: 100+ certified platforms (Sage, Pennylane, Docaposte, Cegid, Qonto, etc.), each with their own proprietary API.
  • Normative Complexity: Generating PDF/A-3 files with embedded XML (Factur-X) and validating against hundreds of business rules (Schematron / AFNOR) requires heavy tooling.
  • Vendor Lock-in: Connecting directly to a single PDP ties your invoicing logic to their specific infrastructure.

Solution

onefacture is a unified, open-source API Gateway that abstracts all complexity of the French electronic invoicing ecosystem.

Instead of developing dozens of point-to-point integrations, your application communicates with a single REST API. onefacture handles: Factur-X generation, strict EN 16931 validation, dynamic PDP routing, and lifecycle tracking.

Standards implemented

Standard Description
XP Z12-012 Invoice message formats and profiles
XP Z12-013 Standard API for business ↔ PA interfacing
XP Z12-014 B2B usage cases
EN 16931 European invoicing standard
Factur-X 1.08 French PDF+XML hybrid format

Project Structure

onefacture/
├── cmd/
│   ├── api/              # Main API server entrypoint
│   │   └── main.go       # Wire-up, graceful shutdown
│   └── genopenapi/       # OpenAPI spec generator
├── internal/
│   ├── adapters/         # PA (Platform Partner) adapters
│   │   ├── chorus/       # Chorus Pro / PPF
│   │   ├── docaposte/    # Docaposte SERES
│   │   ├── pennylane/    # Pennylane
│   │   ├── cegid/        # Cegid
│   │   ├── qonto/        # Qonto
│   │   ├── mock/         # Mock adapter for tests
│   │   ├── sandbox/      # Sandbox mode client
│   │   ├── registry/     # Adapter registry
│   │   └── types.go      # PAAdapter interface definition
│   ├── billing/          # Subscription management, usage tracking, Stripe integration
│   │   ├── service.go    # Billing service (register, auth, usage checks, Stripe webhooks)
│   │   ├── stripe.go     # Stripe checkout / portal / webhook client
│   │   ├── tiers.go      # Plan tiers (Free, Starter, Advanced, Enterprise) & limits
│   │   └── password.go   # bcrypt password hashing
│   ├── config/           # Configuration loading from env
│   ├── core/
│   │   ├── invoice/      # Core domain: Invoice model, state, totals, formats
│   │   └── facturx/      # Factur-X PDF/XML generation
│   ├── dir/              # PA directory lookup
│   ├── events/           # Event bus (Redis Streams)
│   ├── gateway/
│   │   ├── routes/       # HTTP handlers (CRUD, submission, inbox, validation, billing, auth)
│   │   ├── middleware/   # API key auth, JWT auth, rate limiting, logging, usage tracking
│   │   ├── openapi/      # OpenAPI spec generation
│   │   ├── problem/      # RFC 7807 problem details
│   │   └── server.go     # Chi router assembly
│   ├── metrics/          # Prometheus metrics
│   ├── jurisdiction/     # Multi-jurisdiction tax rules
│   ├── reliability/      # Circuit breaker, retry with jitter
│   ├── security/         # KMS/BYOK encryption, AES-256-GCM
│   ├── storage/          # PostgreSQL persistence layer
│   │   ├── migrations/   # SQL migrations (init + SaaS tables)
│   │   ├── users.go      # User model & repo
│   │   ├── subscriptions.go # Subscription model & repo
│   │   ├── usage.go      # Usage tracking repo
│   │   └── ...
│   ├── validation/       # Validation client (Python sidecar)
│   ├── webhooks/         # Webhook delivery engine (retry, HMAC signing)
│   └── workers/          # Background workers (status polling)
├── sidecar/
│   ├── app/              # Python sidecar: Factur-X validation (lxml, Schematron)
│   └── tests/            # Sidecar tests
├── scripts/              # Utility scripts
├── docs/                 # Documentation assets
├── docker-compose.yml    # Dev environment
└── Makefile              # Build, test, dev commands

Configuration

All configuration is via environment variables with the ONEFACTURE_ prefix.

Core

Variable Required Default Description
ONEFACTURE_ENV no development Runtime environment
ONEFACTURE_HTTP_ADDR no :8080 API listen address
ONEFACTURE_PUBLIC_BASE_URL no http://localhost:8080 Public-facing base URL (CORS, JWT, webhooks)
ONEFACTURE_DB_DSN yes PostgreSQL connection string
ONEFACTURE_REDIS_ADDR yes localhost:6379 Redis address
ONEFACTURE_SIDECAR_URL yes http://localhost:9091 Validation sidecar URL
ONEFACTURE_LOG_LEVEL no info Log level (debug, info, warn, error)

Database

Variable Default Description
ONEFACTURE_DB_MAX_CONNS 20 Max pool connections
ONEFACTURE_DB_CONNECT_TIMEOUT 5s Connection timeout
ONEFACTURE_DB_STATEMENT_CACHE true Enable prepared statement cache

Encryption / KMS

Variable Description
ONEFACTURE_ENCRYPTION_KEY_ID Local key identifier (for static key mode)
ONEFACTURE_ENCRYPTION_KEY AES-256 key as hex string (64 hex chars)
ONEFACTURE_KMS_URL HTTP KMS broker base URL (for production)
ONEFACTURE_KMS_TOKEN Workload auth token for KMS broker

Rate Limiting

Variable Default Description
ONEFACTURE_RATE_LIMIT_PER_MIN 600 Requests per minute per API key

Authentication

Variable Required Description
ONEFACTURE_BOOTSTRAP_API_KEY no Initial admin API key for first-time setup
ONEFACTURE_HASH_PEPPER yes (non-dev) Pepper for API key bcrypt hashing

Billing / Stripe

Variable Required Default Description
ONEFACTURE_STRIPE_SECRET_KEY no Stripe secret key (sk_live_xxx)
ONEFACTURE_STRIPE_WEBHOOK_SECRET no Stripe webhook signing secret (whsec_xxx)
ONEFACTURE_JWT_SECRET no dev-jwt-secret-change-in-production JWT signing key for auth tokens
ONEFACTURE_PRICE_FREE no Stripe price ID for Free tier
ONEFACTURE_PRICE_STARTER no Stripe price ID for Starter tier
ONEFACTURE_PRICE_ADVANCED no Stripe price ID for Advanced tier
ONEFACTURE_PRICE_ENTERPRISE no Stripe price ID for Enterprise tier

Tier Display Prices

Variable Default Description
ONEFACTURE_DISPLAY_PRICE_FREE 0 €/mois Display price for Free tier
ONEFACTURE_DISPLAY_PRICE_STARTER 49 €/mois Display price for Starter tier
ONEFACTURE_DISPLAY_PRICE_ADVANCED 199 €/mois Display price for Advanced tier
ONEFACTURE_DISPLAY_PRICE_ENTERPRISE 999 €/mois Display price for Enterprise tier

Tier Transaction Limits

Overrides per-tier monthly limits. 0 or unset = use hardcoded defaults (50/1k free, 500/10k starter, 5k/100k advanced, unlimited enterprise).

Variable Description
ONEFACTURE_TIER_FREE_INVOICES Max invoices/month for Free
ONEFACTURE_TIER_FREE_API_CALLS Max API calls/month for Free
ONEFACTURE_TIER_STARTER_INVOICES Max invoices/month for Starter
ONEFACTURE_TIER_STARTER_API_CALLS Max API calls/month for Starter
ONEFACTURE_TIER_ADVANCED_INVOICES Max invoices/month for Advanced
ONEFACTURE_TIER_ADVANCED_API_CALLS Max API calls/month for Advanced
ONEFACTURE_TIER_ENTERPRISE_INVOICES Max invoices/month for Enterprise
ONEFACTURE_TIER_ENTERPRISE_API_CALLS Max API calls/month for Enterprise

Adapter configuration

Each PA adapter has its own prefix:

Variable Description
ONEFACTURE_CHORUS_CLIENT_ID Chorus Pro OAuth2 client ID
ONEFACTURE_CHORUS_CLIENT_SECRET Chorus Pro OAuth2 client secret
ONEFACTURE_CHORUS_BASE_URL Chorus Pro API base URL
ONEFACTURE_PENNYLANE_API_KEY Pennylane API key
ONEFACTURE_PENNYLANE_BASE_URL Pennylane API base URL
ONEFACTURE_DOCAPOSTE_API_KEY Docaposte SERES API key
ONEFACTURE_DOCAPOSTE_BASE_URL Docaposte SERES API base URL

API Reference

Authentication

API requests use one of two authentication methods:

API Key — Pass via the X-API-Key header. Used for most endpoints.

curl -H "X-API-Key: $ONEFACTURE_API_KEY" http://localhost:8080/v1/invoices

JWT Bearer Token — Used for billing and user-facing endpoints. Obtain via /auth/login.

curl -H "Authorization: Bearer $JWT_TOKEN" http://localhost:8080/billing/usage

API keys are organization-scoped. Create one via the sandbox endpoint or admin API.

Auth (User Registration & Login)

Method Path Description
POST /auth/register Register a new organization + admin user
POST /auth/login Login with email/password, receive JWT
GET /auth/me Get current user and organization info

Billing & Subscription

Method Path Description
GET /billing/plans List available pricing plans and their limits
GET /billing/subscription Get current subscription tier and status
POST /billing/checkout Create a Stripe Checkout session for upgrade
GET /billing/portal Open Stripe Customer Portal to manage subscription
GET /billing/usage Get current monthly usage vs plan limits
POST /billing/stripe-webhook Stripe event webhook (signature-verified, public)

Invoices

Method Path Description
POST /v1/invoices Create and optionally submit an invoice
GET /v1/invoices/{id} Get invoice details and current status
GET /v1/invoices/{id}/timeline Full lifecycle event history
POST /v1/invoices/{id}/submit Submit a DRAFT invoice to the PA
POST /v1/invoices/{id}/retry Resolve a rejection and resubmit
POST /v1/invoices/{id}/cancel Cancel an invoice

Inbox (Received Invoices)

Method Path Description
GET /v1/inbox List invoices received from the network
GET /v1/inbox/{id} Get a received invoice
POST /v1/inbox/{id}/approve Approve a received invoice
POST /v1/inbox/{id}/reject Reject a received invoice

Validation

Method Path Description
POST /v1/validate Validate a Factur-X/UBL/CII file (multipart upload)

Webhooks

Method Path Description
POST /v1/webhooks Register a webhook endpoint
GET /v1/webhooks List registered endpoints
PUT /v1/webhooks/{id} Update a webhook endpoint
DELETE /v1/webhooks/{id} Delete a webhook endpoint
GET /v1/webhooks/deliveries List delivery logs

Directory

Method Path Description
GET /v1/directory/lookup Look up a recipient's PA by SIREN
GET /v1/platforms List supported PAs and their health status

Sandbox

Method Path Description
POST /v1/sandbox/credentials Provision sandbox API credentials

Error Format

All errors follow RFC 7807 (Problem Details):

{
  "type": "https://onefacture.io/errors/validation-failed",
  "title": "Validation Failed",
  "status": 422,
  "detail": "Invoice validation failed: line 1 tax rate must be positive",
  "instance": "/v1/invoices",
  "errors": [
    { "field": "lines[0].tax_rate", "code": "INVALID", "message": "must be positive" }
  ]
}

Data Model

Invoice

Based on Factur-X 1.08 / EN 16931.

Field Type Description
id uuid Unique invoice identifier
status string DRAFT, SUBMITTED, RECEIVED, REJECTED, PAID, CANCELLED
profile string MINIMUM, BASIC, EN16931, EXTENDED
type_code string 380 (invoice), 381 (credit note), 384 (corrective)
number string Invoice number from the issuer
currency string ISO 4217 currency code (default: EUR)
issue_date date Date of issue
due_date date Payment due date
seller object Seller information (name, siren, address, VAT ID, email)
buyer object Buyer information
lines array Invoice lines
totals object Computed totals (net, tax, gross)
notes array Structured notes (credit note reason, corrections)

Invoice Status Lifecycle

DRAFT ──→ SUBMITTED ──→ RECEIVED ──→ APPROVED ──→ PAID
               │             │
               ↓             ↓
           REJECTED      REJECTED
               │
               ↓
           CANCELLED

Webhook Events

Invoices generate webhook events on every status transition:

Event Description
invoice.submitted Invoice submitted to PA
invoice.received Invoice received via network
invoice.approved Invoice approved by buyer
invoice.rejected Invoice rejected
invoice.paid Invoice marked paid
invoice.cancelled Invoice cancelled

Development

Make targets

make dev              # Start all services with Docker Compose
make build            # Build the API binary
make test             # Run unit tests
make test-short       # Run tests excluding integration (no Docker needed)
make test-race        # Run tests with race detector
make lint             # Run golangci-lint
make migrate-up       # Run database migrations
make migrate-down     # Rollback migrations
make coverage         # Generate coverage report
make clean            # Stop services and clean build artifacts

Running the sidecar

The Python validation sidecar runs on port 9091:

cd sidecar
pip install -r requirements.txt
python app/main.py

Code style

  • Go 1.23+ — Standard library preferred
  • Error wrapping — Always use fmt.Errorf("context: %w", err)
  • Testing — Unit tests live alongside source (*_test.go), integration tests use //go:build integration tag
  • Secrets — Never hardcode; always use ONEFACTURE_* env vars
  • Lintgolangci-lint must pass without warnings

Commit conventions

We follow Conventional Commits:

feat: add Docaposte adapter
fix: correct tax rounding in totals calculation
chore: update dependencies
docs: add webhook delivery documentation

Testing

Test categories

Tag Command Requirements Coverage
Unit (no tag) go test ./... None Core logic, handlers, validation rules
Integration go test -tags=integration ./... Docker (Postgres, Redis) DB, event bus, full workflows

Running tests

# Quick check (no Docker needed)
go test -short ./...

# Full suite with race detection
go test -race -short ./...

# Integration tests (Docker required)
make test

# For CI without Docker
go test -short ./...   # Skips all integration tests automatically

Adding integration tests

  1. Add //go:build integration at the top of the test file
  2. Use testcontainers-go for Postgres/Redis in tests
  3. Tagged files are excluded from go test ./... and go test -short ./...

Troubleshooting

go build fails

# Ensure Go 1.23+
go version

# Clear build cache if you see stale errors
go clean -cache

# Verify dependencies
go mod tidy

Docker services won't start

# Check Docker is running
docker ps

# Rebuild and restart
docker compose down -v
make dev

# Check logs
docker compose logs postgres redis

Database errors

# Run migrations explicitly
make migrate-up

# Reset database
docker compose down -v
docker compose up -d postgres
sleep 3
make migrate-up

Sidecar validation failing

# Check sidecar is running
curl http://localhost:9091/health

# View sidecar logs
docker compose logs validator

# Run sidecar directly (for debugging)
cd sidecar
pip install -r requirements.txt
python -m pytest tests/ -v
python app/main.py --port 9091

"API key invalid" errors

# Provision a new sandbox key
curl -X POST http://localhost:8080/v1/sandbox/credentials

# Verify the key works
curl -H "X-API-Key: <key>" http://localhost:8080/v1/platforms

Architecture

System design

┌─────────────────────────────────────────────────┐
│              Client / ERP / SaaS                │
│         (Sage, Odoo, custom app...)             │
└───────────────────┬─────────────────────────────┘
                    │  REST API onefacture (OpenAPI 3.1)
                    ▼
┌──────────────────────────────────────────────────────┐
│              onefacture API Gateway                   │
│  ┌──────────┐ ┌───────────┐ ┌────────────────────┐   │
│  │ Auth     │ │ Router    │ │ Validation Pipeline │   │
│  │ (API Key)│ │ (Chi)     │ │ (Sidecar gRPC)     │   │
│  └──────────┘ └───────────┘ └────────────────────┘   │
│  ┌──────────┐ ┌───────────┐ ┌────────────────────┐   │
│  │ Rate     │ │ OpenAPI   │ │ Adapter Registry   │   │
│  │ Limiter  │ │ Docs      │ │ & Router           │   │
│  └──────────┘ └───────────┘ └────────────────────┘   │
│  ┌──────────────────────────────────────────────┐    │
│  │   Reliability Layer (Retry / Circuit Breaker)│    │
│  └──────────────────────────────────────────────┘    │
└──────────┬──────────────────────────────┬────────────┘
           │                              │
    ┌──────▼──────┐                ┌─────▼──────┐
    │  PostgreSQL  │                │    Redis   │
    │  + pgvector  │                │   Streams  │
    └─────────────┘                └────────────┘
           │                              │
    ┌──────▼──────────────────────────────▼──────┐
    │  Validation Sidecar (Python / lxml)         │
    │  │ XSD     │ Schematron │ Business Rules │  │
    └─────────────────────────────────────────────┘

Stack

Layer Technology Purpose
API Gateway Go 1.23+, Chi router High-concurrency HTTP server
Validation Python sidecar (lxml, Schematron) Factur-X/UBL/CII validation
Database PostgreSQL + pgx v5 Multi-tenant persistence
Event Bus Redis Streams (go-redis v9) Async webhook delivery
Encryption AES-256-GCM, BYOK/KMS At-rest document encryption
Documentation OpenAPI 3.1 + Scalar Interactive API docs

Reliability patterns

  • Circuit Breaker — 3 consecutive failures → open for 30s (applies to all PA adapter calls)
  • Retry with jitter — Up to 3 attempts, exponential backoff (50ms base → 2s max) with ±25% jitter
  • Dead Letter Queue — Rejected submissions are persisted for manual review and replay
  • Webhook delivery — Up to 8 retries with exponential backoff, HMAC-SHA256 signing

Security

  • API Key authentication — Organization-scoped keys with bcrypt hashing at rest
  • Rate limiting — Per-key Redis-based sliding window
  • Encryption at rest — AES-256-GCM envelope encryption for invoice XML/PDF payloads
  • Webhook signing — HMAC-SHA256 signatures on all outgoing webhooks
  • IP allowlisting — Optional IP allowlist per webhook endpoint
  • mTLS — Optional mutual TLS for webhook endpoints

Adaptateurs PA (Platform Adapters)

Interface

type PAAdapter interface {
    Name() string
    Submit(ctx context.Context, inv *Invoice) (*SubmitResult, error)
    GetStatus(ctx context.Context, paRef string) (*LifecycleEvent, error)
    Webhook(ctx context.Context, payload []byte) (*WebhookEvent, error)
    HealthCheck(ctx context.Context) error
}

Each adapter is wrapped with the reliability layer (retry + circuit breaker) automatically.

Implemented

PA Status Auth
Chorus Pro / PPF OAuth2 client credentials
Pennylane API Key
Docaposte (SERES) API Key
Cegid API Key
Qonto API Key

Adding a new adapter

  1. Create a new package under internal/adapters/<name>/
  2. Implement the PAAdapter interface
  3. Register it in internal/adapters/registry/
  4. Document env vars required for configuration

Validation Pipeline

onefacture validates invoices through 6 layers:

PDF/A-3  →  XML Extraction  →  XSD Schema  →  Schematron  →  Business  →  Score
  1. PDF/A-3 — Validate the PDF container (if Factur-X format)
  2. Extraction — Extract embedded CII or UBL XML
  3. XSD — Validate against EN 16931 schemas
  4. Schematron — Apply AFNOR business rules (XP Z12-012)
  5. Business — SIREN coherence, VAT structure, total calculations
  6. Score — Structured error report (RFC 7807)

Business Use Cases

Credit Note (Type 381)

{
  "profile": "EN16931",
  "type_code": "381",
  "number": "AV-2026-0001",
  "currency": "EUR",
  "issue_date": "2026-05-22T00:00:00Z",
  "seller": { "name": "Acme SAS", "siren": "732829320", "address": { "line1": "1 rue Cler", "postal_code": "75007", "city": "Paris", "country_code": "FR" } },
  "buyer": { "name": "Globex SAS", "siren": "552120222", "address": { "line1": "2 avenue Foch", "postal_code": "75116", "city": "Paris", "country_code": "FR" } },
  "lines": [{ "description": "Credit note", "quantity": 1, "unit_code": "C62", "unit_price": 250, "tax_rate": 20, "tax_category": "S" }],
  "notes": [{ "subject": "credit_note", "content": "Credit for INV-2026-0007" }]
}

Retry a rejected invoice

curl -X POST "http://localhost:8080/v1/invoices/{invoice_id}/retry" \
  -H "X-API-Key: $ONEFACTURE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"resolution_hint": "SIREN acheteur corrige dans ERP"}'

Plans & Pricing

onefacture offers four subscription tiers with usage-based limits enforced per organization.

Tier Price Invoices/mo API Calls/mo Support SLA Dashboard Onboarding
Free 0 €/mois 50 1 000 Community none Self-serve
Starter 49 €/mois 500 10 000 Email 99.5% Self-serve
Advanced 199 €/mois 5 000 100 000 Priority 99.9% Email
Enterprise 999 €/mois Illimité Illimité Premium 99.99% Dédié

Usage is tracked monthly — when a limit is reached, the API returns 429 Too Many Requests. Upgrade via the Stripe Checkout session (POST /billing/checkout) or manage from the Customer Portal.

How it works

  1. RegistrationPOST /auth/register creates an organization + admin user + Free subscription.
  2. AuthenticationPOST /auth/login returns a JWT used for billing endpoints.
  3. Check usageGET /billing/usage shows current month consumption vs plan limits.
  4. UpgradePOST /billing/checkout with {"tier": "starter", "success_url": "...", "cancel_url": "..."} redirects to Stripe.
  5. ManageGET /billing/portal opens Stripe Customer Portal for plan changes / payment methods.

All subscriptions sync in real-time via Stripe webhooks (POST /billing/stripe-webhook).


Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feat/my-feature)
  3. Make your changes
  4. Run tests (go test -short ./...)
  5. Run linter (golangci-lint run)
  6. Commit with Conventional Commits (feat:, fix:, docs:, etc.)
  7. Open a pull request

Before submitting a PR

  • go build ./... passes
  • go vet ./... passes
  • go test -short ./... passes
  • golangci-lint run passes
  • Code follows project style (error wrapping, naming conventions)
  • Tests cover new functionality
  • Integration tests are tagged with //go:build integration

License

Ce projet est distribué sous licence Server Side Public License (SSPL). Voir le fichier LICENSE pour plus de détails.

This project is licensed under the Server Side Public License (SSPL). See the LICENSE file for details.


onefacture — Unified e-invoicing for France. Built with in Paris.

About

Un seul routeur central pour les systèmes PA français (plateforme agréée), évitant ainsi la complexité de multiples intégrations spécifiques. Connectez-vous une seule fois et configurez des routes uniques vers votre système PA. Changez de système PA facilement.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors