Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/elecodes/TenderCheck-AI/llms.txt

Use this file to discover all available pages before exploring further.

A generic AI extraction pass against a large tender document can surface requirements that are entirely irrelevant to the bidding company’s sector. A software firm submitting for an IT services contract does not need to be warned about construction material specifications — and a procurement auditor should not have to manually discard them. TenderCheck AI’s industry validation system addresses this by applying a sector-specific scope check immediately after requirement extraction, flagging out-of-scope tenders before you invest time in a full proposal validation.

How It Works

Industry validation runs as part of the CreateTender use case, after the AI extraction pipeline completes but before the analysis is persisted to the database. The pipeline has three components:
  1. ValidationRuleFactory — queries the industry_presets table in Turso with the industry string provided by the user. It returns one or more IRule instances configured for that sector. If the database query fails or the industry name is not found, a hardcoded fallback rule set for Digital Services is used.
  2. ValidationEngine — iterates over the rule set and calls rule.validate(analysis) on each rule, collecting any non-null ValidationResult objects.
  3. ScopeValidationRule — the concrete rule that performs the keyword-based scope check. Its result is prepended to the TenderAnalysis.results array with requirementId = "SCOPE_CHECK" so it can be identified and filtered separately from proposal validation results in the frontend.
TenderAnalysis (post-extraction)


ValidationRuleFactory.createRules("digital_services")
        │  reads industry_presets table

[ScopeValidationRule(positives, negatives)]


ValidationEngine.validate(analysis)


ValidationResult { requirementId: "SCOPE_CHECK", status: "MET" | "NOT_MET" | "AMBIGUOUS" }


Prepended to analysis.results → saved to DB

Supported Industries

Industry presets are stored in the industry_presets database table with the following schema:
ColumnTypeDescription
idtextUUID primary key
nametextIndustry identifier used in API requests (e.g., "Digital Services") — must be unique
positive_keywordstext (JSON array)Keywords that confirm the tender is in scope (e.g., ["software", "digital", "cloud"])
negative_keywordstext (JSON array)Keywords that confirm the tender is out of scope (e.g., ["limpieza", "construcción"])
The ValidationRuleFactory queries this table by name using an exact match. The default fallback (used when no industry is specified or when the DB query fails) applies the Digital Services keyword set:
// Fallback positive keywords
["software", "digital", "plataforma", "app", "sistema", "informático", "tecnológico", "cloud"]

// Fallback negative keywords
["limpieza", "obra", "construcción"]
You can add custom industry presets by inserting rows directly into the industry_presets table in Turso. Use the Turso CLI or dashboard to run an INSERT statement with a name, a positive_keywords JSON array, and a negative_keywords JSON array.

The Scope Validation Rule

ScopeValidationRule combines the tender title and all extracted requirement texts into a single lowercase string, then applies a two-pass keyword check: Pass 1 — Negative keywords (fail fast): If any negative keyword is found in the combined text, the rule immediately returns a NOT_MET result with confidence 0.9 and an explanation identifying the offending keyword. This prevents false positives when a digital services tender mentions a construction sub-item. Pass 2 — Positive keywords: If no negative keyword triggered, the rule checks whether at least one positive keyword appears. If none are found, it returns an AMBIGUOUS result with confidence 0.6 (the tender may or may not be in scope). If at least one positive keyword is present, it returns a MET result with confidence 0.85.
// Possible SCOPE_CHECK outcomes
{ requirementId: "SCOPE_CHECK", status: "MET",       confidence: 0.85 }  // In scope
{ requirementId: "SCOPE_CHECK", status: "AMBIGUOUS", confidence: 0.6  }  // Cannot determine
{ requirementId: "SCOPE_CHECK", status: "NOT_MET",   confidence: 0.9  }  // Out of scope
The SCOPE_CHECK result is filtered out of the main compliance statistics in ValidationSummary (it is excluded from the mandatory/optional requirement counts) so it does not skew the overall compliance score.

Using Industry Validation in the UI

When uploading a tender PDF from the dashboard, an optional industry dropdown appears in the upload form. Selecting an industry sends the industry parameter to the backend along with the PDF file.
1

Upload your tender PDF

Drag and drop or click to select the tender document in the Pliego upload zone.
2

Select an industry (optional)

Choose the relevant sector from the industry dropdown. Available options are driven by the industry_presets table. If no selection is made, the backend defaults to Digital Services.
3

Submit the analysis

The backend runs requirement extraction followed immediately by the scope validation rule for the selected industry. The SCOPE_CHECK result is saved as part of the analysis.
4

Review the scope badge

After analysis completes, the dashboard displays the SCOPE_CHECK result as a contextual badge on the analysis header, indicating whether the tender is in scope (MET), ambiguous (AMBIGUOUS), or out of scope (NOT_MET) for the chosen industry.

Using Industry Validation via API

You can also trigger industry-scoped analysis directly via the REST API by sending a multipart/form-data request to the tender analysis endpoint.
POST /api/tenders/analyze
Content-Type: multipart/form-data
Authorization: Bearer <token>
Request body (multipart/form-data):
FieldTypeRequiredDescription
filePDF binary✅ YesThe tender document to analyse
industrystring❌ NoIndustry name matching an industry_presets.name value
Example using curl:
curl -X POST https://tendercheckai.elecodes.online/api/tenders/analyze \
  -H "Authorization: Bearer <your_token>" \
  -F "file=@pliego_it_security.pdf" \
  -F "industry=Digital Services"
Example response (abbreviated):
{
  "id": "a1b2c3d4-...",
  "tenderTitle": "Pliego de condiciones para servicios de seguridad IT",
  "status": "COMPLETED",
  "requirements": [...],
  "results": [
    {
      "requirementId": "SCOPE_CHECK",
      "status": "MET",
      "reasoning": "Tender aligns with digital services scope.",
      "confidence": 0.85
    }
  ]
}
If the industry field is omitted, the backend uses Digital Services as the default and applies the hardcoded fallback keyword set.
To add a new industry to the platform, insert a row into the industry_presets table in your Turso database. The new industry will be available immediately — no code changes or redeployment are required. Use descriptive name values that match exactly what you will pass in the industry API field or select in the UI dropdown.

Build docs developers (and LLMs) love