Skip to main content
Every enrichment result includes confidence scores that indicate how certain Triqai is about each piece of data. In addition to numeric scores, Triqai provides reason tags that explain why a score is what it is. Understanding these helps you make better decisions about when to trust automated enrichment and when to require manual review.

What Are Confidence Scores?

Confidence scores are objects with two fields:
{
  "value": 92,
  "reasons": ["name_closely_matched", "results_consensus"]
}
  • value: An integer from 0 to 100 representing certainty
  • reasons: An array of string tags explaining the score

Score Ranges

  • 0: No confidence (should not be used)
  • 50: Low confidence (uncertain match)
  • 75: Moderate confidence (likely correct)
  • 90: High confidence (very likely correct)
  • 100: Maximum confidence (definitive match)

Where Scores Appear

Confidence scores appear at multiple levels in the response:

Overall Transaction Confidence

{
  "data": {
    "transaction": {
      "confidence": { "value": 92, "reasons": [] }
    }
  }
}
This represents the overall quality of the enrichment across all modules.

Category Confidence

{
  "category": {
    "primary": { "name": "Shopping" },
    "secondary": { "name": "Online Shopping" },
    "confidence": { "value": 95, "reasons": ["merchant_category_match"] }
  }
}

Per-Entity Confidence

Each entity in the entities array has its own confidence:
{
  "entities": [
    {
      "type": "merchant",
      "role": "organization",
      "confidence": {
        "value": 98,
        "reasons": ["name_closely_matched", "results_consensus"]
      },
      "data": { "name": "Starbucks" }
    },
    {
      "type": "location",
      "role": "store_location",
      "confidence": {
        "value": 72,
        "reasons": ["city_match", "multiple_plausible_locations"]
      },
      "data": { "name": "Starbucks - Downtown" }
    },
    {
      "type": "intermediary",
      "role": "processor",
      "confidence": { "value": 99, "reasons": ["known_processor_match"] },
      "data": { "name": "Square" }
    }
  ]
}

Confidence Reason Tags

Reason tags explain what contributed to or detracted from the confidence score. They are divided into several categories.

Global Reasons

These can appear on any entity type (merchant, location, or intermediary):
TagMeaning
results_consensusMultiple independent sources/results point to the same entity
ambiguous_entityMultiple plausible candidates; evidence does not uniquely identify one
results_contradictTop results disagree on key identity fields, indicating uncertainty
insufficient_evidenceNot enough reliable evidence to support a strong match

Category Reasons

Applied to the category confidence score (deterministic, code-only):
TagMeaning
merchant_category_matchThe identified merchant has a known/linked category mapping
fallback_classificationCategory came from fallback logic rather than strong merchant evidence
p2p_transfer_detectedTransaction detected as P2P transfer by deterministic rules

Merchant Reasons

Applied to merchant entity confidence (global + merchant-specific):
TagMeaning
broad_merchant_nameExtracted merchant string is too broad to uniquely identify a business
generic_descriptor”Merchant name” is primarily a descriptor rather than a proper noun
name_closely_matchedChosen merchant name matches the raw transaction tokens strongly
name_inferredOutput name differs from extracted name because AI inferred the likely correct name
brand_disambiguatedAI resolved a brand ambiguity based on evidence
category_consistent_with_contextMerchant type implied by evidence matches transaction context/category

Location Reasons

Applied to location entity confidence (global + location-specific):
TagMeaning
country_matchLocation country aligns with expected country hints
wrong_countryLocation country doesn’t aligns with expected country hints
city_matchCity token is present in raw or strong context and matches chosen location city
store_id_matchStore number/branch ID appears in raw and matches a specific store
single_result_matchOnly one strong relevant place result exists and it matches clearly
identifier_matchSpecific identifier matches (street, phone, postal code, store code)
address_closely_matchedAddress text in results aligns closely with chosen location fields
multiple_plausible_locationsSeveral plausible places exist and evidence doesn’t uniquely select one
chain_location_disambiguatedFor chains, AI selected a specific branch based on evidence

Intermediary Reasons

Applied to intermediary entity confidence (global + intermediary-specific):
TagMeaning
name_closely_matchedIntermediary name matches raw tokens strongly
processor_role_disambiguatedAI resolved whether entity acts as processor/gateway vs actual merchant
platform_vs_merchant_disambiguatedAI resolved platform vs underlying merchant
known_processor_matchDeterministic match to internal processor dictionary (prefix/pattern)

Score Interpretation

Interpretation: Highly reliable for automated decisions When you see this: - Transaction string closely matches known patterns - Multiple data points confirm the identification - Entity is well-known with clear signatures Common reasons: results_consensus, name_closely_matched, known_processor_match Recommended action: Use directly in your application without review

Confidence by Entity Type

Different entity types typically have different confidence distributions:
EntityTypical RangeNotes
Merchant70-99Well-known merchants score higher
Location50-95Store-level matching is harder
Category75-99Based on merchant + context
Intermediary90-99Distinct patterns, high accuracy
Person85-99Extracted directly from transaction string

Using Confidence in Your Application

Threshold-Based Logic

import Triqai from "triqai";

const triqai = new Triqai(process.env.TRIQAI_API_KEY!);

const result = await triqai.transactions.enrich({
  title: "STARBUCKS NYC",
  country: "US",
  type: "expense",
});

const threshold = 85;

const autoApprove =
  result.data.transaction.confidence.value >= threshold &&
  result.data.entities.every((e) => e.confidence.value >= threshold);

const needsReview = result.data.transaction.confidence.value < 70;

Using Reason Tags

function analyzeConfidence(entity: { confidence: { value: number; reasons: string[] } }) {
  const { value, reasons } = entity.confidence;

  if (value >= 90 && reasons.includes("results_consensus")) {
    return { reliable: true, action: "auto_approve" };
  }

  if (reasons.includes("ambiguous_entity") || reasons.includes("results_contradict")) {
    return { reliable: false, action: "manual_review" };
  }

  if (reasons.includes("known_processor_match")) {
    return { reliable: true, action: "auto_approve" };
  }

  return {
    reliable: value >= 75,
    action: value >= 75 ? "auto_approve" : "manual_review",
  };
}

const result = await triqai.transactions.enrich({
  title: "STRIPE* ACME CORP",
  country: "US",
  type: "expense",
});

for (const entity of result.data.entities) {
  const analysis = analyzeConfidence(entity);
  console.log(`${entity.type}: ${analysis.action}`);
}

Displaying Confidence to Users

function getConfidenceLabel(confidence: { value: number; reasons: string[] }) {
  if (confidence.value >= 90) return { text: "Verified", color: "green" };
  if (confidence.value >= 70) return { text: "Likely", color: "blue" };
  if (confidence.value >= 50) return { text: "Uncertain", color: "yellow" };
  return { text: "Unverified", color: "red" };
}

Filtering by Confidence

const result = await triqai.transactions.enrich({
  title: "AMAZON MKTPLACE PMTS",
  country: "US",
  type: "expense",
});

const reliableMerchants = result.data.entities.filter(
  (e) => e.type === "merchant" && e.confidence.value >= 80,
);

const flaggedForReview = result.data.entities.filter(
  (e) => e.confidence.value < 60 || e.confidence.reasons.includes("ambiguous_entity"),
);

Best Practices

Different applications have different tolerance for errors. A personal finance app might accept lower confidence than a compliance system.
If incorrect categorization has serious consequences, require higher confidence thresholds or manual review.
Don’t just check the numeric score reason tags like known_processor_match or results_contradict give you richer context for decision-making.
Monitor the confidence scores you’re seeing. Consistently low scores for certain transaction types might indicate a need for different handling.
Use the Issue Report API to flag incorrect enrichments. This helps improve accuracy over time.

Next Steps

Error Handling

Handle errors and partial results gracefully

Report Issues

Report enrichment issues to improve accuracy