Contact
If you have any questions, encounter bugs, or just want to say hello, send us an email at dev@spotwatch.io.
Schema
The Spotwatch API is accessible via HTTPS through api.spotwatch.io
. You can pass arguments either as query strings or as JSON content with the content type application/json
. Successful requests return 200 OK
, while failed requests return either 400 Bad Request
or 403 Forbidden
with an error message in text/plain
.
Most requests require a valid API key. The API key can be provided either as an argument or as a header field Authorization
with the type key
.
Passing API key as a header field
$ curl -i 'https://api.spotwatch.io/get-ad
?ad_fields=categories
' -H '
Authorization: key
your-key'
Passing API key in a JSON body
$ curl -i 'https://api.spotwatch.io/get-ad
' -d '
{"key":"your-key"
,"ad_fields":["categories"]}'
Error response example
HTTP/1.1 400 Bad Request
Content-Type: text/plain
Argument(s) missing. Expected [key, id], got [key, ad_fields], missing [id].
Success response example
HTTP/1.1 200 OK
Content-Type: application/json
{
"categories" : [ "telecommunication", "electronics", "mobile" ]
}
Time Formats
By default, timestamps are provided in ISO 8601 format in UTC. You can specify the desired time format for timestamps in your requests using the time_fmt
argument.
Accepted values for time_fmt
are:
value | formatting | output example | |
---|---|---|---|
iso8601 |
YYYY-MM-DDTHH:MM:SSZ |
2024-03-31T06:07:07Z | *default |
unix |
integer |
1678454850 | |
plain |
YYYY-MM-DD HH:MM:SS |
2024-03-31 08:07:07 |
Plain Format
The plain
format returns a timestamp adjusted to the timezone set for your API key. By default, the timezone is Europe/Berlin
.
Set your timezone with
/set-timezone-for-api-key
Arguments
required | ||
key |
string | your API key |
tz |
string | the timezone to set |
Example
/set-timezone-for-api-key
?key=your-key
&tz=Europe/London
Default timezone set to [Europe/London].
Date Arguments
Requests with date arguments, usually indicated with a *_to / *_from
postfix, accept either ISO 8601, unix or a short day format
YYYY-MM-DD
.
Example
/get-ads
?key=your-key
&created_from=2024-06-30
&created_to=1656592050
Pagination
Requests which return a page object accept an optional page_lim
argument:
page_lim |
integer |
sets the limit for results per page
default 200
max 100'000
max value will be chosen when -1
|
A page
object consists of the following values:
index |
integer | current page index zero based |
prev |
string |
path to the previous page
null if first page
|
next |
string |
path to the next page
null if last page
|
results_total |
integer | total number of results (all pages combined) | pages_total |
integer | total number of pages |
Example
/get-broadcasts
?key=your-key
&time_from=2024-12-01
&page_lim=1000
Returns
{
"page": {
"index": 0,
"prev": null,
"next": "/hl0fserktnimhbcnfcmq",
"results_total": 424588,
"pages_total": 425
},
"results": [
...
]
}
The prev
and next
fields are paths to the next / previous pages. For example, requesting:
https://api.spotwatch.io/hl0fserktnimhbcnfcmq
would return the next set of results.
API Key
Get your key with
/get-api-key
Arguments
required | ||
email |
string | your email |
pw |
string | your password |
Returns
Your API key as text/plain
.
Example
$ curl https://api.spotwatch.io/get-api-key
-d '
{"email":"you@email.com"
,"pw":"your-password"}'
Response
your_api_key
Ads
Get a single ad with
/get-ad
Arguments
required | ||
key |
string | your API key |
id |
integer | the ad ID |
optional | ||
---|---|---|
ad_fields |
string(s)comma-separated or json array | fields the ad object shall containdefault all |
broadcast_fields |
string(s)comma-separated or json array | fields the nested broadcast objects shall containdefault all except program
genre
subgenre
ad
|
time_fmt |
time format |
Returns
The ad with given ID as application/json
.
Example
/get-ad
?key=your-key
&id=3893859079416045
{
"id": 3893859079416045,
"created": "2024-03-31T06:07:07Z",
"lastseen": "2024-06-12T22:26:26Z",
"duration": 20,
"brand": "vodafone",
"description": "allnet flat",
"categories": [ "telecommunication" ],
"nbroadcasts": 1,
"broadcasts": [
{
"id": 39840,
"time": "2024-06-11T18:08:46Z",
"region": "de",
"channel": "vox",
"ad": 3893859079416045,
"block": 1259,
"blockindex": 3
}
],
"related": [ 2798804439039186 ],
"media": {
"video": {
"mp4": "/klwc7ilp41lgb8kiopye"
},
"image": {
"preview": "/9dgnbp81g6jndapeazyy",
"grid": "/pjbphmperbfaopf4qx8s"
}
}
}
Get multiple ads with
/get-ads
Arguments
required | ||
key |
string | your API key |
optional | ||
---|---|---|
ids |
integers(s)comma-separated or json array | filter by Ad-ID(s) |
category |
string(s)comma-separated or json array | filter by categories |
brand |
string(s)comma-separated or json array | filter by brand |
region |
string(s)comma-separated or json array | filter by region |
unidentified |
bool | include ads which are not identified default true
|
self_promo |
bool | include self promotional ads default true
|
created_from |
date | lower limit for creation date |
created_to |
date | upper limit for creation date |
lastseen_from |
date | lower limit for last seen date |
lastseen_to |
date | upper limit for last seen date |
time_seen_from |
date | only return ads broadcasted from time_seen_from |
time_seen_to |
date | only return ads broadcasted until time_seen_to |
duration_from |
integer | lower limit for ad durationin seconds |
duration_to |
integer | upper limit for ad durationin seconds |
ad_fields |
string(s)comma-separated or json array | fields the ad objects shall containdefault all |
broadcast_fields |
string(s)comma-separated or json array | fields the nested broadcast objects shall containdefault all except program
ad
|
keyword |
string(s)comma-separated or json array | only return ads which contain one of given keyword(s) |
time_fmt |
time format | |
page_lim |
integer | maximum number of results per page |
Returns
Page and an array results
with matched ads as application/json
.
Example
/get-ads
?key=your-key
&category=telecommunication
&ad_fields=id,lastseen,media
&time_fmt=unix
{
"page": { ... }
"results": [
{
"id": 6353806529225371,
"lastseen": 1656592050,
"media": {
"video": {
"mp4": "/klwc7ilp41lgb8kiopye"
},
"image": {
"preview": "/azfe4d2qwcmk0shik1gw",
"grid": "/pjbphmperbfaopf4qx8s"
}
}
},
...
]
}
Broadcasts
Get a single broadcast with
/get-broadcast
Arguments
required | ||
key |
string | your API key |
id |
integer | the broadcast ID |
optional | ||
---|---|---|
broadcast_fields |
string(s)comma-separated or json array | fields the broadcast object shall containdefault all |
time_fmt |
time format |
Returns
The broadcast with given ID as application/json
.
Example
/get-broadcast
?key=your-key
&id=39840
{
"id": 39840,
"time": "2024-06-11T18:08:46Z",
"region": "de",
"channel": "vox",
"ad": 3893859079416045,
"block": 1259,
"blockindex": 3,
"program": "gute zeiten, schlechte zeiten",
"genre": "serien",
"subgenre": "daily soap"
}
Get multiple broadcasts with
/get-broadcasts
Arguments
required | ||
key |
string | your API key |
optional | ||
---|---|---|
channel |
string(s)comma-separated or json array | filter by channel |
region |
string(s)comma-separated or json array | filter by region |
time_from |
date | lower limit for broadcast date |
time_to |
date | upper limit for broadcast date |
ad_id |
integer(s)comma-separated or json array | only return broadcasts for given Ad-ID(s) |
ad_brand |
string(s)comma-separated or json array | filter by ad brand |
ad_category |
string(s)comma-separated or json array | filter by ad category |
ad_identified |
bool | only return broadcasts for ads which are identified
default false
|
block_id |
integer(s)comma-separated or json array | only return broadcasts for given block-id(s) |
broadcast_fields |
string(s)comma-separated or json array | fields the broadcast objects shall contain |
time_fmt |
time format | |
page_lim |
integer | maximum number of results per page |
Returns
Page and an array results
with matched broadcasts as application/json
.
Example
/get-broadcasts
?key=your-key
&channel=rtl,dmax
&ad_brand=sony
&time_from=2024-06-09
&time_fmt=plain
&broadcast_fields=ad,time,region,channel
{
"page": { ... },
"results": [
{
"ad": 2371504209363725,
"time": "2024-05-06 18:40:10",
"region": "de",
"channel": "dmax",
},
...
]
}
Get all broadcasts for an ad with
/get-broadcasts-for-ad
Arguments
required | ||
---|---|---|
key |
string | your API key |
ad |
integer | the ad ID |
optional | ||
broadcast_fields |
string(s)comma-separated or json array | fields the broadcast objects shall containdefault all |
region |
string(s)comma-separated or json array | return broadcasts for specific region(s)default all |
fmt |
string | return format, csv or json default json |
csv_delimiter |
string | delimiter for the returned csvdefault , |
time_fmt |
time format |
Returns
An array containing all broadcast objects for given ad as
-
application/json
onfmt=json
-
text/csv
onfmt=csv
Example
/get-broadcasts-for-ad
?key=your-key
&ad=2798804439039186
&fmt=csv
&csv_delimiter=;
"id";"time";"region";"channel";"ad";"block";"blockindex"
"47501";"2024-06-09 01:00:00";"de";"rtl";"3392276504707697";"5922";"0"
...
Broadcast blocks
Get a single broadcast block with
/get-block
Arguments
required | ||
key |
string | your API key |
id |
integer | the block ID |
optional | ||
ad_fields |
string(s)comma-separated or json array | fields the nested ad objects shall containdefault id only |
broadcast_fields |
string(s)comma-separated or json array | fields the nested broadcast objects shall containdefault id only |
time_fmt |
time format |
Returns
The block with given ID as application/json
.
Example
/get-block
?key=your-key
&id=1259
&ad_fields=id,duration
{
"id": 1259,
"region": "de",
"channel": "rtl",
"start": "2024-06-09T01:00:00Z",
"finish": "2024-06-09T01:01:31Z",
"program": "two and a half men",
"genre": "serien",
"subgenre": "comedyserie",
"ads": [
{
"id": 3392276504707697,
"duration": 20
},
...
]
}
Get multiple broadcast blocks with
/get-blocks
Arguments
required | ||
key |
string | your API key |
optional | ||
---|---|---|
channel |
string(s)comma-separated or json array | filter by channel |
region |
string(s)comma-separated or json array | filter by region |
start_from |
date | lower limit for broadcast date |
start_to |
date | upper limit for broadcast date |
updated_from |
date | lower limit for date of last block update |
updated_to |
date | upper limit for date of last block update |
ad_fields |
string(s)comma-separated or json array | fields the nested ad objects shall containdefault id only |
broadcast_fields |
string(s)comma-separated or json array | fields the nested broadcast objects shall containdefault id only |
ad_id |
integer(s)comma-separated or json array | list only blocks which contain any of the specified ad ID(s) |
time_fmt |
time format | |
page_lim |
integer | maximum number of results per page |
Returns
Page and an array results
with matched blocks as application/json
.
Example
/get-blocks
?key=your-key
&start_from=2024-06-11
{
"page": { ... }
"results": [
{
"id" : 661,
"region": "de",
"channel" : "sat1",
"start" : "2024-06-11T01:00:00Z",
"finish" : "2024-06-11T01:01:31Z",
"program": "navy cis",
"genre": "serien",
"subgenre": "krimiserie"
"ads" : [
{
"id" : 767171625096234
},
...
]
}
]
}
Batch Requests
Make multiple API requests in one go with
/batch
Arguments
required | ||
key |
string | your API key |
requests |
json array | json objects with form: { "mapkey": "", "path": "", "args": {} } |
optional | ||
---|---|---|
concurrent |
bool | allows concurrent processing of multiple requestsdefault false |
Returns
A map (mapkey -> result) of json objects with form:
{
"code": "", "reply": ""
}
Example
$ curl https://api.spotwatch.io/batch -H 'Authorization: key your-key' -d '{
"requests": [
{
"mapkey": "first",
"path": "/get-block",
"args": { "id": 810, "ad_fields": ["id", "brand"] }
},
{
"mapkey": "second",
"path": "/get-block",
"args": { "id": 14426, "ad_fields": ["id", "brand"] }
}
]
}'
Result
{
"first": {
"code": 200,
"reply": {
"id": 810,
"region": "de",
"channel": "viva",
"start": "2024-06-25T07:45:38Z",
"finish": "2024-06-25T07:46:18Z",
"ads": [
{ "id": 504038989557373, "brand": "goodgame.de" },
{ "id": 3996816512810860, "brand": "wimdu.de" }
]
}
},
"second": {
"code": 400,
"reply": "Block ID [14426] not found."
}
}
Masked Requests
To avoid exposing sensible information in urls, mask requests with
/mask
Arguments
required | ||
key |
string | your API key |
path |
string | request path |
args |
json | request arguments |
optional | ||
---|---|---|
ttl |
integer |
time to live for returned link, in seconds
default 7200 (2 hours)
|
ctl |
integer |
calls to live for returned link
no limit when -1
default -1
|
allow_args |
bool |
allows late binding for arguments
default false
|
Returns
Generated link in text/plain
.
Example
$ curl https://api.spotwatch.io/mask -d '{
"key": "your-key",
"allow_args": true,
"path": "/get-ad",
"args": {
"ad_fields": ["id", "brand", "description", "media"],
"time_fmt": "plain"
}
}'
/t1o0rc7lt1887qjnruje
The generated link can be called with arguments when allow_args
is set to true
:
https://api.spotwatch.io/t1o0rc7lt1887qjnruje
?id=8763496104749285
Broadcast Push Messages via Webhooks
Set a webhook for broadcast push messages with
/set-push-broadcast
Arguments
required | ||
key |
string | your API key |
url |
string | push endpoint |
optional | ||
---|---|---|
token |
string | your chosen token |
time_fmt |
time format | |
ad_fields |
string(s)comma-separated or json array | fields the nested ad object shall contain
default:
id
created
lastseen
duration
nbroadcasts
brand
description
categories
related
media
|
Push messages are sent over HTTP/HTTPS using the POST
method with a Content-Type
of application/json
. To verify a given endpoint, the server will send a ping message:
{ "ping": "random-string" }
The server expects the random string to be sent back as text/plain
.
When setting an endpoint, you can pass an optional argument called token
. This token can be any string of your choosing and will be included with every push message sent to the endpoint. You can use this token on your end to verify that the request comes from an authorized source.
Please note that only one endpoint can be set at any given time. Setting a new endpoint will overwrite the previous one.
Setting an Endpoint
To set an endpoint, use the following API call:
/set-push-broadcast
?key=your-key
&url=https://your-domain.net/your-webhook-endpoint
&token=your-chosen-token
Deleting an Endpoint
To delete an endpoint, use the following API call:
/delete-push-broadcast
?key=your-key
Example Implementation
The following is an exemplary implementation of setting up a webhook and receiving messages:
express = require("express")
axios = require("axios")
crypto = require("crypto")
bodyParser = require("body-parser")
spotwatchApiKey = "your-api-key"
webhookUrl = "https://your-domain.net/spotwatch-webhook"
randomToken = crypto.randomBytes(32).toString("hex")
setupBroadcastWebhook = () ->
apiRequestUrl = "https://api.spotwatch.io/set-push-broadcast"
# Pass your webhook URL along with the generated token
requestBody =
key: spotwatchApiKey
url: webhookUrl
token: randomToken
try
await axios.post(apiRequestUrl, requestBody)
console.log("Webhook set up successfully.")
catch error
console.log("Failed to set up webhook => #{error.response?.data}")
handleBroadcastMessage = (message) ->
# Process and handle the broadcast message
console.log(message)
app = express()
app.use(bodyParser.json())
# The endpoint which will be called to deliver broadcast messages
app.post "/spotwatch-webhook", (request, response) ->
body = request.body
token = body?.token
# This token should match your generated token
if token isnt randomToken
# Unauthorized access
response.status(403).end()
else if body.ping?
# Respond with the incoming ping in clear text
response.end(body.ping)
else
response.end()
# Handle incoming broadcast message
handleBroadcastMessage(body.message)
app.listen process.env.PORT, () ->
# Set up the webhook once the server is running
setupBroadcastWebhook()
Example Broadcast Push Message
{
"token": "your-chosen-token",
"push_type": "broadcast",
"message": {
"broadcast": {
"id": 895797,
"time": "2024-09-13T13:01:28Z",
"region": "de",
"channel": "sport1",
"ad": 1843718744355554,
"block": 110529,
"blockindex": 0,
"program": "american chopper"
"genre": "report",
"subgenre": "dokumentation"
},
"timings": {
"start": "2024-09-13T13:01:28Z",
"end": "2024-09-13T13:01:48Z",
"detected": "2024-09-13T13:01:30Z"
},
"ad": {
"id": 1843718744355554,
"brand": "alfa romeo",
...
}
}
}
Broadcast Push Messages via Message Queue
You can also set up an internal message queue for broadcast messages. This can be accomplished by passing the special /message-queue
URL argument to /set-push-broadcast
as shown below:
/set-push-broadcast
?key=your-key
&url=/message-queue
If /message-queue
is used as the endpoint, new broadcast messages will be queued in an internal queue. The maximum number of queued messages is 1000. If the messages in the queue exceed this maximum number, old messages will be replaced by new ones.
Accessing Your Message Queue
To access your message queue, call:
/get-message-queue
Arguments
required | ||
key |
string | your API key |
optional | ||
---|---|---|
num_messages
|
integer |
maximum number of messages to return
default -1 which means all messages
|
Returns
An array containing up to num_messages
or all messages, sorted from oldest to newest, in application/json
format.
All returned messages are considered delivered and will be removed from the internal queue.
Examples
Fetch all queued messages
/get-message-queue
?key=your-key
Fetch up to 100 queued messages
/get-message-queue
?key=your-key
&num_messages=100
Sample Response
{
"messages": [
{
"push_type": "broadcast"
"message": {
"broadcast": {
"id": 181132408,
"time": "2024-07-29T19:31:01Z",
"region": "de",
"channel": "tlc",
"ad": 8693926032257232,
"block": 1728925,
"blockindex": 13,
"program": "Dating ohne Grenzen: In 90 Tagen zum Altar"
"genre": "report",
"subgenre": "reality-soap"
},
"timings": {
"start": "2024-07-29T19:31:01Z",
"end": "2024-07-29T19:31:11Z",
"detected": "2024-07-29T19:31:04Z"
},
"ad": {
"id": 8693926032257232,
"brand": "emma",
"created": "2024-07-04T04:43:47Z",
"lastseen": "2024-07-29T19:31:01Z",
"duration": 10,
...
}
}
},
...
]
}
Misc Requests
Get all available regions with
/get-all-regions
Arguments
required | ||
key |
string | your API key |
Returns
A list of all available regions as application/json
.
Get all channels for which data is available, including historical data
/get-all-channels
Arguments
required | ||
key |
string | your API key |
optional | ||
---|---|---|
fmt |
string | return format, csv or json default json |
Returns
A map of all available channels mapped by region as application/json
or a list as text/csv
.
Get all currently tracked channels with
/get-tracked-channels
Arguments
required | ||
key |
string | your API key |
optional | ||
fmt |
string | return format, csv or json default json |
Returns
A map of all currently tracked channels mapped by region as application/json
or a list as text/csv
.
Get all categories with
/get-all-categories
Arguments
key |
string | your API key |
Returns
A list of all categories as application/json
.
Get all brands with
/get-all-brands
Arguments
required | ||
key |
string | your api key |
required | ||
region |
string(s)comma-separated or json array | filter by region |
channel |
string(s)comma-separated or json array | filter by channel |
time_seen_from |
time format | return only brands seen from time_seen_from |
time_seen_to |
time format | return only brands seen until time_seen_to |
Returns
A list of all brands as application/json
.
Get all possible tv genres and subgenres with
/get-all-tv-genres
Arguments
required | ||
key |
string | your API key |
Returns
A map of all possible genres and subgenres mapped by region as application/json
.
Object Fields
Ad
Field | Type | Description |
---|---|---|
id |
integer | ID of ad |
created |
time format | time when ad was generated |
lastseen |
time format | last time ad was seen |
duration |
integer | ad duration in seconds |
brand |
string | the advertised brand, empty string if no brand assigned |
description |
string | short description of advertised content, empty string if no description made |
regions |
array of strings | country code(s) of regions this ad is broadcasted in |
categories |
array of strings | categories of ad |
broadcasts |
array of broadcasts | all broadcasts of ad |
nbroadcasts |
integer | number of broadcasts |
self_promo |
bool | true or false if this ad is a broadcaster self promotion |
url |
string | visible url in ad, empty string if ad does not contain an url |
media |
media | video and images of ad |
related |
array of integers | IDs of ads this ad is looking similar to |
cross_region_ads |
map of string => integer | ads broadcasted in other regions which look exactly like this ad, ad IDs mapped by country code |
user_payload |
string | custom user payload |
Ad Media
Field | Type | Description | |
---|---|---|---|
image |
object | images of ad, null if ad has no images yet |
|
preview |
string | path to preview image | |
preview_xs |
string | path to smaller version of preview image | |
grid |
string | path to image from different ad snapshots arranged in a 3x3 grid | |
grid_xs |
string | path to smaller version of grid image | |
video | object | videos of ad, null if ad has no videos yet | |
mp4 | string | path to .mp4 version of video |
Broadcast
Field | Type | Description |
---|---|---|
id |
integer | ID of broadcast |
time |
time format | start time of broadcast |
ad |
integer | ID of broadcasted ad |
region |
string | region code of broadcast region |
channel |
string | name of broadcast channel |
block |
integer | ID of broadcast block |
blockindex |
integer | position of broadcast in broadcast block starting at 0 |
block_length |
integer | total number of broadcasts in broadcast block |
pic_in_pic |
bool | true or false if broadcast is special picture in picture format |
ad_brand |
string | brand of broadcasted ad |
ad_categories |
array of strings | categories of broadcasted ad |
ad_description |
string | description of broadcasted ad |
ad_duration |
integer | duration of broadcasted ad |
ad_nbroadcasts |
integer | total number of broadcasts of broadcasted ad |
ad_user_payload |
text | custom user payload of broadcasted ad |
program |
string | name of TV-program during broadcast, empty string if no program data available |
genre |
string | genre of TV-program, empty string if no program data available |
subgenre |
string | subgenre of TV-program, empty string if no program data available |
Block
Field | Type | Description |
---|---|---|
id |
integer | ID of block |
start |
time format | start time of broadcast block |
finish |
time format | end time of broadcast block |
updated |
time format | timestamp indicating when this block was last updated |
region |
string | region code of broadcast region |
channel |
string | name of broadcast channel |
ads |
array of ads | ads in this broadcast block, same order as they were broadcasted |
program |
string | name of TV-program during broadcast, empty string if no program data available |
genre |
string | genre of TV-program empty string if no program data available |
subgenre |
string | subgenre of TV-program empty string if no program data available |