Lucit V1 Contract API
API Documentation Version : 1.14
The Lucit system provides a public API (Application Programming Interface) for out-of-home software systems to interface with our inventory-driven creatives.
This interface is targeted at Contract based campaigns where the OOH Operator has an existing or planned client, and Lucit powers the creative stream to your player software and we provide the statistics back to the client.
This API is superceded by the V3 api in most scenarios - See https://www.lucit.cc/post/player-apps-choosing-between-lucit-v1-or-v3-api for help in choosing which one to use.
Process Overview
In its simplest form, the process works like this:
-
Your system makes a request to our API
-
We respond with an JSON Response or an XML Document containing a URI for a creative image (png or jpg)
-
Your system downloads the image, validates it, and displays it on the appropriate digital billboard
-
Your system provides proof of play by calling our analytics api with statistics
1. Requirements
-
An API Token (This API requires a Public API Token that can be created by creating a new Lucit App, and generating a new Public token - See Creating your first application and see Creating Tokens
-
An Export Id (Consider this a “Campaign Id”) (Please contact your Account Exec, or Contact Us)
-
A list of digital asset locations that we store in our system (see required fields in Digital Display Asset Inventory Template Fields)
-
An ability to consume a remote HTTPS JSON OR XML Response
-
Note, if you have specific digital displays that run on older software that does not support HTTPS, please contact us
-
2. Interface
Base URI
The base URI for the interface is:
https://pull.lucit.app/api/v1/{endPoint}/?api_token={your_api_token}
The API Interface for our contract interface provides a 4 endpoints. Either a json (default) endpoint or an XML endpoint
json: /campaigns/generic/{exportid}/pull
xml : /campaigns/generic/{exportid}/pull/xml
vast : /campaigns/generic/{exportid}/pull/vast (experimental)
html : /campaigns/generic/{exportid}/pull/html (experimental)
An example full URI to retrieve an export (Campaign) might look something like this:
Sample Export Id : lch-MYID
Display ID : YOUR_DISPLAY_ID
Sample Api Token : SomeLong60CharString
Sample Complete URI: https://pull.lucit.app/api/v1/campaigns/generic/lch-MYID/pull?api_token=SomeLong60CharString&location_id=YOUR_DISPLAY_ID
This will return a single creative image for the digital board referenced in the location_id parameter
Optionally, for pre-caching purposes, you may retrieve the complete set of available creatives for each board by passing in the parameter show_all=1
Sample URI with location id: https://pull.lucit.app/api/v1/campaigns/generic/lch-MYID/pull?api_token=SomeLong60CharString&location_id=YOUR_DISPLAY_ID&show_all=1
3. Response
The response is in either JSON (default) or XML format and will return a minimum of 1 “set” and a single “item” in that set.
Each “pull” or “refresh” of the URI may or may not return a new “item.”
JSON response
{
"lucit_layout_drive": {
"source": "Layout by Lucit",
"source_href": "https://lucit.cc/lucit-layout",
"account": "Some Company Name",
"account_id": "lch-xxx",
"layout_export_id": "lch-xxx",
"layout_export_run_id": "1234",
"generated_datetime": "2020-01-05T18:04:05+00:00",
"layout_drive_schema_version": "1.0",
"item_sets": [
{
"location_id": "XXYYZZ.A",
"location_name": "123 N 45th St, W/S, your town",
"lucit_layout_digital_board_id": "12345",
"item_count": "7",
"item_total_weight": "70,
"item_selected_index": "5",
"items": [
{
"creative_id" : "C1-4C9D-LP-4PcU",
"creative_datetime": "2020-01-02T22:43:54+00:00",
"id": "1234"
"object_class" : "InventoryPhoto",
"name": "Name Of The Creative",
"slug": "name_of_the_creative",
"src": "https://the-image-server.com/the/path/to/the_creative_image.png",
"hash" : "d41d8cd98f00b204e9800998ecf8427e",
"hash_algo" : "md5",
"width": "840",
"height": "400"
"weight": "10",
"weight_pct": "0.14",
"pingback_url" : "https://track.lucit.app/api/v1/analytics/track/lucit-drive-play/?creative_id=C1-4C9D-LP-4PcU&lucit_layout_digital_board_id=12345&play_datetime=${PLAY_DATETIME_UTC}&play_duration=${PLAY_DURATION_SECONDS}&api_token=${API_TOKEN}
}
]
}
]
}
}
XML Response
<lucit-layout-drive
source="Layout by Lucit"
source-href="https://www.lucit.cc/lucit-layout"
account="Some Company Name"
account-id="lch-xxx"
layout-export-id="lch-xxx"
layout-export-run-id="1234"
generated-datetime="2020-01-05T18:04:05+00:00"
layout-drive-schema-version="1.0">
<item-set
location-id="XXYYZZ.A"
location-name="123 N 45th St, W/S, your town"
lucit-layout-digital-board-id="12345"
item-count="7"
item-selected-index="5">
<item
creative_id="C1-4C9D-LP-4PcU"
creative-datetime="2020-01-02T22:43:54+00:00"
id="1234"
"object-class"="InventoryPhoto"
name="Name Of The Creative"
slug="name_of_the_creative"
src="https://the-image-server.com/the/path/to/the_creative_image.png" hash="d41d8cd98f00b204e9800998ecf8427e"
hash_algo="md5"
width="840"
height="400"
weight="10"
weight-pct="0.14"
pingback-url="https://track.lucit.app/api/v1/analytics/track/lucit-drive-play/?creative_id=C1-4C9D-LP-4PcU&lucit_layout_digital_board_id=12345&play_datetime=${PLAY_DATETIME_UTC}&play_duration=${PLAY_DURATION_SECONDS}&api_token=${API_TOKEN}"
/>
</item-set>
</lucit-layout-drive>
4. Element Reference
JSON RESPONSE
lucit_layout_drive | Root Element | |
---|---|---|
weight | The “weight” of this image in the set of total images | |
weight-pct | weight expressed as a fraction of 1. Typically this represents the “chance” that this image will appear in any given pull | |
pingback_url | A preformatted URI to call with the pingback (proof of play) callback. – This will contain 3 macros to substitute values for. ${PLAY_DATETIME_UTC}, ${PLAY_DURATION_SECONDS}, and ${API_TOKEN} | |
height | The height of the creative image in pixels | |
width | The width of the creative image in pixels | |
hash_algo | The algorithm used to hash the image. Currently only md5 is supported | |
hash | A hash that we generate and store when we created this image. This is a hash of the file itself that can be used to validate that the file located at src is the expected file. Image validation is optional and is recommended for player integrations that want additional layers of security | |
src | The href to the actual image – Typically this is a png or jpg – See Lucit Creative Spec Guaranteed to be unique – If id changes, the src will change | |
slug | Machine readable version of the name. URL safe, no spaces, no special chars – NOT Guaranteed to be unique | |
name | Human readable name for this creative, typically descriptive of it’s contents | |
object_class | Internal class for this image | |
id | Internal ID number for this creative image | |
creative_datetime | Date/Time that this specific image was generated (pieced together from the template and inventory assets) | |
creative_id | This is the unique ID you will use to record a play with our analytics track interface – Guaranteed to be unique If id changes, the src will change | |
item | Represents an individual creative | |
item_selected_index | The zero-based index number of the item in the set that has been selected for display. This number is between zero and item_count-1 | |
item_count | Total Number of items that are available in this set | |
lucit_layout_digital_board_id | Internal ID number (integer) that represents the specific location_id/location_name | |
location_name | Typically a geographical name identifying this billboard location – Usually a street name and city/state with additional info | |
layout_drive_schema_version | Internal version number of this format (future API changes may come with new format schemas)
| |
<item-set> | Represents a “set” of creatives logically grouped together by their display . Most exports will contain just 1 set | |
location_id | Vendor specific digital display ID that matches end-system. To filter results for JUST a single display id, specify the location_id=xxx parameter in the query string params | |
Source | Name of Source - Usually "Layout by Lucit" | |
source_href | Link to source description | |
account | account_id | |
account_id | Internal ID number for Lucit Client | |
layout_export_id | Internal ID number for the Lucit Export | |
generated_datetime | Date/Time that this data was generated. This is the datetime when @layout_export_run_id actually ran |
XML RESPONSE
< lucit-layout-drive > | Root Element | |
---|---|---|
@pingback-url | A preformatted URI to call with the pingback (proof of play) callback. – This will contain 3 macros to substitute values for. ${PLAY_DATETIME_UTC}, ${PLAY_DURATION_SECONDS}, and ${API_TOKEN} | |
@account | Name of Internal Lucit client | |
@account-id | Internal ID number for Lucit Client | |
@layout-export-id | Internal ID number for the Lucit Export | |
@layout-export-run-id | Internal ID number representing the last time this data was generated | |
@generated-datetime | Date/Time that this data was generated. This is the datetime when @layout-export-run-id actually ran | |
@layout-drive-schema-version | Internal version number of this format (future API changes may come with new format schemas) | |
<item-set> | Represents a “set” of creatives logically grouped together by their display. Most exports will contain just 1 set | |
@location-id | Vendor specific digital board ID that matches end-system. To filter results for JUST a single board id, specify the location_id=xxx parameter in the query string params | |
@location-name | Typically a geographical name identifying this billboard location – Usually a street name and city/state with additional info | |
@lucit-layout-digital-board-id | Internal ID number (integer) that represents the specific location-id/location-name | |
@item-count | Total Number of items that are available in this set | |
@item-selected-index | The zero-based index number of the item in the set that has been selected for display. This number is between zero and @item-count-1 | |
<item> | Represents an individual creative | |
@creative-id | This is the unique ID you will use to record a play with our analytics track interface – Guaranteed to be unique If id changes, the src will change | |
@creative-datetime | Date/Time that this specific image was generated (pieced together from the template and inventory assets) | |
@id | Internal ID number for this creative image | |
@name | Human readable name for this creative, typically descriptive of it’s contents | |
@slug | Machine readable version of the @name. URL safe, no spaces, no special chars – NOT Guaranteed to be unique | |
@src | The href to the actual image – Typically this is a png or jpg – See Lucit Creative Spec Guaranteed to be unique – If @id changes, the @src will change | |
@hash | A hash that we generate and store when we created this image. This is a hash of the file itself that can be used to validate that the file located at src is the expected file. Image validation is optional and is recommended for player integrations that want additional layers of security | |
@hash_algo | The algorithm used to hash the image. Currently only md5 is supported | |
@width | The width of the creative image in pixels | |
@height | The height of the creative image in pixels | |
@weight | The “weight” of this image in the set of total images | |
@weight-pct | @weight expressed as a fraction of 1. Typically this represents the “chance” that this image will appear in any given pull | |
@source-href | Link to source description | |
@source | Name of Source – Usually “Layout by Lucit” | |
<lucit-layout-drive> | Root Element |
5. Considerations
A few important considerations:
-
The “Puller” is always only displaying ONE out of “XXX” potential creative images. EACH REFRESH of the Puller may produce a new image. These numbers are represented by @item-count, @item-selected-index, @weight, @weight-pct (See definitions above)
-
@item-selected-index is zero-based, so, if @item-count=n, you can expect @item-selected-index to be any number between 0 and (n-1). For example, if there are 5 creatives and the system randomly selects the 3rd creative in the set, @item-count=5 and @item-selected-index=2
-
The @generated-datetime will change with EVERY Export run (The @layout-export-run-id will change as well)
-
Typically a new export is generated HOURLY, however, clients may force an update at any time with new rules / data / creatives
6. Validation & Security
With each creative image, our system generates a validation hash using the indicated algorithm. This hash is generated when we generate the creative and is provided as part of this API as a way to allow player software to validate image data.
In a typical implementation :
-
Fetch the image located at src
-
Compute the “hash” of the image using hash_algo (typically md5)
-
Compare this hash to the value provided in the hash field
-
If these values match, this image is the same as what the Lucit API is providing a reference to
-
If these values do not match then the image you retrieved has been modified since we generated it.
(For an example implementation, see the Lucit Library located at https://github.com/lucit-cc/lucit-layout-drive-api
7. Caching
DON’T CACHE : The Response. The Response will/may change on every pull.
DO CACHE: The images. Please use “creative_id” of the “item” element as a key to cache the “src” of the image. The “creative_id” is guaranteed to be unique to each creative image
8. Exceptions
If the server is available and the API is functioning, exceptions will returned with HTTP status codes and appropriate error
{"ok":false,"http_code":xxx,"code":"internal_error_code_string","message":"Invalid or Missing Parameters"}
The error XML format is as follows
<lucit-layout-error
http-code="XXX"
internal-code="internal_error_code_string"
message="Error Message"/>
Please note the following error codes that are available:
Code | HTTP Status | Description |
---|---|---|
token_invalid_or_unauthorized | 401 | You have provided an invalid token, it is missing, or the token is not authorized to view this resource |
export_puller_not_authorized | 401 | Your account does not have permission to pull exports via this api |
export_not_authorized | 401 | Your account does not have permission to view this specific campaign |
export_id_not_found | 422 | The export id is invalid, does not exist, cannot be found, or has been deleted |
export_pull_not_supported | 422 | This export does not support being pulled via this api endpoint |
export_puller_uncaught_error | 422 | Some other uncaught error has occurred – Please review the message |
export_puller_no_data | 422 | This export exists, however, there is no data, or, there are no creatives available |
invalid_location_id | 422 | The location_id parameter is invalid or, this location could not be attached to this campaign |
204 | (No Content Response) – Usually presented when a new location_id was encountered. This indicates that there are no creatives yet for this location, but, the system is currently generating them. Check back. | |
export_json_format_not_supported | 422 | This export does not support JSON via the puller |
export_xml_format_not_supported | 422 | This export does not support XML via the puller |
export_puller_factory_uncaught_error | 422 | Some other uncaught error has occurred – Please review the message |
Note that there may be more types of error codes than this. Also, you may receive other HTTP status codes in the event of server issues, network issues, etc. Please consult the HTTP Status Code documentation handler for your implementation.
9. Play Impression Recording
In order to provide Lucit Analytics with play information/statistics and proof of performance. Your system can ping our analytics system.
In order to record a single play impression via the pingback interface:
Base URI
The base URI for the interface is:
https://pull.lucit.app/api/v1/{endPoint}/?api_token={your_api_token}
Endpoint for Pingback
/analytics/track/lucit-drive-play
This endpoints expects the following parameters:
creative_id (string creative_id, or string item/@creative-id from xml)
play_datetime (datetime of play, ISO8601 Format with timezone info, e.g. 2020-01-12T14:20:01-0600)
lucit_layout_digital_board_id (string lucit_layout_digital_board_id, or string item-set/@lucit-layout-digital-board-id from xml,)
play_duration (optional – int seconds) - Will default to the digital board default play length per slot
impressions (optional – int count) - Will default to the avg impressions per play stored on the board
api_token (your api token)
This URL is provided for you for each creative via the pingback_url parameter –
This will contain 3 macros to substitute values for. ${PLAY_DATETIME_UTC}, ${PLAY_DURATION_SECONDS}, and ${API_TOKEN}
10. Play Impression PingBack Response
This endpoint will respond with a json response on success an HTTP Status Code 200
{"ok" : true}
On Failure, you will receive an appropriate error message and the HTTP status code will be an error code
{"ok":false,"http_code":422,"code":"invalid_parameters","message":"Invalid or Missing Parameters","data":{"item_id":["The item id field is required."]}}
More Information
Change Log
Version 1.1 – 6/15/2020
-
Changed domain name to lucit.cc
Version 1.2 6/24/2020
-
Added location_id as a parameter to the pull URI
Version 1.3 7/21/2020
-
Added show_all as a parameter to the pull URI
https://pull.lucit.app/api/v1/campaigns/generic/{id}/pull/xml?api_token=SomeLong60CharString&show_all=1
Version 1.4 7/22/2020
-
The pull endpoint now supports a (default) JSON response :
https://pull.lucit.app/api/v1/campaigns/generic/{id}/pull/?api_token=SomeLong60CharString
-
layout-drive-xml-schema-version renamed to layout-drive-schema-version
-
Added link to github library https://github.com/lucit-cc/lucit-layout-drive-api
Version 1.5 8/21/2020
-
Addition of the creative_id and @creative-id identifiers to uniquely identify a creative (replaces @id)
-
Added new replacement endpoint for tracking analytics /analytics/track/lucit-drive-play
-
Deprecated the old pingback endpoint
Version 1.6 9/3/2020
-
Fixed type in JSON response for creative_id
Version 1.7 10/12/2020
-
Began removing references to old “Drive” verbiage and replacing where appropriate with “Contract”
-
Updated a few references to “Exports” with additional “Campaign” type verbiage
Version 1.8 11/17/2020
-
Added pingback_url as a parameter with a partially constructed url for pingbacks
Version 1.9 1/22/2021
-
Added hash field to items
-
Added hash_algo field to items
-
Added new section on image validation
Version 1.10 2/12/2021
-
Removed some references to the Layout brand
Version 1.11 11/4/2021
-
Added new error code for export_puller_no_data
-
Added new error code for invalid_location_id
Version 1.12 03/08/2022
-
Changed DNS name from old endpoints to new pull.lucit.app and track.lucit.app
Version 1.13 12/06/2024
-
Added references to the vast and html endpoints
Version 1.14 5/20/25
-
Added documentation for the impressions parameter on the playback reporting endpoint