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

# Live Activity Stream

> Use a stable stream_key for each ongoing thing you want to show as a Live Activity. Send the latest content_state whenever it changes, and ActivitySmith will keep the Live Activity in sync. For timer streams, send duration_seconds to start or reset the timer; omit duration_seconds on later updates to preserve the existing timer window. Use secondary_action for a second button on alert, progress, and segmented_progress Live Activities. Optional tags to organize and filter notification history. On later stream updates, omit tags to keep the current tags, send tags again to replace them, or send an empty array to clear them.

Use this endpoint when you want ActivitySmith to manage the Live Activity for
you.

* Send the latest state for a stable `stream_key`.
* If the Live Activity does not exist yet, ActivitySmith starts it.
* If it already exists, ActivitySmith updates it.
* You do not need to keep local state between updates.
* For `timer`, send `duration_seconds` for countdowns. To start at 00:00 and count up, set `counts_down` to `false` and leave out `duration_seconds`.
* Later `timer` updates can change visible fields without sending `duration_seconds`.

This is a good fit for cron jobs, scheduled tasks, CI workflows, monitoring
jobs, and background workers that only know the latest state.

To stop a managed stream, use
[`DELETE /live-activity/stream/{stream_key}`](/docs/api-reference/endpoint/live-activity-stream-end).


## OpenAPI

````yaml PUT /live-activity/stream/{stream_key}
openapi: 3.1.0
info:
  title: ActivitySmith API
  description: >-
    Send push notifications and Live Activities to your own devices via a single
    API key.
  version: 1.0.0
servers:
  - url: https://activitysmith.com/api
security:
  - apiKeyAuth: []
tags:
  - name: PushNotifications
    description: Send push notifications to paired devices.
  - name: AppIconBadges
    description: Update App Icon Badge Counts on paired devices.
  - name: LiveActivities
    description: Start, update, stream, and end Live Activities.
  - name: Metrics
    description: Update metric values shown in ActivitySmith widgets.
paths:
  /live-activity/stream/{stream_key}:
    put:
      tags:
        - LiveActivities
      summary: Start a new Live Activity or update an existing one
      description: >-
        Use a stable stream_key for each ongoing thing you want to show as a
        Live Activity. Send the latest content_state whenever it changes, and
        ActivitySmith will keep the Live Activity in sync. For timer streams,
        send duration_seconds to start or reset the timer; omit duration_seconds
        on later updates to preserve the existing timer window. Use
        secondary_action for a second button on alert, progress, and
        segmented_progress Live Activities. Optional tags to organize and filter
        notification history. On later stream updates, omit tags to keep the
        current tags, send tags again to replace them, or send an empty array to
        clear them.
      operationId: reconcileLiveActivityStream
      parameters:
        - name: stream_key
          in: path
          required: true
          description: >-
            Stable identifier for one ongoing thing. Allowed characters:
            letters, numbers, underscores, and hyphens.
          schema:
            type: string
            maxLength: 255
            pattern: ^[A-Za-z0-9_-]+$
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/LiveActivityStreamRequest'
            examples:
              metrics:
                value:
                  content_state:
                    title: Server Health
                    subtitle: prod-web-1
                    type: metrics
                    metrics:
                      - label: CPU
                        value: 27
                        unit: '%'
                      - label: MEM
                        value: 64
                        unit: '%'
              channel_targeted:
                value:
                  channels:
                    - ops
                  content_state:
                    title: Server Health
                    subtitle: prod-web-1
                    type: metrics
                    metrics:
                      - label: CPU
                        value: 27
                        unit: '%'
                      - label: MEM
                        value: 64
                        unit: '%'
              timer:
                value:
                  content_state:
                    title: Benchmark Run
                    subtitle: sampling
                    type: timer
                    duration_seconds: 300
                    color: cyan
              approval_secondary_actions:
                value:
                  content_state:
                    title: Approval Needed
                    message: Should I send the follow-up email to Brightlane?
                    type: alert
                    color: cyan
                  action:
                    title: Send
                    type: webhook
                    url: https://example.com/hooks/approvals/send
                    method: POST
                    body:
                      approval_id: appr_123
                  secondary_action:
                    title: Deny
                    type: webhook
                    url: https://example.com/hooks/approvals/deny
                    method: POST
                    body:
                      approval_id: appr_123
              tagged:
                summary: Organize notification history with tags
                value:
                  content_state:
                    title: Search Reindex
                    subtitle: catalog-v2
                    type: progress
                    percentage: 42
                  tags:
                    - user:382
                    - search-reindex
      responses:
        '200':
          description: Stream reconciled
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LiveActivityStreamPutResponse'
              examples:
                started:
                  value:
                    success: true
                    operation: started
                    stream_key: prod-web-1
                    activity_id: h8QmSyYFTuwOIF6Wh3YcZlzHLhUcr034
                    devices_notified: 2
                    timestamp: '2025-08-12T12:00:00.000Z'
                noop:
                  value:
                    success: true
                    operation: noop
                    stream_key: prod-web-1
                    activity_id: h8QmSyYFTuwOIF6Wh3YcZlzHLhUcr034
                    timestamp: '2025-08-12T12:05:00.000Z'
                paused:
                  value:
                    success: true
                    operation: paused
                    stream_key: prod-web-1
                    activity_id: null
                    timestamp: '2025-08-12T12:10:00.000Z'
                tagged:
                  value:
                    success: true
                    operation: started
                    stream_key: search-reindex
                    activity_id: h8QmSyYFTuwOIF6Wh3YcZlzHLhUcr034
                    devices_notified: 2
                    tags:
                      - user:382
                      - search-reindex
                    timestamp: '2025-08-12T12:00:00.000Z'
        '400':
          description: >-
            Bad request (invalid stream_key, payload, action, or channel
            targeting input)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BadRequestError'
              examples:
                invalid_stream_key:
                  value:
                    error: Invalid stream_key
                    message: >-
                      stream_key must contain only letters, numbers,
                      underscores, and hyphens
                invalid_target:
                  value:
                    error: Invalid channel targeting
                    message: channels must contain at least one channel
                invalid_tags:
                  value:
                    error: Invalid tags
                    code: invalid_tags
                    message: tags must contain at most 20 unique values
        '403':
          description: Forbidden (API key scope or channel assignment violation)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ForbiddenError'
              examples:
                channel_scope_violation:
                  value:
                    error: Invalid channel targeting
                    message: >-
                      This API key can only target assigned channels. Requested
                      channels include channels outside this key scope.
        '404':
          description: No recipients found for effective channel target
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NoRecipientsError'
              examples:
                no_devices:
                  value:
                    error: No recipients found
                    message: >-
                      No Live Activity devices matched the effective channel
                      target
                    effective_channel_slugs:
                      - ops
        '429':
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/RateLimitError'
                  - $ref: '#/components/schemas/LiveActivityLimitError'
              examples:
                rate_limited:
                  value:
                    error: Rate limit exceeded
                    message: Too many requests, please try again later.
                concurrent_live_activity_limit_reached:
                  value:
                    error: Live Activity limit reached
                    message: Only 4 concurrent Live Activities are allowed per account
                    limit: 4
                    active: 4
      x-codeSamples:
        - lang: javascript
          label: Node
          source: |-
            import ActivitySmith from "activitysmith";

            const activitysmith = new ActivitySmith({
              apiKey: process.env.ACTIVITYSMITH_API_KEY,
            });

            await activitysmith.liveActivities.stream("search-reindex", {
              content_state: {
                title: "Search Reindex",
                subtitle: "catalog-v2",
                type: "progress",
                percentage: 42,
              },
            });
        - lang: python
          label: Python
          source: >-
            import os

            from activitysmith import ActivitySmith


            activitysmith =
            ActivitySmith(api_key=os.environ["ACTIVITYSMITH_API_KEY"])


            activitysmith.live_activities.stream(
                "search-reindex",
                {
                    "content_state": {
                        "title": "Search Reindex",
                        "subtitle": "catalog-v2",
                        "type": "progress",
                        "percentage": 42,
                    },
                },
            )
        - lang: go
          label: Go
          source: "package main\n\nimport (\n\t\"log\"\n\n\tactivitysmithsdk \"github.com/ActivitySmithHQ/activitysmith-go\"\n)\n\nfunc main() {\n\tactivitysmith, err := activitysmithsdk.New(\"YOUR-API-KEY\")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t_, err = activitysmith.LiveActivities.Stream(\"search-reindex\", activitysmithsdk.LiveActivityStreamInput{\n\t\tTitle:      \"Search Reindex\",\n\t\tSubtitle:   \"catalog-v2\",\n\t\tType:       \"progress\",\n\t\tPercentage: 42,\n\t})\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n}"
        - lang: php
          label: PHP
          source: |-
            <?php

            use ActivitySmith\ActivitySmith;

            $activitysmith = new ActivitySmith($_ENV['ACTIVITYSMITH_API_KEY']);

            $activitysmith->liveActivities->stream('search-reindex', [
                'content_state' => [
                    'title' => 'Search Reindex',
                    'subtitle' => 'catalog-v2',
                    'type' => 'progress',
                    'percentage' => 42,
                ],
            ]);
        - lang: ruby
          label: Ruby
          source: >-
            require "activitysmith"


            activitysmith = ActivitySmith::Client.new(api_key:
            ENV.fetch("ACTIVITYSMITH_API_KEY"))


            activitysmith.live_activities.stream(
              "search-reindex",
              content_state: {
                title: "Search Reindex",
                subtitle: "catalog-v2",
                type: "progress",
                percentage: 42
              }
            )
        - lang: bash
          label: cURL
          source: >-
            curl -X PUT
            "https://activitysmith.com/api/live-activity/stream/search-reindex"
            \
              -H "Authorization: Bearer $ACTIVITYSMITH_API_KEY" \
              -H "Content-Type: application/json" \
              -d '{
                "content_state": {
                  "title": "Search Reindex",
                  "subtitle": "catalog-v2",
                  "type": "progress",
                  "percentage": 42
                }
              }'
components:
  schemas:
    LiveActivityStreamRequest:
      type: object
      description: >-
        Send the latest state for a managed Live Activity stream. channels is
        the streamlined form for stream targeting. target.channels is also
        accepted for compatibility. If both are provided, they must match.
      required:
        - content_state
      properties:
        content_state:
          $ref: '#/components/schemas/StreamContentState'
        action:
          $ref: '#/components/schemas/LiveActivityAction'
        secondary_action:
          $ref: '#/components/schemas/LiveActivityAction'
          description: >-
            Optional secondary action button. Supported for alert, progress, and
            segmented_progress Live Activities. Uses the same open_url,
            shortcuts://, and webhook shapes as action.
        alert:
          $ref: '#/components/schemas/AlertPayload'
        channels:
          type: array
          items:
            type: string
          minItems: 1
          description: Channel slugs. When omitted, API key scope determines recipients.
        target:
          $ref: '#/components/schemas/ChannelTarget'
        tags:
          $ref: '#/components/schemas/TagSlugs'
          description: >-
            Optional tags to organize and filter notification history. Omit this
            field on later updates to keep the current tags, send tags again to
            replace them, or send an empty array to clear them.
      additionalProperties: false
    LiveActivityStreamPutResponse:
      type: object
      description: Returned after a managed stream request is reconciled.
      properties:
        success:
          type: boolean
        operation:
          type: string
          enum:
            - started
            - updated
            - rotated
            - noop
            - paused
        stream_key:
          type: string
        activity_id:
          type:
            - string
            - 'null'
        previous_activity_id:
          type: string
        devices_notified:
          type: integer
        devices_queued:
          type: integer
        users_notified:
          type: integer
        effective_channel_slugs:
          type:
            - array
            - 'null'
          items:
            type: string
        tags:
          $ref: '#/components/schemas/TagSlugs'
        timestamp:
          type: string
          format: date-time
      required:
        - success
        - operation
        - stream_key
        - timestamp
      additionalProperties: false
    BadRequestError:
      type: object
      properties:
        error:
          type: string
        message:
          type: string
      required:
        - error
        - message
      additionalProperties: true
    ForbiddenError:
      type: object
      properties:
        error:
          type: string
        message:
          type: string
      required:
        - error
        - message
      additionalProperties: true
    NoRecipientsError:
      type: object
      properties:
        error:
          type: string
        message:
          type: string
        effective_channel_slugs:
          type:
            - array
            - 'null'
          items:
            type: string
      required:
        - error
        - message
      additionalProperties: true
    RateLimitError:
      type: object
      properties:
        error:
          type: string
        message:
          type: string
      required:
        - error
        - message
      additionalProperties: false
    LiveActivityLimitError:
      type: object
      properties:
        error:
          type: string
        message:
          type: string
        limit:
          type: integer
        active:
          type: integer
          description: Current number of active Live Activities.
      required:
        - error
        - message
        - limit
        - active
      additionalProperties: false
    StreamContentState:
      type: object
      description: >-
        Current state for a managed Live Activity stream. Include type on the
        first PUT, and whenever the stream may need to start a fresh activity.
        Supports segmented_progress, progress, metrics, stats, alert, and timer
        types. For timer, send duration_seconds to start or reset a bounded
        timer; omit duration_seconds on later updates to preserve the existing
        timer window.
      required:
        - title
      properties:
        title:
          type: string
        subtitle:
          type: string
        number_of_steps:
          type: integer
          minimum: 1
          description: Use for segmented_progress.
        current_step:
          type: integer
          minimum: 0
          description: >-
            Use for segmented_progress. Set 0 when no segment is complete yet.
            Must be less than or equal to number_of_steps when number_of_steps
            is provided.
        percentage:
          type: number
          minimum: 0
          maximum: 100
          description: >-
            Use for progress. Takes precedence over value/upper_limit if both
            are provided.
        value:
          type: number
          description: Current progress value. Use with upper_limit for progress.
        upper_limit:
          type: number
          exclusiveMinimum: 0
          description: Maximum progress value. Use with value for progress.
        duration_seconds:
          type: number
          exclusiveMinimum: 0
          description: >-
            Timer duration in seconds. For type=timer, send duration_seconds to
            start or reset the timer window; omit it on later stream updates to
            preserve the existing timer window.
        counts_down:
          type: boolean
          default: true
          description: >-
            Use with type=timer. When true or omitted, the timer counts down
            from duration_seconds. Set false for an elapsed timer; omit
            duration_seconds for an open-ended elapsed timer.
        is_running:
          type: boolean
          default: true
          description: >-
            Use with type=timer. Defaults to true. Set false to pause/freeze via
            API; set true on a paused timer to resume.
        type:
          type: string
          enum:
            - segmented_progress
            - progress
            - metrics
            - stats
            - alert
            - timer
          description: >-
            Required on the first PUT or whenever the stream cannot infer the
            current activity type.
        color:
          type: string
          enum:
            - lime
            - green
            - cyan
            - blue
            - purple
            - magenta
            - red
            - orange
            - yellow
            - gray
          description: >-
            Optional. Accent color for progress, segmented_progress, metrics,
            and timer Live Activities. For Alert Live Activities, this tints
            action and secondary_action buttons when included.
        step_color:
          type: string
          enum:
            - lime
            - green
            - cyan
            - blue
            - purple
            - magenta
            - red
            - orange
            - yellow
            - gray
          description: >-
            Optional. Overrides color for the current step. Only applies to
            segmented_progress.
        step_colors:
          type: array
          items:
            type: string
            enum:
              - lime
              - green
              - cyan
              - blue
              - purple
              - magenta
              - red
              - orange
              - yellow
              - gray
          description: >-
            Optional. Colors for completed steps. When used with
            segmented_progress, the array length should match current_step.
        metrics:
          type: array
          description: Use for metrics and stats activities.
          minItems: 1
          maxItems: 8
          items:
            $ref: '#/components/schemas/ActivityMetric'
        message:
          type: string
          minLength: 1
          description: Required for type=alert.
        icon:
          $ref: '#/components/schemas/LiveActivityAlertIcon'
          description: >-
            Optional SF Symbol icon. Supported by alert, progress,
            segmented_progress, metrics, stats, and timer.
        badge:
          $ref: '#/components/schemas/LiveActivityAlertBadge'
          description: >-
            Optional badge. Supported by alert, progress, and
            segmented_progress.
        auto_dismiss_seconds:
          type: integer
          minimum: 0
          description: Optional. Seconds before the ended Live Activity is dismissed.
        auto_dismiss_minutes:
          type: integer
          minimum: 0
          description: Optional. Minutes before the ended Live Activity is dismissed.
      dependentRequired:
        value:
          - upper_limit
        upper_limit:
          - value
      additionalProperties: false
    LiveActivityAction:
      type: object
      description: >-
        Optional action button shown in the Live Activity UI. Use action for the
        primary button, or secondary_action for a secondary button on alert,
        progress, and segmented_progress Live Activities.
      properties:
        title:
          type: string
          description: Button title displayed in the Live Activity UI.
        type:
          $ref: '#/components/schemas/LiveActivityActionType'
        url:
          type: string
          format: uri
          description: >-
            Action URL. For open_url, use an HTTP or HTTPS URL or a
            shortcuts://run-shortcut?name=... URL that runs a specific iPhone
            Shortcut. For webhook, use an HTTPS URL called by the ActivitySmith
            backend.
        method:
          $ref: '#/components/schemas/LiveActivityWebhookMethod'
          description: Webhook HTTP method. Used only when type=webhook.
        body:
          type: object
          additionalProperties: true
          description: Optional webhook payload body. Used only when type=webhook.
      required:
        - title
        - type
        - url
      allOf:
        - if:
            properties:
              type:
                const: open_url
            required:
              - type
          then:
            properties:
              url:
                pattern: ^(http|https|shortcuts)://
        - if:
            properties:
              type:
                const: webhook
            required:
              - type
          then:
            properties:
              url:
                pattern: ^https://
      additionalProperties: false
    AlertPayload:
      type: object
      properties:
        title:
          type: string
        body:
          type: string
      additionalProperties: false
    ChannelTarget:
      type: object
      properties:
        channels:
          type: array
          items:
            type: string
          minItems: 1
          description: Channel slugs. When omitted, API key scope determines recipients.
      required:
        - channels
      additionalProperties: false
    TagSlugs:
      type: array
      description: Optional tags to organize and filter notification history.
      items:
        type: string
        minLength: 1
        maxLength: 64
        pattern: ^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$
      examples:
        - - user:382
          - environment:production
    ActivityMetric:
      type: object
      required:
        - label
        - value
      properties:
        label:
          type: string
          minLength: 1
        value:
          oneOf:
            - type: number
              minimum: 0
            - type: string
              minLength: 1
              maxLength: 64
        unit:
          type: string
        color:
          type: string
          enum:
            - lime
            - green
            - cyan
            - blue
            - purple
            - magenta
            - red
            - orange
            - yellow
            - gray
          description: Optional per-metric accent color for metrics and stats activities.
      additionalProperties: false
    LiveActivityAlertIcon:
      type: object
      description: Optional SF Symbol icon for Live Activities.
      required:
        - symbol
      properties:
        symbol:
          type: string
          minLength: 1
          description: Apple SF Symbol name.
        color:
          $ref: '#/components/schemas/LiveActivityColor'
          description: Optional icon color.
      additionalProperties: false
    LiveActivityAlertBadge:
      type: object
      description: Optional badge for Live Activities.
      required:
        - title
      properties:
        title:
          type: string
          minLength: 1
        color:
          $ref: '#/components/schemas/LiveActivityColor'
          description: Optional badge color.
      additionalProperties: false
    LiveActivityActionType:
      type: string
      enum:
        - open_url
        - webhook
    LiveActivityWebhookMethod:
      type: string
      enum:
        - GET
        - POST
      default: POST
    LiveActivityColor:
      type: string
      enum:
        - lime
        - green
        - cyan
        - blue
        - purple
        - magenta
        - red
        - orange
        - yellow
        - gray
  securitySchemes:
    apiKeyAuth:
      type: http
      scheme: bearer
      bearerFormat: API Key
      description: >-
        Required. Include `Authorization: Bearer ask_123456789` in every
        request. Replace `ask_123456789` with your API key.

````