# Paid catalogue preparation and storefront integration

The shared catalogue is available in the CourierAPP merchant dashboard at
`https://app.courierapp.gr/eshops/catalog`, the authenticated embedded Shopify app,
WooCommerce 0.4.26 and the server-side `MerchantAssistantClient`.

## Product limits

| Plan | Unique product checks / UTC month / store | Shared AI requests / day | Application budget / month / store |
| --- | ---: | ---: | ---: |
| connect300 | 100 | 20 | USD 0.25 |
| connect1000 | 300 | 50 | USD 0.60 |
| business2000 | 600 | 100 | USD 1.20 |
| scale5000 | 1200 | 150 | USD 2.50 |
| pro10000 | 2400 | 250 | USD 5.00 |

The first limit reached pauses generation. The budget is an application token
reservation/usage limit, not an OpenAI account billing guarantee. Estimates,
abstentions and uncertain attempts count as checks, not accepted corrections.
Header mapping and shipping-rule drafting share request and budget limits.
Source reads consume product checks but no model tokens. Cached unchanged
products do not repeat next month; pending products retain their position.
The free plan has no AI entitlement. Automatic preparation is opt-in and paused
by default; it never means automatic acceptance.

## Source-first proposals

Import a catalogue with exact numeric product/Shopify Variant IDs and explicit
kg/cm columns from the supplied CSV template. Import batches contain at most
100 products; lists contain 20 products by default. Known measurements are
preserved. Source readers currently support exact IKEA packaged-product
identity and reject Logitech product-only dimensions as shipping dimensions.
This is a limited allowlist, not unrestricted web search. Other products fall
back to a clearly labelled Luna estimate when possible; otherwise they remain
on the merchant's manual review list. No paid search is used.

Individual and bulk acceptance (up to 50) require acknowledgement and the
unchanged proposal fingerprint. Official-source evidence and AI ranges remain
attached to accepted fields. A timeout becomes an uncertain attempt, never a
blind provider retry. An estimate is not a measurement or a guarantee of the
courier's final bill. Outer box, tare and protection remain separate.

## Custom server example

```js
import {MerchantAssistantClient} from '../commerce/assistant-client.mjs';
import {fillApprovedCartMeasurements} from './catalogue-cart.mjs';
const assistant = new MerchantAssistantClient({base: process.env.COURIERAPP_API_BASE,
  key: process.env.COURIERAPP_STORE_KEY});
// Load these items/prices from your authenticated server session, never from
// untrusted browser measurement fields. Each line includes product_ref.
const cart = await fillApprovedCartMeasurements(assistant, await loadNativeCart());
// Your existing CourierAppClient.quotes({cart, checkout_policy, ...}) performs
// 3D packing, merchant-price markup and destination-specific free tiers.
```

Use `custom/cart-service.mjs` to expose a private cart-session endpoint. It
re-quotes additions and only presents those with unchanged safe shipping cost.
Checkout returns quiet shipping choices and optional compact geometry, with no
upsell messages. `commerce/packing-projection.mjs` strips wholesale costs,
margin, credentials and addresses before geometry reaches the browser. Shared
rendering assets are `/connect/assets/packing-view.js` and `.css`.

## Shopify boundary

The embedded merchant interface uses App Bridge session tokens and the installed
store binding. It imports a merchant-exported Variant CSV without adding
`read_products` or `write_products` scopes. Accepted data populates the existing
CourierAPP packing sidecar; native Shopify product fields are not overwritten.
Known native gram weights remain authoritative. CarrierService eligibility is
still required for calculated rates. Shopify controls its native checkout;
this release does not replace it or install a theme block in a merchant's store.
Optional storefront geometry/cart suggestions need that store's theme/server
integration using the public projection, without a store key in the browser.

WooCommerce reads native product/variation fields and converts store units to
kg/cm. After approval it can save missing native values with merchant evidence.
Custom stores may consume the accepted sidecar or save to their own native
catalogue through their explicitly authorised server integration.
