Guide

# Resolve customers and catalogue

Nothing on a sales document is written by name. Before you can build a single line you need ids — and for catalogue lines, the right id out of four that look alike.

## Customers

List with `companyName` to resolve by name — a case-insensitive contains-match, so compare each hit's full company name before taking its id. List entries are summaries — id, company name, billing address, last order time. If you need the email, contacts, tax identifier or price level, fetch the full record with `GetCustomer`. Cache the id against your own customer record; names get edited, ids do not. `CreateOrder` and `CreateQuote` take `customerId` only: a request that sends `companyName` instead is refused with 501 (`not_implemented`).

## Search first, then drill in

One query across products, kits and flashings, returning minimal ranked hits. Every whitespace-separated word has to match something: a name, a category, a material, or an attribute value such as an item code. Then fetch full detail by the hit's id.

> Result order is relevance-based and can change between identical requests. It is not a stable contract — never cache position, and never auto-pick hit one without a human or an exact item-code match behind it.

## Which id goes on the line

This is the step that trips people up. A product has variant rows; a row has a price at each of your price levels. The line requires the product id; the row and row-price are optional refinements.

| Id | What it identifies |
| --- | --- |
| prod_ | The product. Required on every catalogue line. |
| prodrow_ | One variant, identified by attributes such as thickness and size. Optional — omit to let the server pick. |
| rowprice_ | That variant at one of your price levels. Optional — omit to use the default level. |
| pricelvl_ | The price level itself — Standard, Account. Not a line reference. |
| flashtpl_ | One flashing at one thickness, carrying the colours you can pick from. |

Send `priceLevelId` where `rowPriceId` is expected and it is rejected — different prefixes, deliberately. Omit both and the server picks the default row at your default price level.

## Colour is per line, not per variant

Variant rows are identified by attributes like thickness and size. Colour usually is not one of them — it is chosen per line from the row's `colourOptions`, which come from the material, so every row sharing a material offers the same list. An empty list means the product has no colour choice at all. The same rule applies to flashings, where the selectable colours sit on the template.

## Kits and flashings

Listings are deliberately light: `ListProducts` and `ListKits` leave rows and component trees empty. Call `GetProduct` or `GetKit` for the detail. Flashing templates are one flashing at one thickness — to change thickness you change template, not a field. And when you build a kit line from a template, echo the component's `productName` through: component names are stored as given and are not derived from the product.

---

Source: https://developer.factory.app/guides/resolve-customers-and-catalogue · Factory Sales API v1
