Skip to main content

Overview

The Shopping Agent API provides two endpoints: one to initiate a real-time menu scan via a Trigger.dev task, and one to retrieve a cached scan result. The scan is an asynchronous operation. Web clients can request a Trigger.dev trigger token for useRealtimeTaskTrigger; native clients set triggerServerSide: true and subscribe to the returned run with the publicAccessToken.

Endpoints


POST /api/v1/shopping/scan-token

Creates a public Trigger.dev access token and triggers the shopping-menu-scan task. If a valid cached scan already exists for the requested dispensary, the token is returned alongside the cached result and no new task is started. If a scan for the same dispensary is already running (de-duplication check), the token for that active run is returned instead.

Request

Request Body Schema

Responses

200 OK — Cache Hit A valid scan was found in cache. No new task is triggered.
200 OK — New Scan Triggered (Native / Server-Side Trigger) triggerServerSide: true starts the Trigger.dev run from the API and returns a scoped token for subscribing to that run.
200 OK — Trigger Token Ready (Web / Client-Side Trigger) When triggerServerSide is omitted or false, the API returns a short-lived token that the web client uses with useRealtimeTaskTrigger.
200 OK — Deduplication A scan for the same domain and category set is already in progress. Subscribe to the returned existing run.
The underlying task output keeps the domain under websiteDomain:
400 Bad Request
401 Unauthorized

GET /api/v1/shopping/scan/:domain/cached

Retrieves the most recent cached scan result for a dispensary domain. Returns 404 if no valid cache entry exists or if the cache has expired (4-hour TTL).

Request

Path Parameters

Response

200 OK — Cache Hit
404 Not Found — No Cache

Data Schemas

Product

A matched menu product with strain data and personalization tags.

Recommendation

An AI-generated top recommendation from the current menu.

Discovery

An unmatched product flagged for potential database addition.

Real-Time Progress

The mobile app does not poll for scan results. Native clients call /scan-token with triggerServerSide: true, then subscribe to the returned runId using publicAccessToken and Trigger.dev realtime SSE. Web clients can use the returned triggerToken with useRealtimeTaskTrigger and submit the task input client-side.

Progress Event Shape

Trigger.dev emits run metadata updates as the task progresses. The Shopping Agent task emits structured metadata at each stage:

Native Integration

Web Integration


The shopping-menu-scan Trigger.dev Task

The Trigger.dev task runs in the @tiwih/trigger package and executes six stages in sequence.

Task ID

Trigger.dev Dashboard

View task in dashboard

Stage Details

Input Schema

Output Schema


Strain Matching Algorithm

The match stage runs three passes in sequence, stopping as soon as a match is found for each product.

Pass 1: Exact Match

Confidence: high

Pass 2: Slug Match

Confidence: high

Pass 3: Trigram Match

Confidence: medium if similarity > 0.6, low if 0.4–0.6 Products with no match across all three passes are placed in the discoveries array.

Database

Scan results are stored in the menu_scans table in Supabase.

Table: menu_scans

Unique constraint: UNIQUE (website_domain, categories_hash) — prevents duplicate scans for the same dispensary and menu composition.

Error Codes