Aller au contenu
Commencer

Votre premier import, de bout en bout

La vue d’ensemble vous laisse un moteur sain. Cette page est le reste des deux premières heures : un fichier entre, quelqu’un le relit, et des lignes signées arrivent sur votre backend.

Vous n’écrivez pas d’UI de mapping et vous ne déclarez pas le schéma dans le code hôte. Le schéma est un catalogue publié. Le widget le charge. Apply est un webhook signé — c’est le défaut.

your page Mildport engine your backend
───────── ─────────────── ────────────
<mildport-import ingest → match → review
catalog-key="crm"> ─────────► ─────────► POST /apply
HMAC-signed rows

Deux valeurs, toutes deux depuis votre compte Mildport :

Quoi Où ça va
Clé de licence Licences — une fois à l’émission license-key du widget
Clé publique Self-hosting (IMPORT_LICENSE_PUBLIC_KEY) le moteur, déjà, si le preflight de la vue d’ensemble a passé

Confirmez que le moteur accepte la clé :

Terminal window
curl -H "Authorization: Bearer $LICENSE" \
https://imports.your-infra.example/api/import/v1/license/verify

Une bonne réponse est "verified": true. Tout le reste — voir Dépannage de déploiement.

Le schéma vit dans l’éditeur de catalogues/admin/catalogs sur votre moteur, ou <mildport-catalog-editor> dans votre propre admin. Rédigez les champs depuis une spec OpenAPI ou un enregistrement d’exemple, marquez required ceux que votre API rejetterait vides, et publiez. Donnez au catalogue une clé stable (crm, contacts, …).

Épinglez cette clé sur le widget. Les changements de schéma après ça sont un publish dans l’éditeur, pas un release hôte :

<mildport-import
api-base-url="https://imports.your-infra.example"
license-key="SIGNED_TENANT_KEY"
catalog-key="crm"
></mildport-import>

Un catalogue publié et pas de catalog-key, ça va aussi — le widget l’adopte tout seul. Épinglez la clé quand une page doit toujours importer dans un schéma précis.

Schéma calculé par utilisateur à l’exécution, ou versionné avec votre app ? C’est le chemin schéma-en-code. Passez-le tant que vous n’avez pas une raison.

Apply est par défaut un POST signé vers votre backend. Enregistrez l’URL une fois ; la réponse porte le secret de signature exactement une fois — stockez-le.

Terminal window
curl -X POST https://imports.your-infra.example/api/import/v1/webhooks \
-H "Authorization: Bearer $LICENSE" \
-H "Content-Type: application/json" \
-d '{ "url": "https://api.your-app.example/mildport/apply" }'

Un premier regard sans backend ? el.applyMode = 'browser' et lisez les lignes depuis onResults. La production, c’est le webhook. Détails : Événements et apply et la référence webhook.

Ouvrez la page, déposez un CSV (ou un tableur brouillon, ou un PDF avec un tableau), confirmez le mapping proposé, corrigez ce que la grille de revue signale, et apply.

Le widget parle à votre moteur pour l’ingest et le mapping. Vous n’appelez pas l’ingest vous-même, sauf à construire un flux headless, sans widget.

Chaque livraison est signée HMAC. Vérifiez le corps brut avant de lui faire confiance, rejetez les horodatages trop vieux, et dédupliquez sur x-import-delivery-id — les retries sont normaux.

import { createHmac, timingSafeEqual } from 'node:crypto';
function verify(rawBody: string, header: string, secret: string): boolean {
const parts = Object.fromEntries(header.split(',').map(kv => kv.split('=')));
const expected = createHmac('sha256', secret).update(`${parts.t}.${rawBody}`).digest('hex');
const got = Buffer.from(parts.v1 ?? '', 'hex');
const exp = Buffer.from(expected, 'hex');
return got.length === exp.length && timingSafeEqual(got, exp);
}

Le corps, ce sont des lignes à la forme de votre catalogue (contact.email, …) plus un mapping. Renvoyez 2xx quand vous les avez persistées. Un 4xx est terminal ; un 5xx est retenté. Payload et en-têtes : Webhooks d’apply.

  • Le widget a émis import-applied avec un rowCount.
  • Votre handler a journalisé un deliveryId et écrit autant de lignes.
  • Une deuxième livraison avec le même id est un no-op de votre côté.

Bloqué ? Dépannage de déploiement couvre les images qui ne pullent pas, les 401 de licence, le CORS, et un pod qui ne devient jamais Ready.

Suite : Configuration · Licences · Catalogues