Enterprise Data Enrichment and Approval Queue
Import records from an external Postgres database, enrich each one through a REST enrichment provider, score and classify results automatically, and route low-confidence records to a human approval queue — with Slack alerts, retry logic, and a full audit trail.
Start building in Xano: Access the prompt at https://go.xano.co/start-xano-with-template-skill and run it here with data-enrichment-approval-queue-postgres-slack as your template.
Copy and paste the prompt in your local coding agent of choice.
Template Details
Integrations
workspace templates {
acceptance = {ai_terms: false}
preferences = {
internal_docs : false
track_performance: true
sql_names : false
sql_columns : true
}
}
Overview
Import records from an external Postgres database, enrich each one through a REST enrichment provider, score and classify the result automatically, and route only the low-confidence records to a human approval queue — with Slack alerts, retry limits, and a full audit trail.
Xano owns the pipeline and the judgment: what a record scores, whether it clears automatically or needs a human, who approved it, and when. Push it and the whole import → enrich → score → queue → resolve loop runs, with the external Postgres / enrichment / Slack calls doc-mocked so it works before you wire in credentials.
What it provides
Enrichment is easy to start and hard to trust. A script calls a provider, writes whatever comes back, and nobody notices when the provider returns half-empty rows or a low-confidence guess — until that bad data is three systems deep. The missing piece is judgment with a paper trail: score each result, auto-accept the clean ones, auto-reject the clearly bad ones, and put a human in the loop only for the uncertain middle.
This template is that pipeline. Records are imported from Postgres, enriched through a REST provider, and scored 0–100 by a deterministic rule set; the score maps to approved_auto, needs_review, or rejected_auto. Only needs_review items land in the approval queue and fire a Slack alert, so humans see the few records that actually need them. Every attempt is tracked (with a 3-try retry cap), every decision writes an event, and every API call is logged — so the enrichment your systems trust has a reconstructable history.
Repo layout
backend/
api/
data_enrichment/
approvals_approve_post.xs
approvals_pending_get.xs
approvals_reject_post.xs
data_enrichment.xs
records_enrich_post.xs
records_import_post.xs
function/
deaq_authorize_and_log.xs
deaq_check_auth.xs
deaq_classify.xs
deaq_enrich_record.xs
deaq_fetch_source_record.xs
deaq_ingest_source_record.xs
deaq_next_job_state.xs
deaq_reject_approval.xs
deaq_resolve_approval.xs
deaq_score.xs
deaq_send_slack.xs
table/
api_request_logs.xs
approval_events.xs
approval_queue.xs
enriched_records.xs
enrichment_jobs.xs
source_records.xs
workflow_test/
deaq_enrichment_to_approval_flow.xs
workspace/
templates.xs
How it works
- Import —
POST /records/importpulls a row from Postgres intosource_recordsand opens apendingenrichment_jobsrow. - Enrich —
POST /records/{record_id}/enrichcalls the provider, then scores (deaq_score) and classifies (deaq_classify):- Score 0–100 starts at 100 and deducts for missing
company_name/domain/industry/employee_countand for providerconfidencebelow 0.75 (clamped ≥ 0). - Classification — score ≥ 85 →
approved_auto, 50–84 →needs_review, < 50 →rejected_auto. approved_auto/rejected_autostore the result inenriched_recordswith no human action.needs_reviewopens anapproval_queuerow, writes acreatedevent, and sends a Slack alert (only forneeds_review).- Every attempt updates
enrichment_jobs; a failed provider call incrementsattempt_count, and after 3 attempts the record can't be retried.
- Score 0–100 starts at 100 and deducts for missing
- Review —
GET /approvals/pendinglists open items. - Resolve —
approve/rejectflipsapproval_statusand appends an event; rejection requires a non-emptyreview_note.
The scoring and classification are pure XanoScript functions (unit-tested at every boundary), so the rules are visible and adjustable in one place.
Quick start
Start with your coding agent. Paste the prompt below into a local MCP-capable coding agent — Claude Code, Cursor, Windsurf, and others. It installs the Xano CLI, connects Xano, and imports this template.
Start building in Xano: Access the prompt at https://go.xano.co/start-xano-with-template-skill and run it here with data-enrichment-approval-queue-postgres-slack as your template.
The agent will walk you through the setup below.
- Push the backend to a Xano workspace (the CLI/agent flow below does this).
- Run the loop —
POST /records/import→POST /records/{record_id}/enrich→GET /approvals/pending→approve/reject. - It runs before you wire credentials. The Postgres fetch, enrichment call, and Slack alert are doc-mocked so the full flow exercises end-to-end; with
API_AUTH_SECRETunset the auth check is a no-op. Set the environment variables to connect your real Postgres, enrichment provider, and Slack workspace.
API surface
All endpoints live in the DataEnrichment API group (canonical deaq-data-enrichment), take an api_secret field (matched against API_AUTH_SECRET), and write an api_request_logs row before auth is evaluated — so even a rejected request is audited (the shared deaq_authorize_and_log gate runs first).
| Method | Path | Purpose |
|---|---|---|
POST |
/records/import |
Fetch a row from Postgres → source_records; open a pending enrichment_jobs row. |
POST |
/records/{record_id}/enrich |
Enrich, score, and classify; on needs_review queue it and Slack-alert. |
GET |
/approvals/pending |
List approval_queue rows with approval_status = pending. |
POST |
/approvals/{approval_id}/approve |
Set approved, write an approved event. |
POST |
/approvals/{approval_id}/reject |
Set rejected (requires a note), write a rejected event. |
Database Tables
- source_records — rows imported from Postgres, keyed by
external_record_id. - enriched_records — the stored enrichment result for auto-accepted/rejected records.
- enrichment_jobs — one job per record: status, score, classification, and
attempt_count(3-try cap). - approval_queue — the human review queue; one row per
needs_reviewrecord (approval_status). - approval_events — append-only audit trail of
created/approved/rejecteddecisions. - api_request_logs — one row per API call, written before auth so every request (even rejected) is audited.
Testing
Run from a deployed workspace:
- Unit tests (
xano unit_test run_all) — the scoring (deaq_score) and classification (deaq_classify) rules, with a case for every deduction, theconfidence == 0.75and score boundary (49/50/84/85) edges, and the min-0 clamp. - Workflow test (
xano workflow_test run_all) —deaq_enrichment_to_approval_flow: import → enrich → aneeds_reviewrecord lands in the queue → approve, asserting the statuses and event trail, against doc-mocked Postgres/enrichment/Slack.
Environment variables
Set these to connect the real external systems. The flow runs without them (externals doc-mocked, auth no-op).
POSTGRES_CONNECTION_STRING— connection string for the external Postgres theimportstep reads from.ENRICHMENT_API_BASE_URL— base URL of your REST enrichment provider.ENRICHMENT_API_KEY— API key for the enrichment provider.SLACK_WEBHOOK_URL— incoming-webhook URL alerts are posted to forneeds_reviewrecords.API_AUTH_SECRET— shared secret every endpoint checks (via theapi_secretfield). When unset the check is a no-op so it runs out of the box; set it in production.
Postgres source schema. POST /records/import runs SELECT * FROM records WHERE external_record_id = ?, so the external Postgres must expose a records table with a unique external_record_id key — the rest of the row is stored in source_records.source_payload and forwarded to the enrichment provider. Minimal DDL to provision it:
CREATE TABLE records (
external_record_id text PRIMARY KEY,
company_name text,
domain text,
raw jsonb
);
INSERT INTO records (external_record_id, company_name, domain)
VALUES ('acct-1001', 'Beta LLC', 'beta.io');
Frequently asked questions
Get started for free today
Xano gives you everything you need to ship modern applications - fast, securely, and at scale.
Get started