GoodLeads Classification API

The classification API from GoodLeads — 4 operation(s) for classification.

GitHub OpenAPI

Operations 4

GET /api/v1/classification/coverage Get Coverage #
GET /api/v1/classification/fp-sample Get Fp Sample #
POST /api/v1/classification/taxonomy-proposal Post Taxonomy Proposal #
POST /api/v1/classification/blast-radius Post Blast Radius #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/goodleads-club:goodleads-club-classification-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

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.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

goodleads-club-classification-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Formation GTM Classification API
  description: GoodLeads Formation Data Platform — scored, enriched, campaign-ready leads.
  version: 0.1.0
tags:
- name: Classification
paths:
  /api/v1/classification/coverage:
    get:
      tags:
      - Classification
      summary: Get Coverage
      description: 'Coverage summary for the classification brain.


        Returns total / classified / unclassified counts, confidence-tier

        distribution, and a top-K sample of unclassified entity names. The

        agent tokenizes the sample natively (no server-side tokenization).'
      operationId: get_coverage_api_v1_classification_coverage_get
      security:
      - APIKeyHeader: []
      parameters:
      - name: state
        in: query
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          description: Two-letter state code (CO, FL, VA, NY); omit for cross-state
          title: State
        description: Two-letter state code (CO, FL, VA, NY); omit for cross-state
      - name: sector
        in: query
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          description: industry_sector to scope; omit for all sectors
          title: Sector
        description: industry_sector to scope; omit for all sectors
      - name: top_tokens
        in: query
        required: false
        schema:
          type: integer
          maximum: 200
          minimum: 1
          description: How many top unclassified entity names to return for token-mining
          default: 30
          title: Top Tokens
        description: How many top unclassified entity names to return for token-mining
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CoverageResponse'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /api/v1/classification/fp-sample:
    get:
      tags:
      - Classification
      summary: Get Fp Sample
      description: 'Random sample of N records currently classified into `sector` for

        false-positive audit.


        Uses `ORDER BY random() LIMIT n` — fine at our scale (≤ ~1M rows per

        sector cross-state). If sample sizes climb past ~100, swap to

        TABLESAMPLE BERNOULLI which is constant-time. Random ordering rather

        than recency on purpose — FP audit needs an unbiased sample so the

        agent isn''t seeing only the most recent classification decisions.'
      operationId: get_fp_sample_api_v1_classification_fp_sample_get
      security:
      - APIKeyHeader: []
      parameters:
      - name: sector
        in: query
        required: true
        schema:
          type: string
          description: industry_sector to sample (required)
          title: Sector
        description: industry_sector to sample (required)
      - name: n
        in: query
        required: false
        schema:
          type: integer
          maximum: 100
          minimum: 1
          default: 30
          title: N
      - name: state
        in: query
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          description: Optional state scope (CO/FL/VA/NY)
          title: State
        description: Optional state scope (CO/FL/VA/NY)
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FpSampleResponse'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /api/v1/classification/taxonomy-proposal:
    post:
      tags:
      - Classification
      summary: Post Taxonomy Proposal
      description: 'Accept a structured taxonomy proposal from the agent and persist it

        as an AgentFinding (finding_type=''revenue_opportunity'', domain=''data_quality'').


        The proposal action + target + evidence land in the finding''s

        evidence JSONB so the existing approval queue (and the agent''s

        `evaluate_peer_findings` skill) reads them with the same machinery

        it uses for every other finding type. Proposals are always created

        `pending` — no auto-approval path; Gib reviews on the standard

        cadence (Tenet #31 — blast radius must be visible before approval).'
      operationId: post_taxonomy_proposal_api_v1_classification_taxonomy_proposal_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TaxonomyProposalRequest'
        required: true
      responses:
        '201':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TaxonomyProposalResponse'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
      security:
      - APIKeyHeader: []
  /api/v1/classification/blast-radius:
    post:
      tags:
      - Classification
      summary: Post Blast Radius
      description: 'Blast-radius preflight for a proposed taxonomy diff.


        Tenet #31 enforcement: every keyword / taxonomy proposal must ship

        with three numbers (records newly classified, records rebucketed,

        records confidence-tier shifted). This endpoint produces those

        numbers by loading the current FusionEngine, applying the proposed

        diff in-memory, classifying a representative sample, and diffing

        against current labels.


        Response shape mirrors `/api/v1/enrichment/preview` — same

        `total / eligible / by_segment / sample / cost_implication` skeleton

        so reviewers read both with the same mental model.


        Scope discipline for v1:

        - add_keyword is fully modelled.

        - split / merge / add_sub return a partial response with

        `requires_offline_review=true` and the sample populated —

        enough to file a Tier-2 finding with legible-but-partial

        numbers; full modelling lands when PR 1''s taxonomy IP tables

        are populated.'
      operationId: post_blast_radius_api_v1_classification_blast_radius_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BlastRadiusRequest'
        required: true
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BlastRadiusResponse'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
      security:
      - APIKeyHeader: []
components:
  schemas:
    TaxonomyProposalRequest:
      properties:
        agent_id:
          type: string
          title: Agent Id
          description: Agent that authored the proposal
        action:
          type: string
          title: Action
          description: 'One of: [''add_keyword'', ''add_sub'', ''merge'', ''split'']'
        target:
          additionalProperties: true
          type: object
          title: Target
          description: 'What the proposal is changing. Shape depends on action: {industry_id} for merge, {sector, name} for split/add_sub, {keyword, industry_id_or_industry_sub_id, tier} for add_keyword.'
        evidence:
          additionalProperties: true
          type: object
          title: Evidence
          description: 'Supporting data: corpus_frequency, sample_records, blast_radius (records newly classified / rebucketed / confidence-tier shifted), source_findings.'
        title:
          type: string
          title: Title
          description: One-line summary for the findings table
        description:
          type: string
          title: Description
          description: Full proposal narrative
        state:
          anyOf:
          - type: string
          - type: 'null'
          title: State
        session_id:
          anyOf:
          - type: string
          - type: 'null'
          title: Session Id
      type: object
      required:
      - agent_id
      - action
      - target
      - evidence
      - title
      - description
      title: TaxonomyProposalRequest
    BlastRadiusResponse:
      properties:
        state:
          anyOf:
          - type: string
          - type: 'null'
          title: State
        total:
          type: integer
          title: Total
        eligible:
          anyOf:
          - type: integer
          - type: 'null'
          title: Eligible
        by_segment:
          anyOf:
          - additionalProperties: true
            type: object
          - type: 'null'
          title: By Segment
        sample:
          items:
            $ref: '#/components/schemas/BlastRadiusSampleRecord'
          type: array
          title: Sample
        cost_implication:
          type: string
          title: Cost Implication
        runtime_warning:
          anyOf:
          - type: string
          - type: 'null'
          title: Runtime Warning
        diff_applied:
          additionalProperties: true
          type: object
          title: Diff Applied
        requires_offline_review:
          type: boolean
          title: Requires Offline Review
          default: false
      type: object
      required:
      - state
      - total
      - eligible
      - by_segment
      - sample
      - cost_implication
      - diff_applied
      title: BlastRadiusResponse
      description: 'Response mirrors `/api/v1/enrichment/preview` so reviewers read both

        with the same mental model — `total`, `eligible`, `by_segment`, `sample`,

        `cost_implication` map 1:1.'
    BlastRadiusRequest:
      properties:
        action:
          type: string
          title: Action
          description: Diff type — one of ['add_keyword', 'add_sub', 'merge', 'split']. add_keyword is fully modelled; split / merge / add_sub return a partial response with requires_offline_review=true for v1.
        target:
          additionalProperties: true
          type: object
          title: Target
          description: 'What the diff changes. For add_keyword: {keyword, tier, sector_label, formation_code (optional)}. Other actions accept arbitrary shape so the stub path can pass them through to the proposal.'
        state:
          anyOf:
          - type: string
          - type: 'null'
          title: State
          description: Optional state scope (CO/FL/VA/NY); omit for cross-state preflight
      type: object
      required:
      - action
      - target
      title: BlastRadiusRequest
    CoverageResponse:
      properties:
        state:
          anyOf:
          - type: string
          - type: 'null'
          title: State
        sector:
          anyOf:
          - type: string
          - type: 'null'
          title: Sector
        total:
          type: integer
          title: Total
        classified:
          type: integer
          title: Classified
        unclassified:
          type: integer
          title: Unclassified
        classified_pct:
          type: number
          title: Classified Pct
        by_confidence_tier:
          additionalProperties:
            type: integer
          type: object
          title: By Confidence Tier
        sample_unclassified:
          items:
            additionalProperties: true
            type: object
          type: array
          title: Sample Unclassified
      type: object
      required:
      - state
      - sector
      - total
      - classified
      - unclassified
      - classified_pct
      - by_confidence_tier
      - sample_unclassified
      title: CoverageResponse
    FpSampleResponse:
      properties:
        sector:
          type: string
          title: Sector
        n_requested:
          type: integer
          title: N Requested
        n_returned:
          type: integer
          title: N Returned
        records:
          items:
            $ref: '#/components/schemas/FpSampleRecord'
          type: array
          title: Records
      type: object
      required:
      - sector
      - n_requested
      - n_returned
      - records
      title: FpSampleResponse
    TaxonomyProposalResponse:
      properties:
        finding_id:
          type: string
          title: Finding Id
        status:
          type: string
          title: Status
      type: object
      required:
      - finding_id
      - status
      title: TaxonomyProposalResponse
    FpSampleRecord:
      properties:
        lead_ref:
          type: string
          title: Lead Ref
        state:
          type: string
          title: State
        entity_name:
          type: string
          title: Entity Name
        entity_type:
          anyOf:
          - type: string
          - type: 'null'
          title: Entity Type
        industry_sector:
          anyOf:
          - type: string
          - type: 'null'
          title: Industry Sector
        industry_name:
          anyOf:
          - type: string
          - type: 'null'
          title: Industry Name
        industry_confidence_tier:
          anyOf:
          - type: string
          - type: 'null'
          title: Industry Confidence Tier
      type: object
      required:
      - lead_ref
      - state
      - entity_name
      - entity_type
      - industry_sector
      - industry_name
      - industry_confidence_tier
      title: FpSampleRecord
    BlastRadiusSampleRecord:
      properties:
        glid:
          type: string
          title: Glid
        name:
          type: string
          title: Name
        current:
          type: string
          title: Current
        proposed:
          type: string
          title: Proposed
      type: object
      required:
      - glid
      - name
      - current
      - proposed
      title: BlastRadiusSampleRecord
    ValidationError:
      properties:
        loc:
          items:
            anyOf:
            - type: string
            - type: integer
          type: array
          title: Location
        msg:
          type: string
          title: Message
        type:
          type: string
          title: Error Type
        input:
          title: Input
        ctx:
          type: object
          title: Context
      type: object
      required:
      - loc
      - msg
      - type
      title: ValidationError
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: '#/components/schemas/ValidationError'
          type: array
          title: Detail
      type: object
      title: HTTPValidationError
  securitySchemes:
    APIKeyHeader:
      type: apiKey
      in: header
      name: X-API-Key