Seekmodo developer docs

Reference for the REST shim, MCP JSON-RPC surface, and storefront connectors. Authenticate with HMAC; replay window is 5 minutes.

numinix/seekmodo-connector

Server-side PHP SDK for the Seekmodo MCP gateway. Bundles the HMAC signer, the three-state circuit breaker, the per-tenant snapshot poller, the mode FSM (off / learning / shadow / active / enforce), the EdDSA pairing handshake, the browser-token mint, the events batcher, and a structured exception taxonomy into a single Composer package shared by the Zen Cart, WordPress, and AKS connectors — and by any custom PHP integration you build on top of the gateway.

When to reach for this

Use this SDK when you're writing a PHP storefront connector or a server-side integration that talks to the gateway with your tenant's HMAC shared secret. For browser code (single-page apps, headless storefronts, web components), use the JavaScript SDK — it never sees your shared secret.

Install

composer require numinix/seekmodo-connector

Requires PHP ^8.0, ext-json, ext-hash, and ext-sodium (for EdDSA JWT verify during pairing). Brings in psr/log, psr/http-client, psr/http-factory, and psr/http-message as the only hard runtime deps. You inject whichever PSR-18 HTTP client your stack already uses (Guzzle on Laravel, wp_remote_request wrapped as PSR-18 on WordPress, raw curl on Zen Cart) so the SDK never duplicates an HTTP layer you already have.

Quick start

use GuzzleHttp\Client as Guzzle;
use GuzzleHttp\Psr7\HttpFactory;
use Numinix\SeekmodoSdk\Client;
use Numinix\SeekmodoSdk\HmacSigner;
use Numinix\SeekmodoSdk\CircuitBreaker;
use Numinix\SeekmodoSdk\Storage\InMemoryBreakerStore;

$signer  = new HmacSigner('your-tenant-id', getenv('SEEKMODO_SHARED_SECRET'));
$breaker = new CircuitBreaker(new InMemoryBreakerStore());
$factory = new HttpFactory();

$client = new Client(
    $signer,
    new Guzzle(['http_errors' => false]),
    $factory,
    $factory,
    'https://mcp.seekmodo.com',
    $breaker,
);

$hits = $client->search([
    'q' => 'red sneakers',
    'per_page' => 24,
]);

Public surface

Five namespaces cover everything a connector needs:

  • TransportNuminix\SeekmodoSdk\Client (search, index, events, tenant.handshake, tenant.snapshot, tools, health, browser-token), Numinix\SeekmodoSdk\HmacSigner (the threeX-Seekmodo-* headers per request).
  • Resilience Numinix\SeekmodoSdk\CircuitBreaker (three-state FSM: closed / open / half_open) plus three pluggable storage adapters via BreakerStateStore: InMemoryBreakerStore (tests, CLI), ApcuBreakerStore (single-host cPanel), and connectors' own platform-native stores (WP transients, Laravel cache).
  • Per-tenant config Numinix\SeekmodoSdk\TenantSnapshot polls /v1/admin/tenant.snapshot with stale-while-revalidate caching via a pluggable CacheInterface.
  • Mode FSM Numinix\SeekmodoSdk\ModeFsm resolves the effective operating mode (off / learning / shadow / active / enforce) from configured mode + breaker state + tenant snapshot. AutoPromoter handles shadow ⇄ enforce promotion / demotion based on breaker health.
  • Pairing & events Numinix\SeekmodoSdk\Pairing verifies EdDSA JWTs against the gateway's jwks.json; BrowserToken mints short-lived browser JWTs; Events\\EventsQueue batches click / impression / search events for efficient delivery; Events\\ClickBeacon builds the canonical payload shapes.

Pluggable storage

Three storage interfaces let you inject your platform's native cache without forcing APCu (or anything else) on your host:

  • BreakerStateStore — three-state breaker FSM shared across php-fpm workers.
  • CacheInterface — tenant snapshot, JWKS, browser-token, signature-mismatch sliding window.
  • EventQueueStore — buffer for click / impression / search events between request and cron flush.

Reference implementations ship in src/Storage/: InMemoryBreakerStore, ApcuBreakerStore, InMemoryCache, ApcuCache, InMemoryEventQueueStore. Each first-party connector ships its own thin platform adapter on top.

Exception taxonomy

Every transport-level failure is a Numinix\SeekmodoSdk\Exception\ClientException with a kind classifier you can switch on for fallback decisions:

try {
    $hits = $client->search(['q' => $kw]);
} catch (\Numinix\SeekmodoSdk\Exception\ClientException $e) {
    if ($e->shouldFallback()) {
        return $nativeStorefrontSearch($kw);
    }
    throw $e;
}

Specialised subclasses surface the high-signal cases: BreakerOpenException (gateway short-circuited locally), TenantUnavailableException (tenant disabled / not provisioned), OverQuotaException (402), SignatureMismatchException (HMAC verify failed on the gateway side — usually a clock skew or a rotated secret).

First-party connectors built on the SDK

The three first-party PHP connectors all ship on top of this package:

  • Zen Cart — plugin vendors the SDK into v<X.Y.Z>/catalog/includes/library/ at release-build time; no Composer at runtime needed.
  • WordPress — plugin pulls the SDK via Composer and ships three WP-flavoured storage adapters (transient breaker store, transient cache, options-row event queue) plus a wp_remote_request-backed PSR-18 client to keep the plugin Guzzle-free.
  • AKS (Laravel) — package pulls the SDK via Composer and registers Laravel-flavoured storage adapters against the container so every SDK service is resolvable via app(\\Numinix\\SeekmodoSdk\\Client::class).

Custom connectors

Building a connector for a platform we don't ship? Implement the four swap-points your platform exposes — search, indexer, click beacon, typeahead — and reach for the SDK for every gateway interaction in between. The plumbing this SDK handles for you (HMAC, breaker, snapshot polling, mode FSM, pairing, browser-token mint, event batching) is the same on every platform, so a fresh connector is closer to one person-week than the three weeks it would take from scratch.

Repo + issue tracker: github.com/numinix/seekmodo-php-sdk.