Integrations
Data Ingestion Guide
Worked examples for pushing content into Reaktly from TypeScript, Python, and cURL.
This guide gets data into a knowledge base. For the exact field list and every endpoint, see the Ingestion API reference.
What you need
| Value | Where to find it |
|---|---|
API key with iq:import | Dashboard → Settings → API keys (Authentication) |
integrationId | Dashboard → the integration (connector) the data belongs to |
knowledgeBaseId | Dashboard → Knowledge base. Optional — omit to use the tenant's default |
The flow
- Extract — read items from your source system
- Transform — map to the ingestion shape:
sourceType,externalId,data.title,data.content - Load —
POST /ingestfor one item,POST /ingest/bulkfor batches - Clean up — after a full sync,
POST /ingest/cleanupremoves items deleted at the source
First request (cURL)
curl -X POST https://api.reaktly.com/ingest \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{
"integrationId": "your-integration-id",
"knowledgeBaseId": "your-kb-id",
"sourceType": "ARTICLE",
"externalId": "my-first-article",
"data": {
"title": "Getting Started Guide",
"content": "The text the AI will answer from…",
"url": "https://your-site.com/getting-started"
}
}'A 200 with { "status": "queued", "jobId": "…" } means the item is accepted. Processing (chunking, embedding, indexing) happens in the background — allow a short delay before the assistant can answer from it.
TypeScript
const response = await fetch('https://api.reaktly.com/ingest', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': process.env.REAKTLY_API_KEY!,
},
body: JSON.stringify({
integrationId: process.env.REAKTLY_INTEGRATION_ID,
sourceType: 'ARTICLE',
externalId: `post-${post.id}`,
data: {
title: post.title,
content: post.body,
url: `https://your-site.com/blog/${post.slug}`,
hash: contentHash(post),
},
options: { priority: 'high' },
}),
});
if (!response.ok) throw new Error(`Ingestion failed: ${response.status}`);
const result = await response.json();
console.log('Queued as', result.jobId);Python
import os
import requests
response = requests.post(
"https://api.reaktly.com/ingest",
json={
"integrationId": os.environ["REAKTLY_INTEGRATION_ID"],
"sourceType": "ARTICLE",
"externalId": f"post-{post_id}",
"data": {
"title": title,
"content": body,
"url": url,
},
},
headers={"x-api-key": os.environ["REAKTLY_API_KEY"]},
timeout=30,
)
response.raise_for_status()
print(response.json()["jobId"])Batching an initial load
Send 50–100 items per request with /ingest/bulk. Keep externalIds stable across syncs — they are the deduplication key, and re-sending the same item updates it rather than creating a duplicate.
const chunk = items.slice(0, 100).map(toIngestionItem);
await fetch('https://api.reaktly.com/ingest/bulk', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': process.env.REAKTLY_API_KEY!,
},
body: JSON.stringify({ items: chunk }),
});Keeping in sync
| Goal | Approach |
|---|---|
| Skip unchanged content | Send data.hash; unchanged items are skipped (Change detection) |
| Update prices or URLs only | options.metadataOnly: true updates metadata without re-embedding |
| Remove deleted items | POST /ingest/cleanup with the full list of surviving externalIds |
| Prioritise user-triggered imports | options.priority: "high" |
Next steps
- Ingestion API reference — endpoints, fields, responses
- Integration patterns — webhook vs. scheduled syncs
- Error handling — retries and backoff
- Build a custom connector — a full walkthrough