Developer reference

Build on CatalogHub

Keep supplier catalogues in sync from your ERP, propose buyer-specific prices for review, and let AI assistants work with the same catalogue through MCP. Every surface enforces the same verification, relationship and review rules as the CatalogHub app.

First request/api/supplier/v1
curl https://cataloghub.hopshq.com/api/supplier/v1/me \
  -H "Authorization: Bearer $CATALOGHUB_SUPPLIER_KEY"
Products per upsert
500
Maximum REST body
2 MiB
Requests per minute
120

CatalogHub offers three integration surfaces. Suppliers use the REST API or MCP to maintain their own catalogue and propose products to connected buyers. Buying organisations use the separate ordering agent API to search products and build orders.

Proposals are reviewed, never pushed

Editing a supplier catalogue or proposing a price never changes a buyer's live products. Each proposal becomes a catalogue review that the buyer accepts or rejects. Accepted products are published to Hops only through the existing, separate publishing workflow.

Each surface has its own credential. Choose by who is acting and where the integration runs.

Supplier catalogue API

Server-to-server integrations that run unattended, such as an ERP export job.

Credential
Supplier API key, sent as a bearer token
Issued by
A supplier manager or administrator, in Products › Supplier API access
Acts as
The supplier account that owns the key
Lifetime
90 days by default; 1 to 365 days
Endpoint
/api/supplier/v1
API key details

Supplier MCP tools

AI assistants and agent clients acting for a signed-in person.

Credential
OAuth 2.1 access token, obtained with PKCE
Issued by
The signed-in user, on the CatalogHub consent screen
Acts as
That user, within the suppliers they currently belong to
Lifetime
1-hour access token; 30-day rotating refresh token
Endpoint
/api/mcp
OAuth flow

Ordering agent API

Purchasing agents acting for a buying organisation.

Credential
Ordering agent token
Issued by
A buying organisation administrator, in Shopping › Ordering agents
Acts as
The named ordering agent, within its organisation's limits
Lifetime
Set when the agent token is created
Endpoint
/api/agent/v1
Ordering API

Credentials are not interchangeable

Supplier API keys work only on the supplier REST API. OAuth tokens are required for the supplier MCP tools. Ordering agent tokens work only on the ordering API. Never share a credential between systems or embed it in browser code.

Supplier API access is off by default. Complete these steps once per supplier.

  1. Create a supplier account and verify its account email. A CatalogHub administrator then verifies the supplier's identity.
  2. Connect the supplier to each buying organisation and confirm the trade relationship through the existing supplier or administrator workflow.
  3. As a supplier manager or administrator, open Products › Supplier API access, enable access and create a named key with only the scopes you need. Copy the key when it is shown; it cannot be retrieved later.
  4. Store the key in your secret store and send it over HTTPS in the Authorization header. For MCP, connect your assistant instead and approve the requested scopes.
curl https://cataloghub.hopshq.com/api/supplier/v1/me \
  -H "Authorization: Bearer $CATALOGHUB_SUPPLIER_KEY"

Every supplier REST request carries a supplier API key as a bearer token.

Header
Authorization: Bearer chsup_xxxxxxxx…
  • Keys expire after 90 days by default. You can choose between 1 and 365 days when creating a key.
  • A supplier can have up to ten active keys. Give each integration its own named key so it can be revoked independently.
  • CatalogHub stores only a hash of each key and a short display prefix. The full key is shown once, at creation.
  • Every request re-checks that the supplier is verified, API access is enabled, the key owner's email is verified and the owner is still a supplier manager or administrator.
  • Revoking a key or disabling API access stops it immediately. Re-enabling access does not restore old keys.
Key scopes
ScopeAllows
catalog:readRead the supplier’s catalogue, private reference prices, archived products and allergen evidence revisions.
catalog:writeCreate, update, archive and restore products by SKU; submit supplier-attested allergen evidence.
relationships:readRead trade relationships, proposed offers and accepted buyer products and prices.
catalog:publishPropose products, buyer prices and allergen evidence for buyer review. Buyer declaration and Hops approval stay separate.

All supplier endpoints are relative to the base path below and return JSON.

Base URLhttps://cataloghub.hopshq.com/api/supplier/v1

Exact request and response schemas are published in the supplier OpenAPI specification, linked under Resources.

List endpoints use offset pagination.

  • limit accepts 1 to 100 and defaults to 100.
  • offset defaults to 0.
  • Catalogue and relationship lists return total, limit and offset. Keep requesting until offset reaches total.
  • Relationship product reads return offers and accepted products with separate totals, both paged by the same offset. Continue until both totals are exhausted.

Read the supplier's own catalogue to reconcile it with your source system.

  • Without a filter, the response includes private and archived products and the supplier's private reference prices.
  • With visibility=public, only active products explicitly marked public are returned. Private reference prices are still included because the caller is the supplier.
curl "https://cataloghub.hopshq.com/api/supplier/v1/products?limit=100&offset=0" \
  -H "Authorization: Bearer $CATALOGHUB_SUPPLIER_KEY"

curl "https://cataloghub.hopshq.com/api/supplier/v1/products?visibility=public&limit=100&offset=100" \
  -H "Authorization: Bearer $CATALOGHUB_SUPPLIER_KEY"

Send the complete intended state of each product. Products are matched by SKU.

  • SKUs are supplier-scoped, trimmed and case-insensitive. Updating, archiving or restoring a SKU keeps its product ID. Changing a SKU creates another product; archive the previous SKU if needed.
  • Fields replace the stored product. Omitted optional description, pack, unit and sizing fields are cleared.
  • Omitted public visibility becomes private, and omitted active status becomes active. Products you do not send are left unchanged.
  • A batch holds up to 500 products with unique SKUs. Any invalid product rejects the whole batch, so nothing is partially written.
  • Upserting never changes any buyer's catalogue.

Required

skuproductNamecategorybasePrice

Optional

descriptionunitOfMeasurepackSizeisPublicisActivesizingmultipleL1ContainermultipleL1Number
  • Prices are non-negative JSON numbers with at most two decimal places, up to 99,999,999.99.
  • Reference and negotiated prices are net prices per ordering unit. The currency of a buyer-specific price comes from the buying organisation in that relationship.
  • Category is the supplier's own text. During review it is matched to the receiving organisation's active category taxonomy.
  • Structured sizing is optional. Use consistent type and unit pairs (Unit with Units, Weight with Grams, Volume with Millilitres) and the canonical container names.
  • The outer container name and its positive whole-number count must be supplied together.
curl -X PUT https://cataloghub.hopshq.com/api/supplier/v1/products \
  -H "Authorization: Bearer $CATALOGHUB_SUPPLIER_KEY" \
  -H "Content-Type: application/json" \
  -d @products.json

The response returns the stored products, with stable product IDs and prices as decimal strings. Request bodies are limited to 2 MiB.

Relationships connect the supplier to buying organisations. Use them to choose where to propose products and to see what each buyer has accepted.

  • The relationship list includes the buyer, currency, lifecycle status and product counts.
  • A relationship's products separate the latest proposed offers from the products and prices the buyer has accepted.
  • Each buyer receives its own negotiated prices; proposing to one buyer does not affect another.
curl "https://cataloghub.hopshq.com/api/supplier/v1/trade-relationships?limit=100&offset=0" \
  -H "Authorization: Bearer $CATALOGHUB_SUPPLIER_KEY"

curl "https://cataloghub.hopshq.com/api/supplier/v1/trade-relationships/<relationship-id>/products?limit=100&offset=0" \
  -H "Authorization: Bearer $CATALOGHUB_SUPPLIER_KEY"

A publication sends selected products at buyer-specific net prices to one buying organisation as a catalogue review.

  • The supplier must be verified.
  • The relationship must be confirmed: supplier_confirmedadmin_confirmed
  • Its status must be one of: approvedterms_setcatalogue_enabledordering_enabled
  • Every product must belong to the calling supplier and be active.
  • Prospects, inferred or unconfirmed relationships, suspended relationships and company-only relationships cannot receive proposals.
  • An idempotency key is required. Use 8 to 120 letters, numbers, dots, underscores, colons or hyphens.
  • A new proposal returns HTTP 201 with publication, catalogue request and submission IDs and an initial pending review status.
  • An exact retry returns HTTP 200 with the same IDs and marks the result as idempotent. Retries are safe even when they run concurrently.
  • Reusing a key with different items, prices or notes returns HTTP 409.
  • Item order does not affect identity. The returned status describes the initial proposal only; read the relationship's products for the current review status.
curl -X POST https://cataloghub.hopshq.com/api/supplier/v1/trade-relationships/<relationship-id>/publications \
  -H "Authorization: Bearer $CATALOGHUB_SUPPLIER_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: proposal-00000001" \
  -d '{
    "items": [{ "productId": "<product-id-from-upsert>", "price": 4.25 }],
    "notes": "New products and agreed prices for your review."
  }'
  1. Product data and prices are copied into the review. Later catalogue edits do not change it.
  2. The buyer reviews each product; their decisions stay staged until the review is completed.
  3. Completing the review saves the accepted products and prices to the buyer's catalogue.
  4. Publishing to Hops remains a separate step and still requires the supplier link, category and account mapping, tax mapping and sizing checks.

No automatic Hops publication

Neither the REST API nor MCP pushes products to Hops. Accepted products reach Hops only through the existing publishing workflow.

The primary catalogue holds every supplier product. Mark selected items isPublic for the public base catalogue; basePrice is standard RRP excluding tax per ordering unit. Anonymous public discovery still excludes prices. A customer catalogue stores selected primary products and one percentage-off-RRP tier for a confirmed trade relationship.

Send revision 0 to create; use the returned revision for edits. discountedProductIds: null discounts all shared items; an array discounts only that subset. Other shared items keep RRP. Use 0–100%, at most two decimal places. Prices round half up to cents. There are no quantity tiers or currency conversions.

Request body
{
  "revision": 0,
  "name": "Customer standard",
  "productIds": [
    "<shared-product-id>",
    "<second-shared-product-id>"
  ],
  "discountPercent": 10,
  "discountedProductIds": [
    "<shared-product-id>"
  ]
}
curl -X PUT https://cataloghub.hopshq.com/api/supplier/v1/trade-relationships/<relationship-id>/catalogue \
  -H "Authorization: Bearer $CATALOGHUB_SUPPLIER_KEY" -H "Content-Type: application/json" -d @customer-catalogue.json

curl https://cataloghub.hopshq.com/api/supplier/v1/trade-relationships/<relationship-id>/catalogue/preview \
  -H "Authorization: Bearer $CATALOGHUB_SUPPLIER_KEY"

curl -X POST https://cataloghub.hopshq.com/api/supplier/v1/trade-relationships/<relationship-id>/catalogue/publications \
  -H "Authorization: Bearer $CATALOGHUB_SUPPLIER_KEY" -H "Content-Type: application/json" -H "Idempotency-Key: customer-00000001" \
  -d '{"previewHash":"<hash-from-preview>"}'

Customer catalogues and pricing tiers

Save the selection, GET its preview, then POST previewHash to catalogue/publications with Idempotency-Key. Changed source products or tiers return 409 until reviewed again. The exact retry returns the same review. Saving or publishing never changes accepted buyer products automatically, withdraws omitted items, declares allergens or writes to Hops. Unchanged selected products can also be proposed for reconfirmation.

POST imports/file-preview with a CSV/XLS/XLSX file, or imports/preview with JSON products. Neither saves products. Ambiguous file headers return mappingRequired; resubmit a mapping from source headers to canonical fields. Correct returned products and row issues, then POST imports/commit with baseline, products and Idempotency-Key. Omitted fields retain existing metadata and visibility; new products default private. Stale baselines return 409. Commit is atomic and exact retries return the original products.

curl -X POST https://cataloghub.hopshq.com/api/supplier/v1/imports/file-preview \
  -H "Authorization: Bearer $CATALOGHUB_SUPPLIER_KEY" -F 'file=@supplier-catalogue.csv'

curl -X POST https://cataloghub.hopshq.com/api/supplier/v1/imports/commit \
  -H "Authorization: Bearer $CATALOGHUB_SUPPLIER_KEY" -H "Content-Type: application/json" -H "Idempotency-Key: import-00000001" \
  -d @reviewed-import.json

Store reusable supplier-attested evidence against an exact supplier product. Supplier identity verification does not independently verify allergen content. Each immutable revision records the source reference, exact wording, submitting account and SHA-256 hash.

Allergen evidence and buyer declarations

Use the fourteen canonical allergen codes. Contains and declared-not-present answer the Contains question; May contain is a separate precautionary warning. Complete evidence needs an explicit Contains answer for all fourteen. Partial evidence is allowed; omitted allergens stay unknown. Free-from and threshold claims require the existing human review process.
curl -X POST https://cataloghub.hopshq.com/api/supplier/v1/products/<product-id>/allergen-evidence \
  -H "Authorization: Bearer $CATALOGHUB_SUPPLIER_KEY" \
  -H "Idempotency-Key: allergen-00000001" \
  -H "Content-Type: application/json" \
  -d @allergen-evidence.json
Allergen evidence and buyer declarations
{
  "supplierAttested": true,
  "source": {
    "reference": "<supplier-specification-reference>",
    "description": "<source-description>",
    "issuedOn": "2026-10-14"
  },
  "completeness": "partial",
  "statements": [
    {
      "allergenCode": "milk",
      "statementType": "contains",
      "exactText": "<exact-source-wording>"
    }
  ]
}

After the buyer accepts a catalogue item, share a selected evidence revision with its exact accepted product ID. Up to 100 items per evidence publication. The buyer opens Supplier requests in Allergens, reviews the source and product match, confirms statements and closes the declaration. Hops then requires its separate mapped-product preview and human approval.

Share selected revisions for the buyer’s declaration review.
{
  "items": [
    {
      "productId": "<supplier-product-id>",
      "revisionId": "<evidence-revision-id>",
      "restaurantCatalogItemId": "<accepted-buyer-product-id>"
    }
  ]
}

No automatic Hops publication

A new supplier revision leaves accepted buyer declarations and Hops unchanged. Publish the new revision for a new review. Evidence is private; the anonymous public catalogue does not expose it. Supplier API keys and MCP tools cannot sign buyer declarations or authorise Hops allergen writes.

Anyone can discover a verified supplier's public listings without credentials.

  • No authentication is required. Pagination works the same way as the supplier API.
  • Only active products explicitly marked public are returned, and every price field is excluded.
  • Public visibility is optional. Private products can still be proposed to connected buyers.
REST (curl)
curl "https://cataloghub.hopshq.com/api/public/suppliers/<supplier-id>/catalog?limit=100&offset=0"

Errors include an English message, a stable machine code and a message key for localised display. Handle them by code, not by message text.

Errors and limits
StatusMeaning
400Invalid fields, category or sizing mapping, or a missing or malformed idempotency key.
401The key is missing, invalid, expired, revoked or no longer authorised.
403The key lacks the required scope, or the supplier is not verified or API access is disabled.
404The relationship or product does not exist for this supplier.
409The relationship is inactive, an assignment conflicts, or an idempotency key was reused with different content.
413The request body is larger than 2 MiB.
429Rate limit exceeded. Wait and retry with backoff.
  • Up to 500 products per upsert.
  • Request bodies up to 2 MiB.
  • Up to 120 requests per minute on the bearer API.
  • Up to 100 results per page.
  • Authenticated responses are sent with Cache-Control: no-store. Do not cache them in shared caches.

The CatalogHub Model Context Protocol server lets AI assistants read and update a supplier catalogue and propose products, on behalf of the person who connected it.

  • Endpoint: https://cataloghub.hopshq.com/api/mcp
  • Streamable HTTP with stateless JSON responses. Send JSON-RPC 2.0 requests with POST.
  • Call it from your assistant or server. Browser requests from other websites are rejected.
  • Tools apply the same validation, limits and review workflow as the REST API.
curl https://cataloghub.hopshq.com/api/mcp \
  -H "Authorization: Bearer $CATALOGHUB_OAUTH_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d @request.json

Most MCP clients perform discovery, sign-in, initialisation and tool listing automatically when you add the endpoint URL. The raw requests are shown for clients you build yourself.

MCP access is bound to a CatalogHub user. The assistant never sees the user's password or a supplier API key.

  1. Discover the authorisation server from the protected resource metadata.
  2. Register your client dynamically with its redirect URIs, or reuse an existing registration.
  3. Create a random code verifier and send its SHA-256 challenge (S256) with the requested scopes and the MCP resource.
  4. The user signs in to CatalogHub and approves or declines the requested access on the consent screen.
  5. Exchange the authorisation code and verifier for an access token and refresh token.
  6. Send the access token as a bearer token to the MCP endpoint, refresh it when it expires, and revoke it when access is no longer needed.
curl https://cataloghub.hopshq.com/.well-known/oauth-protected-resource/api/mcp
curl https://cataloghub.hopshq.com/.well-known/oauth-authorization-server
  • Access tokens are valid for 1 hour.
  • Refresh tokens last 30 days and rotate: each refresh returns a new refresh token. Reusing an old refresh token revokes the connection.
  • Disconnect from the Connect an AI agent panel in CatalogHub, or revoke a token at the revocation endpoint.
  • Redirect URIs must use HTTPS, HTTP on a loopback address, or a native app's private scheme.

Request only the scopes the assistant needs. Each OAuth scope mirrors a supplier API key scope.

OAuth scopes
OAuth scopeREST key scopeAllows
supplier:catalog:readcatalog:readRead the supplier’s catalogue, private reference prices, archived products and allergen evidence revisions.
supplier:catalog:writecatalog:writeCreate, update, archive and restore products by SKU; submit supplier-attested allergen evidence.
supplier:relationships:readrelationships:readRead trade relationships, proposed offers and accepted buyer products and prices.
supplier:catalog:publishcatalog:publishPropose products, buyer prices and allergen evidence for buyer review. Buyer declaration and Hops approval stay separate.

The consent screen shows read access, product changes and buyer proposals as separate choices, with changes and proposals unchecked by default. Existing connections never gain new scopes automatically; reconnect to grant supplier permissions.

Every supplier tool takes a supplier_id. First call cataloghub_list_my_accounts, granted with the feedback scope, to find the suppliers the signed-in user can act for. tools/list returns only the tools your token’s scopes allow. Argument names use snake_case; product and item objects use the same camelCase fields as the REST API.

Lists the buying organisations, suppliers and reseller accounts the signed-in user can use, with their role in each. Use it to find supplier IDs.

OAuth scope
feedback

This tool takes no arguments.

tools/call request
{
  "jsonrpc": "2.0",
  "id": 10,
  "method": "tools/call",
  "params": {
    "name": "cataloghub_list_my_accounts",
    "arguments": {}
  }
}

Lists the supplier's catalogue, one page at a time, including private reference prices.

OAuth scope
supplier:catalog:read
REST equivalent
GET /api/supplier/v1/products
Arguments for cataloghub_list_supplier_catalog
ArgumentRequiredDescription
supplier_idRequiredID of a supplier the signed-in user currently belongs to. Product changes and proposals need a manager or administrator.
limitOptionalPage size, from 1 to 100. Defaults to 100.
offsetOptionalNumber of results to skip. Defaults to 0.
visibilityOptionalall (the default) returns the full catalogue; public returns only active public listings.
tools/call request
{
  "jsonrpc": "2.0",
  "id": 11,
  "method": "tools/call",
  "params": {
    "name": "cataloghub_list_supplier_catalog",
    "arguments": {
      "supplier_id": "<supplier-id>",
      "limit": 100,
      "offset": 0,
      "visibility": "public"
    }
  }
}

Creates or updates up to 500 products by SKU in one atomic batch. Buyer catalogues do not change.

OAuth scope
supplier:catalog:write
REST equivalent
PUT /api/supplier/v1/products
Arguments for cataloghub_upsert_supplier_products
ArgumentRequiredDescription
supplier_idRequiredID of a supplier the signed-in user currently belongs to. Product changes and proposals need a manager or administrator.
productsRequiredArray of up to 500 product objects, with the same fields as the REST upsert.
tools/call request
{
  "jsonrpc": "2.0",
  "id": 12,
  "method": "tools/call",
  "params": {
    "name": "cataloghub_upsert_supplier_products",
    "arguments": {
      "supplier_id": "<supplier-id>",
      "products": [
        {
          "sku": "ONIONS-1KG",
          "productName": "Onions 1kg",
          "description": "Fresh onions",
          "category": "Vegetables",
          "unitOfMeasure": "kg",
          "packSize": 1,
          "basePrice": 9,
          "isPublic": true,
          "isActive": true,
          "sizing": {
            "baseUomType": "Weight",
            "baseUom": "Grams",
            "baseNumber": 1000,
            "baseContainer": "Bag"
          }
        }
      ]
    }
  }
}

Lists the supplier's trade relationships with buyer, currency, status and product counts.

OAuth scope
supplier:relationships:read
REST equivalent
GET /api/supplier/v1/trade-relationships
Arguments for cataloghub_list_supplier_trade_relationships
ArgumentRequiredDescription
supplier_idRequiredID of a supplier the signed-in user currently belongs to. Product changes and proposals need a manager or administrator.
limitOptionalPage size, from 1 to 100. Defaults to 100.
offsetOptionalNumber of results to skip. Defaults to 0.
tools/call request
{
  "jsonrpc": "2.0",
  "id": 13,
  "method": "tools/call",
  "params": {
    "name": "cataloghub_list_supplier_trade_relationships",
    "arguments": {
      "supplier_id": "<supplier-id>",
      "limit": 100,
      "offset": 0
    }
  }
}

Returns the proposed offers and the accepted products and prices for one relationship.

OAuth scope
supplier:relationships:read
REST equivalent
GET /api/supplier/v1/trade-relationships/{relationshipId}/products
Arguments for cataloghub_get_supplier_trade_catalog
ArgumentRequiredDescription
supplier_idRequiredID of a supplier the signed-in user currently belongs to. Product changes and proposals need a manager or administrator.
relationship_idRequiredTrade relationship ID from the relationship list.
limitOptionalPage size, from 1 to 100. Defaults to 100.
offsetOptionalNumber of results to skip. Defaults to 0.
tools/call request
{
  "jsonrpc": "2.0",
  "id": 14,
  "method": "tools/call",
  "params": {
    "name": "cataloghub_get_supplier_trade_catalog",
    "arguments": {
      "supplier_id": "<supplier-id>",
      "relationship_id": "<relationship-id>",
      "limit": 100,
      "offset": 0
    }
  }
}

Proposes products at buyer-specific net prices for the buyer's review. Requires an idempotency key.

OAuth scope
supplier:catalog:publish
REST equivalent
POST /api/supplier/v1/trade-relationships/{relationshipId}/publications
Arguments for cataloghub_publish_supplier_products
ArgumentRequiredDescription
supplier_idRequiredID of a supplier the signed-in user currently belongs to. Product changes and proposals need a manager or administrator.
relationship_idRequiredTrade relationship ID from the relationship list.
itemsRequiredArray of objects with productId and the proposed net price per ordering unit.
notesOptionalOptional message shown to the buyer with the review.
idempotency_keyRequired8 to 120 letters, numbers, dots, underscores, colons or hyphens. Reuse it only to retry the identical proposal.
tools/call request
{
  "jsonrpc": "2.0",
  "id": 15,
  "method": "tools/call",
  "params": {
    "name": "cataloghub_publish_supplier_products",
    "arguments": {
      "supplier_id": "<supplier-id>",
      "relationship_id": "<relationship-id>",
      "items": [
        {
          "productId": "<product-id-from-upsert>",
          "price": 4.25
        }
      ],
      "notes": "New products and agreed prices for your review.",
      "idempotency_key": "proposal-00000001"
    }
  }
}

Read immutable allergen evidence revisions for a supplier product.

OAuth scope
supplier:catalog:read
REST equivalent
GET /api/supplier/v1/products/{productId}/allergen-evidence
Arguments for cataloghub_list_supplier_allergen_evidence
ArgumentRequiredDescription
supplier_idRequiredID of a supplier the signed-in user currently belongs to. Product changes and proposals need a manager or administrator.
product_idRequiredExact supplier product identifier returned by the catalogue.
limitOptionalPage size, from 1 to 100. Defaults to 100.
offsetOptionalNumber of results to skip. Defaults to 0.
tools/call request
{
  "jsonrpc": "2.0",
  "id": 16,
  "method": "tools/call",
  "params": {
    "name": "cataloghub_list_supplier_allergen_evidence",
    "arguments": {
      "supplier_id": "<supplier-id>",
      "product_id": "<product-id>",
      "limit": 100,
      "offset": 0
    }
  }
}

Submit a new supplier-attested allergen evidence revision.

OAuth scope
supplier:catalog:write
REST equivalent
POST /api/supplier/v1/products/{productId}/allergen-evidence
Arguments for cataloghub_submit_supplier_allergen_evidence
ArgumentRequiredDescription
supplier_idRequiredID of a supplier the signed-in user currently belongs to. Product changes and proposals need a manager or administrator.
product_idRequiredExact supplier product identifier returned by the catalogue.
evidenceRequiredSource reference, exact statements, completeness and explicit supplier attestation.
idempotency_keyRequired8 to 120 letters, numbers, dots, underscores, colons or hyphens. Reuse it only to retry the identical proposal.
tools/call request
{
  "jsonrpc": "2.0",
  "id": 17,
  "method": "tools/call",
  "params": {
    "name": "cataloghub_submit_supplier_allergen_evidence",
    "arguments": {
      "supplier_id": "<supplier-id>",
      "product_id": "<product-id>",
      "evidence": {
        "supplierAttested": true,
        "source": {
          "reference": "<supplier-specification-reference>",
          "description": "<source-description>",
          "issuedOn": "2026-10-14"
        },
        "completeness": "partial",
        "statements": [
          {
            "allergenCode": "milk",
            "statementType": "contains",
            "exactText": "<exact-source-wording>"
          }
        ]
      },
      "idempotency_key": "allergen-00000001"
    }
  }
}

Share selected revisions for the buyer’s declaration review.

OAuth scope
supplier:catalog:publish
REST equivalent
POST /api/supplier/v1/trade-relationships/{relationshipId}/allergen-publications
Arguments for cataloghub_publish_supplier_allergen_evidence
ArgumentRequiredDescription
supplier_idRequiredID of a supplier the signed-in user currently belongs to. Product changes and proposals need a manager or administrator.
relationship_idRequiredTrade relationship ID from the relationship list.
itemsRequiredExact supplier product, evidence revision and accepted buyer product identifiers.
idempotency_keyRequired8 to 120 letters, numbers, dots, underscores, colons or hyphens. Reuse it only to retry the identical proposal.
tools/call request
{
  "jsonrpc": "2.0",
  "id": 18,
  "method": "tools/call",
  "params": {
    "name": "cataloghub_publish_supplier_allergen_evidence",
    "arguments": {
      "supplier_id": "<supplier-id>",
      "relationship_id": "<relationship-id>",
      "items": [
        {
          "productId": "<supplier-product-id>",
          "revisionId": "<evidence-revision-id>",
          "restaurantCatalogItemId": "<accepted-buyer-product-id>"
        }
      ],
      "idempotency_key": "allergen-00000002"
    }
  }
}

Read customer catalogue

OAuth scope
supplier:relationships:read
REST equivalent
GET /api/supplier/v1/trade-relationships/{relationshipId}/catalogue
Arguments for cataloghub_get_customer_catalogue
ArgumentRequiredDescription
supplier_idRequiredID of a supplier the signed-in user currently belongs to. Product changes and proposals need a manager or administrator.
relationship_idRequiredTrade relationship ID from the relationship list.
tools/call request
{
  "jsonrpc": "2.0",
  "id": 19,
  "method": "tools/call",
  "params": {
    "name": "cataloghub_get_customer_catalogue",
    "arguments": {
      "supplier_id": "<supplier-id>",
      "relationship_id": "<relationship-id>"
    }
  }
}

Save customer selection and tier

OAuth scope
supplier:catalog:write
REST equivalent
PUT /api/supplier/v1/trade-relationships/{relationshipId}/catalogue
Arguments for cataloghub_save_customer_catalogue
ArgumentRequiredDescription
supplier_idRequiredID of a supplier the signed-in user currently belongs to. Product changes and proposals need a manager or administrator.
relationship_idRequiredTrade relationship ID from the relationship list.
catalogueRequiredSaved selection and percentage tier, including the last revision.
tools/call request
{
  "jsonrpc": "2.0",
  "id": 20,
  "method": "tools/call",
  "params": {
    "name": "cataloghub_save_customer_catalogue",
    "arguments": {
      "supplier_id": "<supplier-id>",
      "relationship_id": "<relationship-id>",
      "catalogue": {
        "revision": 0,
        "name": "Customer standard",
        "productIds": [
          "<product-id>"
        ],
        "discountPercent": 10,
        "discountedProductIds": null
      }
    }
  }
}

Preview customer prices

OAuth scope
supplier:relationships:read
REST equivalent
GET /api/supplier/v1/trade-relationships/{relationshipId}/catalogue/preview
Arguments for cataloghub_preview_customer_catalogue
ArgumentRequiredDescription
supplier_idRequiredID of a supplier the signed-in user currently belongs to. Product changes and proposals need a manager or administrator.
relationship_idRequiredTrade relationship ID from the relationship list.
tools/call request
{
  "jsonrpc": "2.0",
  "id": 21,
  "method": "tools/call",
  "params": {
    "name": "cataloghub_preview_customer_catalogue",
    "arguments": {
      "supplier_id": "<supplier-id>",
      "relationship_id": "<relationship-id>"
    }
  }
}

Propose saved catalogue for buyer review

OAuth scope
supplier:catalog:publish
REST equivalent
POST /api/supplier/v1/trade-relationships/{relationshipId}/catalogue/publications
Arguments for cataloghub_publish_customer_catalogue
ArgumentRequiredDescription
supplier_idRequiredID of a supplier the signed-in user currently belongs to. Product changes and proposals need a manager or administrator.
relationship_idRequiredTrade relationship ID from the relationship list.
previewHashRequiredExact hash returned by the price preview.
notesOptionalOptional message shown to the buyer with the review.
idempotency_keyRequired8 to 120 letters, numbers, dots, underscores, colons or hyphens. Reuse it only to retry the identical proposal.
tools/call request
{
  "jsonrpc": "2.0",
  "id": 22,
  "method": "tools/call",
  "params": {
    "name": "cataloghub_publish_customer_catalogue",
    "arguments": {
      "supplier_id": "<supplier-id>",
      "relationship_id": "<relationship-id>",
      "previewHash": "<hash-from-preview>",
      "idempotency_key": "customer-00000001"
    }
  }
}

Preview import without saving

OAuth scope
supplier:catalog:write
REST equivalent
POST /api/supplier/v1/imports/preview
Arguments for cataloghub_preview_supplier_import
ArgumentRequiredDescription
supplier_idRequiredID of a supplier the signed-in user currently belongs to. Product changes and proposals need a manager or administrator.
productsRequiredArray of up to 500 product objects, with the same fields as the REST upsert.
tools/call request
{
  "jsonrpc": "2.0",
  "id": 23,
  "method": "tools/call",
  "params": {
    "name": "cataloghub_preview_supplier_import",
    "arguments": {
      "supplier_id": "<supplier-id>",
      "products": [
        {
          "sku": "ONIONS-1KG",
          "productName": "Onions 1kg",
          "description": "Fresh onions",
          "category": "Vegetables",
          "unitOfMeasure": "kg",
          "packSize": 1,
          "basePrice": 9,
          "isPublic": true,
          "isActive": true,
          "sizing": {
            "baseUomType": "Weight",
            "baseUom": "Grams",
            "baseNumber": 1000,
            "baseContainer": "Bag"
          }
        }
      ]
    }
  }
}

Save reviewed import

OAuth scope
supplier:catalog:write
REST equivalent
POST /api/supplier/v1/imports/commit
Arguments for cataloghub_commit_supplier_import
ArgumentRequiredDescription
supplier_idRequiredID of a supplier the signed-in user currently belongs to. Product changes and proposals need a manager or administrator.
baselineRequiredCatalogue baseline returned by the import preview.
productsRequiredArray of up to 500 product objects, with the same fields as the REST upsert.
idempotency_keyRequired8 to 120 letters, numbers, dots, underscores, colons or hyphens. Reuse it only to retry the identical proposal.
tools/call request
{
  "jsonrpc": "2.0",
  "id": 24,
  "method": "tools/call",
  "params": {
    "name": "cataloghub_commit_supplier_import",
    "arguments": {
      "supplier_id": "<supplier-id>",
      "baseline": "<baseline-from-preview>",
      "products": [
        {
          "sku": "ONIONS-1KG",
          "productName": "Onions 1kg",
          "description": "Fresh onions",
          "category": "Vegetables",
          "unitOfMeasure": "kg",
          "packSize": 1,
          "basePrice": 9,
          "isPublic": true,
          "isActive": true,
          "sizing": {
            "baseUomType": "Weight",
            "baseUom": "Grams",
            "baseNumber": 1000,
            "baseContainer": "Bag"
          }
        }
      ],
      "idempotency_key": "import-00000001"
    }
  }
}

MCP tools act as the signed-in user, never as a broader service account.

  • Tools work only for suppliers the user currently belongs to directly. Reading needs any verified member; product changes and proposals need a manager or administrator.
  • Supplier tools require OAuth. Supplier REST keys and personal MCP access tokens cannot use them.
  • Membership, roles and supplier status are checked live on every call. Removing a user from a supplier stops access immediately, even if their token has not expired.
  • Reseller access and support impersonation never grant supplier tool authority, and administrators’ view-as sessions do not carry over to tokens.
  • The existing rules still apply: the user’s email and the supplier must be verified, and Supplier API access must be enabled.
  • Proposals follow the same relationship eligibility, idempotency and buyer review rules as the REST API.
  • No tool publishes to Hops or changes a buyer's live catalogue directly.

Buying organisations can let a purchasing agent search their suppliers' products, build baskets and, when permitted, submit orders. This API is separate from the supplier catalogue API.

  • A buying organisation administrator creates the agent and gives it a dedicated ordering agent token.
  • Agents either propose baskets for people to review and send, or submit orders within spending limits and approval thresholds.
  • Agents see only suppliers and products that the organisation can already order from.

REST only

Ordering is available through the REST ordering API, documented by its own OpenAPI specification. The supplier MCP tools on this page do not place orders.
REST (curl)
curl "https://cataloghub.hopshq.com/api/agent/v1/products?q=olive%20oil" \
  -H "Authorization: Bearer $CATALOGHUB_ORDERING_AGENT_TOKEN"
Read the ordering agent overview