curl --request POST \
--url https://api.tryfuse.ai/api/v1/business/knowledge-hubs \
--header 'Authorization: Basic <encoded-value>' \
--header 'Content-Type: application/json' \
--data '
{
"websites": [
{
"url": "<string>",
"includeSubPages": false,
"isCompetitor": false
}
]
}
'import requests
url = "https://api.tryfuse.ai/api/v1/business/knowledge-hubs"
payload = { "websites": [
{
"url": "<string>",
"includeSubPages": False,
"isCompetitor": False
}
] }
headers = {
"Authorization": "Basic <encoded-value>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Basic <encoded-value>', 'Content-Type': 'application/json'},
body: JSON.stringify({websites: [{url: '<string>', includeSubPages: false, isCompetitor: false}]})
};
fetch('https://api.tryfuse.ai/api/v1/business/knowledge-hubs', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"knowledgeHub": {
"id": "68a1f8509c41d20014b3ee41",
"name": "Brightpay KB",
"companyName": null,
"status": "processing",
"isDefault": false,
"websites": [
{
"url": "https://brightpay.com",
"includeSubPages": true,
"isCompetitor": false,
"parentUrl": null,
"lastCrawledAt": null
}
],
"notes": [
{
"id": "68a1f8509c41d20014b3ee55",
"text": "We sell payroll software to UK accountants.",
"filename": "positioning.md",
"isCompetitor": false,
"hasAttachment": false
}
],
"createdAt": "2026-08-20T09:15:00.000Z",
"updatedAt": "2026-08-20T09:15:00.000Z"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"param": "<string>",
"doc_url": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"param": "<string>",
"doc_url": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"param": "<string>",
"doc_url": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"param": "<string>",
"doc_url": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"param": "<string>",
"doc_url": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"param": "<string>",
"doc_url": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"param": "<string>",
"doc_url": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"param": "<string>",
"doc_url": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"param": "<string>",
"doc_url": "<string>",
"request_id": "<string>"
}
}Create a knowledge hub from websites
Creates the hub immediately with status processing and enqueues the build: every website is crawled (subpages too where includeSubPages is true), the content is synthesized into knowledge pages, and a company name — and, when name was omitted, the hub name — are generated. Poll GET /business/knowledge-hubs/{hubId} until status is complete; draft means the build did not finish — it exhausted its retries (hubs saved as drafts in the web app carry the same status without ever having been built). Until the build finishes a hub created without a name carries the placeholder “Processing…”, and websites lists only what you sent — the crawler’s subpages appear later. Building does not debit credits. Inline file attachments are not accepted here: add them per note via POST /business/knowledge-hubs/{hubId}/attachments once the hub is complete. isDefault: true makes this the default hub and clears the flag on the previous one.
Errors:
422VALIDATION_FAILED— The body failed validation locally, or a website URL the crawler cannot parse was rejected by the builder.500UNEXPECTED_ERROR— The build workflow could not be enqueued (upstream STATE_MACHINE_ERROR); no hub was created — retry.429RATE_LIMITED— More than 30 knowledge-hub/campaign requests in a minute (or 1000 in a day). Knowledge hubs share the campaigns bucket.
Requires one of the following token scopes: campaigns.
curl --request POST \
--url https://api.tryfuse.ai/api/v1/business/knowledge-hubs \
--header 'Authorization: Basic <encoded-value>' \
--header 'Content-Type: application/json' \
--data '
{
"websites": [
{
"url": "<string>",
"includeSubPages": false,
"isCompetitor": false
}
]
}
'import requests
url = "https://api.tryfuse.ai/api/v1/business/knowledge-hubs"
payload = { "websites": [
{
"url": "<string>",
"includeSubPages": False,
"isCompetitor": False
}
] }
headers = {
"Authorization": "Basic <encoded-value>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Basic <encoded-value>', 'Content-Type': 'application/json'},
body: JSON.stringify({websites: [{url: '<string>', includeSubPages: false, isCompetitor: false}]})
};
fetch('https://api.tryfuse.ai/api/v1/business/knowledge-hubs', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"knowledgeHub": {
"id": "68a1f8509c41d20014b3ee41",
"name": "Brightpay KB",
"companyName": null,
"status": "processing",
"isDefault": false,
"websites": [
{
"url": "https://brightpay.com",
"includeSubPages": true,
"isCompetitor": false,
"parentUrl": null,
"lastCrawledAt": null
}
],
"notes": [
{
"id": "68a1f8509c41d20014b3ee55",
"text": "We sell payroll software to UK accountants.",
"filename": "positioning.md",
"isCompetitor": false,
"hasAttachment": false
}
],
"createdAt": "2026-08-20T09:15:00.000Z",
"updatedAt": "2026-08-20T09:15:00.000Z"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"param": "<string>",
"doc_url": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"param": "<string>",
"doc_url": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"param": "<string>",
"doc_url": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"param": "<string>",
"doc_url": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"param": "<string>",
"doc_url": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"param": "<string>",
"doc_url": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"param": "<string>",
"doc_url": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"param": "<string>",
"doc_url": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"param": "<string>",
"doc_url": "<string>",
"request_id": "<string>"
}
}Authorizations
Your API token (af_…) as the Basic-auth username, with an empty password.
Body
Websites the hub is built from: at least 1, at most 20. Accepted values for each entry's url: any http(s) web address, with or without the scheme (brightpay.com, https://brightpay.com/pricing). Every entry is crawled and all of the collected text is pooled into ONE set of knowledge pages — entries are not kept apart, and a page reached from two entries is used once. The crawl runs in the background after the 202, so a site that cannot be fetched is never reported as an error: its entry stays on the hub with lastCrawledAt null and contributes nothing. Read the hub back to check.
1 - 20 elementsShow child attributes
Show child attributes
Hub name (1-100 characters); omit to have one generated from the crawled content once the build finishes.
1 - 100Free-text notes to include as sources (up to 50). Inline file uploads are not accepted here.
50Show child attributes
Show child attributes
Make this hub the default one used when a campaign does not name a hub; the previous default is unset. Default false.
Response
Success
Show child attributes
Show child attributes