Intégration CRMCRM integration HTTP only Bearer token Hive ACLs TLC coordinates

Intégration CRM
Connecter sans exposer votre base de données
CRM Integration
Connect without exposing your database

Connectez un CRM à APIBASE avec des coordonnées déterministes. Votre CRM ou backend n’a jamais besoin d’un accès direct à la base de données. Il envoie seulement des requêtes API ou Hive autorisées.

Connect a CRM to APIBASE using deterministic coordinates. Your CRM or backend never needs direct database access. It only sends authorized API or Hive requests.

Vue d’ensembleOverview

Le modèle d’intégrationThe integration model

Une intégration CRM devrait communiquer avec APIBASE uniquement par requêtes HTTP. L’application externe n’appelle pas les modèles, classes ou méthodes PHP internes d’APIBASE.

A CRM integration should communicate with APIBASE through HTTP requests only. The external application does not call internal APIBASE models, classes or PHP methods.

Le design recommandé est simple : un backend externe ou proxy conserve les identifiants CRM et le bearer token APIBASE. Le navigateur appelle votre backend. Votre backend appelle APIBASE et le fournisseur CRM.

The recommended design is simple: an external backend or proxy holds the CRM credentials and the APIBASE bearer token. The browser calls your backend. Your backend calls APIBASE and the CRM provider.

// Recommended architecture

Browser
  ↓
external backend / proxy
  ↓ HTTP requests
APIBASE API / Hive
  ↓
user BASE

external backend / proxy
  ↓ HTTP requests
CRM provider
Le développeur ne code pas à l’intérieur d’APIBASE. Il parle à APIBASE par /api/* ou /hive/*. The developer does not code inside APIBASE. The developer talks to APIBASE through /api/* or /hive/*.
Règles structurellesStructural rules

Utiliser une nomenclature APIBASE valideUse valid APIBASE naming

Les noms APIBASE sont structurels. Ils ne sont pas seulement des étiquettes. Une nomenclature valide permet aux humains et au moteur de comprendre le schéma instantanément.

APIBASE names are structural. They are not just labels. A valid naming pattern allows both humans and the engine to understand the schema instantly.

Les tables sont 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. Les champs métier composés peuvent utiliser un point.

Tables are plural. Primary keys use id_*. Foreign keys use *_id. Normal business fields do not use underscores. Composed business fields may use one dot.

// Valid APIBASE table structure

customers
  C1 = id_customer
  C2 = customer
  C3 = email
  C4 = phone
  C5 = crm.id
  C6 = synced.at
  C7 = crm.status

orders
  C1 = id_order
  C2 = order
  C3 = customer_id
  C4 = order.date
  C5 = total.amount
  C6 = order.status
Noms de tables validesValid table names

customers, orders, products, invoices.

Clés validesValid keys

id_customer, id_order, customer_id, order_id.

Champs métier invalidesInvalid business fields

full_name, deal_name, syncedAt, crm.synced.at.

Le souligné est réservé à la logique de clés seulement : id_customer et customer_id. Un champ métier devrait utiliser un nom simple en minuscules ou une notation à un niveau avec point, comme crm.id ou synced.at. The underscore is reserved for key logic only: id_customer and customer_id. A business field should use simple lowercase names or one-level dot notation such as crm.id or synced.at.
Phase de configurationSetup phase

Découvrir les coordonnées de tables et colonnesDiscover table and column coordinates

Ne codez pas les ids de tables et colonnes à l’aveugle. Appelez /schema une fois pendant la configuration, puis stockez les ids 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 CRM cible la table customers dans la base d’exemple publique acme.

In this example, the CRM integration targets the customers table in the public example base acme.

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

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

$schema = api_get("$api/hive/schema/$base/customers", $token);

$T_customers = $schema['T'];                  // 2
$cols        = array_flip($schema['columns']);

$C_customer   = $cols['customer'];     // 2
$C_email      = $cols['email'];        // 3
$C_phone      = $cols['phone'];        // 4
$C_crm_id     = $cols['crm.id'];       // 5
$C_synced_at  = $cols['synced.at'];    // 6
$C_crm_status = $cols['crm.status'];   // 7
La phase de configuration devrait être exécutée une seule 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.
Modèle 1Pattern 1

Lire un client depuis APIBASERead a customer from APIBASE

Le backend lit un client précis avec la coordonnée de table et l’identifiant logique de ligne. Dans Hive, la clé de base apparaît dans l’URL. Ici, la base d’exemple est acme.

The backend reads a precise customer using the table coordinate and the logical line identifier. In Hive, the base key appears in the URL. Here, the example base is acme.

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

$line = 14;

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

// Example returned data
$customer = [
  'id_customer' => 14,
  'customer'    => 'Acme Industries',
  'email'       => 'billing@acme.example',
  'phone'       => '+1-555-0100',
  'crm.id'      => '',
  'synced.at'   => '',
  'crm.status'  => 'pending',
];
Le token doit avoir le droit read sur la table T2 pour la base Hive acme. The token must have the read right on table T2 for the acme Hive base.
Modèle 2Pattern 2

Ajouter un client CRM dans APIBASEAdd a CRM customer to APIBASE

Pour ajouter un enregistrement par Hive, envoyez une requête POST vers la table cible. Le body doit contenir un objet record.

To add a record through Hive, send a POST request to the target table. The request body must contain a record object.

N’envoyez pas d’appels PHP internes APIBASE. C’est une requête HTTP normale faite par votre backend externe.

Do not send internal APIBASE PHP calls. This is a normal HTTP request made by your external backend.

// ── PHASE 2 : add customer through Hive ──────────────────────

$created = api_post(
  "$api/hive/post/$base/T{$T_customers}",
  $token,
  [
    'record' => [
      'customer'   => 'Acme Industries',
      'email'      => 'billing@acme.example',
      'phone'      => '+1-555-0100',
      'crm.id'     => '',
      'synced.at'  => '',
      'crm.status' => 'pending',
    ]
  ]
);

$line       = $created['line'];          // 14
$customerId = $created['id_customer'];   // 14
// Example response from APIBASE

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

Envoyer le client au fournisseur CRMSend the customer to the CRM provider

L’appel CRM se fait à l’extérieur d’APIBASE. APIBASE n’a pas besoin de connaître le fonctionnement du fournisseur CRM. Votre backend lit depuis APIBASE, envoie le payload au CRM, puis écrit le résultat de synchronisation dans APIBASE.

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

// ── PHASE 3 : send customer to the external CRM ──────────────

$crmResponse = crm_post(
  "https://crm.example.com/api/contacts",
  [
    'name'  => $customer['customer'],
    'email' => $customer['email'],
    'phone' => $customer['phone'],
  ]
);

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

Écrire le résultat CRM dans APIBASEWrite the CRM result back to APIBASE

Dans un PUT Hive, l’URL identifie la coordonnée exacte à modifier. La nouvelle valeur est envoyée dans le body JSON. N’ajoutez pas les valeurs dans la query string.

In Hive PUT, the URL identifies the exact target coordinate. The new value is sent in the JSON body. Do not append values to the URL query string.

Cet exemple écrit l’identifiant CRM retourné dans crm.id, puis met à jour synced.at et crm.status.

This example writes the returned CRM identifier into crm.id, then updates synced.at and crm.status.

// ── PHASE 4 : update one cell at a time through Hive ─────────

api_put(
  "$api/hive/put/$base/T{$T_customers}/L{$line}/C{$C_crm_id}",
  $token,
  ['value' => $crmId]
);

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

api_put(
  "$api/hive/put/$base/T{$T_customers}/L{$line}/C{$C_crm_status}",
  $token,
  ['value' => 'synced']
);
// Example response for a cell update

[
  'status'    => 'success',
  'mode'      => 'cell',
  'message'   => 'Cell updated.',
  'hive_base' => 'acme',
]
La coordonnée est la cellule : T2/L14/C5. Le body transporte la valeur : {"value":"crm7890"}. The coordinate is the cell: T2/L14/C5. The body carries the value: {"value":"crm7890"}.
AlternativeAlternative

Remplacer une ligne client complèteReplace a full customer line

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

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

Utilisez cela avec prudence. Une mise à jour de ligne complète devrait contenir l’état complet voulu de l’enregistrement. Pour les changements de métadonnées, les mises à jour cellule sont souvent plus sûres.

Use this carefully. A full-line update should contain the full intended record state. For metadata changes, cell updates are often safer.

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

$updated = api_put(
  "$api/hive/put/$base/T{$T_customers}/L{$line}",
  $token,
  [
    'record' => [
      'customer'   => 'Acme Industries',
      'email'      => 'billing@acme.example',
      'phone'      => '+1-555-0100',
      'crm.id'     => 'crm7890',
      'synced.at'  => date('Y-m-d\TH:i'),
      'crm.status' => 'synced',
    ]
  ]
);
// Example response for a line update

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

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

Utilisez /api/* quand le token cible la base propre au propriétaire. Utilisez /hive/* quand le token accède à une base partagée contrôlée par les ACLs 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 ──────────────────

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

api_put(
  "$api/api/put/T{$T_customers}/L{$line}/C{$C_crm_id}",
  $token,
  ['value' => 'crm7890']
);
L’API personnelle n’utilise pas de clé de base 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 CRMMap APIBASE fields to CRM fields

Un connecteur CRM 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 du CRM externe.

A CRM connector needs a mapping layer. The left side represents APIBASE field names. The right side represents external CRM field names.

Les noms APIBASE doivent rester structurellement valides. Les noms de champs CRM externes peuvent suivre le schéma propre au fournisseur CRM.

APIBASE names must remain structurally valid. External CRM field names may follow the CRM provider’s own schema.

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

$crmMap = [
  'customers' => [
    'customer'   => 'name',
    'email'      => 'email',
    'phone'      => 'phone',
    'crm.id'     => 'id',
    'synced.at'  => 'synced.at',
    'crm.status' => 'status',
  ],
  'orders' => [
    'order'        => 'name',
    'total.amount' => 'amount',
    'order.status' => 'stage',
    'customer_id'  => 'customer.id',
  ],
];
customer_id est valide parce que c’est une clé étrangère. full_name ou deal_name ne seraient pas des champs métier APIBASE valides.customer_id is valid because it is a foreign key. full_name or deal_name would not be valid APIBASE business fields.
Modèle completComplete pattern

Flux complet de synchronisation CRMComplete CRM synchronization flow

C’est la première version la plus propre quand APIBASE reste la source de vérité et que le CRM stocke un contact miroir.

This is the cleanest first version when APIBASE remains the source of truth and the CRM stores a mirrored contact.

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

// 1. Discover schema once
$schema = api_get("$api/hive/schema/$base/customers", $token);
$T_customers = $schema['T'];
$cols = array_flip($schema['columns']);

$C_crm_id     = $cols['crm.id'];
$C_synced_at  = $cols['synced.at'];
$C_crm_status = $cols['crm.status'];

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

// 3. Send the customer to the CRM provider
$crmResponse = crm_post(
  "https://crm.example.com/api/contacts",
  [
    'name'  => $customer['customer'],
    'email' => $customer['email'],
    'phone' => $customer['phone'],
  ]
);

$crmId = $crmResponse['id'];

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

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

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

Recevoir des webhooks CRMReceiving CRM webhooks

Si le CRM 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 CRM supports webhooks, the CRM should notify your external backend. The backend verifies the event, then writes authorized changes to APIBASE through API or Hive requests.

// Webhook architecture

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

$event = verify_crm_webhook();

if ($event['type'] === 'contact.updated') {
  api_put(
    "$api/hive/put/$base/T{$T_customers}/L{$line}/C{$C_crm_status}",
    $token,
    ['value' => 'updated']
  );
}
Le CRM ne devrait pas appeler APIBASE directement à moins de pouvoir protéger sécuritairement le bearer token APIBASE. Un proxy backend est généralement le design le plus sûr.The CRM 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 CRM devrait recevoir seulement les droits nécessaires à l’intégration. Pour Hive, les droits sont accordés par token, par base et par table.

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

// Example CRM token rights for the acme base

token: crm-sync
scope: hive

customers:
  read:   yes
  add:    yes
  edit:   yes
  delete: no

orders:
  read:   yes
  add:    no
  edit:   yes
  delete: no
Enregistrer une base dans Hive ne donne pas accès à lui seul. Les permissions doivent être ajoutées explicitement dans les ACLs Hive. Tant qu’une règle ACL n’existe pas 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

Commencer par APIBASE maître → miroir CRMStart with APIBASE master → CRM mirror

Ne commencez pas par une synchronisation bidirectionnelle. Elle ajoute trop tôt la gestion des conflits, doublons, comparaisons de timestamps et règles de suppression.

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

// Best first version

APIBASE master → CRM mirror

// Later, if truly required

CRM ↔ APIBASE
SimpleSimple

Une seule direction. Moins de cas limites. Plus rapide à implanter et plus facile à déboguer.

One direction. Fewer edge cases. Faster to implement and easier to debug.

SécuriséSecure

Le CRM reçoit seulement les coordonnées et permissions nécessaires à sa tâche.

The CRM receives only the coordinates and permissions required for its task.

APIBASE peut se connecter à n’importe quel CRM avec des coordonnées de données déterministes. APIBASE can connect to any CRM through deterministic data coordinates. Un CRM n’a pas besoin d’un accès base de données. Il a seulement besoin de requêtes API ou Hive autorisées. A CRM does not need database access. It only needs authorized API or Hive requests.