Skip to main content

AI Quality Suggestions API

AI Quality Suggestions generate draft quality checks from a product's schema, column profiling data, and existing check coverage. Suggestions stay inert until a reviewer accepts them. Accepted suggestions create real QualityCheck rows and link those checks back to the product.

All endpoints are served under /api/v1.0/ai. Paths below omit that prefix.

The API is feature-gated by ai.quality_suggestion_enabled.

Endpoint Overview

MethodEndpointPurpose
POST/products/{product_id}/quality/suggestionsGenerate and persist pending AI quality-check suggestions for a product.
GET/products/{product_id}/quality/suggestionsList persisted suggestions for a product.
PUT/quality/suggestions/{suggestion_id}/reviewAccept or reject one suggestion.
POST/quality/suggestions/bulk-reviewAccept or reject multiple suggestions.

Permissions

EndpointRequired permission
Generate suggestionsproduct:edit on {product_id}
List suggestionsproduct:view on {product_id}
Review one suggestionproduct:edit on the suggestion's product
Bulk reviewproduct:edit on every product represented by suggestion_ids

Bulk review first verifies that every suggestion id exists. If any id is missing, the endpoint returns 404 before applying reviews.

Suggestion Generation

POST /products/{product_id}/quality/suggestions
Content-Type: application/json
{
"max_suggestions": 10
}

max_suggestions must be between 5 and 10; the default is 10.

The service builds LLM context from:

  • Product field metadata, including field name, data type, nullability, and field descriptions.
  • Column profile statistics, including row count, null ratio, distinct count, min/max, and top values when available.
  • Existing non-deprecated quality checks linked to the product, so duplicate recommendations can be avoided.

The response contains only suggestions that passed the backend filters.

{
"product_id": "6d1506b3-41b8-4ce0-8a7f-057c7bb80c07",
"total_suggestions": 2,
"suggestions": [
{
"id": "5e4f58f6-4da3-46ea-9d19-7a4dd93186ff",
"product_id": "6d1506b3-41b8-4ce0-8a7f-057c7bb80c07",
"space_id": "a186c40f-febd-4623-a481-ff7fc7043714",
"check_name": "Customer email should be present",
"check_type": "null_check",
"configuration": {
"field_name": "email"
},
"threshold_config": {},
"field_name": "email",
"reasoning": "Email is a key customer contact field and should not be null.",
"confidence": "high",
"confidence_score": 0.91,
"status": "pending",
"accepted_check_id": null,
"reviewed_by_id": null,
"reviewed_at": null,
"created_at": "2026-06-26T13:45:22.419000Z"
}
]
}

Generation logs an AI interaction with feature: "quality_check_generation" and action: "suggest_checks". The endpoint response does not include an AI log id.

Structured Output Contract

The LLM response is contract-validated before suggestions are stored. The backend accepts either a root list or an object with one of these wrapper keys: suggestions, checks, or quality_checks.

Each LLM suggestion has this shape:

{
"check_name": "Order total should be non-negative",
"check_type": "range_check",
"field_name": "order_total",
"configuration": {
"field_name": "order_total"
},
"threshold_config": {
"min": 0
},
"confidence": 0.86,
"reasoning": "Negative order totals usually indicate refund handling or ingestion defects."
}

Supported check_type values are:

Check typeTypical use
null_checkRequired fields.
uniquenessKeys and unique identifiers.
range_checkNumeric minimum/maximum checks.
freshness_checkTimeliness checks for date/time fields.
pattern_checkRegex or format checks.
enum_checkAllowed-value checks.
sql_conditionCustom SQL conditions.

Backend filtering rules:

  • Unknown check_type values are skipped.
  • Suggestions with confidence < 0.5 are skipped.
  • confidence_score is clamped to 0.0..1.0.
  • confidence is bucketed as high for scores >= 0.8, medium for scores >= 0.5, and low below that threshold. Low-confidence suggestions are normally filtered out by the 0.5 persistence threshold.
  • configuration and threshold_config are parsed through the same typed quality-check payload parsers used by runtime quality checks.

If the AI output contract fails, the service uses a controlled fallback that can return zero persisted suggestions instead of storing malformed checks.

List Suggestions

GET /products/{product_id}/quality/suggestions?status=pending&skip=0&limit=50

Query parameters:

ParameterNotes
statusOptional status filter. Common values are pending, accepted, and rejected.
skipOffset, default 0, minimum 0.
limitPage size, default 50, range 1..200.

Responses are sorted by confidence_score descending. The endpoint returns a JSON array and does not include a total count in the response body.

Review One Suggestion

PUT /quality/suggestions/{suggestion_id}/review
Content-Type: application/json
{
"action": "accepted"
}

action must be accepted or rejected.

Review side effects:

ActionSide effect
acceptedCreates a real QualityCheck, links it to the product, sets accepted_check_id, and records reviewer metadata.
rejectedUpdates the suggestion status and reviewer metadata without creating a check.

Accepted quality checks inherit:

  • name from check_name.
  • check_type, configuration, and threshold_config from the suggestion.
  • space_id from the suggestion.
  • description as AI-suggested: {reasoning} when reasoning exists.

The endpoint returns the updated suggestion.

Bulk Review

POST /quality/suggestions/bulk-review
Content-Type: application/json
{
"suggestion_ids": [
"5e4f58f6-4da3-46ea-9d19-7a4dd93186ff",
"bff9155b-61e9-4bda-88db-d85b2a7722d4"
],
"action": "accepted"
}

Response:

{
"updated_count": 2,
"action": "accepted"
}

Bulk review applies the same side effects as single review. An empty suggestion_ids list is valid and returns updated_count: 0.

Failure Cases

StatusCause
400Bulk review received an invalid review action after request validation.
403Feature gate is disabled, the user is not authenticated, or the caller lacks product permissions.
404A suggestion id does not exist, or the product/suggestion cannot be resolved for permission checks.
422Request validation failed, such as max_suggestions outside 5..10, invalid UUID, invalid pagination range, or action outside `accepted
500Unexpected AI provider, prompt rendering, database, or quality-check creation failure.

Generation can legitimately return total_suggestions: 0 when existing checks already cover the product, the product has limited schema/profile context, the LLM returns only low-confidence suggestions, or the structured output contract falls back after invalid AI output.