Your first size recommendation
Create a merchant, connect a store and complete one sizing session.
0. Run the complete example
In the metr_api repository, copy .env.example to .env, replace the local database password and bootstrap key, then run docker compose up --build. Set BOOTSTRAP_KEY in your shell to the same local value. The standard-library Python example creates fictional tops, trousers, a dress and shoes, runs the quiz, accepts each recommendation and reports purchases and return/kept outcomes.
docker compose up --build
# In another terminal, load BOOTSTRAP_KEY securely from your local .env.
export METR_API_URL=http://localhost:8080
python3 scripts/demo.pyThe requests below show that flow step by step. Set STORE_ID, CHART_ID, PRODUCT_ID and SESSION_ID from each response. Replace placeholder IDs inside JSON bodies before sending; single-quoted JSON does not expand shell variables.
1. Create a merchant
Only the Metr operator uses the bootstrap credential. A store developer receives a merchant admin key through a secure channel; they must never receive the operator key. The response contains merchant.id and api_key.secret. Save that secret as METR_API_KEY; it is returned only once.
curl --fail-with-body -X POST "$METR_API_URL/v1/merchants" \
-H "Authorization: Bearer $BOOTSTRAP_KEY" \
-H 'Content-Type: application/json' \
--data '{
"name": "Example Fashion"
}'2. Connect a store
curl --fail-with-body -X POST "$METR_API_URL/v1/stores" \
-H "Authorization: Bearer $METR_API_KEY" \
-H 'Content-Type: application/json' \
--data '{
"name": "Example store",
"domain": "https://shop.example.com"
}'Save the returned id as STORE_ID. Create a store-scoped backend key with catalog, fit and events permissions for the integration; keep the merchant admin key in your operator tooling.
3. Add the approved size chart
This example uses full garment chest circumferences. Customer answers are body centimetres. The merchant must check the measurements before setting verified=true.
curl --fail-with-body -X POST "$METR_API_URL/v1/stores/$STORE_ID/size-charts" \
-H "Authorization: Bearer $METR_API_KEY" \
-H 'Content-Type: application/json' \
--data '{
"name": "Shirt chart",
"category": "tops",
"unit": "cm",
"basis": "garment",
"verified": true,
"measurements": [
{
"name": "chest",
"method": "circumference"
}
],
"rows": [
{
"size": "S",
"measurements": {
"chest": {
"min": 100,
"max": 100
}
}
},
{
"size": "M",
"measurements": {
"chest": {
"min": 104,
"max": 104
}
}
},
{
"size": "L",
"measurements": {
"chest": {
"min": 108,
"max": 108
}
}
}
]
}'4. Sync a product and variants
curl --fail-with-body -X POST "$METR_API_URL/v1/stores/$STORE_ID/products" \
-H "Authorization: Bearer $METR_API_KEY" \
-H 'Content-Type: application/json' \
--data '{
"external_id": "linen-shirt",
"title": "Linen camp-collar shirt",
"product_type": "shirt",
"gender": "unisex",
"garment_fit": "regular",
"stretch": "none",
"size_chart_id": "REPLACE_WITH_CHART_ID"
}'curl --fail-with-body -X POST "$METR_API_URL/v1/stores/$STORE_ID/products/$PRODUCT_ID/variants" \
-H "Authorization: Bearer $METR_API_KEY" \
-H 'Content-Type: application/json' \
--data '{
"external_id": "shirt-m-black",
"size": "M",
"color": "black",
"available": true
}'Create S and L variants in the same way if they are available. Save the product id as PRODUCT_ID. Variant sizes must exactly match chart labels.
5. Request the questionnaire and start a session
curl --fail-with-body -X GET "$METR_API_URL/v1/stores/$STORE_ID/products/$PRODUCT_ID/fit-questionnaire" \
-H "Authorization: Bearer $METR_API_KEY"curl --fail-with-body -X POST "$METR_API_URL/v1/stores/$STORE_ID/fit-sessions" \
-H "Authorization: Bearer $METR_API_KEY" \
-H 'Content-Type: application/json' \
--data '{
"product_id": "REPLACE_WITH_PRODUCT_ID",
"color": "black",
"customer_reference": "opaque-customer-reference"
}'Use the questionnaire returned by session creation to render the quiz. It is frozen with that session’s chart revision. Save id as SESSION_ID.
6. Run the adaptive quiz
curl --fail-with-body -X POST "$METR_API_URL/v1/stores/$STORE_ID/fit-sessions/$SESSION_ID/next-question" \
-H "Authorization: Bearer $METR_API_KEY" \
-H 'Content-Type: application/json' \
--data '{
"answers": {
"usual_size": "M"
},
"skipped": [
"height_cm"
]
}'Send the answers so far and any skipped question IDs. The response is either the next question to show or done=true, with the current estimate. Repeat until done; the quiz asks the question that most reduces uncertainty about the size and stops once one size is clearly most likely.
7. Submit answers
curl --fail-with-body -X POST "$METR_API_URL/v1/stores/$STORE_ID/fit-sessions/$SESSION_ID/recommendations" \
-H "Authorization: Bearer $METR_API_KEY" \
-H 'Content-Type: application/json' \
--data '{
"answers": {
"usual_size": "M",
"size_consistency": "consistent",
"preferred_fit": "regular",
"measurements": {
"chest": 98
}
}
}'The response includes recommended_size, per-size probabilities, eligible variant_ids, confidence, per-area fit, method and explanation. Render the result and let the customer choose.
8. Record the choice and outcome
curl --fail-with-body -X POST "$METR_API_URL/v1/stores/$STORE_ID/fit-sessions/$SESSION_ID/complete" \
-H "Authorization: Bearer $METR_API_KEY" \
-H 'Content-Type: application/json' \
--data '{
"decision": "accepted",
"chosen_variant_id": "REPLACE_WITH_RECOMMENDED_VARIANT_ID"
}'curl --fail-with-body -X POST "$METR_API_URL/v1/stores/$STORE_ID/events" \
-H "Authorization: Bearer $METR_API_KEY" \
-H 'Content-Type: application/json' \
--data '{
"external_id": "order-123-line-1-purchase",
"source": "custom-store",
"type": "purchase",
"product_id": "REPLACE_WITH_PRODUCT_ID",
"variant_id": "REPLACE_WITH_PURCHASED_VARIANT_ID",
"session_id": "REPLACE_WITH_SESSION_ID",
"order_id": "order-123",
"line_item_id": "line-1",
"quantity": 1,
"occurred_at": "REPLACE_WITH_CURRENT_RFC3339_TIMESTAMP"
}'Purchase events come from your backend after a confirmed order. Include the same product, order and line IDs on later returns or exchanges. The demo supplies current timestamps automatically.