# Get Spot
Source: https://docs.framen.com/api-reference/ad-delivery/get-spot
GET https://api.framen.com/v3/vendor/{org_token}/1/rt_ad/{screen_id}
Request a single creative for a single playout on a specific screen.
## Get Spot
Request a single creative for a single playout on a specific screen. Returns content (news or ad) along with a proof-of-play URL.
This is part of the **Vendor Default API** for real-time ad serving, separate from the SMAPI CRUD endpoints.
**Need a test campaign?**
To set up a test campaign for your screens, contact [support@framen.com](mailto:support@framen.com) with one or multiple `screen_id` you want to test with.
Your organization token (e.g., `Org_4KmTqZnWpLx`).
The unique identifier of the screen requesting content.
### Response
The response `data` object contains:
| Field | Type | Description |
| ----------- | ------- | -------------------------------------- |
| `requestId` | string | Unique ID for this request |
| `billable` | boolean | Whether this playout is billable |
| `newsFirst` | boolean | Whether news should play before the ad |
The `data` object also contains two nested content objects: **`news`** and **`ad`**. Both share the same schema:
| Field | Type | Description |
| ---------- | ------- | -------------------------------- |
| `id` | string | Content item ID |
| `title` | string | Content title |
| `mimeType` | string | e.g., `text/html`, `video/mp4` |
| `height` | integer | Pixel height |
| `width` | integer | Pixel width |
| `duration` | integer | Duration in **milliseconds** |
| `url` | string | URL to fetch/render the content |
| `pop` | string | Proof-of-play callback URL (GET) |
The `news` object additionally contains:
| Field | Type | Description |
| ---------- | ------ | ----------------------------------- |
| `newsType` | string | News category (e.g., `WELT_WISSEN`) |
### Request Cycle Flow
1. Player sends ad-request -> receives ad-response (containing news + ad + pop URLs).
2. Player pre-caches content.
3. Player plays the content.
4. Player fires the proof-of-play GET request. **Must happen within 1 hour** of the original request.
5. Repeat for next spot.
### Example Request
```bash theme={null}
curl -X GET https://api.framen.com/v3/vendor/Org_4KmTqZnWpLx/1/rt_ad/Scr_xYz789
```
# Proof of Play
Source: https://docs.framen.com/api-reference/ad-delivery/proof-of-play
Confirm that content has been displayed on a screen.
## Proof of Play
The `pop` field returned in the [Get Spot](/api-reference/ad-delivery/get-spot) response is a GET URL that **must be called exactly once** after the content has been displayed. It confirms playback to FRAMEN.
### Rules
* A proof-of-play URL can only be registered **once**. Subsequent calls will be ignored.
* The proof-of-play request **must happen within 1 hour** of the original ad request.
* If the GET request fails (network error, timeout, 5xx), retry up to 3 times with exponential backoff (e.g., 1s, 2s, 4s). Retries are safe because the server deduplicates by spot ID.
### Example
After displaying the content from a Get Spot response, fire the proof-of-play URL:
```bash theme={null}
curl -X GET "https://api.framen.com/pop/5Kv88XyDCkWHf4DTHeS63BmAmMjWatjZRYcWN1cWq3rm"
```
### Proof-of-Play Dashboard
Use the [Proof-of-Play Dashboard](https://metabase.framen.io/public/question/dcb346a7-1bef-48e1-9db8-1bdda0b35ff1) to monitor proof-of-play rates for your screens. Filter by `org_token` and `screen_id` to view hourly request counts, response counts, PoP counts, and PoP rates.
# Authentication
Source: https://docs.framen.com/api-reference/authentication
How to authenticate with the Screen Manager API.
All API requests require your **organization token** (`org_token`) as a path parameter. There are no additional headers or API keys required.
## Getting your token
1. Go to [dashboard.framen.com/account/orgs](https://dashboard.framen.com/account/orgs)
2. Copy your **Org ID** from the organization settings page
Your token will look like this:
```
Org_4KmTqZnWpLx
```
## Using the token
Include your organization token as a path parameter in all API requests:
```bash theme={null}
curl -X GET "https://api.framen.com/vendor/Org_4KmTqZnWpLx/locations"
```
For a POST request to create a location:
```bash theme={null}
curl -X POST "https://api.framen.com/vendor/Org_4KmTqZnWpLx/locations" \
-H "Content-Type: application/json" \
-d '{
"name": "Downtown Mall",
"latitude": 40.7128,
"longitude": -74.0060,
"venue_type_id": "205"
}'
```
Keep your organization token confidential. Treat it like a password and do not commit it to version control or share it publicly. If your token is compromised, contact [support@framen.com](mailto:support@framen.com) immediately.
# Approve a creative
Source: https://docs.framen.com/api-reference/creative-approvals/approve
POST https://api.framen.com/vendor/{org_token}/cars/{car_id}/approve
Approve a Creative Approval Request.
## Approve a creative
Approve a Creative Approval Request, making the creative eligible for delivery on your screens. Once approved, the creative becomes available for active campaign scheduling.
Your organization token (e.g., `Org_4KmTqZnWpLx`).
The CAR identifier (e.g., `car_Xy7Kp2mN9qR4`).
### Request Body
No request body is required. The approval action is performed based on the path parameters alone.
### Response
Returns the updated CAR object with status changed to `approved` and the `updated_at` timestamp reflecting the approval action.
### Example Request
```bash theme={null}
curl -X POST "https://api.framen.com/vendor/Org_4KmTqZnWpLx/cars/car_Xy7Kp2mN9qR4/approve" \
-H "Content-Type: application/json"
```
# Get a creative
Source: https://docs.framen.com/api-reference/creative-approvals/get
GET https://api.framen.com/vendor/{org_token}/cars/{car_id}
Retrieve a single CAR by ID.
Retrieve a single Creative Approval Request by its ID. Use this to fetch detailed information about a specific creative submission.
Your organization token (e.g., `Org_4KmTqZnWpLx`).
The CAR identifier (e.g., `car_Xy7Kp2mN9qR4`).
### Response
Returns a single CAR object with complete details including the creative asset information, current status, and timestamp.
| Field | Type | Description |
| ------------------- | -------------- | -------------------------------------------------------------------------------------------------- |
| `car_id` | string | Unique CAR identifier |
| `status` | string | Current status: `pending`, `approved`, or `rejected` |
| `advertiser_name` | string | Name of the advertiser |
| `cities` | array | Array of targeted city names |
| `countries` | array | Array of targeted country codes |
| `item` | object | Creative asset object (see [Overview](/api-reference/creative-approvals/overview) for full schema) |
| `rejection_reasons` | array \| null | Rejection reasons if rejected, otherwise null |
| `custom_message` | string \| null | Custom rejection message if provided |
| `created_on` | string | ISO 8601 creation timestamp |
### Example Request
```bash theme={null}
curl -X GET "https://api.framen.com/vendor/Org_4KmTqZnWpLx/cars/car_Xy7Kp2mN9qR4"
```
### Example Response
```json theme={null}
{
"car_id": "car_Xy7Kp2mN9qR4",
"status": "pending",
"advertiser_name": "Acme Corporation",
"cities": ["Berlin", "Munich"],
"countries": ["DEU"],
"item": {
"url": "https://assets.example.com/creatives/acme-summer-2026.mp4",
"title": "Acme Summer Campaign",
"width": 1920,
"height": 1080,
"duration": 15,
"mimeType": "video/mp4",
"size": 2456789,
"md5": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4"
},
"rejection_reasons": null,
"custom_message": null,
"created_on": "2026-03-28T14:30:00Z"
}
```
### Error Responses
| Status | Description |
| ------ | --------------------------------- |
| 404 | CAR not found or invalid `car_id` |
# Get all active creatives
Source: https://docs.framen.com/api-reference/creative-approvals/list-active
GET https://api.framen.com/vendor/{org_token}/cars_active
List active Creative Approval Requests forecasted for delivery.
## Get all active creatives
Retrieve a list of all active Creative Approval Requests that are forecasted to deliver to your screens soon. These are approved CARs from campaigns with active schedules.
### Purpose
This endpoint returns creatives that are actively scheduled or about to run on your screen network. Use this to:
* **Pre-cache assets**: Download and cache creative media files before delivery
* **Prepare infrastructure**: Validate asset quality and availability ahead of ad delivery
* **Monitor campaigns**: Track which approved creatives are actively scheduled
* **Optimize delivery**: Ensure creative assets are available locally for fast playback
Your organization token (e.g., `Org_4KmTqZnWpLx`).
### Response
Returns an array of approved CAR objects with active campaigns. All creatives in this response have status `approved`.
### Example Request
```bash theme={null}
curl -X GET "https://api.framen.com/vendor/Org_4KmTqZnWpLx/cars_active"
```
# Get all creatives
Source: https://docs.framen.com/api-reference/creative-approvals/list-all
GET https://api.framen.com/vendor/{org_token}/cars
List all Creative Approval Requests in your organization.
## Get all creatives
Retrieve a list of all Creative Approval Requests for your organization. This includes creatives with all statuses: pending, approved, and rejected.
Your organization token (e.g., `Org_4KmTqZnWpLx`).
### Response
Returns an array of CAR objects. Each object contains the complete creative details, current status, and relevant timestamps.
### Response Schema
Array of objects with the following properties:
| Field | Type | Description |
| ------------------- | -------------- | ------------------------------------------------------------------- |
| `id` | string | Unique CAR identifier |
| `status` | string | Current status: `pending`, `approved`, or `rejected` |
| `advertiser_name` | string | Name of the advertiser |
| `item` | object | Creative asset object with url, width, height, duration, mime\_type |
| `rejection_reasons` | array \| null | Rejection reasons if rejected, otherwise null |
| `custom_message` | string \| null | Custom rejection message if provided |
| `created_at` | string | ISO 8601 creation timestamp |
| `updated_at` | string | ISO 8601 last modified timestamp |
### Example Request
```bash theme={null}
curl -X GET "https://api.framen.com/vendor/Org_4KmTqZnWpLx/cars"
```
# Overview
Source: https://docs.framen.com/api-reference/creative-approvals/overview
Review and manage Creative Approval Requests (CARs) for your organization.
## What are Creative Approval Requests (CARs)?
Creative Approval Requests are a critical part of your screen network management workflow. When advertisers want to run their creatives on your screens, they submit a CAR containing the creative asset (image or video), advertiser information, and targeting details. As a screen network operator, you review these submissions and decide whether to approve or reject them based on your content standards and business requirements.
## CAR Lifecycle
1. **Pending**: A new CAR arrives in your queue with status `pending`. The advertiser has submitted a creative for review.
2. **Review**: You examine the creative asset, advertiser information, and targeting details.
3. **Decision**: You either approve the creative to make it eligible for delivery, or reject it with specific reasons.
4. **Active**: Approved creatives with active campaigns become candidates for ad delivery on your screens.
## CAR Object
A Creative Approval Request contains the following properties:
| Field | Type | Description |
| ------------------- | -------------- | ----------------------------------------------------------- |
| `car_id` | string | Unique CAR identifier (e.g., `car_Xy7Kp2mN9qR4`) |
| `status` | string | Current status: `pending`, `approved`, or `rejected` |
| `advertiser_name` | string | Name of the advertiser submitting the creative |
| `cities` | array | Array of city names targeted by this campaign |
| `countries` | array | Array of country codes targeted by this campaign |
| `item` | object | The creative asset object (see below) |
| `rejection_reasons` | array \| null | Array of rejection reason codes if rejected, otherwise null |
| `custom_message` | string \| null | Custom message provided during rejection, if applicable |
| `created_on` | string | ISO 8601 timestamp when CAR was created |
### Item Sub-Object
The `item` object contains details about the media asset:
| Field | Type | Description |
| ---------- | ------- | -------------------------------------------------------- |
| `url` | string | URL to the creative media file (image or video) |
| `title` | string | Creative asset name |
| `width` | integer | Width of the creative in pixels |
| `height` | integer | Height of the creative in pixels |
| `duration` | integer | Duration in seconds (0 for static images) |
| `mimeType` | string | MIME type of the asset (e.g., `video/mp4`, `image/jpeg`) |
| `size` | integer | File size in bytes |
| `md5` | string | MD5 hash of the creative file |
## Example CAR Object
```json theme={null}
{
"car_id": "car_Xy7Kp2mN9qR4",
"status": "pending",
"advertiser_name": "Acme Corporation",
"cities": ["Berlin", "Munich"],
"countries": ["DEU"],
"item": {
"url": "https://assets.example.com/creatives/acme-summer-2026.mp4",
"title": "Acme Summer Campaign",
"width": 1920,
"height": 1080,
"duration": 15,
"mimeType": "video/mp4",
"size": 2456789,
"md5": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4"
},
"rejection_reasons": null,
"custom_message": null,
"created_on": "2026-03-28T14:30:00Z"
}
```
## Active Creatives
The `cars_active` endpoint returns a filtered list of approved CARs whose campaigns are forecasted to deliver to your screens soon. This is useful for **pre-caching creative assets** to your content delivery infrastructure before ads are scheduled to run.
Use this endpoint periodically to:
* Download and cache video/image assets locally
* Validate creative quality before delivery
* Prepare your screens for upcoming ad campaigns
* Monitor active advertising campaigns in your network
## Next Steps
Explore the Creative Approval Requests API endpoints:
* [List all creatives](/api-reference/creative-approvals/list-all)
* [List active creatives](/api-reference/creative-approvals/list-active)
* [Get a creative](/api-reference/creative-approvals/get)
* [Approve a creative](/api-reference/creative-approvals/approve)
* [Reject a creative](/api-reference/creative-approvals/reject)
# Reject a Creative
Source: https://docs.framen.com/api-reference/creative-approvals/reject
POST https://api.framen.com/vendor/{org_token}/cars/{car_id}/reject
Reject a creative approval request (CAR) with one or more rejection reasons.
## Reject a Creative
Reject a creative approval request (CAR) with one or more rejection reasons. Once rejected, the advertiser is notified and can submit a revised creative.
Your organization token (e.g., `Org_4KmTqZnWpLx`). [Find it here](https://dashboard.framen.com/account/orgs).
The unique identifier of the creative approval request (e.g., `car_Xy7Kp2mN9qR4`).
Array of one or more rejection reason codes. Valid values: `ADVERTISER`, `INAPPROPRIATE`, `FILTER`, `CUSTOM`.
A custom rejection message. **Required** when `CUSTOM` is included in `rejection_reasons`.
### Rejection Reasons
| Code | Description |
| --------------- | ------------------------------------------------------- |
| `ADVERTISER` | The advertiser is not approved to run on your network |
| `INAPPROPRIATE` | The creative content is inappropriate for your venues |
| `FILTER` | The creative does not meet your content filter criteria |
| `CUSTOM` | Custom reason -- requires a `custom_message` |
### Example Request
```bash theme={null}
curl -X POST "https://api.framen.com/vendor/Org_4KmTqZnWpLx/cars/car_Xy7Kp2mN9qR4/reject"
-H "Content-Type: application/json" \
-d '{
"rejection_reasons": ["INAPPROPRIATE", "CUSTOM"],
"custom_message": "Creative contains content not suitable for family-oriented venues"
}'
```
### Example Response
```json theme={null}
{
"id": "car_Xy7Kp2mN9qR4",
"status": "rejected",
"advertiser_name": "Acme Corporation",
"campaign_name": "Summer Sale 2026",
"rejection_reasons": ["INAPPROPRIATE", "CUSTOM"],
"custom_message": "Creative contains content not suitable for family-oriented venues",
"created_at": "2026-03-28T14:30:00Z",
"updated_at": "2026-03-28T16:20:15Z"
}
```
## Error Responses
| Status | Error | Description |
| ------ | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| 400 | Bad Request | CAR is already approved or rejected; cannot reject an already-decided creative. Also returned if rejection\_reasons is missing or invalid. |
| 401 | Unauthorized | Invalid or missing org\_token |
| 404 | Not Found | CAR not found; invalid car\_id or organization does not own this CAR |
| 422 | Unprocessable Entity | CUSTOM is in rejection\_reasons but custom\_message is missing or empty |
| 429 | Too Many Requests | Rate limit exceeded; retry after delay |
| 500 | Internal Server Error | Server error; please try again later |
# Opening Hours (opening_168)
Source: https://docs.framen.com/api-reference/data-formats/opening-168
Weekly opening-hours array used when creating or updating a location.
The `opening_168` field is a JSON array of **168 integers** (one per hour of the week, starting Monday 00:00) that tells the FRAMEN platform when a location is open.
Each element is either **`1`** (open) or **`0`** (closed).
## Structure
| Index | Day | Hour |
| ----- | ------- | ----- |
| 0 | Monday | 00:00 |
| 1 | Monday | 01:00 |
| ... | ... | ... |
| 23 | Monday | 23:00 |
| 24 | Tuesday | 00:00 |
| ... | ... | ... |
| 167 | Sunday | 23:00 |
## Example
A location open Monday to Friday, 08:00 -- 20:00:
```json theme={null}
[
0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,
0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,
0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,
0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,
0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
]
```
The array must always contain exactly 168 elements. Passing fewer or more will result in a validation error.
# Daily Visitors (visitors_7)
Source: https://docs.framen.com/api-reference/data-formats/visitors-7
Weekly expected-visitors array used when creating or updating a location.
The `visitors_7` field is a JSON array of **7 integers** — one per day of the week, starting with Monday — representing the expected number of daily visitors at a location.
## Structure
| Index | Day |
| ----- | --------- |
| 0 | Monday |
| 1 | Tuesday |
| 2 | Wednesday |
| 3 | Thursday |
| 4 | Friday |
| 5 | Saturday |
| 6 | Sunday |
## Example
A café that expects roughly 200 visitors on weekdays, 350 on Saturdays, and 150 on Sundays:
```json theme={null}
[200, 200, 200, 200, 200, 350, 150]
```
The array must always contain exactly 7 elements. Passing fewer or more will result in a validation error.
# Introduction
Source: https://docs.framen.com/api-reference/introduction
Welcome to the FRAMEN Screen Manager API
## Overview
The FRAMEN Screen Manager API lets you programmatically manage your digital signage network. Use it to register physical locations, configure screens, control ad delivery, and manage creative approvals.
### Base URL
```
https://api.framen.com
```
### What you can do
* **Locations** — Create and manage physical venues where screens are installed
* **Screens** — Register and configure individual displays within locations
* **Venue Types** — Browse the classification system for your locations
* **Ad Delivery** — Request ad creatives for real-time playback on screens
* **Creatives** — Review and approve or reject creative assets before they go live
## Getting started
1. **Get your organization token** — See [Authentication](/api-reference/authentication) for how to find your `org_token`
2. **Create a location** — Register your first physical venue via [Create a location](/api-reference/locations/create)
3. **Add a screen** — Attach a screen to the location via [Create a screen](/api-reference/screens/create)
4. **Go live** — Once your location is approved, request ads via [Get Spot](/api-reference/ad-delivery/get-spot)
All API requests use your `org_token` as a path parameter. There are no additional headers or parameters required.
# Create a Location
Source: https://docs.framen.com/api-reference/locations/create
POST https://api.framen.com/vendor/{org_token}/locations
Register a new physical location in your organization.
## Create a Location
Register a new physical location in your organization. The location will initially be created with a `DRAFT` status and must be approved before screens can be deployed.
Locations go through an approval process: `DRAFT -> REVIEW -> APPROVED`. Providing all "required for Review" fields automatically moves the status to `REVIEW`. FRAMEN then performs the approval.
Your organization token (e.g., `Org_4KmTqZnWpLx`).
Your unique identifier for this location. If not provided, one will be assigned automatically.
Display name of the location.
Must be a **level 2** venue type ID from the [Venue Types](/api-reference/venue-types/list) endpoint. Required for Review.
Latitude coordinate (WGS84, range: -90 to 90). Required for Review.
Longitude coordinate (WGS84, range: -180 to 180). Required for Review.
Hourly opening schedule for one week (168 booleans). Index 0 = Monday 00:00. Required for Review.
Daily visitor counts, Monday through Sunday. Required for Review.
Whether the location is archived. Default: `false`.
Contact email for the location.
Contact phone number for the location.
### Example Request
```bash theme={null}
curl -X POST https://api.framen.com/vendor/{org_token}/locations \
-H "Content-Type: application/json" \
-d '{
"location_id": "Loc_MyCustomId123",
"title": "Berlin Hauptbahnhof",
"venue_type_id": "205",
"lat": 52.5251,
"long": 13.3694,
"opening_168": [true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false],
"visitors_7": [500, 600, 700, 800, 900, 1000, 400]
}'
```
# Get a Location
Source: https://docs.framen.com/api-reference/locations/get
GET https://api.framen.com/vendor/{org_token}/locations/{location_id}
Retrieve a single location by its ID.
## Get a Location
Retrieve a single location by its ID.
Your organization token (e.g., `Org_4KmTqZnWpLx`).
The unique identifier of the location to retrieve.
### Response
Returns the Location object with all fields populated.
### Example Request
```bash theme={null}
curl -X GET https://api.framen.com/vendor/Org_4KmTqZnWpLx/locations/Loc_f9FxuWDTfzy
```
### Example Response
```json theme={null}
{
"location_id": "Loc_f9FxuWDTfzy",
"title": "Downtown Plaza - Main Entrance",
"status": "APPROVED",
"available_for_ads": true,
"venue_type_id": "205",
"lat": 40.7128,
"long": -74.006,
"opening_168": [true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false],
"visitors_7": [500, 600, 700, 800, 900, 1000, 400],
"archived": false,
"timezone": "America/New_York",
"country": "USA",
"region": "New York",
"city": "New York",
"zip": "10001",
"address": "123 Main Street, New York, NY 10001",
"email": "contact@example.com",
"phone": "+1-555-0100"
}
```
# List Locations
Source: https://docs.framen.com/api-reference/locations/list
GET https://api.framen.com/vendor/{org_token}/locations
Retrieve all locations in your organization.
## List Locations
Retrieve all locations in your organization.
Your organization token (e.g., `Org_4KmTqZnWpLx`).
### Response
Returns an array of Location objects.
### Example Request
```bash theme={null}
curl -X GET https://api.framen.com/vendor/Org_4KmTqZnWpLx/locations
```
# Overview
Source: https://docs.framen.com/api-reference/locations/overview
Location object definition and approval workflow.
Locations are the containers for your screens. Each location represents a physical place (mall, airport, gym, office building, etc.) where one or more screens are installed. Locations hold geo-coordinates, opening hours, and visitor estimates. They go through an approval workflow before they can receive ads.
You must create a location before you can add screens to it. Screens inherit their geographic context from their parent location.
## The Location object
| Field | Type | Description |
| ------------------- | ------------- | --------------------------------------------------------------------------------------------------------- |
| `location_id` | string | Unique identifier assigned by the system |
| `title` | string | Human-readable location name |
| `status` | string | Approval status: `DRAFT`, `REVIEW`, or `APPROVED` |
| `available_for_ads` | boolean | Whether ads can be delivered to screens at this location |
| `venue_type_id` | string | Level 2 venue type ID (see [Venue Types](/api-reference/venue-types/list)) |
| `lat` | float | Latitude (-90 to 90) |
| `long` | float | Longitude (-180 to 180) |
| `opening_168` | boolean\[168] | Hourly open/closed schedule (see [Opening 168](/api-reference/data-formats/opening-168)) |
| `visitors_7` | int\[7] | Daily visitor estimates, Monday through Sunday (see [Visitors 7](/api-reference/data-formats/visitors-7)) |
| `archived` | boolean | Whether the location is hidden from the dashboard |
| `timezone` | string | IANA timezone, auto-derived from coordinates (e.g., `Europe/Berlin`) |
| `country` | string | ISO 3166-1 alpha-3 country code, auto-derived |
| `region` | string | Region or state name, auto-derived |
| `city` | string | City name, auto-derived |
| `zip` | string | Postal code, auto-derived |
| `address` | string | Street address, auto-derived |
| `email` | string | Contact email for this location |
| `phone` | string | Contact phone for this location |
The fields `timezone`, `country`, `region`, `city`, `zip`, and `address` are **read-only**. They are automatically derived from `lat` and `long`. Do not include them in create or update requests.
## Approval workflow
Locations go through a three-stage approval process:
```
DRAFT -> REVIEW -> APPROVED
```
| Status | Trigger | What it means |
| ---------- | ----------------------------------- | ------------------------------------------------------------- |
| `DRAFT` | Created without all required fields | Location is incomplete. Cannot receive ads. |
| `REVIEW` | All required fields provided | Awaiting review. Cannot receive ads yet. |
| `APPROVED` | Location is approved | Eligible for ad delivery. `available_for_ads` can now be set. |
**Fields required for REVIEW status**: `title`, `venue_type_id`, `lat`, `long`, `opening_168`, `visitors_7`.
When all of these fields are present on creation, the location skips `DRAFT` and goes directly to `REVIEW`.
Updating `venue_type_id`, `lat`, or `long` on an `APPROVED` location **resets its status to `REVIEW`**. This may temporarily disrupt ad delivery to screens at that location.
## Archiving vs. disabling ads
There are two ways to take a location out of active use:
| Action | Effect |
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `"archived": true` | Hides the location from the dashboard. Screens remain but are effectively inactive. |
| `"available_for_ads": false` | Location becomes invisible to the Ads Manager for **new** campaign targeting. Already running campaigns **continue delivering**. |
To immediately stop all ad delivery at a location, set `available_for_ads: false` on each individual [screen](/api-reference/screens/overview).
# Update a Location
Source: https://docs.framen.com/api-reference/locations/update
POST https://api.framen.com/vendor/{org_token}/locations/{location_id}
Update an existing location's details.
## Update a Location
Update an existing location's details. All body parameters are optional -- only include the fields you want to change.
Your organization token (e.g., `Org_4KmTqZnWpLx`).
The unique identifier of the location to update.
Display name of the location.
Must be a **level 2** venue type ID from the [Venue Types](/api-reference/venue-types/list) endpoint.
Latitude coordinate (WGS84, range: -90 to 90).
Longitude coordinate (WGS84, range: -180 to 180).
Hourly opening schedule for one week (168 booleans). Index 0 = Monday 00:00.
Daily visitor counts, Monday through Sunday.
Location status. Can only be changed via `DRAFT -> REVIEW`. You cannot set it to `APPROVED` yourself.
Whether the location is available for ad campaigns. Cannot be set while status is `DRAFT` or `REVIEW`.
Whether the location is archived.
Contact email for the location.
Contact phone number for the location.
If the location status is `APPROVED` and you update `venue_type_id`, `lat`, or `long`, the status will revert to `REVIEW` and must be re-approved by FRAMEN. Campaign delivery may be affected.
### Example Request
```bash theme={null}
curl -X POST https://api.framen.com/vendor/Org_4KmTqZnWpLx/locations/Loc_f9FxuWDTfzy \
-H "Content-Type: application/json" \
-d '{
"title": "Berlin Hauptbahnhof - West Wing",
"visitors_7": [600, 700, 800, 900, 1000, 1100, 500]
}'
```
# Create a Screen
Source: https://docs.framen.com/api-reference/screens/create
POST https://api.framen.com/vendor/{org_token}/screens
Register a new screen device at a location.
## Create a Screen
Register a new screen device at a location. Each screen belongs to exactly one Location.
Your organization token (e.g., `Org_4KmTqZnWpLx`).
Your unique identifier for this screen.
Display name of the screen.
Must be the same as or a child of the parent Location's `venue_type_id`. Use values from the [Venue Types](/api-reference/venue-types/list) endpoint.
Must reference an existing Location.
Pixel width of the screen (e.g., `1920`).
Pixel height of the screen (e.g., `1080`).
Loop duration in seconds.
Whether the screen is archived. Default: `false`. When `true`, the screen disappears from the Dashboard UI.
Whether the screen is available for ad campaigns. Default: `true`.
Number of physical screens this entry represents.
Estimated weekly impressions.
### Example Request
```bash theme={null}
curl -X POST https://api.framen.com/vendor/Org_4KmTqZnWpLx/screens \
-H "Content-Type: application/json" \
-d '{
"screen_id": "Scr_xYz789",
"title": "Lobby Display A",
"venue_type_id": "205",
"location_id": "Loc_f9FxuWDTfzy",
"width": 1920,
"height": 1080,
"loop_duration": 60
}'
```
# Get a Screen
Source: https://docs.framen.com/api-reference/screens/get
GET https://api.framen.com/vendor/{org_token}/screens/{screen_id}
Retrieve a single screen by its ID.
## Get a Screen
Retrieve a single screen by its ID.
Your organization token (e.g., `Org_4KmTqZnWpLx`).
The unique identifier of the screen to retrieve.
### Response
Returns the Screen object with all fields populated.
### Example Request
```bash theme={null}
curl -X GET https://api.framen.com/vendor/Org_4KmTqZnWpLx/screens/Scr_xYz789
```
### Example Response
```json theme={null}
{
"screen_id": "Scr_xYz789",
"title": "Lobby Display A",
"venue_type_id": "205",
"location_id": "Loc_f9FxuWDTfzy",
"width": 1920,
"height": 1080,
"loop_duration": 60,
"archived": false,
"available_for_ads": true,
"amount": 1,
"imps_weekly": 5000
}
```
# List Screens
Source: https://docs.framen.com/api-reference/screens/list
GET https://api.framen.com/vendor/{org_token}/screens
Retrieve all screens in your organization.
## List Screens
Retrieve all screens in your organization.
Your organization token (e.g., `Org_4KmTqZnWpLx`).
### Response
Returns an array of Screen objects.
### Example Request
```bash theme={null}
curl -X GET https://api.framen.com/vendor/Org_4KmTqZnWpLx/screens
```
# Overview
Source: https://docs.framen.com/api-reference/screens/overview
Manage individual display devices within your locations.
## Screens
Screens represent individual display devices deployed within a location. Each screen displays advertisements in a continuous loop and is identified by its unique configuration, including resolution and loop timing parameters.
### Key Concepts
* **Screen**: A physical or virtual display device that plays a sequence of ads
* **Location**: Parent location containing one or more screens
* **Loop Duration**: The total time (in seconds) for one complete rotation through all queued advertisements
* **Venue Type**: Classification that must match or be compatible with the parent location's venue type
* **Resolution**: Pixel dimensions (width x height) of the display
Before creating screens, you must first create a location. Each screen belongs to exactly one location and inherits the location's organizational context.
### Screen Object
The Screen object contains all configuration and metadata for a display device:
| Field | Type | Description |
| ------------------- | ------- | ---------------------------------------------------------------------------------------------------------- |
| `screen_id` | string | Unique identifier for the screen (client-generated, UUID format) |
| `title` | string | Human-readable label for the screen (e.g., "Main Lobby Display") |
| `venue_type_id` | string | Venue type classification (e.g., `"205"` for Malls); must match or be a child of the location's venue type |
| `location_id` | string | ID of the parent location |
| `width` | integer | Pixel width of the display resolution |
| `height` | integer | Pixel height of the display resolution |
| `loop_duration` | integer | Duration in seconds for one complete advertisement loop |
| `archived` | boolean | Whether hidden from Dashboard. Default: `false` |
| `available_for_ads` | boolean | Whether the screen accepts ad campaigns. Default: `true` |
| `amount` | integer | Number of physical screens this entry represents |
| `imps_weekly` | integer | Estimated weekly impressions |
### Example Screen Object
```json theme={null}
{
"screen_id": "d3c8dbb6-c21b-4b26-8f35-d73260c95fa1",
"title": "Main Lobby Display",
"venue_type_id": "602",
"location_id": "Loc_f9FxuWDTfzy",
"width": 1920,
"height": 1080,
"loop_duration": 120,
"archived": false,
"available_for_ads": true,
"amount": 1,
"imps_weekly": 12503
}
```
### Common Use Cases
* **Create a Screen**: Add a new display device to your location with specific resolution and timing parameters
* **Retrieve Screen Details**: Look up configuration and metadata for a specific screen
* **Update Screen Settings**: Modify display name, loop duration, or venue classification
* **List Organization Screens**: View all screens deployed across your organization
* **Manage Ad Content**: Use the screen ID to request and manage advertisements for that specific display
### Requirements
* Parent location must exist before creating screens
* Screen `venue_type_id` must be compatible with the location's venue type hierarchy
* Resolution values (width/height) must be positive integers
* Loop duration must be a positive integer representing seconds
* The client generates the `screen_id` (UUID format). Sending a duplicate returns an error.
# Update a Screen
Source: https://docs.framen.com/api-reference/screens/update
POST https://api.framen.com/vendor/{org_token}/screens/{screen_id}
Update an existing screen's details.
## Update a Screen
Update an existing screen's details. All body parameters are optional -- only include the fields you want to change.
Your organization token (e.g., `Org_4KmTqZnWpLx`).
The unique identifier of the screen to update.
Display name of the screen.
Must be the same as or a child of the parent Location's `venue_type_id`.
Must reference an existing Location.
Pixel width of the screen.
Pixel height of the screen.
Loop duration in seconds.
Whether the screen is archived.
Whether the screen is available for ad campaigns.
Number of physical screens this entry represents.
Estimated weekly impressions.
Changing `location_id` will set the Location's status to `REVIEW`, even if it was previously `APPROVED`.
### Example Request
```bash theme={null}
curl -X POST https://api.framen.com/vendor/Org_4KmTqZnWpLx/screens/Scr_xYz789 \
-H "Content-Type: application/json" \
-d '{
"title": "Lobby Display A - Updated",
"width": 3840,
"height": 2160
}'
```
# List Venue Types
Source: https://docs.framen.com/api-reference/venue-types/list
GET https://api.framen.com/vendor/{org_token}/venue_types
Retrieve all available venue types.
## List Venue Types
Retrieve all available venue types. Venue types classify locations and screens into a **3-level hierarchy**:
* **Level 1** -- Category (not selectable, e.g., "Retail")
* **Level 2** -- Venue type (selectable, e.g., "Grocery")
* **Level 3** -- Sub-venue type (selectable, e.g., "Shop Entrance (Grocery)")
The `id` values returned here are used as `venue_type_id` in both the Screens and Locations endpoints.
**Constraint:** Locations must use a level 2 `venue_type_id`. Screens must use a `venue_type_id` that is either the same as their parent Location's (level 2) or one of its children (level 3).
Your organization token (e.g., `Org_4KmTqZnWpLx`).
### Response
Returns an array of venue type objects.
| Field | Type | Description |
| ------------- | -------------- | ---------------------------------------------------------------- |
| `label` | string | Display name (e.g., "Grocery") |
| `id` | string | Venue type ID (used as `venue_type_id` in Screens and Locations) |
| `parent_id` | string \| null | ID of the parent venue type. `null` for level 1 |
| `level` | integer | `1` = category, `2` = venue type, `3` = sub-venue type |
| `selectable` | boolean | Whether this type can be assigned to a Location or Screen |
| `description` | string \| null | Human-readable description of the venue type |
### Example Request
```bash theme={null}
curl -X GET https://api.framen.com/vendor/Org_4KmTqZnWpLx/venue_types
```
### Example Response
```json theme={null}
[
{
"label": "Retail",
"id": "2",
"parent_id": null,
"level": 1,
"selectable": false,
"description": "These dynamic screens are strategically placed in key locations throughout shopping centers, malls, and retail districts."
},
{
"label": "Grocery",
"id": "203",
"parent_id": "2",
"level": 2,
"selectable": true,
"description": "Digital signage is dispersed throughout supermarkets, you'll often find screens in direct view of shoppers, above cash points, at the entrance/exit, within the shelves, in the aisles and on the walls."
},
{
"label": "Shop Entrance (Grocery)",
"id": "20301",
"parent_id": "203",
"level": 3,
"selectable": true,
"description": "As shoppers enter the supermarket, there'll usually be medium to large sized screens close to the entrance, so consumers have a prominent view of ads."
},
{
"label": "Check Out (Grocery)",
"id": "20302",
"parent_id": "203",
"level": 3,
"selectable": true,
"description": "The till areas are where consumers pay for their purchases, and here you'll find display monitors close to the bagging area or above the self-service check out points."
}
]
```
# Overview
Source: https://docs.framen.com/api-reference/venue-types/overview
Understand the three-level venue type taxonomy for classifying locations and screens.
## Venue Type Taxonomy
Venue types form a three-level hierarchical tree used for ad targeting and location classification within the FRAMEN Screen Manager API. This taxonomy allows precise targeting of ad campaigns based on where screens are physically located and their specific placement within a venue.
### Hierarchy Structure
The venue type system is organized into three distinct levels:
```
Level 1: Category (not selectable)
Level 2: Location type (assign to Locations)
Level 3: Screen placement (assign to Screens)
```
* **Level 1 (Category)**: Non-selectable organizational groups that serve as the top-level categorization. Examples include "Transit", "Retail", and "Hospitality".
* **Level 2 (Location type)**: Venue types assigned directly to Locations. These describe the general type of physical venue (e.g., "Airport", "Shopping Mall", "Hotel").
* **Level 3 (Screen placement)**: Venue types assigned to Screens. These describe the specific placement or zone within a location (e.g., "Arrival Hall", "Food Court", "Lobby").
### Assignment Rules
Different entity types can be assigned venue types at different levels according to these rules:
| Entity | Allowed levels | Rule |
| -------- | -------------- | ---------------------------------------------------------------------------- |
| Location | Level 2 only | Pick the venue type that best describes the physical place |
| Screen | Level 2 or 3 | Must be the same as the location's type (level 2) or a child of it (level 3) |
### Parent-Child Constraint
A critical validation rule ensures data integrity: **a screen's venue type must be related to its parent location's venue type via the `parent_id` field**. This means:
* If a Location is assigned venue type "Airport" (Level 2), its Screens can be assigned either "Airport" (Level 2) or children like "Arrival Hall" or "Departure Lounge" (Level 3, parent\_id = "Airport").
* Cross-branch assignments are invalid. A Screen in a "Hotel" Location cannot be assigned a venue type under the "Airport" branch.
### Venue Type Object Definition
Each venue type object contains the following fields:
* **id** (string): Unique identifier for the venue type
* **name** (string): Display name of the venue type
* **level** (integer): The hierarchical level (1, 2, or 3)
* **parent\_id** (string or null): The ID of the parent venue type; null for Level 1 categories
### Python Validation Logic
Here's an example of how to validate venue type assignments in Python:
```python theme={null}
def validate_screen_venue_type(location_venue_type, screen_venue_type, venue_types_map):
"""
Validate that a screen's venue type is compatible with its location's venue type.
Args:
location_venue_type: The venue type object assigned to the location
screen_venue_type: The venue type object to be assigned to the screen
venue_types_map: A dict mapping venue_type_id -> venue_type_object
Returns:
bool: True if valid, False otherwise
"""
# Location must be Level 2
if location_venue_type['level'] != 2:
return False
# Screen must be Level 2 or 3
if screen_venue_type['level'] not in [2, 3]:
return False
# If screen is Level 2, must match location
if screen_venue_type['level'] == 2:
return screen_venue_type['id'] == location_venue_type['id']
# If screen is Level 3, must be a child of location
if screen_venue_type['level'] == 3:
return screen_venue_type['parent_id'] == location_venue_type['id']
return False
```
### Why Venue Types Matter
Venue types are critical to the FRAMEN system because they directly impact:
* **Ad Targeting**: Advertisers use venue types to specify where their campaigns should run, ensuring ads reach the right audience in the right context.
* **Fill Rate**: Proper classification increases the likelihood that available inventory matches advertiser targeting criteria, improving fill rates and reducing unsold ad slots.
* **Revenue Optimization**: Accurate venue type assignment enables better matching between supply and demand, maximizing revenue per screen.
* **Campaign Performance**: Misclassified venues can result in poor audience targeting, wasted impressions, and advertiser dissatisfaction.
Always ensure that locations and screens are assigned the appropriate venue types according to their physical characteristics and purpose within the broader venue hierarchy.