openapi: 3.1.0 info: title: API reference Download blocklist API version: '2022-06-01' description: The Blowfish API reference specification contact: name: Blowfish API Support email: contact@blowfish.xyz url: https://blowfish.xyz license: name: MIT License url: https://opensource.org/licenses/MIT servers: - url: https://free.api.blowfish.xyz description: API server for clients on the free plan - url: https://api.blowfish.xyz description: API server for all other clients (e.g., Enterprise) security: - ApiKeyAuth: [] tags: - name: Download blocklist description: Endpoints related to downloading blocklists paths: /v0/domains/blocklist: post: tags: - Download blocklist summary: Blocklist operationId: download-blocklist description: "Generate a downloadable snapshot with all blocked domains in order to check domains a user visits against a local blocklist, preserving their browsing privacy.\n\n### Integration\nThis API enables to verify domain safety while maintaining the end user's privacy. To integrate this API into your app, you should follow the steps below:\n\n1. Regularly update the blocklist metadata from the /v0/domains/blocklist endpoint.\n - In browser extensions, set up a timer to update the blocklist every 2-5 minutes.\n - In mobile apps, update the blocklist each time the user opens the app and every 2-5 minutes while the user is using the app.\n2. During each update, check if the app has previously downloaded a bloom filter with the hash bloomFilter.hash. If not, download it from bloomFilter.url.\n - Since the bloom filter can be up to 1MB in size, make sure you never re-download the same bloom filter. Identical bloom filters always have the same URL and the same hash.\n - Store the blocklist metadata (recentlyAdded, recentlyRemoved), bloom filter hash, and downloaded bloom filter.\n - Chrome extensions can use localStorage. The endpoint is designed with a 5MB limit on localStorage in mind.\n - The bloom filter is changed once a day, so users will never use more than 1 MB of traffic per day if the download and local caching logic is implemented correctly.\n3. When the user visits a domain, check if the domain is present on the bloom filter or the recentlyAdded list from the blocklist metadata and isn't present on the recentlyRemoved list. If this is the case, block the user from visiting the website.\n\nBrowser extensions and React Native apps can use the Javascript package [@blowfish/blocklist](https://www.npmjs.com/package/@blowfishxyz/blocklist) to implement the outlined logic. For example:\n\n```js\n// Regular updates\nimport { fetchBloomFilter, fetchDomainBlocklist } from '@blowfishxyz/blocklist';\n\nconst blocklist = await fetchDomainBlocklist(apiConfig);\nconst storedHash = [...]; // fetch it from your storage\nif (storedHash != blocklist.bloomFilter.hash) {\n const bloomFilter = await fetchBloomFilter(blocklist.bloomFilter.url);\n [...] // save bloomFilter to a local database\n [...] // save bloomFilter.hash or blocklist.bloomFilter.hash to a local database\n}\n\n// Lookups\nimport { scanDomain, Action } from '@blowfishxyz/blocklist';\n\nconst recentlyAdded = [...]; // get from storage\nconst recentlyRemoved = [...]; // get from storage\nconst bloomFilter = [...]; // get from storage\n\nconst action = scanDomain(\n bloomFilter,\n recentlyAdded,\n recentlyRemoved, \n \"https://example.com/\"\n);\n\nif (action === Action.BLOCK) {\n // block the domain\n}\n```\n\nFor more information on how to use the package, please refer to the NPM package description.\n\n### Priority lists\nThe API aggregates different proprietary Blowfish lists and ecosystem lists. In some cases, different lists may have conflicting data on whether to block or allow a domain. By providing priorityBlockLists and priorityAllowLists, you can override the results in these cases.\n\nIf a domain is blocked by one of the lists that Blowfish aggregates, but included in one of priorityAllowLists, it will not be included in the blocklist snapshot. Conversely, if a domain is allow-listed by one of the lists that Blowfish aggregates, but is included in one of priorityBlockLists, it will be included in the snapshot.\n\nThis is an advanced feature for integrators who want granular control over blocking domains. By default, the API uses internal list priority heuristics designed for most use cases. The Blowfish team continuously monitors the quality of the underlying blocklists and removes incorrect entries.\n\nBlowfish can also ingest custom blocklists and allowlists. If you have a custom list, you can reach out to the Blowfish team and provide a publicly available URL with the domains in a .txt format.\n" security: - ApiKeyAuth: [] parameters: - name: X-Api-Key in: header description: API Key required: true schema: $ref: '#/components/schemas/ApiKeyHeader' - name: X-Api-Version in: header description: Which version of the API to use schema: $ref: '#/components/schemas/ApiVersionHeader' - name: Content-Type in: header description: The expected return content type schema: $ref: '#/components/schemas/ContentType' requestBody: content: application/json: schema: type: object properties: priorityAllowLists: type: array items: type: string enum: - BLOWFISH - METAMASK - DEFILLAMA example: BLOWFISH description: Override domain blocking if domain is present on one of these lists priorityBlockLists: type: array items: type: string enum: - PHANTOM - BLOWFISH - SOLFARE - PHISHFORT - SCAMSNIFFER example: BLOWFISH description: Always block domain if it present on one of these lists responses: '200': description: "A successful API response will include a link to download the bloom filter, which contains all blocked domains and any domains that were recently added to or removed from the filter.\n\nIt's important to note that the recentlyAdded and recentlyRemoved fields take precedence over the bloom filter result. \nThe bloom filter is updated every 24 hours. If new domains are added or removed, they will be listed in the recentlyAdded and recentlyRemoved fields until the bloom filter is updated.\nThe bloom filter file, located at bloomFilter.url, is guaranteed to be less than 1 MB\n" content: application/json: schema: type: object properties: bloomFilter: type: object properties: url: type: string format: uri example: https://d1ts37qlq4uz4s.cloudfront.net/e9087494a6b9fa71c26788a7111b1c9384ad9f539139d0b33c9856c3fc0351b2.json hash: type: string example: e9087494a6b9fa71c26788a7111b1c9384ad9f539139d0b33c9856c3fc0351b2 recentlyAdded: type: array items: type: string example: scammer.com recentlyRemoved: type: array items: type: string example: notscammer.com '400': description: Bad request content: application/json: schema: $ref: '#/components/schemas/BadRequest' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Unauthorized' '500': description: Internal server error content: application/json: schema: $ref: '#/components/schemas/InternalServerError' components: schemas: InternalServerError: type: object properties: error: type: string enum: - Internal Server Error example: Internal Server Error ApiKeyHeader: description: API key type: string default: 4daa1e3b-87e6-40b2-8883-758feb6a8e46 example: e79e18b4-8ffa-4fab-9e2e-f24057644f93 BadRequest: type: object properties: error: type: string description: The error that caused the 400 example: No transactions to simulate Unauthorized: type: object properties: error: type: string description: The error that caused the 401 example: 'Unauthorized: invalid X-API-KEY header value' ApiVersionHeader: type: string description: API version like 2022-06-01 default: '2022-06-01' example: '2022-06-01' ContentType: description: Expected response content type type: string default: application/json example: application/json securitySchemes: ApiKeyAuth: type: apiKey in: header name: X-Api-Key