Skip to main content

Recommendation engine

Product recommendations for a live conversation: given a customer's phone number and/or their purchase history, the engine returns ranked, in-stock product offers in well under a second.

Base URL: https://recommendation-engine.trywink.io

Authentication

Requests carry an API key in the X-API-Key header. The engine currently validates a dedicated service credential issued by Wink; issuing recommendation_engine-scoped keys from Org Settings → API Keys is rolling out — until then, use the credential Wink provisioned for you.

note

The service sits behind Cloudflare. Use a normal HTTP client user-agent — default library UAs (e.g. raw urllib) can be challenged at the edge.

POST /recommend

Returns ranked recommendations for one customer.

FieldTypeRequiredDefaultNotes
phonestringyesCustomer's number; US 10-digit (a leading 1 is stripped). Send "0000000000" when unavailable.
purchased_skusstring[]no[]Anchor SKUs for the session (e.g. what's being discussed). Unknown SKUs are silently ignored.
num_itemsintno11–10. Values outside → 422.
check_stockboolnotrueFilter to in-stock items.
customer_order_historyobject[]no[{sku?, product_title?, order_date?}]. Supplying it (even []) skips the engine's own history lookup and saves ~0.5–1.5 s.
sourcestringno"IVR"Free-text traffic tag for analytics.
curl -s https://recommendation-engine.trywink.io/recommend \
-H 'Content-Type: application/json' \
-H "X-API-Key: $WINK_API_KEY" \
-d '{
"phone": "2015550100",
"purchased_skus": ["8151583"],
"customer_order_history": [
{"sku": "5066562", "product_title": "white topaz 4.90 ctw sterling silver ring", "order_date": "2026-05-02"}
],
"num_items": 10,
"check_stock": true,
"source": "my-integration"
}'

Response (abridged):

{
"recommendation_id": "0b8c7a4e-9f1d-4c56-a9a1-6d2f8e64c1aa",
"recommendations": [
{
"rank": 1,
"sku": "3086432",
"title": "white topaz sterling silver bracelet",
"web_price": 14.99,
"article_type": "Bracelet",
"size": 7.0,
"rerank_score": 0.9137,
"slot": 1
}
],
"recommendation": { "rank": 1, "sku": "3086432" },
"resolved_purchased": [8151583],
"history_size": 12,
"customer_found": true,
"normalized_phone": "2015550100",
"fallback": false,
"feature_schema_hash": "…",
"artifact_version": "…",
"catalog_version": "…"
}

Notes:

  • recommendation is an alias for the first item and can be null when nothing qualifies.
  • The three trailing hashes identify the model/catalog build that served the request — log them with the recommendation_id if you A/B or debug.
  • customer_found is null when you supplied customer_order_history (the engine didn't look the customer up itself).
  • Sized jewelry (rings, bracelets, bangles) is size-gated: a customer with no purchase history in a sized category receives no offers from it, by design — the engine won't guess a ring size.
  • Stock can be up to ~30 minutes stale.

POST /purchase

Confirms that a recommendation converted, closing the loop for model training and attribution.

curl -s https://recommendation-engine.trywink.io/purchase \
-H 'Content-Type: application/json' \
-H "X-API-Key: $WINK_API_KEY" \
-d '{"phone": "2015550100", "recommendation_id": "0b8c7a4e-…", "purchased_skus": ["3086432"]}'

Response: {"purchase_id": "…", "recommendation_id": "…", "matched_skus": ["3086432"], "converted": true, "recorded": true}. A recommendation_id the engine doesn't know returns 404.

Errors

StatusMeaning
401{"detail": "invalid or missing API key"} — wrong or absent X-API-Key. Do not retry.
404/purchase only: unknown recommendation_id.
422Validation error (num_items out of range, malformed body). Do not retry unchanged.
5xxEngine-side failure. Retry with backoff; the service self-heals.

Performance

  • p50 latency ≈ 0.35 s when customer_order_history is supplied; omitting it adds ~0.5–1.5 s for the lookup.
  • Wink's own clients use a 3-second timeout — treat that as the SLO.
  • Sustained throughput is modest (single-digit req/s); this is a conversational API, not a batch one. Talk to us before bulk workloads.

Availability

GET /health (no auth) returns {"status": "ok" | "degraded", …} and serves HTTP 503 when the engine is unhealthy — suitable for your monitoring.