LEON.
Under Development

Beperkte Toegang

Deze site is momenteel in ontwikkeling. Voer het toegangswachtwoord in om verder te gaan.

LEON Integrity Systems · Privé Preview

import { createClient } from '@database/client';
import { analyzeDocument } from '@core/engine';
 
export async function handleRequest(request: Request) {
const { candidateId, propertyId } = await request.json();
const candidate = await db.candidates.findUnique({ where: { id: candidateId } });
if (!candidate) throw new Error('Candidate not found');
 
const documents = await storage.getDocuments(candidateId);
const fraudResult = await detectManipulation(documents);
 
if (fraudResult.score > FRAUD_THRESHOLD) {
await audit.log({ event: 'FRAUD_DETECTED', candidateId, score: fraudResult.score });
return { status: 'BLOCKED', reason: fraudResult.reason };
}
 
const income = parseFloat(candidate.declared_income);
const rent = await properties.getRent(propertyId);
const solvabilityRatio = income / rent;
 
const criteria = await config.getCriteria(propertyId);
const totalScore = criteria.reduce((acc: number, criterion: Criterion) => {
const value = evaluate(candidate, criterion);
return acc + (value * criterion.weight) / 100;
}, 0);
 
await results.save({ candidateId, propertyId, score: totalScore, ratio: solvabilityRatio });
return { status: 'APPROVED', score: totalScore, solvability: solvabilityRatio };
}
 
async function detectManipulation(files: Document[]): Promise<FraudResult> {
const results = await Promise.all(files.map(async (file) => {
const metadata = await extractMetadata(file);
const modified = metadata.modifiedAt > metadata.createdAt - THRESHOLD_MS;
const software = FORBIDDEN_SOFTWARE.includes(metadata.software);
return { file: file.name, suspicious: modified || software };
}));
const suspicious = results.filter(r => r.suspicious);
return { score: suspicious.length / results.length, flagged: suspicious };
}
 
function evaluate(candidate: Candidate, criterion: Criterion): number {
switch (criterion.type) {
case 'INCOME_RATIO': return candidate.income / criterion.threshold;
case 'OCCUPANCY': return candidate.persons <= criterion.maxPersons ? 1 : 0;
case 'EMPLOYMENT': return STABLE_CONTRACTS.includes(candidate.contractType) ? 1 : 0.5;
case 'HISTORY': return candidate.rentalHistory?.complaints === 0 ? 1 : 0.3;
default: return 0;
}
}
 
export const FRAUD_THRESHOLD = 0.8;
export const THRESHOLD_MS = 600_000; // 10 minutes
export const STABLE_CONTRACTS = ['permanent', 'civil_servant', 'self_employed'];
export const FORBIDDEN_SOFTWARE = ['Preview', 'Adobe Acrobat', 'Foxit Editor'];
 
// Scoring engine — all weights must sum to 100
const DEFAULT_WEIGHTS = { income: 40, occupation: 25, history: 20, documents: 15 };
const validateWeights = (w: Record<string, number>) => Object.values(w).reduce((a,b) => a+b, 0) === 100;
import { createClient } from '@database/client';
import { analyzeDocument } from '@core/engine';
 
export async function handleRequest(request: Request) {
const { candidateId, propertyId } = await request.json();
const candidate = await db.candidates.findUnique({ where: { id: candidateId } });
if (!candidate) throw new Error('Candidate not found');
 
const documents = await storage.getDocuments(candidateId);
const fraudResult = await detectManipulation(documents);
 
if (fraudResult.score > FRAUD_THRESHOLD) {
await audit.log({ event: 'FRAUD_DETECTED', candidateId, score: fraudResult.score });
return { status: 'BLOCKED', reason: fraudResult.reason };
}
 
const income = parseFloat(candidate.declared_income);
const rent = await properties.getRent(propertyId);
const solvabilityRatio = income / rent;
 
const criteria = await config.getCriteria(propertyId);
const totalScore = criteria.reduce((acc: number, criterion: Criterion) => {
const value = evaluate(candidate, criterion);
return acc + (value * criterion.weight) / 100;
}, 0);
 
await results.save({ candidateId, propertyId, score: totalScore, ratio: solvabilityRatio });
return { status: 'APPROVED', score: totalScore, solvability: solvabilityRatio };
}
 
async function detectManipulation(files: Document[]): Promise<FraudResult> {
const results = await Promise.all(files.map(async (file) => {
const metadata = await extractMetadata(file);
const modified = metadata.modifiedAt > metadata.createdAt - THRESHOLD_MS;
const software = FORBIDDEN_SOFTWARE.includes(metadata.software);
return { file: file.name, suspicious: modified || software };
}));
const suspicious = results.filter(r => r.suspicious);
return { score: suspicious.length / results.length, flagged: suspicious };
}
 
function evaluate(candidate: Candidate, criterion: Criterion): number {
switch (criterion.type) {
case 'INCOME_RATIO': return candidate.income / criterion.threshold;
case 'OCCUPANCY': return candidate.persons <= criterion.maxPersons ? 1 : 0;
case 'EMPLOYMENT': return STABLE_CONTRACTS.includes(candidate.contractType) ? 1 : 0.5;
case 'HISTORY': return candidate.rentalHistory?.complaints === 0 ? 1 : 0.3;
default: return 0;
}
}
 
export const FRAUD_THRESHOLD = 0.8;
export const THRESHOLD_MS = 600_000; // 10 minutes
export const STABLE_CONTRACTS = ['permanent', 'civil_servant', 'self_employed'];
export const FORBIDDEN_SOFTWARE = ['Preview', 'Adobe Acrobat', 'Foxit Editor'];
 
// Scoring engine — all weights must sum to 100
const DEFAULT_WEIGHTS = { income: 40, occupation: 25, history: 20, documents: 15 };
const validateWeights = (w: Record<string, number>) => Object.values(w).reduce((a,b) => a+b, 0) === 100;
import { createClient } from '@database/client';
import { analyzeDocument } from '@core/engine';
 
export async function handleRequest(request: Request) {
const { candidateId, propertyId } = await request.json();
const candidate = await db.candidates.findUnique({ where: { id: candidateId } });
if (!candidate) throw new Error('Candidate not found');
 
const documents = await storage.getDocuments(candidateId);
const fraudResult = await detectManipulation(documents);
 
if (fraudResult.score > FRAUD_THRESHOLD) {
await audit.log({ event: 'FRAUD_DETECTED', candidateId, score: fraudResult.score });
return { status: 'BLOCKED', reason: fraudResult.reason };
}
 
const income = parseFloat(candidate.declared_income);
const rent = await properties.getRent(propertyId);
const solvabilityRatio = income / rent;
 
const criteria = await config.getCriteria(propertyId);
const totalScore = criteria.reduce((acc: number, criterion: Criterion) => {
const value = evaluate(candidate, criterion);
return acc + (value * criterion.weight) / 100;
}, 0);
 
await results.save({ candidateId, propertyId, score: totalScore, ratio: solvabilityRatio });
return { status: 'APPROVED', score: totalScore, solvability: solvabilityRatio };
}
 
async function detectManipulation(files: Document[]): Promise<FraudResult> {
const results = await Promise.all(files.map(async (file) => {
const metadata = await extractMetadata(file);
const modified = metadata.modifiedAt > metadata.createdAt - THRESHOLD_MS;
const software = FORBIDDEN_SOFTWARE.includes(metadata.software);
return { file: file.name, suspicious: modified || software };
}));
const suspicious = results.filter(r => r.suspicious);
return { score: suspicious.length / results.length, flagged: suspicious };
}
 
function evaluate(candidate: Candidate, criterion: Criterion): number {
switch (criterion.type) {
case 'INCOME_RATIO': return candidate.income / criterion.threshold;
case 'OCCUPANCY': return candidate.persons <= criterion.maxPersons ? 1 : 0;
case 'EMPLOYMENT': return STABLE_CONTRACTS.includes(candidate.contractType) ? 1 : 0.5;
case 'HISTORY': return candidate.rentalHistory?.complaints === 0 ? 1 : 0.3;
default: return 0;
}
}
 
export const FRAUD_THRESHOLD = 0.8;
export const THRESHOLD_MS = 600_000; // 10 minutes
export const STABLE_CONTRACTS = ['permanent', 'civil_servant', 'self_employed'];
export const FORBIDDEN_SOFTWARE = ['Preview', 'Adobe Acrobat', 'Foxit Editor'];
 
// Scoring engine — all weights must sum to 100
const DEFAULT_WEIGHTS = { income: 40, occupation: 25, history: 20, documents: 15 };
const validateWeights = (w: Record<string, number>) => Object.values(w).reduce((a,b) => a+b, 0) === 100;
import { createClient } from '@database/client';
import { analyzeDocument } from '@core/engine';
 
export async function handleRequest(request: Request) {
const { candidateId, propertyId } = await request.json();
const candidate = await db.candidates.findUnique({ where: { id: candidateId } });
if (!candidate) throw new Error('Candidate not found');
 
const documents = await storage.getDocuments(candidateId);
const fraudResult = await detectManipulation(documents);
 
if (fraudResult.score > FRAUD_THRESHOLD) {
await audit.log({ event: 'FRAUD_DETECTED', candidateId, score: fraudResult.score });
return { status: 'BLOCKED', reason: fraudResult.reason };
}
 
const income = parseFloat(candidate.declared_income);
const rent = await properties.getRent(propertyId);
const solvabilityRatio = income / rent;
 
const criteria = await config.getCriteria(propertyId);
const totalScore = criteria.reduce((acc: number, criterion: Criterion) => {
const value = evaluate(candidate, criterion);
return acc + (value * criterion.weight) / 100;
}, 0);
 
await results.save({ candidateId, propertyId, score: totalScore, ratio: solvabilityRatio });
return { status: 'APPROVED', score: totalScore, solvability: solvabilityRatio };
}
 
async function detectManipulation(files: Document[]): Promise<FraudResult> {
const results = await Promise.all(files.map(async (file) => {
const metadata = await extractMetadata(file);
const modified = metadata.modifiedAt > metadata.createdAt - THRESHOLD_MS;
const software = FORBIDDEN_SOFTWARE.includes(metadata.software);
return { file: file.name, suspicious: modified || software };
}));
const suspicious = results.filter(r => r.suspicious);
return { score: suspicious.length / results.length, flagged: suspicious };
}
 
function evaluate(candidate: Candidate, criterion: Criterion): number {
switch (criterion.type) {
case 'INCOME_RATIO': return candidate.income / criterion.threshold;
case 'OCCUPANCY': return candidate.persons <= criterion.maxPersons ? 1 : 0;
case 'EMPLOYMENT': return STABLE_CONTRACTS.includes(candidate.contractType) ? 1 : 0.5;
case 'HISTORY': return candidate.rentalHistory?.complaints === 0 ? 1 : 0.3;
default: return 0;
}
}
 
export const FRAUD_THRESHOLD = 0.8;
export const THRESHOLD_MS = 600_000; // 10 minutes
export const STABLE_CONTRACTS = ['permanent', 'civil_servant', 'self_employed'];
export const FORBIDDEN_SOFTWARE = ['Preview', 'Adobe Acrobat', 'Foxit Editor'];
 
// Scoring engine — all weights must sum to 100
const DEFAULT_WEIGHTS = { income: 40, occupation: 25, history: 20, documents: 15 };
const validateWeights = (w: Record<string, number>) => Object.values(w).reduce((a,b) => a+b, 0) === 100;
import { createClient } from '@database/client';
import { analyzeDocument } from '@core/engine';
 
export async function handleRequest(request: Request) {
const { candidateId, propertyId } = await request.json();
const candidate = await db.candidates.findUnique({ where: { id: candidateId } });
if (!candidate) throw new Error('Candidate not found');
 
const documents = await storage.getDocuments(candidateId);
const fraudResult = await detectManipulation(documents);
 
if (fraudResult.score > FRAUD_THRESHOLD) {
await audit.log({ event: 'FRAUD_DETECTED', candidateId, score: fraudResult.score });
return { status: 'BLOCKED', reason: fraudResult.reason };
}
 
const income = parseFloat(candidate.declared_income);
const rent = await properties.getRent(propertyId);
const solvabilityRatio = income / rent;
 
const criteria = await config.getCriteria(propertyId);
const totalScore = criteria.reduce((acc: number, criterion: Criterion) => {
const value = evaluate(candidate, criterion);
return acc + (value * criterion.weight) / 100;
}, 0);
 
await results.save({ candidateId, propertyId, score: totalScore, ratio: solvabilityRatio });
return { status: 'APPROVED', score: totalScore, solvability: solvabilityRatio };
}
 
async function detectManipulation(files: Document[]): Promise<FraudResult> {
const results = await Promise.all(files.map(async (file) => {
const metadata = await extractMetadata(file);
const modified = metadata.modifiedAt > metadata.createdAt - THRESHOLD_MS;
const software = FORBIDDEN_SOFTWARE.includes(metadata.software);
return { file: file.name, suspicious: modified || software };
}));
const suspicious = results.filter(r => r.suspicious);
return { score: suspicious.length / results.length, flagged: suspicious };
}
 
function evaluate(candidate: Candidate, criterion: Criterion): number {
switch (criterion.type) {
case 'INCOME_RATIO': return candidate.income / criterion.threshold;
case 'OCCUPANCY': return candidate.persons <= criterion.maxPersons ? 1 : 0;
case 'EMPLOYMENT': return STABLE_CONTRACTS.includes(candidate.contractType) ? 1 : 0.5;
case 'HISTORY': return candidate.rentalHistory?.complaints === 0 ? 1 : 0.3;
default: return 0;
}
}
 
export const FRAUD_THRESHOLD = 0.8;
export const THRESHOLD_MS = 600_000; // 10 minutes
export const STABLE_CONTRACTS = ['permanent', 'civil_servant', 'self_employed'];
export const FORBIDDEN_SOFTWARE = ['Preview', 'Adobe Acrobat', 'Foxit Editor'];
 
// Scoring engine — all weights must sum to 100
const DEFAULT_WEIGHTS = { income: 40, occupation: 25, history: 20, documents: 15 };
const validateWeights = (w: Record<string, number>) => Object.values(w).reduce((a,b) => a+b, 0) === 100;
import { createClient } from '@database/client';
import { analyzeDocument } from '@core/engine';
 
export async function handleRequest(request: Request) {
const { candidateId, propertyId } = await request.json();
const candidate = await db.candidates.findUnique({ where: { id: candidateId } });
if (!candidate) throw new Error('Candidate not found');
 
const documents = await storage.getDocuments(candidateId);
const fraudResult = await detectManipulation(documents);
 
if (fraudResult.score > FRAUD_THRESHOLD) {
await audit.log({ event: 'FRAUD_DETECTED', candidateId, score: fraudResult.score });
return { status: 'BLOCKED', reason: fraudResult.reason };
}
 
const income = parseFloat(candidate.declared_income);
const rent = await properties.getRent(propertyId);
const solvabilityRatio = income / rent;
 
const criteria = await config.getCriteria(propertyId);
const totalScore = criteria.reduce((acc: number, criterion: Criterion) => {
const value = evaluate(candidate, criterion);
return acc + (value * criterion.weight) / 100;
}, 0);
 
await results.save({ candidateId, propertyId, score: totalScore, ratio: solvabilityRatio });
return { status: 'APPROVED', score: totalScore, solvability: solvabilityRatio };
}
 
async function detectManipulation(files: Document[]): Promise<FraudResult> {
const results = await Promise.all(files.map(async (file) => {
const metadata = await extractMetadata(file);
const modified = metadata.modifiedAt > metadata.createdAt - THRESHOLD_MS;
const software = FORBIDDEN_SOFTWARE.includes(metadata.software);
return { file: file.name, suspicious: modified || software };
}));
const suspicious = results.filter(r => r.suspicious);
return { score: suspicious.length / results.length, flagged: suspicious };
}
 
function evaluate(candidate: Candidate, criterion: Criterion): number {
switch (criterion.type) {
case 'INCOME_RATIO': return candidate.income / criterion.threshold;
case 'OCCUPANCY': return candidate.persons <= criterion.maxPersons ? 1 : 0;
case 'EMPLOYMENT': return STABLE_CONTRACTS.includes(candidate.contractType) ? 1 : 0.5;
case 'HISTORY': return candidate.rentalHistory?.complaints === 0 ? 1 : 0.3;
default: return 0;
}
}
 
export const FRAUD_THRESHOLD = 0.8;
export const THRESHOLD_MS = 600_000; // 10 minutes
export const STABLE_CONTRACTS = ['permanent', 'civil_servant', 'self_employed'];
export const FORBIDDEN_SOFTWARE = ['Preview', 'Adobe Acrobat', 'Foxit Editor'];
 
// Scoring engine — all weights must sum to 100
const DEFAULT_WEIGHTS = { income: 40, occupation: 25, history: 20, documents: 15 };
const validateWeights = (w: Record<string, number>) => Object.values(w).reduce((a,b) => a+b, 0) === 100;
AVG/GDPR Compliant · Belgische Markt · Fase 1

LEON.

Legal Evaluation & Objective Network

Geautomatiseerde huurderscreening voor Belgische vastgoedprofessionals.
Geen bias. Alleen data. Win uren per dossier.

Scroll
LEON
LEON Audit Engine v2.0
Dossier #882 — Marc & Elena94%
Solvabiliteit
92%
Fraude Check
100%
Bezetting
88%
Documenten
95%

Status

Goedgekeurd

AI Model

Sonnet 4.6 / Haiku 4.5

Tijd

28 sec

Fraude

Geen

94%
Audit accuraatheid
3.2u
Tijdsbesparing/dossier
100%
GDPR compliant
<30s
Analysetijd
Platform Features

Alles wat u nodig heeft.

Kern Feature

AI Fraude Detectie

Metadata analyse van PDF-documenten detecteert gemanipuleerde loonfiches en identiteitsbewijzen.

Financieel

Solvabiliteitscheck

Automatische berekening van de huur/inkomen ratio op basis van ingediende loonfiches.

Pro & Scale

Cross Web Search

AI zoekt kandidaten op via publieke bronnen voor extra verificatielaag.

Configureerbaar

Custom Criteria

Stel uw eigen beoordelingscriteria in met gewichten per pand. Volledig flexibel.

Juridisch

GDPR Compliant

Data processing conform Belgische wet en AVG. DPA met Anthropic en Supabase.

Scale

Multi-user Toegang

Geef teamleden toegang tot uw dashboard met enterprise analytics.

Contact

Neem contact op.

Heb je een vraag, opmerking of wil je meer informatie? Vul het formulier in en we nemen zo snel mogelijk contact op — ook als je nog geen klant bent.

Uw gegevens worden vertrouwelijk behandeld conform onze Privacy Policy.

Werkwijze

Hoe werkt LEON.

01.

Upload

Kandidaat levert gevraagde informatie aan in een beveiligde LEON-omgeving. Geen papier, geen e-mail.

02.

Audit

Onze AI-engine checkt op documentfraude, solvabiliteit en alle verhuurderseisen in minder dan 30 seconden.

03.

Decide

U ontvangt een objectief rapport met score en motivatie. De finale beslissing blijft altijd bij u.

Over LEON

Gebouwd voor de Belgische vastgoedmarkt.

Ons Verhaal

Hoe we zijn begonnen

LEON ontstond uit frustratie. Als vastgoedprofessionals merkten we dat het screenen van huurkandidaten te veel tijd kostte, te subjectief was en juridisch risico's met zich meebracht.

We zagen hoe makelaars uren spendeerden aan het manueel controleren van loonfiches, het berekenen van solvabiliteitsratio's en het inschatten van risico's op basis van gevoel in plaats van data.

In 2026 besloten we dat er een betere manier moest zijn. LEON is het antwoord.

2025

Idee geboren uit frustratie met manuele screening

Q1 2026

Eerste versie LEON gebouwd en getest

Mrt 2026

Fase 1 launch — eerste klanten onboarden

2026+

Uitbreiding naar heel België en Nederland

M
Onze Missie

Objectiviteit als standaard

Elke huurkandidaat verdient een eerlijke, objectieve beoordeling op basis van feiten. Geen vooroordelen, geen subjectiviteit. LEON zorgt ervoor dat elke beslissing datagestuurd en juridisch verdedigbaar is.

"Geen bias. Alleen data."

V
Onze Visie

De toekomst van verhuur

Een vastgoedmarkt waar elke verhuurder toegang heeft tot professionele screening tools, waar discriminatie technisch onmogelijk is gemaakt en waar huurders worden beoordeeld op wat telt.

"Eerlijk voor iedereen."

Onze Waarden

Waar we voor staan.

Eerlijkheid

Elke kandidaat krijgt dezelfde objectieve behandeling.

Privacy

GDPR-compliant by design. Uw data is uw data.

Efficiëntie

Win uren per dossier zonder kwaliteitsverlies.

Vertrouwen

Transparante AI — altijd uitlegbaar en betwistbaar.

Transparante Pricing

Kies uw plan.

Starter

Tot 3 panden/maand

59,99/maand
  • Basis AI (Haiku)
  • Basis fraude detectie
  • Email support
Advanced

Tot 5 panden/maand

99,99/maand
  • Advanced AI (Sonnet)
  • Volledige fraude detectie
  • Priority support
Meest gekozen
Pro

Tot 10 panden/maand

149,99/maand
  • Advanced AI (Sonnet)
  • Custom forms
  • Priority support
  • Cross web search
  • Volledige fraude detectie
Scale

Onbeperkt panden

229,99/maand
  • Advanced AI (Sonnet)
  • Custom forms
  • Multi-user & enterprise dashboard
  • Priority support
  • Cross web search
  • Custom API key
  • Volledige fraude detectie