Register screens
Create a site for each venue and a screen for each display.
You need the sites:read, sites:write, screens:read and screens:write scopes. Send an Idempotency-Key on every create so you can retry safely.
Create a site
curl -X POST https://api.vojo-media.com/v1/sites \
-H "Authorization: Bearer $VOJO_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"name": "Leeds Trinity",
"address": {
"street": "1 Market Street",
"city": "Leeds",
"postal_code": "LS1 6DT",
"country": "GB",
"latitude": 53.7966,
"longitude": -1.5432
},
"operating_times_enabled": true,
"operating_times": {
"monday": { "operational": true, "ranges": [
{ "start": "07:00", "end": "12:00" },
{ "start": "13:00", "end": "22:00" }
] },
"tuesday": { "operational": true, "ranges": [{ "start": "07:00", "end": "22:00" }] },
"wednesday": { "operational": true, "ranges": [{ "start": "07:00", "end": "22:00" }] },
"thursday": { "operational": true, "ranges": [{ "start": "07:00", "end": "22:00" }] },
"friday": { "operational": true, "ranges": [{ "start": "07:00", "end": "22:00" }] },
"saturday": { "operational": true, "ranges": [{ "start": "07:00", "end": "22:00" }] },
"sunday": { "operational": false, "ranges": [] }
}
}'const { data: site, error } = await api.POST("/v1/sites", {
params: { header: { "Idempotency-Key": crypto.randomUUID() } },
body: {
name: "Leeds Trinity",
address: {
street: "1 Market Street",
city: "Leeds",
postal_code: "LS1 6DT",
country: "GB",
latitude: 53.7966,
longitude: -1.5432,
},
},
});
if (error) throw new VojoApiError(error);The response is 201 with the site. A day can have several opening windows, as Monday does here.
Site names are unique within your organisation, and a clash returns 409 duplicate_name. To find a site, use GET /v1/sites?q=leeds.
Create a screen
curl -X POST https://api.vojo-media.com/v1/screens \
-H "Authorization: Bearer $VOJO_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"name": "Lobby North",
"site_id": "'"$SITE_ID"'",
"size_inches": 55,
"orientation": "portrait",
"brand": "iiyama",
"model": "LH5560UHS"
}'const { data: screen, error } = await api.POST("/v1/screens", {
params: { header: { "Idempotency-Key": crypto.randomUUID() } },
body: {
name: "Lobby North",
site_id: site.data.id,
size_inches: 55,
orientation: "portrait",
brand: "iiyama",
model: "LH5560UHS",
},
});
if (error) throw new VojoApiError(error);Store data.id against your own screen record. You'll pass it as screen_id every time you wrap a creative for that screen.
Screen names are unique within your organisation. For the size, send size_inches and Vojo picks the band. You can send screen_size_range_id from GET /v1/screen-size-ranges instead, but not both.
Check your screens
Vojo reports facts about a screen, not a status. See Screens and Harvesters for what last_evidence_at, harvester and quality_bad mean.
GET /v1/screens filters by site_id, has_harvester and q (a name search). To list the screens with the most recent evidence first, with any that have none last:
curl "https://api.vojo-media.com/v1/screens?sort=-last_evidence_at" \
-H "Authorization: Bearer $VOJO_KEY"To change a screen, use PATCH /v1/screens/{screen_id}. DELETE removes it, and keeps its evidence history.
Next: wrap a creative for your new screen.