Ingestion API

Ingest content directly into your search index without crawling. Ideal for CMS integrations, dynamic content, or bulk imports.

Ingest Pages

POST /api/sites/{siteId}/pages
Authorization: Bearer qs_your_api_key
Content-Type: application/json

{
  "pages": [
    {
      "url": "https://example.com/docs/getting-started",
      "title": "Getting Started Guide",
      "content": "Welcome to our platform! This guide will help you get up and running...",
      "metadata": { "section": "docs" }
    }
  ]
}

Page Fields

FieldTypeRequiredDescription
urlstringYesUnique URL identifier for the page
contentstringYesFull page content (plain text or HTML)
titlestringNoPage title (auto-extracted if HTML)
summarystringNoBrief description for search results
tagsstring[]NoKeywords for search relevance

Response

{
  "success": true,
  "processed": 1,
  "skipped": 0,
  "failed": 0,
  "results": [
    {
      "url": "https://example.com/docs/getting-started",
      "status": "success",
      "chunks": 1,
      "isNew": true,
      "processingTimeMs": 3514
    }
  ]
}

Content Processing

When you ingest content:

  1. HTML is cleaned - Navigation, headers, footers are removed
  2. Metadata is extracted - Title, summary, tags (if not provided)
  3. Content is chunked - Split into searchable segments
  4. Embeddings are generated - For semantic search

Pre-processed Content

If you've already cleaned your content, you can skip AI processing by providing all metadata fields (title, summary, tags):

  • HTML content → Always processed (to remove boilerplate)
  • Plain text + all metadata → Indexed directly (faster, cheaper)
  • Plain text, missing metadata → AI extracts missing fields

Batch Ingestion

Ingest up to 100 pages per request:

{
  "pages": [
    { "url": "https://example.com/page1", "title": "Page 1", "content": "..." },
    { "url": "https://example.com/page2", "title": "Page 2", "content": "..." },
    { "url": "https://example.com/page3", "title": "Page 3", "content": "..." }
  ]
}

For large imports, batch your requests and implement retry logic for any errors.

Updating Content

To update a page, simply ingest it again with the same URL. The new content replaces the old.

Delete Content

Pass urls to remove specific pages. It takes an array, so one request can remove many pages — there is no need to call it per URL.

DELETE /api/sites/{siteId}/pages
Authorization: Bearer qs_your_api_key
Content-Type: application/json

{
  "urls": ["https://example.com/docs/getting-started"]
}

Removes each page and all of its chunks from the index. URLs must match exactly, including the scheme and host, as they were ingested or crawled.

Delete by Pattern

Pass patterns instead to remove a whole section without listing every URL:

DELETE /api/sites/{siteId}/pages
Authorization: Bearer qs_your_api_key
Content-Type: application/json

{
  "patterns": ["/blog/archive/*"]
}

At least one of urls, patterns or keys is required; you may combine them in a single request.

Response

{
  "message": "Pages deleted successfully",
  "siteId": "4226a896-f2d3-40d3-aa80-5bc627d4c83b",
  "requestedUrls": 1,
  "deletedChunks": 1,
  "deletedPages": 1
}

deletedPages is what was actually removed, which can be lower thanrequestedUrls. Deleting a URL that is not in the index is not an error — it succeeds and removes nothing — so check deletedPagesrather than the status code if you need to know whether anything changed.

Ingested pages are not removed automatically

Stale-content reconciliation — which removes indexed pages once they disappear from your site — only covers pages the crawler found. A page pushed in through this API stays indexed until you delete it, even if the source page is later removed. If your CMS deletes content, call the delete endpoint as part of that workflow.

List Indexed Pages

To see what is currently in the index, for example to verify a delete:

GET /api/sites/{siteId}/index-pages?limit=50
Authorization: Bearer qs_your_api_key

Purge the Whole Index

POST /api/sites/{siteId}/purge empties the index for a site. This cannot be undone; the content must be re-crawled or re-ingested.

Use Cases

CMS Integration

Trigger ingestion when content is published:

  1. Listen for publish/update webhooks from your CMS
  2. Fetch the page content
  3. POST to the ingestion API

Bulk Import

Import existing content:

  1. Export content from your source system
  2. Transform into the required format
  3. Batch ingest in chunks of 100
  4. Monitor for errors and retry failures

Dynamic Content

For content that changes frequently:

  • Ingest on a schedule (e.g., hourly)
  • Or trigger on content changes
  • Consider using tags to track content freshness

Limits

LimitValue
Pages per request100
Content size per page1 MB
Requests per minute60