Primer for AI Agents
This page is written for AI coding assistants and for developers who want the whole mental model on one screen. It condenses the rest of this documentation into one page; each section links to the authoritative one. A machine-readable index of the full documentation is at /llms.txt.
1. Which product am I working on?
Section titled “1. Which product am I working on?”| If the task is about… | You are in | Start at |
|---|---|---|
| A native iOS/Android shopping app, its UI, its checkout, an extension or a theme | Shopping Apps (Shopgate CONNECT) | Shopping Apps introduction |
| Inventory, order routing, ship-from-store, click & collect, customer or catalog data over REST | Omnichannel Suite | Omnichannel welcome |
The two products have separate APIs, separate auth and separate concepts. Pipelines
belong to Shopping Apps. REST services under *.shopgate.io belong to the Omnichannel
Suite. Do not mix them.
2. Shopping Apps in one paragraph
Section titled “2. Shopping Apps in one paragraph”A Shopgate app is a native shell around a React/Redux frontend (called Engage) that talks to a Node.js backend (called CONNECT). You do not fork the app. You extend it with extensions: npm-like packages that contribute steps and pipelines to the backend and portals, subscribers, reducers, widgets and translations to the frontend. Merchant-specific behaviour lives in extensions; the theme stays upgradeable.
Reference: App Architecture
3. Local setup
Section titled “3. Local setup”Requires Node.js 18+ and Git. Reference: Set up your developer environment
npm install -g @shopgate/platform-sdksgconnect loginsgconnect initsgconnect init creates the application folder — the workspace that holds
extensions/ and themes/. All further commands run from there.
The commands you will actually use
Section titled “The commands you will actually use”| Command | Purpose |
|---|---|
sgconnect extension create [types...] |
Scaffold a new extension (backend, frontend or both) |
sgconnect extension attach [name...] |
Attach extensions to the sandbox app (no name = all) |
sgconnect extension detach [name...] |
Detach again |
sgconnect extension manage |
Interactive list of extensions and their attach status |
sgconnect backend start |
Run the backend runtime locally |
sgconnect frontend setup |
One-time frontend environment setup |
sgconnect frontend start |
Run the frontend dev server |
sgconnect extension upload [dir] |
Upload to the Developer Center |
sgconnect theme upload |
Upload a theme |
Attach/detach changes only take effect after restarting the backend and/or frontend process.
Reference: Platform SDK reference
4. Anatomy of an extension
Section titled “4. Anatomy of an extension”extensions/myFirstExtension/├── extension/ # Backend: step files (plain Node.js), node_modules├── pipelines/ # Backend: pipeline definitions (.json)├── frontend/ # Frontend: React components, subscribers, reducers, locale files└── extension-config.json # Manifest: id, version, trust level, config, components, stepsExtension IDs follow @<organization>/<name>, e.g. @myAwesomeOrganization/myFirstExtension.
The organization part is assigned to you when you create your developer account.
Reference: Hello World part 1
extension-config.json
Section titled “extension-config.json”Minimal:
{ "id": "@myAwesomeOrganization/myFirstExtension", "version": "1.0.0", "trusted": false}Full set of top-level properties:
| Property | Type | Required | Purpose |
|---|---|---|---|
id |
string | yes | Extension id, @org/name |
version |
string | yes | semver |
trusted |
boolean | no | Runs in the trusted environment (payments, login) |
configuration |
object | no | Values injected into frontend and/or backend |
components |
array | no | Frontend contributions |
steps |
array | no | Backend steps that hook into existing pipelines |
Reference: Extension config reference
5. Backend: steps and pipelines
Section titled “5. Backend: steps and pipelines”A step is a plain async function
Section titled “A step is a plain async function”Every step file lives under extension/ and exports one function:
module.exports = async (context, input) => { const message = 'Hello World' return { message }}context— meta information, storage access, logger, app and device info.input— the input the pipeline hands to this step.- The returned object is the step’s output. Property names must match the
outputkeys declared for the step.
Reference: Step context reference
A pipeline is a JSON file that chains steps
Section titled “A pipeline is a JSON file that chains steps”The file name must match the id, and the id must start with your organization id.
Everything after that is up to you: myAwesomeOrganization.myFirstPipeline is valid.
Shopgate’s own pipelines use a longer four-part convention —
<organization>.<collection>.<action>.<version>, as in
shopgate.catalog.getProducts.v1 — and new pipelines should follow it. Both forms
appear in this documentation: the pipelines guide
states the four-part convention, the
Hello World tutorial uses the
short form.
{ "version": "1", "pipeline": { "id": "myAwesomeOrganization.myFirstPipeline", "public": true, "input": [], "output": [ { "key": "message", "id": "1" } ], "steps": [ { "type": "extension", "id": "@myAwesomeOrganization/myFirstExtension", "path": "@myAwesomeOrganization/myFirstExtension/helloWorld.js", "input": [], "output": [ { "key": "message", "id": "1" } ] } ] }}public: falsemeans the pipeline can only be called by another pipeline in the same environment, not from the app.- Steps must consume all declared pipeline input and produce all declared output, otherwise the request fails.
- A pipeline request times out after 20 seconds and returns
ETIMEOUT. Anything slower needs to be async or cached.
Reference: Pipelines guide · Pipeline reference
Extending Shopgate’s pipelines instead of writing your own
Section titled “Extending Shopgate’s pipelines instead of writing your own”To add behaviour to an existing pipeline, declare a step with a hook string in
extension-config.json:
"steps": [ { "path": "extension/addBonusPoints.js", "description": "Adds bonus points to each product; place after price calculation.", "hooks": ["shopgate.catalog.getProducts.v1:after"], "input": [{ "key": "productId" }], "output": [{ "key": "bonusPoints", "addPipelineOutput": true, "optional": true }] }]Hook string format is {pipelineName}:{hookName}. Use *:{hookName} to hook into
every pipeline that exposes that hook. Steps are only inserted into hooks of
pipelines with the same trust level.
Every pipeline implicitly has a before and an after hook — before steps see
and can modify the pipeline input, after steps see input and output and can modify
the output. Writing a hook step literally named before or after into a pipeline
file is an error. Custom hook steps are declared explicitly in the pipeline:
{ "type": "hook", "id": "getProductImageUrl", "input": [{ "key": "productId", "id": "1" }], "output": [{ "key": "imageUrl", "id": "10" }]}One hook can hold steps from several extensions, and their execution order is not guaranteed — never write a hook step that depends on another hook step having run.
Two different
pathformats — a common source of errors. Inextension-config.json→steps[].path, the path is relative to the extension root and must start withextension/(e.g.extension/myStep.js); a path outside the extension throws an error. In a pipeline file →steps[].path, the path is the fully qualified@org/extension/file.jsform (e.g.@myAwesomeOrganization/myFirstExtension/helloWorld.js).
Reference: Step insertion · Hook step
Trusted vs. regular
Section titled “Trusted vs. regular”Trusted pipelines and steps may use steps that regular ones cannot, and are meant for sensitive work: payments, user login. Trusted extensions are manually reviewed by Shopgate for malicious code. Only mark an extension trusted if it genuinely needs it.
Testing a pipeline locally
Section titled “Testing a pipeline locally”sgconnect extension attachsgconnect backend startThen call the local proxy:
curl -X POST http://localhost:8090/pipelines/myAwesomeOrganization.myFirstPipeline \ -H 'Content-Type: application/json' \ -d '{}'6. Frontend: portals, not forks
Section titled “6. Frontend: portals, not forks”Portals are named extension points inside the theme. A parent portal wraps or
replaces a component; a sibling portal injects a component above or below one.
Names follow <feature>.<content>.<position>, e.g. PRODUCT-ITEM.NAME (parent) and
PRODUCT-ITEM.NAME.AFTER (sibling).
Register a component in extension-config.json:
"components": [ { "id": "MyComponent", "path": "frontend/MyComponent/index.jsx", "target": "product-item.name.before", "type": "portals" }]Component types are portals, subscribers, reducers, widgets and translations.
target only applies to portals.
Adding a whole page
Section titled “Adding a whole page”Use the app.routes portal. It passes a View component as a prop:
import React from 'react';import { Route } from '@shopgate/engage/components';
const MyPageComponent = ({ View }) => ( <View> <div>Hello, I'm a page.</div> </View>);
const MyRoute = props => ( <Route path="/myroutepath" component={MyPageComponent} {...props} />);
export default MyRoute;Reference: Portals guide · Portals reference · Custom routes
Where to look for the rest
Section titled “Where to look for the rest”| Need | Page |
|---|---|
| Call a pipeline from the frontend | Data fetching |
| Read app state | Selectors |
| React to app events | Streams |
| Dispatch behaviour | Actions |
| Translations | Translation system |
| Tracking / analytics extension | Tracking events |
| Camera, push, geolocation, keychain … | Native modules |
7. Omnichannel Suite REST APIs
Section titled “7. Omnichannel Suite REST APIs”URL scheme
Section titled “URL scheme”https://{serviceName}.shopgate.io/v{version}/merchants/{merchantCode}/{entity}Examples: https://catalog.shopgate.io/v1/merchants/TEST/products,
https://order.shopgate.io/v1/merchants/TEST/salesOrders.
Services: catalog, customer, order, import, webhook, location, auth.
Reference: Service URLs
Auth — every request needs a bearer token
Section titled “Auth — every request needs a bearer token”The generated code samples in the API reference omit this. They will return 401 as-is.
Get a token (OAuth2, x-www-form-urlencoded):
curl -X POST https://auth.shopgate.io/oauth/token \ -H "Authorization: Basic $(printf '%s:%s' "$CLIENT_ID" "$CLIENT_SECRET" | base64)" \ -H 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'grant_type=password' \ --data-urlencode "username=$API_USER_EMAIL" \ --data-urlencode "password=$API_USER_PASSWORD" \ --data-urlencode 'tenantType=merchant' \ --data-urlencode "tenantId=$MERCHANT_CODE"Response:
{ "access_token": "eyJhbGciOiJIUz...", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "kcLKlSPYc2fDr4..."}Then use it on every call:
curl "https://catalog.shopgate.io/v1/merchants/$MERCHANT_CODE/products?limit=100" \ -H "Authorization: Bearer $ACCESS_TOKEN"- Access token: valid 1 hour.
- Refresh token: valid 3 months; use
grant_type=refresh_tokento get a new access token. - Staging host:
https://auth.demo.shopgatedev.io/oauth/token. clientId/clientSecretcome from Shopgate support.
Reference: Authentication
Conventions shared by all services
Section titled “Conventions shared by all services”- Batch creation: entity creation goes through batch routes. Batch routes
- Sorting, filtering, sparse fields: consistent query parameters across services. Sorting and filtering
- Everything is scoped by
merchantCode.
8. Rules of thumb for generated code
Section titled “8. Rules of thumb for generated code”- Never emit an Omnichannel request without an
Authorization: Bearerheader. - Never fork a theme to change the UI — use a portal, unless the task is an explicitly new theme.
- Keep pipeline work under 20 seconds. Long-running work must be moved out.
- Don’t mark an extension
trustedunless it handles payment or login; it triggers a manual Shopgate review. - Pipeline id and file name must agree, and mind the two
pathformats:extension/myStep.jsinextension-config.json,@org/extension/myStep.jsin a pipeline file. - Declared
input/outputkeys and the object the step returns must match exactly. - Never rely on the execution order of steps inside the same hook.
- Frontend imports come from
@shopgate/engage/*, not from the theme’s internals. - After changing
extension-config.json, restart backend and/or frontend — the SDK does not hot-reload the manifest.
9. What is not covered here
Section titled “9. What is not covered here”Themes, CMS widgets, the consent manager, accessibility, web checkout handover, the cart-integration (legacy) route, and every REST endpoint in detail. Use llms.txt for the full page index.

