Knowledge

Knowledge sync

Load the products and files a persona answers from, over REST. Authenticate every request with that persona's API key (the X-Api-Key header).

PUThttps://api.personaizer.com/v1/knowledge/docs
Per callup to 100 products
Processingautomatic

Products

Create or update products, matched by id.

Body — each product

Requirements & limits

Per-field requirements

attributes — supported types

The object≤100 keys · each key name ≤100 chars
string≤500 chars
number|n| ≤ 1e15 (1×1015)
booleantrue or false (JSON literal, never "true"/"yes" strings)
string[]≤50 items · each item ≤100 chars
dateISO-8601 string, e.g. "2026-03-01" (JSON has no date literal)

Reserved keys

attributes holds your own custom fields. These eight names are already first-class product fields, so they can't be reused as attribute keys — a custom field would shadow the real one, so the request is rejected. Put the value on the top-level field instead (e.g. price, not attributes.price).

priceoriginal_pricein_stockcurrencyimageslinkstitledescription
PUThttps://api.personaizer.com/v1/knowledge/docs
Try it
{
  "items": [
    {
      "id": "sku-002",
      "source": "my-shop.ge",
      "category": "footwear",
      "title": "Red trail runners",
      "description": "Lightweight trail shoe with a grippy outsole.",
      "attributes": {
        "brand": "acme",
        "weight_kg": 0.5,
        "waterproof": true,
        "sizes": [
          "8",
          "9",
          "10"
        ],
        "released_at": "2026-03-01"
      },
      "images": [
        {
          "url": "https://cdn.example.com/red-runners.jpg",
          "description": "Red trail runners",
          "is_primary": true
        }
      ],
      "links": [
        {
          "url": "https://my-shop.ge/p/sku-002",
          "is_primary": true
        }
      ],
      "price": 109.99,
      "original_price": 129.99,
      "currency": "USD",
      "in_stock": true
    },
    {
      "source": "my-shop.ge",
      "category": "footwear",
      "title": "Blue running shoes"
    }
  ]
}
Response
{ "created": 2, "updated": 0, "no_op": 0 }

Validation

All-or-nothing: if any product is invalid, nothing is written and the call returns 422 (see the response tab) with one entry per problem.

Each errors[] entry

Request-level failures use their own status (the console's response tabs): 401 (missing or invalid key), 403 (Persona ID used — needs the API key), 402 (over quota), or 429 (rate limited).

POSThttps://api.personaizer.com/v1/knowledge/docs/upload
Bodymultipart/form-data

File

Upload non-product knowledge — FAQs, Q&A, manuals, policies, troubleshooting, company info, glossaries. Structured products go through the PUT above.

Validate large files first with POST /v1/knowledge/docs/upload/preflight (name, size, page count) before transferring bytes. The response includes the document's id — poll GET /v1/knowledge/docs/{id} until status.state is ready. File docs come back with kind: "file" and original_file_name / content_type / pages.

Form fields

images and links are independent lanes: omit a field and the server auto-discovers that lane from the document; send [] to suppress it; send entries to use them verbatim. There is no category on files — that's for structured products only.

POSThttps://api.personaizer.com/v1/knowledge/docs/upload
Try it
Response
{
  "id": "manuals-v3",
  "kind": "file",
  "source": "my-shop.ge",
  "title": "Manuals",
  "original_file_name": "product-manuals.pdf",
  "content_type": "pdf",
  "pages": 12,
  "status": { "state": "pending", "created_at": "...", "processed_at": null }
}
POSThttps://api.personaizer.com/v1/knowledge/docs/upload/preflight
Bodyapplication/json
Checksname · size · pages

Preflight an upload

Validate a file's metadata before transferring the bytes — cheap guard against an upload that would be rejected. Returns { ok: true }, or 400 with the reason.

Send the file_name, content_length (bytes), and page_count (for PDF / DOCX / PPTX). The same size and page limits as the upload apply.

POSThttps://api.personaizer.com/v1/knowledge/docs/upload/preflight
Try it
{
  "file_name": "product-manuals.pdf",
  "content_length": 5242880,
  "page_count": 12
}
Response
{ "ok": true }

Scoping & activation

The API key determines the persona; reads only see that persona's knowledge.

Every document you write is automatically activated on the key's persona. Documents won't surface in conversations until processing completes. To share one document across personas, upload it with the same id using each persona's key — the content is stored once and activated per persona.

DELETEhttps://api.personaizer.com/v1/knowledge/docs

Delete

Two-phase: documents leave this persona immediately (deactivated); any that no other persona still references are queued for permanent deletion.

  • ids not in the persona's knowledge are silently skipped.
  • job_id is present only when queued_for_deletion > 0 — poll the jobs endpoint until completed.
DELETEhttps://api.personaizer.com/v1/knowledge/docs
Try it
Response
{ "deactivated": 2, "queued_for_deletion": 1, "job_id": "0197a1b2-..." }
GEThttps://api.personaizer.com/v1/knowledge/docs
Paginatedlimit ≤200
Echosymmetric + status

Read endpoints

Read the persona's catalog back. A document comes back exactly as you sent it, plus a status block (state, processing accounting).

Endpoints

List query params

GEThttps://api.personaizer.com/v1/knowledge/docs
Try it
Response
{
  "items": [
    {
      "id": "sku-002", "kind": "item",
      "source": "my-shop.ge", "category": "footwear",
      "title": "Red trail runners",
      "price": 109.99, "original_price": 129.99, "currency": "USD", "in_stock": true,
      "status": { "state": "ready", "knowledge_units": 1.0, "active_persona_count": 1 }
    }
  ],
  "total_count": 1
}
GEThttps://api.personaizer.com/v1/knowledge/docs/{id}

Read one document

Full detail for a single document — the same typed shape as a list row, including its status block. 404 if the id isn't on this persona.

GEThttps://api.personaizer.com/v1/knowledge/docs/{id}
Try it
Response
{
  "id": "sku-002", "kind": "item",
  "source": "my-shop.ge", "category": "footwear",
  "title": "Red trail runners",
  "description": "Lightweight trail shoe with a grippy outsole.",
  "price": 109.99, "original_price": 129.99, "currency": "USD", "in_stock": true,
  "status": { "state": "ready", "knowledge_units": 1.0, "active_persona_count": 1 }
}
GEThttps://api.personaizer.com/v1/knowledge/jobs/{job_id}

Job status

Status of an async job — the job_id comes back from a delete that queued documents for permanent removal. Poll until status is completed or failed; processed / total track progress.

GEThttps://api.personaizer.com/v1/knowledge/jobs/{job_id}
Try it
Response
{ "job_id": "0197a1b2-...", "status": "completed", "processed": 1, "total": 1 }
GEThttps://core.personaizer.com/api/subscription/limits

Checking your limits

Check remaining quota before large uploads. Knowledge Units (Ku) measure your searchable content; Storage Units (Su) measure raw file storage in MB.

Note the host — this is served from core.personaizer.com, the one /api route that accepts API keys. Uploading beyond your limit returns 402 limits.quota_exceeded (Credit quota exceeded).

GEThttps://core.personaizer.com/api/subscription/limits
Try it
Response
{
  "usage": {
    "knowledgeUnitsUsed": 12480, "knowledgeUnitsLimit": 100000,
    "storageUnitsUsed": 4.2,     "storageUnitsLimit": 512
  }
}