# Stream Status API

Use the **Stream Status** endpoint to ask DailyPlay whether a stream should be shown right now —
before you mount an iframe, floating Play button, or custom overlay on your site.

This is a **public GET** (no API key). It is designed for site and app owners who want to:

- Show a stream overlay **only while the stream is active**
- Hide Play buttons when a campaign has not started or has ended
- Avoid loading a full stream player when there are no published games

:::tip[Lightweight by design]
Unlike the full stream player payload, this endpoint does **not** return game configs or prizes and
does **not** record analytics. Prefer it for availability gating; load the stream URL only when
`available` is `true`.
:::

## Endpoint

```
GET https://app.dailyplay.ai/api/stream-status?org_slug=<org-slug>&stream_slug=<stream-slug>
```

| Parameter     | Required | Description                                      |
| ------------- | -------- | ------------------------------------------------ |
| `org_slug`    | Yes      | Organization slug (from the stream share URL)    |
| `stream_slug` | Yes      | Stream slug (from the stream share URL)          |

**Auth:** none  
**CORS:** `Access-Control-Allow-Origin: *` (safe to call from the browser)  
**Cache:** `public, s-maxage=30, stale-while-revalidate=60` — hosts can poll about every 30s

### Example

```
https://app.dailyplay.ai/api/stream-status?org_slug=your-org&stream_slug=summer-campaign
```

## Response

HTTP `200` with `success: true` means the request was handled. Use **`data.available`** to decide
whether to show the stream UI.

### Available

```json
{
  "success": true,
  "data": {
    "available": true,
    "reason": null,
    "total_games": 4,
    "starts_at": null,
    "ends_at": null,
    "timezone": "UTC",
    "server_time": "2026-10-15T07:23:43.597Z",
    "stream": {
      "slug": "summer-campaign",
      "status": "active"
    },
    "organization": {
      "slug": "your-org"
    }
  }
}
```

### Unavailable

```json
{
  "success": true,
  "data": {
    "available": false,
    "reason": "stream_inactive",
    "total_games": 0,
    "starts_at": null,
    "ends_at": null,
    "timezone": "UTC",
    "server_time": "2026-10-15T07:23:43.597Z",
    "stream": {
      "slug": "summer-campaign",
      "status": "draft"
    },
    "organization": {
      "slug": "your-org"
    }
  }
}
```

### Response fields

| Field                     | Type           | Description |
| ------------------------- | -------------- | ----------- |
| `available`               | boolean        | `true` when visitors can play the stream |
| `reason`                  | string \| null | Why the stream is unavailable (`null` when available) |
| `total_games`             | number         | Count of **published** games on the stream (`0` when not public) |
| `starts_at` / `ends_at`   | string \| null | Schedule bounds as ISO UTC (from the stream timezone) |
| `timezone`                | string         | Stream timezone used for schedule checks |
| `server_time`             | string         | Server clock (ISO UTC) for the decision |
| `stream.slug` / `status`  | string         | Stream identity and status |
| `organization.slug`       | string         | Organization slug |

### Unavailable reasons

| `reason`             | Meaning |
| -------------------- | ------- |
| `not_public`         | Stream is not public (details are not leaked) |
| `stream_inactive`    | Stream status is not `active` (e.g. draft / archived) |
| `stream_not_started` | Current time is before `starts_at` |
| `stream_ended`       | Current time is after `ends_at` |
| `no_games`           | Stream is active/public but has no published games |

### Error responses

| Code | When |
| ---- | ---- |
| `400` | Missing `org_slug` or `stream_slug` |
| `404` | Organization or stream not found |
| `405` | Method other than `GET` / `OPTIONS` |
| `500` | Server error |

```json
{
  "success": false,
  "error": "Stream not found"
}
```

---

## When is a stream “available”?

All of the following must be true:

1. The stream exists under the given org slug
2. The stream is **public**
3. Stream status is **`active`**
4. If a start time is set, it has already begun (in the stream timezone)
5. If an end time is set, it has not ended yet
6. At least one **published** game is attached to the stream

---

## Typical integration: gate an overlay

Site owners often keep a floating Play button or modal out of the DOM until the stream is live.

```html
<script>
  async function shouldShowStreamOverlay(orgSlug, streamSlug) {
    const url =
      "https://app.dailyplay.ai/api/stream-status" +
      `?org_slug=${encodeURIComponent(orgSlug)}` +
      `&stream_slug=${encodeURIComponent(streamSlug)}`;

    const res = await fetch(url);
    const json = await res.json();
    return Boolean(json?.success && json?.data?.available);
  }

  async function maybeMountOverlay() {
    const available = await shouldShowStreamOverlay(
      "your-org",
      "summer-campaign"
    );

    if (!available) {
      // Do not inject iframe / floating button
      return;
    }

    // Mount your overlay or iframe:
    // https://app.dailyplay.ai/stream/your-org/summer-campaign/widget?origin=...
  }

  maybeMountOverlay();
  // Optional: re-check every ~30s to match CDN cache
  setInterval(maybeMountOverlay, 30000);
</script>
```

### Recommended stream URLs after a positive check

| Purpose | URL |
| ------- | --- |
| Full stream page | `https://app.dailyplay.ai/stream/<org-slug>/<stream-slug>` |
| Widget / floating overlay | `https://app.dailyplay.ai/stream/<org-slug>/<stream-slug>/widget?origin=<encoded-site-origin>` |

See [Floating Play Button](/sharing/floating-play-button/) for the hosted widget snippet. DailyPlay’s
widget script also gates stream launchers so they only appear when the stream can be played.

:::note[Session tokens]
If the stream requires an API session token, availability can still be `true` while play requires a
token. Mint tokens with the [Session Tokens](/api/session-tokens/) API (Business+).
:::

---

## Next Steps

- [Embed games and streams](/sharing/embed/)
- [Floating Play button](/sharing/floating-play-button/)
- [Session Tokens](/api/session-tokens/) for controlled access
- [API Reference](/api/reference/) for the full endpoint list