Emotional-AI recommendation API
Every pick explains itself.
One endpoint returns a ranked shortlist across 25+ verticals — and every pick arrives with the sentence that justifies it, in language your users can actually read. No training data, no inference to run, no six-month build.
No key, no signup — the playground runs against the live API.
Noise-cancelling earbuds for a 40-minute subway commute. Under $300.
Why it fits
Thirty decibels of cancellation is the difference between enduring the subway and not noticing it — at $279 you skip flagship features you would never switch on.
- 018-hour battery outlasts the longest commute
- 02$279 — under budget, with room for a case
- 03Multipoint pairing for laptop and phone
Fast mode · grounding off · 3 of 5 shown
Sunday night. I'm wrung out, but I don't want anything dumb.
Why it fits
Two hours at the pace of one man’s ordinary week in Tokyo — it asks nothing of you and still leaves you with something, which is the narrow thing you wanted.
- 01124 minutes, and no plot to hold on to
- 02It ends kindly — nothing to brace for
- 03Wenders, 2023 — quiet by design, not by accident
Fast mode · grounding off · 3 of 5 shown
Dinner for four in Kreuzberg. One vegetarian, and quiet enough to talk.
Why it fits
The vegetarian menu here runs eight courses of its own rather than standing in for the meat one — and the room is a Kreuzberg flat, not a dining hall.
- 01A parallel eight-course vegetarian menu
- 02One star, and still a room you can talk in
- 03Fichtestraße, in the middle of the Kiez
Fast mode · grounding off · 3 of 5 shown
Five days in late October. Warm, walkable, not a resort. Direct from Berlin.
Why it fits
Late October is when Seville stops being unbearable and starts being ideal — mid-twenties by day, the August crowds gone, a centre you cover on foot.
- 01Mid-twenties all week, evenings stay outdoors
- 02Direct from BER, under four hours
- 03A city to stay in, not a resort strip
Fast mode · grounding off · 3 of 5 shown
A shortlist, and why each one is on it.
Each pick comes back with the sentence that justifies it, the factors behind that sentence, and the sources it checked. Your front end renders the reason — it does not have to invent one.
One response object, six fields your UI can use
- item.name
- Sony WF-1000XM5
- item.match_score
-
0.96
- explanation.why_match
- “Thirty decibels of cancellation is the difference between enduring the subway and not noticing it — and at $279 you stop paying for flagship features you would never switch on.”
- explanation.key_factors
- 8-hour battery outlasts the longest commute $279 — under budget, with room for a case Multipoint pairing for laptop and phone at once
- explanation.sources
- meta.latency_ms
- 2412
Clicks record what people did.
They never learn why.
- Context in any shape.
- A sentence, a chat excerpt, a list of past likes, a structured profile, your own catalogue — send what you already have. There is no schema your users have to be flattened into first.
- The reason ships with the pick.
- Not a similarity score. A sentence a person can read, agree with, or reject — which is the only thing that makes a recommendation trustworthy enough to act on.
- Grounded when it matters.
- Turn on grounding and the model verifies availability, price and detail with a live web search before it writes the response. Leave it off when speed matters more than freshness.
- Useful from the first sentence.
- There is no cold start to engineer around. A user who has clicked nothing yet still gets a shortlist, because the model reasons about what they told you rather than what they clicked.
Three requests to production.
- 01 Get a key Free tier, no card, one email field.
- 02 POST your context One endpoint, any vertical, whatever shape your data is already in.
- 03 Render the reason The explanation is already in the payload. No second call, no prompt of your own.
// Every vertical is the same call — only `vertical` changes. const res = await fetch('https://api.tasteray.com/v1/recommend', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-API-Key': process.env.TASTERAY_KEY, }, body: JSON.stringify({ vertical: 'electronics', context: { profile: 'Noise-cancelling earbuds for a ' + '40-minute subway commute.', constraints: { budget_max: 300 }, }, options: { count: 5, fast: true }, }), }); const { recommendations } = await res.json(); // recommendations[0].explanation.why_match // → the sentence you render under the title
# Every vertical is the same call — only `vertical` changes. import os, requests res = requests.post( 'https://api.tasteray.com/v1/recommend', headers={'X-API-Key': os.environ['TASTERAY_KEY']}, json={ 'vertical': 'electronics', 'context': { 'profile': 'Noise-cancelling earbuds for a' ' 40-minute subway commute.', 'constraints': {'budget_max': 300}, }, 'options': {'count': 5, 'fast': True}, }, ) recs = res.json()['recommendations'] # recs[0]['explanation']['why_match']
# Every vertical is the same call — only `vertical` changes. curl -X POST https://api.tasteray.com/v1/recommend \ -H "Content-Type: application/json" \ -H "X-API-Key: $TASTERAY_KEY" \ -d '{ "vertical": "electronics", "context": { "profile": "Noise-cancelling earbuds for a 40-minute subway commute.", "constraints": { "budget_max": 300 } }, "options": { "count": 5, "fast": true } }' # → { "recommendations": [ … ] }
Your vertical is already in there.
Movies and mortgages take the same call. Swap one string and the model brings the domain knowledge with it.
Same endpoint, same response contract — only "vertical" changes
The build-versus-buy question, answered honestly.
- You don't hire for ML.
- No ranking model to train, evaluate or re-train when the catalogue shifts. The reasoning is bought; what you build is the surface your users see.
- You don't collect training data first.
- Collaborative filtering needs a year of behaviour before it earns its keep. This needs one sentence about the person in front of you.
- You don't run inference.
- No GPUs, no vector store, no eval harness on call at 3am. A REST call with rate-limit headers and a stable response contract.
- You choose what you send.
- The API reasons from the context in the request, so pseudonymous profiles work fine and it never needs an identity. What happens to a request after that — processing, retention, the providers involved — is set out in the privacy policy rather than claimed on this page.
And the case against: if your recommendations are your moat, build them.
We'd rather tell you that now than after the invoice. If personalization is table stakes for your product rather than the product itself, this is an afternoon instead of two quarters.
Start free. Pay when it's in production.
Every tier gets every vertical. What changes is throughput and who picks up the phone.
Prototyping and evaluation.
- 1,000 requests / month
- 5 requests / minute
- All verticals
- Community support
A live app with real users.
- 10,000 requests / month
- 50 requests / minute
- All verticals
- Email support
Personalization on the main path.
- 100,000 requests / month
- 200 requests / minute
- Usage analytics
- Priority support
Scale, procurement, compliance.
- Volume pricing
- Custom rate limits
- SLA
- Dedicated support
Questions a skeptic asks first.
- Is this a thin wrapper around a frontier model?
- It's a wrapper with opinions: versioned prompts, per-vertical constraint handling, optional web grounding, and a response contract that stays stable when the model underneath changes. The reasoning is bought. The product around it is the part you'd otherwise build.
- How slow is it, really?
- Fast mode targets a few seconds; grounding trades latency for verified detail. Both are per-request flags, so a search page and a checkout upsell can make different calls. Actual latency comes back on every response — check it against your own path rather than ours.
- What happens when it makes something up?
- Turn grounding on, or pass your own catalogue in the request — the model then ranks and explains the items you sent instead of recalling from memory. For inventory-backed products that second mode is the one to use.
- Where does our data go?
- Requests run at the edge and your context is passed to the AI models that generate the recommendation. Request logs are retained for up to 90 days. You choose what goes in the request — the API works fine with pseudonymous profiles and never needs an identity to reason about a preference. The privacy policy is the binding statement; read it before you send anything regulated.
- What if we outgrow it?
- The response contract is the integration. If you later build in-house, you keep the shape your front end already renders and swap what fills it — which is a smaller migration than the one you’d be starting from today.
See it work before you believe us.
The playground runs the same endpoint your code would. Pick an example, press Run, read the reason it gives you.
No key. No signup. A real response.