IngestItem — the universal content model
IngestItem is the canonical unit of content in bAInquet. Every connector — WordPress, Shopify, Ghost, Django, a hand-rolled REST connector — produces IngestItem objects and pushes them via the ingestion API. bAInquet normalises, deduplicates, and assembles these items into the knowledge graph.
The model is designed to represent any content type from any website: a blog post, a product page, a service listing, a portfolio entry, an event, a restaurant menu item, a help-centre article — anything. It is simultaneously compact (only type, id, url, checksum are required) and extensible (the json payload carries an open bag of structured sub-schemas).
Contract version: 0.4.0 — the ingestion server validates every item against this schema.
Top-level fields
| Field | Required | Type | Notes |
|---|---|---|---|
type | ✅ | SourceType | Content category |
id | ✅ | string | Stable connector-scoped id, e.g. post:412 |
url | ✅ | string (URI) | Canonical public URL; host must match X-Site-Domain |
checksum | ✅ | string | sha256:<hex> computed by the SDK; dedup key |
canonical_url | string (URI) | Alternate canonical if different from url | |
title | string (≤1024) | Human-readable heading | |
excerpt | string (≤4096) | Short summary; connectors populate this from the CMS excerpt / short description | |
html | string | Full body HTML | |
text | string | Plain-text version (derived from html when absent) | |
json | JsonPayload | Structured sub-schemas: SEO, images, price, author, etc. | |
language | string (BCP-47) | e.g. en, fr-FR | |
updated_at | string (RFC3339) | Last-modified timestamp in UTC | |
attributes | Record<string, unknown> | Arbitrary per-connector metadata bag |
At least one of html, text, or json must be present.
SourceType
The type field classifies the content:
| Value | Use for |
|---|---|
page | Generic web pages, CMS pages |
post | Blog posts, articles, news items |
product | E-commerce products |
category | Taxonomy terms, collections used as categories |
collection | CMS collections, product collections |
faq | FAQ entries |
review | Customer / editorial reviews |
event | Time-bounded events |
location | Physical locations |
profile | Author, team member, business profiles |
doc | Technical documentation, help articles |
media | Standalone media items (video, audio, image pages) |
service | Service offerings (booking services, SaaS features) |
custom | Any type that doesn't fit the above; use attributes.subtype to sub-classify |
JsonPayload
json is an open object — connectors may add any keys. bAInquet recognises a set of canonical sub-schemas that all normalisation pipelines understand. When connectors populate these canonical keys, the knowledge graph extracts richer structured data with higher confidence.
json.images[] — ImageObject
{
"images": [
{
"src": "https://example.com/img/hero.jpg",
"alt": "A product photo",
"caption": "Available in three colours",
"width": 1200,
"height": 800,
"mime": "image/jpeg"
}
]
}| Field | Required | Notes |
|---|---|---|
src | ✅ | Absolute image URL |
alt | Alt text | |
caption | Caption / title | |
width | Pixel width | |
height | Pixel height | |
mime | MIME type, e.g. image/jpeg |
json.seo{} — SeoObject
{
"seo": {
"title": "Buy Widgets | Acme Shop",
"description": "Best widgets on the internet.",
"canonical_url": "https://acme.com/widgets",
"focus_keyword": "widgets",
"keywords": "widget, buy widget, cheap widget",
"robots": "index, follow",
"og_title": "Acme Widgets",
"og_description": "Best widgets on the internet.",
"og_image": "https://acme.com/img/og.jpg",
"og_type": "product",
"twitter_title": "Acme Widgets",
"twitter_description": "Best widgets on the internet.",
"twitter_image": "https://acme.com/img/twitter.jpg",
"twitter_card": "summary_large_image",
"schema_markup": "{\"@context\":\"https://schema.org\",...}",
"provenance_method": "seo_meta"
}
}All fields are optional. provenance_method must always be "seo_meta" when present.
Populated by: WordPress (Yoast + RankMath), Shopify, Ghost, Drupal (metatag module), Magento, Joomla, Webflow, Wix, and all framework connectors.
json.author{} — AuthorObject
{
"author": {
"id": "wp:42",
"name": "Jane Smith",
"url": "https://example.com/author/jane",
"avatar": "https://gravatar.com/avatar/abc",
"provenance_method": "cms_field"
}
}json.authors[]
Array of AuthorObject for multi-author content (e.g. Ghost posts with multiple authors).
json.tags[]
Array of tag name strings:
{ "tags": ["javascript", "performance", "tutorial"] }json.categories[]
Array of category name strings (or IDs when names unavailable):
{ "categories": ["Tech", "Tutorials"] }json.excerpt
Plain-text excerpt string (mirrors the top-level excerpt field; useful for JSON-only consumers):
{ "excerpt": "A short summary of the article content..." }json.price{} — TypedPrice
{
"price": {
"value": 49.99,
"unit": "currency",
"currency": "EUR"
}
}unit is always the literal "currency". Never use concatenated price strings.
Connector-namespaced extensions
Connectors add their own namespaced sub-objects alongside canonical keys:
{
"json": {
"images": [...],
"seo": {...},
"wp": { "post_type": "product", "post_status": "publish" },
"acf": { "hero_cta_text": "Shop now" },
"product": { "sku": "WGT-001", "price": { "value": 49.99, "unit": "currency", "currency": "USD" } }
}
}Canonical keys (images, seo, author, authors, tags, categories, excerpt, price) are always at the top level of json. Connector-specific data goes in a namespace key (wp, shopify, ghost, wix, acf, custom, etc.).
Provenance ladder
When multiple extractors produce the same fact, confidence is determined by the provenance method:
| Method | Confidence | Source |
|---|---|---|
cms_field | 0.98 | Directly from a CMS field (highest trust) |
schema_org | 0.95 | JSON-LD / structured data in HTML |
seo_meta | 0.85 | SEO plugin meta fields |
text_extraction | 0.75 | Derived from body text (lowest trust) |
Full example
A WordPress product post with ACF, Yoast SEO, and WooCommerce data:
{
"type": "product",
"id": "product:1042",
"url": "https://acme.com/products/blue-widget",
"canonical_url": "https://acme.com/products/blue-widget",
"title": "Blue Widget Pro",
"excerpt": "The professional-grade widget for serious makers.",
"html": "<p>The professional-grade widget...</p>",
"text": "The professional-grade widget for serious makers.",
"language": "en",
"updated_at": "2026-06-20T14:30:00Z",
"checksum": "sha256:a3b2c1d4...",
"json": {
"images": [
{ "src": "https://acme.com/img/blue-widget.jpg", "alt": "Blue Widget Pro", "width": 800, "height": 800 }
],
"seo": {
"title": "Buy Blue Widget Pro | Acme Shop",
"description": "The best blue widget for professionals.",
"focus_keyword": "blue widget pro",
"og_image": "https://acme.com/img/og-blue-widget.jpg",
"provenance_method": "seo_meta"
},
"author": { "id": "wp:3", "name": "Admin", "provenance_method": "cms_field" },
"tags": ["widgets", "professional"],
"categories": ["Hardware", "Pro Tools"],
"price": { "value": 49.99, "unit": "currency", "currency": "USD" },
"product": {
"sku": "BW-PRO-001",
"in_stock": true,
"stock_quantity": 42,
"variations": [
{ "id": "variant:2001", "sku": "BW-PRO-S", "attributes": { "size": "Small" }, "price": { "value": 39.99, "unit": "currency", "currency": "USD" } }
]
},
"acf": {
"hero_cta_text": "Order now",
"warranty_years": "2"
},
"wp": {
"post_id": 1042,
"post_type": "product",
"post_status": "publish"
}
}
}Related
- Ingestion and signing — how to push items to the API
- Connector SDK —
makeItem()and signing helpers - WordPress connector — full field reference for WP/WooCommerce
- Shopify connector — metafields and SEO