Identifying a shoe
The POST /shoe-selection endpoint is a single progressive loop that walks the user through brand, model (or "I don't know"), variant, size system and size. Your caller never needs to know whether the underlying source is a per-product chart or a brand-level fallback chart. The server picks the right path based on what the brand has.
The request
{
"purpose": "ADD_TO_RACK",
"selection": { "answers": [], "metadata": {} }
}
selection.answers is the ordered list of the user's picks so far, one per step. The server replays the whole list on every call, so you never say which step an answer belongs to: you append the id of the option the user picked and send the list back. metadata is optional and is carried through to the finished shoe.
The response
{
"selection": { "answers": ["nike"], "metadata": {} },
"complete": false,
"nextStep": {
"prompt": "Which model?",
"options": [ { "id": "FD2722", "name": "Nike Pegasus 41 Men's Road Running Shoes" }, ... ],
"sizeOptions": null
},
"shoe": null
}
nextStep.promptis the question to show the user.nextStep.optionslists the choices as{ id, name }. Showname; appendid.- On the size step,
optionsisnulland the choices are innextStep.sizeOptionsas{ size, sizeSystem }. Appendsize. - When
completeistrue,nextStepisnullandshoedescribes the identified shoe.
The loop
- Send
"selection": { "answers": [] }. - Show
nextStep.promptand the options. The user picks one. - Append the picked
id(orsize) toanswersand send the request again. - Repeat until
complete: true. - Pass the final
selection(the{ answers, metadata }pair) toPOST /sessions/{id}/shoesasshoe, or toPOST /sessions/{id}/recommendationsastarget. Theshoeobject in the response is for display; the session endpoints do not accept it.
Some steps are skipped when there is only one way to answer them: a brand without per-model charts goes straight from brand to its brand-level charts. Always follow nextStep rather than assuming a fixed number of steps. An answer the server did not offer returns 400 INVALID_INPUT; answers sent after the selection is complete are ignored.
Example: brand with per-product chart
# 1. Start empty
curl -X POST https://www.getsize.shoes/api/public/v1/shoe-selection \
-H "X-Api-Key: $KEY" -H "Content-Type: application/json" \
-d '{"purpose": "ADD_TO_RACK", "selection": {"answers": []}}'
→ prompt "Which brand?", options [{"id": "nike", "name": "Nike"}, ...]
# 2. Pick Nike
curl -X POST https://www.getsize.shoes/api/public/v1/shoe-selection \
-H "X-Api-Key: $KEY" -H "Content-Type: application/json" \
-d '{"purpose": "ADD_TO_RACK", "selection": {"answers": ["nike"]}}'
→ prompt "Which model?", options [..., {"id": "FD2722", ...}, {"id": "", "name": "Don't know / Can't find"}]
# 3. Pick the model, then the variant and the size system
curl -X POST https://www.getsize.shoes/api/public/v1/shoe-selection \
-H "X-Api-Key: $KEY" -H "Content-Type: application/json" \
-d '{"purpose": "ADD_TO_RACK", "selection": {"answers": ["nike", "FD2722", "FD2722-002", "US_MALE"]}}'
→ prompt "Which size?", sizeOptions [{"size": "6", "sizeSystem": "US_MALE"}, ...]
# 4. Pick the size
curl -X POST https://www.getsize.shoes/api/public/v1/shoe-selection \
-H "X-Api-Key: $KEY" -H "Content-Type: application/json" \
-d '{"purpose": "ADD_TO_RACK", "selection": {"answers": ["nike", "FD2722", "FD2722-002", "US_MALE", "10"]}}'
→ complete: true, shoe {"brandId": "nike", "modelId": "FD2722", "size": "10", "lengthMm": 265, ...}
Example: "I don't know" path
# After the brand, answer the empty-id option ("Don't know / Can't find")
curl -X POST https://www.getsize.shoes/api/public/v1/shoe-selection \
-H "X-Api-Key: $KEY" -H "Content-Type: application/json" \
-d '{"purpose": "ADD_TO_RACK", "selection": {"answers": ["nike", ""]}}'
→ prompt asks which of the brand's charts, options [Nike Men's, Nike Women's, ...]
# Continue with the chart, size system and size until complete: true
The finished shoe has modelId and variationId set to "" and globalChartName populated.
Closed-world guarantee
The options list is computed on the server from the actual catalog. You can only pick values we support. This matters especially for LLM-driven clients, since the model cannot hallucinate brand or size names that don't exist.
Recommendation targets
Use purpose: "RECOMMENDATION_TARGET" to walk the same flow for a target shoe. The loop completes once we have enough to look up a size chart. The size step is skipped, since computing the size is the whole point of the recommendation.
End-to-end example: from a fresh session to a size recommendation
A recommendation always runs against a session. The flow is: create session → (optional) store foot measurement → (optional) add shoes the user owns → walk /shoe-selection with RECOMMENDATION_TARGET → pass the completed selection as target.
# 1. Create a session
curl -X POST https://www.getsize.shoes/api/public/v1/sessions \
-H "X-Api-Key: $KEY"
# → { "sessionId": "ses_abc123", ... }
# 2. (Optional) Store foot length
curl -X POST https://www.getsize.shoes/api/public/v1/sessions/ses_abc123/foot-measurement \
-H "X-Api-Key: $KEY" -H "Content-Type: application/json" \
-d '{ "rightFootLengthMm": 268, "leftFootLengthMm": 270 }'
# 3. Walk the wizard for the TARGET shoe
curl -X POST https://www.getsize.shoes/api/public/v1/shoe-selection \
-H "X-Api-Key: $KEY" -H "Content-Type: application/json" \
-d '{ "purpose": "RECOMMENDATION_TARGET", "selection": { "answers": [] } }'
# → nextStep with options. Append each pick to "answers" and call again
# until the response has "complete": true.
# 4. Hand the completed selection to /recommendations as target
curl -X POST https://www.getsize.shoes/api/public/v1/sessions/ses_abc123/recommendations \
-H "X-Api-Key: $KEY" -H "Content-Type: application/json" \
-d '{
"target": {
"answers": ["adidas", "SAMBAU2312", "KZ6720", "EU"],
"metadata": {}
}
}'
# → { "recommendedSize": "44", "sizeSystem": "EU", "confidenceBasis": [ ... ] }
Important: target (and shoe on POST /sessions/{id}/shoes) takes the { answers, metadata } selection from the wizard, not the shoe object it returns and not a free-form { brand, model, gender } object. Walk the wizard first; the server then knows exactly which canonical shoe you mean.