# Authenticate ad pod timing metadata (ATM) requests

For server-side ad stitching, your manifest manipulator makes ad pod timing metadata requests to Google DAI. For more information, see [Build ad segment URLs](https://developers.google.com/ad-manager/dynamic-ad-insertion/api/pod-serving/live/manipulator#build_ad_segment_urls).

This page covers authenticating ad pod metadata requests using the Hash-Based Message Authentication Code (HMAC) token.

## Before you begin

Before you continue, do the following:

- Complete the [prerequisites](https://developers.google.com/ad-manager/dynamic-ad-insertion/api/pod-serving/live/pod-request-overview#prerequisites).
- Ensure you've enabled the **Pod resource authentication keys** 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 ATM request. For a full list, see the [Method: Ad pod timing metadata](https://developers.google.com/ad-manager/dynamic-ad-insertion/api/pod-serving/reference/live#method_ad_pod_timing_metadata).
2. Organize your parameters into a single string. You must sort the parameters alphabetically
   and separate them with the tilde `~` character, for example:

       ad_break_id=AD_BREAK_ID~custom_asset_key=CUSTOM_ASSET_KEY~exp=EXPIRATION~network_code=NETWORK_CODE~pod_id=POD_IDENTIFIER

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 you gathered earlier:

       ad_break_id=...~hmac=HMAC_SIGNATURE`

   Replace the `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 snippet generates the URL-encoded value of a signed token string:

    # Add 60 seconds to the current time
    future_epoch=$((EPOCHSECONDS + 60))

    echo "Current: $EPOCHSECONDS"
    echo "Future: $future_epoch"
    # Current: 1769644251
    # Future: 1769644311


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

    # Sort parameters in the token string
    token="ad_break_id=ab-001~custom_asset_key=hls-pod-serving-redirect-auth-stream-pod~exp=1769644311~network_code=21775744923~pd=30000"

    # Generate the token's signature.
    echo -n $token | openssl dgst -sha256 -mac HMAC -macopt key:$key


    # SHA-256(stdin)= 056d442f19baee6988c0e88d2eb8e9f9f6ffcc98737a2fef301dec759701cfb6

    # Sign the token: ad_break_id=ab-001~custom_asset_key=hls-pod-serving-redirect-auth-stream-pod~exp=1769644311~network_code=21775744923~pd=30000~hmac=056d442f19baee6988c0e88d2eb8e9f9f6ffcc98737a2fef301dec759701cfb6

    # Encode the token: ad%5Fbreak%5Fid%3Dab%2D001%7Ecustom%5Fasset%5Fkey%3Dhls%2Dpod%2Dserving%2Dredirect%2Dauth%2Dstream%2Dpod%7Eexp%3D1769644311%7Enetwork%5Fcode%3D21775744923%7Epd%3D30000%7Ehmac%3D056d442f19baee6988c0e88d2eb8e9f9f6ffcc98737a2fef301dec759701cfb6

## Authenticate an ATM request

To authenticate your ATM requests, use the `auth-token` query string parameter
to pass the URL-encoded signed HMAC token.

The following example uses an HMAC token to authenticate an ATM request:

    curl --include "https://dai.google.com/linear/pods/v1/adv/network/21775744923/custom_asset/hls-pod-serving-redirect-auth-stream-pod/pod.json?stream_id=6755b6a6-ef0f-4587-9b7f-8a59c76ae210:CBF2&ad_break_id=ab-001&pd=30000&auth-token=ad%5Fbreak%5Fid%3Dab%2D001%7Ecustom%5Fasset%5Fkey%3Dhls%2Dpod%2Dserving%2Dredirect%2Dauth%2Dstream%2Dpod%7Eexp%3D1769644311%7Enetwork%5Fcode%3D21775744923%7Epd%3D30000%7Ehmac%3D056d442f19baee6988c0e88d2eb8e9f9f6ffcc98737a2fef301dec759701cfb6"

If successful, you see the following JSON response:

    {
        "ads": [
            {
                "duration_ms": 10010,
                "variants": {
                    "media-ts-4628000bps": {
                        "segment_durations": {
                            "timescale": 1000,
                            "values": [
                                5005,
                                5005
                            ]
                        },
                        "segment_extension": "ts"
                    }
                }
            },
            ...
        ],
        "slate": {
            "duration_ms": 0,
            "variants": {
                "media-ts-4628000bps": {
                    "segment_durations": {
                        "timescale": 1000,
                        "values": [
                            10010
                        ]
                    },
                    "segment_extension": "ts"
                }
            }
        },
        "status": "final"
    }

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