Match Product
Map line-item descriptions to product IDs with substitutes and rationale.
Authorization
bearerAuth OAuth2 client credentials flow. Token obtained from /oauth2/token on the auth host.
In: header
Header Parameters
Caller-supplied correlation ID. Propagated end-to-end and returned in responses and audit logs.
Optional. If reused within 24 hours with the same payload, the cached response is returned. Reuse with a different payload yields 409.
Set to 'respond-async' to receive a 202 Accepted with a job ID instead of a synchronous result.
"respond-async"Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://api.eu.faction.ai/v1/match/product" \ -H "X-Correlation-Id: 8f3c-b21" \ -H "Idempotency-Key: case-CRM-2026-04-29-00417-intent-v1" \ -H "Content-Type: application/json" \ -d '{ "case_id": "string", "line_items": [ {} ] }'{
"matches": [
{
"input_description": "SKF 6205-2RS bearing",
"rubix_product_id": "GB-BRG-6205-2RS",
"quantity": 50,
"confidence_score": 0.98,
"match_rationale": "Manufacturer + part number exact match. Customer ordered same SKU 11 times in last 18 months.",
"alternatives": [
{
"rubix_product_id": "GB-BRG-6205-2Z",
"confidence_score": 0.71,
"reason": "Same series, sealed variant"
}
],
"unmatched_flag": false
},
{
"input_description": "Gates B-section drive belt B72",
"rubix_product_id": "GB-BLT-GATES-B72",
"quantity": 20,
"confidence_score": 0.94,
"match_rationale": "Manufacturer + size + section exact match.",
"alternatives": [],
"unmatched_flag": false
}
],
"unmatched": []
}{
"job_id": "job_01JZP4XYZ123",
"status_url": "/v1/jobs/job_01JZP4XYZ123",
"status": "queued"
}{
"error_code": "MISSING_REQUIRED_FIELD",
"message": "Field 'case_id' is required.",
"correlation_id": "8f3c-b21",
"request_id": "req_01JZP4..."
}{
"error_code": "EXPIRED_TOKEN",
"message": "Bearer token expired at 2026-04-29T13:00:00Z.",
"correlation_id": "8f3c-b21",
"request_id": "req_01JZP4..."
}{
"error_code": "SCOPE_INSUFFICIENT",
"message": "Token lacks scope 'extract.quote'.",
"correlation_id": "8f3c-b21",
"request_id": "req_01JZP4..."
}{
"error_code": "IDEMPOTENCY_KEY_CONFLICT",
"message": "Idempotency key was previously used with a different request payload.",
"correlation_id": "8f3c-b22",
"request_id": "req_01JZP4..."
}{
"error_code": "RATE_LIMITED",
"message": "Per-tenant per-module rate limit exceeded.",
"correlation_id": "8f3c-b21",
"request_id": "req_01JZP4..."
}{
"error_code": "INTERNAL_ERROR",
"message": "An unexpected error occurred.",
"correlation_id": "8f3c-b21",
"request_id": "req_01JZP4..."
}Match paths
The matcher tries multiple paths and returns the strongest. The path that won is reported in match_rationale:
- Manufacturer + part number exact match.
- Manufacturer cross-reference (competitor part to Rubix-stocked equivalent).
- Semantic match (description embeddings against catalogue).
- Historical-pattern match (this customer ordered this SKU before).
- Branch-local override (branch-supplied spreadsheet).
Notes
match_strategy:strict,balanced(default),permissive. Controls how aggressively the matcher returns ambiguous candidates.- Unit-of-measure mismatch (e.g., "box of 50" vs. per-unit catalogue) triggers
unit_conversion_required: truewith a proposed conversion. - Discontinued SKU with a successor mapped: returns the successor with rationale.
- Line-item count over 200 should use the async pattern.