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-connectorRequires 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:
- Transport —
Numinix\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 viaBreakerStateStore:InMemoryBreakerStore(tests, CLI),ApcuBreakerStore(single-host cPanel), and connectors' own platform-native stores (WP transients, Laravel cache). - Per-tenant config —
Numinix\SeekmodoSdk\TenantSnapshotpolls/v1/admin/tenant.snapshotwith stale-while-revalidate caching via a pluggableCacheInterface. - Mode FSM —
Numinix\SeekmodoSdk\ModeFsmresolves the effective operating mode (off / learning / shadow / active / enforce) from configured mode + breaker state + tenant snapshot.AutoPromoterhandles shadow ⇄ enforce promotion / demotion based on breaker health. - Pairing & events —
Numinix\SeekmodoSdk\Pairingverifies EdDSA JWTs against the gateway'sjwks.json;BrowserTokenmints short-lived browser JWTs;Events\\EventsQueuebatches click / impression / search events for efficient delivery;Events\\ClickBeaconbuilds 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.