Skip to content

Knowledge

Le knowledge c'est la source de vérité de l'assistant IA pour tout ce qui n'est pas un produit : politique de livraison, fenêtre de retours, guides de tailles, histoire de la marque, FAQ. Poussez-le une fois et l'assistant ancre ses réponses sur ce que vous avez écrit, au lieu de deviner.

Quatre types d'entrées knowledge sont supportés :

  • snippet : réponse courte en texte brut pour une question donnée.
  • article : contenu HTML plus long (un article de blog, un article de help-center).
  • webpage : pointez Humind vers une URL publique et on fetch la page pour vous.
  • file : uploadez un PDF, DOCX, Markdown ou document texte. Flow en deux étapes : crée la metadata, puis upload le fichier vers une URL pré-signée.

Les endpoints ici couvrent create, read, update, replace, archive et batch sur les entrées knowledge, y compris leurs tags, périodes d'activité et traductions embarquées.

L'objet Knowledge

ChampTypeRequisDescription
external_idstringOui (à la création)Votre identifiant unique pour cette entrée. Free-form, doit être unique par company. Utilisé comme clé d'upsert.
humind_idstringRenvoyé seulement24 caractères hex ObjectId qu'Humind assigne. Stable pendant toute la vie de l'entrée.
type'snippet' | 'article' | 'webpage' | 'file'Oui (à la création)Discriminateur. Détermine lequel de content, content_html, url, ou original_filename + mime_type est requis. Voir les sections par type ci-dessous.
titlestringOuiTitre court utilisé pour l'affichage, la recherche et le contexte de grounding de l'assistant.
tagsstring[]NonNoms de tags. Le serveur les résout en ids et crée tout tag qui n'existe pas encore. Voir Tags.
is_available_for_ai_agentbooleanNonDéfaut true. Mettez false pour garder l'entrée dans votre librairie sans l'exposer à l'assistant.
status'draft' | 'published' | 'archived' | 'queued' | 'failed'NonDéfaut published à la création. queued/failed sont réservés aux fetches webpage : voir Le type webpage.
active_fromISO 8601NonDate la plus tôt à laquelle l'assistant peut utiliser cette entrée. Voir Période d'activité.
active_untilISO 8601NonDate la plus tard à laquelle l'assistant peut utiliser cette entrée.
default_languagestringNonCode ISO 639-1 de la langue des champs top-level.
translationsobject[]NonOverrides par locale. Voir Translations.
created_atISO 8601Renvoyé seulementTimestamp de création (UTC).
updated_atISO 8601Renvoyé seulementTimestamp de dernière modification (UTC).

Champs spécifiques par type

Le discriminateur type décide quels champs body sont requis.

TypeRequisOptionnelNotes
snippetcontent-Texte brut. Réponses courtes et focalisées.
articlecontent_htmlexcerpt, slugBody HTML. Sanitizé côté serveur, voir HTML content. excerpt et slug sont auto-dérivés s'ils sont omis.
webpageurlcontent_htmlSi content_html est omis, Humind fetch l'URL en async. Voir Le type webpage.
fileoriginal_filename, mime_type-Le fichier lui-même est uploadé hors-bande via une URL pré-signée. Voir Le type file.
ChampTypeDescription
contentstringBody texte brut pour type='snippet'.
content_htmlstringBody HTML pour type='article', ou snapshot de la page pour type='webpage'.
excerptstringOptionnel pour type='article'. Résumé court affiché dans la liste knowledge du dashboard. Max 500 caractères. Quand il est omis, l'API dérive un excerpt de 160 caractères depuis content_html ; les articles publiés en ont toujours un. Fournissez-le explicitement pour une accroche soignée.
slugstringOptionnel pour type='article'. Slug URL-safe, en minuscules, séparé par des tirets. Max 255 caractères. Dérivé du title quand il est omis (ASCII en minuscules, les non-alphanumériques remplacés par des tirets). Même politique d'auto-dérivation qu'excerpt.
urlstringURL HTTPS pour type='webpage'. Doit être joignable publiquement. Pour les clés live, l'API rejette http://, la syntaxe userinfo@host (https://example.com@attacker.com), localhost et tout *.localhost, l'host 0.0.0.0, les ranges IPv4 RFC 1918 / loopback / link-local / CGN, le loopback IPv6 (::1) et IPv6 ULA / link-local, ainsi que les suffixes internes Kubernetes (*.svc.cluster.local, *.cluster.local, *.internal) — tout renvoie 422 invalid_url. Les clés test (hmd_test_*) skip ces checks pour que les marchands puissent développer en local avec des tunnels ou http://localhost.
original_filenamestringNom d'affichage pour type='file'. L'API strip les composants de répertoire (/ et \), les caractères de contrôle, et les segments . / .. standalone avant le stockage — seul le basename est conservé. La longueur finale doit faire 1–255 caractères après sanitization.
mime_typestringMIME type pour type='file'. Whitelisté, voir Le type file.
file_sizeintegerRenvoyé seulement. Octets. null tant que l'upload est pending.
file_urlstringRenvoyé seulement. Chemin relatif opaque ; ne pas parser. null tant que l'upload est pending.
uploaded_atISO 8601Renvoyé seulement. Quand le fichier a fini de s'uploader. null jusqu'à ce moment-là.

Champs cachés

Le dashboard peut afficher des champs que l'API publique ne renvoie pas ; traitez-les comme internes. Vous pouvez ignorer en sécurité tout ce que vous voyez dans le dashboard qui n'est pas documenté ici.

HTML content

Le champ content_html : utilisé par les types article et webpage : accepte du HTML. Humind sanitize le HTML côté serveur avant de le stocker, avec une allowlist fixe :

  • Tags préservés : p, a, br, hr, em, strong, b, i, u, ul, ol, li, h1h6, blockquote, pre, code, table, thead, tbody, tr, th, td, img, span, div.
  • Tags strippés : script, iframe, style, object, embed, form, input, et tout autre tag non listé ci-dessus.
  • Attributs strippés : event handlers (onclick, onerror, …), style, et toute URL javascript:.
  • Attributs préservés : href sur <a> (uniquement https, http, mailto et URIs data: valides), src, alt, width, height sur <img>, plus un set limité de valeurs class.

Le HTML est sanitizé en entrée

Ne comptez pas sur l'API pour préserver votre HTML brut. Les tags comme <script> ou les attributs comme onclick sont strippés silencieusement, votre markup stocké peut être un sous-ensemble strict de ce que vous avez envoyé. Relisez l'entrée après une écriture si vous voulez voir ce qui a été retenu. La même règle s'applique aux snapshots webpage qu'Humind récupère pour vous.


Create or upsert

POST /knowledge crée une nouvelle entrée, ou met à jour une existante si l'external_id existe déjà pour votre company. Les champs body requis dépendent du type.

Scope requis : knowledge:write

type='snippet'

Request

bash
curl -X POST https://api.thehumind.com/public/v1/knowledge \
  -H "Authorization: Bearer hmd_live_..." \
  -H "Idempotency-Key: 3f1a8d92-7c4b-4e6f-b2a1-d5e9c8f7a3b4" \
  -H "Content-Type: application/json" \
  -d '{
    "external_id": "kb-shipping-faq",
    "type": "snippet",
    "title": "Shipping delays",
    "content": "Standard delivery takes 3-5 business days. Express delivery takes 1-2 business days. Free shipping on orders over 50 EUR.",
    "tags": ["shipping", "faq"],
    "is_available_for_ai_agent": true,
    "status": "published",
    "default_language": "en"
  }'

Response 201 Created ou 200 OK

json
{
  "external_id": "kb-shipping-faq",
  "humind_id": "65f1ab9c8e7d4a2b1c3d4e5f",
  "type": "snippet",
  "title": "Shipping delays",
  "content": "Standard delivery takes 3-5 business days. Express delivery takes 1-2 business days. Free shipping on orders over 50 EUR.",
  "tags": ["shipping", "faq"],
  "is_available_for_ai_agent": true,
  "status": "published",
  "default_language": "en",
  "created_at": "2026-04-25T14:30:00Z",
  "updated_at": "2026-04-25T14:30:00Z"
}

type='article'

Request

bash
curl -X POST https://api.thehumind.com/public/v1/knowledge \
  -H "Authorization: Bearer hmd_live_..." \
  -H "Idempotency-Key: 4a5b6c7d-8e9f-4a3b-2c1d-0e9f8a7b6c5d" \
  -H "Content-Type: application/json" \
  -d '{
    "external_id": "kb-sizing-guide-shoes",
    "type": "article",
    "title": "How to pick the right shoe size",
    "content_html": "<p>If you're between two sizes, we recommend going up.</p><p>Our shoes use European sizing. See the chart below to convert from US or UK.</p>",
    "tags": ["sizing", "shoes"],
    "default_language": "en"
  }'

Response 201 Created ou 200 OK

json
{
  "external_id": "kb-sizing-guide-shoes",
  "humind_id": "65f1cd9e8e7d4a2b1c3d4e60",
  "type": "article",
  "title": "How to pick the right shoe size",
  "content_html": "<p>If you're between two sizes, we recommend going up.</p><p>Our shoes use European sizing. See the chart below to convert from US or UK.</p>",
  "tags": ["sizing", "shoes"],
  "is_available_for_ai_agent": true,
  "status": "published",
  "default_language": "en",
  "created_at": "2026-04-25T14:30:00Z",
  "updated_at": "2026-04-25T14:30:00Z"
}

type='webpage'

Vous pouvez soit fournir url et content_html (publication immédiate), soit juste url et laisser Humind fetcher la page pour vous (async).

Request, URL seule, fetch async

bash
curl -X POST https://api.thehumind.com/public/v1/knowledge \
  -H "Authorization: Bearer hmd_live_..." \
  -H "Idempotency-Key: 7a8b9c0d-1e2f-4a3b-4c5d-6e7f8a9b0c1d" \
  -H "Content-Type: application/json" \
  -d '{
    "external_id": "kb-shipping-policy-page",
    "type": "webpage",
    "title": "Shipping policy",
    "url": "https://merchant.com/shipping-policy",
    "tags": ["shipping", "policy"],
    "default_language": "en"
  }'

Response 202 Accepted (fetch en file)

json
{
  "external_id": "kb-shipping-policy-page",
  "humind_id": "65f1ef0e8e7d4a2b1c3d4e61",
  "type": "webpage",
  "title": "Shipping policy",
  "url": "https://merchant.com/shipping-policy",
  "tags": ["shipping", "policy"],
  "is_available_for_ai_agent": true,
  "status": "queued",
  "default_language": "en",
  "created_at": "2026-04-25T14:30:00Z",
  "updated_at": "2026-04-25T14:30:00Z"
}

L'entrée existe immédiatement avec status: "queued". Humind fetch l'URL en arrière-plan et bascule status à published (ou failed) une fois le fetch terminé. Tant que ce n'est pas fait, l'entrée n'est pas utilisée par l'assistant. Voir Le type webpage pour le polling.

Request, URL avec content_html (publication immédiate)

bash
curl -X POST https://api.thehumind.com/public/v1/knowledge \
  -H "Authorization: Bearer hmd_live_..." \
  -H "Idempotency-Key: 8b9c0d1e-2f3a-4b4c-5d6e-7f8a9b0c1d2e" \
  -H "Content-Type: application/json" \
  -d '{
    "external_id": "kb-returns-policy-page",
    "type": "webpage",
    "title": "Returns policy",
    "url": "https://merchant.com/returns",
    "content_html": "<p>You can return any unworn item within 30 days of delivery.</p>",
    "tags": ["returns", "policy"],
    "default_language": "en"
  }'

Response 201 Created

Renvoyée avec status: "published" immédiatement, aucun fetch n'est exécuté puisque vous avez fourni le snapshot.

200 vs 201 vs 202

  • 201 Created : nouvelle entrée, prête à l'usage.
  • 200 OK : entrée existante mise à jour en place.
  • 202 Accepted : entrée webpage créée, fetch en file. Pollez l'entrée pour voir la transition de status.

The webpage type

Le type webpage est le chemin de moindre résistance pour du contenu que vous publiez déjà sur votre site. Vous donnez une URL à Humind ; on fetch la page, on enlève la chrome de navigation et on snapshot le body.

Cycle de vie

statusSignification
queuedHumind n'a pas encore fetché l'URL. L'entrée existe mais n'est pas utilisée par l'assistant.
publishedFetch réussi. content_html est peuplé et l'assistant ancre ses réponses dessus.
failedFetch échoué (404, bloqué par robots.txt, erreur serveur, timeout, etc.). L'entrée est conservée pour que vous voyiez l'échec ; l'assistant ne l'utilise pas.

Pour re-déclencher un fetch après un statut failed : corrigez le problème de votre côté, puis PATCH l'entrée avec la même url (ou une nouvelle). Le statut repasse à queued.

Polling

Pas de webhook pour la complétion de fetch. Pollez l'entrée par external_id ou humind_id :

bash
curl https://api.thehumind.com/public/v1/knowledge/api:kb-shipping-policy-page \
  -H "Authorization: Bearer hmd_live_..."

La plupart des pages publient dans la minute. Si status est toujours queued après quelques minutes, vérifiez que votre URL est publiquement joignable.

Snapshot statique vs fetch live

Le content_html que Humind stocke est un snapshot point-in-time. Il ne se rafraîchit pas automatiquement quand votre page change. Pour récupérer les éditions sur votre site, PATCH l'entrée, envoyer la même url (sans content_html) re-met en file un fetch frais.


List knowledge

GET /knowledge renvoie les entrées qui appartiennent à la company à laquelle la clé API est rattachée.

Scope requis : knowledge:read

Query parameterTypeDescription
cursorstringCursor opaque renvoyé comme next_cursor à la page précédente. Omettez-le au premier appel.
limitintegerItems par page (1100). Défaut 50.
type'snippet' | 'article' | 'webpage' | 'file'Filtre sur un seul type.

Request

bash
curl "https://api.thehumind.com/public/v1/knowledge?type=snippet&limit=50" \
  -H "Authorization: Bearer hmd_live_..."

Response 200 OK

json
{
  "data": [
    {
      "external_id": "kb-shipping-faq",
      "humind_id": "65f1ab9c8e7d4a2b1c3d4e5f",
      "type": "snippet",
      "title": "Shipping delays",
      "tags": ["shipping", "faq"],
      "status": "published",
      "is_available_for_ai_agent": true,
      "created_at": "2026-04-25T14:30:00Z",
      "updated_at": "2026-04-25T14:30:00Z"
    }
  ],
  "next_cursor": "eyJpZCI6IjY1ZjFjZDllOGU3ZDRhMmIxYzNkNGU2MCJ9"
}

Quand next_cursor vaut null ou est absent, vous êtes à la dernière page.


Retrieve a knowledge entry

GET /knowledge/{id} renvoie une seule entrée. Le {id} accepte l'une ou l'autre forme documentée dans Identifiants.

Scope requis : knowledge:read

Request

bash
curl https://api.thehumind.com/public/v1/knowledge/api:kb-shipping-faq \
  -H "Authorization: Bearer hmd_live_..."

Response 200 OK

Même forme que la réponse de création.


Replace a knowledge entry

PUT /knowledge/{id} fait un remplacement complet : le body de la requête devient l'entrée entière. Les champs que vous n'incluez pas sont reset à leurs défauts (ou unset là où c'est applicable).

Scope requis : knowledge:write

Request

bash
curl -X PUT https://api.thehumind.com/public/v1/knowledge/api:kb-shipping-faq \
  -H "Authorization: Bearer hmd_live_..." \
  -H "Idempotency-Key: 7a2b3c4d-5e6f-4a8b-9c0d-1e2f3a4b5c6d" \
  -H "Content-Type: application/json" \
  -d '{
    "external_id": "kb-shipping-faq",
    "type": "snippet",
    "title": "Shipping delays (updated)",
    "content": "Standard delivery now takes 2-4 business days. Express delivery is 1 business day. Free shipping on orders over 50 EUR.",
    "tags": ["shipping", "faq"],
    "default_language": "en"
  }'

Response 200 OK

Renvoie l'entrée complète, même forme que la réponse de création.

Replace est destructif

PUT enlève tout champ, tag ou traduction non présent dans le body. Pour bumper un seul champ, utilisez plutôt PATCH.


Update a knowledge entry

PATCH /knowledge/{id} fait un update partiel : seuls les champs présents dans le body sont modifiés. Le reste reste comme avant.

Scope requis : knowledge:write

Request, refresher le content d'un snippet

bash
curl -X PATCH https://api.thehumind.com/public/v1/knowledge/api:kb-shipping-faq \
  -H "Authorization: Bearer hmd_live_..." \
  -H "Idempotency-Key: 9b8a7c6d-5e4f-4a3b-2c1d-0e9f8a7b6c5d" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Standard delivery takes 2-4 business days. Express is 1 business day."
  }'

Request, re-fetcher une webpage

bash
curl -X PATCH https://api.thehumind.com/public/v1/knowledge/api:kb-shipping-policy-page \
  -H "Authorization: Bearer hmd_live_..." \
  -H "Idempotency-Key: ab3c4d5e-6f78-4a9b-8c0d-1e2f3a4b5c6d" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://merchant.com/shipping-policy"
  }'

PATCH-er une entrée webpage avec une url re-met en file un fetch et bascule status à queued.

Response 200 OK

Renvoie l'entrée complète mise à jour.

Les changements de type ne sont pas autorisés

Vous ne pouvez pas switcher un snippet en article (ou tout autre changement cross-type) en PATCH-ant type. Supprimez l'entrée et créez-en une nouvelle avec le bon type.


Archiver (ou supprimer) une entrée knowledge

DELETE /knowledge/{id} fait un soft delete par défaut : le status de l'entrée passe à archived et l'assistant arrête de l'utiliser. Le record reste en base, donc vous pouvez le restaurer plus tard en PATCH-ant le statut à published.

Passez ?force=true pour faire un hard delete : le document est supprimé physiquement de la base après la cascade d'archivage. Il n'y a pas d'un-delete ; à n'utiliser que quand l'entrée doit vraiment disparaître (ex. nettoyage d'une base de test, entrée créée par erreur).

Scope requis : knowledge:write

Query parameters

NomTypeRequisDescription
forcebooleanNontrue (ou 1) pour supprimer définitivement l'entrée. Défaut false (soft delete).

Request — soft delete (par défaut)

bash
curl -X DELETE https://api.thehumind.com/public/v1/knowledge/api:return-policy \
  -H "Authorization: Bearer hmd_live_..." \
  -H "Idempotency-Key: 1a2b3c4d-5e6f-4789-9abc-def012345678"

Request — hard delete

bash
curl -X DELETE 'https://api.thehumind.com/public/v1/knowledge/api:return-policy?force=true' \
  -H "Authorization: Bearer hmd_live_..." \
  -H "Idempotency-Key: 1a2b3c4d-5e6f-4789-9abc-def012345678"

Response 204 No Content

Pas de body.

Soft vs. hard delete

Le soft delete est recommandé pour les opérations marchandes normales : l'entrée disparaît immédiatement du retrieval chat, vous pouvez désarchiver en un PATCH, et les caches downstream (vector index, dashboards) se nettoient via la cascade d'archivage.

Le hard delete (?force=true) sert au nettoyage de la base de connaissances — typiquement une entrée de test qu'on veut totalement enlevée. Le soft delete déclenche d'abord la routine d'archivage ; ?force=true supprime ensuite définitivement la ressource. Les conversations chat passées qui référençaient cette entrée gardent leur snapshot, donc l'historique reste cohérent même quand la source disparaît.


Tags

tags est un array de noms free-form. Le serveur résout chaque nom en id de tag, créant le tag s'il n'existe pas déjà pour votre company :

json
{
  "tags": ["shipping", "faq", "europe"]
}

Vous ne pré-créez pas de tags via un endpoint séparé, la première fois que vous référencez un nom de tag, il est créé. L'assistant utilise les tags comme un signal de soft-grouping quand il récupère du knowledge pertinent pour une question.

Gardez les noms de tags stables

Renommer un tag équivaut à en créer un nouveau et à orpheliner l'ancien. Si vous changez régulièrement de taxonomie, taggez plutôt par concepts stables (shipping) que par concepts transitoires (q1-2026-promo).

Si un nom de tag échoue à la résolution (rare), l'API renvoie tag_resolution_failed avec le nom fautif dans details.tag.


Active period

Mettez active_from et/ou active_until pour scoper quand l'assistant peut faire remonter une entrée. Le record reste dans votre librairie toute l'année ; la fenêtre de date n'affecte que si l'assistant ancre sur elle.

Cas d'usageSetup recommandé
Promo saisonnière (FAQ Black Friday)active_from = "2026-11-25T00:00:00Z", active_until = "2026-12-02T23:59:59Z"
Lancement future-datéactive_from seul, laissez active_until non défini.
Politique en sunsetactive_until seul, l'assistant arrête de l'utiliser après le cutoff.

Hors fenêtre, l'entrée est traitée comme si is_available_for_ai_agent valait false. Le statut (published, archived, …) n'est pas changé.


Translations

translations est une liste d'overrides par locale, keyée par language :

json
{
  "default_language": "en",
  "title": "Shipping delays",
  "content": "Standard delivery takes 3-5 business days.",
  "translations": [
    {
      "language": "fr",
      "title": "Délais de livraison",
      "content": "La livraison standard prend 3-5 jours ouvrés."
    }
  ]
}

Champs par locale que vous pouvez override :

ChampTypeS'applique à
titlestringTous les types
contentstringsnippet
content_htmlstringarticle, webpage

Les locales non listées dans translations retombent sur la valeur top-level (en default_language).

Vous pouvez aussi patcher une locale à la fois sans renvoyer l'entrée complète via la sub-resource Translations dédiée.


Translations sub-resource

Pour les entrées knowledge qui existent déjà, vous pouvez patcher une seule locale sans renvoyer le payload complet. Utilisez le champ translations embarqué sur POST / PUT / PATCH pour le seed initial, puis pilotez les updates suivants via ces endpoints.

{lang} est un tag court BCP 47, en, fr, de, pt-BR, zh-CN, etc. La regex de validation est ^[a-z]{2}(-[A-Z]{2})?$. Une valeur invalide renvoie 422 avec code: invalid_lang_format.

La forme du body dépend du type de l'entrée. Le serveur valide contre le schéma correspondant ; envoyer content sur un article (ou content_html sur un snippet) renvoie 422.

Set or update a translation

PUT /knowledge/{id}/translations/{lang} upserte la traduction pour une seule locale. Les champs que vous omettez sont laissés intouchés sur un update ; à la première écriture, ils défaulent à unset.

Scope requis : knowledge:write

Body, type='snippet'

ChampTypeDescription
titlestringTitre d'affichage localisé.
contentstringBody texte brut localisé.

Body, type='article' ou type='webpage'

ChampTypeDescription
titlestringTitre d'affichage localisé.
content_htmlstringBody HTML localisé. Sanitizé, voir HTML content.

Tous les champs sont optionnels individuellement, mais le body doit contenir au moins un. Un body vide renvoie 400 validation_failed.

Request, snippet

bash
curl -X PUT https://api.thehumind.com/public/v1/knowledge/api:kb-shipping-faq/translations/fr \
  -H "Authorization: Bearer hmd_live_..." \
  -H "Idempotency-Key: 5f6a7b8c-9d0e-4f1a-2b3c-4d5e6f7a8b9c" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Délais de livraison",
    "content": "La livraison standard prend 3-5 jours ouvrés."
  }'

Request, article ou webpage

bash
curl -X PUT https://api.thehumind.com/public/v1/knowledge/api:kb-sizing-guide-shoes/translations/fr \
  -H "Authorization: Bearer hmd_live_..." \
  -H "Idempotency-Key: 6a7b8c9d-0e1f-4a2b-3c4d-5e6f7a8b9c0d" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Comment choisir la bonne pointure",
    "content_html": "<p>Si vous hésitez entre deux tailles, on recommande de prendre la plus grande.</p>"
  }'

Response 200 OK

Renvoie l'entrée knowledge complète, même forme que la réponse de création, pour que vous voyiez toutes les locales actuellement stockées, pas juste celle que vous avez écrite.

Remove a translation

DELETE /knowledge/{id}/translations/{lang} enlève la traduction pour une seule locale. Idempotent : supprimer une locale qui n'existe pas est un no-op, pas une erreur.

Scope requis : knowledge:write

Request

bash
curl -X DELETE https://api.thehumind.com/public/v1/knowledge/api:kb-shipping-faq/translations/fr \
  -H "Authorization: Bearer hmd_live_..." \
  -H "Idempotency-Key: 7b8c9d0e-1f2a-4b3c-4d5e-6f7a8b9c0d1e"

Response 204 No Content

Pas de body.


Le type file

type='file' permet de pousser un PDF, document Word, Markdown, texte brut ou fichier HTML comme entrée knowledge. Comme le payload ne tient pas dans un body JSON, le workflow est divisé en trois étapes :

1. POST /knowledge                              ──►  status='draft', file_url=null
   { type: 'file', original_filename, mime_type }

2. POST /knowledge/{id}/file-upload-url         ──►  { upload_url, expires_at }

3. PUT  $UPLOAD_URL  --data-binary @file.pdf    ──►  Azure Blob (no auth, just the SAS)

4. POST /knowledge/{id}/file-upload-completed   ──►  status='published',
                                                     file_size + uploaded_at populés

Le premier appel enregistre la metadata seulement, aucun fichier n'est stocké encore. L'URL SAS générée à l'étape 2 est write-only et expire après 1 heure. L'étape 3 est un PUT direct vers Azure Blob storage ; vous ne touchez pas l'API Humind. L'étape 4 vérifie que le blob est bien arrivé et passe status à published pour que l'agent IA puisse l'utiliser.

Étape 1, créer l'entrée

bash
curl -X POST https://api.thehumind.com/public/v1/knowledge \
  -H "Authorization: Bearer hmd_live_..." \
  -H "Idempotency-Key: 9c8b7a6d-5e4f-4a3b-2c1d-0e9f8a7b6c5d" \
  -H "Content-Type: application/json" \
  -d '{
    "external_id": "kb-sizing-chart-pdf",
    "type": "file",
    "title": "Charte de tailles détaillée (PDF)",
    "original_filename": "sizing-chart.pdf",
    "mime_type": "application/pdf",
    "tags": ["sizing"],
    "default_language": "fr"
  }'

La réponse revient avec status: "draft", file_url: null, file_size: null, uploaded_at: null. L'entrée n'est pas utilisée par l'assistant tant que l'étape 4 n'est pas complétée.

Étape 2, obtenir une URL d'upload

bash
curl -X POST https://api.thehumind.com/public/v1/knowledge/api:kb-sizing-chart-pdf/file-upload-url \
  -H "Authorization: Bearer hmd_live_..." \
  -H "Idempotency-Key: 0d9e8f7a-6b5c-4d3e-2f1a-9b8c7d6e5f4a"

Response 200 OK

json
{
  "upload_url": "https://<storage>.blob.core.windows.net/<container>/<opaque-path>/sizing-chart.pdf?sig=...&se=...",
  "expires_at": "2026-04-25T15:30:00Z",
  "blob_path": "<opaque-path>/sizing-chart.pdf"
}

Appeler cet endpoint sur une entrée knowledge qui n'est pas type='file' renvoie 422 wrong_type.

Étape 3, PUT le fichier

Uploadez les bytes directement vers upload_url. Pas de header Authorization : le SAS dans la query string est l'auth.

bash
curl -X PUT "$UPLOAD_URL" \
  -H "x-ms-blob-type: BlockBlob" \
  -H "Content-Type: application/pdf" \
  --data-binary @sizing-chart.pdf

Azure renvoie 201 Created en cas de succès. L'URL SAS n'a que les permissions Create + Write : elle ne peut pas read ou list autre chose.

Étape 4, finaliser

bash
curl -X POST https://api.thehumind.com/public/v1/knowledge/api:kb-sizing-chart-pdf/file-upload-completed \
  -H "Authorization: Bearer hmd_live_..." \
  -H "Idempotency-Key: 1e0f9a8b-7c6d-4e5f-2a1b-0c9d8e7f6a5b"

Response 200 OK

L'entrée mise à jour complète, avec status: "published", file_size populé et un uploaded_at frais. À partir de ce point, l'agent IA peut grounder ses réponses sur le document.

Si vous appelez cet endpoint avant que l'étape 3 n'ait fini (ou si l'upload a échoué silencieusement), vous obtenez :

json
{
  "error": {
    "code": "file_not_uploaded",
    "message": "No file has been uploaded to the SAS URL yet. PUT your file before calling this endpoint."
  }
}

Réessayez simplement une fois le PUT complété. L'endpoint est idempotent, l'appeler à nouveau après un upload réussi re-publie l'entrée avec un uploaded_at frais.

MIME types autorisés

mime_typeExtension
application/pdf.pdf
application/vnd.openxmlformats-officedocument.wordprocessingml.document.docx
application/msword.doc (legacy)
text/plain.txt
text/markdown.md
text/html.html
application/rtf.rtf

Tout autre type renvoie validation_failed à l'étape 1.

Limites

LimiteValeur
Longueur de original_filename255 caractères
Taille de fichierPas de hard cap. On recommande de garder les fichiers individuels sous 50 MB pour que l'agent IA puisse les fetch dans le budget de la requête.
TTL de l'URL d'upload1 heure. Mintez une nouvelle URL si elle expire.

OCR / extraction de texte

Les PDFs born-digital et les formats text-based marchent le mieux. Pour de l'OCR ou des PDFs scannés, contactez le support.


Batch upsert

POST /knowledge/batch accepte jusqu'à 500 entrées dans un seul appel et renvoie une réponse 207 Multi-Status avec une entrée par item. À utiliser pour le sync initial de votre base de connaissances ou n'importe quelle mise à jour bulk.

Scope requis : knowledge:write

ContrainteValeur
Max items par batch500
Max taille body5 MB
ComportementChaque item est traité indépendamment ; un échec ne bloque pas les autres.

Request

bash
curl -X POST https://api.thehumind.com/public/v1/knowledge/batch \
  -H "Authorization: Bearer hmd_live_..." \
  -H "Idempotency-Key: 4d3c2b1a-9f8e-4d7c-6b5a-4f3e2d1c0b9a" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      {
        "external_id": "kb-shipping-faq",
        "type": "snippet",
        "title": "Shipping delays",
        "content": "Standard delivery takes 3-5 business days.",
        "tags": ["shipping", "faq"],
        "default_language": "en"
      },
      {
        "external_id": "kb-returns-page",
        "type": "webpage",
        "title": "Returns policy",
        "url": "https://merchant.com/returns",
        "default_language": "en"
      },
      {
        "external_id": "kb-bad",
        "type": "snippet",
        "title": "Missing content"
      }
    ]
  }'

Response 207 Multi-Status

json
{
  "results": [
    {
      "external_id": "kb-shipping-faq",
      "status": "created",
      "humind_id": "65f1ab9c8e7d4a2b1c3d4e5f"
    },
    {
      "external_id": "kb-returns-page",
      "status": "created",
      "humind_id": "65f1cd9e8e7d4a2b1c3d4e60",
      "queued_for_fetch": true
    },
    {
      "external_id": "kb-bad",
      "status": "failed",
      "error": {
        "code": "validation_failed",
        "message": "Invalid knowledge payload.",
        "details": {
          "issues": [
            { "path": ["content"], "message": "Required", "code": "invalid_type" }
          ]
        }
      }
    }
  ]
}
ChampTypeDescription
results[i].external_idstringL'external_id de l'item d'entrée, écho pour matching.
results[i].statusstringUne valeur parmi created, updated, failed.
results[i].humind_idstringPrésent en cas de succès, l'id Humind 24-hex assigné.
results[i].queued_for_fetchbooleanOptionnel, uniquement sur les items webpage quand le fetch d'URL a été mis en file.
results[i].errorobjectPrésent en cas d'échec. Même forme qu'un objet d'erreur top-level.

Doublons d'external_id au sein d'un batch

Si le même external_id apparaît plusieurs fois dans items, la première occurrence est traitée et les doublons suivants reviennent avec status: "failed" et le code duplicate_external_id_in_batch. Dédupliquez côté client avant l'envoi.

Wrapper ou tableau bare

Le body peut être un tableau JSON comme montré ci-dessus, ou wrappé : { "items": [ ... ] }. L'API normalise les deux vers la même réponse results.

Idempotency sur les batches

L'Idempotency-Key s'applique au batch entier. Un retry du même batch avec la même clé rejoue toute la réponse 207 : aucun item n'est traité deux fois. Générez un nouveau UUID pour un autre batch.


Erreurs courantes

Les endpoints knowledge peuvent renvoyer n'importe lequel des statuts HTTP standards, mais voici ceux que vous verrez le plus souvent :

StatutCodeQuandFix
401missing_credentials, invalid_key_format, invalid_key, revokedLe header d'auth manque, est malformé, ou la clé n'est plus active.Voir Authentication.
403insufficient_scopeLa clé n'a pas knowledge:read (pour GET) ou knowledge:write (pour POST/PUT/PATCH/DELETE).Créez une nouvelle clé avec le bon scope.
404not_foundLe {id} ne correspond pas à une entrée qui appartient à votre company.Vérifiez l'external_id ou le humind_id. Les lookups cross-tenant renvoient aussi 404.
409idempotency_conflictMême Idempotency-Key réutilisée avec un body différent.Générez un UUID frais.
400validation_failedLe body a échoué le schéma Knowledge : le plus souvent un champ type-spécifique manquant (content pour snippet, content_html pour article, url pour webpage, original_filename/mime_type pour file).Corrigez le champ et renvoyez.
422wrong_type/file-upload-url ou /file-upload-completed appelé sur une entrée knowledge qui n'est pas type='file'.Utilisez une entrée file, ou enlevez l'appel.
422file_not_uploaded/file-upload-completed appelé avant d'avoir PUT les bytes vers upload_url.Complétez l'étape 3 (le PUT) en premier, puis retentez l'étape 4.
422tag_resolution_failedUn nom de tag dans tags n'a pas pu être résolu ou créé. Rare.Retentez ; si ça persiste, partagez le request_id avec le support.
422invalid_lang_formatLe segment {lang} d'une URL de sub-resource translations ne match pas ^[a-z]{2}(-[A-Z]{2})?$.Utilisez un tag court BCP 47 comme en, fr, pt-BR.
200/202 (l'entrée affiche status='failed')webpage_fetch_failedHumind a tenté de fetcher l'URL d'une webpage et la page a renvoyé une erreur, a été bloquée par robots.txt, a timeout, ou n'a pas renvoyé du HTML.Vérifiez que l'URL est joignable, puis PATCH l'entrée avec la même url (ou une corrigée) pour re-mettre en file.

Pour aller plus loin

  • Authentication : générer une clé knowledge:write.
  • Conventions : identifiants, idempotency, dates.
  • Products : pousser votre catalogue pour que l'assistant puisse recommander.
  • Collections : grouper les produits pour des recommandations plus fines.

Released under the proprietary Humind license.