Skip to main content
Every product in the Black Hair API goes through an ingredient enrichment pipeline powered by GPT-4o-mini. For each ingredient in a product’s formula, the pipeline returns a structured object that covers its INCI name, functional category, water solubility, curl-friendliness, porosity compatibility, and specific notes for Black and textured hair. This gives your application the data it needs to explain product choices at an ingredient level — not just flag sulphates and silicones, but tell users why an ingredient may or may not work for their hair.

What ingredient analysis returns

When you fetch ingredient data from the API, each analysed ingredient comes back with the following fields.
name
string
The normalised common name of the ingredient as it appears in product labelling.
inci_name
string | null
The official International Nomenclature of Cosmetic Ingredients (INCI) name. Returns null when the INCI name cannot be determined from available data.
type
string
The functional category of the ingredient. One of: protein, oil, butter, humectant, emulsifier, surfactant, silicone, preservative, fragrance, or other.
is_water_soluble
boolean
Whether the ingredient dissolves in water. Water-insoluble ingredients (many silicones and petroleum derivatives) require a surfactant-based cleanser to remove fully and may cause buildup on low-porosity hair.
curl_friendly
boolean
A top-level boolean indicating whether the ingredient is generally considered curl-friendly across the textured hair community. This is a convenience flag — check porosity_recommendation and avoid_if for more nuanced guidance.
porosity_recommendation
string
The porosity level this ingredient is best suited for. One of: low, medium, high, all, or none. Lightweight humectants like glycerin are typically all; heavy butters are often high (best for high-porosity hair that needs sealing).
what_it_does
string
A 2–3 sentence plain-English explanation of what the ingredient does in a hair product formulation.
black_hair_notes
string
1–2 sentences specifically addressing how the ingredient affects Black, natural, curly, or coily hair. These notes are generated with explicit awareness of the textured hair context and may highlight concerns (e.g. hygral fatigue risk for high-porosity hair) that generic ingredient databases omit.
can_cause_buildup
boolean
Whether the ingredient is known to accumulate on the hair shaft over time. Ingredients that cause buildup typically require regular clarifying to maintain scalp health and product absorption.
requires_clarifying
boolean
Whether regular use of this ingredient means the user should incorporate a clarifying shampoo into their routine.
common_in_products
array of strings
Product categories this ingredient commonly appears in — for example ["conditioner", "leave-in", "deep conditioner"].
avoid_if
array of strings
A list of hair concerns or conditions under which this ingredient should be avoided. For example: ["low porosity", "protein sensitive", "fine hair"].

Example ingredient analysis response

{
  "name": "Glycerin",
  "inci_name": "Glycerin",
  "type": "humectant",
  "is_water_soluble": true,
  "curl_friendly": true,
  "porosity_recommendation": "all",
  "what_it_does": "Glycerin is a humectant that draws moisture from the air into the hair shaft, improving hydration and reducing frizz. It is one of the most widely used conditioning agents in wash-day products. At higher concentrations it also adds slip, making detangling easier.",
  "black_hair_notes": "Glycerin works exceptionally well for 4C and high-porosity coils in humid climates, pulling atmospheric moisture into thirsty strands. In very dry environments or low-humidity climates, it can draw moisture out of the hair instead, leading to increased frizz — formulas with glycerin listed high in the ingredient deck should be used with a sealant in those conditions.",
  "can_cause_buildup": false,
  "requires_clarifying": false,
  "common_in_products": ["conditioner", "leave-in conditioner", "styling cream", "shampoo"],
  "avoid_if": ["very low humidity environments without a sealant layer"]
}

Product-level ingredient flags

In addition to per-ingredient analysis, each product’s Ingredients record carries aggregate boolean and string flags that let you filter products at the catalogue level without inspecting individual ingredients.
has_sulphates
boolean
true if the product contains one or more sulphate surfactants (e.g. sodium lauryl sulphate, ammonium laureth sulphate). Sulphates cleanse effectively but can strip natural oils from coily and dry hair textures.
has_parabens
boolean
true if the product contains paraben preservatives (e.g. methylparaben, propylparaben). Many consumers and brands in the textured hair space opt for paraben-free formulas.
has_silicones
boolean
true if the product contains any silicone ingredient. Note that this flag does not distinguish between water-soluble silicones (e.g. cyclomethicone) and non-water-soluble ones (e.g. dimethicone). Use the per-ingredient is_water_soluble field for that distinction.
protein_level
string
The overall protein content of the formula: none, low, medium, or high. Protein strengthens the hair shaft but can cause brittleness in users who are protein-sensitive — a common concern in 4C hair care.
moisture_level
string
The overall moisture (humectant and emollient) content of the formula: none, low, medium, or high. Use this alongside protein_level to help users maintain a healthy protein-moisture balance.
porosity_match
array of strings
The porosity levels this product is best suited for, derived from the aggregate ingredient profile. Possible values: low, medium, high. A product heavy in lightweight humectants with no occlusive butters might return ["low", "medium"].
flags
array of strings
Short descriptive tags produced during AI enrichment. Examples: LOC-method, wash-and-go, protective-styles, scalp-safe, protein-free. These are useful for tag-based filtering and UI badge display.

Using ingredient data in queries

Look up products by ingredient name

To find all products that contain a specific ingredient, use the name query parameter on the ingredients endpoint:
GET /v1/ingredients/products?name=glycerin
The match is case-insensitive and searches the raw_list text field, so partial matches work — searching for glycerin will match vegetable glycerin and glycerin (derived from coconut).

Exclude ingredients from recommendations

When calling POST /v1/recommend/, pass an exclude_ingredients array to filter out any product whose raw ingredient list contains one of your specified strings:
{
  "hair_type": "4B",
  "porosity": "low",
  "concerns": ["dryness", "frizz"],
  "exclude_ingredients": ["dimethicone", "mineral oil", "petrolatum"]
}
The exclusion check is also case-insensitive and substring-based, so "dimethicone" will exclude products containing Dimethicone, Cyclopentasiloxane/Dimethicone Crosspolymer, and similar variants.
Build a user-facing “ingredients to avoid” list in your onboarding flow and persist it in your application. Pass it as exclude_ingredients on every recommendation call to deliver a consistently personalised experience without asking the user to repeat their preferences.