Channel99 · OpenAPI Overlay 1.0.0
API Evangelist enhancements for the Channel99 Pulsar API
10 actions
10 updates
documentation
extends
openapi/channel99-pulsar-openapi.json
Generated by API Evangelist
Written by API Evangelist tooling for Channel99's API. It is a proposal applied on top of the contract, not a document Channel99 publishes.
What the actions change
contacttermsOfServicex-apis-io-providerx-api-evangelist-notedescriptionurldocumentedretry_after_header
Targets 10
$.servers
$.info
$.externalDocs
$.info.x-rate-limits
$.info.x-pagination
$.info.x-error-format
$.info.x-idempotency
$.paths['/ip/{ipAddress}'].get
$.paths['/auth/token'].post
$.tags
OpenAPI Overlay
overlay: 1.0.0
info:
title: API Evangelist enhancements for the Channel99 Pulsar API
version: 1.0.0
extends: openapi/channel99-pulsar-openapi.json
x-provenance:
generated: '2026-08-12'
method: generated
source: >-
Enhancements derived from the Channel99 Reporting API Developer Guide
(https://support.channel99.com/hc/en-us/articles/49766041989787-Channel99-Reporting-API-Developer-Guide)
and from live probes of pulsar.channel99.com. The original document at
openapi/channel99-pulsar-openapi.json is never mutated.
note: >-
The single highest-value correction here is servers[]. The document as published declares
`servers: [{url: "/"}]` - a relative server that names no host, so an agent handed only the
spec cannot reach the API at all. Channel99's own developer guide states plainly: "All
Reporting API endpoints use https://pulsar.channel99.com unless otherwise specified in the
API reference." That sentence is the authority for the server URL set below.
actions:
- target: $.servers
description: >-
Replace the relative server with the real production host, as named by Channel99's own
developer guide.
update:
- url: https://pulsar.channel99.com
description: Production - Channel99 Pulsar (Bulk Data Transfer / Reporting) API
- target: $.info
description: Add contact, licence-free terms pointers and external documentation identity.
update:
contact:
name: Channel99 Support
email: support@channel99.com
url: https://support.channel99.com/hc/en-us
termsOfService: https://www.channel99.com/terms-of-service
x-apis-io-provider: channel99
x-api-evangelist-note: >-
Contact and terms are added from Channel99's published support and legal pages; the
original document declares neither.
- target: $.externalDocs
description: Point at the human developer guide that documents the auth exchange and reporting concepts.
update:
description: Channel99 Reporting API Developer Guide
url: https://support.channel99.com/hc/en-us/articles/49766041989787-Channel99-Reporting-API-Developer-Guide
- target: $.info.x-rate-limits
description: >-
Surface the rate-limit tiers as structured data. They are published in the document today,
but only as prose inside components.responses.TooManyRequests.description, where no tool can
read them.
update:
documented: true
retry_after_header: Retry-After
status_on_exhaustion: 429
budget_headers: false
tiers:
- scope: client_id
applies_to: POST /auth/token
limit: 20
window: 60
unit: requests-per-minute
- scope: client
applies_to: /events/* and /dimensions/*
limit: 100
window: 10
unit: requests-per-10-seconds
burst: true
- scope: x-client-id
applies_to: all authenticated routes
limit: 60
window: 1
unit: requests-per-second
enforced_at: waf
- scope: client
applies_to: /ip/*
limit: null
enforced_at: waf
tier: elevated
source: components.responses.TooManyRequests.description of the published document
- target: $.info.x-pagination
description: Declare the cursor pagination contract at document level so a client can discover it without reading every parameter.
update:
style: cursor
cursor_param: cursor
limit_param: limit
default_limit: 200
max_limit: 1000
next_field: nextCursor
terminator: nextCursor is null
applies_to:
- /events/visits
- /events/pageviews
- /events/impressions
- /events/intents
- target: $.info.x-error-format
description: Declare the error envelope, which the document models as a schema but never names.
update:
format: custom-json
media_type: application/json
rfc9457: false
fields:
- error
- code
- message
code_namespace: err:pulsar.<domain>.<condition>
catalog: errors/channel99-problem-types.yml
- target: $.info.x-idempotency
description: State the absence explicitly so an agent does not have to infer it.
update:
supported: false
header: null
note: >-
No idempotency key is defined. 16 of 17 operations are GETs and are safe to retry;
POST /auth/token is not idempotent - each call mints a new token.
- target: $.paths['/ip/{ipAddress}'].get
description: Flag the separately-permissioned entitlement documented in the developer guide but absent from the spec.
update:
x-entitlement:
separately_permissioned: true
note: >-
"Access to separately permissioned services, including the Channel99 IP API, is not
enabled unless explicitly granted." A token valid for /events/* and /dimensions/* may
still return 403 here.
source: https://support.channel99.com/hc/en-us/articles/49766041989787-Channel99-Reporting-API-Developer-Guide
- target: $.paths['/auth/token'].post
description: Record the token lifetime and the absence of a refresh token as structured data.
update:
x-token:
lifetime_seconds: 3600
refresh_token: false
reissue: Re-POST the same credentials after expiry.
pairing: >-
Every subsequent request must carry BOTH Authorization: Bearer <token> and
x-client-id: <client_id>; a mismatch returns 403.
- target: $.tags
description: Add a machine-readable grouping of the tag set into fact, dimension, identity and platform families.
update:
- name: x-families
description: >-
events (Visits, Pageviews, Impressions, Intents) are fact entities; dimensions
(Ad Accounts, Ad Campaign Groups, Ad Campaigns, Ad Groups, Ad Units, Ads, Audiences,
Channels, Companies, Vendors) are lookup entities joined by *_id; IP Lookup is identity
resolution; Auth and Health are platform operations. See data-model/channel99-data-model.yml.