Data ingest
Most powersport brands and importers carry catalog data in whatever shape their internal systems produce. CSVs in five different column orderings, REST APIs with custom auth, XML feeds with bespoke schemas. PowersportOS handles the translation step so retailers downstream consume one normalised data shape regardless of upstream source. This doc covers what's live today, what's added per data-provider relationship, and how the underlying brand-permission model gates writes to the central catalog.
Two ways data lands in PowersportOS today
Both paths write to the same central catalog and respect the same brand-permission gate (see below). The difference is just how the data physically gets here.
- CSV upload
- Live for all tenants. Data provider downloads a CSV template, fills it in (or exports from their own system), uploads via the portal. Backend parses, validates, applies brand-permission gating per row, and writes to central Part rows. Same column shape as the in-app downloadable template. Asset URLs (images, manuals) are mirrored to our object storage on import.
- Direct API
- Live for all tenants. POST / PUT / DELETE against /api/app/managed-brands and /api/app/managed-parts with the tenant's X-API-Key. JSON in, JSON out. Same brand-permission gating. Useful for tenants who already have an internal export pipeline and want to stream catalog updates on a schedule.
Per-provider adapters: built per relationship
Brands that ship data in formats outside CSV or JSON (XML feeds, custom REST APIs, FTP drops, TecDoc / ACES&PIES dumps, etc.) get a dedicated adapter on the PowersportOS side. The adapter's job is to pull from the source on a configured cadence, normalise the response into our internal data shape, and run it through the same write pipeline the CSV and API paths use.
We don't ship a generic XML importer or a universal format-detection layer. Each adapter is built for one provider, against their actual API or feed, with their actual data quirks accounted for. Realistic build time is roughly one to two weeks per source after the technical conversation with the provider lands.
- When you'd want one
- Your data is in a non-CSV format and you don't want to maintain a CSV export. Or your data updates often enough that scheduled syncs from the source-of-truth make more sense than file uploads. Or you already have a dealer-data API your existing partners use.
- What we need from you
- Technical access to your API or feed (credentials, sandbox if available), documentation of pagination and rate limits, a clear answer on whether IDs are stable across releases, and the recommended polling cadence. We bring the rest of the integration work.
- What you get out
- Your data lands cleanly in PowersportOS under your brand permissions. Every retailer running on PowersportOS sees your catalog in the same structural shape as every other brand. You stay the source of truth; we're a normalised mirror that serves it onward.
The brand-permission gate
Every write to the central catalog, regardless of which ingest path it came in through, is checked against the calling tenant's brand permissions. A data provider can only create, update, or deprecate Part rows under brands they've been granted write access to. This protects the catalog from cross-brand writes and audit-logs every change with the tenant identity attached.
- READ
- Tenant can see central data for this brand but cannot write. Useful for review-only relationships.
- WRITE
- Tenant can create and edit Part rows under this brand. Default role for data providers.
- OWNER
- WRITE plus the right to edit Brand metadata (logo, description, country, website).
Permissions are granted by PowersportOS staff per (tenant, brand) pair from the admin portal. Multiple tenants can hold permissions on the same brand, though the conventional setup is one data provider per brand.
What lifecycle looks like
Data providers don't hard-delete Part rows from the central catalog. A Part that retailers have already activated carries dependencies (their activation rows, fitments, Shopify product mappings, etc.) that get destroyed by a cascade. The right tool when an SKU is going away is the lifecycle status.
- ACTIVE
- Default. Part is current and orderable.
- DEPRECATED
- Still sold, but a successor exists. Storefront shows a 'Replaced by X' hint when the part links to a successor via replacedById.
- DISCONTINUED
- No longer in production. Retailers keep their activation rows; the storefront can decide how to display.
- DRAFT
- Not yet released. Useful for staging new SKUs before announcement.
A new Part with no retailer activations yet can still be deleted (cleans up a typo on create). Past that point, lifecycle is the path.
What's normalised, what stays as-is
- Country of origin
- Normalised to ISO 3166-1 alpha-2 codes (SE, TW, US, DE). Importer accepts common country names and maps them automatically.
- HS code
- Validated for 6, 8, or 10-digit format. Maps cleanly to Shopify variant.harmonizedSystemCode at push time.
- Description HTML
- Sanitised server-side through a tight whitelist (paragraphs, headings, lists, basic formatting, https-only images). Plain text gets wrapped in paragraphs automatically.
- Year ranges in fitments
- Expand single-year or compressed-range syntax (2020-2024 or 2012-2016,2018-2023) into individual Fitment rows per year.
- Images and manuals
- Source URLs are fetched server-side and mirrored to our object storage. Original URL stored alongside so re-imports dedupe and re-fetch only when needed.
- Part numbers, brand strings, OEM references
- Preserved verbatim. We don't enforce a global SKU schema across providers; brand strings stay as the provider names them, and OEM cross-references are stored per-row.
Cadence and stability
CSV upload is operator-triggered. API push runs whenever the data provider's backend sends it. Per-provider adapters typically run on a daily or hourly schedule, configured per relationship after a conversation with the provider on what their own data cadence supports.
The data shape retailers consume from /api/t/* endpoints is stable across all ingest paths. Catalog rows look identical to a downstream consumer whether the data came from a CSV upload last week or an adapter sync 30 seconds ago.
Related documentation
- Tenant types covers DATA_PROVIDER, MANUFACTURER, DISTRIBUTOR and which surfaces each get.
- Two-layer data model explains where central catalog data lives versus tenant-owned data.
- PIM-Light details the structured product data shape every ingest path normalises into.
- CSV import format covers the column shape, year-range syntax, and quoting rules.