> ## 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.

# Start Live Activity

> Legacy manual lifecycle endpoint. For new integrations, use PUT /live-activity/stream/{stream_key} so ActivitySmith can manage start, update, rotation, and end state for you. This endpoint remains supported for existing integrations and advanced lifecycle control. Starts a Live Activity on devices matched by API key scope and optional target channels. Supports segmented_progress, progress, metrics, stats, alert, and timer activity types. For segmented_progress activities, number_of_steps can be changed later during update or end calls if the workflow changes. Use secondary_action for a second button on alert, progress, and segmented_progress Live Activities. Optional tags to organize and filter notification history.

Use this manual lifecycle endpoint only when you need direct control over a
specific Live Activity instance. For new integrations, prefer
[`PUT /live-activity/stream/{stream_key}`](/docs/api-reference/endpoint/live-activity-stream).

This endpoint creates a new Live Activity and returns an `activity_id`. You will
use that same ID for later update and end calls.

* `metrics`: send `title`, `type`, and a non-empty `metrics` array.
* `stats`: send `title`, `type`, and a non-empty `metrics` array for up to 8 labeled values.
* `segmented_progress`: send `title`, `type`, `number_of_steps`, and `current_step`.
* `progress`: send `title`, `type`, and either `percentage` or `value` with `upper_limit`.
* `timer`: send `title`, `type`, and `duration_seconds` for a countdown. To start at 00:00 and count up, set `counts_down` to `false` and leave out `duration_seconds`.
* `action` is optional if you want the Live Activity to show one button that opens a URL or triggers a webhook.
* `target.channels` is optional if you want to scope delivery to specific channel slugs.

For `segmented_progress`, `number_of_steps` is not fixed for the full lifecycle.
You can change it later in update or end calls if the workflow adds or removes
steps.


## OpenAPI

````yaml POST /live-activity/start
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/start:
    post:
      tags:
        - LiveActivities
      summary: Start a Live Activity (legacy manual lifecycle)
      description: >-
        Legacy manual lifecycle endpoint. For new integrations, use PUT
        /live-activity/stream/{stream_key} so ActivitySmith can manage start,
        update, rotation, and end state for you. This endpoint remains supported
        for existing integrations and advanced lifecycle control. Starts a Live
        Activity on devices matched by API key scope and optional target
        channels. Supports segmented_progress, progress, metrics, stats, alert,
        and timer activity types. For segmented_progress activities,
        number_of_steps can be changed later during update or end calls if the
        workflow changes. Use secondary_action for a second button on alert,
        progress, and segmented_progress Live Activities. Optional tags to
        organize and filter notification history.
      operationId: startLiveActivity
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/LiveActivityStartRequest'
            examples:
              segmented_progress:
                value:
                  content_state:
                    title: Nightly database backup
                    subtitle: create snapshot
                    number_of_steps: 3
                    current_step: 1
                    type: segmented_progress
                    color: yellow
              progress:
                value:
                  content_state:
                    title: EV Charging
                    subtitle: Added 30 mi range
                    percentage: 15
                    type: progress
                    color: lime
              metrics:
                value:
                  content_state:
                    title: Server Health
                    subtitle: prod-web-1
                    type: metrics
                    metrics:
                      - label: CPU
                        value: 21
                        unit: '%'
                      - label: MEM
                        value: 64
                        unit: '%'
              open_url_action:
                value:
                  content_state:
                    title: Deploying payments-api
                    subtitle: Running database migrations
                    number_of_steps: 5
                    current_step: 3
                    type: segmented_progress
                  action:
                    title: Open Workflow
                    type: open_url
                    url: >-
                      https://github.com/acme/payments-api/actions/runs/1234567890
              segmented_progress_channel_targeted:
                value:
                  content_state:
                    title: Nightly database backup
                    subtitle: create snapshot
                    number_of_steps: 3
                    current_step: 1
                    type: segmented_progress
                    color: yellow
                  target:
                    channels:
                      - devs
                      - ops
              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: Nightly database backup
                    subtitle: create snapshot
                    number_of_steps: 3
                    current_step: 1
                    type: segmented_progress
                    color: yellow
                  tags:
                    - user:382
                    - database-backup
      responses:
        '200':
          description: Live Activity started
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LiveActivityStartResponse'
              examples:
                segmented_progress:
                  value:
                    success: true
                    activity_id: pLAr-Hnq9ZFW4sxlk43Lhbuok4GLh7UW
                    devices_notified: 2
                    users_notified: 1
                    timestamp: '2026-01-28T09:57:22.929Z'
                segmented_progress_channel_targeted:
                  value:
                    success: true
                    activity_id: pLAr-Hnq9ZFW4sxlk43Lhbuok4GLh7UW
                    devices_notified: 2
                    users_notified: 1
                    effective_channel_slugs:
                      - devs
                      - ops
                    timestamp: '2026-01-28T09:57:22.929Z'
                tagged:
                  value:
                    success: true
                    activity_id: pLAr-Hnq9ZFW4sxlk43Lhbuok4GLh7UW
                    devices_notified: 2
                    users_notified: 1
                    tags:
                      - user:382
                      - database-backup
                    timestamp: '2026-01-28T09:57:22.929Z'
        '400':
          description: Bad request (invalid payload or channel targeting input)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BadRequestError'
              examples:
                invalid_target:
                  value:
                    error: Invalid channel targeting
                    message: target.channels must be an array of channel slugs
                invalid_tags:
                  value:
                    error: Invalid tags
                    code: invalid_tags
                    message: >-
                      tags must use 1-64 lowercase letters, numbers, dashes,
                      underscores, periods, or colons
        '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:
                      - marketing
        '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,
            });

            const start = await activitysmith.liveActivities.start({
              content_state: {
                title: "Nightly database backup",
                subtitle: "create snapshot",
                number_of_steps: 3,
                current_step: 1,
                type: "segmented_progress",
                color: "yellow",
              },
            });

            const activityId = start.activity_id;
        - lang: python
          label: Python
          source: >-
            import os

            from activitysmith import ActivitySmith


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


            start = activitysmith.live_activities.start({
                "content_state": {
                    "title": "Nightly database backup",
                    "subtitle": "create snapshot",
                    "number_of_steps": 3,
                    "current_step": 1,
                    "type": "segmented_progress",
                    "color": "yellow",
                },
            })


            activity_id = start.activity_id
        - 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\tstart, err := activitysmith.LiveActivities.Start(activitysmithsdk.LiveActivityStartInput{\n\t\tTitle:         \"Nightly database backup\",\n\t\tSubtitle:      \"create snapshot\",\n\t\tNumberOfSteps: 3,\n\t\tCurrentStep:   1,\n\t\tType:          \"segmented_progress\",\n\t\tColor:         \"yellow\",\n\t})\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tactivityID := start.GetActivityId()\n\t_ = activityID\n}"
        - lang: php
          label: PHP
          source: |-
            <?php

            use ActivitySmith\ActivitySmith;

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

            $start = $activitysmith->liveActivities->start([
                'content_state' => [
                    'title' => 'Nightly database backup',
                    'subtitle' => 'create snapshot',
                    'number_of_steps' => 3,
                    'current_step' => 1,
                    'type' => 'segmented_progress',
                    'color' => 'yellow',
                ],
            ]);

            $activityId = $start->getActivityId();
        - lang: ruby
          label: Ruby
          source: >-
            require "activitysmith"


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


            start = activitysmith.live_activities.start(
              content_state: {
                title: "Nightly database backup",
                subtitle: "create snapshot",
                number_of_steps: 3,
                current_step: 1,
                type: "segmented_progress",
                color: "yellow"
              }
            )


            activity_id = start.activity_id
        - lang: bash
          label: cURL
          source: |-
            curl -X POST "https://activitysmith.com/api/live-activity/start" \
              -H "Authorization: Bearer $ACTIVITYSMITH_API_KEY" \
              -H "Content-Type: application/json" \
              -d '{
                "content_state": {
                  "title": "Nightly database backup",
                  "subtitle": "create snapshot",
                  "number_of_steps": 3,
                  "current_step": 1,
                  "type": "segmented_progress",
                  "color": "yellow"
                }
              }'
components:
  schemas:
    LiveActivityStartRequest:
      type: object
      description: >-
        Start a new Live Activity. The response includes activity_id for later
        update and end calls.
      required:
        - content_state
      properties:
        content_state:
          $ref: '#/components/schemas/ContentStateStart'
        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'
        target:
          $ref: '#/components/schemas/ChannelTarget'
        tags:
          $ref: '#/components/schemas/TagSlugs'
      additionalProperties: false
    LiveActivityStartResponse:
      type: object
      description: >-
        Returned after a Live Activity starts. Save activity_id and use it for
        all later updates and for the final end call.
      properties:
        success:
          type: boolean
        devices_notified:
          type: integer
        users_notified:
          type: integer
        activity_id:
          type: string
        effective_channel_slugs:
          type:
            - array
            - 'null'
          items:
            type: string
        tags:
          $ref: '#/components/schemas/TagSlugs'
        timestamp:
          type: string
          format: date-time
      required:
        - success
        - activity_id
        - 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
    ContentStateStart:
      type: object
      description: >-
        Start payload requires title and type. For segmented_progress include
        number_of_steps and current_step. For progress include percentage or
        value with upper_limit. For metrics and stats include a non-empty
        metrics array. For alert include message. For timer include
        duration_seconds for countdowns, or set counts_down false without
        duration_seconds for an open-ended elapsed timer. Optional icon is
        supported by all Live Activity types. Optional badge is supported by
        alert, progress, and segmented_progress. For segmented_progress,
        number_of_steps is not locked and can be changed in later update or end
        calls.
      required:
        - title
        - type
      properties:
        title:
          type: string
        subtitle:
          type: string
        number_of_steps:
          type: integer
          minimum: 1
          description: >-
            Total number of steps. Use for type=segmented_progress. This value
            can be increased or decreased later when updating or ending the same
            activity.
        current_step:
          type: integer
          minimum: 0
          description: >-
            Current completed step count. Use for type=segmented_progress. Set 0
            when the activity has started but no segment is complete yet. Must
            be less than or equal to number_of_steps.
        percentage:
          type: number
          minimum: 0
          maximum: 100
          description: >-
            Progress percentage (0–100). Use for type=progress. Takes precedence
            over value/upper_limit if both are provided.
        value:
          type: number
          description: Current progress value. Use with upper_limit for type=progress.
        upper_limit:
          type: number
          exclusiveMinimum: 0
          description: Maximum progress value. Use with value for type=progress.
        duration_seconds:
          type: number
          exclusiveMinimum: 0
          description: >-
            Timer duration in seconds. For type=timer countdowns, required on
            start when counts_down is true or omitted.
        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.
        metrics:
          type: array
          description: Use for type=metrics or type=stats.
          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.
        type:
          type: string
          enum:
            - segmented_progress
            - progress
            - metrics
            - stats
            - alert
            - timer
        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
            type=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.
      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.

````