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 :
| 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
descriptionde 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.