Product catalog
Your product catalog is the list of manufacturer partners you represent and the products underneath each one. It is the most direct evidence Prok has that you can actually supply what a solicitation asks for: when a requirement lines up with a product in your catalog, that lifts the opportunity’s score, and the matched product is named in the reasoning you see on the opportunity.
A profile without a catalog leaves Prok guessing from categories and prose alone. The catalog is where you tell it exactly what you sell.
How the catalog feeds matching
Section titled “How the catalog feeds matching”Two fields on a product decide how much weight it carries.
rep_status says how you supply it:
rep_status |
Meaning |
|---|---|
carried |
You represent or stock the product directly. This is the default. |
catalog |
The manufacturer makes it and you could source it, but supply would have to be arranged. It scores slightly below an otherwise identical carried product. |
status says whether it counts at all:
status |
Meaning |
|---|---|
active |
In your catalog and matched against every opportunity Prok scores. |
discontinued |
Kept on file and visible in the portal, but excluded from matching entirely. |
Only active products are ever considered, so discontinuing one is how you stop it influencing scores without losing the record of it.
Re-scoring
Section titled “Re-scoring”Any catalog change that could move a score queues a background re-score: a new
product, a status or rep_status change, or an edit to a product’s name,
model, description, specs or partner. The re-score waits for the required
product indexing and stages qualifying results for a later digest, rather
than sending an email of its own. Saving a change does not mean indexing or
re-scoring has already finished.
Manufacturer partners
Section titled “Manufacturer partners”Every product belongs to a partner, so a partner has to exist before its first product does.
Listing partners
Section titled “Listing partners”curl "https://app.prokure.ca/api/v1/products/partners" \ -H "Authorization: Bearer $PROKURE_API_KEY"Requires profile:read. Returns every partner ordered by name, each with a
count of its active and discontinued products:
{ "partners": [ { "id": "6f0a1c2d-0000-0000-0000-000000000000", "name": "Vertex Optics", "authorized": true, "relationship": "Authorized reseller, Western Canada", "source_url": "https://example.com/partners/vertex", "active_product_count": 12, "discontinued_product_count": 3, "created_at": "2026-09-01T16:20:00.000Z" } ]}authorized is false for a partner that has been removed from your company
profile. It stays in this list with its products so the removal can be undone,
but no product can be added or moved under it while it is false. Add the partner
again to clear that.
Adding a partner
Section titled “Adding a partner”curl -X POST "https://app.prokure.ca/api/v1/products/partners" \ -H "Authorization: Bearer $PROKURE_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Vertex Optics", "relationship": "Authorized reseller, Western Canada", "source_url": "https://example.com/partners/vertex" }'Requires profile:write. name is 1 to 200 characters; relationship is 1 to
200 characters or null; source_url is a URL or null. A 201 returns the
partner object.
Adding a partner does two things at once. It creates the partner in the
catalog, and it adds the name to manufacturer_partners on your company
profile through the ordinary change history, with source set to
portal_edit. That entry is revertible on the usual terms, so an accidental
addition is undone the same way any other profile change is.
Posting a name that is already yours re-authorizes it rather than creating a
duplicate, and updates relationship and source_url if you send them. That is
also how you clear a partner_not_authorized refusal on a catalog write. It
does not bring back that partner’s discontinued products: reactivating a
product is a separate, deliberate step (see
Discontinuing and reactivating).
Removing a partner
Section titled “Removing a partner”Removal happens on the company profile, not here. Removing a manufacturer partner deactivates that partner’s products in the same change, so they stop counting toward match scores immediately, and reverting the removal brings the partner and exactly those products back. See Removing a manufacturer partner.
Products
Section titled “Products”Adding a product
Section titled “Adding a product”curl -X POST "https://app.prokure.ca/api/v1/products" \ -H "Authorization: Bearer $PROKURE_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "oem_partner_id": "6f0a1c2d-0000-0000-0000-000000000000", "name": "Thermal monocular", "model": "VX-640", "description": "640x480 uncooled thermal monocular, 12 um pitch, NVG-compatible.", "commodity_codes": ["5855"], "specs": { "resolution": "640x480", "weight_g": 380 }, "rep_status": "carried" }'Requires profile:write. A 201 returns the product:
{ "id": "9c31d4e5-0000-0000-0000-000000000000", "oem_partner_id": "6f0a1c2d-0000-0000-0000-000000000000", "oem_name": "Vertex Optics", "name": "Thermal monocular", "model": "VX-640", "description": "640x480 uncooled thermal monocular, 12 um pitch, NVG-compatible.", "commodity_codes": ["5855"], "specs": { "resolution": "640x480", "weight_g": 380 }, "rep_status": "carried", "status": "active", "source": "portal", "source_url": null, "created_at": "2026-09-05T14:03:11.000Z", "updated_at": "2026-09-05T14:03:11.000Z"}The product is saved immediately, with its indexing work retained for background processing. It becomes available to product matching after that indexing succeeds. Temporary indexing failures can be retried without changing the description again; repeated failures may need the Prokure team to investigate.
| Field | Required | Value |
|---|---|---|
oem_partner_id |
Yes | The id of one of your partners, from the partner list. |
name |
Yes | 1 to 200 characters. |
model |
No | 1 to 100 characters, or null. |
description |
No | 1 to 4000 characters, or null. The richer this is, the better a requirement can be matched against it. |
commodity_codes |
No | Up to 50 codes, each 1 to 50 characters. |
specs |
No | A JSON object of your own keys, serialising to at most 8,192 characters of JSON. |
rep_status |
No | carried or catalog. Defaults to carried. |
source_url |
No | A URL or null. |
Three failures are worth handling specifically:
| Status | error |
Meaning |
|---|---|---|
404 |
not_found |
oem_partner_id is not a partner of yours. |
409 |
already_exists |
You already have a product with this partner, name and model. |
409 |
partner_not_authorized |
The partner has been removed from your company profile. Add it again with POST /api/v1/products/partners, which re-authorizes it, before adding products under it. |
Editing a product
Section titled “Editing a product”curl -X PATCH "https://app.prokure.ca/api/v1/products/$ID" \ -H "Authorization: Bearer $PROKURE_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "description": "640x480 uncooled thermal monocular, 12 um pitch, MIL-STD-810H." }'Requires profile:write. Send any subset of the create fields plus status,
which takes active or discontinued. At least one field has to be present,
and a field the endpoint does not define is rejected with
400 validation_failed rather than ignored. A 200 returns the product in the
same shape the create does.
An edit is refused on the same terms a create is, because a rename can move a product onto an identity another product already holds:
| Status | error |
Meaning |
|---|---|---|
404 |
not_found |
No such product, or oem_partner_id is not a partner of yours. |
409 |
already_exists |
The new partner, name and model would collide with another product of yours. Identity is checked against the product as it would stand afterwards, so a field you leave out keeps its current value for that comparison. |
409 |
partner_not_authorized |
The partner you are moving the product to has been removed from your company profile. Add it again first. |
Changing the name, model, description, specs or partner schedules product
indexing for matching. Specs contribute to the product text used to find
candidates and to the evidence supplied for selected candidates. Very large
spec objects are bounded for processing, so do not assume every stored field
reaches the model. Changing only source_url does not change the matching
text.
Discontinuing and reactivating
Section titled “Discontinuing and reactivating”Products are never deleted. A product that has been quoted, matched or drafted against is part of the record of why an opportunity scored the way it did, and deleting it would rewrite that history.
Retire one by discontinuing it instead:
curl -X PATCH "https://app.prokure.ca/api/v1/products/$ID" \ -H "Authorization: Bearer $PROKURE_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "status": "discontinued" }'It disappears from matching immediately and stays in the catalog, counted
under discontinued_product_count on its partner. Setting status back to
active brings it back into scoring.
Importing from a spreadsheet
Section titled “Importing from a spreadsheet”A whole catalog does not have to go in one product at a time.
POST /api/v1/products/import takes a CSV of up to 500 products, validates it
as a unit, and writes partners and products in one transaction. Start from
the template:
curl "https://app.prokure.ca/api/v1/products/import/template" \ -H "Authorization: Bearer $PROKURE_API_KEY" \ -o product-import-template.csvGET /api/v1/products/import/template returns the header row plus one example
row, which is the fastest way to see the shape the import expects. Send the
file with ?dry_run=true first to see what it would create and update before
anything is written.
The import has no specs column and never changes a product’s status, so a
discontinued product stays discontinued through a re-import. Everything the
file does carry is authoritative, blank cells included. See
Importing products from CSV for
the columns, the validation rules and the re-import contract.
Listing and filtering
Section titled “Listing and filtering”curl "https://app.prokure.ca/api/v1/products?status=active&limit=50" \ -H "Authorization: Bearer $PROKURE_API_KEY"Requires profile:read. Products come back newest first:
{ "products": [ { "id": "9c31d4e5-0000-0000-0000-000000000000", "oem_partner_id": "6f0a1c2d-0000-0000-0000-000000000000", "oem_name": "Vertex Optics", "name": "Thermal monocular", "model": "VX-640", "description": "640x480 uncooled thermal monocular, 12 um pitch, NVG-compatible.", "commodity_codes": ["5855"], "specs": { "resolution": "640x480", "weight_g": 380 }, "rep_status": "carried", "status": "active", "source": "portal", "source_url": null, "created_at": "2026-09-05T14:03:11.000Z", "updated_at": "2026-09-05T14:03:11.000Z" } ], "next_cursor": null}| Parameter | Value |
|---|---|
status |
active or discontinued. Both are returned when it is omitted. |
partner_id |
Restrict to one partner. |
q |
Free text, up to 200 characters, matched case-insensitively against name, model and description. |
limit |
1 to 100. Defaults to 50. |
cursor |
The previous page’s next_cursor. |
next_cursor is opaque. Pass it back verbatim as cursor and stop when it
comes back null. Do not decode it or construct one; a malformed cursor is
rejected with 400 validation_failed. Keep the filters identical for every
request in a paging pass. These are the same rules the opportunity list
follows, described in
Filtering and pagination.
In the portal
Section titled “In the portal”Settings has a Product catalog page that does all of the above without the API: partners with their active and discontinued counts, adding a partner, adding and editing products, searching and filtering the list, and discontinuing or reactivating a product. An Import button on the same page loads a catalog from a CSV, with a dry-run preview before anything is written. The Company Profile page’s partner-removal dialog now tells you how many active products the removal will deactivate before you confirm it.
Limits
Section titled “Limits”- Product fields. Name up to 200 characters, model up to 100, description
up to 4000, up to 50 commodity codes of up to 50 characters each, and
specsserialising to at most 8,192 characters of JSON. - Partner fields. Name and relationship up to 200 characters each.
- 60 requests per minute on each read route, 10 per minute on each write route, counted per client IP like every other route. See Rate limits and errors.
Related
Section titled “Related”- List manufacturer partners, Add a manufacturer partner, List catalog products, Add a catalog product, Update a catalog product: full schemas.
- Importing products from CSV: the bulk import, its template, and what a re-import overwrites.
- Editing your company profile: manufacturer partners on the profile, and the partner-removal cascade.
- Company profile: the change history and revert rules that a partner addition lands in.
- Scopes explained.