{
  "openapi": "3.1.0",
  "info": {
    "title": "Humanform API",
    "version": "0.1.0",
    "description": "Anthropometric prediction API. Authenticated /v1 routes charge one credit per successful prediction (or free-tier call when credits are zero)."
  },
  "servers": [
    {
      "url": "https://api.humanform.app"
    }
  ],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "API key",
        "description": "Authorization: Bearer <api_key>"
      }
    },
    "schemas": {
      "Gender": {
        "type": "string",
        "enum": [
          "Male",
          "Female"
        ]
      },
      "Unit": {
        "type": "string",
        "enum": [
          "mm",
          "cm",
          "in"
        ]
      },
      "Country": {
        "type": "string",
        "enum": [
          "US",
          "UK",
          "CA",
          "FR",
          "DE",
          "NL",
          "SE",
          "DK",
          "NO",
          "CN",
          "JP",
          "KR",
          "IN",
          "ES",
          "IT",
          "AT",
          "BE",
          "CH",
          "PL",
          "TR",
          "MX",
          "AR",
          "BR",
          "AU",
          "NZ",
          "SG",
          "TH",
          "MY",
          "ID",
          "VN",
          "PH",
          "TW",
          "RU",
          "UA",
          "FI",
          "CZ",
          "PT",
          "RO",
          "SA",
          "EG",
          "ZA",
          "NG",
          "PK",
          "BD",
          "CO",
          "IE",
          "CL",
          "PE",
          "HK",
          "IL",
          "AE",
          "GR",
          "HU",
          "KE",
          "ET",
          "IR",
          "LK",
          "MA",
          "GH",
          "EC",
          "DZ",
          "VE",
          "MM",
          "IQ",
          "SK",
          "TN",
          "UZ",
          "HR",
          "AO",
          "KZ",
          "BG",
          "RS",
          "LT",
          "JO",
          "NP",
          "SI",
          "LV",
          "EE",
          "LB",
          "KH",
          "LU",
          "CY",
          "AZ",
          "LA",
          "BY",
          "MT",
          "IS",
          "BA",
          "AL",
          "MK",
          "ME",
          "MD",
          "TJ",
          "KG",
          "TM",
          "GE",
          "MN",
          "AM",
          "BN",
          "AF",
          "YE",
          "BO",
          "PY",
          "UY",
          "GT",
          "CU",
          "DO",
          "HT",
          "HN",
          "NI",
          "SV",
          "CR",
          "PA",
          "JM",
          "TT",
          "GY",
          "SR",
          "PG",
          "FJ",
          "SB",
          "VU",
          "WS",
          "TO",
          "CD",
          "TZ",
          "SD",
          "MZ",
          "MG",
          "CM",
          "CI",
          "NE",
          "BF",
          "ML",
          "MW",
          "SN",
          "TD",
          "SO",
          "ZW",
          "GN",
          "RW",
          "BJ",
          "BI",
          "TG",
          "LY",
          "LR",
          "MR",
          "KW",
          "OM",
          "QA",
          "BH"
        ]
      },
      "Measurement": {
        "type": "string",
        "enum": [
          "AbdominalDepth",
          "ArmRestHeight",
          "BackOfHeadToChin",
          "BackOfHeadToEye",
          "BackOfHeadToLip",
          "BackOfHeadToNoseTip",
          "BackOfHeadToSelion",
          "BackOfHeadToTragion",
          "Biocular",
          "BitragionWidth",
          "ButtockKneeLength",
          "ButtockPoplitealLength",
          "ChestBreadth",
          "ChestDepth",
          "CrotchHeight",
          "DorsomLength",
          "EarLength",
          "ElbowFingertipLength",
          "ElbowHeight",
          "ElbowSpan",
          "EyeBodyCentreDistance",
          "EyeHeight",
          "EyeScalpDistance",
          "EyeToSeat",
          "EyeToTableDistance",
          "FingertipHeight",
          "FootBreadth",
          "FootLength",
          "ForearmLength",
          "ForeheadWidth",
          "GripWidth",
          "HairLine",
          "HandBreadth",
          "HandLength",
          "HeadBreadth",
          "HeadGirth",
          "HeadLength",
          "HeadToGlabella",
          "HeadToNoseTip",
          "HeadToTragion",
          "HighCounterHeight",
          "HipBreadth",
          "HipHeight",
          "IndexFingerLength",
          "IndexFingerWidthPip",
          "IndexFingerWidthTip",
          "KneeHeight",
          "KnuckleHeight",
          "LegLength",
          "LegRoom",
          "LipLength",
          "LittleFingerLength",
          "LittleFingerWidthPip",
          "LittleFingerWidthTip",
          "LowCounterHeight",
          "MaximumSeatLength",
          "MaximumTableHeight",
          "MiddleFingerLength",
          "MiddleFingerWidthPip",
          "MiddleFingerWidthTip",
          "NeckCircumference",
          "NoseLength",
          "PalmLength",
          "PoplitealHeight",
          "RingFingerLength",
          "RingFingerWidthPip",
          "RingFingerWidthTip",
          "SeatHeight",
          "ShoulderBreadthBiacromial",
          "ShoulderBreadthBideltoid",
          "ShoulderElbowLength",
          "ShoulderGripLength",
          "ShoulderHeight",
          "SittingDistance",
          "SittingElbowHeight",
          "SittingEyeHeight",
          "SittingHeight",
          "SittingHipBreadth",
          "SittingShoulderHeight",
          "Span",
          "StandingHipBreadth",
          "Stature",
          "ThighLength",
          "ThighThickness",
          "ThumbTipToCrotch",
          "TopOfHeadToStomion",
          "TrunkLength",
          "UpperArmLength",
          "UpperLimbLength",
          "WorkReach",
          "WristWidth",
          "ShoulderToWristLength",
          "SittingUpperLegLength",
          "BackOfElbowToWristLength",
          "ElbowToMiddleFingertipLength",
          "CreaseBehindKneeToAnkle",
          "ButtockToSoleSitting",
          "OutsideLegLength",
          "MidShoulderToWaistLength",
          "ShoulderToFingertipHorizontal",
          "UpperLegLengthSitting",
          "WaistToCrotchLength",
          "FrontOfNeckToWaistLength",
          "ThumbLength",
          "VerticalGripReachStanding",
          "VerticalGripReachSitting",
          "HorizontalPinchGripReach",
          "EarBreadth",
          "HandGripHeightStanding",
          "NapeHeightSitting",
          "SacralHeightSitting",
          "C7HeightStanding",
          "C7HeightSitting",
          "ArmpitHeightStanding",
          "JawWidth",
          "MidShoulderHeightStanding",
          "MidShoulderHeightSitting",
          "IndexFingerHeightStanding",
          "WristCircumference",
          "HandCircumference",
          "FistCircumference",
          "WaistHeightStanding",
          "WaistHeightSitting",
          "WaistDepthStanding",
          "FaceBreadth",
          "NoseBreadth",
          "InterNippleDistance",
          "ThighCircumferenceMidpoint",
          "UpperArmCircumferenceMidpoint",
          "NeckCircumferenceAdamsApple",
          "HipCircumferenceMax",
          "MidHipCircumference",
          "ChestCircumferenceArmpit",
          "ChestCircumferenceNipple",
          "CalfCircumference",
          "KneeCircumference",
          "WaistCircumferenceAbdominal",
          "FemaleChestCircumferenceBelowBreasts",
          "FootHeight",
          "FootCircumferenceBall",
          "FootCircumferenceInstep",
          "ThighCircumferenceBelowButtock",
          "CircumferenceBelowKnee",
          "TrunkDepthAtButtocks",
          "ThighDepthSitting",
          "ShoulderDepth",
          "WholeBodyBreadthMax",
          "WholeBodyDepthMax"
        ]
      }
    }
  },
  "paths": {
    "/": {
      "get": {
        "summary": "This API catalog (schema, instructions, endpoints).",
        "operationId": "get",
        "tags": [
          "meta"
        ],
        "responses": {
          "200": {
            "description": "Successful response"
          }
        }
      }
    },
    "/health": {
      "get": {
        "summary": "Liveness check.",
        "operationId": "get_health",
        "tags": [
          "meta"
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "ok": true,
                  "service": "humanform-workers",
                  "env": "preview|production"
                }
              }
            }
          }
        }
      }
    },
    "/mcp": {
      "get|post": {
        "summary": "Remote MCP (Streamable HTTP). Authenticate with the same Bearer API key as /v1. Tools: get_catalog, predict, predict_range, predict_compare, percentile_lookup, connected_dimension. Tool calls charge credits like the matching /v1 routes.",
        "operationId": "get|post_mcp",
        "tags": [
          "meta"
        ],
        "responses": {
          "200": {
            "description": "Successful response"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/v1/predict": {
      "post": {
        "summary": "Predict a single measurement at one percentile for one country.",
        "operationId": "post_v1_predict",
        "tags": [
          "v1"
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "measurement": "string",
                  "gender": "Male|Female",
                  "country": "string",
                  "clothing": "string",
                  "posture": "string",
                  "value": "number",
                  "unit": "mm|cm|in",
                  "source": "modeled|derived",
                  "remaining_free_calls": "number (when billed via free tier)"
                }
              }
            }
          },
          "400": {
            "description": "Validation or unknown field error"
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "402": {
            "description": "Insufficient credits or free tier exhausted"
          },
          "404": {
            "description": "Model not found"
          },
          "422": {
            "description": "Unprocessable request"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "measurement": {
                    "$ref": "#/components/schemas/Measurement"
                  },
                  "gender": {
                    "$ref": "#/components/schemas/Gender"
                  },
                  "age": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 120
                  },
                  "unit": {
                    "$ref": "#/components/schemas/Unit"
                  },
                  "clothing": {
                    "type": "string",
                    "default": "nude",
                    "description": "Clothing profile id from adjustments (e.g. nude, light, shoes, light_shoes, winter). Unknown ids return 400."
                  },
                  "posture": {
                    "type": "string",
                    "default": "standing_erect",
                    "description": "Posture profile id from adjustments (e.g. standing_erect, standing_relaxed, sitting). Unknown ids return 400."
                  },
                  "percentile": {
                    "type": "number",
                    "minimum": 1,
                    "maximum": 99
                  },
                  "country": {
                    "$ref": "#/components/schemas/Country"
                  }
                },
                "required": [
                  "measurement",
                  "gender",
                  "age",
                  "percentile"
                ],
                "additionalProperties": false
              },
              "example": {
                "measurement": "Stature",
                "gender": "Male",
                "age": 30,
                "percentile": 50,
                "country": "UK",
                "unit": "mm",
                "clothing": "light_shoes",
                "posture": "standing_relaxed"
              }
            }
          }
        }
      }
    },
    "/v1/predict/range": {
      "post": {
        "summary": "Predict one measurement for one country across multiple percentiles.",
        "operationId": "post_v1_predict_range",
        "tags": [
          "v1"
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "measurement": "string",
                  "gender": "Male|Female",
                  "country": "string",
                  "clothing": "string",
                  "posture": "string",
                  "unit": "mm|cm|in",
                  "source": "modeled|derived",
                  "values": [
                    {
                      "percentile": "number",
                      "value": "number"
                    }
                  ],
                  "remaining_free_calls": "number (when billed via free tier)"
                }
              }
            }
          },
          "400": {
            "description": "Validation or unknown field error"
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "402": {
            "description": "Insufficient credits or free tier exhausted"
          },
          "404": {
            "description": "Model not found"
          },
          "422": {
            "description": "Unprocessable request"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "measurement": {
                    "$ref": "#/components/schemas/Measurement"
                  },
                  "gender": {
                    "$ref": "#/components/schemas/Gender"
                  },
                  "age": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 120
                  },
                  "unit": {
                    "$ref": "#/components/schemas/Unit"
                  },
                  "clothing": {
                    "type": "string",
                    "default": "nude",
                    "description": "Clothing profile id from adjustments (e.g. nude, light, shoes, light_shoes, winter). Unknown ids return 400."
                  },
                  "posture": {
                    "type": "string",
                    "default": "standing_erect",
                    "description": "Posture profile id from adjustments (e.g. standing_erect, standing_relaxed, sitting). Unknown ids return 400."
                  },
                  "country": {
                    "$ref": "#/components/schemas/Country"
                  },
                  "percentiles": {
                    "type": "array",
                    "items": {
                      "type": "number",
                      "minimum": 1,
                      "maximum": 99
                    }
                  }
                },
                "required": [
                  "measurement",
                  "gender",
                  "age",
                  "percentiles"
                ],
                "additionalProperties": false
              },
              "example": {
                "measurement": "Stature",
                "gender": "Female",
                "age": 35,
                "country": "US",
                "unit": "mm",
                "percentiles": [
                  5,
                  50,
                  95
                ]
              }
            }
          }
        }
      }
    },
    "/v1/predict/compare": {
      "post": {
        "summary": "Predict one measurement at one percentile across multiple countries.",
        "operationId": "post_v1_predict_compare",
        "tags": [
          "v1"
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "measurement": "string",
                  "gender": "Male|Female",
                  "percentile": "number",
                  "clothing": "string",
                  "posture": "string",
                  "unit": "mm|cm|in",
                  "source": "modeled|derived",
                  "values": [
                    {
                      "country": "string",
                      "value": "number"
                    }
                  ],
                  "remaining_free_calls": "number (when billed via free tier)"
                }
              }
            }
          },
          "400": {
            "description": "Validation or unknown field error"
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "402": {
            "description": "Insufficient credits or free tier exhausted"
          },
          "404": {
            "description": "Model not found"
          },
          "422": {
            "description": "Unprocessable request"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "measurement": {
                    "$ref": "#/components/schemas/Measurement"
                  },
                  "gender": {
                    "$ref": "#/components/schemas/Gender"
                  },
                  "age": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 120
                  },
                  "unit": {
                    "$ref": "#/components/schemas/Unit"
                  },
                  "clothing": {
                    "type": "string",
                    "default": "nude",
                    "description": "Clothing profile id from adjustments (e.g. nude, light, shoes, light_shoes, winter). Unknown ids return 400."
                  },
                  "posture": {
                    "type": "string",
                    "default": "standing_erect",
                    "description": "Posture profile id from adjustments (e.g. standing_erect, standing_relaxed, sitting). Unknown ids return 400."
                  },
                  "percentile": {
                    "type": "number",
                    "minimum": 1,
                    "maximum": 99
                  },
                  "countries": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/Country"
                    }
                  }
                },
                "required": [
                  "measurement",
                  "gender",
                  "age",
                  "percentile",
                  "countries"
                ],
                "additionalProperties": false
              },
              "example": {
                "measurement": "Stature",
                "gender": "Male",
                "age": 30,
                "percentile": 50,
                "unit": "mm",
                "countries": [
                  "US",
                  "UK",
                  "JP"
                ]
              }
            }
          }
        }
      }
    },
    "/v1/percentile-lookup": {
      "post": {
        "summary": "Inverse of predict: given a measured value, return the matching percentile.",
        "operationId": "post_v1_percentile_lookup",
        "tags": [
          "v1"
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "measurement": "string",
                  "gender": "Male|Female",
                  "country": "string",
                  "clothing": "string",
                  "posture": "string",
                  "value": "number",
                  "unit": "mm|cm|in",
                  "percentile": "number",
                  "remaining_free_calls": "number (when billed via free tier)"
                }
              }
            }
          },
          "400": {
            "description": "Validation or unknown field error"
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "402": {
            "description": "Insufficient credits or free tier exhausted"
          },
          "404": {
            "description": "Model not found"
          },
          "422": {
            "description": "Unprocessable request"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "measurement": {
                    "$ref": "#/components/schemas/Measurement"
                  },
                  "gender": {
                    "$ref": "#/components/schemas/Gender"
                  },
                  "age": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 120
                  },
                  "unit": {
                    "$ref": "#/components/schemas/Unit"
                  },
                  "clothing": {
                    "type": "string",
                    "default": "nude",
                    "description": "Clothing profile id from adjustments (e.g. nude, light, shoes, light_shoes, winter). Unknown ids return 400."
                  },
                  "posture": {
                    "type": "string",
                    "default": "standing_erect",
                    "description": "Posture profile id from adjustments (e.g. standing_erect, standing_relaxed, sitting). Unknown ids return 400."
                  },
                  "country": {
                    "$ref": "#/components/schemas/Country"
                  },
                  "value": {
                    "type": "number"
                  }
                },
                "required": [
                  "measurement",
                  "gender",
                  "age",
                  "value"
                ],
                "additionalProperties": false
              },
              "example": {
                "measurement": "Stature",
                "gender": "Male",
                "age": 30,
                "country": "US",
                "unit": "mm",
                "value": 1750
              }
            }
          }
        }
      }
    },
    "/v1/connected-dimension": {
      "post": {
        "summary": "Given an anchor measurement at a percentile, return the conditional range of a linked measurement for a target accommodation level.",
        "operationId": "post_v1_connected_dimension",
        "tags": [
          "v1"
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "anchorMeasurement": "string",
                  "anchorPercentile": "number",
                  "linkedMeasurement": "string",
                  "accommodationPercent": "number",
                  "conditionalMean": "number",
                  "lowerBound": "number",
                  "upperBound": "number",
                  "unit": "mm|cm|in",
                  "distributionPoints": "array",
                  "remaining_free_calls": "number (when billed via free tier)"
                }
              }
            }
          },
          "400": {
            "description": "Validation or unknown field error"
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "402": {
            "description": "Insufficient credits or free tier exhausted"
          },
          "404": {
            "description": "Model not found"
          },
          "422": {
            "description": "Unprocessable request"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "anchorMeasurement": {
                    "$ref": "#/components/schemas/Measurement"
                  },
                  "anchorPercentile": {
                    "type": "number",
                    "minimum": 1,
                    "maximum": 99
                  },
                  "linkedMeasurement": {
                    "$ref": "#/components/schemas/Measurement"
                  },
                  "accommodationPercent": {
                    "type": "number",
                    "minimum": 1,
                    "maximum": 99
                  },
                  "gender": {
                    "$ref": "#/components/schemas/Gender"
                  },
                  "age": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 120
                  },
                  "country": {
                    "$ref": "#/components/schemas/Country"
                  },
                  "unit": {
                    "$ref": "#/components/schemas/Unit"
                  },
                  "clothing": {
                    "type": "string",
                    "default": "nude",
                    "description": "Clothing profile id from adjustments (e.g. nude, light, shoes, light_shoes, winter). Unknown ids return 400."
                  },
                  "posture": {
                    "type": "string",
                    "default": "standing_erect",
                    "description": "Posture profile id from adjustments (e.g. standing_erect, standing_relaxed, sitting). Unknown ids return 400."
                  }
                },
                "required": [
                  "anchorMeasurement",
                  "anchorPercentile",
                  "linkedMeasurement",
                  "accommodationPercent",
                  "gender",
                  "age"
                ],
                "additionalProperties": false
              },
              "example": {
                "anchorMeasurement": "Stature",
                "anchorPercentile": 50,
                "linkedMeasurement": "SittingHeight",
                "accommodationPercent": 95,
                "gender": "Male",
                "age": 30,
                "country": "US",
                "unit": "mm"
              }
            }
          }
        }
      }
    }
  },
  "x-humanform": {
    "defaults": {
      "country": "US",
      "unit": "mm",
      "clothing": "nude",
      "posture": "standing_erect"
    },
    "billing": {
      "predict": "1 credit (or 1 free-tier call) per successful request",
      "predict/range": "1 credit (or free-tier call) per returned percentile value",
      "predict/compare": "1 credit (or free-tier call) per returned country value",
      "percentile-lookup": "1 credit (or 1 free-tier call) per successful request",
      "connected-dimension": "1 credit (or 1 free-tier call) per successful request",
      "note": "Failed predictions (validation / model errors) do not consume credits."
    },
    "errors": {
      "400": "validation_error | unknown_measurement | unknown_clothing | unknown_posture",
      "401": "Missing or invalid Authorization header / Invalid API key",
      "402": "free_tier_exhausted | insufficient_credits",
      "404": "model_not_found (for unknown route paths also)",
      "422": "gender_not_supported",
      "429": "rate_limited",
      "500": "inference_error | internal_error"
    },
    "source": "https://api.humanform.app/",
    "generatedAt": "2026-07-18T09:58:13.989Z"
  }
}
