A stream request registers a new session for a livestream event.
For more information, see [Make a stream request](https://developers.google.com/ad-manager/dynamic-ad-insertion/api/pod-serving/live/client#make_a_stream_request)

This page covers using HMAC token to authenticate the stream requests.

## Before you begin

- Complete the [prerequisites](https://developers.google.com/ad-manager/dynamic-ad-insertion/api/pod-serving/live/pod-request-overview#prerequisites).
- Ensure the **Stream create authentication keys** are enabled in your livestream event in your [Google Ad Manager Account](https://admanager.google.com).

## Generate an HMAC token

To generate a token, do the following:

1. Collect the path and query parameters required for your stream session request. For a full list, see [Method: stream](https://developers.google.com/ad-manager/dynamic-ad-insertion/api/pod-serving/reference/live#method_stream).
2. Combine your parameter key and value strings. You must sort the parameters alphabetically
   and separate the parameters with the tilde `~` character, for example:

       custom_asset_key=CUSTOM_ASSET_KEY~exp=EXPIRATION~network_code=NETWORK_CODE

   Replace the following:
   - `CUSTOM_ASSET_KEY`: **Required.** The livestream event's custom asset key.
   - `EXPIRATION`: **Required.** The expiration timestamp for the token in Unix epoch time.
   - `NETWORK_CODE`: **Required.** The network code of your Google Ad Manager account.
3. Calculate a SHA-256 hash of the token string using your **DAI authentication key**.

4. Format the hash output in hexadecimal.

5. To sign the token string, append the signature at the end of the parameters gathered earlier:

       custom_asset_key=...~hmac=HMAC_SIGNATURE

   Replace `HMAC_SIGNATURE` with the signature you generated by
   hashing the token string using your DAI authentication key.
6. To pass the signed token string safely, apply URL-encoding to the signed
   token string.

The following example signs and encodes a token string that expires within 60
seconds:

    # Add 60 seconds to the current time
    future_epoch=$((EPOCHSECONDS + 60))
    echo "Current: $EPOCHSECONDS"
    echo "Future: $future_epoch"
    # Current: 1774478306
    # Future: 1774478366

    # Sample DAI stream authentication key
    key="DE0E9..."

    # Sort parameters in the token string
    token="custom_asset_key=hls-pod-serving-redirect-auth-stream-pod~exp=1774478366~network_code=21775744923"

    # Generate the token's signature.
    echo -n $token | openssl dgst -sha256 -mac HMAC -macopt key:$key
    # SHA2-256(stdin)= 17cdf7079b735320dbc66e4c9d677ae0380fb0ef3cf9ce90fdd55d0667574365

    # Sign the token: custom_asset_key=hls-pod-serving-redirect-auth-stream-pod~exp=1774478366~network_code=21775744923~hmac=17cdf7079b735320dbc66e4c9d677ae0380fb0ef3cf9ce90fdd55d0667574365

    # Encode the token: custom_asset_key%3Dhls-pod-serving-redirect-auth-stream-podexp%3D1774478366network_code%3D21775744923~hmac%3D17cdf7079b735320dbc66e4c9d677ae0380fb0ef3cf9ce90fdd55d0667574365

## Use the HMAC token to request a livestream session

To authenticate your stream create request with an HMAC token, do one of the
following:

### HLS

### `Authorization` request header

    curl "https://dai.google.com/ssai/pods/api/v1/network/21775744923/custom_asset/hls-pod-serving-redirect-auth-stream-pod/stream" \
    -X POST \
    -H "Content-Type: application/x-www-form-urlencoded" \
    -H "Authorization: DCLKDAI token=custom_asset_key%3Dhls-pod-serving-redirect-auth-stream-podexp%3D1774478366network_code%3D21775744923~hmac%3D17cdf7079b735320dbc66e4c9d677ae0380fb0ef3cf9ce90fdd55d0667574365"

### Query string parameter

    curl "https://dai.google.com/ssai/pods/api/v1/network/21775744923/custom_asset/hls-pod-serving-redirect-auth-stream-pod/stream?auth-token=custom_asset_key%3Dhls-pod-serving-redirect-auth-stream-podexp%3D1774478366network_code%3D21775744923~hmac%3D17cdf7079b735320dbc66e4c9d677ae0380fb0ef3cf9ce90fdd55d0667574365" \
    -X POST \
    -H "Content-Type: application/x-www-form-urlencoded"

### Form data field

    curl "https://dai.google.com/ssai/pods/api/v1/network/21775744923/custom_asset/hls-pod-serving-redirect-auth-stream-pod/stream" \
    -X POST \
    -H "Content-Type: application/x-www-form-urlencoded" \
    -d "auth-token=custom_asset_key%3Dhls-pod-serving-redirect-auth-stream-podexp%3D1774478366network_code%3D21775744923~hmac%3D17cdf7079b735320dbc66e4c9d677ae0380fb0ef3cf9ce90fdd55d0667574365"

If successful, you see the following JSON response:

    {
    "stream_id":"6299a01b-450d-4879-a5c8-fe3cf2188aee:CBF2",
    "media_verification_url":"https://dai.google.com/view/p/service/linear/stream/6299a01b-450d-4879-a5c8-fe3cf2188aee:CBF2/loc/CBF2/network/21775744923/event/C5BT3czhT2Sc7OIbM8ibqA/media/","metadata_url":"https://dai.google.com/linear/pods/hls/pa/event/C5BT3czhT2Sc7OIbM8ibqA/stream/6299a01b-450d-4879-a5c8-fe3cf2188aee:CBF2/metadata",
    "session_update_url":"https://dai.google.com/linear/v1/pa/event/C5BT3czhT2Sc7OIbM8ibqA/stream/6299a01b-450d-4879-a5c8-fe3cf2188aee:CBF2/session",
    "polling_frequency":10
    }

To understand the response structure and status codes, refer to [Method: stream](https://developers.google.com/ad-manager/dynamic-ad-insertion/api/pod-serving/reference/live#method_stream).

If authentication fails, you see the following error:

    <!DOCTYPE html>
    <html lang=en>
    <meta charset=utf-8>
    <meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">
    <title>Error 401 (Unauthorized)!!1</title>
    ...
    <a href=//www.google.com/><span id=logo aria-label=Google></span></a>
    <p><b>401.</b> <ins>That's an error.</ins>
    <p><ins>That's all we know.</ins>s

### DASH

### `Authorization` request header

    curl "https://dai.google.com/ssai/pods/api/v1/network/21775744923/custom_asset/dash-pod-serving-redirect-auth-stream-pod/stream"\
    -X POST \
    -H "Content-Type: application/x-www-form-urlencoded" \
    -H "Authorization: DCLKDAI token=custom_asset_key%3Ddash-pod-serving-redirect-auth-stream-podexp%3D1772817105network_code%3D21775744923~hmac%3Dc7e10f51f544610cdda28fdee903472839bf1154701ae371c0196d8f63c8bdda"

### Query string parameter

    curl "https://dai.google.com/ssai/pods/api/v1/network/21775744923/custom_asset/dash-pod-serving-redirect-auth-stream-pod/stream?auth-token=custom_asset_key%3Ddash-pod-serving-redirect-auth-stream-podexp%3D1772817105network_code%3D21775744923~hmac%3Dc7e10f51f544610cdda28fdee903472839bf1154701ae371c0196d8f63c8bdda" \
    -X POST \
    -H "Content-Type: application/x-www-form-urlencoded"

### Form data field

    curl "https://dai.google.com/ssai/pods/api/v1/network/21775744923/custom_asset/dash-pod-serving-redirect-auth-stream-pod/stream" \
    -X POST \
    -H "Content-Type: application/x-www-form-urlencoded" \
    -d "auth-token=custom_asset_key%3Ddash-pod-serving-redirect-auth-stream-podexp%3D1772817105network_code%3D21775744923~hmac%3Dc7e10f51f544610cdda28fdee903472839bf1154701ae371c0196d8f63c8bdda"

If successful, you see the following JSON response:

    {
    "stream_id": "e66568dc-cb5c-4859-b645-e12d9b5b821b:ATL",
    "media_verification_url": "https://dai.google.com/view/p/service/linear/stream/e66568dc-cb5c-4859-b645-e12d9b5b821b:ATL/loc/ATL/network/21775744923/event/YMTFNxBxTR66kFv-krZHcQ/media/",
    "metadata_url": "https://dai.google.com/linear/pods/dash/pa/event/YMTFNxBxTR66kFv-krZHcQ/stream/e66568dc-cb5c-4859-b645-e12d9b5b821b:ATL/metadata",
    "session_update_url": "https://dai.google.com/linear/v1/pa/event/YMTFNxBxTR66kFv-krZHcQ/stream/e66568dc-cb5c-4859-b645-e12d9b5b821b:ATL/session",
    "polling_frequency": 10,
    "pod_manifest_url": "https://dai.google.com/linear/pods/v1/dash/event/YMTFNxBxTR66kFv-krZHcQ/stream/e66568dc-cb5c-4859-b645-e12d9b5b821b:ATL/pod/$pod-id$/manifest.mpd",
    "manifest_format": "dash"
    }

To understand the response structure and status codes, refer to [Method: stream](https://developers.google.com/ad-manager/dynamic-ad-insertion/api/pod-serving/reference/live#method_stream).

If authentication fails, you see the following error:

    <!DOCTYPE html>
    <html lang=en>
    <meta charset=utf-8>
    <meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">
    <title>Error 401 (Unauthorized)!!1</title>
    ...
    <a href=//www.google.com/><span id=logo aria-label=Google></span></a>
    <p><b>401.</b> <ins>That's an error.</ins>
    <p><ins>That's all we know.</ins>