> ## Documentation Index
> Fetch the complete documentation index at: https://docs.capedigital.co.ke/llms.txt
> Use this file to discover all available pages before exploring further.

# Not-aired story reason breakdown

> Powers the **Not-aired reasons** doughnut on the **Content analytics** screen.

Groups `BulletinStory` records where `airing_status = not_aired` by the `not_aired_reason` field added in migration `0041`. Reasons:

| Value | Label |
|---|---|
| `time_constraints` | Time Constraints |
| `legal_hold` | Legal Hold |
| `breaking_news` | Breaking News Displaced |
| `editor_decision` | Editor Decision |
| `technical` | Technical Issue |
| `other` | Other |
| `unknown` | `not_aired_reason` was NULL (pre-migration data) |

`share_pct` sums to 100 across the returned rows.



## OpenAPI

````yaml /openapi/content.yaml get /api/v1/analytics/content/not-aired
openapi: 3.0.3
info:
  title: Content Service API
  version: 1.0.0
  description: |2-

        **Content Service API** - Comprehensive content(story) and management system.
        
servers:
  - url: https://api.capedigital.co.ke/content
    description: Production
  - url: http://localhost:8000
    description: Local
security: []
paths:
  /api/v1/analytics/content/not-aired:
    get:
      tags:
        - Content Analytics
      summary: Not-aired story reason breakdown
      description: >-
        Powers the **Not-aired reasons** doughnut on the **Content analytics**
        screen.


        Groups `BulletinStory` records where `airing_status = not_aired` by the
        `not_aired_reason` field added in migration `0041`. Reasons:


        | Value | Label |

        |---|---|

        | `time_constraints` | Time Constraints |

        | `legal_hold` | Legal Hold |

        | `breaking_news` | Breaking News Displaced |

        | `editor_decision` | Editor Decision |

        | `technical` | Technical Issue |

        | `other` | Other |

        | `unknown` | `not_aired_reason` was NULL (pre-migration data) |


        `share_pct` sums to 100 across the returned rows.
      operationId: analytics_content_not_aired_list
      parameters:
        - in: query
          name: period
          schema:
            type: string
          description: |-
            Period string. Accepted formats:
            - `2026-05` — calendar month
            - `Q2-2026` — quarter (Q1–Q4)
            - `YTD-2026` — year to date
          required: true
        - in: query
          name: platform
          schema:
            type: string
            enum:
              - radio
              - television
          description: Broadcast platform. One of `television` (default) or `radio`.
      responses:
        '200':
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/NotAiredReason'
              examples:
                May2026—TV:
                  value:
                    - - reason: time_constraints
                        count: 25
                        share_pct: '44.6'
                      - reason: legal_hold
                        count: 10
                        share_pct: '17.9'
                      - reason: breaking_news
                        count: 9
                        share_pct: '16.1'
                      - reason: editor_decision
                        count: 7
                        share_pct: '12.5'
                      - reason: technical
                        count: 5
                        share_pct: '8.9'
                  summary: May 2026 — TV
          description: ''
      security:
        - bearerAuth: []
components:
  schemas:
    NotAiredReason:
      type: object
      properties:
        reason:
          type: string
        count:
          type: integer
        share_pct:
          type: string
          format: decimal
          pattern: ^-?\d{0,4}(?:\.\d{0,1})?$
      required:
        - count
        - reason
        - share_pct
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: 'Enter your JWT token in the format: Bearer <token>'

````