Get Generated Story Count#
Returns a deterministic count of generated stories in a date window, with explicit include/exclude filtering and optional audit samples.
Endpoint#
POST /api/app/analytics/generatedStoryCount
Authentication#
This endpoint requires:
- bearer authentication (
Authorization: Bearer <token>) - an analytics-enabled CMS role (
editor,admin,developer,superadmin, orsystemadmin) - tenant context (for example
x-storyteller-api-key: <tenant-guid>)
See Authentication for details.
Request Body#
| Field | Type | Required | Description |
|---|---|---|---|
startDate |
string (ISO 8601) |
Yes | Range start timestamp (UTC-normalized) |
endDate |
string (ISO 8601) |
Yes | Range end timestamp, exclusive (UTC-normalized) |
profile |
string |
No | Optional caller-provided profile label echoed in response metadata |
includeExternalIdPatterns |
string[] |
No | SQL-LIKE include patterns over Stories.ExternalId (%, _) |
excludeExternalIdPatterns |
string[] |
No | SQL-LIKE exclude patterns over Stories.ExternalId (%, _) |
categoryIds |
guid[] |
No | Match stories with at least one matching category id |
categoryExternalIds |
string[] |
No | Match stories with at least one matching category external id |
publishedAtMode |
string |
No | earliest (default, durable firstPublishedAt) or current (computed earliestCurrentPublishAt) |
auditSampleSize |
int |
No | Number of deterministic sample rows to return (0..100) |
categoryIds and categoryExternalIds are mutually exclusive.
Request#
Example Request#
POST /api/app/analytics/generatedStoryCount
Host: cmsapi.localhost
Authorization: Bearer <jwt>
x-storyteller-api-key: 11111111-2222-3333-4444-555555555555
Content-Type: application/json
{
"startDate": "2026-02-01T00:00:00Z",
"endDate": "2026-02-08T00:00:00Z",
"profile": "nba-automated-v1",
"excludeExternalIdPatterns": ["00224%-%", "localized-recap%", "top-headlines%"],
"categoryExternalIds": ["nba"],
"publishedAtMode": "earliest",
"auditSampleSize": 5
}
Response#
Success Response#
Status Code: 200 OK
{
"kind": "analytics.generated-story-count",
"version": "1",
"env": "Production",
"tenant": "11111111-2222-3333-4444-555555555555",
"range": {
"startDate": "2026-02-01T00:00:00Z",
"endDate": "2026-02-08T00:00:00Z",
"endDateSemantics": "exclusive",
"timestampField": "firstPublishedAt"
},
"filters": {
"profile": "nba-automated-v1",
"publishedAtMode": "earliest",
"categoryMatch": "any",
"patternSyntax": "sql-like",
"patternPrecedence": "exclude-wins",
"includeExternalIdPatterns": [],
"excludeExternalIdPatterns": ["00224%-%", "localized-recap%", "top-headlines%"],
"categoryIds": [],
"categoryExternalIds": ["nba"]
},
"metrics": {
"generatedStoryCount": 123
},
"audit": {
"sampleStoryIds": [
"8f3c6d9e-40ef-4c61-b340-2134de95ec4a"
],
"sampleExternalIds": [
"nba-recap-2026-02-07"
]
}
}
Error Responses#
Status Code: 400 Bad Request
Common cases:
- missing tenant context
startDateis not earlier thanendDate- range is larger than the maximum supported window (120 days)
- both
categoryIdsandcategoryExternalIdswere provided - invalid filter values (empty pattern, too many values, oversized values)
Semantics#
- Date window contract:
startDate <= timestamp < endDate(end-exclusive). - Timezone behavior: incoming timestamps are normalized to UTC.
publishedAtMode = earliestuses the story's first recorded publish timestamp (firstPublishedAt), not a live-delivery transition.- In
earliestmode, a story can remain countable after it was later unscheduled or moved out ofPublished. - Generated story filter baseline:
Stories.Source == IntegrationsApi- story is not soft-deleted (current state)
- story is not hidden from CMS (current state)
- Pattern precedence:
excludewins overinclude. - Category filter behavior:
anymatch.