openapi: 3.1.0
info:
  title: Report URI API
  description: |
    The Report URI REST API provides programmatic access to your report data,
    account configuration, and security policy management.

    ## Authentication

    All API endpoints require Bearer token authentication. Pass your API key in
    the `Authorization` header:

    ```
    Authorization: Bearer ruri_d_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    ```

    API keys can be generated from your account settings. Personal account keys
    start with `ruri_d_`; team keys start with `ruri_t_`.

    ## Rate Limiting

    Requests are rate limited to **120 requests per 60-second window** per account.
    Exceeding this limit returns HTTP 429. The rate limit resets automatically after
    the window expires.

    ## Errors

    All error responses are JSON with an `error` field:

    ```json
    {"error": "Unauthorized"}
    ```
  version: "1"
  contact:
    url: https://report-uri.com
servers:
  - url: https://api.report-uri.com
    description: Production

security:
  - bearerAuth: []

tags:
  - name: Account
    description: Account information and configuration
  - name: Reports
    description: Query collected report data
  - name: Policies
    description: CSP policy management
  - name: Watches
    description: Script Watch, Data Watch, Frame Watch, and Policy Watch
  - name: Certificate Transparency
    description: Certificate Transparency monitoring
  - name: Team
    description: Team management (team API keys only)

components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: |
        API key authentication. Generate keys at https://report-uri.com/api/getKey/.
        Personal keys: `ruri_d_[32 hex chars]`. Team keys: `ruri_t_[32 hex chars]`.

  parameters:
    WatchDomain:
      name: domain
      in: path
      required: true
      description: The domain being watched
      schema:
        type: string
      examples:
        default:
          value: example.com

  schemas:
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: string
          examples:
            - Unauthorized

    ReportTypeValue:
      type: string
      description: Report type identifier
      enum:
        - csp
        - csp_integrity
        - integrity_policy
        - deprecation
        - intervention
        - nel
        - crash
        - dmarc
        - permissions_policy
        - certificate_transparency
        - tls_rpt
        - cross_origin_opener_policy
        - cross_origin_embedder_policy

    CspPolicy:
      type: object
      required:
        - id
        - name
        - policy
      properties:
        id:
          type: string
          description: Unique policy identifier
          examples:
            - abc123
        name:
          type: string
          description: Human-readable policy name
          examples:
            - My Production Policy
        policy:
          type: string
          description: The CSP header value
          examples:
            - "default-src 'self'; script-src 'self' cdn.example.com"

    WatchList:
      type: object
      required:
        - watches
      properties:
        watches:
          type: array
          description: List of monitored domains and their alert configuration
          items:
            type: object
            required:
              - site
              - emailAlertsEnabled
              - webhookEnabled
              - webhookTarget
              - alertThreshold
            properties:
              site:
                type: string
                description: Monitored domain
                examples:
                  - example.com
              emailAlertsEnabled:
                type: boolean
                description: Whether email alerts are enabled for this watch
              webhookEnabled:
                type: boolean
                description: Whether webhook alerts are enabled for this watch
              webhookTarget:
                type: string
                description: Webhook URL for alerts, or empty string if not configured
                examples:
                  - https://alerts.example.com/webhook
              alertThreshold:
                type: integer
                description: Number of findings required before an alert is triggered
                minimum: 1
                examples:
                  - 1
          examples:
            - - site: example.com
                emailAlertsEnabled: true
                webhookEnabled: false
                webhookTarget: ''
                alertThreshold: 1

    WatchFinding:
      type: object
      required:
        - uri
        - count
        - firstSeen
        - lastSeen
        - source
      properties:
        uri:
          type: string
          description: The blocked URI
          examples:
            - https://cdn.example.com/script.js
        count:
          type: integer
          description: Number of times this URI was observed
          examples:
            - 42
        firstSeen:
          type: string
          format: date-time
          description: ISO 8601 timestamp when this URI was first observed
          examples:
            - "2026-01-01T00:00:00+00:00"
        lastSeen:
          type: string
          format: date-time
          description: ISO 8601 timestamp when this URI was last observed
          examples:
            - "2026-03-25T12:00:00+00:00"
        source:
          $ref: '#/components/schemas/ReportTypeValue'
          description: Report type that produced this finding

    BlockedUriFindingsList:
      type: object
      required:
        - findings
      properties:
        findings:
          type: array
          items:
            $ref: '#/components/schemas/WatchFinding'

    PolicyWatchFinding:
      type: object
      required:
        - policy
        - enforced
        - count
        - firstSeen
        - lastSeen
      properties:
        policy:
          type: string
          description: The observed CSP policy header value
          examples:
            - "default-src 'self'"
        enforced:
          type: boolean
          description: Whether this policy was observed in enforce mode
          examples:
            - true
        count:
          type: integer
          description: Number of times this policy was observed
          examples:
            - 17
        firstSeen:
          type: string
          format: date-time
          examples:
            - "2026-01-01T00:00:00+00:00"
        lastSeen:
          type: string
          format: date-time
          examples:
            - "2026-03-25T12:00:00+00:00"

    WizardItem:
      type: object
      required:
        - directive
        - uri
        - lastSeen
      properties:
        directive:
          type: string
          description: The CSP directive this item relates to
          examples:
            - script-src
        uri:
          type: string
          description: The blocked URI
          examples:
            - https://cdn.example.com/script.js
        lastSeen:
          type: string
          format: date-time
          examples:
            - "2026-03-25T12:00:00+00:00"

  responses:
    Unauthorized:
      description: Missing or invalid API key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            default:
              value:
                error: Unauthorized

    Forbidden:
      description: Insufficient permissions (e.g. feature requires a paid plan)
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            default:
              value:
                error: Forbidden

    NotFound:
      description: Resource or route not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            default:
              value:
                error: Not found

    MethodNotAllowed:
      description: HTTP method not allowed for this endpoint
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            default:
              value:
                error: Method not allowed

    TooManyRequests:
      description: Rate limit exceeded (120 requests per 60 seconds)
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            default:
              value:
                error: Too many requests

    InternalServerError:
      description: Unexpected server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            default:
              value:
                error: Internal server error

paths:
  /v1/me:
    get:
      operationId: getMe
      summary: Get account info
      description: |
        Returns information about the authenticated account. The response shape differs
        based on whether a personal or team API key was used.
      tags:
        - Account
      responses:
        '200':
          description: Account information
          content:
            application/json:
              schema:
                oneOf:
                  - title: Personal account
                    type: object
                    required:
                      - type
                      - email
                    properties:
                      type:
                        type: string
                        enum:
                          - personal
                      email:
                        type: string
                        format: email
                        examples:
                          - user@example.com
                  - title: Team account
                    type: object
                    required:
                      - type
                      - teamId
                      - teamName
                    properties:
                      type:
                        type: string
                        enum:
                          - team
                      teamId:
                        type: string
                        examples:
                          - a1b2c3d4-e5f6-7890-abcd-ef1234567890
                      teamName:
                        type: string
                        examples:
                          - Acme Corp
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /v1/setup:
    get:
      operationId: getSetup
      summary: Get setup URLs
      description: |
        Returns all the URIs and email addresses needed to configure report collection
        for your website.
      tags:
        - Account
      responses:
        '200':
          description: Setup configuration
          content:
            application/json:
              schema:
                type: object
                required:
                  - reportUri
                  - reportingApi
                  - nel
                  - dmarc
                  - tlsRpt
                properties:
                  reportUri:
                    type: object
                    description: URLs for the legacy `report-uri` CSP directive
                    required:
                      - enforce
                      - reportOnly
                      - wizard
                    properties:
                      enforce:
                        type: string
                        format: uri
                        description: URL for enforce-mode CSP headers
                        examples:
                          - https://abc123.report-uri.com/r/d/csp/enforce
                      reportOnly:
                        type: string
                        format: uri
                        description: URL for report-only CSP headers
                        examples:
                          - https://abc123.report-uri.com/r/d/csp/reportOnly
                      wizard:
                        type: string
                        format: uri
                        description: URL for the CSP Wizard
                        examples:
                          - https://abc123.report-uri.com/r/d/csp/wizard
                  reportingApi:
                    type: object
                    description: Values for the `Report-To` / `Reporting-Endpoints` header
                    required:
                      - group
                      - max_age
                      - endpoints
                      - include_subdomains
                    properties:
                      group:
                        type: string
                        examples:
                          - default
                      max_age:
                        type: integer
                        examples:
                          - 31536000
                      endpoints:
                        type: array
                        items:
                          type: object
                          required:
                            - url
                          properties:
                            url:
                              type: string
                              format: uri
                              examples:
                                - https://abc123.report-uri.com/a/d/g
                      include_subdomains:
                        type: boolean
                        examples:
                          - true
                  nel:
                    type: object
                    description: Values for the `NEL` header
                    required:
                      - report_to
                      - max_age
                      - include_subdomains
                    properties:
                      report_to:
                        type: string
                        examples:
                          - default
                      max_age:
                        type: integer
                        examples:
                          - 31536000
                      include_subdomains:
                        type: boolean
                        examples:
                          - true
                  dmarc:
                    type: string
                    description: Email address for the DMARC `rua`/`ruf` tags
                    examples:
                      - abc123@dmarc.report-uri.com
                  tlsRpt:
                    type: string
                    description: Email address for the SMTP TLS Reporting `rua` tag
                    examples:
                      - abc123@tlsrpt.report-uri.com
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /v1/filters:
    get:
      operationId: getFilters
      summary: Get filter settings
      description: Returns the account's report collection and filtering configuration.
      tags:
        - Account
      responses:
        '200':
          description: Filter settings
          content:
            application/json:
              schema:
                type: object
                required:
                  - global
                  - advanced
                  - certificateTransparency
                  - sampling
                properties:
                  global:
                    type: object
                    required:
                      - removeReferrer
                      - removeQueryStringAndFragment
                      - collectHosts
                      - clientReputation
                    properties:
                      removeReferrer:
                        type: boolean
                        description: Whether referrer information is stripped from reports
                      removeQueryStringAndFragment:
                        type: boolean
                        description: Whether query strings and fragments are stripped from URIs in reports
                      collectHosts:
                        type: array
                        description: Allowlisted hostnames; only reports from these hosts are collected (empty means collect from all)
                        items:
                          type: string
                          examples:
                            - example.com
                      clientReputation:
                        type: integer
                        nullable: true
                        description: Client reputation threshold (0–100); reports from clients with a score below this value are filtered. Null means no filtering.
                        minimum: 0
                        maximum: 100
                        examples:
                          - 100
                  advanced:
                    type: object
                    required:
                      - filterBrowserExtensions
                      - filterNoise
                      - removeData
                      - removeAbout
                    properties:
                      filterBrowserExtensions:
                        type: boolean
                        description: Whether reports from browser extensions are filtered
                      filterNoise:
                        type: boolean
                        description: Whether noise filtering is enabled
                      removeData:
                        type: boolean
                        description: Whether `data:` URIs are filtered from reports
                      removeAbout:
                        type: boolean
                        description: Whether `about:` URIs are filtered from reports
                  certificateTransparency:
                    type: object
                    required:
                      - emailAlerts
                      - hosts
                    properties:
                      emailAlerts:
                        type: boolean
                        description: Whether email alerts are enabled for new certificates
                      hosts:
                        type: array
                        description: Hostnames monitored via Certificate Transparency
                        items:
                          type: string
                          examples:
                            - example.com
                  sampling:
                    type: object
                    description: >
                      Sampling rates per report type. Keys are report type identifiers (e.g. `csp`,
                      `nel`, `csp_integrity`) plus `wizard` for CSP Wizard reports. Only samplable
                      types are included; non-samplable types such as `dmarc`, `certificate_transparency`, and `tls_rpt`
                      are omitted.
                    additionalProperties:
                      type: object
                      required:
                        - value
                        - label
                      properties:
                        value:
                          type: integer
                          description: Sampling rate as a percentage (1–100)
                          minimum: 1
                          maximum: 100
                        label:
                          type: string
                          description: Human-readable label for the report type
                    examples:
                      - csp:
                          value: 100
                          label: Content Security Policy
                        nel:
                          value: 50
                          label: Network Error Logging
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /v1/quota:
    get:
      operationId: getQuota
      summary: Get quota usage
      description: Returns the number of reports consumed and the monthly quota limit for the current billing period.
      tags:
        - Account
      responses:
        '200':
          description: Quota information
          content:
            application/json:
              schema:
                type: object
                required:
                  - used
                  - limit
                properties:
                  used:
                    type: integer
                    description: Reports consumed in the current billing period
                    examples:
                      - 48230
                  limit:
                    type: integer
                    description: Monthly report quota limit
                    examples:
                      - 100000
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /v1/breakdown:
    get:
      operationId: getBreakdown
      summary: Get monthly breakdown by report type
      description: Returns the count of accepted reports per type in the current billing period, sorted by count descending.
      tags:
        - Reports
      responses:
        '200':
          description: Monthly breakdown
          content:
            application/json:
              schema:
                type: object
                required:
                  - breakdown
                properties:
                  breakdown:
                    type: array
                    items:
                      type: object
                      required:
                        - type
                        - label
                        - accepted
                      properties:
                        type:
                          $ref: '#/components/schemas/ReportTypeValue'
                        label:
                          type: string
                          examples:
                            - CSP
                        accepted:
                          type: integer
                          description: Reports accepted this billing period
                          examples:
                            - 12300
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /v1/last-seven-days:
    get:
      operationId: getLastSevenDays
      summary: Get last 7 days of daily report totals
      description: Returns daily report counts per type for the last 7 days.
      tags:
        - Reports
      responses:
        '200':
          description: Daily report counts
          content:
            application/json:
              schema:
                type: object
                required:
                  - days
                properties:
                  days:
                    type: array
                    items:
                      type: object
                      required:
                        - date
                        - reports
                      properties:
                        date:
                          type: string
                          format: date
                          description: Date in YYYY-MM-DD format
                          examples:
                            - "2026-03-25"
                        reports:
                          type: object
                          description: Report counts keyed by report type
                          additionalProperties:
                            type: integer
                          examples:
                            - csp: 1500
                              nel: 300
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /v1/usage-metrics:
    get:
      operationId: getUsageMetrics
      summary: Get usage metrics
      description: Returns accepted, filtered, sampled, and rejected report counts per type for the current billing period, sorted by accepted count descending.
      tags:
        - Reports
      responses:
        '200':
          description: Usage metrics
          content:
            application/json:
              schema:
                type: object
                required:
                  - metrics
                properties:
                  metrics:
                    type: array
                    items:
                      type: object
                      required:
                        - type
                        - label
                        - accepted
                        - filtered
                        - sampled
                        - rejected
                      properties:
                        type:
                          $ref: '#/components/schemas/ReportTypeValue'
                        label:
                          type: string
                          examples:
                            - CSP
                        accepted:
                          type: integer
                          examples:
                            - 12300
                        filtered:
                          type: integer
                          examples:
                            - 450
                        sampled:
                          type: integer
                          examples:
                            - 0
                        rejected:
                          type: integer
                          examples:
                            - 12
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /v1/report-types:
    get:
      operationId: getReportTypes
      summary: List available report types
      description: Returns all report types supported by the platform.
      tags:
        - Reports
      responses:
        '200':
          description: Report types
          content:
            application/json:
              schema:
                type: object
                required:
                  - types
                properties:
                  types:
                    type: array
                    items:
                      type: object
                      required:
                        - type
                        - label
                      properties:
                        type:
                          $ref: '#/components/schemas/ReportTypeValue'
                        label:
                          type: string
                          examples:
                            - CSP
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /v1/audit-log:
    get:
      operationId: getAuditLog
      summary: Get audit log
      description: |
        Returns account audit trail events in reverse chronological order. If there
        are more events than can be returned, `truncated` will be `true`.
      tags:
        - Account
      responses:
        '200':
          description: Audit log events
          content:
            application/json:
              schema:
                type: object
                required:
                  - events
                  - truncated
                properties:
                  events:
                    type: array
                    items:
                      type: object
                      required:
                        - timestamp
                        - event
                        - message
                        - loggedById
                        - loggedByEmail
                      properties:
                        timestamp:
                          type: string
                          format: date-time
                          examples:
                            - "2026-03-25T10:30:00+00:00"
                        event:
                          type: string
                          description: Machine-readable event identifier
                          examples:
                            - api_key_created
                        message:
                          type: string
                          description: Human-readable event description
                          examples:
                            - API key created.
                        loggedById:
                          type: string
                          description: ID of the user who triggered the event
                        loggedByEmail:
                          type: string
                          format: email
                          examples:
                            - user@example.com
                  truncated:
                    type: boolean
                    description: Whether the result was truncated due to volume
                    examples:
                      - false
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /v1/policies/csp:
    get:
      operationId: getCspPolicies
      summary: List saved CSP policies
      description: Returns all saved CSP policies for the account.
      tags:
        - Policies
      responses:
        '200':
          description: CSP policy list
          content:
            application/json:
              schema:
                type: object
                required:
                  - policies
                properties:
                  policies:
                    type: array
                    items:
                      $ref: '#/components/schemas/CspPolicy'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /v1/policies/csp/{id}:
    get:
      operationId: getCspPolicyById
      summary: Get a CSP policy by ID
      tags:
        - Policies
      parameters:
        - name: id
          in: path
          required: true
          description: CSP policy ID
          schema:
            type: string
          examples:
            default:
              value: abc123
      responses:
        '200':
          description: CSP policy
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CspPolicy'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /v1/wizard/csp:
    get:
      operationId: getCspWizard
      summary: Get CSP wizard status
      description: |
        Returns the current state of the CSP Wizard, including new, allowed, and blocked
        URI findings. Returns `{"enabled": false}` when the wizard is not active.
      tags:
        - Policies
      responses:
        '200':
          description: CSP wizard status
          content:
            application/json:
              schema:
                oneOf:
                  - title: Wizard disabled
                    type: object
                    required:
                      - enabled
                    properties:
                      enabled:
                        type: boolean
                        enum:
                          - false
                  - title: Wizard enabled
                    type: object
                    required:
                      - enabled
                      - policy
                      - new
                      - allowed
                      - blocked
                    properties:
                      enabled:
                        type: boolean
                        enum:
                          - true
                      policy:
                        type: object
                        required:
                          - id
                          - name
                        properties:
                          id:
                            type: string
                            examples:
                              - abc123
                          name:
                            type: string
                            examples:
                              - My Wizard Policy
                      new:
                        type: array
                        description: Newly observed URIs not yet classified
                        items:
                          $ref: '#/components/schemas/WizardItem'
                      allowed:
                        type: array
                        description: URIs marked as allowed
                        items:
                          $ref: '#/components/schemas/WizardItem'
                      blocked:
                        type: array
                        description: URIs marked as blocked
                        items:
                          $ref: '#/components/schemas/WizardItem'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /v1/watches/script:
    get:
      operationId: getScriptWatchList
      summary: List Script Watch domains
      description: Returns all domains currently being monitored by Script Watch.
      tags:
        - Watches
      responses:
        '200':
          description: Script Watch domain list
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WatchList'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /v1/watches/data:
    get:
      operationId: getDataWatchList
      summary: List Data Watch domains
      description: Returns all domains currently being monitored by Data Watch.
      tags:
        - Watches
      responses:
        '200':
          description: Data Watch domain list
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WatchList'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /v1/watches/frame:
    get:
      operationId: getFrameWatchList
      summary: List Frame Watch domains
      description: Returns all domains currently being monitored by Frame Watch.
      tags:
        - Watches
      responses:
        '200':
          description: Frame Watch domain list
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WatchList'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /v1/watches/policy:
    get:
      operationId: getPolicyWatchList
      summary: List Policy Watch domains
      description: Returns all domains currently being monitored by Policy Watch.
      tags:
        - Watches
      responses:
        '200':
          description: Policy Watch domain list
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WatchList'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /v1/watches/script/{domain}:
    get:
      operationId: getScriptWatchFindings
      summary: Get Script Watch findings for a domain
      description: Returns all blocked script URIs observed for the specified domain, sorted by last seen descending.
      tags:
        - Watches
      parameters:
        - $ref: '#/components/parameters/WatchDomain'
      responses:
        '200':
          description: Script Watch findings
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BlockedUriFindingsList'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /v1/watches/data/{domain}:
    get:
      operationId: getDataWatchFindings
      summary: Get Data Watch findings for a domain
      description: Returns all blocked data exfiltration URIs observed for the specified domain, sorted by last seen descending.
      tags:
        - Watches
      parameters:
        - $ref: '#/components/parameters/WatchDomain'
      responses:
        '200':
          description: Data Watch findings
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BlockedUriFindingsList'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /v1/watches/frame/{domain}:
    get:
      operationId: getFrameWatchFindings
      summary: Get Frame Watch findings for a domain
      description: Returns all blocked framing URIs observed for the specified domain, sorted by last seen descending.
      tags:
        - Watches
      parameters:
        - $ref: '#/components/parameters/WatchDomain'
      responses:
        '200':
          description: Frame Watch findings
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BlockedUriFindingsList'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /v1/watches/policy/{domain}:
    get:
      operationId: getPolicyWatchFindings
      summary: Get Policy Watch findings for a domain
      description: Returns all CSP policies observed for the specified domain.
      tags:
        - Watches
      parameters:
        - $ref: '#/components/parameters/WatchDomain'
      responses:
        '200':
          description: Policy Watch findings
          content:
            application/json:
              schema:
                type: object
                required:
                  - findings
                properties:
                  findings:
                    type: array
                    items:
                      $ref: '#/components/schemas/PolicyWatchFinding'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /v1/certificate-transparency/cert/{sha256}:
    get:
      operationId: getCertificate
      summary: Get a CT certificate
      description: Returns the PEM-encoded certificate for the given SHA-256 hash observed via Certificate Transparency.
      tags:
        - Certificate Transparency
      parameters:
        - name: sha256
          in: path
          required: true
          description: SHA-256 hash of the certificate
          schema:
            type: string
            pattern: '^[a-f0-9]{64}$'
          example: a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2
      responses:
        '200':
          description: Certificate data
          content:
            application/json:
              schema:
                type: object
                required:
                  - sha256
                  - pem
                properties:
                  sha256:
                    type: string
                    description: SHA-256 hash of the certificate
                    example: a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2
                  pem:
                    type: string
                    description: PEM-encoded certificate
                    examples:
                      - "-----BEGIN CERTIFICATE-----\nMIIB...\n-----END CERTIFICATE-----"
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /v1/graphs/{type}/{unit}/{amount}:
    get:
      operationId: getGraphs
      summary: Get graph data
      description: |
        Returns time-series data suitable for charts. Weeks 2–4 and all month intervals
        require a paid subscription.

        **Valid amounts:**
        - `weeks`: 1, 2, 3, or 4
        - `months`: 3, 6, or 12

        For CSP reports, each period includes a per-directive breakdown. For all other
        report types, only a total count is returned per period.
      tags:
        - Reports
      parameters:
        - name: type
          in: path
          required: true
          description: Report type
          schema:
            $ref: '#/components/schemas/ReportTypeValue'
        - name: unit
          in: path
          required: true
          description: Time unit
          schema:
            type: string
            enum:
              - weeks
              - months
        - name: amount
          in: path
          required: true
          description: "Number of units. For `weeks`: 1, 2, 3, or 4. For `months`: 3, 6, or 12."
          schema:
            type: integer
            enum:
              - 1
              - 2
              - 3
              - 4
              - 6
              - 12
          examples:
            default:
              value: 4
      responses:
        '200':
          description: Graph data
          content:
            application/json:
              schema:
                type: object
                required:
                  - type
                  - unit
                  - amount
                  - periods
                properties:
                  type:
                    $ref: '#/components/schemas/ReportTypeValue'
                  unit:
                    type: string
                    enum:
                      - weeks
                      - months
                  amount:
                    type: integer
                    examples:
                      - 4
                  periods:
                    type: array
                    items:
                      oneOf:
                        - title: Non-CSP period
                          type: object
                          required:
                            - date
                            - total
                          properties:
                            date:
                              type: string
                              description: "`YYYY-MM-DD` for weeks, `YYYY-MM` for months"
                              examples:
                                - "2026-03-25"
                            total:
                              type: integer
                              examples:
                                - 1500
                        - title: CSP period
                          type: object
                          required:
                            - date
                            - total
                            - directives
                          properties:
                            date:
                              type: string
                              examples:
                                - "2026-03-25"
                            total:
                              type: integer
                              examples:
                                - 1500
                            directives:
                              type: object
                              description: Report counts per CSP directive
                              additionalProperties:
                                type: integer
                              examples:
                                - script-src: 800
                                  style-src: 200
                                  unknown: 500
        '400':
          description: Invalid parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                default:
                  value:
                    error: "Invalid amount for weeks: must be 1, 2, 3, or 4"
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /v1/reports/{type}:
    get:
      operationId: getReports
      summary: Get report records
      description: |
        Returns individual report records for a given type and time window.

        **Required query parameters:** `unit` and `date`.

        **Date formats by unit:**
        - `hours`: `YYYY-MM-DDTHH` (e.g. `2026-03-25T14`)
        - `days`: `YYYY-MM-DD` (e.g. `2026-03-25`)
        - `months`: `YYYY-MM` (e.g. `2026-03`)

        Results are limited by your plan's data retention period. If the result set is
        large, `truncated` will be `true`. The optional filter parameters are type-specific —
        supply only the filters relevant to the report type being queried.
      tags:
        - Reports
      parameters:
        - name: type
          in: path
          required: true
          description: Report type to query
          schema:
            $ref: '#/components/schemas/ReportTypeValue'
        - name: unit
          in: query
          required: true
          description: Time granularity
          schema:
            type: string
            enum:
              - hours
              - days
              - months
          examples:
            default:
              value: days
        - name: date
          in: query
          required: true
          description: Time window to query in the format matching `unit`
          schema:
            type: string
          examples:
            default:
              value: "2026-03-25"
        - name: action
          in: query
          description: Filter by report action
          schema:
            type: string
            enum:
              - accept
              - filter
              - downsample
              - reject
        - name: hostnames
          in: query
          description: Filter by source hostname
          schema:
            type: string
        - name: paths
          in: query
          description: Filter by source path
          schema:
            type: string
        - name: effectiveDirective
          in: query
          description: Filter by CSP directive (CSP reports)
          schema:
            type: string
        - name: blockedHostnames
          in: query
          description: Filter by blocked hostname
          schema:
            type: string
        - name: blockedPaths
          in: query
          description: Filter by blocked path
          schema:
            type: string
        - name: subresourceHostnames
          in: query
          description: Filter by subresource hostname (CSP Integrity / Integrity Policy reports)
          schema:
            type: string
        - name: subresourcePaths
          in: query
          description: Filter by subresource path (CSP Integrity / Integrity Policy reports)
          schema:
            type: string
        - name: subresourceHashes
          in: query
          description: Filter by subresource hash (CSP Integrity / Integrity Policy reports)
          schema:
            type: string
        - name: browser
          in: query
          description: Filter by browser
          schema:
            type: string
        - name: platform
          in: query
          description: Filter by platform
          schema:
            type: string
        - name: nelType
          in: query
          description: Filter by NEL error type (NEL reports)
          schema:
            type: string
        - name: phase
          in: query
          description: Filter by NEL phase (NEL reports)
          schema:
            type: string
        - name: disposition
          in: query
          description: Filter by DMARC disposition (DMARC reports)
          schema:
            type: string
            enum:
              - none
              - quarantine
              - reject
        - name: organisation
          in: query
          description: Filter by reporting organisation (DMARC reports)
          schema:
            type: string
        - name: id
          in: query
          description: Filter by report ID
          schema:
            type: string
        - name: certType
          in: query
          description: Filter by certificate type (CT reports)
          schema:
            type: string
        - name: issuer
          in: query
          description: Filter by certificate issuer (CT reports)
          schema:
            type: string
        - name: policyId
          in: query
          description: Filter by CSP policy ID
          schema:
            type: string
        - name: message
          in: query
          description: Filter by message text (Deprecation / Intervention reports)
          schema:
            type: string
        - name: policy
          in: query
          description: Filter by policy identifier (Permissions Policy reports)
          schema:
            type: string
        - name: property
          in: query
          description: Filter by policy property (Permissions Policy reports)
          schema:
            type: string
        - name: destination
          in: query
          description: Filter by fetch destination (Integrity Policy reports)
          schema:
            type: string
        - name: sha256Spki
          in: query
          description: Filter by SHA-256 SPKI fingerprint (CT reports)
          schema:
            type: string
        - name: ioc
          in: query
          description: Filter to threat intelligence matches only. Pass `true` to enable.
          schema:
            type: string
            enum:
              - 'true'
        - name: generatedDomain
          in: query
          description: Filter to algorithmically generated domains only. Pass `true` to enable.
          schema:
            type: string
            enum:
              - 'true'
        - name: newlyRegisteredDomain
          in: query
          description: Filter to newly registered domains only. Pass `true` to enable.
          schema:
            type: string
            enum:
              - 'true'
        - name: domainReputationScore
          in: query
          description: Filter by maximum domain reputation score
          schema:
            type: integer
      responses:
        '200':
          description: Report records
          content:
            application/json:
              schema:
                type: object
                required:
                  - reports
                  - truncated
                properties:
                  reports:
                    type: array
                    description: Report records. The fields of each object depend on the report type.
                    items:
                      type: object
                      additionalProperties: true
                  truncated:
                    type: boolean
                    description: Whether the result was truncated due to volume
                    examples:
                      - false
        '400':
          description: Invalid query parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                default:
                  value:
                    error: "Invalid unit: must be hours, days, or months"
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /v1/team:
    get:
      operationId: getTeam
      summary: Get team info
      description: |
        Returns team details including members, quota limit, and 2FA requirements.

        When called with a personal API key, returns a message object rather than an error.
      tags:
        - Team
      responses:
        '200':
          description: Team info, or message when called with a personal API key
          content:
            application/json:
              schema:
                oneOf:
                  - title: Team info
                    type: object
                    required:
                      - name
                      - members
                      - quotaLimit
                      - twoFaRequired
                    properties:
                      name:
                        type: string
                        description: Team name
                        examples:
                          - Acme Corp
                      members:
                        type: array
                        items:
                          type: object
                          required:
                            - email
                            - role
                          properties:
                            email:
                              type: string
                              format: email
                              examples:
                                - admin@example.com
                            role:
                              type: string
                              examples:
                                - owner
                      quotaLimit:
                        type: integer
                        description: Monthly report quota for the team
                        examples:
                          - 1000000
                      twoFaRequired:
                        type: boolean
                        description: Whether 2FA is required for all team members
                        examples:
                          - false
                  - title: Personal key message
                    type: object
                    required:
                      - message
                    properties:
                      message:
                        type: string
                        examples:
                          - This endpoint is only available for team API keys.
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
