Enrich

Given a category and either a fileId from Vision, a set of attributes, or both, Enrich returns normalized attributes plus per-field details: which values were derived and how confident the API is. When called without a fileId, Enrich normalizes and fills in missing attribute values based on the attributes you supply — no image required.

Simplest request — after getting a fileId from Vision:

POST
/v1/enrich
{
  "category": "wristwatch",
  "fileId": "f47ac10b-58cc-4372-a567-0e02b2c3d479"
}

Response (200):

{
  "normalizedAttributes": {
    "brand": "Rolex",
    "strap": "steel",
    "dialColor": "black"
  },
  "candidates": [],
  "enriched": [
    { "attribute": "strap", "value": "steel", "confidence": 0.9, "source": "VISUAL_MATCH" }
  ],
  "confidence": 0.82,
  "warnings": []
}

Pass normalizedAttributes directly to POST /v1/valuations as attributes, or show them to the user for editing first.

When to use Enrich

Use caseApproach
You only have an imageVision → Enrich → get suggested attributes
You want to show "what we detected" before valuingEnrich → show normalizedAttributes and enriched → valuate
You want a valuation in one stepPOST /v1/valuations with fileId; server enriches internally
You have all attributes and no imageSkip Enrich; call Valuations with attributes only

Prerequisites: vision and fileId

Upload an image:

POST
/v1/vision
{
  "imageUrl": "https://example.com/photos/watch-front.jpg"
}

Response (200):

{
  "fileId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "status": "completed",
  "objects": [{ "type": "wristwatch" }],
  "usage": { "creditUsed": 1 }
}

If the same image was processed before, the server returns a cached result (creditUsed: 0).

Request and response

Request body:

FieldTypeRequiredDescription
categorystringYes"car" | "wristwatch" | "ring" (see GET /v1/categories).
fileIdstringNoID from POST /v1/vision. Required if no attributes are provided.
attributesobjectNoInitial or partial attributes. Required if no fileId is provided. Enrichment merges them with derived values.

Response (200):

{
  "normalizedAttributes": { "..." : "..." },
  "candidates": [ "..." ],
  "enriched": [ "..." ],
  "confidence": 0.92,
  "warnings": [ "..." ]
}

Response fields explained

FieldDescription
normalizedAttributesMerged result of your input + enriched values. Use directly as attributes in POST /v1/valuations.
enrichedAttributes that were derived (not only copied from input). Each item: attribute, value, confidence (0–1), source.
candidatesPossible values when the system is unsure. Same shape as enriched items.
confidenceOverall confidence (0–1) for the enrichment result.
warningsOptional { "code": "...", "message": "..." } items (e.g. ambiguous options, conflicts).

Enriched item shape:

{
  "attribute": "strap",
  "value": "steel",
  "confidence": 0.95,
  "source": "VISUAL_MATCH"
}

Examples by category

Wristwatch — image only

{
  "category": "wristwatch",
  "fileId": "f47ac10b-58cc-4372-a567-0e02b2c3d479"
}

Response (200):

{
  "normalizedAttributes": {
    "brand": "Rolex",
    "model": "Submariner",
    "strap": "steel",
    "case": "steel",
    "bezel": "steel",
    "movement": "automatic",
    "dialColor": "black",
    "caseDiameter": 41
  },
  "candidates": [
    { "attribute": "referenceNumber", "value": "116610LN", "confidence": 0.75, "source": "watch-database" }
  ],
  "enriched": [
    { "attribute": "strap", "value": "steel", "confidence": 0.9, "source": "VISUAL_MATCH" },
    { "attribute": "dialColor", "value": "black", "confidence": 0.85, "source": "VISUAL_MATCH" },
    { "attribute": "movement", "value": "automatic", "confidence": 0.7, "source": "MOST_POPULAR" }
  ],
  "confidence": 0.82,
  "warnings": [
    { "code": "AMBIGUOUS_OPTION", "message": "Multiple referenceNumber options available; send one to lock valuation range." }
  ]
}

Wristwatch — with initial attributes (brand + model)

Seeding brand and model lets enrichment narrow reference number and other fields more confidently.

{
  "category": "wristwatch",
  "fileId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "attributes": {
    "brand": "Rolex",
    "model": "Submariner"
  }
}

Response (200):

{
  "normalizedAttributes": {
    "brand": "Rolex",
    "model": "Submariner",
    "referenceNumber": "116610LN",
    "strap": "steel",
    "case": "steel",
    "bezel": "steel",
    "movement": "automatic",
    "dialColor": "black",
    "caseDiameter": 41
  },
  "candidates": [],
  "enriched": [
    { "attribute": "referenceNumber", "value": "116610LN", "confidence": 0.92, "source": "WATCH_DATABASE" },
    { "attribute": "strap", "value": "steel", "confidence": 0.95, "source": "VISUAL_MATCH" }
  ],
  "confidence": 0.91,
  "warnings": []
}

Car — license plate from image

Vision detects the plate; Enrich calls the car registry to fill brand, model, color, year, mileage.

{
  "category": "car",
  "fileId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "attributes": {}
}

Response (200):

{
  "normalizedAttributes": {
    "licensePlate": "ABC123",
    "brand": "Volvo",
    "model": "XC60",
    "color": "black",
    "yearOfManufacture": 2020,
    "odometerReading": 52000
  },
  "candidates": [],
  "enriched": [
    { "attribute": "brand", "value": "Volvo", "confidence": 1, "source": "car-registry" },
    { "attribute": "model", "value": "XC60", "confidence": 1, "source": "car-registry" }
  ],
  "confidence": 1,
  "warnings": []
}

Using Enrich with Valuations

Pattern A: Enrich first, then valuate (two calls)

Use when you want to show the user the enriched attributes and let them edit before valuing.

RESP=$(curl -s -X POST https://api.gemmai.io/v1/vision \
  -H "Content-Type: application/json" \
  -d '{"imageUrl": "https://example.com/watch.jpg"}')
FILE_ID=$(echo "$RESP" | jq -r '.fileId')

Pattern B: Single valuate call (enrich inside)

Use when you want one round-trip and don't need to show enrichment details.

{
  "category": "wristwatch",
  "attributes": { "brand": "Rolex" },
  "fileId": "f47ac10b-58cc-4372-a567-0e02b2c3d479"
}

The server runs enrichment internally. The response contains the valuation and the attributes used after enrichment.

Warnings and confidence

  • confidence (0–1): Higher means the enriched attributes are more reliable. Low confidence often accompanies candidates or warnings.
  • AMBIGUOUS_OPTION: Several values are possible for a field; sending one narrows the valuation.
  • CONFLICT_DERIVED: A value you sent conflicts with what was derived; consider showing both and letting the user choose.

Error handling

400 — Missing or invalid category:

{ "error": "category query param is required" }

400 — Invalid or missing fileId:

{ "error": "..." }

500 — Enrichment failed:

{ "error": "Enrichment failed" }

Typical causes: vision data missing for fileId, external service unavailable, or invalid category.

Was this page helpful?