{
  "openapi": "3.0.3",
  "info": {
    "title": "Easy Email Verification API",
    "version": "1.2.0",
    "description": "REST API to verify email addresses one at a time, in small batches, or as bulk lists.\n\n## Authentication\n\nEvery request needs an API key, created in the dashboard under\n[API Settings](https://dashboard.easyemailverification.com/apisettings).\n\n**Recommended:** send the key in the `X-API-Key` header.\n\n**Also supported** (all endpoints keep accepting them):\n\n- `apikey` query parameter (`GET /verify`, `GET /credits`)\n- `apikey` header (`POST /verify` and `/bulk/*`)\n- `Authorization` header, as `Authorization: <key>` or `Authorization: token <key>`\n\nIf a request carries more than one of them, `apikey` wins over `X-API-Key`, which wins\nover `Authorization`.\n\nKeys created for the JavaScript widget (keys with an authorized domain) are rejected\nby these endpoints with `401`.\n\nKeep API keys on a trusted server. Do not use them in browser or mobile code.\n\n## Sandbox\n\nUse the public key `eev_sandbox_key` to test an integration without an account and\nwithout spending credits. It works on `GET /verify`, `POST /verify` and `GET /credits`,\nonly accepts addresses at `sandbox.easyemailverification.com` (plus `typo@gmial.com`),\nand answers with fixed results chosen by the local part:\n\n| Address | Answer |\n| --- | --- |\n| `valid@sandbox.easyemailverification.com` | `valid`, `accepted_email` |\n| `invalid@sandbox.easyemailverification.com` | `invalid`, `rejected_email` |\n| `unknown@sandbox.easyemailverification.com` | `unknown`, `timeout` |\n| `disposable@sandbox.easyemailverification.com` | `valid`, `disposable: true` |\n| `catchall@sandbox.easyemailverification.com` | `valid`, `accept_all: true` |\n| `role@sandbox.easyemailverification.com` | `valid`, `role: true` |\n| `typo@gmial.com` | `invalid`, `did_you_mean: typo@gmail.com` |\n| `quota@sandbox.easyemailverification.com` | `402` (no credits) |\n| `ratelimit@sandbox.easyemailverification.com` | `429` (simulated) |\n\nAny other sandbox address returns `invalid`. Sandbox responses carry the header\n`X-EEV-Sandbox: true` and are limited to 60 requests per minute per IP.\n",
    "contact": {
      "email": "info@easyemailverification.com"
    },
    "license": {
      "name": "Easy Email Verification",
      "url": "https://www.easyemailverification.com/"
    }
  },
  "servers": [
    {
      "url": "https://api.easyemailverification.com/v1"
    }
  ],
  "tags": [
    {
      "name": "Single Verification",
      "description": "Verify one address, or a batch of up to 50, synchronously."
    },
    {
      "name": "Bulk Verification",
      "description": "Upload a list, follow the job, and download the results."
    },
    {
      "name": "Account",
      "description": "Account information for the owner of the API key."
    }
  ],
  "externalDocs": {
    "description": "Getting started",
    "url": "https://eev.stoplight.io/docs/eev/122963476e10f-getting-started"
  },
  "paths": {
    "/verify": {
      "get": {
        "tags": [
          "Single Verification"
        ],
        "operationId": "verify",
        "summary": "Verify a single email address",
        "description": "Verifies one email address. Each verification consumes one credit, except when the\nreceiving server could not be reached (`reason: no_connect`).\n\n`success: true` means the request was processed; it does not mean the address is\ndeliverable. Use `result`, `reason` and `safe_to_send`. Do not treat `unknown` as `valid`.\n",
        "security": [
          {
            "xApiKey": []
          },
          {
            "apikeyQuery": []
          },
          {
            "authorizationHeader": []
          }
        ],
        "parameters": [
          {
            "name": "email",
            "in": "query",
            "required": true,
            "description": "Email address to verify. URL-encode it (for example `+` as `%2B`).",
            "schema": {
              "type": "string"
            },
            "example": "john@gmail.com"
          },
          {
            "name": "apikey",
            "in": "query",
            "required": false,
            "description": "API key. Optional when the key is sent in a header (`X-API-Key` recommended).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Verification result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VerificationResult"
                },
                "example": {
                  "email": "john@gmail.com",
                  "result": "invalid",
                  "reason": "rejected_email",
                  "disposable": false,
                  "accept_all": false,
                  "role": false,
                  "free": true,
                  "user": "john",
                  "domain": "gmail.com",
                  "mx_record": "gmail-smtp-in.l.google.com",
                  "mx_domain": "google.com",
                  "safe_to_send": false,
                  "did_you_mean": "",
                  "success": true,
                  "message": "Processing time: 812 ms",
                  "http_code": "200"
                }
              }
            }
          },
          "400": {
            "description": "Missing API key (`message: \"Apikey is null\"`), empty `email`, or (sandbox key) an address\noutside the sandbox domain. When the `email` parameter is absent, the framework returns\nits default error body.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VerificationError"
                },
                "examples": {
                  "apikeyIsNull": {
                    "$ref": "#/components/examples/ApikeyIsNull"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unknown API key, or a widget-only key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VerificationError"
                },
                "examples": {
                  "invalidKey": {
                    "$ref": "#/components/examples/InvalidKey"
                  },
                  "widgetKey": {
                    "$ref": "#/components/examples/WidgetKey"
                  }
                }
              }
            }
          },
          "402": {
            "description": "The account has no credits left.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VerificationError"
                },
                "examples": {
                  "noCredits": {
                    "$ref": "#/components/examples/NoCredits"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Sandbox key only (sandbox rate limit or the simulated `ratelimit@` address).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VerificationError"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Single Verification"
        ],
        "operationId": "verifyBatch",
        "summary": "Verify a small batch of email addresses",
        "description": "Verifies up to 50 email addresses in one request and returns one result per address.\nEach address consumes one credit, except `reason: no_connect`.\nFor larger lists use the bulk endpoints.\n",
        "security": [
          {
            "xApiKey": []
          },
          {
            "apikeyHeader": []
          },
          {
            "authorizationHeader": []
          }
        ],
        "parameters": [
          {
            "name": "apikey",
            "in": "header",
            "required": false,
            "description": "API key. Optional when the key is sent in `X-API-Key` (recommended) or `Authorization`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BatchRequest"
              },
              "example": {
                "emails": [
                  "john@gmail.com",
                  "mary@example.com"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "One result per address, in the same shape as `GET /verify`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/VerificationResult"
                  }
                }
              }
            }
          },
          "400": {
            "description": "No API key, or (sandbox key) an address outside the sandbox domain.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VerificationErrorList"
                }
              }
            }
          },
          "401": {
            "description": "Unknown API key, or a widget-only key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VerificationErrorList"
                }
              }
            }
          },
          "402": {
            "description": "The account has no credits left.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VerificationErrorList"
                }
              }
            }
          },
          "429": {
            "description": "Too many addresses in one request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VerificationErrorList"
                },
                "example": [
                  {
                    "email": null,
                    "result": null,
                    "reason": null,
                    "disposable": false,
                    "accept_all": false,
                    "role": false,
                    "free": false,
                    "user": null,
                    "domain": null,
                    "mx_record": null,
                    "mx_domain": null,
                    "safe_to_send": false,
                    "did_you_mean": "",
                    "success": false,
                    "message": "Too many requests. Rate limit exceeded. Max=50.",
                    "http_code": "429"
                  }
                ]
              }
            }
          }
        }
      }
    },
    "/bulk/upload": {
      "post": {
        "tags": [
          "Bulk Verification"
        ],
        "operationId": "uploadBulkFile",
        "summary": "Upload a list for bulk verification",
        "description": "Uploads a TXT or CSV file with one email address per line and starts an asynchronous\nverification job. Lines that contain `@` and are longer than 5 characters are counted.\nThe account needs enough credits for every counted line. Maximum file size: 16 MB.\nPoll `GET /bulk/status/{id}` and download the result with `GET /bulk/download/{id}`.\n",
        "security": [
          {
            "xApiKey": []
          },
          {
            "apikeyHeader": []
          },
          {
            "authorizationHeader": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ApikeyHeader"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "file"
                ],
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary",
                    "description": "TXT or CSV file, one email address per line."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "File accepted and job created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BulkUploadAccepted"
                }
              }
            }
          },
          "400": {
            "description": "Missing API key, or the file has no valid email addresses.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BulkError"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/BulkUnauthorized"
          },
          "402": {
            "description": "Not enough credits for the number of addresses in the file.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BulkError"
                },
                "example": {
                  "status": "error",
                  "message": "You are running out of your credit limit."
                }
              }
            }
          },
          "500": {
            "description": "The file could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BulkError"
                }
              }
            }
          }
        }
      }
    },
    "/bulk/status": {
      "get": {
        "tags": [
          "Bulk Verification"
        ],
        "operationId": "listBulkJobs",
        "summary": "List the bulk jobs of the account",
        "security": [
          {
            "xApiKey": []
          },
          {
            "apikeyHeader": []
          },
          {
            "authorizationHeader": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ApikeyHeader"
          }
        ],
        "responses": {
          "200": {
            "description": "Jobs of the account that owns the API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BulkJobList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BulkMissingKey"
          },
          "401": {
            "$ref": "#/components/responses/BulkUnauthorized"
          }
        }
      }
    },
    "/bulk/status/{id}": {
      "get": {
        "tags": [
          "Bulk Verification"
        ],
        "operationId": "getBulkJob",
        "summary": "Get the status of a bulk job",
        "security": [
          {
            "xApiKey": []
          },
          {
            "apikeyHeader": []
          },
          {
            "authorizationHeader": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/JobId"
          },
          {
            "$ref": "#/components/parameters/ApikeyHeader"
          }
        ],
        "responses": {
          "200": {
            "description": "Job status.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BulkJobStatus"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BulkMissingKey"
          },
          "401": {
            "$ref": "#/components/responses/BulkUnauthorized"
          },
          "404": {
            "description": "Job not found, or it belongs to another account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BulkError"
                },
                "example": {
                  "status": "error",
                  "message": "List not found"
                }
              }
            }
          }
        }
      }
    },
    "/bulk/download/{id}": {
      "get": {
        "tags": [
          "Bulk Verification"
        ],
        "operationId": "downloadBulkResults",
        "summary": "Download the results of a completed bulk job",
        "description": "Returns the results as CSV with the header\n`Email,Result,Reason,Disposable,AcceptAll,Role,Free,User,Domain,MXRecord,DomainMX,IsSafeToSend,DidYouMean,Success,Message,HttpCode`.\nJobs and their results are deleted automatically 30 days after upload.\n",
        "security": [
          {
            "xApiKey": []
          },
          {
            "apikeyHeader": []
          },
          {
            "authorizationHeader": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/JobId"
          },
          {
            "$ref": "#/components/parameters/ApikeyHeader"
          }
        ],
        "responses": {
          "200": {
            "description": "CSV file (`Content-Disposition: attachment; filename=results.csv`).",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BulkMissingKey"
          },
          "401": {
            "$ref": "#/components/responses/BulkUnauthorized"
          },
          "404": {
            "description": "Job not found, not completed yet, or it belongs to another account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BulkError"
                },
                "example": {
                  "status": "error",
                  "message": "Processed file not found or not completed"
                }
              }
            }
          }
        }
      }
    },
    "/bulk/{id}": {
      "delete": {
        "tags": [
          "Bulk Verification"
        ],
        "operationId": "deleteBulkJob",
        "summary": "Delete a bulk job and its results",
        "security": [
          {
            "xApiKey": []
          },
          {
            "apikeyHeader": []
          },
          {
            "authorizationHeader": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/JobId"
          },
          {
            "$ref": "#/components/parameters/ApikeyHeader"
          }
        ],
        "responses": {
          "200": {
            "description": "Job deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BulkDeleted"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BulkMissingKey"
          },
          "401": {
            "$ref": "#/components/responses/BulkUnauthorized"
          },
          "404": {
            "description": "Job not found, or it belongs to another account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BulkError"
                },
                "example": {
                  "status": "error",
                  "message": "File not found"
                }
              }
            }
          }
        }
      }
    },
    "/credits": {
      "get": {
        "tags": [
          "Account"
        ],
        "operationId": "getCredits",
        "summary": "Remaining credits of the account",
        "description": "Does not consume credits. With the sandbox key it returns fixed values.",
        "security": [
          {
            "xApiKey": []
          },
          {
            "apikeyQuery": []
          },
          {
            "authorizationHeader": []
          }
        ],
        "parameters": [
          {
            "name": "apikey",
            "in": "query",
            "required": false,
            "description": "API key. Optional when the key is sent in a header (`X-API-Key` recommended).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Remaining credits.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Credits"
                },
                "example": {
                  "success": true,
                  "credits_remaining": 1250,
                  "subscription_remaining": 250,
                  "persistent_remaining": 1000,
                  "subscription_credits": 500
                }
              }
            }
          },
          "400": {
            "description": "No API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          },
          "401": {
            "description": "Unknown API key, or a widget-only key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimpleError"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "xApiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "Recommended."
      },
      "apikeyQuery": {
        "type": "apiKey",
        "in": "query",
        "name": "apikey"
      },
      "apikeyHeader": {
        "type": "apiKey",
        "in": "header",
        "name": "apikey"
      },
      "authorizationHeader": {
        "type": "apiKey",
        "in": "header",
        "name": "Authorization",
        "description": "`Authorization: <key>` or `Authorization: token <key>`."
      }
    },
    "parameters": {
      "ApikeyHeader": {
        "name": "apikey",
        "in": "header",
        "required": false,
        "description": "API key. Optional when the key is sent in `X-API-Key` (recommended) or `Authorization`.",
        "schema": {
          "type": "string"
        }
      },
      "JobId": {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Job id (`list_id`) returned by `POST /bulk/upload`.",
        "schema": {
          "type": "string"
        },
        "example": "1ec74e7f-77d4-4d21-ab4b-7256b2d2c943"
      }
    },
    "responses": {
      "BulkMissingKey": {
        "description": "No API key, or the sandbox key (not supported on bulk endpoints).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/BulkError"
            },
            "example": {
              "status": "error",
              "message": "Missing authentication header"
            }
          }
        }
      },
      "BulkUnauthorized": {
        "description": "Unknown API key, or a widget-only key.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/BulkError"
            },
            "example": {
              "status": "error",
              "message": "Invalid or missing API key"
            }
          }
        }
      }
    },
    "examples": {
      "ApikeyIsNull": {
        "value": {
          "email": null,
          "result": null,
          "reason": null,
          "disposable": false,
          "accept_all": false,
          "role": false,
          "free": false,
          "user": null,
          "domain": null,
          "mx_record": null,
          "mx_domain": null,
          "safe_to_send": false,
          "did_you_mean": "",
          "success": false,
          "message": "Apikey is null",
          "http_code": "400"
        }
      },
      "InvalidKey": {
        "value": {
          "email": null,
          "result": null,
          "reason": null,
          "disposable": false,
          "accept_all": false,
          "role": false,
          "free": false,
          "user": null,
          "domain": null,
          "mx_record": null,
          "mx_domain": null,
          "safe_to_send": false,
          "did_you_mean": "",
          "success": false,
          "message": "Server can not verify your authentication to use API. Please check whether API key is proper or not.",
          "http_code": "401"
        }
      },
      "WidgetKey": {
        "value": {
          "email": null,
          "result": null,
          "reason": null,
          "disposable": false,
          "accept_all": false,
          "role": false,
          "free": false,
          "user": null,
          "domain": null,
          "mx_record": null,
          "mx_domain": null,
          "safe_to_send": false,
          "did_you_mean": "",
          "success": false,
          "message": "API key allowed only for form integration (Widget Javascript).",
          "http_code": "401"
        }
      },
      "NoCredits": {
        "value": {
          "email": null,
          "result": null,
          "reason": null,
          "disposable": false,
          "accept_all": false,
          "role": false,
          "free": false,
          "user": null,
          "domain": null,
          "mx_record": null,
          "mx_domain": null,
          "safe_to_send": false,
          "did_you_mean": "",
          "success": false,
          "message": "You are running out of your credit limit.",
          "http_code": "402"
        }
      }
    },
    "schemas": {
      "VerificationResult": {
        "type": "object",
        "description": "Result of one verification. All fields are always present.",
        "required": [
          "email",
          "result",
          "reason",
          "disposable",
          "accept_all",
          "role",
          "free",
          "user",
          "domain",
          "mx_record",
          "mx_domain",
          "safe_to_send",
          "did_you_mean",
          "success",
          "message",
          "http_code"
        ],
        "properties": {
          "email": {
            "type": "string",
            "nullable": true,
            "description": "Address that was verified, normalized to lowercase."
          },
          "result": {
            "type": "string",
            "nullable": true,
            "enum": [
              "valid",
              "invalid",
              "unknown",
              null
            ],
            "description": "Overall result. Check `reason` for details."
          },
          "reason": {
            "type": "string",
            "nullable": true,
            "description": "Detail of the result. Known values:\n`accepted_email` (SMTP server accepted the address),\n`rejected_email` (mailbox does not exist),\n`invalid_email` (invalid syntax),\n`invalid_domain` (domain does not exist),\n`no_mx_record` (domain has no MX record),\n`invalid_mx_record`,\n`no_connect` (could not connect to the receiving server; no credit is consumed),\n`timeout`, `unavailable_smtp`, `unexpected_error`,\n`temporarily_blocked` (greylisted), `exceeded_storage` (mailbox full).\nNew values may be added; treat unknown values as inconclusive.\n",
            "example": "accepted_email"
          },
          "disposable": {
            "type": "boolean",
            "description": "Known temporary/disposable address."
          },
          "accept_all": {
            "type": "boolean",
            "description": "Catch-all domain; it accepts any mailbox, so the address cannot be confirmed."
          },
          "role": {
            "type": "boolean",
            "description": "Role address such as support@ or postmaster@."
          },
          "free": {
            "type": "boolean",
            "description": "Address from a popular free provider (Gmail, Outlook, Yahoo...)."
          },
          "user": {
            "type": "string",
            "nullable": true,
            "description": "Local part of the address."
          },
          "domain": {
            "type": "string",
            "nullable": true,
            "description": "Domain part of the address."
          },
          "mx_record": {
            "type": "string",
            "nullable": true,
            "description": "MX host that receives mail for the domain."
          },
          "mx_domain": {
            "type": "string",
            "nullable": true,
            "description": "Domain of the MX host."
          },
          "safe_to_send": {
            "type": "boolean",
            "description": "Whether the address is considered safe for sending."
          },
          "did_you_mean": {
            "type": "string",
            "description": "Suggested correction when a typo is detected; empty string otherwise."
          },
          "success": {
            "type": "boolean",
            "description": "Whether the request was processed. It does not mean the address is deliverable."
          },
          "message": {
            "type": "string",
            "nullable": true,
            "description": "Error description, or processing information on success."
          },
          "http_code": {
            "type": "string",
            "nullable": true,
            "description": "HTTP status code repeated in the body, as a string.",
            "example": "200"
          }
        }
      },
      "VerificationError": {
        "description": "Error response of `GET /verify`. Same shape as a result, with `success: false`.",
        "allOf": [
          {
            "$ref": "#/components/schemas/VerificationResult"
          }
        ]
      },
      "VerificationErrorList": {
        "description": "Error response of `POST /verify`: a list with one error item.",
        "type": "array",
        "minItems": 1,
        "maxItems": 1,
        "items": {
          "$ref": "#/components/schemas/VerificationResult"
        }
      },
      "BatchRequest": {
        "type": "object",
        "required": [
          "emails"
        ],
        "properties": {
          "emails": {
            "type": "array",
            "maxItems": 50,
            "items": {
              "type": "string"
            },
            "description": "Addresses to verify (maximum 50)."
          }
        }
      },
      "Credits": {
        "type": "object",
        "required": [
          "success",
          "credits_remaining",
          "subscription_remaining",
          "persistent_remaining",
          "subscription_credits"
        ],
        "properties": {
          "success": {
            "type": "boolean"
          },
          "credits_remaining": {
            "type": "integer",
            "format": "int64",
            "description": "Total verifications left (subscription + prepaid)."
          },
          "subscription_remaining": {
            "type": "integer",
            "format": "int64",
            "description": "Left in the current subscription period."
          },
          "persistent_remaining": {
            "type": "integer",
            "format": "int64",
            "description": "Prepaid credits that do not expire with the period."
          },
          "subscription_credits": {
            "type": "integer",
            "format": "int64",
            "description": "Credits granted per subscription period."
          }
        }
      },
      "SimpleError": {
        "type": "object",
        "required": [
          "success",
          "message",
          "http_code"
        ],
        "properties": {
          "success": {
            "type": "boolean",
            "enum": [
              false
            ]
          },
          "message": {
            "type": "string"
          },
          "http_code": {
            "type": "string"
          }
        }
      },
      "BulkError": {
        "type": "object",
        "required": [
          "status",
          "message"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "error"
            ]
          },
          "message": {
            "type": "string"
          }
        }
      },
      "BulkUploadAccepted": {
        "type": "object",
        "required": [
          "status",
          "list_id",
          "filename",
          "uploaded",
          "message"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "accepted"
            ]
          },
          "list_id": {
            "type": "string",
            "description": "Job id used by the other bulk endpoints.",
            "example": "1ec74e7f-77d4-4d21-ab4b-7256b2d2c943"
          },
          "filename": {
            "type": "string",
            "example": "leads.csv"
          },
          "uploaded": {
            "type": "integer",
            "format": "int64",
            "description": "Number of addresses counted in the file.",
            "example": 1200
          },
          "message": {
            "type": "string",
            "example": "File accepted for processing"
          }
        }
      },
      "BulkJobStatusValue": {
        "type": "string",
        "enum": [
          "queued",
          "processing",
          "completed",
          "failed",
          "deleted",
          "not_enough_credits",
          "unknown"
        ],
        "description": "`not_enough_credits`: processing stopped because the account ran out of credits.\n"
      },
      "BulkJobStatus": {
        "type": "object",
        "required": [
          "list_id",
          "status",
          "progress"
        ],
        "properties": {
          "list_id": {
            "type": "string"
          },
          "status": {
            "$ref": "#/components/schemas/BulkJobStatusValue"
          },
          "progress": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100,
            "description": "Percentage processed."
          },
          "started_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Upload time."
          },
          "estimated_finish": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Completion time once the job is completed; null before that."
          },
          "totals": {
            "type": "object",
            "nullable": true,
            "description": "Counters; null before processing starts.",
            "properties": {
              "total": {
                "type": "integer",
                "format": "int64"
              },
              "processed": {
                "type": "integer",
                "format": "int64"
              },
              "valid": {
                "type": "integer",
                "format": "int64"
              },
              "invalid": {
                "type": "integer",
                "format": "int64"
              },
              "unknown": {
                "type": "integer",
                "format": "int64"
              }
            }
          }
        }
      },
      "BulkJobList": {
        "type": "object",
        "required": [
          "status",
          "total_lists",
          "lists"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "ok"
            ]
          },
          "total_lists": {
            "type": "integer"
          },
          "lists": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "list_id",
                "filename",
                "status"
              ],
              "properties": {
                "list_id": {
                  "type": "string"
                },
                "filename": {
                  "type": "string"
                },
                "status": {
                  "$ref": "#/components/schemas/BulkJobStatusValue"
                },
                "uploaded_at": {
                  "type": "string",
                  "format": "date-time",
                  "nullable": true
                },
                "completed_at": {
                  "type": "string",
                  "format": "date-time",
                  "nullable": true
                },
                "emails_total": {
                  "type": "integer",
                  "format": "int64"
                },
                "emails_valid": {
                  "type": "integer",
                  "format": "int64"
                },
                "emails_invalid": {
                  "type": "integer",
                  "format": "int64"
                }
              }
            }
          }
        }
      },
      "BulkDeleted": {
        "type": "object",
        "required": [
          "status",
          "list_id",
          "message"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "deleted"
            ]
          },
          "list_id": {
            "type": "string"
          },
          "message": {
            "type": "string",
            "example": "File permanently removed"
          }
        }
      }
    }
  }
}
