{
  "openapi": "3.1.0",
  "info": {
    "title": "MailSenpai blacklist check API",
    "version": "1.0.0",
    "summary": "Free check of a public IPv4 address or a domain on public email blocklists (DNSBLs).",
    "description": "One GET request tells you whether an IP address or a domain is on the public email blocklists the API queries, list by list, with the official removal page of each list. Free, no API key, CORS enabled. Limits: 10 checks per hour per IP address and 300 checks per day in total across all users; answers served from the 30-minute cache do not count. When license_notices is not empty, show those notices next to the results.",
    "contact": {
      "name": "MailSenpai",
      "url": "https://en.mailsenpai.com/blacklist-check-api/"
    }
  },
  "externalDocs": {
    "description": "Documentation with examples",
    "url": "https://en.mailsenpai.com/blacklist-check-api/"
  },
  "servers": [
    {
      "url": "https://app.mailsenpai.com/tools"
    }
  ],
  "security": [],
  "tags": [
    {
      "name": "Blacklist check",
      "description": "Lookups of an IP address or a domain on public email blocklists."
    }
  ],
  "paths": {
    "/blacklist-check": {
      "get": {
        "operationId": "checkBlacklist",
        "tags": [
          "Blacklist check"
        ],
        "summary": "Check an IP address or a domain on email blocklists",
        "description": "Pass target to start a check. Pass job, instead of target, only to read the result of a check that answered 202.",
        "parameters": [
          {
            "name": "target",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 255
            },
            "example": "8.8.8.8",
            "description": "A public IPv4 address or a domain. Required unless job is passed. IPv6 and private addresses are not accepted: for IPv6 pass the domain."
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "it"
              ],
              "default": "en"
            },
            "description": "Language of summary, labels and notes. Field names and result values stay in English."
          },
          {
            "name": "job",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^[a-f0-9]{32}$"
            },
            "description": "The job returned by a 202 answer. Returns the result of that check without starting a new one."
          }
        ],
        "responses": {
          "200": {
            "description": "The result, list by list.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Checks allowed per hour from one IP address. Sent only when a new check was run.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Checks left in the current hour. Sent only when a new check was run.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BlacklistReport"
                },
                "examples": {
                  "ip": {
                    "summary": "An IP address (real response, lists shortened)",
                    "value": {
                      "target": "8.8.8.8",
                      "type": "ip",
                      "status": "done",
                      "lang": "en",
                      "summary": "Not found on any of the lists this API queries",
                      "listed": false,
                      "counts": {
                        "checks": 7,
                        "listed": 0,
                        "unreachable": 0,
                        "clean": 7
                      },
                      "targets": [
                        {
                          "target": "8.8.8.8",
                          "role": "ip",
                          "role_label": "IP address",
                          "name": "dns.google",
                          "listed_count": 0,
                          "lists": [
                            {
                              "id": "psbl",
                              "name": "PSBL",
                              "result": "clean",
                              "reason": "",
                              "removal_url": "https://psbl.org/listing?ip=8.8.8.8"
                            },
                            {
                              "id": "0spam",
                              "name": "0spam",
                              "result": "clean",
                              "reason": "",
                              "removal_url": "https://0spam.org/"
                            },
                            {
                              "id": "uceprotect1",
                              "name": "UCEPROTECT Level 1",
                              "result": "clean",
                              "reason": "",
                              "removal_url": "https://www.uceprotect.net/en/rblcheck.php"
                            }
                          ]
                        }
                      ],
                      "lists_queried": 7,
                      "lists_not_queried": [
                        {
                          "name": "SpamCop",
                          "url": "https://www.spamcop.net/bl.shtml",
                          "checked_by_web_tool": true,
                          "note": "Queried by the web tool, not by this API."
                        },
                        {
                          "name": "Abusix",
                          "url": "https://lookup.abusix.com/",
                          "checked_by_web_tool": false,
                          "note": "Check on the official site."
                        }
                      ],
                      "license_notices": [
                        "UCEPROTECT Level 1 data: Copyright © 2001-2021 UCEPROTECT-Network http://www.uceprotect.net. Permission to use, copy, modify, and/or distribute this data for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies."
                      ],
                      "note": "",
                      "checked_at": "2026-10-12T11:45:04Z",
                      "cached": false,
                      "more": "https://en.mailsenpai.com/blacklist-check/",
                      "docs": "https://en.mailsenpai.com/blacklist-check-api/",
                      "source": "MailSenpai"
                    }
                  },
                  "domain": {
                    "summary": "A domain (real response, targets and lists shortened)",
                    "value": {
                      "target": "mailsenpai.com",
                      "type": "domain",
                      "status": "done",
                      "lang": "en",
                      "summary": "Not found on any of the lists this API queries",
                      "listed": false,
                      "counts": {
                        "checks": 16,
                        "listed": 0,
                        "unreachable": 0,
                        "clean": 16
                      },
                      "targets": [
                        {
                          "target": "mailsenpai.com",
                          "role": "domain",
                          "role_label": "Domain",
                          "name": "",
                          "listed_count": 0,
                          "lists": [
                            {
                              "id": "0spam_url",
                              "name": "0spam URL",
                              "result": "clean",
                              "reason": "",
                              "removal_url": "https://0spam.org/"
                            },
                            {
                              "id": "zapbl_rhs",
                              "name": "ZapBL RHSBL",
                              "result": "clean",
                              "reason": "",
                              "removal_url": "https://zapbl.net/lookup"
                            }
                          ]
                        },
                        {
                          "target": "65.21.7.91",
                          "role": "mx",
                          "role_label": "Incoming mail server (MX)",
                          "name": "mx.webmail.mailsenpai.com",
                          "listed_count": 0,
                          "lists": [
                            {
                              "id": "psbl",
                              "name": "PSBL",
                              "result": "clean",
                              "reason": "",
                              "removal_url": "https://psbl.org/listing?ip=65.21.7.91"
                            },
                            {
                              "id": "0spam",
                              "name": "0spam",
                              "result": "clean",
                              "reason": "",
                              "removal_url": "https://0spam.org/"
                            },
                            {
                              "id": "uceprotect1",
                              "name": "UCEPROTECT Level 1",
                              "result": "clean",
                              "reason": "",
                              "removal_url": "https://www.uceprotect.net/en/rblcheck.php"
                            }
                          ]
                        }
                      ],
                      "lists_queried": 9,
                      "lists_not_queried": [
                        {
                          "name": "SpamCop",
                          "url": "https://www.spamcop.net/bl.shtml",
                          "checked_by_web_tool": true,
                          "note": "Queried by the web tool, not by this API."
                        },
                        {
                          "name": "Abusix",
                          "url": "https://lookup.abusix.com/",
                          "checked_by_web_tool": false,
                          "note": "Check on the official site."
                        }
                      ],
                      "license_notices": [
                        "UCEPROTECT Level 1 data: Copyright © 2001-2021 UCEPROTECT-Network http://www.uceprotect.net. Permission to use, copy, modify, and/or distribute this data for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies."
                      ],
                      "note": "",
                      "checked_at": "2026-10-12T11:45:04Z",
                      "cached": false,
                      "more": "https://en.mailsenpai.com/blacklist-check/",
                      "docs": "https://en.mailsenpai.com/blacklist-check-api/",
                      "source": "MailSenpai"
                    }
                  }
                }
              }
            }
          },
          "202": {
            "description": "The lists are taking more than 12 seconds. Call retry_url after a couple of seconds.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Checks allowed per hour from one IP address. Sent only when a new check was run.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Checks left in the current hour. Sent only when a new check was run.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before trying again.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InProgress"
                },
                "example": {
                  "target": "8.8.8.8",
                  "type": "ip",
                  "status": "in_progress",
                  "lang": "en",
                  "job": "74876807dc9ec798b9dfe0f0a61e9171",
                  "retry_after_seconds": 2,
                  "source": "MailSenpai",
                  "retry_url": "https://app.mailsenpai.com/tools/blacklist-check?job=74876807dc9ec798b9dfe0f0a61e9171&lang=en"
                }
              }
            }
          },
          "404": {
            "description": "The job is not known or has expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "mspck_error",
                  "message": "Check not found: start a new one with ?target=.",
                  "data": {
                    "status": 404,
                    "field": "job"
                  }
                }
              }
            }
          },
          "422": {
            "description": "The target is missing or not valid (not an IPv4 address or a domain, IPv6, private or reserved address).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "mspck_error",
                  "message": "This is a private or reserved address: we need the public IP your emails are sent from.",
                  "data": {
                    "status": 422,
                    "field": "target"
                  }
                }
              }
            }
          },
          "429": {
            "description": "A limit was reached: data.limit says which one and Retry-After how long to wait.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "mspck_error",
                  "message": "Too many checks from this connection: the API allows 10 per hour. Try again later, or use the web tool.",
                  "data": {
                    "status": 429,
                    "limit": "per_ip_hour",
                    "retry_after": 3509,
                    "web_tool": "https://en.mailsenpai.com/blacklist-check/"
                  }
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before trying again.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "The check did not complete: try again in a minute.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "mspck_error",
                  "message": "The check didn't complete: try again in a minute.",
                  "data": {
                    "status": 500
                  }
                }
              }
            }
          },
          "503": {
            "description": "The API is switched off, or the service that runs the lookups is not answering.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "mspck_error",
                  "message": "The blacklist check API is not available right now.",
                  "data": {
                    "status": 503
                  }
                }
              }
            }
          },
          "504": {
            "description": "The check did not complete within 40 seconds.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "code": "mspck_error",
                  "message": "The check did not complete: try again in a minute.",
                  "data": {
                    "status": 504,
                    "retry_after": 60
                  }
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before trying again.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "BlacklistReport": {
        "type": "object",
        "required": [
          "target",
          "type",
          "status",
          "lang",
          "summary",
          "listed",
          "counts",
          "targets",
          "lists_queried",
          "lists_not_queried",
          "license_notices",
          "note",
          "checked_at",
          "cached",
          "more",
          "docs",
          "source"
        ],
        "properties": {
          "target": {
            "type": "string",
            "description": "The IP address or the domain that was checked."
          },
          "type": {
            "type": "string",
            "enum": [
              "ip",
              "domain"
            ]
          },
          "status": {
            "type": "string",
            "const": "done"
          },
          "lang": {
            "type": "string",
            "enum": [
              "en",
              "it"
            ]
          },
          "summary": {
            "type": "string",
            "description": "One line, for example \"Found on 2 lists\"."
          },
          "listed": {
            "type": "boolean",
            "description": "true when at least one list reports one of the targets."
          },
          "counts": {
            "type": "object",
            "required": [
              "checks",
              "listed",
              "unreachable",
              "clean"
            ],
            "properties": {
              "checks": {
                "type": "integer",
                "minimum": 0,
                "description": "Lookups made: one per list and per target."
              },
              "listed": {
                "type": "integer",
                "minimum": 0
              },
              "unreachable": {
                "type": "integer",
                "minimum": 0
              },
              "clean": {
                "type": "integer",
                "minimum": 0
              }
            }
          },
          "targets": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Target"
            },
            "description": "For an IP address: the address. For a domain: the domain, its registered domain when different, the IP addresses of its first MX servers and of its A record."
          },
          "lists_queried": {
            "type": "integer",
            "description": "How many lists this API queries for this kind of target."
          },
          "lists_not_queried": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ListNotQueried"
            },
            "description": "Lists this API does not query, each with the link to its official lookup page."
          },
          "license_notices": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Attribution notices of the lists queried. When you display the results, display these next to them."
          },
          "note": {
            "type": "string",
            "description": "Empty, or a warning when more than half of the lists did not answer."
          },
          "checked_at": {
            "type": "string",
            "format": "date-time"
          },
          "cached": {
            "type": "boolean",
            "description": "true when the same target was checked in the last 30 minutes."
          },
          "more": {
            "type": "string",
            "format": "uri",
            "description": "The web page that runs the check."
          },
          "docs": {
            "type": "string",
            "format": "uri"
          },
          "source": {
            "type": "string",
            "const": "MailSenpai"
          }
        }
      },
      "Target": {
        "type": "object",
        "required": [
          "target",
          "role",
          "role_label",
          "name",
          "listed_count",
          "lists"
        ],
        "properties": {
          "target": {
            "type": "string"
          },
          "role": {
            "type": "string",
            "enum": [
              "ip",
              "domain",
              "registered_domain",
              "mx",
              "a"
            ],
            "description": "mx: incoming mail server. a: website address."
          },
          "role_label": {
            "type": "string",
            "description": "The role in words, in the language of the request."
          },
          "name": {
            "type": "string",
            "description": "Reverse name of the IP address, or the host it was resolved from. May be empty."
          },
          "listed_count": {
            "type": "integer",
            "minimum": 0
          },
          "lists": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ListResult"
            }
          }
        }
      },
      "ListResult": {
        "type": "object",
        "required": [
          "id",
          "name",
          "result",
          "reason",
          "removal_url"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "result": {
            "type": "string",
            "enum": [
              "listed",
              "clean",
              "unreachable"
            ],
            "description": "unreachable: the list did not answer; reason says why."
          },
          "reason": {
            "type": "string",
            "description": "For a listed result, what the list reports when it says so; for unreachable, why. Often empty."
          },
          "removal_url": {
            "type": "string",
            "description": "The official page of the list to check the entry and ask for removal."
          }
        }
      },
      "ListNotQueried": {
        "type": "object",
        "required": [
          "name",
          "url",
          "checked_by_web_tool",
          "note"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Official lookup page of the list."
          },
          "checked_by_web_tool": {
            "type": "boolean",
            "description": "true when the MailSenpai web page queries this list."
          },
          "note": {
            "type": "string"
          }
        }
      },
      "InProgress": {
        "type": "object",
        "required": [
          "target",
          "type",
          "status",
          "lang",
          "job",
          "retry_after_seconds",
          "source",
          "retry_url"
        ],
        "properties": {
          "target": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "ip",
              "domain"
            ]
          },
          "status": {
            "type": "string",
            "const": "in_progress"
          },
          "lang": {
            "type": "string",
            "enum": [
              "en",
              "it"
            ]
          },
          "job": {
            "type": "string",
            "pattern": "^[a-f0-9]{32}$",
            "description": "Pass it back in the job parameter to read the result."
          },
          "retry_after_seconds": {
            "type": "integer"
          },
          "source": {
            "type": "string",
            "const": "MailSenpai"
          },
          "retry_url": {
            "type": "string",
            "format": "uri",
            "description": "The address to call to read the result."
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "code",
          "message",
          "data"
        ],
        "properties": {
          "code": {
            "type": "string",
            "const": "mspck_error"
          },
          "message": {
            "type": "string",
            "description": "Human-readable explanation, in the language of the request."
          },
          "data": {
            "type": "object",
            "required": [
              "status"
            ],
            "description": "The HTTP status again, plus details that depend on the error.",
            "properties": {
              "status": {
                "type": "integer",
                "description": "Same value as the HTTP status code."
              },
              "field": {
                "type": "string",
                "description": "Name of the parameter that is missing or not valid."
              },
              "campo": {
                "type": "string",
                "description": "Name of the parameter that is missing or not valid (DNS check)."
              },
              "limit": {
                "type": "string",
                "enum": [
                  "per_ip_hour",
                  "daily_total",
                  "requests_per_ip_hour"
                ],
                "description": "Which limit was reached."
              },
              "retry_after": {
                "type": "integer",
                "description": "Seconds to wait before trying again."
              },
              "web_tool": {
                "type": "string",
                "format": "uri",
                "description": "The web page that runs the same check."
              }
            }
          }
        }
      }
    }
  }
}