---
title: "Preflight Enrichment"
method: POST
path: "/enrichment/preflight"
tags: ["Enrichment"]
---

# Preflight Enrichment

`POST /enrichment/preflight`

## Request

- Base URL: `https://be.graph8.com/api/v1`
- URL: `https://be.graph8.com/api/v1/enrichment/preflight`
- Auth: HTTP bearer

Check an enrichment request before running it. Free: nothing is written,
queued or charged.

Errors for input a run could never use: an unknown `mode` (400
`invalid_mode`), zero or negative contact IDs (400 `invalid_record_ids`), a
list that is not in this organization (404 `list_not_found`), an unknown
`target_field` (400 `unsupported_field`), an unknown provider (400
`unsupported_provider` / `unsupported_provider_for_field`) and a missing AI
config (404 `ai_config_not_found`).

Otherwise returns what the run would do: the unique contact IDs (repeats
are counted once), contacts that are not on the list, the providers that
would run, and plain warnings such as "Lusha is not connected: add your
key" or "No providers chosen: using your saved pipeline".

## Headers

- `Authorization` string, nullable
- `X-Target-Org-Id` string, nullable

## Request body

- EnrichmentPreflightRequest: Check an enrichment request before running it. Free: nothing is written, queued or charged. Takes the same inputs as the MCP `g8_enrich_contacts` tool so a preview can say up front whether the run would work.
  - `list_id` integer, required: List ID the contacts belong to
  - `contact_ids` integer[], required: Contact IDs to enrich (duplicates are counted once)
  - `mode` string: 'auto' (AI when ai_group_id is set, else waterfall), 'waterfall' or 'ai-research'
  - `ai_group_id` string, nullable: group_id of a saved AI enrichment config (required for 'ai-research')
  - `providers` string[], nullable: Ordered provider names for a waterfall run. Omit to use the list's saved pipeline; an empty list also uses the saved pipeline (a warning says so).
  - `target_field` string, nullable: Column to enrich: a canonical CONTACT_*/COMPANY_* column or a synonym like 'phone' or 'email'
  - `email_verification` boolean: Add ZeroBounce email verification

## Response `200`

Successful Response

- ApiResponseEnrichmentPreflightResponse
  - `data` EnrichmentPreflightResponse, required: What a run with these inputs would do. Errors (unknown list, mode, field or provider, impossible contact IDs) come back as 400/404 instead.
    - `list_id` integer, required
    - `list_name` string, nullable
    - `mode` string, required: Resolved mode: 'waterfall' or 'ai-research'
    - `contact_ids` integer[], required: Contact IDs that will be enriched: duplicates removed, order kept
    - `contact_count` integer, required: Number of unique contacts (the count credits are estimated on)
    - `duplicates_removed` integer: How many repeated contact IDs were dropped
    - `not_in_list` integer[]: Contact IDs that are not on the list; the run skips them and does not charge for them
    - `target_field` string, nullable: Canonical column for target_field, when given
    - `providers` string[]: Providers that would run, in order (empty = the saved pipeline)
    - `uses_saved_pipeline` boolean: True when the list's saved pipeline (or the graph8 default) would run
    - `providers_detail` ProviderStepDetail[]
      - `provider` string, required
      - `is_system_provider` boolean, required: True = uses graph8-managed system key (charges credits). False = uses org BYOK key.
      - `credential_source` 'system' | 'byok', required: 'system' = graph8-funded; 'byok' = org's own key.
      - `credential_ready` boolean, required: True if the step can actually run: system steps are always ready; BYOK steps are ready only when the org has an active key for that provider.
    - `missing_credentials` string[]: Providers whose step would be skipped because the org has no key for them
    - `warnings` string[]: Plain-language advisories for the user
    - `pipeline_column_id` string, nullable: column_id of the saved waterfall pipeline the run would reuse. Null when the run would create a new pipeline (it is created on confirm) or in 'ai-research' mode. Pass it to POST /enrichment/waterfall/validate-credits for the record-exact quote.
    - `credits_per_record` integer, nullable: Waterfall only: the most one contact can cost, in graph8 credits. A record is charged its dearest graph8-funded step that finds a value (steps are not added together); steps on your own key cost 0. Null when the pipeline could not be priced.
    - `priced_records` integer, nullable: Waterfall only: contacts the price covers (unique contacts that are on the list).
    - `max_total_credits` integer, nullable: Waterfall only: priced_records x credits_per_record, the most this run can charge. Records the pipeline skips (values already present, run conditions) cost less. Null when not priced.
  - `pagination` PaginationMeta
    - `page` integer, required: Current page number (1-indexed)
    - `limit` integer, required: Items per page
    - `total` integer, required: Total number of items
    - `has_next` boolean, required: Whether there are more pages
    - `next_cursor` string, nullable: Opaque cursor for the next page; null when there are no more items. Pass it back as the `cursor` query param to fetch the following page without computing page numbers.
    - `total_available` integer, nullable: Search endpoints only: how many records really match, when known. Can be larger than `total`, which is capped at the 10,000 results that can be paged. For company search this is a distinct-company estimate. Null when unknown; absent outside search.
    - `total_is_lower_bound` boolean, nullable: Search endpoints only: true when more records match than `total` shows (the result set is larger than the 10,000 results that can be paged). Absent outside search.
    - `notes` string[], nullable: Search endpoints only: plain-language notes about the result, e.g. that more records match than can be paged, or that a reversed `between` range was put in order.

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/graph8/apis/graph8-developer-api.md) · [All operations](https://skmtc.dev/graph8/apis/graph8-developer-api/llms.txt) · [OpenAPI document](https://skmtc.dev/graph8/apis/graph8-developer-api/revisions/2e7cfa0ca921?raw)
