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.
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
/api/* ou /hive/*.
The developer does not code inside APIBASE. The developer talks to APIBASE through /api/* or /hive/*.
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
customers, orders, products, invoices.
id_customer, id_order, customer_id, order_id.
full_name, deal_name, syncedAt, crm.synced.at.
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.
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
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',
];
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.
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,
]
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.
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
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',
]
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"}.
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',
]
/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":{...}}.
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']
);
/hive/get/acme/....Personal API does not use a base key in the URL. Hive does: /hive/get/acme/....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.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']
);
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']
);
}
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
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.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
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.
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.