---
title: "Stream callback and longpoll payload reference"
description: "The exact JSON your callback receiver and longpoll consumer get from AudD streams: result bodies, notification bodies, the getStreams list, and the longpoll keepalive."
slug: "/resources/reference/streams-callback-shape"
section: "reference"
keywords: [audd, streams, callback, longpoll, notification_code, radio_id]
---

# Stream callback and longpoll payload reference

This page documents what arrives at your callback receiver (or longpoll
consumer) when AudD recognizes music on a registered stream. The payloads
below are captured API responses. There are two callback shapes —
a result and a notification — and exactly one of them is present per
callback. Longpoll delivers the same result bodies, plus a keepalive shape
when nothing has happened.

## Result callback body

When AudD recognizes a song on one of your streams, it POSTs a JSON body to
your configured callback URL. By default this is sent after the song
finishes playing (and carries the total played time in `play_length`); with
`callbacks="before"` it is sent at song start and `play_length` is not
meaningful.

```json
{
  "status": "success",
  "result": {
    "radio_id": 7,
    "timestamp": "2020-04-13 10:31:43",
    "play_length": 111,
    "results": [
      {
        "artist": "Alan Walker, A$AP Rocky",
        "title": "Live Fast (PUBGM)",
        "album": "Live Fast (PUBGM)",
        "release_date": "2019-07-25",
        "label": "MER Recordings",
        "score": 100,
        "song_link": "https://lis.tn/LiveFastPUBGM"
      }
    ]
  }
}
```

### Top-level fields

| Field | Type | Description |
|---|---|---|
| `status` | string | `"success"` on a result callback. |
| `result` | object | The recognition result for one stream event. |

### `result` object

| Field | Type | Description |
|---|---|---|
| `radio_id` | integer | The integer you chose when you added the stream. Identifies which stream this result came from. |
| `timestamp` | string | When the recognition occurred, formatted `YYYY-MM-DD HH:MM:SS`. |
| `play_length` | integer | Total time, in seconds, the song was streamed. Present on default (song-end) callbacks; not meaningful with `callbacks="before"`. |
| `results` | array | The recognized song(s). See below. A result body can contain more than one candidate song. |

### `results` array entries

Each entry describes one recognized track. A single callback's `results`
array can hold multiple candidate songs, so iterate it rather than reading
only the first element.

| Field | Type | Description |
|---|---|---|
| `artist` | string \| null | Track artist(s). May be null for a custom-catalog match. |
| `title` | string \| null | Track title. May be null for a custom-catalog match. |
| `album` | string | Album the recording appears on. |
| `release_date` | string | Release date, `YYYY-MM-DD`. |
| `label` | string | Publishing label. |
| `score` | integer | Match confidence, 0–100. Higher is a stronger match. |
| `song_link` | string | Universal link to the song's page on `lis.tn`. |

## Notification callback body

When something goes wrong with a stream — or to confirm a stream is healthy
— AudD POSTs a notification instead of a result. A notification tells you to
fix or re-point a stream; it never contains a recognized song.

```json
{
  "status": "-",
  "notification": {
    "radio_id": 3,
    "stream_running": false,
    "notification_code": 650,
    "notification_message": "Recognition failed: can't connect to the audiostream"
  },
  "time": 1587939136
}
```

### Top-level fields

| Field | Type | Description |
|---|---|---|
| `status` | string | `"-"` on a notification callback (not `"success"`). |
| `notification` | object | The notification detail. See below. |
| `time` | integer | Unix epoch seconds at which the notification was sent. |

### `notification` object

| Field | Type | Description |
|---|---|---|
| `radio_id` | integer | The stream this notification is about. |
| `stream_running` | boolean | Whether the stream is currently being recognized. `false` when AudD has stopped because of the condition in `notification_code`. |
| `notification_code` | integer | The condition code. See the table below. |
| `notification_message` | string | Human-readable description of the condition. |

### `notification_code` values

| Code | Meaning |
|---|---|
| `0` | Everything is fine. |
| `650` | Can't connect to the stream. |
| `651` | No music from the stream — white noise only. |

## Exactly one of result or notification per callback

Each callback POST carries either a `result` object or a `notification`
object, never both. Branch on which key is present (or on `status`):

- `status` is `"success"` and a `result` key is present → a recognition
  result. Read `result.results`.
- `status` is `"-"` and a `notification` key is present → a stream
  notification. Read `notification.notification_code`.

Treat any unexpected `status` value as a server-side error rather than a
stream event.

## Longpoll response

Longpoll is an alternative to running a callback server: `GET
https://api.audd.io/longpoll/` holds the request open until an event is
ready or the timeout elapses. A working callback URL must still be
configured for the account — longpoll may never return events for an account
with no callback URL set, even while songs are being recognized.

Request parameters:

| Parameter | Type | Description |
|---|---|---|
| `category` | string | The subscription key. Use the `longpoll_category` value from a `getStreams` row. |
| `timeout` | integer | Seconds to hold the request open waiting for an event. |
| `since_time` | integer | The `timestamp` from your previous longpoll response, used as the cursor for the next request. |

Example request URL:

```text
https://api.audd.io/longpoll/?category=92b1cc7f0&timeout=50&since_time=1652123144400
```

When an event is available, the response carries the same result body shape
documented in [Result callback body](#result-callback-body). When you
receive a response containing a `timestamp` field, use that value as the
`since_time` on your next request.

### No-events keepalive

When the timeout elapses with nothing to report, longpoll returns a
keepalive rather than an event. This is normal; reissue the request.

```json
{
  "timeout": "no events before timeout",
  "timestamp": 1777901270049
}
```

| Field | Type | Description |
|---|---|---|
| `timeout` | string | `"no events before timeout"` — the keepalive marker. |
| `timestamp` | integer | The cursor to pass as `since_time` on your next longpoll request. |

## getStreams list

`POST https://api.audd.io/getStreams/` returns every stream registered on
the account. The result is an array of stream rows. When no streams are
registered, the array is empty:

```json
{
  "status": "success",
  "result": []
}
```

A populated row describes one registered stream:

| Field | Type | Description |
|---|---|---|
| `radio_id` | integer | The integer you assigned when adding the stream. |
| `url` | string | The stream URL — a direct stream URL or a shortcut such as `youtube:5qap5aO4i9A` or `twitch:monstercat`. |
| `stream_running` | boolean | Whether the stream is currently being recognized. |
| `longpoll_category` | string | The subscription key to pass as the longpoll `category`. Safe to share with clients without exposing your API token. |

## SDK note

The SDKs parse a raw callback body into a typed value that is either a match
result or a notification, so your handler branches on a type rather than
inspecting `status` by hand. Look for the callback-parsing method on the
streams surface — for example `parseCallback` / `handleCallback` — which
accepts the raw POST body and returns the typed result-or-notification. The
longpoll consumers (such as the Go library's longpoll client) hand you the
same typed result objects and manage the `since_time` cursor for you.

## Notes

- The `score` field on a result entry is a 0–100 confidence value; higher is
  a stronger match.
- A custom-catalog match returns the track ID you uploaded; `artist` and
  `title` may be null on those entries.
- ISRCs, UPCs, and provider metadata (Apple Music, Spotify, MusicBrainz) are
  not in the default stream callback. Contact api@audd.io to enable
  additional metadata on your callbacks.
- If your server doesn't return `200 OK`, AudD queues the callbacks and
  re-sends the backlog gradually once your server is reachable again.

---

**Related**

- [Callbacks vs. longpoll: choosing a delivery method](/resources/concepts/callback-vs-longpoll)
- [Build a now-playing widget](/resources/recipes/now-playing-widget)
- [Monitor radio airplay](/resources/recipes/radio-airplay-monitor)
- [Glossary](/resources/reference/glossary)
- [API reference](https://docs.audd.io)