# Apporteur d'affaires

import { ApiExample, ApiResponse } from "../../src/ApiExample";

Un **apporteur d'affaires** apporte et gère un portefeuille d'entreprises clientes sur Instafuel. Vous construisez votre propre interface ; Instafuel fournit l'API et exécute les mouvements d'argent.

Cette page décrit le modèle. Les autres guides en détaillent les mécanismes.

## Le portefeuille

Votre portefeuille, c'est l'ensemble des entreprises rattachées à votre compte. Trois propriétés à retenir :

**Exclusif.** Une entreprise appartient à **un seul** apporteur à un instant donné. Il n'y a pas de portefeuille partagé.

**Dérivé de la clé.** Vos appels sont automatiquement restreints à votre portefeuille. Aucun paramètre ne permet d'en sortir — voir [Périmètre](/guides/perimetre).

**Non modifiable par vous.** Vous ajoutez une entreprise en l'onboardant. Vous ne pouvez ni en détacher une, ni en récupérer une qui appartient à un autre apporteur : ce sont des opérations Instafuel.

## Ce que vous pouvez faire

| Domaine | Capacité | Droit requis |
|---|---|---|
| Lecture | portefeuille, wallets et grand livre, transactions, chauffeurs, alertes | `COMPANIES_READ` … `ALERTS_READ` |
| Onboarding | créer une entreprise cliente et son premier compte gestionnaire de flotte | `COMPANIES_WRITE`, `USERS_WRITE` |
| Comptes clients | créer et modifier les comptes gestionnaire de flotte et directeur financier | `COMPANIES_WRITE`, `USERS_WRITE` |
| Financier | **demander** un crédit de wallet avec preuve — voir [Crédit wallet](/guides/credit-wallet) | `CREDIT_REQUEST_WRITE` |
| Rapports | déclencher un export et récupérer le fichier produit | `REPORTS_READ` |

Hors de votre portée : les stations, les marketeurs, les paramètres de la plateforme, les débits, les blocages de wallet, et toute donnée d'une entreprise qui n'est pas dans votre portefeuille.

## Onboarder une entreprise

Un seul appel fait trois choses : il crée l'entreprise, la rattache à votre portefeuille, et crée son compte gestionnaire de flotte initial — qui reçoit son lien d'activation.

<ApiExample
  method="POST"
  path="/v1/papi/companies"
  idempotency
  body={{
    name: "Transports Kouassi SARL",
    email: "contact@kouassi.ci",
    phoneNumber: "+2250700000001",
    rccm: "CI-ABJ-2024-B-12345",
    nif: "1234567A",
    headquartersAddress: "Zone 4, Marcory, Abidjan",
    fleetAdministrator: {
      firstName: "Awa",
      lastName: "Kouassi",
      email: "awa.kouassi@kouassi.ci",
      phoneNumber: "+2250700000002",
    },
  }}
/>

<ApiResponse
  status={201}
  body={{
    id: 4832,
    ref: "ENT-B14E77A3",
    name: "Transports Kouassi SARL",
    email: "contact@kouassi.ci",
    phoneNumber: "+2250700000001",
    rccm: "CI-ABJ-2024-B-12345",
    nif: "1234567A",
    headquartersAddress: "Zone 4, Marcory, Abidjan",
    status: "ACTIVE",
    walletBalanceFcfa: 0,
    fleetAdministrator: {
      id: 9114,
      ref: "USR-2D80F5C7",
      firstName: "Awa",
      lastName: "Kouassi",
      email: "awa.kouassi@kouassi.ci",
      role: "FLEET_ADMINISTRATOR",
      status: "PENDING_ACTIVATION",
      activationExpiresAt: "2026-09-03T10:22:05.000Z",
    },
    createdAt: "2026-08-31T10:22:05.000Z",
  }}
/>

Une entreprise déjà connue — même RCCM ou même email — est refusée plutôt que dupliquée :

<ApiResponse
  status={409}
  body={{
    error: {
      code: "COMPANY_ALREADY_EXISTS",
      message: "Une entreprise avec ce RCCM existe déjà",
      conflictingField: "rccm",
    },
  }}
/>

<Callout type="caution" title="Le rattachement n'est pas négociable depuis le corps">
  Un identifiant d'apporteur envoyé dans le corps est ignoré. L'entreprise est rattachée au portefeuille de la clé utilisée, toujours.
</Callout>

### L'email est obligatoire

Aucun compte web n'est créé avec un mot de passe. Le gestionnaire de flotte reçoit un **lien d'activation à usage unique, valable 72 h** — d'où le `status: "PENDING_ACTIVATION"` et l'`activationExpiresAt` de la réponse. Sans adresse email valide, le compte existe mais ne pourra jamais se connecter.

Vérifiez l'adresse avant l'appel : une faute de frappe se solde par un client bloqué et un compte à recréer.

## Lire le portefeuille

```http title="Endpoints"
GET /v1/papi/companies                     # entreprises du portefeuille
GET /v1/papi/companies/4832                # détail d'une entreprise
GET /v1/papi/companies/4832/wallet         # solde et engagements
GET /v1/papi/companies/4832/wallet/ledger  # écritures du wallet
GET /v1/papi/wallets                       # soldes de tout le portefeuille
GET /v1/papi/transactions                  # transactions, toutes entreprises confondues
GET /v1/papi/transactions/{id}             # un plein précis
GET /v1/papi/drivers                       # portefeuilles chauffeurs
GET /v1/papi/alerts                        # alertes ouvertes de vos clients
GET /v1/papi/reports/portfolio-summary     # synthèse chiffrée sur une période
```

Toutes ces routes sont restreintes à votre portefeuille. Un `companyId` en paramètre restreint **davantage** ; hors portefeuille, il renvoie `404` — l'API ne confirme pas l'existence d'une entreprise qui n'est pas la vôtre.

<ApiExample
  path="/v1/papi/companies"
  query={{ search: "Kouassi", page: 1, perPage: 20 }}
/>

<ApiResponse
  status={200}
  body={{
    data: [
      {
        id: 4832,
        ref: "ENT-B14E77A3",
        name: "Transports Kouassi SARL",
        email: "contact@kouassi.ci",
        phoneNumber: "+2250700000001",
        rccm: "CI-ABJ-2024-B-12345",
        nif: "1234567A",
        headquartersAddress: "Zone 4, Marcory, Abidjan",
        status: "ACTIVE",
        walletBalanceFcfa: 1450000,
        driversCount: 8,
        vehiclesCount: 6,
        createdAt: "2026-02-11T09:14:02.000Z",
      },
      {
        id: 4790,
        ref: "ENT-3F71B8D2",
        name: "Bâtiments Diallo & Fils",
        email: "compta@diallo-btp.ci",
        phoneNumber: "+2250505000042",
        rccm: "CI-ABJ-2023-B-88120",
        nif: "9982104B",
        headquartersAddress: "Yopougon Zone Industrielle, Abidjan",
        status: "ACTIVE",
        walletBalanceFcfa: 320000,
        driversCount: 3,
        vehiclesCount: 3,
        createdAt: "2026-01-28T15:02:47.000Z",
      },
    ],
    pagination: {
      page: 1,
      perPage: 20,
      total: 12,
      totalPages: 1,
    },
  }}
/>

Le wallet d'une entreprise se lit à part, avec le détail de ce qui est engagé :

<ApiExample path="/v1/papi/companies/4832/wallet" />

<ApiResponse
  status={200}
  body={{
    companyId: 4832,
    ref: "WAL-6E51A9C4",
    balanceFcfa: 1450000,
    heldFcfa: 62000,
    availableFcfa: 1388000,
    status: "ACTIVE",
    lastEntryAt: "2026-08-30T07:41:19.000Z",
  }}
/>

`availableFcfa` est ce que les chauffeurs de l'entreprise peuvent réellement dépenser : le solde moins les pleins ouverts (`heldFcfa`). C'est ce chiffre qu'il faut afficher, pas `balanceFcfa`.

## Gérer les comptes de vos clients

```http title="Endpoints"
GET  /v1/papi/companies/4832/users
POST /v1/papi/companies/4832/users
PUT  /v1/papi/companies/4832/users/9114
```

Deux rôles sont créables : **gestionnaire de flotte** (`FLEET_ADMINISTRATOR`) et **directeur financier** (`DAF`).

<ApiExample
  method="POST"
  path="/v1/papi/companies/4832/users"
  idempotency
  body={{
    firstName: "Serge",
    lastName: "Bamba",
    email: "serge.bamba@kouassi.ci",
    phoneNumber: "+2250707000123",
    role: "DAF",
  }}
/>

<ApiResponse
  status={201}
  body={{
    id: 9127,
    ref: "USR-45C1E0B8",
    firstName: "Serge",
    lastName: "Bamba",
    email: "serge.bamba@kouassi.ci",
    phoneNumber: "+2250707000123",
    role: "DAF",
    companyId: 4832,
    status: "PENDING_ACTIVATION",
    activationExpiresAt: "2026-09-03T11:40:12.000Z",
  }}
/>

Toute autre valeur de `role` est refusée :

<ApiResponse
  status={422}
  body={{
    error: {
      code: "ROLE_NOT_ALLOWED",
      message: "Rôle non autorisé à la création d'un compte client",
      allowedRoles: ["FLEET_ADMINISTRATOR", "DAF"],
    },
  }}
/>

Le compte créé appartient à l'**entreprise**, pas à vous : il n'obtient aucun accès à l'API partenaire. Il reçoit son propre lien d'activation et se connecte au tableau de bord Instafuel.

La séparation des deux rôles est délibérée : le gestionnaire de flotte pilote l'exploitation (véhicules, chauffeurs, documents), le directeur financier pilote l'argent (plafonds, recharges, rapports). Voir [Rôles](/reference/roles).

## Modifier une entreprise

<ApiExample
  method="PUT"
  path="/v1/papi/companies/4832"
  idempotency
  body={{
    email: "finance@kouassi.ci",
    phoneNumber: "+2250700000003",
    headquartersAddress: "Zone 4C, Rue du Canal, Marcory, Abidjan",
  }}
/>

Champs modifiables : `name`, `email`, `phoneNumber`, `rccm`, `nif`, `headquartersAddress`.

Tout autre champ envoyé est ignoré côté serveur. Vous ne pouvez ni déplacer une entreprise vers un autre portefeuille, ni toucher à son wallet, ni la supprimer.

## Rapports

Un seul endpoint, **synchrone** : la synthèse du portefeuille sur une période. Il n'y a pas d'export de fichier sur cette API — un ERP veut des nombres à agréger, pas un classeur à parser.

<ApiExample
  path="/v1/papi/reports/portfolio-summary"
  query={{ from: "2026-08-01", to: "2026-08-31" }}
/>

<ApiResponse
  status={200}
  body={{
    period: { from: "2026-08-01T00:00:00.000Z", to: "2026-08-31T23:59:59.000Z" },
    totals: {
      companies: 14,
      activeCompanies: 12,
      transactions: 318,
      amountFcfa: 9482500,
      walletBalanceFcfa: 13942000,
      walletHeldFcfa: 214000,
    },
    companies: [
      {
        id: 4832,
        ref: "ENT-B14E77A3",
        name: "Transports Kouassi SARL",
        status: "ACTIVE",
        transactions: 47,
        amountFcfa: 1842300,
        walletBalanceFcfa: 1450000,
      },
    ],
  }}
/>

Sans `from` ni `to`, la période couvre les **30 derniers jours**. Seules les transactions confirmées sont comptabilisées : un plein ouvert n'entre pas dans `amountFcfa`, mais pèse dans `walletHeldFcfa`.

Pour un export de fichier, passez par le portail partenaire : la surface machine ne produit que du JSON.

## Ce que vous ne pouvez pas faire

| Opération | Pourquoi |
|---|---|
| Créditer directement un wallet | vous êtes un tiers ; seul Instafuel constate l'encaissement — voir [Crédit wallet](/guides/credit-wallet) |
| Débiter, rembourser, bloquer un wallet | opérations Instafuel |
| Détacher une entreprise de votre portefeuille | opération Instafuel |
| Supprimer une entreprise ou un compte client | les données financières sont conservées ; on désactive, on ne supprime pas |
| Voir les stations, les marketeurs, les prix | hors du modèle apporteur |
