Skip to main content

Tax Bundles

This guide explains how to collect and analyze a company’s tax bundles from multiple sources and formats.

Goal

Collect detailed tax bundles:

  • From public sources (INPI via company_legal_fr)
  • From Infogreffe for confidential tax bundles
  • From the impots.gouv professional space (private data)
  • Via OCR performed on uploaded PDF documents

Data sources

Tax bundle pipelines

Mix public filings, secure OAuth flows, and OCR uploads for maximum coverage.

INPI (Public)

Provider: `company_legal_fr`

  • Automatic sync
  • Published bundles (≈6-month lag)
  • No OAuth needed
  • Free access

Infogreffe

Provider: `infogreffe`

  • Confidential tax bundles
  • Requires Infogreffe account
  • Automatic sync
  • Last 2 tax returns by default

Impots.gouv

Provider: `impots_gouv`

  • OAuth redirect (pro space)
  • Real-time tax data + VAT
  • Corporate tax & tax account
  • User-level consent required

OCR Service

Provider: `ocr_service`

  • Manual PDF uploads
  • Automatic data extraction
  • Works with scans or exports
  • Quality depends on document
SourceProviderAdvantagesDrawbacks
INPIcompany_legal_frAutomatic, freePublication delay (~6 months)
InfogreffeinfogreffeConfidential tax bundlesRequires Infogreffe account
Impots.gouvimpots_gouvReal-time data, VATRequires user OAuth
OCRocr_serviceAny PDF documentQuality depends on the scan

Structure of a tax bundle

Bundle types

CodeTypeDescription
CFullStandard regime - 2050 to 2059 bundle
SSimplifiedSimplified regime - 2033 bundle
KConsolidatedConsolidated accounts

Main forms (Standard Regime)

FormContent
2050-SDBalance sheet - Assets
2051-SDBalance sheet - Liabilities
2052-SDIncome statement (I)
2053-SDIncome statement (II)
2054-SDFixed assets
2055-SDDepreciation
2056-SDProvisions
2057-SDReceivables and payables

Main forms (Simplified Regime)

FormContent
2033-A-SDSimplified balance sheet
2033-B-SDSimplified income statement
2033-C-SDFixed assets

Implementation

Option 1: INPI public data

Configuration

PUT /api/v6/providers/company_legal_fr
{
"enable": true
}
PUT /api/v6/providers/company_legal_fr/settings
{
"auto_connect": true
}

Create the user and launch the sync

POST /api/v6/users/legal
{
"name": "Entreprise SAS",
"siren": "123456789"
}
POST /api/v6/users/{userId}/data-connections
{
"requested_data_types": ["TAX_RETURN", "TAX_RETURN_ANALYSIS"],
"provider_name": "company_legal_fr"
}
POST /api/v6/users/{userId}/sync
{
"data_types": ["TAX_RETURN", "TAX_RETURN_ANALYSIS"]
}

Option 2: Infogreffe confidential data

Infogreffe gives access to confidential tax bundles that are not available via INPI.

Configuration

PUT /api/v6/providers/infogreffe/credentials
{
"credentials": {
"client_id": "INFOGREFFE_CLIENT_ID",
"password": "INFOGREFFE_PASSWORD"
}
}
PUT /api/v6/providers/infogreffe/settings
{
"auto_connect": true,
"confidential_only": true
}
PUT /api/v6/providers/infogreffe
{
"enable": true
}

Create the connection and sync

POST /api/v6/users/{userId}/data-connections
{
"requested_data_types": ["TAX_RETURN", "TAX_RETURN_ANALYSIS"],
"provider_name": "infogreffe"
}
POST /api/v6/users/{userId}/sync
{
"data_types": ["TAX_RETURN", "TAX_RETURN_ANALYSIS"]
}
info

By default, Infogreffe returns the last 2 available tax bundles regardless of the year. You can adjust this through the month history setting.

Option 3: Impots.gouv private data

Configuration

PUT /api/v6/providers/impots_gouv
{
"enable": true
}

Create the connection

POST /api/v6/users/{userId}/data-connections
{
"requested_data_types": [
"TAX_RETURN",
"VAT_DECLARATION",
"CORPORATE_TAX",
"TAX_ACCOUNT"
],
"provider_name": "impots_gouv"
}

Authentication flow

  1. Retrieve the user redirect_url
  2. Redirect the user to that link
  3. The user signs in on impots.gouv.fr
  4. They grant access to their data
  5. They are redirected back to your return_url
  6. You can now trigger the synchronization
POST /api/v6/users/{userId}/sync
{
"data_types": ["TAX_RETURN", "VAT_DECLARATION"]
}

Option 4: OCR applied to PDF documents

Configuration

PUT /api/v6/providers/ocr_service
{
"enable": true
}

Upload and processing

The OCR service extracts tax bundle data from scanned or exported PDFs. See the OCR Service provider documentation for implementation details.

Retrieve the data

List tax bundles

GET/api/v6/users/{userId}/tax-returns

Response:

{
"total": 0,
"per_page": 0,
"current_page": 0,
"last_page": 0,
"result": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"type": "C",
"closing_year": 2023,
"closing_date": "2023-12-31",
"millesime": 2024,
"duration": 12,
"submitted_date": "2024-05-15",
"revenue": 2500000,
"net_profit": 180000,
"file_id": "abc123...",
"provider_name": "company_legal_fr",
"data_connection_id": "...",
"warnings": [],
"tax_return_values": [
{ "code": "AA", "values": [1200000, 0, 0, 0] },
{ "code": "FL", "values": [2500000, 0, 0, 0] },
{ "code": "HN", "values": [180000, 0, 0, 0] }
]
}
]
}

Tax bundle detail

GET/api/v6/users/{userId}/tax-returns/{taxReturnId}

Download the original PDF

GET/api/v6/files/{fileId}

Tax cell codes

Key codes (Balance sheet)

CodeDescriptionFormulaire
AAIntangible assets - Start-up costs2050
ABIntangible assets - Development costs2050
CJTotal fixed assets (net)2050
COTotal current assets (net)2050
EETotal assets (net)2050
DAShare capital2051
DLTotal equity2051
ECTotal liabilities2051
EETotal liabilities & equity2051

Key codes (Income statement)

CodeDescriptionFormulaire
FAGoods sold (France)2052
FJProduction sold - Goods2052
FLNet revenue2052
FRTotal operating income2052
GFPayroll expenses2052
GWTotal operating expenses2052
GGOperating profit2052
GVFinancial result2053
HIExceptional result2053
HKCorporate tax2053
HNNet income2053
Full documentation

For the exhaustive list of codes, see the INPI technical document: Document Technique Comptes annuels

Tax bundle analysis

Extract key indicators

function extractKeyIndicators(taxReturn) {
const values = taxReturn.tax_return_values.reduce((acc, v) => {
acc[v.code] = v.values[0];
return acc;
}, {});

return {
// Activity
revenue: values['FL'] || 0,
revenueGrowth: null, // À calculer avec N-1

// Profitability
operatingResult: values['GG'] || 0,
netProfit: values['HN'] || 0,
profitMargin: (values['HN'] || 0) / (values['FL'] || 1),

// Balance sheet structure
equity: values['DL'] || 0,
totalAssets: values['EE'] || 0,
totalDebt: values['EC'] || 0,

// Ratios
debtToEquityRatio: (values['EC'] || 0) / (values['DL'] || 1),
returnOnEquity: (values['HN'] || 0) / (values['DL'] || 1),
returnOnAssets: (values['HN'] || 0) / (values['EE'] || 1)
};
}
function calculateTrends(taxReturns) {
// Sort by descending closing year
const sorted = taxReturns.sort((a, b) => b.closing_year - a.closing_year);

if (sorted.length < 2) return null;

const current = extractKeyIndicators(sorted[0]);
const previous = extractKeyIndicators(sorted[1]);

return {
revenueGrowth: (current.revenue - previous.revenue) / previous.revenue,
profitGrowth: (current.netProfit - previous.netProfit) / Math.abs(previous.netProfit || 1),
marginEvolution: current.profitMargin - previous.profitMargin,
years: {
current: sorted[0].closing_year,
previous: sorted[1].closing_year
}
};
}

Use the Tax Return Analysis

The API automatically computes ratios:

GET/api/v6/users/{userId}/tax-return-analysis

Checking data quality

Completeness warnings

CodeMessageImpact
01Absence BILAN- Actif - 2050-SDBilan incomplet
02Absence BILAN-Passif - 2051-SDBilan incomplet
03Absence COMPTE DE RESULTAT - 2052-SDCR incomplet
04Absence COMPTE DE RESULTAT - 2053-SDCR incomplet

Consistency warnings

CodeMessageMeaning
26Controle ACTIF= PASSIFTotal assets ≠ total liabilities
41Profit or loss controlProfit or loss inconsistency

Data validation

function validateTaxReturn(taxReturn) {
const issues = [];

// Check warnings
if (taxReturn.warnings?.length > 0) {
issues.push({
severity: 'WARNING',
message: 'Tax bundle incomplete or inconsistent',
details: taxReturn.warnings
});
}

// Check fiscal year duration
if (taxReturn.duration !== 12) {
issues.push({
severity: 'INFO',
message: `Fiscal year lasting ${taxReturn.duration} months (non standard)`
});
}

// Check revenue vs. net result consistency
if (taxReturn.revenue > 0 && Math.abs(taxReturn.net_profit) > taxReturn.revenue) {
issues.push({
severity: 'WARNING',
message: 'Net result is higher than revenue (verify)'
});
}

return {
valid: issues.filter(i => i.severity === 'ERROR').length === 0,
issues
};
}

Source comparison

CriterionINPIInfogreffeImpots.gouvOCR
Availability delay~6 months~6 monthsReal-timeImmediate
Authorization requiredNoInfogreffe accountOAuthNo
CostIncludedIncludedIncludedDepends on volume
VAT includedNoNoYesDepends on document
Data reliabilityHighHighVery highVariable
CoveragePublished filings onlyPublished + confidentialAll declarationsAny document

Combined use cases

Fetch the freshest data

async function getLatestTaxReturn(userId) {
// Synchronize all sources
await Promise.all([
qardApi.sync(userId, { data_types: ['TAX_RETURN'], provider: 'company_legal_fr' }),
qardApi.sync(userId, { data_types: ['TAX_RETURN'], provider: 'infogreffe' }),
qardApi.sync(userId, { data_types: ['TAX_RETURN'], provider: 'impots_gouv' })
]);

// Retrieve every tax bundle
const taxReturns = await qardApi.getTaxReturns(userId);

// Sort by closing date and take the newest
return taxReturns.sort((a, b) =>
new Date(b.closing_date) - new Date(a.closing_date)
)[0];
}

Fill missing data

async function enrichTaxData(userId, closingYear) {
// Public data (INPI)
const publicData = await qardApi.getTaxReturns(userId, {
filter: { closing_year: closingYear, provider_name: 'company_legal_fr' }
});

// Confidential data (Infogreffe)
const infogreffeData = await qardApi.getTaxReturns(userId, {
filter: { closing_year: closingYear, provider_name: 'infogreffe' }
});

// Private data (Impots.gouv, if available)
const privateData = await qardApi.getTaxReturns(userId, {
filter: { closing_year: closingYear, provider_name: 'impots_gouv' }
});

// Merge while prioritizing private data (most complete)
return {
year: closingYear,
public: publicData[0] || null,
infogreffe: infogreffeData[0] || null,
private: privateData[0] || null,
best: privateData[0] || infogreffeData[0] || publicData[0] || null
};
}

See also