Skip to main content
A hair profile is a structured description of a person’s hair characteristics. Every product in the Black Hair API carries a HairProfile record that captures the curl patterns, porosity levels, texture, styling goals, and hair concerns that the product is best suited for. When you call the recommendation engine, those product-side attributes are compared against the preferences you supply in your request to surface the most relevant matches. Understanding how hair profiles are structured — and how to send one in a request — lets you build precise, personalised product discovery into your application.

Profile attributes

Each product in the database has a linked HairProfile record. The fields below are stored as arrays because many products are suitable for a range of hair types or concerns.
hair_types
array of strings
The curl-pattern types this product is formulated for. Values follow the widely used André Walker typing system: 3A, 3B, 3C, 4A, 4B, 4C. A product aimed at tightly coiled hair might carry ["4A", "4B", "4C"].
porosity
array of strings
The porosity levels the product is best suited for. Porosity describes how readily a hair strand absorbs and retains moisture. Possible values are low, medium, and high. Products with heavy oils or butters are often tagged ["low"] because they help seal the cuticle on hair that loses moisture quickly.
concerns
array of strings
The specific hair concerns the product addresses. Supported values are dryness, breakage, growth, scalp, frizz, definition, moisture, and protein. A deep conditioner might carry ["dryness", "breakage", "moisture"].
texture
array of strings
The strand thickness the product is designed for: fine, medium, or coarse. Fine hair is easily weighed down, so this attribute helps filter out heavy creams and butters when appropriate.
use_case
array of strings
The styling method or routine the product supports. Examples include wash-and-go, twist-out, and protective-styles. These map to the flags produced during AI enrichment (see Ingredient Analysis).
ai_confidence
float
A score between 0.0 and 1.0 indicating how certain the AI enrichment pipeline was when it classified the product’s hair profile. Scores above 0.85 indicate high confidence. Lower scores may reflect ambiguous ingredient lists or sparse product descriptions, and you may want to surface them with a lower weight in your UI.

How hair profiles are used

When you call POST /v1/recommend/, the API performs a semantic search across the product catalogue to identify the top 20 candidates whose hair profiles are most similar to the preferences you submitted. Those candidates are then passed to GPT-4o-mini, which re-ranks them based on your specific hair_type, porosity, concerns, and budget_max. The model returns a ranked list with a plain-English reason for each recommendation. This two-stage approach — semantic search first, GPT-4o-mini re-ranking second — means results are both contextually relevant and clearly explained.
The POST /v1/recommend/ endpoint is available on Pro and Enterprise plans only. Calling it on a Starter or Growth key returns a 403 error. See Plans & Limits for upgrade details.

Passing a hair profile

Send a JSON body to POST /v1/recommend/ with the attributes that describe your user’s hair. All fields except hair_type and porosity are optional.

Request fields

hair_type
string
required
The user’s primary curl pattern. Use a single value from the André Walker typing system: 3A, 3B, 3C, 4A, 4B, or 4C.
porosity
string
required
The user’s hair porosity. One of low, medium, or high. If your users don’t know their porosity, consider linking to a porosity quiz in your onboarding flow.
concerns
array of strings
An array of hair concerns to prioritise during ranking. Supported values: dryness, breakage, growth, scalp, frizz, definition, moisture, protein. Omit this field to apply no concern filter.
budget_max
float
An optional upper price bound in the currency specified by currency. Products whose minimum price exceeds this value are excluded before re-ranking. Defaults to no limit.
currency
string
default:"GBP"
The currency code to apply when evaluating budget_max. Defaults to GBP.
exclude_ingredients
array of strings
An optional list of ingredient names to exclude. Any product whose raw ingredient list contains one of these strings (case-insensitive) is removed before re-ranking. Useful for users with known sensitivities — for example ["mineral oil", "lanolin"].
limit
integer
default:"5"
The maximum number of recommendations to return. Defaults to 5. The API fetches the top 20 vector-similar candidates internally and returns up to limit after filtering and re-ranking.

Example request

{
  "hair_type": "4C",
  "porosity": "high",
  "concerns": ["dryness", "breakage", "moisture"],
  "budget_max": 25.00,
  "currency": "GBP",
  "exclude_ingredients": ["mineral oil", "petrolatum"],
  "limit": 5
}

Example response

{
  "query": {
    "hair_type": "4C",
    "porosity": "high",
    "concerns": ["dryness", "breakage", "moisture"]
  },
  "recommendations": [
    {
      "rank": 1,
      "reason": "This leave-in conditioner is specifically formulated for high-porosity 4C hair. Its shea butter and aloe vera base delivers intense moisture while the protein blend helps reduce breakage at the strand level.",
      "product": {
        "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "name": "Moisture Surge Leave-In Conditioner",
        "brand": "Adwoa Beauty",
        "category": "Leave-In Conditioner",
        "price_range": { "min": 18.00, "max": 18.00 },
        "buy_url": "https://example.com/products/moisture-surge",
        "hair_types": ["4A", "4B", "4C"],
        "sulphate_free": true,
        "silicone_free": true
      }
    }
  ]
}
If your application serves users who don’t know their curl pattern or porosity, start with broader values like hair_type: "4A" combined with concerns that reflect their symptoms (e.g. dryness, frizz). The vector similarity layer is robust enough to return relevant results even from partial profiles.