Aller au contenu

API interne Bricks — guide d'intégration

Les routes /internal/* exposent les données Bricks aux applications consommatrices internes hébergées hors monorepo (ticketing/care, support, IA WhatsApp, gestion des défauts, projet-analyse, AI platform, ai-agent, middleware facturation Axonaut, espace financement Bubble) — en remplacement des requêtes SQL directes sur la base Postgres. Ce guide s'adresse aux devs de ces apps.

Authentification

Une seule clé API par header, propre à chaque app consommatrice :

x-api-key: <clé de l'app>
App Type (dans la doc OpenAPI) Variable d'env (côté Bricks)
Ticketing / care ticketing TICKETING_API_KEY_INTERNAL
IA WhatsApp ia-whatsapp IA_WHATSAPP_API_KEY_INTERNAL
Gestion des défauts gestion-defauts GESTION_DEFAUTS_API_KEY_INTERNAL
Projet-analyse projet-analyse PROJET_ANALYSE_API_KEY_INTERNAL
AI Platform (classification documentaire, fonctionnalités IA) ai-platform AI_PLATFORM_API_KEY_INTERNAL
AI Agent ai-agent AI_AGENT_API_KEY_INTERNAL
Facturation frais de gestion (middleware Axonaut + Bubble) project-owner-invoicing PROJECT_OWNER_INVOICING_API_KEY_INTERNAL
  • Une route peut accepter plusieurs apps : les apps autorisées figurent dans la description de chaque opération de la doc OpenAPI (ex. Apps autorisées : ticketing, ia-whatsapp).
  • Clé absente ou invalide → 401. La clé est obligatoire en production.
  • Vérifier rapidement une clé : curl -H "x-api-key: $TA_CLE" https://api.bricks.co/internal/docs/json → 200 (401 si la clé est invalide).
  • Pour obtenir une clé, demande à l'équipe Bricks (la valeur n'est jamais dans le code ni dans la doc).

Endpoints disponibles

Routes regroupées par domaine ci-dessous. Le contrat OpenAPI fait foi (params, schémas, apps autorisées).

Investisseurs — /internal/investors

Route Objet
POST /lookup Recherche un lot d'emails / téléphones / UUIDs → investisseurs
GET /search Recherche par nom, ou derniers investisseurs créés
GET /{investorId}/identity Identité, coordonnées, statut KYC
GET /{investorId}/balances Soldes (compte, retirable, cadeau), en cents
GET /{investorId}/payment-methods Moyens de paiement / IBAN
GET /{investorId}/tax-rates Taux d'imposition par année
GET /{investorId}/portfolio Portefeuille : totaux + ventilation par type de contrat
GET /{investorId}/projects Projets investis (position, statut)
GET /{investorId}/wallet-transactions Mouvements de portefeuille
GET /{investorId}/revenue-transactions Revenus (imposables / non imposables)
GET /{investorId}/referral Parrainage : code propre, code utilisé, parrain
GET /{investorId}/auto-invest-plan Dernier plan d'investissement automatique

Projets — /internal/projects

Route Objet
GET / Liste des projets (référentiel 24 colonnes)
GET /search Recherche projet par nom / référence
GET /{projectId} Détail d'un projet
GET /repayment-status État de remboursement consolidé pour un lot de projets
GET /{projectId}/owner Porteur du projet (personne morale / physique)
GET /{projectId}/spv Société véhicule (SPV) liée au projet

Porteur de projet / facturation — /internal/project-owner

Route Objet
GET /management-fees-invoicing/{period} Frais de gestion du mois (montants HT/TVA/TTC) + axonautId de la société porteuse à facturer
GET /{projectId}/invoicing-ids siren + axonautId + invoiceNinjaId de la société porteuse d'un projet (404 si pas de correspondance)

Segments — /internal/segments

SQL opérateur (équipe marketing) ; chaque endpoint exécute la même requête contre des outputs différents. Voir l'architecture (section Segments — SQL opérateur) pour les garde-fous.

Route Objet
POST /recipients Liste les investorId matchant un SQL
POST /count Compte les destinataires sans renvoyer la liste
POST /preview Échantillon (50 lignes) du SQL pour validation visuelle

Product highlights (What's New) — /internal/product-highlights

Authentifié par x-api-key (consommateur ai-agent uniquement). Lecture du catalogue + écriture des suggestions ai_proposal. Impossible de publier, Keep/Skip ou supprimer — ça reste au BO App Config.

Route Objet
GET / Tous les highlights du appScope (pdp | investors), tous statuts y compris declined — pas de réactions
PUT /proposals Upsert de suggestions (max 10) : sans id → insert ai_proposal ; avec id → update seulement si déjà ai_proposal du même scope. publishedAt ISO optionnel (date d'affichage = commit / merge) ; absent → maintenant

Leaderboard vitrine — /internal/leaderboard

Authentifié par x-api-key (consommateur site-vitrine) — la data n'expose aucune donnée sensible (publicInvestorId opaque, jamais le customerId). Données précalculées (1 refresh / jour). Voir le module Leaderboard pour le flow, les limites et la roadmap.

Route Objet
POST /top Top investisseurs paginé (rank, revenus mois courant, all-time)
POST /statistics Globals dérivés (investorCount, totalCouponRevenue, totalInvested, …)
POST /investor Une ligne du leaderboard + time series 12 mois + investmentsByProject (lookup par publicInvestorId)

Projet Analyse — /internal/projet-analyse/project/{projectId}

Contrat machine-to-machine avec l'outil d'analyse : lecture de l'état d'un dossier de financement (phase 1) et actions d'instruction (questions, demandes de documents, refus, offre). Les mutations répondent sans corps — POST en 201, PUT en 200 ; l'état frais se relit toujours via le GET /.

Route Objet
GET / État complet phase 1 : statut, questions, demandes de documents, présentation, emprunteur, documents déposés (URLs presigned)
POST /questions Pousser une question au porteur → passe le dossier en blocked
POST /document-requests Réclamer un document nominatif → blocked
POST /comment Commentaire analyste affiché sur la page bloquée → blocked
PUT /missing-documents Synchroniser la liste des documents manquants (remplacement total)
PUT /document/{documentId}/refuse Marquer un document déposé comme refusé
POST /offer Pousser une offre de financement versionnée
POST /reject Rejeter le dossier avec un commentaire

AI Platform — /internal/project-financing-request/{projectId}

Retour de la classification documentaire lancée par le PDP à la soumission d'un dossier (POST {AI_PLATFORM_API_URL}/classifications). projectId est celui reçu dans l'appel.

Route Objet
POST /documents/classifications Webhook de résultats : { documents: [{ documentId, kind, companyId, representativeId }] }, au plus un des deux ids non null, les deux null = la pièce décrit le dossier lui-même. Répond 201 ; 400 si un documentId apparaît deux fois dans le lot ou si les deux ids sont posés ; 404 si le projet, un document, la société ou un représentant est inconnu, et rien n'est écrit. Pose kind et la société ou le représentant décrit sur la pièce du dossier, seulement s'ils sont encore vides : un type posé par le back-office ou un premier résultat est conservé, un rejeu n'écrit rien
GET /documents Documents d'onboarding du dossier avec kind (null tant que non classé), companyId / representativeId et URLs presigned fraîches — les URLs de l'appel sortant expirent : à relire avant de rejouer une classification pour ne pas reclasser ce qui l'est déjà, ou pour contrôler ce que le PDP a retenu. Aussi accessible avec la clé projet-analyse (outil d'analyse)

Récupérer le contrat OpenAPI

Le contrat est servi par l'API au format JSON, scopé au namespace /internal (pas de page HTML : c'est le JSON qui fait foi) :

Environnement Spec JSON
Production https://api.bricks.co/internal/docs/json
Staging https://api.staging.bricks.co/internal/docs/json
Local http://localhost:<port>/internal/docs/json

La spec est protégée

L'endpoint exige le même header x-api-key que les routes (n'importe quelle clé d'outil interne). Sans clé → 401. Le contrat n'est donc pas public.

Générer un client typé

La spec étant protégée, récupère-la une fois avec ta clé, puis génère depuis le fichier local — le plus simple est openapi-typescript + openapi-fetch (léger, zéro code runtime généré) :

curl -H "x-api-key: $BRICKS_API_KEY" https://api.bricks.co/internal/docs/json -o bricks-internal-openapi.json
npx openapi-typescript bricks-internal-openapi.json -o src/bricks-internal.d.ts
import createClient from 'openapi-fetch'
import type { paths } from './bricks-internal'

const client = createClient<paths>({
  baseUrl: 'https://api.bricks.co',
  headers: { 'x-api-key': process.env.BRICKS_API_KEY },
})

// Entièrement typé depuis la spec : path params, query et réponse
const { data, error } = await client.GET('/internal/investors/{investorId}/identity', {
  params: { path: { investorId } },
})

Besoin d'explorer la doc visuellement ? Pointe un viewer sur le même fichier local — npx @redocly/cli build-docs bricks-internal-openapi.json -o internal-api.html, ou ouvre le JSON dans Swagger Editor ou Scalar.

Côté Bricks ?

Comment ces routes sont construites (couches, contrat zod, validation, clés par app, doc auto, tests) → Architecture & décisions.