Documentation
The browser explains and previews; the product CLI and the REST API perform repeatable work. Every page on product.cloud shows the equivalent command and route for what you are looking at.
CLI
brew install product-cloud/tap/product
# or
cargo install product-cliSign in with the browser (OAuth 2.0 Authorization Code with PKCE) or, on headless machines, with the device authorization flow. Refresh tokens are kept in the operating system keychain; commands never embed credentials.
product auth login
product auth login --device
product auth statusproduct clone acme/power-tools-eu --revision 2026.09
product pull acme/power-tools-eu@2026.09 --include products,attributes --market DE
product diff 2026.08..2026.09 --entity product
product query products --where 'brand = "ACME"' --select gtin,mpn,nameproduct sync plan acme/power-tools-eu --target ./mirror
product sync run acme/power-tools-eu --target ./mirror \
--checkpoint .product/checkpoints/mirror.json --resumeREST API
The normative API is REST described by OpenAPI 3.1 at https://api.product.cloud/v1. The web platform uses exactly these routes. Any read can be pinned with ?revision= (branch, release tag, or commit digest).
| Route | Purpose |
|---|---|
/v1/orgs | Organizations, members, roles |
/v1/repos | Repository discovery and creation |
/v1/repos/{namespace}/{repo}/refs · commits · releases | Versions: branches, immutable commits, signed releases |
/v1/repos/{namespace}/{repo}/manifests · objects · assets | Content-addressed artifacts (sha256 digests) |
/v1/repos/{namespace}/{repo}/products/{scheme}:{id} | One product, e.g. products/gtin:04012345678901 |
/v1/repos/{namespace}/{repo}/classes/{code} | One class, e.g. classes/EC004532 |
/v1/repos/{namespace}/{repo}/mappings?source={ns}:{code} | Mappings for a source identifier |
/v1/repos/{namespace}/{repo}/changes?after={cursor} | Change feed for synchronization |
/v1/repos/{namespace}/{repo}/quality · access-requests · query | Quality results, entitlements, constrained queries |
/v1/products/resolve?identifier=gtin:… | Assertions for one identifier across repositories |
/v1/upload-sessions · /v1/jobs · /v1/webhooks · /v1/connectors · /v1/sync-runs | Publishing, long-running jobs, events, integrations |
Conventions
- Cursor pagination for changing collections; cursors are opaque — never derive offsets from them.
- ETag and conditional requests; ref updates use
If-Matchand fail with 409 on a concurrent change. Idempotency-Keyon every retried mutation.- Errors are RFC 9457 problem details with stable
typeURIs and a request ID. - Long operations return a job resource; large bytes move through time-limited object grants.
curl -s "https://api.product.cloud/v1/products/resolve?identifier=gtin:04012345678901"Publishing
Start in the browser with a sample file to get a validated product.yaml draft, then publish the full dataset with the CLI. Pushes upload only missing objects; the hub re-verifies every digest before advancing a ref.
product auth login
product repo create acme/power-tools-eu --type product --restricted
product init --type product
product import bmecat catalog.xml --output data/
product validate
product quality check --policy quality/rules.yaml
product add product.yaml README.md data/ schemas/ quality/
product commit -m "Publish September 2026 catalog"
product push origin main
product release create 2026.09 --sign --notes CHANGELOG.mdFormats
CSV import
Identity columns are gtin (or ean), mpn, brand (or manufacturer), and name. Every other column is an attribute whose header may carry a unit and a language: property[unit]@lang. Empty cells produce no attribute; values are kept verbatim.
gtin,mpn,brand,name,rated_voltage[V],weight[kg],class:etim,description@de,description@en
04012345678901,GSR-18,ACME,Cordless drill driver 18 V,230,2.35,EC004532,Akkubohrschrauber,Cordless drill driverBMEcat 2005 (INTERNATIONAL_PID type="gtin", ETIM features) is imported with product import bmecat. Canonical tables are stored as Parquet; exports include JSONL, CSV, and BMEcat.
Canonical JSON and digests
Commits and manifests are identified by sha256: digests of their canonical JSON: a subset of RFC 8785 with object members sorted by UTF-16 code units, no insignificant whitespace, minimal string escaping, and integers only (decimals travel as strings). The golden vectors in specs/repository/0.1/golden-vectors.json are reproduced by both the Rust implementation and an independent TypeScript verifier; every client should pass them.