Programmatic EngineAPI All connections

Partner API

Live · Version 1.0.0

Base URL

https://accounting.programmatic-engine.com · Main host. Every path starts with your partner path, written {partner}.

https://accounting.programmatic-engine.ru · Mirror host. It serves the same data from the same system, so use it when the main host is not reachable from your network.

Authentication

Bearer token in the Authorization header

The API key we issued to you. Send it as Authorization Bearer followed by the key.

Spec file
partner-api.yaml

Import into Postman: File → Import → paste the URL.

Overview

This API is for partners that buy screen time on the Programmatic Engine network. It covers four jobs:

  • find out which screens you can buy (GET /{partner}/inventory),
  • upload a creative and check whether it was approved (POST /{partner}/video, GET /{partner}/moderated),
  • check your account and the current server time (GET /{partner}/me),
  • download the plays you will be billed for (GET /{partner}/reconciliation/impressions).

The network sells screen time through real-time bidding only. There is no endpoint for booking a campaign, a date range or a fixed number of plays. When a screen is about to play a slot, the network asks every partner assigned to that screen for a bid. The request that carries the slot, and the answer you send back, are described on the Bid protocol page. This API only prepares and settles that exchange.

A typical integration order:

  1. Call /me to confirm that your key works.
  2. Call /inventory and store the screens you want to bid on.
  3. Upload each creative with /video. Keep the id and your own external_id.
  4. Poll /moderated until the creative reaches confirmed.
  5. Answer bid requests (see the Bid protocol page) with the external_id of a confirmed creative.
  6. Pull /reconciliation/impressions every day and compare it with your own records.

Access

We issue one API key per partner when you are onboarded. We also tell you your partner path, the first segment of every URL. In this document it is written as {partner} and the examples use acme.

Send the key in the Authorization header on every call:

Authorization: Bearer <your key>

Keys are sent over HTTPS only. Anyone who holds your key can read your inventory and upload creatives in your name, so keep it on your servers. If a key leaks, ask us to replace it. A key stays valid until we replace it.

The key and the path belong together. A key does not work under another partner's path. A missing, wrong or empty key returns 401 with the header WWW-Authenticate: Bearer. A partner only ever sees its own screens, creatives and plays.

Call GET /{partner}/me first. It confirms the key, shows how many screens are assigned to you and returns the server clock, which helps when you compare timestamps.

Time and identifiers

Times in query parameters and request bodies are read as UTC unless the value carries an offset such as +04:00. date_start, date_end, date_from and date_to accept 2026-10-08, 2026-10-08 10:00:00 and 2026-10-08T10:00:00Z. A date without a time means the start of that day in date_from and the end of that day in date_to.

Times in responses are Unix seconds (start_time, end_time) or ISO 8601 UTC (server_time). Bid requests use milliseconds, see the Bid protocol page.

Four identifiers are in use. Keep them apart:

Name Where it comes from Where you use it
id Assigned by us when you upload a creative. An integer. ids[] in /moderated; video_id in /reconciliation/impressions.
external_id Chosen by you. Up to 64 characters. Returned by us in upload and reconciliation. In a bid, you send it back as video_id.
request_id Created per bid request. In a bid you echo it back. It is the key of a play in reconciliation.
gid The screen. An integer. In inventory it is gid. In reconciliation it is side_gid. In a bid request it is screen.gid, as a string.

gid is the same number everywhere. Screen 173 in inventory is side_gid 173 in reconciliation and "173" in the bid request.

Creative lifecycle

Every creative has one status. The status changes as we download, check and moderate the file.

Status Meaning Can win a bid Billed
new Accepted. The download from url is queued. no no
loaded File downloaded. no no
checking The file is being inspected. no no
checked Inspected. A moderator must confirm the target screens. Skipped when you upload with gid or gids. no no
waiting Queued for conversion. no no
decode Being converted for the players. no no
accepted Converted. Waiting for the technical and legal review by a moderator. no no
confirmed Approved. yes yes
rejected A moderator refused it. comment holds the reason. no no
failed Download or inspection failed. comment holds the reason, which can be in Russian. no no
archived Removed from circulation. no no

Only confirmed creatives can win a bid, and only a confirmed creative that was played and verified shows up in reconciliation. A creative can leave confirmed, for example when a moderator rejects it later. Poll /moderated and stop bidding with it when it does.

Approval is a manual step by our moderators. There is no fixed time for it. rejected and failed are final. Upload a corrected file as a new creative with a new external_id.

A creative can only win on screens it is assigned to. The assignment is made at upload through gid, gids or operator, and confirmed by a moderator.

Limits

What Limit
Requests per partner key 300 per minute. The minute starts with the first request and the counter resets 60 seconds later. Over the limit the API returns 429. A second cap of 600 requests per minute applies to each client IP address, whatever keys it sends.
Reconciliation window 3 days per call. A longer window is cut short and reported in errors.
ids[] in /moderated 1024 values.
gids in /video 1024 values.
file_url in /video 5 URLs, each up to 191 characters.
shot_second in /video 16 values, each 0 to 32767.
url, title, video_md5 191 characters.
external_id, video_id, operator 64 characters.
width, height 0 to 32767.

/inventory, /moderated and /reconciliation/impressions do not paginate. They return everything that matches in one response.

Errors

Every error has the same body:

{"status": "error", "error_message": "Unauthorized"}
HTTP status When
400 A field has the wrong type or value. error_message names the field, for example Value error in gids: One or more values are not available.
401 The key is missing, wrong or empty. The response carries WWW-Authenticate: Bearer.
429 More than 300 requests per key, or 600 per IP address, in a minute. The response carries Retry-After (seconds) and X-RateLimit-Limit. Successful responses carry X-RateLimit-Limit and X-RateLimit-Remaining.
500 Something failed on our side. error_message is always Internal Server Error. Repeat later and write to us if it persists.

The API never returns 422. Unknown fields in a request body are ignored without a warning, so a misspelled field name does not fail the call. The field is then missing. Empty strings are treated as if the field was not sent.

Two cases return 200 although the call did not do what you meant. Read the response, not only the status code:

  • /reconciliation/impressions without unique_id or both dates returns an empty list and a message in errors.
  • /reconciliation/impressions with a window longer than 3 days returns only the first days and a message in errors.

Versioning

This is version 1.0.0. We make additive changes only: new endpoints, new optional parameters and new fields in responses. We do not rename or remove fields, and we do not change their meaning without a new path.

Read response fields by name, never by position, and ignore fields you do not know. Unknown request fields are ignored by us in the same way. Changes are announced to the technical contact of each partner before they go live.

Account

Check your key and read the server clock.

GET/{partner}/me

Check your key and account#

Returns the partner path and name, the number of screens assigned to you, the request limit and the server time. Use it as the first call after you receive a key, and as a health check.

The response never contains keys or other secrets.

Parameters

NameInTypeRequiredDescriptionExample
partner path string yes

Your partner path, assigned by us at onboarding.

acme

Responses

200

The key is valid.

HeaderTypeDescriptionExample
X-RateLimit-Limitinteger

Requests allowed per minute for your key.

300
X-RateLimit-Remaininginteger

Requests left in the current minute.

299
Response fields
FieldTypeDescriptionExample
partnerrequired string

The partner path of this request.

acme
namerequired string

The internal account name. It can differ from the partner path.

acme
screensrequired integer

Number of screens assigned to you. It equals the length of the inventory list.

42
rate_limit_per_minuterequired integer

Requests per minute allowed for your key.

300
server_timerequired string (date-time)

Current server time in UTC, ISO 8601 with a trailing Z.

2026-10-09T14:03:11Z
{
    "partner": "acme",
    "name": "acme",
    "screens": 42,
    "rate_limit_per_minute": 300,
    "server_time": "2026-10-09T14:03:11Z"
}
401

The key is missing, wrong or empty.

HeaderTypeDescriptionExample
WWW-Authenticatestring

Always Bearer.

Bearer
Response fields
FieldTypeDescriptionExample
statusrequired string one of: error

Always error.

error
error_messagerequired string

What went wrong. For 400 it names the field. The wording may be refined over time, so do not match on the full text.

Value error in gids: One or more values are not available.
{
    "status": "error",
    "error_message": "Unauthorized"
}
429

More than 300 requests in the last minute for this key. Wait for the number of seconds in Retry-After.

HeaderTypeDescriptionExample
Retry-Afterinteger

Seconds to wait before the next call.

42
X-RateLimit-Limitinteger

Requests allowed per minute for your key.

300
Response fields
FieldTypeDescriptionExample
statusrequired string one of: error

Always error.

error
error_messagerequired string

What went wrong. For 400 it names the field. The wording may be refined over time, so do not match on the full text.

Value error in gids: One or more values are not available.
{
    "status": "error",
    "error_message": "Too many requests"
}

Example request

curl 'https://accounting.programmatic-engine.com/acme/me' \
  -H "Authorization: Bearer $API_KEY"

Inventory

The screens you can bid on.

GET/{partner}/inventory

List your screens#

Returns every screen assigned to you. The call takes no filters and does not paginate.

The list holds screens as they are configured, not as they are online. It does not say whether a screen is playing right now, and it includes screens that we have blocked. No bid requests are sent for a blocked screen. A screen added to your account appears here on the next call, so read the list again from time to time instead of caching it for good.

There is no price information. Floor prices are not published through this API.

Parameters

NameInTypeRequiredDescriptionExample
partner path string yes

Your partner path, assigned by us at onboarding.

acme

Responses

200

All screens assigned to the partner. The list is empty when none are assigned.

HeaderTypeDescriptionExample
X-RateLimit-Limitinteger

Requests allowed per minute for your key.

300
X-RateLimit-Remaininginteger

Requests left in the current minute.

299
Response fields
FieldTypeDescriptionExample
itemsrequired object[]

One entry per screen.

items[].gidrequired integer

Screen id. Use it as gid in uploads, as side_gid in reconciliation and as screen.gid in bid requests.

173
items[].faceoptional string | null

Face or side of the structure, as entered by the screen owner.

A
items[].namerequired string

Display name of the screen.

Dubai Marina Walk, west entrance
items[].playeridrequired integer

The same value as gid. Kept for older integrations.

173
items[].photooptional string | null (uri)

Address of a photo of the screen, or null.

https://accounting.programmatic-engine.com/storage/players/173.jpg
items[].durationoptional integer | null

Length of one slot in seconds. Null when the owner has not set it. Then the bid request carries duration_ms as null.

10
items[].cityoptional string | null

City.

Dubai
items[].addressoptional string | null

Street address.

Marina Walk 12
items[].typeoptional string | null

Screen type as entered by the screen owner. It is free text, not a fixed list.

Citylight
items[].formatrequired string

Resolution as width and height in pixels, written WIDTHxHEIGHT.

1080x1920
items[].dimensionsoptional string | null

Aspect ratio as entered by the screen owner, written WxH.

9x16
items[].latoptional number | null

Latitude in degrees. Stored with single precision, so expect about seven significant digits and rounding noise.

25.0805
items[].lonoptional number | null

Longitude in degrees. Same precision as lat.

55.1403
items[].indoorrequired boolean

True for an indoor screen. False for outdoor and for screens where the owner did not set a placement.

false
items[].creative_formatrequired string[]

Accepted file formats, each as container[;codec];WIDTHxHEIGHT. Video entries come first, then image formats such as jpeg and png.

{
    "items": [
        {
            "gid": 173,
            "face": "A",
            "name": "Dubai Marina Walk, west entrance",
            "playerid": 173,
            "photo": "https://accounting.programmatic-engine.com/storage/players/173.jpg",
            "duration": 10,
            "city": "Dubai",
            "address": "Marina Walk 12",
            "type": "Citylight",
            "format": "1080x1920",
            "dimensions": "9x16",
            "lat": 25.0805,
            "lon": 55.1403,
            "indoor": false,
            "creative_format": ["mp4;h264;1080x1920", "jpeg;1080x1920"]
        }
    ]
}
401

The key is missing, wrong or empty.

HeaderTypeDescriptionExample
WWW-Authenticatestring

Always Bearer.

Bearer
Response fields
FieldTypeDescriptionExample
statusrequired string one of: error

Always error.

error
error_messagerequired string

What went wrong. For 400 it names the field. The wording may be refined over time, so do not match on the full text.

Value error in gids: One or more values are not available.
{
    "status": "error",
    "error_message": "Unauthorized"
}
429

More than 300 requests in the last minute for this key. Wait for the number of seconds in Retry-After.

HeaderTypeDescriptionExample
Retry-Afterinteger

Seconds to wait before the next call.

42
X-RateLimit-Limitinteger

Requests allowed per minute for your key.

300
Response fields
FieldTypeDescriptionExample
statusrequired string one of: error

Always error.

error
error_messagerequired string

What went wrong. For 400 it names the field. The wording may be refined over time, so do not match on the full text.

Value error in gids: One or more values are not available.
{
    "status": "error",
    "error_message": "Too many requests"
}

Example request

curl 'https://accounting.programmatic-engine.com/acme/inventory' \
  -H "Authorization: Bearer $API_KEY"

Creatives

Upload creatives and follow their moderation status.

POST/{partner}/video

Upload a creative for moderation#

Registers a creative. Send the address of the file in url. The file itself is not part of this request: we download it later, so the address must be reachable from the internet without a login for as long as the creative is in review.

The call returns at once with status new. It does not wait for the download or the moderation. Use GET /{partner}/moderated to follow the status.

Name the screens with gid (one screen) or gids (up to 1024 screens), or name a network with operator, or both. At least one is required. All screens must be assigned to you, and without operator they must belong to one network. With gid or gids the screens are approved at upload and the creative skips the checked step. With operator alone the creative is assigned to all your screens of that network and a moderator confirms the screens. The network name is given to you at onboarding and also appears as operator in reconciliation.

video_id (preferred) or external_id is stored as the creative's external_id. If both are sent, video_id wins. If neither is sent, we use the current Unix time in seconds, which is not unique when you upload several creatives in the same second. The external_id is not checked for duplicates. If you reuse one, both creatives exist, and a bid that names it can resolve to either of them. Use a new external_id for every upload.

Always send url. If the field is missing, the call still succeeds, but the creative ends in failed when the download is attempted. An empty url is rejected with 400.

date_start and date_end are stored with the creative for the moderators. A creative is not stopped at its date_end. To stop a creative, stop bidding with it.

The body must be JSON (Content-Type: application/json). A body that is not valid JSON is read as empty and returns the operator and gids error.

Parameters

NameInTypeRequiredDescriptionExample
partner path string yes

Your partner path, assigned by us at onboarding.

acme

Request body · application/json

FieldTypeDescriptionExample
urlrequired string (uri)maxLength 191

Public address of the file. We download it after the call returns.

https://cdn.example.com/acme/spring_2026_001.mp4
video_idoptional stringmaxLength 64

Your identifier of the creative. Stored as external_id. Preferred over external_id.

spring_2026_001
external_idoptional stringmaxLength 64

Alternative name for video_id. Ignored when video_id is sent.

spring_2026_001
titleoptional stringmaxLength 191

A name that moderators see.

Spring campaign, 10 s
video_md5optional stringmaxLength 191

MD5 checksum of the file, in hexadecimal. It is stored with the creative.

5d41402abc4b2a76b9719d911017c592
operatoroptional stringmaxLength 64

Network name. Use it to target all your screens in one network. Given to you at onboarding.

marina-network
gidoptional integer

One screen id. When sent, it is used instead of gids.

173
gidsoptional integer[]maxItems 1024

Screen ids from inventory. All must be assigned to you.

date_startoptional string

Start of the campaign, UTC unless an offset is given. Stored for the moderators. The zero date 0000-00-00 00:00:00 is read as not set.

2026-10-10 00:00:00
date_endoptional string

End of the campaign, UTC unless an offset is given. Stored for the moderators. The zero date 0000-00-00 00:00:00 is read as not set.

2026-10-31 23:59:59
widthoptional integermin 0 · max 32767

Width of the creative in pixels.

1080
heightoptional integermin 0 · max 32767

Height of the creative in pixels.

1920
durationoptional number

Length of the creative in seconds, as you declare it. We also inspect the file.

10
shot_secondoptional integer[]maxItems 16

Seconds from the start of the creative at which the camera takes a proof-of-play photo. Up to 16 values.

file_urloptional string[]maxItems 5

Addresses of additional files that belong to the creative. We download and store them. A single string is accepted as a list of one.

{
    "url": "https://cdn.example.com/acme/spring_2026_001.mp4",
    "video_id": "spring_2026_001",
    "title": "Spring campaign, 10 s",
    "video_md5": "5d41402abc4b2a76b9719d911017c592",
    "gids": [173, 174],
    "date_start": "2026-10-10 00:00:00",
    "date_end": "2026-10-31 23:59:59",
    "width": 1080,
    "height": 1920,
    "duration": 10,
    "shot_second": [3]
}

Responses

200

The creative was registered. The status is new. The response code is 200, not 201.

HeaderTypeDescriptionExample
X-RateLimit-Limitinteger

Requests allowed per minute for your key.

300
X-RateLimit-Remaininginteger

Requests left in the current minute.

299
Response fields
FieldTypeDescriptionExample
idrequired integer

Our identifier of the creative. Use it in ids[] of the status call.

1234
external_idrequired string

Your identifier, as stored.

spring_2026_001
operator_idrequired integer

Our numeric id of the network that owns the target screens.

7
statusrequired string

The status right after upload. Always new.

new
commentrequired string

Empty after upload.

successrequired boolean

Always true in a 200 response.

true
{
    "id": 1234,
    "external_id": "spring_2026_001",
    "operator_id": 7,
    "status": "new",
    "comment": "",
    "success": true
}
400

A field is invalid, or the screens cannot be used.

Response fields
FieldTypeDescriptionExample
statusrequired string one of: error

Always error.

error
error_messagerequired string

What went wrong. For 400 it names the field. The wording may be refined over time, so do not match on the full text.

Value error in gids: One or more values are not available.
{
    "status": "error",
    "error_message": "Value error: Undefined value in \"operator\" and \"gids\"."
}
401

The key is missing, wrong or empty.

HeaderTypeDescriptionExample
WWW-Authenticatestring

Always Bearer.

Bearer
Response fields
FieldTypeDescriptionExample
statusrequired string one of: error

Always error.

error
error_messagerequired string

What went wrong. For 400 it names the field. The wording may be refined over time, so do not match on the full text.

Value error in gids: One or more values are not available.
{
    "status": "error",
    "error_message": "Unauthorized"
}
429

More than 300 requests in the last minute for this key. Wait for the number of seconds in Retry-After.

HeaderTypeDescriptionExample
Retry-Afterinteger

Seconds to wait before the next call.

42
X-RateLimit-Limitinteger

Requests allowed per minute for your key.

300
Response fields
FieldTypeDescriptionExample
statusrequired string one of: error

Always error.

error
error_messagerequired string

What went wrong. For 400 it names the field. The wording may be refined over time, so do not match on the full text.

Value error in gids: One or more values are not available.
{
    "status": "error",
    "error_message": "Too many requests"
}

Example request

curl -X POST 'https://accounting.programmatic-engine.com/acme/video' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
    "url": "https://cdn.example.com/acme/spring_2026_001.mp4",
    "video_id": "spring_2026_001",
    "title": "Spring campaign, 10 s",
    "video_md5": "5d41402abc4b2a76b9719d911017c592",
    "gids": [
        173,
        174
    ],
    "date_start": "2026-10-10 00:00:00",
    "date_end": "2026-10-31 23:59:59",
    "width": 1080,
    "height": 1920,
    "duration": 10,
    "shot_second": [
        3
    ]
}'
GET/{partner}/moderated

Check the status of your creatives#

Returns the status of creatives you uploaded. Pass the id values from the upload responses in ids[].

Without ids[] the call returns every creative of yours, including rejected, failed and archived ones, in one unpaginated response. That list grows over time. Ask for the ids you are waiting for.

An id that does not exist, or belongs to another partner, is left out of the answer. The call still returns 200. Compare the ids you sent with the ids you got back.

comment is filled only for rejected and failed. For other statuses it is an empty string. The text is written by a moderator or by our checks and can be in Russian.

The answer holds id and status, not your external_id. Keep the mapping from id to external_id on your side, or read it from the upload response.

Parameters

NameInTypeRequiredDescriptionExample
partner path string yes

Your partner path, assigned by us at onboarding.

acme
ids[] query integermin 1 no

Creative ids to look up, as returned by the upload call. Repeat the parameter for each id, as in ids[]=1234&ids[]=1235. Digits only, at most 1024 values. A single ids=1234 without brackets returns 400.

[1234,1235]

Responses

200

The statuses of the creatives that were found.

HeaderTypeDescriptionExample
X-RateLimit-Limitinteger

Requests allowed per minute for your key.

300
X-RateLimit-Remaininginteger

Requests left in the current minute.

299
Response fields
FieldTypeDescriptionExample
itemsrequired object[]

One entry per creative found.

items[].idrequired integer

Our identifier of the creative.

1234
items[].commentrequired string

Reason text for rejected and failed. Empty for every other status.

Resolution does not match the screen
items[].statusrequired string one of: new, loaded, checking, checked, waiting, decode, accepted, confirmed, rejected, failed, archived

Current status. See Creative lifecycle for the meaning of each value.

confirmed
{
    "items": [
        {
            "id": 1234,
            "comment": "",
            "status": "confirmed"
        },
        {
            "id": 1235,
            "comment": "Resolution does not match the screen",
            "status": "rejected"
        }
    ]
}
400

The ids are malformed.

Response fields
FieldTypeDescriptionExample
statusrequired string one of: error

Always error.

error
error_messagerequired string

What went wrong. For 400 it names the field. The wording may be refined over time, so do not match on the full text.

Value error in gids: One or more values are not available.
{
    "status": "error",
    "error_message": "Type error in ids.0: Invalid number."
}
401

The key is missing, wrong or empty.

HeaderTypeDescriptionExample
WWW-Authenticatestring

Always Bearer.

Bearer
Response fields
FieldTypeDescriptionExample
statusrequired string one of: error

Always error.

error
error_messagerequired string

What went wrong. For 400 it names the field. The wording may be refined over time, so do not match on the full text.

Value error in gids: One or more values are not available.
{
    "status": "error",
    "error_message": "Unauthorized"
}
429

More than 300 requests in the last minute for this key. Wait for the number of seconds in Retry-After.

HeaderTypeDescriptionExample
Retry-Afterinteger

Seconds to wait before the next call.

42
X-RateLimit-Limitinteger

Requests allowed per minute for your key.

300
Response fields
FieldTypeDescriptionExample
statusrequired string one of: error

Always error.

error
error_messagerequired string

What went wrong. For 400 it names the field. The wording may be refined over time, so do not match on the full text.

Value error in gids: One or more values are not available.
{
    "status": "error",
    "error_message": "Too many requests"
}

Example request

curl 'https://accounting.programmatic-engine.com/acme/moderated' \
  -H "Authorization: Bearer $API_KEY"

Reconciliation

The plays you are billed for.

GET/{partner}/reconciliation/impressions

List the plays you are billed for#

Returns the plays that count for billing: bids of yours that won, were played on the screen and were verified. One row is one play.

A play is verified after the player reports the playback and the network has called the nurl that you returned in your bid. If that call to you failed, the play is not in this list and is not billed. The call is made once and is not repeated. See the Bid protocol page.

Send either unique_id (the request_id of the bids you want) or both date_from and date_to. If you send neither, the call returns 200 with no rows and a message in errors. If you send both kinds of filter, both apply.

The window is at most 3 days per call. If date_to is more than 3 days after date_from, the API does not fail. It silently replaces date_to with the day that is 3 days after date_from (date only, so that whole day is included), returns what it finds and adds Максимальный интервал между датами: 3 дней to errors. Always check errors in the response, and request one day or one hour at a time for large networks.

A search by date lists a play only after it has been matched with the playback log of the player, which usually takes a few hours. A search by unique_id does not wait for that match.

operator limits the result to the screens of one network or several networks. side_gid (or player_id, the same value) limits it to screens. Pass arrays as side_gid[]=173&side_gid[]=174. An unknown operator returns an empty list.

start_time and end_time are Unix seconds. They come from the player's playback log. end_time is null when the duration is unknown. When you search by unique_id alone, start_time can also be null if no playback record was matched.

price is the price you bid, unchanged, as a string with two decimals. The currency is the one in your contract, the API has no currency field.

A malformed date_from or date_to currently returns 500, not 400. Send valid dates.

Parameters

NameInTypeRequiredDescriptionExample
partner path string yes

Your partner path, assigned by us at onboarding.

acme
date_from query string no

Start of the period, UTC. A date without time means the start of that day. Required together with date_to unless unique_id is sent.

2026-10-08
date_to query string no

End of the period, UTC. A date without time means the end of that day. Required together with date_from unless unique_id is sent.

2026-10-08
unique_id[] query string no

One or more request_id values from your bids. Repeat the parameter for several values. A single unique_id=... also works.

["req_8f3a1c92e7"]
operator query string no

Network name. Only plays on screens of this network are returned. A single value or operator[]=... for several.

marina-network
side_gid[] query integer no

Screen ids (gid from inventory). Only plays on these screens are returned. player_id[] is accepted as a synonym and wins if both are sent.

[173]

Responses

200

The plays found. Check errors as well, it can be present with a normal status code.

HeaderTypeDescriptionExample
X-RateLimit-Limitinteger

Requests allowed per minute for your key.

300
X-RateLimit-Remaininginteger

Requests left in the current minute.

299
Response fields
FieldTypeDescriptionExample
itemsrequired object[]

One entry per verified play.

items[].request_idrequired string

The request_id of the bid, as you echoed it in your answer.

req_8f3a1c92e7
items[].video_idoptional integer | null

Our id of the creative that played. Null if the creative no longer exists.

1234
items[].external_idoptional string | null

Your identifier of the creative that played.

spring_2026_001
items[].side_gidrequired integer | null

Screen id, the same value as gid in inventory.

173
items[].operatoroptional string | null

Network name of the screen.

marina-network
items[].pricerequired string | null

The price in your bid, as a decimal string with two digits. Null if your answer had no price.

150.00
items[].start_timeoptional integer | null

Start of the play in Unix seconds, UTC.

1791454530
items[].end_timeoptional integer | null

End of the play in Unix seconds, UTC. Null when the duration is unknown.

1791454540
totalrequired integer

Number of entries in items.

1
errorsoptional string[]

Present only when the call was adjusted or could not run as asked. Texts are currently in Russian.

{
    "items": [
        {
            "request_id": "req_8f3a1c92e7",
            "video_id": 1234,
            "external_id": "spring_2026_001",
            "side_gid": 173,
            "operator": "marina-network",
            "price": "150.00",
            "start_time": 1791454530,
            "end_time": 1791454540
        }
    ],
    "total": 1
}
401

The key is missing, wrong or empty.

HeaderTypeDescriptionExample
WWW-Authenticatestring

Always Bearer.

Bearer
Response fields
FieldTypeDescriptionExample
statusrequired string one of: error

Always error.

error
error_messagerequired string

What went wrong. For 400 it names the field. The wording may be refined over time, so do not match on the full text.

Value error in gids: One or more values are not available.
{
    "status": "error",
    "error_message": "Unauthorized"
}
429

More than 300 requests in the last minute for this key. Wait for the number of seconds in Retry-After.

HeaderTypeDescriptionExample
Retry-Afterinteger

Seconds to wait before the next call.

42
X-RateLimit-Limitinteger

Requests allowed per minute for your key.

300
Response fields
FieldTypeDescriptionExample
statusrequired string one of: error

Always error.

error
error_messagerequired string

What went wrong. For 400 it names the field. The wording may be refined over time, so do not match on the full text.

Value error in gids: One or more values are not available.
{
    "status": "error",
    "error_message": "Too many requests"
}
500

Something failed on our side, or a date could not be parsed.

Response fields
FieldTypeDescriptionExample
statusrequired string one of: error

Always error.

error
error_messagerequired string

What went wrong. For 400 it names the field. The wording may be refined over time, so do not match on the full text.

Value error in gids: One or more values are not available.
{
    "status": "error",
    "error_message": "Internal Server Error"
}

Example request

curl 'https://accounting.programmatic-engine.com/acme/reconciliation/impressions' \
  -H "Authorization: Bearer $API_KEY"