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

# Report now playing

> Requires exactly one of `?stationId=` or `?stationSlug=` (public station slug, same as `/api/v1/stations/{stationSlug}`) plus an integration credential (integration `playback`, scope `ingest:write`) for that same station. Body is at most 8 KiB. Send `artist` and `title`, or a single encoder `streamTitle` (`Artist - Title`; without a separator the whole string is stored as title). Legacy `duration` (seconds) is accepted as an alias of `durationSeconds` but both must match when present. Valid observations are persisted before rundown following; `eventId` deduplicates provider retries and legacy payloads without ids may collapse within a short adjacent window. Rundown following still requires a live broadcast at `observedAt`. When the station has artwork lookup on and the body omits `artworkUrl`, a provider lookup may fill the stored track after this response; the response does not wait for it. Errors on this compatibility-sensitive endpoint are `{ error: string }`.



## OpenAPI

````yaml /radiotools/openapi.json post /api/v1/integrations/playback
openapi: 3.1.0
info:
  title: RadioTools API
  version: 1.0.0
  description: >-
    RadioTools APIs for listener websites and apps, published media, and
    now-playing metadata ingestion.
servers:
  - url: https://radiotools.rivi.software
    description: radiotools API
security: []
tags:
  - name: Public listener
    description: >-
      Tenant-token published delivery (listener:read; push:register for device
      changes). Published media remains anonymous. OPTIONS allows every origin;
      JSON is no-store with a strong ETag for conditional polling.
  - name: Ingest
    description: >-
      Automation credentials. The credential resolves the station; payloads
      cannot change it.
paths:
  /api/v1/integrations/playback:
    post:
      tags:
        - Ingest
      summary: Canonical now-playing observation ingest for automation systems
      description: >-
        Requires exactly one of `?stationId=` or `?stationSlug=` (public station
        slug, same as `/api/v1/stations/{stationSlug}`) plus an integration
        credential (integration `playback`, scope `ingest:write`) for that same
        station. Body is at most 8 KiB. Send `artist` and `title`, or a single
        encoder `streamTitle` (`Artist - Title`; without a separator the whole
        string is stored as title). Legacy `duration` (seconds) is accepted as
        an alias of `durationSeconds` but both must match when present. Valid
        observations are persisted before rundown following; `eventId`
        deduplicates provider retries and legacy payloads without ids may
        collapse within a short adjacent window. Rundown following still
        requires a live broadcast at `observedAt`. When the station has artwork
        lookup on and the body omits `artworkUrl`, a provider lookup may fill
        the stored track after this response; the response does not wait for it.
        Errors on this compatibility-sensitive endpoint are `{ error: string }`.
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 80
          required: false
          name: stationId
          in: query
          description: >-
            Station ID associated with your credential. Send this or
            stationSlug, not both.
          example: station-rivier
        - schema:
            type: string
            minLength: 3
            maxLength: 63
          required: false
          name: stationSlug
          in: query
          description: >-
            Public station slug from the station settings; distinct from the
            internal station ID.
          example: radio-rivier
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                eventId:
                  type: string
                  minLength: 1
                  maxLength: 100
                  description: >-
                    Stable source event identifier for deduplicating retries of
                    the same observation.
                  example: automation-rivier-20261005-080000
                observedAt:
                  type: integer
                  minimum: 0
                  maximum: 8640000000000000
                  description: >-
                    Source observation time as Unix milliseconds (not seconds).
                    Omit when the encoder cannot supply it.
                  example: 1791187200000
                artist:
                  type: string
                  minLength: 1
                  maxLength: 500
                  description: Artist reported by external automation.
                  example: The Riverlights
                title:
                  type: string
                  minLength: 1
                  maxLength: 500
                  description: >-
                    Human-readable title. Track titles come from external
                    automation.
                  example: Morning Sun
                streamTitle:
                  type: string
                  minLength: 1
                  maxLength: 1001
                  description: >-
                    Encoder stream title, usually Artist - Title. Without a
                    separator, the whole string is stored as the title.
                album:
                  type: string
                  minLength: 1
                  maxLength: 500
                  description: Reported album; null when unknown in listener responses.
                  example: Open Water
                sourceTrackId:
                  type: string
                  minLength: 1
                  maxLength: 120
                  description: >-
                    Optional track identifier in the automation library. Omitted
                    from listener responses.
                  example: library-track-4821
                artworkUrl:
                  type: string
                  minLength: 1
                  maxLength: 2048
                  format: uri
                  description: >-
                    Artwork URL when available. May be omitted; do not assume
                    every track has artwork.
                durationSeconds:
                  type:
                    - integer
                    - 'null'
                  minimum: 0
                  maximum: 86400
                  description: Reported track duration in seconds; null when unknown.
                  example: 210
                duration:
                  type:
                    - integer
                    - 'null'
                  minimum: 0
                  maximum: 86400
                  description: >-
                    Legacy alias of durationSeconds. If both are provided, their
                    values must match.
                isPlaying:
                  type: boolean
                  default: true
                  description: >-
                    Whether the automation observation reports the track as
                    playing.
                  example: true
              additionalProperties: false
              example:
                eventId: automation-rivier-20261005-080000
                observedAt: 1791187200000
                artist: The Riverlights
                title: Morning Sun
                album: Open Water
                sourceTrackId: library-track-4821
                durationSeconds: 210
                isPlaying: true
            examples:
              fields:
                summary: Separate artist and title
                description: >-
                  observedAt is Unix time in milliseconds. Reuse the same
                  eventId only when retrying the same observation.
                value:
                  eventId: automation-rivier-20261005-080000
                  observedAt: 1791187200000
                  artist: The Riverlights
                  title: Morning Sun
                  album: Open Water
                  sourceTrackId: library-track-4821
                  durationSeconds: 210
                  isPlaying: true
              streamTitle:
                summary: Encoder stream title
                description: >-
                  For encoders that send a single stream title. Without a
                  separator, the full string becomes the title.
                value:
                  streamTitle: The Riverlights - Morning Sun
                  isPlaying: true
      responses:
        '200':
          description: Observation outcome
          content:
            application/json:
              schema:
                type: object
                properties:
                  accepted:
                    type: boolean
                    description: >-
                      Whether the ingest/follow result was accepted. Inspect
                      outcome for the detailed result.
                    example: true
                  outcome:
                    type: string
                    enum:
                      - no-live-broadcast
                      - on-air-not-following-rundown
                      - not-playing
                      - rejected
                      - recorded
                      - matched
                      - uncertain
                      - ignored
                    description: >-
                      Ingest or rundown-follow result. Observations do not
                      control audio playback.
                    example: recorded
                required:
                  - accepted
                  - outcome
                example:
                  accepted: true
                  outcome: recorded
              examples:
                recorded:
                  summary: Observation recorded
                  description: >-
                    Illustrative response using fictional station data. Replace
                    identifiers with values returned by your station.
                  value:
                    accepted: true
                    outcome: recorded
                noLiveBroadcast:
                  summary: No live broadcast for rundown following
                  description: >-
                    A valid observation can be persisted even when there is no
                    live broadcast to follow. The outcome describes the
                    ingest/follow result, not audio control.
                  value:
                    accepted: false
                    outcome: no-live-broadcast
        '400':
          description: Invalid observation or content type
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    description: Encoder-compatible error summary.
                    example: The request contains invalid parameters or input.
                required:
                  - error
                example:
                  error: The request contains invalid parameters or input.
              examples:
                error:
                  summary: Encoder-compatible error
                  value:
                    error: The request contains invalid parameters or input.
        '401':
          description: Missing, unknown, revoked or cross-station credential
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    description: Encoder-compatible error summary.
                    example: >-
                      A valid station credential with the required scope is
                      needed.
                required:
                  - error
                example:
                  error: >-
                    A valid station credential with the required scope is
                    needed.
              examples:
                error:
                  summary: Encoder-compatible error
                  value:
                    error: >-
                      A valid station credential with the required scope is
                      needed.
        '405':
          description: Use POST
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    description: Encoder-compatible error summary.
                    example: Use the documented HTTP method for this endpoint.
                required:
                  - error
                example:
                  error: Use the documented HTTP method for this endpoint.
              examples:
                error:
                  summary: Encoder-compatible error
                  value:
                    error: Use the documented HTTP method for this endpoint.
      security:
        - integrationToken: []
components:
  securitySchemes:
    integrationToken:
      type: http
      scheme: bearer
      bearerFormat: rtm_…
      description: >-
        Integration credential (playback) with ingest:write. Send Authorization:
        Bearer `<token>`. Sending the rtm_ token alone without Bearer returns
        401. In an API client's Bearer token field, enter only the raw rtm_
        token; the client adds the prefix.

````

## Related topics

- [Now-playing ingest](/radiotools/api-reference/now-playing-ingest.md)
- [Get now playing](/radiotools/api-reference/public-listener/get-now-playing.md)
- [Public delivery](/radiotools/api-reference/public-delivery.md)
- [GraphQL schema reference](/radiotools/api-reference/graphql-reference.md)
- [Authentication](/radiotools/api-reference/authentication.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.