DrillerDB Driller directory API

Find-a-Driller directory and state license records

Operations 2

GET /api/driller-license-lookup Search verified well-driller licenses in a state #
GET /api/find-drillers/nearby Well drilling and pump companies near a location #

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/drillerdb-com:drillerdb-com-driller-directory-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

drillerdb-com-driller-directory-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: DrillerDB Public Driller directory API
  version: '2026-10-07'
  summary: Well data, driller directory, and DrillerDB application APIs
  description: 'Machine-readable description of every public DrillerDB endpoint, in three groups, each with its own server:


    1. drillerdb.com: free, unauthenticated JSON endpoints (well depth and water-table lookup, driller directory and license search, ZIP geocoding, platform stats, conference calendars). Errors are {error, message}. An /api path with no endpoint answers 404, and a method an endpoint does not support answers 405 with an Allow header; both bodies add hint and documentation (ApiRoutingError).

    2. app.drillerdb.com/api/v1: read-only access to a DrillerDB customer''s own projects, invoices, work orders, contacts, equipment and inventory. Requires an X-API-Key issued to an Enterprise-plan company; each key carries scopes and each operation names the scope it needs in x-required-scope. Errors are {error:{code,message,hint}, meta:{request_id}, links}.

    3. enterprise.drillerdb.com/api/mcp: Model Context Protocol server for DrillerDB Enterprise (prospect intelligence), OAuth 2.1 with the mcp:read:enterprise scope.


    Rate limits on drillerdb.com: 500 requests per IP address per 60 seconds, counted across page views and API requests together, not per endpoint. Every /api response the limiter counted carries RateLimit-Policy and RateLimit (draft-ietf-httpapi-ratelimit-headers-11); a 429 also carries Retry-After in seconds.


    Versioning and deprecation: the keyed APIs carry their major version in the path (app.drillerdb.com/api/v1, console.drillerdb.com/api/partner/v1). Additive changes, such as new fields, new optional parameters and new operations, stay in the current version; a breaking change ships under a new major version path. A deprecated version says so on every response with the Deprecation header (RFC 9745), the Sunset header (RFC 8594) and a Link header with rel="deprecation". At least 12 months pass between the date a version first sends the Deprecation header and its Sunset date. No version is deprecated today. Details: https://drillerdb.com/docs/integrations/api-conventions.


    Any HTML page on drillerdb.com can be fetched as Markdown with Accept: text/markdown. Site index for agents: https://drillerdb.com/llms.txt.'
  termsOfService: https://drillerdb.com/terms
  contact:
    name: DrillerDB
    url: https://drillerdb.com/contact-us
    email: support@drillerdb.com
servers:
- url: https://drillerdb.com
  description: drillerdb.com public endpoints (no key)
tags:
- name: Driller directory
  description: Find-a-Driller directory and state license records
paths:
  /api/driller-license-lookup:
    get:
      tags:
      - Driller directory
      operationId: lookupDrillerLicense
      summary: Search verified well-driller licenses in a state
      description: Searches verified state license records by driller or company name and/or license number within one state, joined to the Find-a-Driller directory. When nothing matches, nearbyDrillers lists verified drillers in that state; an empty matches array never means a driller is unlicensed. Public, no key. Rate limited per IP.
      parameters:
      - name: state
        in: query
        required: true
        description: Two-letter state abbreviation (e.g. WI) or state slug (e.g. wisconsin).
        schema:
          type: string
          minLength: 2
        example: WI
      - name: name
        in: query
        required: false
        description: Driller or company name, at least 2 characters. Required unless license is given.
        schema:
          type: string
          minLength: 2
        example: drilling
      - name: license
        in: query
        required: false
        description: License number, at least 2 characters. Required unless name is given.
        schema:
          type: string
          minLength: 2
        example: '1234'
      responses:
        '200':
          description: Matches (possibly empty) and, on a miss, verified drillers in the state.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DrillerLicenseLookupResponse'
          headers:
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimitPolicy'
            RateLimit:
              $ref: '#/components/headers/RateLimit'
        '400':
          description: Unknown state, or neither name nor license was long enough to search.
          content:
            application/json:
              schema:
                allOf:
                - $ref: '#/components/schemas/SiteError'
                - properties:
                    error:
                      type: string
                      enum:
                      - invalid_state
                      - invalid_query
          headers:
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimitPolicy'
            RateLimit:
              $ref: '#/components/headers/RateLimit'
        '429':
          description: Too many requests from this IP address. Wait the number of seconds in Retry-After.
          content:
            application/json:
              schema:
                allOf:
                - $ref: '#/components/schemas/SiteError'
                - properties:
                    error:
                      type: string
                      enum:
                      - rate_limited
          headers:
            Retry-After:
              $ref: '#/components/headers/RetryAfter'
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimitPolicy'
            RateLimit:
              $ref: '#/components/headers/RateLimit'
        '500':
          description: The lookup failed; retry.
          content:
            application/json:
              schema:
                allOf:
                - $ref: '#/components/schemas/SiteError'
                - properties:
                    error:
                      type: string
                      enum:
                      - lookup_failed
          headers:
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimitPolicy'
            RateLimit:
              $ref: '#/components/headers/RateLimit'
  /api/find-drillers/nearby:
    get:
      tags:
      - Driller directory
      operationId: listNearbyDrillers
      summary: Well drilling and pump companies near a location
      description: Public directory of well drilling and pump service companies. Give a ZIP code or a lat/lng to get companies within the radius, sorted by relevance with distance_miles filled in; give no location to get a national list sorted by quality. Only public directory fields are returned. Public, no key; the ZIP branch is rate limited per IP.
      parameters:
      - name: zip
        in: query
        required: false
        description: Five-digit US ZIP code. Used when lat/lng are absent.
        schema:
          type: string
          pattern: ^\d{5}$
        example: '54401'
      - name: lat
        in: query
        required: false
        description: Latitude in decimal degrees.
        schema:
          type: number
          minimum: -90
          maximum: 90
        example: 44.9591
      - name: lng
        in: query
        required: false
        description: Longitude in decimal degrees.
        schema:
          type: number
          minimum: -180
          maximum: 180
        example: -89.6301
      - name: radius
        in: query
        required: false
        description: Search radius in miles when a location is given. Default and maximum useful value 150.
        schema:
          type: number
          default: 150
        example: 25
      - name: limit
        in: query
        required: false
        description: Maximum companies to return. Default 250 with a location, 150 without; capped at 250.
        schema:
          type: integer
          minimum: 1
          maximum: 250
        example: 5
      - name: trade
        in: query
        required: false
        description: Only companies in this category. Omit for every category the directory lists.
        schema:
          type: string
          enum:
          - water_well
          - geothermal
          - environmental
        example: geothermal
      responses:
        '200':
          description: Companies near the location (or the national list). Empty when the directory backend is unavailable.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NearbyDrillersResponse'
          headers:
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimitPolicy'
            RateLimit:
              $ref: '#/components/headers/RateLimit'
        '400':
          description: zip is not five digits.
          content:
            application/json:
              schema:
                allOf:
                - $ref: '#/components/schemas/SiteError'
                - properties:
                    error:
                      type: string
                      enum:
                      - invalid_zip
          headers:
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimitPolicy'
            RateLimit:
              $ref: '#/components/headers/RateLimit'
        '404':
          description: The ZIP code is not known.
          content:
            application/json:
              schema:
                allOf:
                - $ref: '#/components/schemas/SiteError'
                - properties:
                    error:
                      type: string
                      enum:
                      - not_found
          headers:
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimitPolicy'
            RateLimit:
              $ref: '#/components/headers/RateLimit'
        '429':
          description: Too many requests from this IP address. Wait the number of seconds in Retry-After.
          content:
            application/json:
              schema:
                allOf:
                - $ref: '#/components/schemas/SiteError'
                - properties:
                    error:
                      type: string
                      enum:
                      - rate_limited
          headers:
            Retry-After:
              $ref: '#/components/headers/RetryAfter'
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimitPolicy'
            RateLimit:
              $ref: '#/components/headers/RateLimit'
        '503':
          description: The ZIP geocoder is temporarily unavailable.
          content:
            application/json:
              schema:
                allOf:
                - $ref: '#/components/schemas/SiteError'
                - properties:
                    error:
                      type: string
                      enum:
                      - lookup_failed
          headers:
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimitPolicy'
            RateLimit:
              $ref: '#/components/headers/RateLimit'
components:
  schemas:
    LicensedDriller:
      type: object
      properties:
        name:
          type: string
        slug:
          type: string
          description: 'Directory profile: https://drillerdb.com/contractor/{slug}.'
        city:
          type:
          - string
          - 'null'
        activeLicenses:
          type: integer
      required:
      - name
      - slug
      - city
      - activeLicenses
    DrillerLicenseLookupResponse:
      type: object
      properties:
        state:
          type: string
        matches:
          type: array
          items:
            $ref: '#/components/schemas/LicenseMatch'
        nearbyDrillers:
          type: array
          description: Only populated when matches is empty.
          items:
            $ref: '#/components/schemas/LicensedDriller'
      required:
      - state
      - matches
      - nearbyDrillers
    LicenseMatch:
      type: object
      properties:
        licenseNumber:
          type: string
        state:
          type: string
          description: Two-letter state.
        licenseType:
          type:
          - string
          - 'null'
        status:
          type:
          - string
          - 'null'
          description: 'The state record''s status. unverified: the record came from a state license roster DrillerDB cannot re-check, so it is reported as neither active nor expired; expiresDate and lastVerifiedAt are null for it. Confirm it with the state board.'
          enum:
          - active
          - expired
          - suspended
          - revoked
          - unverified
          - null
        holderName:
          type:
          - string
          - 'null'
        holderType:
          type:
          - string
          - 'null'
          enum:
          - individual
          - company
          - null
        issuedDate:
          type:
          - string
          - 'null'
        expiresDate:
          type:
          - string
          - 'null'
        lastVerifiedAt:
          type:
          - string
          - 'null'
        sourceUrl:
          type:
          - string
          - 'null'
          description: State board record, https only.
        companyName:
          type:
          - string
          - 'null'
        companySlug:
          type:
          - string
          - 'null'
          description: 'Directory profile: https://drillerdb.com/contractor/{companySlug}.'
        companyCity:
          type:
          - string
          - 'null'
      required:
      - licenseNumber
      - state
      - licenseType
      - status
      - holderName
      - holderType
      - issuedDate
      - expiresDate
      - lastVerifiedAt
      - sourceUrl
      - companyName
      - companySlug
      - companyCity
    NearbyDrillersResponse:
      type: object
      properties:
        companies:
          type: array
          items:
            $ref: '#/components/schemas/DirectoryCompany'
      required:
      - companies
    SiteError:
      type: object
      description: Error body returned by every drillerdb.com JSON endpoint.
      properties:
        error:
          type: string
          description: Machine-readable code.
        message:
          type: string
          description: What went wrong and what to do.
      required:
      - error
      - message
    DirectoryCompany:
      type: object
      description: Public directory fields only; keys absent when empty.
      properties:
        id:
          type:
          - integer
          - string
        name:
          type: string
        company_name:
          type: string
        phone:
          type: string
        slug:
          type: string
          description: 'Directory profile: https://drillerdb.com/contractor/{slug}.'
        city:
          type: string
        state:
          type: string
        zip:
          type: string
        latitude:
          type: number
        longitude:
          type: number
        distance_miles:
          type: number
          description: Present when a location was given.
        distanceMiles:
          type: number
        is_featured:
          type:
          - boolean
          - integer
        is_claimed:
          type:
          - boolean
          - integer
        company_id:
          type:
          - integer
          - string
        logo:
          type: string
        service_categories:
          type: array
          items: {}
        recent_wells:
          type: integer
        trade:
          type: string
          enum:
          - water_well
          - geothermal
          - environmental
          description: 'The category the directory lists the company under: water well, geothermal or environmental drilling.'
        google_rating:
          type:
          - number
          - string
          description: Average Google rating; the directory backend may serve it as a decimal string (e.g. "4.8").
        google_review_count:
          type: integer
      required:
      - id
      - name
  headers:
    RetryAfter:
      description: Seconds to wait before the next request (RFC 9110, section 10.2.3).
      schema:
        type: integer
        minimum: 1
      example: 45
    RateLimit:
      description: 'Current service limit (draft-ietf-httpapi-ratelimit-headers-11, section 4): r = requests left, t = seconds until the oldest counted request leaves the 60-second window. Absent when the limiter did not count the request.'
      schema:
        type: string
      example: '"default";r=499;t=60'
    RateLimitPolicy:
      description: 'Quota policy (draft-ietf-httpapi-ratelimit-headers-11, section 3): 500 requests per 60 seconds per IP address, counted across page views and API requests together, not per endpoint. Sent whenever the limiter counted the request.'
      schema:
        type: string
      example: '"default";q=500;w=60'
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
      description: Company API key issued in DrillerDB Settings > API Access (Enterprise plan). Keys are scoped; the scopes a key may hold are projects:read, invoices:read, work_orders:read, contacts:read, equipment:read and inventory:read. A key lacking the scope an operation needs receives 403 INSUFFICIENT_SCOPE with meta.required_scope.
    EnterpriseMcpOAuth:
      type: oauth2
      description: 'OAuth 2.1 authorization-code flow with PKCE (S256), as published at https://enterprise.drillerdb.com/.well-known/oauth-authorization-server. Dynamic client registration is available at https://enterprise.drillerdb.com/oauth/register. Tokens are presented as Bearer in the Authorization header. Protected-resource metadata (RFC 9728): https://enterprise.drillerdb.com/.well-known/oauth-protected-resource.'
      flows:
        authorizationCode:
          authorizationUrl: https://enterprise.drillerdb.com/oauth/authorize
          tokenUrl: https://enterprise.drillerdb.com/oauth/token
          refreshUrl: https://enterprise.drillerdb.com/oauth/token
          scopes:
            mcp:read:enterprise: Read drilling-company prospect data, lead scores, lists, territories, and market signals on the user's behalf (read-only).
externalDocs:
  description: When to use DrillerDB and how an agent calls us (llms.txt)
  url: https://drillerdb.com/llms.txt
x-generated-by: scripts/build-openapi.mjs
x-legacy-spec-source: https://app.drillerdb.com/api/v1/openapi.json