---
openapi: 3.0.3
info:
  title: VeriMails API
  version: 1.0.0
  summary: Email verification, bulk list verification, and an Email Finder.
  description: |-
    VeriMails verifies email addresses with syntax validation, MX record lookup, DNS checks, and a live SMTP handshake where the receiving server allows it. It detects catch-all domains, disposable addresses, and role-based addresses, and returns an overall deliverability result.

    The API also includes asynchronous bulk CSV verification and an Email Finder for missing business contact emails.

    Authentication: every endpoint except the health check requires an API key sent as a Bearer token. Issue keys from your VeriMails dashboard.

    Credits: verification costs 1 credit per email address. The Email Finder costs 10 credits, charged only when a verified email is found. New accounts start with 100 free credits, and prepaid credits never expire.
  contact:
    name: VeriMails Support
    email: support@verimails.com
    url: https://verimails.com/contact
  termsOfService: https://verimails.com/terms
externalDocs:
  description: Full API documentation
  url: https://verimails.com/docs
servers:
- url: https://verimails.com
  description: Production
security:
- bearerAuth: []
tags:
- name: Verification
  description: Verify whether a single email address is real and deliverable.
- name: Bulk Verification
  description: Verify entire lists by uploading a CSV file and polling an asynchronous job.
- name: Email Finder
  description: Find and verify missing business contact emails from first name, last name, and company domain.
- name: Health
  description: Service status and availability.
paths:
  "/api/verify/single":
    post:
      tags:
      - Verification
      summary: Verify one email address
      description: Runs syntax validation, MX record lookup, DNS checks, and a live SMTP handshake where the receiving server allows it. Catch-all domains are detected and flagged. Costs 1 credit.
      operationId: verifySingle
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/VerifyRequest"
            example:
              email: person@example.com
      responses:
        '200':
          description: Verification result.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/SingleVerifyResponse"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '402':
          "$ref": "#/components/responses/InsufficientCredits"
        '422':
          "$ref": "#/components/responses/ValidationError"
        '429':
          "$ref": "#/components/responses/RateLimited"
  "/api/bulk":
    post:
      tags:
      - Bulk Verification
      summary: Upload a CSV for bulk verification
      description: Uploads a CSV file and starts an asynchronous bulk verification job. Provide `email_column` when the email field is not auto-detected. Recognised headers include email, Email, Email Address, emails, work_email, business_email, and contact_email. Headerless single-column files are also supported. Each address costs 1 credit.
      operationId: createBulkJob
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required:
              - file
              properties:
                file:
                  type: string
                  format: binary
                  description: CSV file of email addresses to verify.
                email_column:
                  type: string
                  description: Name of the column holding email addresses. Optional when the column can be auto-detected.
      responses:
        '200':
          description: Bulk verification job created.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/BulkJobResponse"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '402':
          "$ref": "#/components/responses/InsufficientCredits"
        '422':
          "$ref": "#/components/responses/ValidationError"
  "/api/bulk/{job_id}":
    get:
      tags:
      - Bulk Verification
      summary: Get bulk job status
      description: Returns the current status and running counts of a bulk verification job. Poll this endpoint until `status` is `completed`.
      operationId: getBulkJob
      parameters:
      - name: job_id
        in: path
        required: true
        description: The bulk job ID returned when the job was created.
        schema:
          type: integer
      responses:
        '200':
          description: Current job status.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/BulkJobResponse"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '404':
          "$ref": "#/components/responses/NotFound"
  "/api/bulk/{job_id}/download":
    get:
      tags:
      - Bulk Verification
      summary: Download bulk results as CSV
      description: Downloads the completed verification results as a CSV file. Returns 409 if the job has not finished yet.
      operationId: downloadBulkResults
      parameters:
      - name: job_id
        in: path
        required: true
        description: The bulk job ID.
        schema:
          type: integer
      responses:
        '200':
          description: CSV file of verification results.
          content:
            text/csv:
              schema:
                type: string
                format: binary
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '404':
          "$ref": "#/components/responses/NotFound"
        '409':
          "$ref": "#/components/responses/JobNotComplete"
  "/api/find-email":
    post:
      tags:
      - Email Finder
      summary: Find an email address
      description: Finds and verifies a missing business contact email from first name, last name, and company domain. It does not return generic role inboxes. Costs 10 credits, charged only when a verified email is found.
      operationId: findEmail
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/FindEmailRequest"
            example:
              first_name: Jane
              last_name: Doe
              domain: example.com
      responses:
        '200':
          description: Finder result. `credits_used` is 10 on a verified find and 0 otherwise.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/FindEmailResponse"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '402':
          "$ref": "#/components/responses/InsufficientCredits"
        '403':
          "$ref": "#/components/responses/FeatureNotEnabled"
        '422':
          "$ref": "#/components/responses/ValidationError"
  "/api/find-email/csv":
    post:
      tags:
      - Email Finder
      summary: Upload a CSV for bulk email finding
      description: Uploads a CSV and starts an asynchronous Email Finder job. Map the required prospect columns in the dashboard or API request. Costs 10 credits per verified email found.
      operationId: createFinderCsvJob
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required:
              - file
              properties:
                file:
                  type: string
                  format: binary
                  description: CSV file of people to find emails for.
                first_name_column:
                  type: string
                  description: Name of the column holding first names.
                last_name_column:
                  type: string
                  description: Name of the column holding last names.
                domain_column:
                  type: string
                  description: Name of the column holding company domains.
      responses:
        '200':
          description: Email Finder job created.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/FinderCsvJob"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '402':
          "$ref": "#/components/responses/InsufficientCredits"
        '403':
          "$ref": "#/components/responses/FeatureNotEnabled"
        '422':
          "$ref": "#/components/responses/ValidationError"
  "/api/find-email/csv/{job_id}":
    get:
      tags:
      - Email Finder
      summary: Get Email Finder job status
      description: Returns the current status of a bulk Email Finder job. Poll until the job is complete, then download the results.
      operationId: getFinderCsvJob
      parameters:
      - name: job_id
        in: path
        required: true
        description: The Email Finder job ID.
        schema:
          type: string
      responses:
        '200':
          description: Current job status.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/FinderCsvJob"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '404':
          "$ref": "#/components/responses/NotFound"
  "/api/find-email/csv/{job_id}/download":
    get:
      tags:
      - Email Finder
      summary: Download Email Finder results as CSV
      description: Downloads the completed Email Finder results as a CSV file. Returns 409 if the job has not finished yet.
      operationId: downloadFinderCsvResults
      parameters:
      - name: job_id
        in: path
        required: true
        description: The Email Finder job ID.
        schema:
          type: string
      responses:
        '200':
          description: CSV file of Email Finder results.
          content:
            text/csv:
              schema:
                type: string
                format: binary
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '404':
          "$ref": "#/components/responses/NotFound"
        '409':
          "$ref": "#/components/responses/JobNotComplete"
  "/api/health":
    get:
      tags:
      - Health
      summary: Service health check
      description: Returns service status, version, and uptime. This endpoint does not require authentication.
      operationId: healthCheck
      security: []
      responses:
        '200':
          description: Service is reachable.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/HealthResponse"
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: 'API key issued from your VeriMails dashboard, sent as `Authorization: Bearer YOUR_API_KEY`.'
  responses:
    Unauthorized:
      description: Missing or invalid API key.
      content:
        application/json:
          schema:
            "$ref": "#/components/schemas/Error"
          example:
            detail: Invalid or missing API key.
    InsufficientCredits:
      description: The account does not have enough credits to complete the request.
      content:
        application/json:
          schema:
            "$ref": "#/components/schemas/Error"
          example:
            detail: Insufficient credits.
    FeatureNotEnabled:
      description: The requested feature is not enabled for this account.
      content:
        application/json:
          schema:
            "$ref": "#/components/schemas/Error"
          example:
            detail: The Email Finder is not enabled for this account.
    NotFound:
      description: The requested job was not found.
      content:
        application/json:
          schema:
            "$ref": "#/components/schemas/Error"
          example:
            detail: Job not found.
    JobNotComplete:
      description: The job exists but has not finished processing yet.
      content:
        application/json:
          schema:
            "$ref": "#/components/schemas/Error"
          example:
            detail: Job is still processing.
    ValidationError:
      description: The request body is invalid, usually because a required field is missing.
      content:
        application/json:
          schema:
            "$ref": "#/components/schemas/Error"
    RateLimited:
      description: Rate limit exceeded. Retry after the period indicated by the Retry-After header when present.
      content:
        application/json:
          schema:
            "$ref": "#/components/schemas/Error"
  schemas:
    VerifyRequest:
      type: object
      required:
      - email
      properties:
        email:
          type: string
          format: email
          description: The email address to verify.
          example: person@example.com
    SingleVerifyResponse:
      type: object
      description: Result of verifying a single email address.
      properties:
        email:
          type: string
          description: The email address that was verified.
        safe_to_send:
          type: boolean
          description: Whether VeriMails recommends sending to this address. True only when the returned status is `valid`.
        status:
          type: string
          description: Verification status.
          enum:
          - valid
          - invalid
          - disposable
          - catchall
          - unknown
          - likely_valid
          - risky
        confidence_score:
          type: number
          format: float
          description: Confidence score from 0.0 to 1.0.
          minimum: 0
          maximum: 1
        reason:
          type: string
          description: Human-readable explanation of the verification result.
        domain:
          type: string
          description: The email domain.
        is_disposable:
          type: boolean
          description: Whether the email is from a disposable email service.
        is_role_based:
          type: boolean
          description: Whether the email is a role-based address such as info@ or support@.
        is_free:
          type: boolean
          description: Whether the email is from a free email provider such as Gmail or Yahoo.
        is_catch_all:
          type: boolean
          description: Whether the domain is a catch-all domain that accepts mail to any address.
        mx_records:
          type: array
          description: MX records for the domain.
          items:
            type: string
      required:
      - email
      - safe_to_send
      - status
      - confidence_score
      - reason
      - domain
      - is_disposable
      - is_role_based
      - is_free
      - is_catch_all
      - mx_records
      example:
        email: jane.doe@example.com
        safe_to_send: true
        status: valid
        confidence_score: 0.95
        reason: Verification completed
        domain: example.com
        is_disposable: false
        is_role_based: false
        is_free: false
        is_catch_all: false
        mx_records:
        - mx1.example.com
    BulkJobResponse:
      type: object
      description: Status of a bulk verification job.
      properties:
        job_id:
          type: integer
          description: Unique job identifier.
        status:
          type: string
          description: Job status.
          enum:
          - pending
          - processing
          - completed
          - failed
        total_emails:
          type: integer
          description: Total number of email addresses in the upload.
        processed_emails:
          type: integer
          description: Number of addresses processed so far.
        valid_count:
          type: integer
          description: Number of addresses verified as valid.
        invalid_count:
          type: integer
          description: Number of addresses verified as invalid.
        catch_all_count:
          type: integer
          description: Number of addresses on detected catch-all domains.
        disposable_count:
          type: integer
          description: Number of addresses on disposable email services.
        unknown_count:
          type: integer
          description: Number of addresses that could not be conclusively verified.
        created_at:
          type: string
          format: date-time
          description: When the job was created.
    FindEmailRequest:
      type: object
      required:
      - first_name
      - last_name
      - domain
      properties:
        first_name:
          type: string
          minLength: 1
          description: The person's first name.
          example: Jane
        last_name:
          type: string
          minLength: 1
          description: The person's last name.
          example: Doe
        domain:
          type: string
          description: The approved company identifier used for matching.
          example: example.com
    FindEmailResponse:
      type: object
      description: Result of an Email Finder lookup.
      properties:
        found:
          type: boolean
          description: Whether a verified email address was found.
        email:
          type: string
          nullable: true
          description: The found email address, or null when none was found.
        status:
          type: string
          description: Finder outcome.
          enum:
          - found
          - not_found
          - catch_all
        confidence:
          type: number
          format: float
          description: Confidence score from 0.0 to 1.0.
          minimum: 0
          maximum: 1
        elapsed_ms:
          type: integer
          description: Time taken for the lookup, in milliseconds.
        credits_used:
          type: integer
          description: Credits charged. The Email Finder charges 10 credits only when a verified email is found, and 0 otherwise.
      example:
        found: true
        email: jane.doe@example.com
        status: found
        confidence: 0.95
        elapsed_ms: 812
        credits_used: 10
    FinderCsvJob:
      type: object
      description: Status of a bulk Email Finder job.
      properties:
        job_id:
          type: string
          description: Unique job identifier.
        status:
          type: string
          description: Job status.
      additionalProperties: true
    HealthResponse:
      type: object
      description: Service health status.
      properties:
        status:
          type: string
          description: 'Service status: healthy or unhealthy.'
        version:
          type: string
          description: API version.
        uptime_seconds:
          type: number
          format: float
          description: Service uptime in seconds.
        database_connected:
          type: boolean
          description: Whether the database connection is healthy.
        verifier_ready:
          type: boolean
          description: Whether the email verifier is ready.
        verification_provider:
          type: string
          description: Verification service identifier.
        timestamp:
          type: string
          format: date-time
          description: Current server timestamp in ISO 8601 format.
    Error:
      type: object
      description: Standard error response.
      properties:
        detail:
          type: string
          description: Human-readable explanation of the error.
