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 is a modular monolith made up of four distinct systems: a FastAPI backend, a Next.js 15 admin frontend, an n8n automation engine, and a TypeScript custom n8n node (n8n-nodes-onprintshop). Each system has a clearly defined role, and the boundaries between them are enforced at the network level — not just by convention.

System overview

The admin UI and n8n both talk exclusively to FastAPI. Neither service touches the database directly. FastAPI is the only writer to PostgreSQL, which means audit logging, encryption, and validation happen in one place.

FastAPI backend

The backend is organized into domain modules. Each module owns its own router, models, and service layer. There are no cross-module database calls — modules communicate through the service layer or via the catalog schema.

API routes

Manages supplier records: create, read, update, delete. Each supplier row stores its adapter_class, encrypted auth_config, enabled status, and PromoStandards directory metadata.POST /api/suppliers/{id}/import triggers a catalog import job. The request body specifies a discovery mode:
ModeBehavior
full_sellableFetches the supplier’s entire sellable catalog
deltaFetches only products changed since the last sync timestamp
closeoutsFetches discontinued/clearance items
first_nFetches the first N products — useful for testing
Exposes the normalized product catalog. Supports filtering by supplier, product type, category, and search query. The product detail endpoint (/api/products/{id}) returns full variant data including size matrix, colors, and pricing tiers — the data needed to render a product detail page (PDP).
Manages customer records, each representing an OnPrintShop storefront. Stores the OPS instance URL, API credentials (encrypted), and default markup rule assignment. The OPS inbound module also uses this table to authenticate webhook calls from storefront events.
Stores per-customer pricing rules: markup percentage, minimum margin floor, rounding strategy, and optional product-level overrides. Rules are evaluated at quote time, not stored per product — so updating a rule affects all future quotes immediately.
Accepts a product ID, quantity, and customer ID. Returns unit price, total, cost breakdown, and the markup rule that was applied. The endpoint is optimized for debounced UI calls — the admin UI uses it to preview pricing as operators adjust quantities.
Returns a health report for each supplier: last successful sync timestamp, recent error count, consecutive failure streak, and current job status. The admin UI displays this on the supplier dashboard.
An append-only log of every push attempt to an OPS storefront. Records the customer, product, push status, response payload, and timestamp. Useful for debugging failed pushes without re-running the workflow.

Backend modules

The backend contains 22 domain modules. Key modules and their responsibilities:

suppliers + ps_directory

Supplier CRUD and PromoStandards Directory integration. The directory module auto-discovers all registered suppliers and populates the supplier table.

catalog

Normalized product and variant storage. Manages the polymorphic product_type field and all variant data including size matrices and color maps.

markup + pricing

Markup rule storage and the pricing engine. The engine resolves the correct rule for a customer and computes quoted prices including tiered breaks.

ops_push + push_mappings

Prepares product data for OPS push, applies field mappings, and records results in push_log. Works in tandem with the n8n ops-push workflow.

n8n_proxy

Bridges FastAPI and n8n. Accepts import trigger calls from n8n, enriches data with catalog and markup context, and returns it for n8n to push externally.

auth + audit_log

JWT-based authentication for the admin UI and append-only audit logging for all credential and configuration changes.

Adapter registry

The adapter registry is the core of API-HUB’s supplier-agnostic design. When an import is triggered, the registry reads the supplier’s adapter_class field and instantiates the corresponding Python class at runtime.

Built-in adapters

AdapterProtocolNotes
PromoStandardsAdapterSOAP (zeep)Base class for all PromoStandards-compliant suppliers
SanMarAdapterSOAP (zeep)Subclass of PromoStandardsAdapter with SanMar-specific overrides
FourOverAdapterREST + HMACSigns requests with HMAC-SHA256; handles FourOver’s print catalog schema
OPSAdapterGraphQL inboundHandles product data incoming from OPS storefront events

BaseAdapter interface

Every adapter implements the BaseAdapter abstract base class:
from abc import ABC, abstractmethod

class BaseAdapter(ABC):

    @abstractmethod
    async def discover(self) -> list[SupplierProduct]:
        """Fetch the supplier's full sellable catalog."""
        ...

    @abstractmethod
    async def hydrate_product(self, product_id: str) -> SupplierProduct:
        """Fetch full detail for a single product SKU."""
        ...

    @abstractmethod
    async def discover_changed(self, since: datetime) -> list[SupplierProduct]:
        """Fetch products modified after the given timestamp."""
        ...

    @abstractmethod
    async def discover_closeouts(self) -> list[SupplierProduct]:
        """Fetch discontinued or clearance products."""
        ...
Adding a new supplier protocol means implementing this interface — the registry, import pipeline, and n8n workflows require no changes.

Polymorphic catalog

All products share one catalog schema, but the pricing and variant model differs by product_type.
Apparel products (product_type = "apparel") use a tiered variant model. Each variant is keyed by color and size, with quantity break pricing:
{
  "product_type": "apparel",
  "variants": [
    {
      "color": "Navy",
      "size": "L",
      "price_tiers": [
        {"min_qty": 1,   "unit_cost": 12.50},
        {"min_qty": 12,  "unit_cost": 10.75},
        {"min_qty": 72,  "unit_cost": 9.00}
      ]
    }
  ]
}
The pricing engine selects the applicable tier based on the requested quantity and applies the customer’s markup rule on top.

n8n automation pipeline

n8n owns all external API calls — to supplier endpoints and to OPS storefronts. This is a deliberate architectural choice: it keeps external network calls auditable, retryable, and configurable without redeploying the FastAPI backend.

Scheduled workflows

WorkflowScheduleMode
catalog-sync-weeklySunday 1:00 AMfull_sellable
pricing-sync-dailyDailydelta
inventory-sync-hourlyEvery hourdelta
closeouts-monthly1st of each monthcloseouts
ops-pushTriggeredRuns after import or on demand
Each cron workflow calls POST /api/suppliers/{id}/import with the appropriate mode. FastAPI processes the response, writes to PostgreSQL, and returns enriched data. n8n then pushes any updated products to OPS storefronts via the n8n-nodes-onprintshop GraphQL node.
The ops-push workflow is trigger-based, not scheduled. It runs automatically after a successful import or can be invoked manually from the n8n UI for a specific customer.

Key design decisions

Adding a supplier requires no code deployment. The adapter_class field tells the registry which Python class to instantiate; the encrypted auth_config JSONB blob holds all credentials. This makes supplier management an operator task, not a developer task.
FastAPI never calls supplier APIs directly. n8n makes all outbound HTTP requests. This separation means failed external calls are visible in n8n’s execution history, can be retried with a click, and do not block or crash the FastAPI process.
The EncryptedJSON SQLAlchemy field type transparently encrypts and decrypts JSONB columns using Fernet AES-128. The encryption key is derived from SECRET_KEY. Credentials are managed through the admin UI — operators never interact with raw JSON or environment-variable credential files per supplier.
All backend domain modules run in a single FastAPI process sharing one database connection pool. This avoids distributed systems overhead (service discovery, network latency between services, distributed transactions) while still maintaining clear module boundaries that could be extracted later if needed.
Rather than separate endpoints for apparel and print, API-HUB exposes a single catalog API. The product_type discriminator field drives pricing logic internally. This simplifies the frontend and any downstream integrations — callers do not need to know which endpoint to call based on product category.
The combination of asyncpg (async PostgreSQL driver) and JSONB columns gives the catalog flexibility for supplier-specific metadata without sacrificing query performance. Supplier auth_config, product attributes, and decoration options are all stored as JSONB, indexed where queried.

Next steps

Adapter framework

Learn how to implement a custom adapter for a supplier that does not use PromoStandards.

n8n workflows

Explore each workflow in detail: triggers, error handling, and execution flow.

Pricing engine

Understand how markup rules, quantity tiers, and the print formula combine at quote time.

Deployment

Deploy API-HUB to production with Docker Compose, environment hardening, and monitoring.

Build docs developers (and LLMs) love