Skip to main content

Sync Webhook

The sync webhook lets external systems push file changes to a knowledge base. Instead of manually uploading files through the admin portal, your CI/CD pipeline, document management system, or storage service can add, replace, and remove files automatically.

How It Works

This is a push-based design — the external system decides when and what to sync. Diosc does not poll or pull from storage systems.

Authentication

The sync endpoint uses the same authentication as all admin API endpoints. For programmatic access, create an API key:

  1. Go to API Keys in the admin portal
  2. Click Create API Key
  3. Select the sync:knowledge scope
  4. Copy the generated key (it's only shown once)

Use the key in the X-API-Key header:

curl -X POST "http://localhost:3000/api/admin/knowledge/{id}/sync" \
-H "X-API-Key: diosc_ak_your_key_here" \
-F "action=add" \
-F "filename=handbook.pdf" \
-F "[email protected]"

Endpoint

POST /api/admin/knowledge/:id/sync
Content-Type: multipart/form-data

Form Fields

FieldTypeRequiredDescription
actionstringYesadd, replace, or remove
filenamestringYesCanonical filename (max 512 chars)
filebinaryFor add/replaceFile content to upload

The filename field is the stable identifier for the file within this knowledge base. It determines the stored filename, not the multipart upload header. This means you can upload a file from any local path and control its canonical name.

Responses

StatusMeaning
200Action performed — response body contains result
204No content — remove on a file that doesn't exist (noop)
400Bad request — missing or invalid action, filename, or file
401Unauthorized — missing or invalid authentication
404Not found — knowledge base does not exist

Response Body (200)

{
"action": "added",
"file": {
"id": "file-uuid",
"originalFilename": "handbook.pdf",
"mimeType": "application/pdf",
"sizeBytes": 524288,
"status": "PROCESSING",
"isIndexed": false,
"strategy": null,
"createdAt": "2026-02-10T12:00:00Z"
},
"message": "File 'handbook.pdf' added"
}

The file field is present for added and replaced actions. It is absent for removed.

Idempotent Behavior

The sync endpoint is fully idempotent — you can safely retry any operation without side effects.

ActionFile Exists?ResultDescription
addNoaddedFile is uploaded and indexed
addYesreplacedOld file is deleted, new file uploaded
replaceNoaddedFile is uploaded and indexed
replaceYesreplacedOld file is deleted, new file uploaded
removeYesremovedFile and its indexed chunks are deleted
removeNonoop204 No Content — nothing to do

This means:

  • You don't need to check whether a file exists before syncing
  • Retrying a failed request is always safe
  • add and replace behave identically — use whichever reads better in your integration

Examples

Add a File

curl -X POST "http://localhost:3000/api/admin/knowledge/{id}/sync" \
-H "X-API-Key: diosc_ak_..." \
-F "action=add" \
-F "filename=employee-handbook.pdf" \
-F "file=@/docs/employee-handbook.pdf"

Replace a File

Upload a new version of the same file. The old version is automatically deleted.

curl -X POST "http://localhost:3000/api/admin/knowledge/{id}/sync" \
-H "X-API-Key: diosc_ak_..." \
-F "action=replace" \
-F "filename=employee-handbook.pdf" \
-F "file=@/docs/employee-handbook-v2.pdf"

Remove a File

curl -X POST "http://localhost:3000/api/admin/knowledge/{id}/sync" \
-H "X-API-Key: diosc_ak_..." \
-F "action=remove" \
-F "filename=employee-handbook.pdf"

Sync from an S3 Event

Example: An AWS Lambda triggered by S3 events syncs files to a knowledge base.

const axios = require('axios');
const fs = require('fs');
const FormData = require('form-data');

exports.handler = async (event) => {
const bucket = event.Records[0].s3.bucket.name;
const key = event.Records[0].s3.object.key;
const eventName = event.Records[0].eventName;

const knowledgeId = process.env.KNOWLEDGE_BASE_ID;
const apiKey = process.env.DIOSC_API_KEY;

if (eventName.startsWith('ObjectRemoved')) {
// File deleted from S3 — remove from knowledge base
const form = new FormData();
form.append('action', 'remove');
form.append('filename', key);

await axios.post(
`${process.env.DIOSC_URL}/api/admin/knowledge/${knowledgeId}/sync`,
form,
{ headers: { 'X-API-Key': apiKey, ...form.getHeaders() } }
);
} else {
// File added/modified in S3 — sync to knowledge base
const s3Object = await s3.getObject({ Bucket: bucket, Key: key }).promise();

const form = new FormData();
form.append('action', 'replace');
form.append('filename', key);
form.append('file', s3Object.Body, { filename: key });

await axios.post(
`${process.env.DIOSC_URL}/api/admin/knowledge/${knowledgeId}/sync`,
form,
{ headers: { 'X-API-Key': apiKey, ...form.getHeaders() } }
);
}
};

Troubleshooting

IssueCauseSolution
400 "File attachment is required"file field missing for add/replaceInclude the file in the multipart form
400 "action is required"Missing or invalid action fieldSet action to add, replace, or remove
404 "Knowledge not found"Invalid knowledge base IDVerify the knowledge base exists in the admin portal
401 "Unauthorized"Missing or invalid API keyCheck X-API-Key header value
File not searchable after syncFile still processingWait for status to change from PROCESSING to READY

Next Steps