In order to be able to access the Backstage Reporting API service, add the following headers:
Authorization: Bearer TOKEN and Authorizer: dsp
(not case-sensitive) to each request. The client should be provisioned with both client_id and
client_secret for the PROD environment.
To obtain these values, please contact pmp@yahooinc.com. Once the credentials are obtained, follow the below Backstage Reporting API Guide to generate the token and access the Reporting API.
This document provides step-by-step instructions for Backstage Reporting API clients to authenticate and execute reports on the Reporting API.
curl installedpython3 installed (for JWT generation)| Environment | Reporting API | ZTS Token Endpoint |
|---|---|---|
| Production | https://api.reports.yahooinc.com/v4/ |
https://id.b2b.yahooincapis.com/zts/v1/oauth2/token |
Create a JWT client assertion and exchange it for an access token using the OAuth2
client_credentials grant with a JWT bearer client assertion (RFC 7523).
| Environment | aud claim value |
|---|---|
| Production | https://id.b2b.yahooincapis.com/zts/v1 |
Note: aud is the ZTS base path, not the full token endpoint URL.
{
"alg": "HS256",
"typ": "JWT"
}
{
"aud": "<ZTS audience from table above>",
"iss": "idb2b.dsp.dspapi.<your_client_id>",
"sub": "idb2b.dsp.dspapi.<your_client_id>",
"iat": "<current_epoch_seconds>",
"exp": "<current_epoch_seconds + 3600>",
"jti": "<random_uuid>"
}
client_secretJWT=$(python3 -c "
import time, uuid, base64, hmac, hashlib, json
def b64url(d): return base64.urlsafe_b64encode(d).decode().rstrip('=')
CLIENT_ID, CLIENT_SECRET, AUD = '<client_id>', '<client_secret>', '<zts_audience>'
header = {'alg':'HS256','typ':'JWT'}
iat = int(time.time())
payload = {'aud':AUD,'iss':f'idb2b.dsp.dspapi.{CLIENT_ID}','sub':f'idb2b.dsp.dspapi.{CLIENT_ID}','iat':iat,'exp':iat+3600,'jti':str(uuid.uuid4())}
hb = b64url(json.dumps(header,separators=(',',':')).encode())
pb = b64url(json.dumps(payload,separators=(',',':')).encode())
si = f'{hb}.{pb}'
sig = hmac.new(CLIENT_SECRET.encode(), si.encode(), hashlib.sha256).digest()
print(f'{si}.{b64url(sig)}')
")
curl -X POST "<ZTS_TOKEN_ENDPOINT>" \ -H "Content-Type: application/x-www-form-urlencoded" \ -H "Accept: application/json" \ -d "grant_type=client_credentials" \ -d "client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer" \ -d "scope=api-client" \ -d "realm=dsp" \ --data-urlencode "client_assertion=$JWT"
{
"access_token": "eyJ0eXAiOiJKV1Qi...",
"token_type": "Bearer",
"expires_in": 21600
}
Verify the token works by listing available reports. Use the optional
platform query parameter to limit the response to report templates for a specific
platform alias, such as 1M. Omit the parameter to return all report templates the
authenticated user can access.
curl -s \ -H "Authorization: Bearer <ACCESS_TOKEN>" \ -H "Authorizer: dsp" \ "https://api.reports.yahooinc.com/v4/report-management/report?platform=1M"
Expected: HTTP 200 with a JSON array of report objects.
Fetch details for a specific report template.
curl -s \ -H "Authorization: Bearer <ACCESS_TOKEN>" \ -H "Authorizer: dsp" \ "https://api.reports.yahooinc.com/v4/report-management/report/<REPORT_ID>"
Expected: HTTP 200 with report template details including columns, filters, and parameters.
Submit a report generation task.
curl -s -X POST \
-H "Authorization: Bearer <ACCESS_TOKEN>" \
-H "Authorizer: dsp" \
-H "Content-Type: application/json" \
-d '{
"reportTemplateId": "12345678910",
"reportParameters": {
"sd": ["2026-04-24T00"],
"ed": ["2026-04-30T23"],
"ocOrgId1M": ["<ORG_ID>"]
}
}' \
"https://api.reports.yahooinc.com/v4/report-management/reporttask"
Expected: HTTP 200 with a task ID.
Notes:
sd (start date) and ed (end date) must be in
yyyy-MM-dd'T'HH formatocOrgId1M is the organization ID filter (Seller ID) — use the specific org ID
permitted for your userreportParameters values must be arrays of strings (e.g.,
["value"])curl -s \ -H "Authorization: Bearer <ACCESS_TOKEN>" \ -H "Authorizer: dsp" \ "https://api.reports.yahooinc.com/v4/report-management/reporttask/<TASK_ID>"
Expected: HTTP 200. Poll until "status": "COMPLETED"
(typically completes within a few seconds for small ranges).
Important: When status == COMPLETED, the report payload is returned
inline in the same response under data.blocks[].
There is no separate /data endpoint on this API version — calling
/reporttask/<TASK_ID>/data returns HTTP 404.
{
"status": "COMPLETED",
"data": {
"blocks": [
{
"fields": [
{ "sqlAlias": "scaledDay1M", "name": "Date", "trending": false },
{ "sqlAlias": "adsDelivered1M", "name": "Impressions", "trending": false },
{ "sqlAlias": "publisherRevenueRtb1M","name": "Net Revenue", "trending": false }
],
"rows": [
{ "fields": { "scaledDay1M": 0000000000000, "adsDelivered1M": 00000, "publisherRevenueRtb1M": 99.99 }, "trendingFields": {} }
],
"total": { "fields": { "adsDelivered1M": 9999999, "publisherRevenueRtb1M": 999.99 }, "trendingFields": {} }
}
]
}
}
data.blocks[].fields — column metadata
(sqlAlias + display name)data.blocks[].rows[].fields — per-row metric values keyed by
sqlAliasdata.blocks[].total.fields — aggregated totals across all rows| Header | Value | Purpose |
|---|---|---|
Authorization |
Bearer <access_token> |
Authentication |
Authorizer |
dsp |
Routes to DSP authentication provider |