AACsearch
Conectores y Widget

Custom Connector — Developer Guide

Build a CMS connector against the AACsearch Connector API. Covers token usage, full/delta/delete sync, document shape, mapping rules and required error handling.

If your CMS or product catalog is not in the supported platform list, you can ship your own connector against the public Connector API. This page describes the minimum surface a connector must implement to be considered production-ready.

The API itself is fully documented in Connector API Lifecycle. This page focuses on the developer responsibilities that live on the CMS side.

What "production-ready" means

A connector is production-ready when it:

  1. Authenticates every request with an ss_connector_* Bearer token.
  2. Runs a handshake on install and config save, and persists the returned projectId and indexSlug.
  3. Performs an initial full sync, batched at ≤1000 documents per request.
  4. Performs delta syncs on every product create / update / stock or price change, batched at ≤100 documents per request.
  5. Issues a delete on every product deletion.
  6. Sends a heartbeat at least every 5 minutes from a background task.
  7. Reports diagnostics after every full sync, after sync failures, and on a daily timer.
  8. Maps the CMS entity into the shared product document shape (below) using all available fields.
  9. Implements the retry strategy.
  10. Surfaces a Test connection action in its admin UI.

A connector that ships steps 1–6 only is acceptable as an Early preview. Items 7–10 are required for Beta, and observed reliability over at least 3 release cycles is required for Supported.

Project layout

You can host your connector wherever it makes sense for the target platform. The reference implementations in this monorepo follow one of three templates documented in wiki/tasks/cms-platform-expansion.md:

  • Template A — PHP CMS module (PrestaShop, Bitrix, WordPress, OpenCart, Magento, Drupal, Joomla)
  • Template B — TypeScript server-side connector (Shopify, InSales)
  • Template C — npm headless CMS plugin (Strapi, Sanity, Contentful, Directus, Payload)

The minimum file set for any template:

your-connector/
├── client.{ts,php}           ← HTTP client around the Connector API
├── product-mapper.{ts,php}   ← Platform entity → SyncProductInput
├── full-sync.{ts,php}        ← Paginated catalog export
├── delta-sync.{ts,php}       ← Event handler for create/update/delete
├── diagnostics.{ts,php}      ← Heartbeat + error reporting
└── admin/
    ├── settings.{tsx,php}    ← Token + project ID form
    └── test-connection.{tsx,php}

Use the existing modules as references:

  • packages/strapi-plugin/src/server/services/aacsearch.ts — TypeScript service with full and delta sync
  • modules/bitrix/aac.search/lib/aacsearch/ConnectorClient.php — PHP API client
  • modules/prestashop/aacsearch/ — PrestaShop module structure
  • packages/shopify-connector/src/ — OAuth-based connector with webhooks

Document shape

Every product sent to AACsearch maps to SyncProductInput. Required fields are external_id and title; everything else is optional but strongly recommended.

type SyncProductInput = {
  external_id: string;            // stable platform ID
  title: string;
  description?: string;
  sku?: string;
  brand?: string;
  categories?: string[];          // human-readable category path
  category_ids?: string[];        // platform category IDs for filters
  tags?: string[];
  price?: number;                 // major units (e.g. 99.99 USD)
  sale_price?: number;
  currency?: string;              // ISO 4217, 3 letters
  image_url?: string;
  product_url?: string;
  availability?: "in_stock" | "out_of_stock" | "preorder";
  stock_quantity?: number;
  attributes?: Record<string, unknown>;
  locale?: "en" | "de" | "es" | "fr" | "ru";
  created_at?: string;            // ISO 8601
  updated_at?: string;            // ISO 8601
};

Mapping rules

  • external_id — must be stable across the product's lifetime. Use the CMS primary key, never a slug or SKU.
  • title — use the localized title for the configured locale. Strip HTML and normalize whitespace.
  • description — same rule. Strip HTML, leave the plain text. AACsearch will tokenize.
  • categories — full breadcrumb path, top → leaf. ["Shoes", "Running", "Trail"] is better than ["Trail"].
  • price / sale_price — major units in the connector wire format. The AACsearch ingest pipeline normalizes to minor units (kopecks-style BigInt) on the storage side. Do not pre-multiply by 100.
  • attributes — anything that is filterable or facetable but does not have a dedicated column. Keys are free-form strings. Numeric attributes (size, length, capacity) should be sent as numbers, not strings — AACsearch will infer the index type from the first batch.
  • locale — if the CMS has localized catalogs, send one document per locale per product, each with a different external_id suffix (for example, prod-123:en, prod-123:de). Do not collapse locales into a single document.

Multi-currency catalogs

If your CMS supports multiple currencies, send the customer-facing currency as currency and an attributes.price_by_currency object for the rest:

{
  "currency": "USD",
  "price": 99.99,
  "attributes": {
    "price_by_currency": { "EUR": 92.5, "GBP": 79.99 }
  }
}

AACsearch will index the alternative prices as numeric attributes so the storefront can switch currency without re-indexing.

Required endpoints

A minimum viable connector calls these endpoints in this order:

  1. POST /api/connectors/handshake on install and on every config save.
  2. POST /api/projects/:projectId/sync/full for the initial catalog export and for a manual "Resync everything" action.
  3. POST /api/projects/:projectId/sync/delta on every product event in the CMS.
  4. DELETE /api/projects/:projectId/products/:externalId on product deletion.
  5. POST /api/connectors/:connectorId/heartbeat every 5 minutes.
  6. POST /api/projects/:projectId/diagnostics after each full sync and on a daily timer.

All payload shapes, error codes, and the lifecycle order are in Connector API Lifecycle.

Auth, scopes, and tenant isolation

The Connector API enforces three invariants that connector authors do not need to reimplement but must not work around:

  • Every call is bound to the organization that owns the token. The :projectId in the URL must match the token's organization. A 404 means the merchant pasted the wrong token, not that AACsearch lost data.
  • The token's connector_write scope is the only scope checked. Connector tokens cannot read search results, manage indexes, or read analytics. Use a ss_search_* token from the storefront for search queries.
  • Documents are written to SearchIngestBuffer first, then to Typesense by the background worker. A 200 means buffered — the document may not be queryable for a few hundred milliseconds.

Never call Typesense, the AACsearch admin search key, or any internal storage directly. The Connector API is the only supported write path. Direct writes bypass tenant isolation, quota tracking, and the buffer that absorbs retries — they will break in non-obvious ways under load.

Webhook receiver

Connectors that operate from the CMS server can choose between two patterns:

  • Outbound push — the module reacts to CMS events and calls the AACsearch sync endpoints directly. Simple, used by every existing PHP module.
  • Webhook receiver — AACsearch sends webhooks to the platform when documents are reindexed, useful for cache invalidation or analytics. Endpoint: POST /api/webhooks/sync/:indexSlug, HMAC-signed with the connector token secret.

Most CMS connectors do not need the receiver. Use it when you want the platform's own cache or CDN to know that the search index has changed.

Local development

For a fast loop:

  1. Run AACsearch with bun run dev — the API mounts at http://localhost:3000/api.
  2. Create a connector token from the dashboard and copy it.
  3. Point your CMS module at http://localhost:3000/api.
  4. Use the /api/projects/:projectId/sync/jobs/:jobId endpoint or Dashboard → Connectors → Sync history to watch documents land.
  5. Use Search → Test Search in the dashboard to confirm documents are indexed under the right tenant.

If you ship a hosted version, prefer https://api.aacsearch.com/api and let merchants paste the connector token as-is.

Submitting your connector

If you want your connector to appear in the platform support matrix:

  1. Open an issue describing the platform and target template (A, B, or C).
  2. Submit a PR that adds the connector under modules/<platform>/ or packages/<platform>-connector/, plus a dedicated docs page in apps/docs/content/docs/{en,de,es,fr,ru}/connectors/<platform>.mdx.
  3. Tag the docs page status as Early preview initially. Promotion to Beta and Supported is gated by reliability over multiple release cycles.

On this page