Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we
store it to create your key and to recognise you if you sign in with another
provider. See our Privacy Policy and
Terms.
openapi: 3.2.0
info:
title: EpicDirectories Screening API
description: API-first directory data platform.
version: '1.0'
contact: {}
servers:
- url: https://api.epicdirectories.com
description: Production
- url: http://localhost:3333
description: Local development
tags:
- name: Screening
paths:
/v1/directories/{directoryId}/screening:
get:
operationId: ScreeningController_report
summary: Which listings point at a site that is not really there
description: 'Reads the probe evidence already on record and applies this directory’s screening policy. **Fetches nothing** — run `POST .../site-probes/sweep` with `kind: "site"` first, or the answer is about hosts nobody has looked at.
Four verdicts, one per listing, most severe first: `site-dead`, `site-parked`, `site-placeholder`, `site-thin`.
**`summary.unscreened` is the gap, not a pass.** Those listings have no site evidence either way. `summary.inconclusive` counts hosts that refused us or that we could not reach — never a verdict, because a Cloudflare challenge is a fact about our crawler and not about the business.'
parameters:
- name: directoryId
required: true
in: path
schema:
type: string
- name: term
required: false
in: query
description: Only this verdict
schema:
type: string
- name: limit
required: false
in: query
description: Rows returned (default 200)
schema:
type: number
responses:
'200':
description: Flagged listings plus a coverage summary
'404':
description: Directory not found or not yours
tags:
- Screening
security:
- bearer: []
/v1/directories/{directoryId}/screening/apply:
post:
operationId: ScreeningController_apply
summary: Tag the flagged listings, and hold the confident ones in draft
description: 'Writes the verdicts as terms in the review taxonomy, creating the taxonomy and only the terms actually earned.
**Additive.** Terms are written directly, so a listing’s services, industries and regions are untouchable by this endpoint — unlike `PUT .../terms`, which is replace-all.
**Self-correcting.** A screening term that no longer applies is removed, so a site that comes back stops being tagged as dead. Only the four screening terms are ever removed; your own review tags are never touched.
**It never re-publishes.** `site-dead`, `site-parked` and `site-placeholder` pull a published listing back to draft. Nothing puts it back — a listing may have been edited or merged since, and silently re-publishing is a change nobody asked for. Pass `hold: false` for a tag-only pass.
Send `dryRun: true` to see the counts without writing. It previews both halves — `wouldTag`/`wouldHold` for what would be added, `wouldClear` for what would be removed. Watch `wouldClear`: clearing recovered listings is uncapped and is not drawn from the capped selection, so a converged directory can preview zero tags and still have removals pending.'
parameters:
- name: directoryId
required: true
in: path
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ApplyScreeningDto'
responses:
'201':
description: Counts of what changed
'404':
description: Directory not found or not yours
tags:
- Screening
security:
- bearer: []
components:
schemas:
ApplyScreeningDto:
type: object
properties:
dryRun:
type: boolean
description: Report what would change and write nothing. The counts are computed by the same code path that does the writing, so a dry run cannot disagree with the real one.
default: false
hold:
type: boolean
description: 'Pull flagged listings back to draft as well as tagging them. On by default: which verdicts unpublish is a property of the policy, not of the caller. Set false for a tag-only pass when you want to read the queue before anything leaves the directory.'
default: true
limit:
type: number
description: How many listings to act on, capped at 2000. The response reports `deferred` when the cap bit rather than implying full coverage.
minimum: 1
maximum: 2000
default: 2000
securitySchemes:
bearer:
scheme: bearer
bearerFormat: JWT
type: http
apiKey:
type: apiKey
in: header
name: x-api-key
x-provenance:
method: harvested
publisher: EpicDirectories
source: https://api.epicdirectories.com/openapi.json
note: split by refine-openapis from the provider's own published document, verified by fetch (openapi/_original/*.fetch.json);
stamped by stamp-openapi-provenance.py (roadmap#793)