Intégration ERPERP integration InventaireInventory AchatsPurchasing FacturesInvoices Hive ACLs

Connectez vos opérations sans exposer votre base de données Connect business operations without exposing your database

Connectez vos systèmes ERP, outils d’inventaire, flux d’achats et plateformes financières à APIBASE avec des coordonnées déterministes. Les systèmes externes n’ont pas besoin d’accès direct à la base de données. Ils envoient seulement des requêtes API ou Hive autorisées.

Connect ERP systems, inventory tools, purchasing workflows and finance platforms to APIBASE using deterministic coordinates. External systems do not need direct database access. They only send authorized API or Hive requests.

Vue d’ensembleOverview

Le modèle d’intégration ERPThe ERP integration model

Une intégration ERP relie les systèmes opérationnels à APIBASE : produits, fournisseurs, niveaux de stock, bons d’achat, expéditions et factures.

An ERP integration connects operational systems to APIBASE: products, suppliers, stock levels, purchase orders, shipments and invoices.

L’ERP externe ou le backend communique avec APIBASE uniquement par requêtes HTTP. Il n’appelle pas les modèles, classes ou méthodes PHP internes d’APIBASE.

The external ERP or backend communicates with APIBASE through HTTP requests only. It does not call internal APIBASE models, classes or PHP methods.

// Recommended architecture

ERP system
  ↓
external backend / proxy
  ↓ HTTP requests
APIBASE API / Hive
  ↓
user BASE
APIBASE agit comme une couche de données opérationnelles contrôlée. L’ERP reçoit seulement les coordonnées et permissions nécessaires à sa tâche. APIBASE acts as a controlled operational data layer. The ERP receives only the coordinates and permissions required for its task.
Règles structurellesStructural rules

Utilisez une nomenclature APIBASE valideUse valid APIBASE naming

Les données ERP sont fortement relationnelles. La discipline de nommage est donc importante. Les tables doivent être au pluriel. Les clés primaires utilisent id_*. Les clés étrangères utilisent *_id. Les champs métier normaux n’utilisent pas de soulignés.

ERP data is highly relational. That makes naming discipline important. Tables must be plural. Primary keys use id_*. Foreign keys use *_id. Normal business fields do not use underscores.

// Valid APIBASE ERP table structure

products
  C1 = id_product
  C2 = product
  C3 = sku
  C4 = unit.price
  C5 = erp.id
  C6 = synced.at
  C7 = erp.status

suppliers
  C1 = id_supplier
  C2 = supplier
  C3 = email
  C4 = phone
  C5 = erp.id

stocks
  C1 = id_stock
  C2 = stock
  C3 = product_id
  C4 = stock.quantity
  C5 = stock.minimum
  C6 = stock.location

purchases
  C1 = id_purchase
  C2 = purchase
  C3 = supplier_id
  C4 = product_id
  C5 = purchase.quantity
  C6 = purchase.status
  C7 = purchase.date
Tables validesValid tables

products, suppliers, stocks, purchases, invoices.

Clés validesValid keys

id_product, product_id, id_supplier, supplier_id.

Champs invalidesInvalid fields

unit_price, stockQuantity, erp.synced.at, purchase_status.

Utilisez une notation à un seul point pour les champs métier composés comme unit.price, stock.quantity, purchase.status et synced.at. N’empilez pas plusieurs points. Use one-level dot notation for composed business fields such as unit.price, stock.quantity, purchase.status and synced.at. Do not stack multiple dots.
Phase de configurationSetup phase

Découvrez les coordonnées des tables et colonnes ERPDiscover ERP table and column coordinates

Ne codez pas les identifiants de tables et de colonnes à l’aveugle. Appelez /schema une fois pendant la configuration, puis stockez les T et C retournés dans votre configuration.

Do not hardcode table and column ids blindly. Call /schema once during setup, then store the returned T and C ids in your configuration.

Dans cet exemple, l’intégration cible les tables products, stocks et purchases dans la base publique d’exemple acme.

In this example, the integration targets products, stocks and purchases in the public example base acme.

// ── PHASE 1 : setup — run once, store results in config ──────

$api   = "https://apibase.work";
$base  = "acme";
$token = "TOKEN_ERP";

$productsSchema  = api_get("$api/hive/schema/$base/products",  $token);
$stocksSchema    = api_get("$api/hive/schema/$base/stocks",    $token);
$purchasesSchema = api_get("$api/hive/schema/$base/purchases", $token);

$T_products  = $productsSchema['T'];   // 4
$T_stocks    = $stocksSchema['T'];     // 9
$T_purchases = $purchasesSchema['T'];  // 12

$productCols  = array_flip($productsSchema['columns']);
$stockCols    = array_flip($stocksSchema['columns']);
$purchaseCols = array_flip($purchasesSchema['columns']);

$C_product_id      = $stockCols['product_id'];        // 3
$C_stock_quantity  = $stockCols['stock.quantity'];    // 4
$C_stock_minimum   = $stockCols['stock.minimum'];     // 5

$C_supplier_id       = $purchaseCols['supplier_id'];        // 3
$C_purchase_product_id= $purchaseCols['product_id'];         // 4
$C_purchase_quantity = $purchaseCols['purchase.quantity'];  // 5
$C_purchase_status   = $purchaseCols['purchase.status'];    // 6
La phase de configuration doit être exécutée une fois par table. Au moment des requêtes, utilisez les constantes stockées plutôt que de redécouvrir le schéma à répétition.The setup phase should run once per table. At request time, use the stored constants instead of rediscovering the schema repeatedly.
Pattern 1

Lire une ligne de stock depuis APIBASERead a stock line from APIBASE

Le backend ERP peut lire une ligne de stock précise avec la coordonnée de table et l’identifiant logique de ligne. En Hive, la base key apparaît dans l’URL.

The ERP backend can read a precise stock line using the table coordinate and logical line identifier. In Hive, the base key appears in the URL.

// ── PHASE 2 : read stock from Hive ───────────────────────────

$line = 21;

$stock = api_get(
  "$api/hive/get/$base/T{$T_stocks}/L{$line}?format=assoc",
  $token
)['data'];

// Example returned data
$stock = [
  'id_stock'       => 21,
  'stock'          => 'Main warehouse stock',
  'product_id'     => 8,
  'stock.quantity' => 42,
  'stock.minimum'  => 10,
  'stock.location' => 'warehousea',
];
Le token doit avoir le droit read sur la table stocks pour la base Hive acme.The token must have the read right on the stocks table for the acme Hive base.
Pattern 2

Mettre à jour une quantité d’inventaireUpdate inventory quantity

Dans un PUT Hive, l’URL identifie la coordonnée cible exacte. La nouvelle valeur est envoyée dans le corps JSON.

In Hive PUT, the URL identifies the exact target coordinate. The new value is sent in the JSON body.

Cet exemple met seulement à jour stock.quantity. L’ERP n’a pas besoin d’accès à toute la base de données.

This example updates only stock.quantity. The ERP does not need access to the full database.

// ── PHASE 3 : update one stock cell through Hive ─────────────

$stockLine = 21;

api_put(
  "$api/hive/put/$base/T{$T_stocks}/L{$stockLine}/C{$C_stock_quantity}",
  $token,
  ['value' => 37]
);
// Example response

[
  'status'    => 'success',
  'mode'      => 'cell',
  'message'   => 'Cell updated.',
  'hive_base' => 'acme',
]
N’ajoutez pas les valeurs dans la query string. La coordonnée identifie la cellule. Le corps transporte la valeur : {"value":37}.Do not append values to the URL query string. The coordinate identifies the cell. The body carries the value: {"value":37}.
Pattern 3

Créer un bon d’achatCreate a purchase order

Pour créer un bon d’achat via Hive, envoyez une requête POST vers la table purchases. Le corps de la requête doit contenir un objet record.

To create a purchase order through Hive, send a POST request to the purchases table. The request body must contain a record object.

// ── PHASE 4 : create purchase through Hive ───────────────────

$created = api_post(
  "$api/hive/post/$base/T{$T_purchases}",
  $token,
  [
    'record' => [
      'purchase'          => 'Purchase for product 8',
      'supplier_id'       => 3,
      'product_id'        => 8,
      'purchase.quantity' => 50,
      'purchase.status'   => 'pending',
      'purchase.date'     => date('Y-m-d'),
    ]
  ]
);

$line       = $created['line'];         // 34
$purchaseId = $created['id_purchase'];  // 34
// Example response from APIBASE

[
  'status'      => 'success',
  'message'     => 'Record added.',
  'line'        => 34,
  'hive_base'   => 'acme',
  'id_purchase' => 34,
]
Le token doit avoir le droit add sur la table purchases. Sans la bonne ACL Hive, APIBASE retourne 403.The token must have the add right on the purchases table. Without the correct Hive ACL, APIBASE returns 403.
Pattern 4

Mettre à jour le statut d’achatUpdate purchase status

Les flux ERP doivent souvent mettre à jour un seul état opérationnel : pending, approved, received, cancelled ou closed.

ERP workflows often need to update only one operational state: pending, approved, received, cancelled or closed.

// ── PHASE 5 : update purchase status through Hive ────────────

$purchaseLine = 34;

api_put(
  "$api/hive/put/$base/T{$T_purchases}/L{$purchaseLine}/C{$C_purchase_status}",
  $token,
  ['value' => 'received']
);
C’est le modèle APIBASE : l’ERP ne met pas à jour une ligne complète à l’aveugle. Il cible une coordonnée opérationnelle exacte.This is the APIBASE model: the ERP does not update a whole database row blindly. It targets one exact operational coordinate.
Pattern 5

Synchroniser avec un fournisseur ERP externeSynchronize with an external ERP provider

L’appel au fournisseur ERP se fait à l’extérieur d’APIBASE. APIBASE n’a pas besoin de savoir comment le fournisseur ERP fonctionne. Votre backend lit depuis APIBASE, envoie le payload à l’ERP, puis écrit le résultat dans APIBASE.

The ERP provider call happens outside APIBASE. APIBASE does not need to know how the ERP provider works. Your backend reads from APIBASE, sends the payload to the ERP, then writes the result back to APIBASE.

// ── PHASE 6 : send product data to an external ERP ───────────

$productLine = 8;

$product = api_get(
  "$api/hive/get/$base/T{$T_products}/L{$productLine}?format=assoc",
  $token
)['data'];

$erpResponse = erp_post(
  "https://erp.example.com/api/products",
  [
    'name'   => $product['product'],
    'sku'    => $product['sku'],
    'price'  => $product['unit.price'],
  ]
);

$erpId = $erpResponse['id'];
Les noms de champs ERP sont externes à APIBASE. Les règles de nommage APIBASE s’appliquent aux tables et champs APIBASE, pas au schéma du fournisseur ERP.The ERP field names are external to APIBASE. APIBASE naming rules apply to APIBASE tables and fields, not to the ERP provider’s schema.
Pattern 6

Écrire les métadonnées de synchronisation ERPWrite ERP synchronization metadata

Après le retour de l’identifiant ERP externe, écrivez le résultat dans APIBASE avec des coordonnées exactes.

After the external ERP returns its identifier, write the result back to APIBASE through exact coordinates.

// ── PHASE 7 : write ERP result back to APIBASE ───────────────

$C_erp_id     = $productCols['erp.id'];      // 5
$C_synced_at  = $productCols['synced.at'];   // 6
$C_erp_status = $productCols['erp.status'];  // 7

api_put(
  "$api/hive/put/$base/T{$T_products}/L{$productLine}/C{$C_erp_id}",
  $token,
  ['value' => $erpId]
);

api_put(
  "$api/hive/put/$base/T{$T_products}/L{$productLine}/C{$C_synced_at}",
  $token,
  ['value' => date('Y-m-d\TH:i')]
);

api_put(
  "$api/hive/put/$base/T{$T_products}/L{$productLine}/C{$C_erp_status}",
  $token,
  ['value' => 'synced']
);
L’intégration met seulement à jour erp.id, synced.at et erp.status. Elle n’a pas besoin d’un accès large en écriture à des données non liées.The integration updates only erp.id, synced.at and erp.status. It does not need broad write access to unrelated data.
AlternativeAlternative

Mettre à jour une ligne ERP complète Update a full ERP line

Pour mettre à jour un enregistrement complet via Hive, omettez la colonne dans l’URL et envoyez un objet record. Cela déclenche le mode ligne.

To update a full record through Hive, omit the column from the URL and send a record object. This triggers line mode.

À utiliser avec prudence. Pour les métadonnées opérationnelles, les mises à jour cellule par cellule sont généralement plus sûres.

Use this carefully. For operational metadata, cell updates are usually safer.

// ── Alternative : full product line update through Hive ──────

$updated = api_put(
  "$api/hive/put/$base/T{$T_products}/L{$productLine}",
  $token,
  [
    'record' => [
      'id_product' => $productLine,
      'product'    => 'Industrial pump',
      'sku'        => 'PMP100',
      'unit.price' => '1200.00',
      'erp.id'     => 'erp7890',
      'synced.at'  => date('Y-m-d\TH:i'),
      'erp.status' => 'synced',
    ]
  ]
);
// Example response for a line update

[
  'status'    => 'success',
  'mode'      => 'line',
  'message'   => 'Line updated.',
  'hive_base' => 'acme',
]
Mode cellule : /hive/put/acme/T4/L8/C5 avec {"value":"..."}. Mode ligne : /hive/put/acme/T4/L8 avec {"record":{...}}. Cell mode: /hive/put/acme/T4/L8/C5 with {"value":"..."}. Line mode: /hive/put/acme/T4/L8 with {"record":{...}}.
Personal API

Même modèle avec l’API personnelleSame pattern through the personal API

Utilisez /api/* quand le token cible la propre base du propriétaire. Utilisez /hive/* quand le token accède à une base partagée contrôlée par ACL Hive.

Use /api/* when the token targets the owner’s own base. Use /hive/* when the token accesses a shared base controlled by Hive ACLs.

// ── Personal API version — owner’s own base ──────────────────

$stock = api_get(
  "$api/api/get/T{$T_stocks}/L{$stockLine}?format=assoc",
  $token
)['data'];

api_put(
  "$api/api/put/T{$T_stocks}/L{$stockLine}/C{$C_stock_quantity}",
  $token,
  ['value' => 37]
);
L’API personnelle n’utilise pas de base key dans l’URL. Hive oui : /hive/get/acme/....Personal API does not use a base key in the URL. Hive does: /hive/get/acme/....
MappingMapping

Mapper les champs APIBASE vers les champs ERPMap APIBASE fields to ERP fields

Un connecteur ERP a besoin d’une couche de mapping. Le côté gauche représente les noms de champs APIBASE. Le côté droit représente les noms de champs ERP externes.

An ERP connector needs a mapping layer. The left side represents APIBASE field names. The right side represents external ERP field names.

// left side  = APIBASE field names
// right side = external ERP field names
// underscores are valid only for APIBASE keys such as id_product and product_id
// dots are used for composed business fields with one structural level

$erpMap = [
  'products' => [
    'product'    => 'name',
    'sku'        => 'sku',
    'unit.price' => 'price',
    'erp.id'     => 'id',
    'synced.at'  => 'synced.at',
    'erp.status' => 'status',
  ],
  'stocks' => [
    'stock'          => 'name',
    'product_id'     => 'product.id',
    'stock.quantity' => 'quantity',
    'stock.minimum'  => 'minimum',
    'stock.location' => 'location',
  ],
  'purchases' => [
    'purchase'          => 'name',
    'supplier_id'       => 'supplier.id',
    'product_id'        => 'product.id',
    'purchase.quantity' => 'quantity',
    'purchase.status'   => 'status',
    'purchase.date'     => 'date',
  ],
];
product_id et supplier_id sont valides parce que ce sont des clés étrangères. unit_price ou purchase_status ne seraient pas des champs métier APIBASE valides.product_id and supplier_id are valid because they are foreign keys. unit_price or purchase_status would not be valid APIBASE business fields.
Modèle completComplete pattern

Flux complet de synchronisation ERPComplete ERP synchronization flow

C’est la première version la plus propre lorsque APIBASE reste la source de vérité et que le fournisseur ERP conserve des données opérationnelles miroirs.

This is the cleanest first version when APIBASE remains the source of truth and the ERP provider stores mirrored operational data.

// ── COMPLETE FLOW : APIBASE master → ERP mirror ──────────────

// 1. Discover schema once
$productsSchema = api_get("$api/hive/schema/$base/products", $token);
$T_products = $productsSchema['T'];
$productCols = array_flip($productsSchema['columns']);

$C_erp_id     = $productCols['erp.id'];
$C_synced_at  = $productCols['synced.at'];
$C_erp_status = $productCols['erp.status'];

// 2. Read the product from APIBASE
$product = api_get(
  "$api/hive/get/$base/T{$T_products}/L{$productLine}?format=assoc",
  $token
)['data'];

// 3. Send the product to the ERP provider
$erpResponse = erp_post(
  "https://erp.example.com/api/products",
  [
    'name'  => $product['product'],
    'sku'   => $product['sku'],
    'price' => $product['unit.price'],
  ]
);

$erpId = $erpResponse['id'];

// 4. Write synchronization metadata back to APIBASE
api_put(
  "$api/hive/put/$base/T{$T_products}/L{$productLine}/C{$C_erp_id}",
  $token,
  ['value' => $erpId]
);

api_put(
  "$api/hive/put/$base/T{$T_products}/L{$productLine}/C{$C_synced_at}",
  $token,
  ['value' => date('Y-m-d\TH:i')]
);

api_put(
  "$api/hive/put/$base/T{$T_products}/L{$productLine}/C{$C_erp_status}",
  $token,
  ['value' => 'synced']
);
APIBASE n’a pas besoin de savoir comment le fournisseur ERP fonctionne. Le backend externe gère le fournisseur, puis écrit seulement le résultat de synchronisation dans APIBASE.APIBASE does not need to know how the ERP provider works. The external backend handles the provider, then writes only the synchronization result back to APIBASE.
Option webhookWebhook option

Recevoir des webhooks ERPReceiving ERP webhooks

Si le fournisseur ERP supporte les webhooks, il devrait notifier votre backend externe. Le backend vérifie l’événement, puis écrit les changements autorisés dans APIBASE par requêtes API ou Hive.

If the ERP provider supports webhooks, it should notify your external backend. The backend verifies the event, then writes authorized changes to APIBASE through API or Hive requests.

// Webhook architecture

ERP provider
  ↓ webhook
external backend / proxy
  ↓ verified HTTP request
APIBASE API / Hive
// Example webhook handling logic

$event = verify_erp_webhook();

if ($event['type'] === 'stock.updated') {
  api_put(
    "$api/hive/put/$base/T{$T_stocks}/L{$stockLine}/C{$C_stock_quantity}",
    $token,
    ['value' => $event['quantity']]
  );
}
Le fournisseur ERP ne devrait pas appeler APIBASE directement sauf s’il peut protéger sécuritairement le bearer token APIBASE. Un proxy backend est généralement plus sûr.The ERP provider should not call APIBASE directly unless it can safely protect the APIBASE bearer token. A backend proxy is usually the safer design.
PermissionsPermissions

Droits requis pour le tokenRequired token rights

Un token ERP devrait recevoir seulement les droits nécessaires à l’intégration. Pour Hive, les droits sont accordés par token, par base et par table.

An ERP token should only receive the rights needed for the integration. For Hive, rights are granted per token, per base and per table.

// Example ERP token rights for the acme base

token: erp-sync
scope: hive

products:
  read:   yes
  add:    no
  edit:   yes
  delete: no

stocks:
  read:   yes
  add:    no
  edit:   yes
  delete: no

purchases:
  read:   yes
  add:    yes
  edit:   yes
  delete: no
Enregistrer une base dans Hive ne donne pas accès par lui-même. Les permissions doivent être ajoutées explicitement dans les ACL Hive. Tant qu’aucune règle ACL n’existe pour une combinaison token + table, la requête retourne 403.Registering a base in Hive does not grant access by itself. Permissions must be added explicitly in Hive ACLs. Until an ACL rule exists for a token and table combination, the request returns 403.
RecommandationRecommendation

Commencez par APIBASE master → miroir ERPStart with APIBASE master → ERP mirror

Ne commencez pas avec une synchronisation bidirectionnelle sauf si c’est absolument nécessaire. Elle ajoute trop tôt la gestion des conflits, des doublons, des comparaisons de timestamps et des règles de suppression.

Do not start with bidirectional synchronization unless it is absolutely required. It adds conflict handling, duplicate handling, timestamp comparisons and deletion rules too early.

// Best first version

APIBASE master → ERP mirror

// Later, if truly required

ERP ↔ APIBASE
Simple opérationnellementOperationally simple

Une seule direction. Moins de cas limites. Plus facile à auditer et à déboguer.

One direction. Fewer edge cases. Easier to audit and debug.

Sécuritaire côté permissionsPermission-safe

L’ERP reçoit seulement les coordonnées et permissions nécessaires pour les produits, stocks, achats ou factures.

The ERP receives only the coordinates and permissions required for products, stock, purchases or invoices.

APIBASE peut connecter des systèmes ERP avec des coordonnées opérationnelles déterministes. Un ERP n’a pas besoin d’accès à la base de données. Il a seulement besoin de requêtes API ou Hive autorisées. APIBASE can connect to ERP systems through deterministic operational coordinates. An ERP does not need database access. It only needs authorized API or Hive requests.