Aller au contenu

Doc Extract API

Port : 8000 | NodePort : 30002 | Repo : solyntek/djinn/services/djinn-doc-extract

Extraction de données structurées depuis factures, reçus, CV et pièces d'identité via OCR + LLM.

Endpoints

Méthode Route Description
GET /health Health check
GET /v1/schemas Schémas des types de documents supportés
POST /v1/extract Extraction depuis un fichier unique
POST /v1/extract/batch Extraction batch depuis plusieurs fichiers

Types de documents

Type Données extraites
invoice vendor, numéro, date, lignes, totaux, TVA, IBAN
receipt vendor, date, lignes, totaux, mode de paiement
resume nom, email, skills, expériences, diplômes, certifications
id_card nom, date naissance, nationalité, numéro document

Exemple

curl -X POST http://localhost:30002/v1/extract \
  -F "file=@cv.pdf" \
  -F "document_type=resume"
curl -X POST https://api.djinn.solyntek.io/v1/extract \
  -H "X-API-Key: your-api-key" \
  -F "file=@cv.pdf" \
  -F "document_type=resume"
{
  "document_type": "resume",
  "data": {
    "firstname": "Jean",
    "lastname": "Dupont",
    "skills": ["Python", "Go", "Docker"],
    "experiences": [{"company": "Acme", "title": "Senior Dev"}]
  },
  "confidence": 0.87
}

Référence interactive

Générée à chaque build depuis la spec versionnée openapi/doc-extract-v1.json (ADR-011) — aucune route documentée à la main.

Djinn Document Extract 0.2.0

Extraction de données structurées depuis factures, reçus, CVs et IDs


Endpoints


GET /health

Health

Description

Health check endpoint.

Responses

{
    "status": "string",
    "version": "string"
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "properties": {
        "status": {
            "type": "string",
            "title": "Status",
            "default": "ok"
        },
        "version": {
            "type": "string",
            "title": "Version",
            "default": "0.2.0"
        }
    },
    "type": "object",
    "title": "HealthResponse",
    "description": "Response model for the health check endpoint."
}

GET /v1/schemas

Schemas

Description

List all supported document schemas with their fields.

Input parameters

Parameter In Type Default Nullable Description
X-API-Key header No
X-Internal-Service header No
X-Tenant-ID header No

Responses

[
    {
        "document_type": "string",
        "fields": [
            {
                "name": "string",
                "type": "string",
                "description": null
            }
        ]
    }
]
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "type": "array",
    "items": {
        "$ref": "#/components/schemas/SchemaInfo"
    },
    "title": "Response Schemas V1 Schemas Get"
}

{
    "detail": [
        {
            "loc": [
                null
            ],
            "msg": "string",
            "type": "string",
            "input": null,
            "ctx": {}
        }
    ]
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "properties": {
        "detail": {
            "items": {
                "$ref": "#/components/schemas/ValidationError"
            },
            "type": "array",
            "title": "Detail"
        }
    },
    "type": "object",
    "title": "HTTPValidationError"
}

POST /v1/extract

Extract

Description

Extract structured data from a single uploaded file.

Input parameters

Parameter In Type Default Nullable Description
document_type query No
X-API-Key header No
X-Internal-Service header No
X-Tenant-ID header No

Request body

{
    "file": "string"
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the request body
{
    "properties": {
        "file": {
            "type": "string",
            "contentMediaType": "application/octet-stream",
            "title": "File"
        }
    },
    "type": "object",
    "required": [
        "file"
    ],
    "title": "Body_extract_v1_extract_post"
}

Responses

{
    "document_type": "invoice",
    "data": null,
    "text_source": null,
    "raw_text": "string",
    "confidence": 10.12,
    "field_confidences": [
        {
            "field": "string",
            "score": 10.12,
            "reason": null
        }
    ],
    "pii_detected": null,
    "error": null
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "properties": {
        "document_type": {
            "$ref": "#/components/schemas/DocumentType"
        },
        "data": {
            "anyOf": [
                {
                    "$ref": "#/components/schemas/InvoiceData"
                },
                {
                    "$ref": "#/components/schemas/ReceiptData"
                },
                {
                    "$ref": "#/components/schemas/ResumeData"
                },
                {
                    "$ref": "#/components/schemas/IDCardData"
                },
                {
                    "type": "null"
                }
            ],
            "title": "Data"
        },
        "text_source": {
            "anyOf": [
                {
                    "$ref": "#/components/schemas/TextSource"
                },
                {
                    "type": "null"
                }
            ]
        },
        "raw_text": {
            "type": "string",
            "title": "Raw Text"
        },
        "confidence": {
            "type": "number",
            "maximum": 1.0,
            "minimum": 0.0,
            "title": "Confidence"
        },
        "field_confidences": {
            "items": {
                "$ref": "#/components/schemas/FieldConfidence"
            },
            "type": "array",
            "title": "Field Confidences"
        },
        "pii_detected": {
            "anyOf": [
                {
                    "items": {
                        "additionalProperties": true,
                        "type": "object"
                    },
                    "type": "array"
                },
                {
                    "type": "null"
                }
            ],
            "title": "Pii Detected"
        },
        "error": {
            "anyOf": [
                {
                    "type": "string"
                },
                {
                    "type": "null"
                }
            ],
            "title": "Error"
        }
    },
    "type": "object",
    "required": [
        "document_type",
        "raw_text",
        "confidence"
    ],
    "title": "ExtractionResult"
}

{
    "detail": [
        {
            "loc": [
                null
            ],
            "msg": "string",
            "type": "string",
            "input": null,
            "ctx": {}
        }
    ]
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "properties": {
        "detail": {
            "items": {
                "$ref": "#/components/schemas/ValidationError"
            },
            "type": "array",
            "title": "Detail"
        }
    },
    "type": "object",
    "title": "HTTPValidationError"
}

POST /v1/extract/batch

Extract Batch

Description

Extract structured data from multiple uploaded files.

Input parameters

Parameter In Type Default Nullable Description
document_type query No
X-API-Key header No
X-Internal-Service header No
X-Tenant-ID header No

Request body

{
    "files": [
        "string"
    ]
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the request body
{
    "properties": {
        "files": {
            "items": {
                "type": "string",
                "contentMediaType": "application/octet-stream"
            },
            "type": "array",
            "title": "Files"
        }
    },
    "type": "object",
    "required": [
        "files"
    ],
    "title": "Body_extract_batch_v1_extract_batch_post"
}

Responses

[
    {
        "document_type": "invoice",
        "data": null,
        "text_source": null,
        "raw_text": "string",
        "confidence": 10.12,
        "field_confidences": [
            {
                "field": "string",
                "score": 10.12,
                "reason": null
            }
        ],
        "pii_detected": null,
        "error": null
    }
]
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "type": "array",
    "items": {
        "$ref": "#/components/schemas/ExtractionResult"
    },
    "title": "Response Extract Batch V1 Extract Batch Post"
}

{
    "detail": [
        {
            "loc": [
                null
            ],
            "msg": "string",
            "type": "string",
            "input": null,
            "ctx": {}
        }
    ]
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "properties": {
        "detail": {
            "items": {
                "$ref": "#/components/schemas/ValidationError"
            },
            "type": "array",
            "title": "Detail"
        }
    },
    "type": "object",
    "title": "HTTPValidationError"
}

GET /v1/receipt-policies

Get Receipt Policy V1

Description

Politique de dépenses du tenant authentifié, ou la politique par défaut.

Input parameters

Parameter In Type Default Nullable Description
X-API-Key header No
X-Internal-Service header No
X-Tenant-ID header No

Responses

{
    "currency": "string",
    "default_max_amount": 10.12,
    "caps": [
        {
            "category": "string",
            "max_amount": 10.12
        }
    ],
    "require_vat_above": null,
    "is_default": true
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "properties": {
        "currency": {
            "type": "string",
            "maxLength": 3,
            "minLength": 3,
            "title": "Currency",
            "default": "EUR"
        },
        "default_max_amount": {
            "type": "number",
            "minimum": 0.0,
            "title": "Default Max Amount",
            "default": 1000.0
        },
        "caps": {
            "items": {
                "$ref": "#/components/schemas/ExpenseCap"
            },
            "type": "array",
            "title": "Caps"
        },
        "require_vat_above": {
            "anyOf": [
                {
                    "type": "number",
                    "minimum": 0.0
                },
                {
                    "type": "null"
                }
            ],
            "title": "Require Vat Above"
        },
        "is_default": {
            "type": "boolean",
            "title": "Is Default",
            "default": false
        }
    },
    "type": "object",
    "title": "ExpensePolicyOut",
    "description": "Politique renvoyée par l'API, avec l'indication qu'aucune n'a été enregistrée."
}

{
    "detail": [
        {
            "loc": [
                null
            ],
            "msg": "string",
            "type": "string",
            "input": null,
            "ctx": {}
        }
    ]
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "properties": {
        "detail": {
            "items": {
                "$ref": "#/components/schemas/ValidationError"
            },
            "type": "array",
            "title": "Detail"
        }
    },
    "type": "object",
    "title": "HTTPValidationError"
}

PUT /v1/receipt-policies

Put Receipt Policy V1

Description

Remplace la politique du tenant authentifié.

Le tenant vient de l'authentification (ADR-001) ; un tenant_id présent dans le corps est ignoré, jamais honoré.

Input parameters

Parameter In Type Default Nullable Description
X-API-Key header No
X-Internal-Service header No
X-Tenant-ID header No

Request body

{
    "currency": "string",
    "default_max_amount": 10.12,
    "caps": [
        {
            "category": "string",
            "max_amount": 10.12
        }
    ],
    "require_vat_above": null
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the request body
{
    "properties": {
        "currency": {
            "type": "string",
            "maxLength": 3,
            "minLength": 3,
            "title": "Currency",
            "default": "EUR"
        },
        "default_max_amount": {
            "type": "number",
            "minimum": 0.0,
            "title": "Default Max Amount",
            "default": 1000.0
        },
        "caps": {
            "items": {
                "$ref": "#/components/schemas/ExpenseCap"
            },
            "type": "array",
            "title": "Caps"
        },
        "require_vat_above": {
            "anyOf": [
                {
                    "type": "number",
                    "minimum": 0.0
                },
                {
                    "type": "null"
                }
            ],
            "title": "Require Vat Above"
        }
    },
    "type": "object",
    "title": "ExpensePolicy",
    "description": "Politique de dépenses d'un tenant.\n\nLe verdict produit à partir de cette politique est une **évaluation**,\njamais une autorisation : doc-extract ne refuse aucun remboursement, il\nrapporte qu'un montant dépasse un plafond déclaré."
}

Responses

{
    "currency": "string",
    "default_max_amount": 10.12,
    "caps": [
        {
            "category": "string",
            "max_amount": 10.12
        }
    ],
    "require_vat_above": null,
    "is_default": true
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "properties": {
        "currency": {
            "type": "string",
            "maxLength": 3,
            "minLength": 3,
            "title": "Currency",
            "default": "EUR"
        },
        "default_max_amount": {
            "type": "number",
            "minimum": 0.0,
            "title": "Default Max Amount",
            "default": 1000.0
        },
        "caps": {
            "items": {
                "$ref": "#/components/schemas/ExpenseCap"
            },
            "type": "array",
            "title": "Caps"
        },
        "require_vat_above": {
            "anyOf": [
                {
                    "type": "number",
                    "minimum": 0.0
                },
                {
                    "type": "null"
                }
            ],
            "title": "Require Vat Above"
        },
        "is_default": {
            "type": "boolean",
            "title": "Is Default",
            "default": false
        }
    },
    "type": "object",
    "title": "ExpensePolicyOut",
    "description": "Politique renvoyée par l'API, avec l'indication qu'aucune n'a été enregistrée."
}

{
    "detail": [
        {
            "loc": [
                null
            ],
            "msg": "string",
            "type": "string",
            "input": null,
            "ctx": {}
        }
    ]
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "properties": {
        "detail": {
            "items": {
                "$ref": "#/components/schemas/ValidationError"
            },
            "type": "array",
            "title": "Detail"
        }
    },
    "type": "object",
    "title": "HTTPValidationError"
}

POST /v1/extract/receipts/analyze

Analyze Receipts

Description

Analyse un lot de reçus : doublons, écarts de politique, cohérence, authenticité.

Pour chaque reçu : extraction (document_type="receipt"), empreinte perceptuelle, contrôle de cohérence interne, confrontation à la politique de dépenses du tenant, et signaux d'authenticité via AuthenticityProvider (implémentation locale aujourd'hui ; doc-trust dès sa v1 en T2, sans changement de contrat). Puis, sur l'ensemble du lot, rapprochement des doublons.

findings et authenticity sont des évaluations, jamais des autorisations : cette route ne bloque rien, ne rejette aucun reçu pour cause de constat, et ne modifie aucune politique. Un fichier illisible, trop volumineux, ou dont l'extraction échoue, produit un item avec error renseigné et n'interrompt jamais le lot — même contrat que /v1/extract/batch. Seul un problème de requête (lot vide, lot au-delà de MAX_BATCH_RECEIPTS) fait échouer l'appel entier.

Input parameters

Parameter In Type Default Nullable Description
X-API-Key header No
X-Internal-Service header No
X-Tenant-ID header No

Request body

{
    "files": [
        "string"
    ],
    "categories": null
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the request body
{
    "properties": {
        "files": {
            "items": {
                "type": "string",
                "contentMediaType": "application/octet-stream"
            },
            "type": "array",
            "title": "Files"
        },
        "categories": {
            "anyOf": [
                {
                    "type": "string"
                },
                {
                    "type": "null"
                }
            ],
            "title": "Categories"
        }
    },
    "type": "object",
    "required": [
        "files"
    ],
    "title": "Body_analyze_receipts_v1_extract_receipts_analyze_post"
}

Responses

{
    "items": [
        {
            "index": 0,
            "filename": "string",
            "data": null,
            "confidence": null,
            "findings": [
                {
                    "code": "string",
                    "message": "string",
                    "severity": "info"
                }
            ],
            "authenticity": null,
            "error": null
        }
    ],
    "duplicate_groups": [
        {
            "indices": [
                0
            ],
            "rule": "fingerprint"
        }
    ],
    "analysed_at": "2022-04-13T15:42:05.901Z",
    "policy_is_default": true
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "properties": {
        "items": {
            "items": {
                "$ref": "#/components/schemas/ReceiptAnalysisItem"
            },
            "type": "array",
            "title": "Items"
        },
        "duplicate_groups": {
            "items": {
                "$ref": "#/components/schemas/DuplicateGroupOut"
            },
            "type": "array",
            "title": "Duplicate Groups"
        },
        "analysed_at": {
            "type": "string",
            "format": "date-time",
            "title": "Analysed At"
        },
        "policy_is_default": {
            "type": "boolean",
            "title": "Policy Is Default"
        }
    },
    "type": "object",
    "required": [
        "items",
        "analysed_at",
        "policy_is_default"
    ],
    "title": "ReceiptAnalysisResponse",
    "description": "Réponse de l'analyse du lot.\n\nNe bloque rien, ne rejette aucun reçu pour cause de constat, et ne\nmodifie aucune politique de dépenses."
}

{
    "detail": [
        {
            "loc": [
                null
            ],
            "msg": "string",
            "type": "string",
            "input": null,
            "ctx": {}
        }
    ]
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "properties": {
        "detail": {
            "items": {
                "$ref": "#/components/schemas/ValidationError"
            },
            "type": "array",
            "title": "Detail"
        }
    },
    "type": "object",
    "title": "HTTPValidationError"
}

Schemas

AuthenticityOut

Name Type Description
explanation string
score number
signals Array<FindingOut>

Body_analyze_receipts_v1_extract_receipts_analyze_post

Name Type Description
categories
files Array<string>

Body_extract_batch_v1_extract_batch_post

Name Type Description
files Array<string>

Body_extract_v1_extract_post

Name Type Description
file string

Certification

Name Type Description
name
provider
year

Diploma

Name Type Description
degree
end_date
field_of_study
school
start_date

DocumentType

Type: string

DuplicateGroupOut

Name Type Description
indices Array<integer>
rule string

ExpenseCap

Name Type Description
category string
max_amount number

ExpensePolicy

Name Type Description
caps Array<ExpenseCap>
currency string
default_max_amount number
require_vat_above

ExpensePolicyOut

Name Type Description
caps Array<ExpenseCap>
currency string
default_max_amount number
is_default boolean
require_vat_above

Experience

Name Type Description
company
description
end_date YYYY-MM, YYYY, or 'Present'
location
start_date YYYY-MM or YYYY
title

ExtractionResult

Name Type Description
confidence number
data
document_type DocumentType
error
field_confidences Array<FieldConfidence>
pii_detected
raw_text string
text_source

FieldConfidence

Name Type Description
field string
reason
score number

FindingOut

Name Type Description
code string
message string
severity string

HealthResponse

Name Type Description
status string
version string

HTTPValidationError

Name Type Description
detail Array<ValidationError>

IDCardData

Name Type Description
birth_date
birth_place
document_number
expiry_date
first_name
gender M or F
issue_date
last_name
nationality

InvoiceData

Name Type Description
currency ISO 4217 code (EUR, USD, ...)
due_date
invoice_date
invoice_number
line_items Array<LineItem>
payment_method
payment_reference IBAN or payment reference
subtotal
total_amount
vat_amount
vendor_address
vendor_name
vendor_tax_id SIRET / tax ID

LineItem

Name Type Description
amount
description
quantity
unit_price
vat_rate

ReceiptAnalysisItem

Name Type Description
authenticity Signaux d'authenticité faibles et contournables — une aide au tri humain, jamais une preuve ni un verdict. `null` signifie que l'authenticité n'a pas pu être évaluée (fichier rejeté avant analyse, ou échec du fournisseur de signaux), jamais qu'aucun signal n'a été trouvé : l'absence de signal se lit sur un objet présent dont `signals` est vide.
confidence
data
error
filename string
findings Array<FindingOut> Écarts de cohérence interne et de politique de dépenses. Une évaluation, jamais une autorisation : aucun reçu n'est rejeté.
index integer

ReceiptAnalysisResponse

Name Type Description
analysed_at string(date-time)
duplicate_groups Array<DuplicateGroupOut>
items Array<ReceiptAnalysisItem>
policy_is_default boolean

ReceiptData

Name Type Description
currency
line_items Array<LineItem>
payment_method
receipt_date
receipt_time Heure du ticket, si imprimée
subtotal
total_amount
vat_amount
vat_breakdown Array<VatBreakdownEntry> Ventilation par taux ; vat_amount reste le total
vendor_address
vendor_name

ResumeData

Name Type Description
certifications Array<Certification>
diplomas Array<Diploma>
email
experiences Array<Experience>
firstname
languages Array<string>
lastname
linkedin
location
phone
skills Array<string>

SchemaField

Name Type Description
description
name string
type string

SchemaInfo

Name Type Description
document_type string
fields Array<SchemaField>

TextSource

Type: string

ValidationError

Name Type Description
ctx
input
loc Array<>
msg string
type string

VatBreakdownEntry

Name Type Description
amount Montant de TVA pour ce taux
rate Taux en pourcentage, ex. 20.0 ou 5.5
taxable_base Base imposable pour ce taux