Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/VisualGraphxLLC/API-HUB/llms.txt

Use this file to discover all available pages before exploring further.

API-HUB ships eight workflow JSON files in the n8n-workflows/ directory. Each file is a self-contained n8n workflow that can be imported directly into the n8n editor. None of them activate automatically — you import, bind credentials, then manually activate.
All workflow JSONs ship with "active": false. Activating before credentials are configured causes every execution to fail immediately. Import first, bind credentials, then activate.

Workflow index

FileTriggerPurpose
vg-ops-pull.jsonManual / DailyPull OPS categories and products → hub /api/ingest/{sid}/*
catalog-sync-weekly.jsonSunday 1 AMFull sellable catalog sync per supplier
pricing-sync-daily.jsonDailyDelta pricing sync for all active suppliers
inventory-sync-hourly.jsonHourlyDelta inventory sync
closeouts-monthly.json1st of monthCloseouts mode sync
ops-push.jsonWebhookApply markup and push hub products → OPS storefront
ops-master-options-pull.jsonDailyPull OPS master options → hub /api/ingest/master-options
sanmar-sftp-pull.jsonDailySanMar SFTP pull → hub /api/ingest/{sid}/*

Environment variables used in all workflows

Workflows reference environment variables using n8n’s {{ $env.VARIABLE }} expression syntax. Set these in your repo-root .env — Docker Compose forwards them to the n8n container automatically.
VariableValue in Docker ComposeDescription
API_BASE_URLhttp://api:8000FastAPI service address. In production, set to your public or internal API hostname.
INGEST_SHARED_SECRETyour secretSent as the X-Ingest-Secret header on every POST to /api/ingest/* and /api/push-log. Must match the value in the FastAPI container.

Workflow details

vg-ops-pull.json — Pull OPS catalog (Manual / Daily)

This workflow pulls the entire Visual Graphics OnPrintShop catalog into the hub. It is the primary inbound pipeline for OPS-hosted suppliers.Flow:
1

Look up VG supplier

Calls GET {{ $env.API_BASE_URL }}/api/suppliers and filters for the supplier with slug = 'vg-ops'. Fails fast with a descriptive error if the row is missing or is_active = false.
2

Pull categories

Uses the OnPrintShop node’s getManyProductCategory operation with pagination to fetch the full product_category GraphQL response.
3

Pull products

Uses the OnPrintShop node’s getManyProductDetailed operation with fetchAllPages = true to retrieve all products via the products_details query.
4

Transform to hub contracts

A code node maps each OPS shape to the hub’s CategoryIngest and ProductIngest contracts — normalizing IDs, names, parent references, and sort order.
5

POST to FastAPI ingest endpoints

Sends the normalized batches to:
  • POST /api/ingest/{vg_sid}/categories
  • POST /api/ingest/{vg_sid}/products
Both requests carry X-Ingest-Secret: {{ $env.INGEST_SHARED_SECRET }}.A successful ingest returns { sync_job_id, records_processed, status: "completed" }.
Stock and pricing are not included in this workflow. They require a per-product fan-out loop (productStocks and product_price queries) and are planned for v2.
Expected node outputs:
NodeOutput shape
Get SuppliersArray of supplier objects
Resolve VG SID{ vg_sid, vg_name }
OPS: Get Categoriesdata.product_category.product_category[]
Shape Categories[{ external_id, name, parent_external_id, sort_order }]
POST /ingest/categories{ sync_job_id, records_processed, status }
Verify hub-side after a successful run:
VG_ID=$(curl -s http://localhost:8000/api/suppliers \
  | jq -r '.[] | select(.slug=="vg-ops") | .id')

curl -s "http://localhost:8000/api/products?supplier_id=$VG_ID" | jq 'length'
curl -s "http://localhost:8000/api/categories?supplier_id=$VG_ID" | jq 'length'
curl -s http://localhost:8000/api/sync-jobs \
  | jq '[.[] | select(.supplier_name | contains("Visual Graphics"))]'
This workflow is the outbound half of the pipeline. It reads hub products, applies markup via FastAPI, then calls OPS GraphQL mutations to create or update products on a customer’s storefront.Flow:
1

Webhook trigger with customer_id

A webhook node starts the workflow. The caller (admin UI or cron) passes customer_id as a query parameter.
curl "http://localhost:5678/webhook/ops-push?customer_id=<UUID>&limit=5"
2

List hub products

Calls GET {{ $env.API_BASE_URL }}/api/products to retrieve the full product list.
3

Fetch markup payload per product

For each product, calls:
GET /api/push/{customer_id}/product/{product_id}/payload
This endpoint applies the customer’s markup rules and storefront overrides, returning a ready-to-push OPS input object. The request carries X-Ingest-Secret.
4

Call OPS GraphQL mutations

The OnPrintShop node executes two mutations per product:
  • setProduct — creates or updates the product shell
  • setProductPrice — creates a simple price band covering quantity 1 to 999,999
5

Write push-log audit row

Posts the result (success or error) to POST /api/push-log for audit and stale-detection tracking.
This workflow pushes to a single OPS credential. It does not dynamically select a credential per customer — the OPS Storefront credential in n8n must be updated manually when switching storefronts. It also uses category_id = 0 and size_id = 0 by default; update the Build OPS Inputs code node if your OPS instance requires valid IDs.
After activating, verify:
# Check push log
curl -s http://localhost:8000/api/push-log | jq '.[0:5]'
This workflow synchronizes the canonical option vocabulary from OPS into the hub. Master options drive the push mapping layer that translates hub option attributes to OPS-specific option IDs.Flow:
1

Fetch paginated master options

Uses the OnPrintShop node’s getManyMasterOptions operation with full pagination enabled. Retrieves all master option fields and nested attributes[] arrays.
2

Normalize to MasterOptionIngest

A code node casts all IDs to integers, coerces pricing fields to the correct numeric types, and unwraps the nested attributes[] array into the hub’s MasterOptionIngest contract.
3

POST to FastAPI

Sends the normalized batch to POST /api/ingest/master-options with X-Ingest-Secret.
4

Handle HTTP errors

On any HTTP error, a Format Error code node transforms the failure into a structured log entry for downstream error handling.
Import via CLI (alternative to the n8n editor):
docker cp n8n-workflows/ops-master-options-pull.json api-hub-n8n-1:/tmp/mo.json
docker exec api-hub-n8n-1 n8n import:workflow --input=/tmp/mo.json
Triggers a full_sellable import on every active supplier. Calls POST /api/suppliers/{id}/import with { "mode": "full_sellable" } for each supplier row returned by GET /api/suppliers. Designed to run overnight when OPS API rate limits are least congested.
Triggers a delta pricing import for each active supplier. Calls POST /api/suppliers/{id}/import with { "mode": "delta" }. Only requests pricing data that has changed since the last sync, keeping API call volume low.
Runs the fastest cycle in the pipeline. Calls POST /api/suppliers/{id}/import with { "mode": "delta" } for each active supplier, refreshing stock levels every hour to keep storefronts accurate.
Runs on the first of each month. Calls POST /api/suppliers/{id}/import with { "mode": "closeouts" } to pull the current closeout catalog from each supplier.
Connects to SanMar’s SFTP server to pull catalog data, then posts normalized batches to POST /api/ingest/{sid}/*. This workflow requires an SFTP credential configured in n8n in addition to the standard INGEST_SHARED_SECRET.

Importing and activating workflows

1

Open the n8n editor

Navigate to http://localhost:5678 (or your hosted n8n URL).
2

Import the workflow JSON

Go to Workflows → Import from File and select the .json file from n8n-workflows/.
3

Bind credentials

Open each OnPrintShop node in the workflow and confirm the credential dropdown shows the correct credential name. If blank, select it manually and save.
4

Activate the workflow

Toggle the workflow to Active in the top-right of the workflow editor. Scheduled and webhook triggers will not fire until this step is complete.

Failure modes

Node in redError messageCauseFix
Resolve VG SID”VG OPS supplier not seeded”No vg-ops row in the databaseStart FastAPI in development (it auto-creates the row), or run python backend/seed_demo.py
Resolve VG SIDis_active = falseSupplier gate is closedRun UPDATE suppliers SET is_active=true WHERE slug='vg-ops'; in Postgres
OPS node401 / 403Bad OAuth2 credentialsRe-enter the Client ID and Client Secret in the n8n credential editor
POST /ingest/*401 “Invalid or missing X-Ingest-Secret”INGEST_SHARED_SECRET mismatch between n8n and FastAPICompare docker exec api-hub-n8n-1 env | grep INGEST to .env; restart n8n
POST /ingest/*409 “not active”Supplier was deactivated after the workflow startedRun the SQL UPDATE above
POST /ingest/*500FastAPI crashedCheck docker compose logs api for the uvicorn traceback
Check the shared secret in the running n8n container:
docker exec api-hub-n8n-1 env | grep INGEST
Compare the output to the value of INGEST_SHARED_SECRET in your .env file. If they differ, edit .env and restart:
docker compose up -d n8n

Build docs developers (and LLMs) love