openapi: 3.0.3 info: title: happyDeliver API description: Email Deliverability Testing Platform API version: 0.1.0 contact: name: happyDomain team url: https://github.com/happyDomain/happydeliver email: contact+api@happydomain.org license: name: GNU Affero General Public License v3.0 or later url: https://spdx.org/licenses/AGPL-3.0-or-later.html servers: - url: http://localhost:8080/api description: Local development server - url: https://api.example.com/api description: Production server tags: - name: tests description: Test management operations - name: reports description: Report retrieval operations - name: health description: Service health and status paths: /test: post: tags: - tests summary: Create a new deliverability test description: Generates a unique test email address for sending test emails. No database record is created until an email is received. operationId: createTest responses: '201': description: Test email address generated successfully content: application/json: schema: $ref: '#/components/schemas/TestResponse' '500': description: Internal server error content: application/json: schema: $ref: '#/components/schemas/Error' /test/{id}: get: tags: - tests summary: Get test status description: Check if a report exists for the given test ID (base32-encoded). Returns pending if no report exists, analyzed if a report is available. operationId: getTest parameters: - name: id in: path required: true schema: type: string pattern: '^[a-z0-9-]+$' description: Base32-encoded test ID (with hyphens) responses: '200': description: Test status retrieved successfully content: application/json: schema: $ref: '#/components/schemas/Test' '500': description: Internal server error content: application/json: schema: $ref: '#/components/schemas/Error' /tests: get: tags: - tests summary: List all tests description: Returns a paginated list of test summaries with scores and grades. Can be disabled via server configuration. operationId: listTests parameters: - name: offset in: query schema: type: integer minimum: 0 default: 0 description: Number of items to skip - name: limit in: query schema: type: integer minimum: 1 maximum: 100 default: 20 description: Maximum number of items to return responses: '200': description: List of test summaries content: application/json: schema: $ref: '#/components/schemas/TestListResponse' '403': description: Test listing is disabled content: application/json: schema: $ref: '#/components/schemas/Error' '500': description: Internal server error content: application/json: schema: $ref: '#/components/schemas/Error' /report/{id}: get: tags: - reports summary: Get detailed report description: Retrieve comprehensive deliverability analysis report operationId: getReport parameters: - name: id in: path required: true schema: type: string pattern: '^[a-z0-9-]+$' description: Base32-encoded test ID (with hyphens) responses: '200': description: Report retrieved successfully content: application/json: schema: $ref: '#/components/schemas/Report' '404': description: Report not found content: application/json: schema: $ref: '#/components/schemas/Error' /report/{id}/raw: get: tags: - reports summary: Get raw annotated email description: Retrieve the original email with headers added by filters operationId: getRawEmail parameters: - name: id in: path required: true schema: type: string pattern: '^[a-z0-9-]+$' description: Base32-encoded test ID (with hyphens) responses: '200': description: Raw email retrieved successfully content: text/plain: schema: type: string '404': description: Email not found content: application/json: schema: $ref: '#/components/schemas/Error' /report/{id}/reanalyze: post: tags: - reports summary: Reanalyze email and regenerate report description: Re-run the analysis on the stored raw email to regenerate the report with the latest analyzer version. This is useful after analyzer improvements or bug fixes. operationId: reanalyzeReport parameters: - name: id in: path required: true schema: type: string pattern: '^[a-z0-9-]+$' description: Base32-encoded test ID (with hyphens) responses: '200': description: Report regenerated successfully content: application/json: schema: $ref: '#/components/schemas/Report' '404': description: Email not found content: application/json: schema: $ref: '#/components/schemas/Error' '500': description: Internal server error during reanalysis content: application/json: schema: $ref: '#/components/schemas/Error' /domain: post: tags: - tests summary: Test a domain's email configuration description: Analyzes DNS records (MX, SPF, DMARC, BIMI) for a domain without requiring an actual email to be sent. Returns results immediately. operationId: testDomain requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/DomainTestRequest' responses: '200': description: Domain test completed successfully content: application/json: schema: $ref: '#/components/schemas/DomainTestResponse' '400': description: Invalid request content: application/json: schema: $ref: '#/components/schemas/Error' '500': description: Internal server error content: application/json: schema: $ref: '#/components/schemas/Error' /blacklist: post: tags: - tests summary: Check an IP address against DNS blacklists description: Tests a single IP address (IPv4 or IPv6) against configured DNS-based blacklists (RBLs) without requiring an actual email to be sent. Returns results immediately. operationId: checkBlacklist requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/BlacklistCheckRequest' responses: '200': description: Blacklist check completed successfully content: application/json: schema: $ref: '#/components/schemas/BlacklistCheckResponse' '400': description: Invalid request content: application/json: schema: $ref: '#/components/schemas/Error' '500': description: Internal server error content: application/json: schema: $ref: '#/components/schemas/Error' /status: get: tags: - health summary: Service health check description: Get service health status and component versions operationId: getStatus responses: '200': description: Service status content: application/json: schema: $ref: '#/components/schemas/Status' components: schemas: Test: $ref: './schemas.yaml#/components/schemas/Test' TestResponse: $ref: './schemas.yaml#/components/schemas/TestResponse' Report: $ref: './schemas.yaml#/components/schemas/Report' ScoreSummary: $ref: './schemas.yaml#/components/schemas/ScoreSummary' ContentAnalysis: $ref: './schemas.yaml#/components/schemas/ContentAnalysis' ContentIssue: $ref: './schemas.yaml#/components/schemas/ContentIssue' LinkCheck: $ref: './schemas.yaml#/components/schemas/LinkCheck' ImageCheck: $ref: './schemas.yaml#/components/schemas/ImageCheck' HeaderAnalysis: $ref: './schemas.yaml#/components/schemas/HeaderAnalysis' HeaderCheck: $ref: './schemas.yaml#/components/schemas/HeaderCheck' ReceivedHop: $ref: './schemas.yaml#/components/schemas/ReceivedHop' DKIMDomainInfo: $ref: './schemas.yaml#/components/schemas/DKIMDomainInfo' DomainAlignment: $ref: './schemas.yaml#/components/schemas/DomainAlignment' HeaderIssue: $ref: './schemas.yaml#/components/schemas/HeaderIssue' AuthenticationResults: $ref: './schemas.yaml#/components/schemas/AuthenticationResults' AuthResult: $ref: './schemas.yaml#/components/schemas/AuthResult' ARCResult: $ref: './schemas.yaml#/components/schemas/ARCResult' IPRevResult: $ref: './schemas.yaml#/components/schemas/IPRevResult' SpamAssassinResult: $ref: './schemas.yaml#/components/schemas/SpamAssassinResult' SpamTestDetail: $ref: './schemas.yaml#/components/schemas/SpamTestDetail' RspamdResult: $ref: './schemas.yaml#/components/schemas/RspamdResult' DNSResults: $ref: './schemas.yaml#/components/schemas/DNSResults' MXRecord: $ref: './schemas.yaml#/components/schemas/MXRecord' SPFRecord: $ref: './schemas.yaml#/components/schemas/SPFRecord' DKIMRecord: $ref: './schemas.yaml#/components/schemas/DKIMRecord' DMARCRecord: $ref: './schemas.yaml#/components/schemas/DMARCRecord' BIMIRecord: $ref: './schemas.yaml#/components/schemas/BIMIRecord' BlacklistCheck: $ref: './schemas.yaml#/components/schemas/BlacklistCheck' Status: $ref: './schemas.yaml#/components/schemas/Status' Error: $ref: './schemas.yaml#/components/schemas/Error' DomainTestRequest: $ref: './schemas.yaml#/components/schemas/DomainTestRequest' DomainTestResponse: $ref: './schemas.yaml#/components/schemas/DomainTestResponse' BlacklistCheckRequest: $ref: './schemas.yaml#/components/schemas/BlacklistCheckRequest' BlacklistCheckResponse: $ref: './schemas.yaml#/components/schemas/BlacklistCheckResponse' TestSummary: $ref: './schemas.yaml#/components/schemas/TestSummary' TestListResponse: $ref: './schemas.yaml#/components/schemas/TestListResponse'