{
  "openapi": "3.1.0",
  "info": {
    "title": "Syvel API",
    "description": "Syvel is a disposable and temporary email detection API — Made in France, GDPR-compliant, hosted in the EU. Detects 100,000+ throwaway domains in real time using live DNS fingerprinting (MX, SPF, DMARC, domain age, provider pattern matching). Zero personal data retained after the request.",
    "version": "1.0.0",
    "contact": {
      "name": "Syvel",
      "url": "https://syvel.io",
      "email": "support@syvel.io"
    },
    "license": {
      "name": "Proprietary",
      "url": "https://syvel.io/legal/terms"
    },
    "x-logo": {
      "url": "https://syvel.io/favicon.svg"
    }
  },
  "externalDocs": {
    "description": "Full documentation",
    "url": "https://syvel.io/docs/guides/introduction"
  },
  "servers": [
    {
      "url": "https://api.syvel.io",
      "description": "Production (EU — France)"
    }
  ],
  "tags": [
    {
      "name": "check",
      "description": "Email and domain risk analysis. The core endpoint — accepts a full email address or a bare domain, returns a structured risk assessment in under 50 ms."
    }
  ],
  "paths": {
    "/v1/check/{email_or_domain}": {
      "get": {
        "operationId": "checkEmailOrDomain",
        "summary": "Analyze an email address or domain",
        "description": "Analyzes an email address (`user@domain.com`) or a bare domain (`domain.com`) and returns a complete risk assessment.\n\n**What Syvel checks:**\n- Proprietary blacklist of 100,000+ known disposable/throwaway domains\n- Live DNS infrastructure: MX record presence, SPF and DMARC authentication, domain age via RDAP\n- MX provider fingerprinting: identifies the hosting provider (Google Workspace, Microsoft 365, Mailchimp, Yopmail…)\n- Local part analysis: detects role accounts (`contact@`, `info@`, `admin@`), random strings, and suspicious patterns\n- Alias service detection: SimpleLogin, AnonAddy, Apple Hide My Email…\n- Typo suggestions: `gmial.com` → `gmail.com`\n\n**Quota:** Only successful `200` responses count against your monthly quota. Errors (`422`, `429`) do not.\n\n**Plans:** Free 100 req/month · Starter 1,000 · Pro 10,000 · Business 100,000",
        "tags": ["check"],
        "parameters": [
          {
            "name": "email_or_domain",
            "in": "path",
            "required": true,
            "description": "Email address (`user@domain.com`) or domain name (`domain.com`) to analyze. Maximum 320 characters for emails, 253 for bare domains.",
            "schema": {
              "type": "string",
              "examples": [
                "user@gmail.com",
                "contact@yopmail.com",
                "test@guerrillamail.com",
                "john.doe@company.com",
                "gmail.com"
              ]
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Analysis complete. The `is_risky` field is the primary signal — `true` means the address should be blocked or flagged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckResponse"
                },
                "examples": {
                  "safe_personal": {
                    "summary": "Safe personal address (Gmail)",
                    "value": {
                      "email": "a9****e5@gmail.com",
                      "is_risky": false,
                      "risk_score": 5,
                      "reason": "safe",
                      "is_free_provider": true,
                      "is_corporate_email": false,
                      "did_you_mean": null,
                      "is_alias_email": false,
                      "mx_provider_label": "Google Workspace",
                      "deliverability_score": 95
                    }
                  },
                  "safe_corporate": {
                    "summary": "Safe corporate address",
                    "value": {
                      "email": "3f****7a@company.com",
                      "is_risky": false,
                      "risk_score": 2,
                      "reason": "safe",
                      "is_free_provider": false,
                      "is_corporate_email": true,
                      "did_you_mean": null,
                      "is_alias_email": false,
                      "mx_provider_label": "Microsoft 365",
                      "deliverability_score": 98
                    }
                  },
                  "disposable_blacklisted": {
                    "summary": "Confirmed disposable email (blacklisted)",
                    "value": {
                      "email": "a9****e5@yopmail.com",
                      "is_risky": true,
                      "risk_score": 100,
                      "reason": "disposable",
                      "is_free_provider": false,
                      "is_corporate_email": false,
                      "did_you_mean": null,
                      "is_alias_email": false,
                      "mx_provider_label": null,
                      "deliverability_score": 0
                    }
                  },
                  "undeliverable_nxdomain": {
                    "summary": "Non-existent domain (NXDOMAIN)",
                    "value": {
                      "email": "b2****f1@fake-domain-xyz123.com",
                      "is_risky": true,
                      "risk_score": 100,
                      "reason": "undeliverable",
                      "is_free_provider": false,
                      "is_corporate_email": false,
                      "did_you_mean": null,
                      "is_alias_email": false,
                      "mx_provider_label": null,
                      "deliverability_score": 0
                    }
                  },
                  "typo_detected": {
                    "summary": "Typo detected — did you mean gmail.com?",
                    "value": {
                      "email": "c4****d8@gmial.com",
                      "is_risky": true,
                      "risk_score": 80,
                      "reason": "undeliverable",
                      "is_free_provider": false,
                      "is_corporate_email": false,
                      "did_you_mean": "gmail.com",
                      "is_alias_email": false,
                      "mx_provider_label": null,
                      "deliverability_score": 10
                    }
                  },
                  "role_account": {
                    "summary": "Role account (contact@, info@…)",
                    "value": {
                      "email": "ro****le@acme.com",
                      "is_risky": false,
                      "risk_score": 30,
                      "reason": "role_account",
                      "is_free_provider": false,
                      "is_corporate_email": true,
                      "did_you_mean": null,
                      "is_alias_email": false,
                      "mx_provider_label": "Google Workspace",
                      "deliverability_score": 70
                    }
                  },
                  "alias_service": {
                    "summary": "Privacy alias detected (SimpleLogin, AnonAddy…)",
                    "value": {
                      "email": "7e****2c@simplelogin.io",
                      "is_risky": false,
                      "risk_score": 45,
                      "reason": "safe",
                      "is_free_provider": false,
                      "is_corporate_email": false,
                      "did_you_mean": null,
                      "is_alias_email": true,
                      "mx_provider_label": "SimpleLogin",
                      "deliverability_score": 80
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "detail": "API key manquante ou invalide"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input — the email or domain format is not valid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "detail": "Email invalide : 'not-an-email'"
                }
              }
            }
          },
          "429": {
            "description": "Monthly quota exceeded for this plan. Upgrade to continue.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying (typically 86400 — until midnight UTC).",
                "schema": {
                  "type": "integer",
                  "example": 86400
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "detail": "Quota mensuel atteint (100 req/mois). Upgradez votre plan."
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "Syvel API Key",
        "description": "Authenticate with your Syvel API key. Get yours at https://dashboard.syvel.io.\n\nFormat: `Authorization: Bearer sv_live_xxxxxxxxxxxxx`\n\nA demo key `sv_demo_checker` is available for unauthenticated testing on the checker page (rate-limited to 10 req/min per IP)."
      }
    },
    "schemas": {
      "CheckResponse": {
        "type": "object",
        "description": "Complete risk assessment for an email address or domain.",
        "required": [
          "email",
          "is_risky",
          "risk_score",
          "reason",
          "is_free_provider",
          "is_corporate_email",
          "is_alias_email",
          "deliverability_score"
        ],
        "properties": {
          "email": {
            "type": "string",
            "description": "Masked email address. The local part (before `@`) is replaced with a cryptographic fingerprint: `sha256(local)[:2] + '****' + sha256(local)[-2:]`. The domain is kept in plain text. For domain-only checks, this field contains the bare domain.\n\nExample: `a9****e5@gmail.com`",
            "example": "a9****e5@gmail.com"
          },
          "is_risky": {
            "type": "boolean",
            "description": "**Primary signal.** `true` if `risk_score` is equal to or above the project's risk threshold (default: 65). Use this as the main boolean gate in your sign-up validation logic.\n\n- `true` → block or flag the address\n- `false` → accept the address",
            "example": false
          },
          "risk_score": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100,
            "description": "Composite risk score from 0 (completely safe) to 100 (confirmed disposable/throwaway).\n\nScore breakdown:\n- `0–20` → Very low risk, almost certainly legitimate\n- `21–50` → Low risk, some signals worth monitoring\n- `51–64` → Moderate risk, below default block threshold\n- `65–79` → High risk, above default block threshold (`is_risky: true`)\n- `80–99` → Very high risk, strong disposable indicators\n- `100` → Confirmed disposable (blacklisted) or NXDOMAIN",
            "example": 5
          },
          "reason": {
            "type": "string",
            "enum": ["safe", "undeliverable", "disposable", "role_account"],
            "description": "Primary reason for the result (highest-priority signal wins):\n\n- `safe` — No suspicious signals detected. Address looks legitimate and deliverable.\n- `disposable` — Confirmed throwaway/temporary email. Domain is in Syvel's blacklist or its MX infrastructure matches a known disposable provider.\n- `undeliverable` — Domain does not exist (NXDOMAIN) or has no MX record. Emails to this address cannot be received.\n- `role_account` — Generic shared address (`contact@`, `info@`, `admin@`, `support@`…). Not necessarily disposable, but unlikely to belong to an individual.",
            "example": "safe"
          },
          "is_free_provider": {
            "type": "boolean",
            "description": "True if the domain is a well-known consumer webmail provider (Gmail, Yahoo, Hotmail, Outlook, iCloud…). Not a risk signal on its own — many legitimate users have personal email addresses. Useful for filtering sign-ups that require a professional or corporate email.",
            "example": true
          },
          "is_corporate_email": {
            "type": "boolean",
            "description": "True if the domain appears to be a professional/corporate email domain: not a consumer webmail, not a disposable domain, and has a properly configured MX infrastructure. Indicates the address likely belongs to a company or organization.",
            "example": false
          },
          "did_you_mean": {
            "type": ["string", "null"],
            "description": "Suggested domain correction if a likely typo is detected. For example, if the user typed `gmial.com`, this field returns `gmail.com`. Use this to prompt users to correct their email before submission.\n\n`null` if no typo is detected.",
            "example": null
          },
          "is_alias_email": {
            "type": "boolean",
            "description": "True if the address is served by a known privacy alias or forwarding service (SimpleLogin, AnonAddy, Apple Hide My Email, DuckDuckGo Email, Firefox Relay…). The real recipient address is hidden behind the alias.\n\nAlias addresses are not inherently risky — they belong to real users who care about privacy — but you may want to flag or reject them depending on your use case.",
            "example": false
          },
          "mx_provider_label": {
            "type": ["string", "null"],
            "description": "Human-readable name of the identified email infrastructure provider, derived from live MX record fingerprinting.\n\nExamples: `Google Workspace`, `Microsoft 365`, `ProtonMail`, `OVH`, `Zoho Mail`, `Mailchimp`, `Mailgun`.\n\n`null` if the provider could not be identified from the MX records.",
            "example": "Google Workspace"
          },
          "deliverability_score": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100,
            "description": "Estimated probability (0–100) that an email sent to this address will actually reach the recipient's inbox.\n\nFactors: MX record presence, SPF record configured, DMARC policy active, domain age, provider reputation.\n\n- `90–100` → Excellent — high delivery probability\n- `70–89` → Good — most emails should be delivered\n- `40–69` → Partial — some configuration missing\n- `0–39` → Poor or critical — delivery very unlikely",
            "example": 95
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "detail": {
            "type": "string",
            "description": "Human-readable error message describing what went wrong.",
            "example": "API key manquante ou invalide"
          }
        }
      }
    }
  }
}
