OTS API
Beta · Version 1.0
Beta. Available to try; fields and behaviour may still change.
The OTS API returns the number of people who have an opportunity to see one output of a creative on a screen, for any hour of the year, and lets you run the same calculation on your own inputs.
What OTS per output means
OTS (opportunity to see) counts people who could see the screen while it shows the creative. This API reports it per output, one showing of the creative:
ots_per_output = daily_ots x hourly_share / 12
daily_otsis the estimated number of people who pass the screen in a day. Each screen has a value for the day regime (10 second creative) and, where the schedule separates them, a value for the night regime (60 second creative). Values are stored per calendar month.hourly_shareis the fraction of the daily traffic that falls into the local hour. The 24 shares of a month sum to 1.12is the fixed number of outputs per hour and is returned asoutputs_per_hour.
Results are rounded to 1 decimal. No random spread is applied: the same request returns the same numbers every time.
Access
Keys are issued by us on request. Issue one key per integrating system so that it can be
revoked on its own. A key looks like ots_ followed by 40 letters and digits. Send it on every
request:
Authorization: Bearer ots_<40 characters>
Call GET /me first. It confirms the key, shows the account and the rate limit, and returns
the server time. An account sees only the screens granted to it. Any other screen id returns
404 not_found, the same as a screen that does not exist.
Time
- Instants in responses are UTC and end with
Z, for example2026-10-09T14:03:11Z. - Instants in requests (the
atparameter) must carryZor an offset such as+03:00. A timestamp without a zone is rejected with400 invalid_parameter. In a query string write+as%2B. - Screen-local times in responses carry an explicit offset, for example
2026-10-09T17:00:00+03:00. - A
dateparameter is a screen-local calendar date,YYYY-MM-DD. atanddateare accepted for the years 2000 to 2099. The data is stored per calendar month, so the year does not change the result.- Every screen has a fixed offset from UTC in whole hours (
utc_offset_hours). Daylight saving time is not applied.
Limits
Each key has a per-minute request limit, 60 by default, counted over a sliding 60 second window. Every response to an authenticated request carries:
X-RateLimit-Limit: the limit of the key.X-RateLimit-Remaining: requests left in the current window.
A request over the limit gets 429 rate_limited and a Retry-After header with the number of
seconds to wait. Rejected requests do not count against the limit.
A request body larger than 64 KiB is refused with 413 invalid_parameter.
Errors
Every error uses the same envelope:
{"error": {"code": "not_found", "message": "Screen 99999 was not found.", "param": null}}
Branch on code. The message is for people and can change. param names the offending
parameter or body field, or is null.
| HTTP | code | Meaning |
|---|---|---|
| 400 | invalid_parameter |
A parameter or body field is missing, malformed or out of range. |
| 401 | unauthorized |
The key is missing, unknown or revoked. The response has WWW-Authenticate: Bearer. |
| 404 | not_found |
The screen does not exist or is not granted to your account. |
| 413 | invalid_parameter |
The request body is larger than 64 KiB. |
| 422 | no_data |
The screen exists but the data for the requested month or date is incomplete. |
| 429 | rate_limited |
The per-minute limit is exceeded. Wait for Retry-After seconds. |
| 500 | internal_error |
Unexpected failure on our side. Retry later and quote the time of the request. |
| 503 | service_unavailable |
The service cannot reach its data right now. Retry later. |
Versioning
The version is part of the path: this document describes /v1. Within v1 changes are additive
only: new endpoints, new optional parameters and new response fields. Existing fields keep
their name, type and meaning. Read response fields by name and ignore fields you do not know.
A breaking change would be published under /v2 with notice.
Account
Check the key and see what the account can access.
Show the account and the key#
Returns the account that owns the key, the key itself (prefix and label, never the secret), its rate limit, the number of granted screens and the current server time. Call it first to check that a new key works.
Responses
The key is valid.
| Header | Type | Description | Example |
|---|---|---|---|
| X-RateLimit-Limit | integer | Requests per minute allowed for the key. | 60 |
| X-RateLimit-Remaining | integer | Requests left in the current 60 second window. | 59 |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| tenantrequired | object | The account the key belongs to. |
|
| tenant.idrequired | integer | Numeric id of the account that owns the key. |
3 |
| tenant.namerequired | string | Account name. |
Acme Media |
| keyrequired | object | The key used for this request. |
|
| key.prefixrequired | string | First 8 characters after "ots_" in the key. Identifies the key in support requests without revealing it. |
7Hk2xQ9p |
| key.labelrequired | string | Label given to the key when it was issued, usually the integrating system. |
BI export |
| key.created_atrequired | string | When the key was issued, UTC, ISO 8601 with Z. |
2026-10-09T10:00:00Z |
| rate_limit_per_minuterequired | integer | Requests per minute allowed for this key. |
60 |
| screensrequired | integer | Number of screens granted to the account. |
12 |
| server_timerequired | string | Current server time, UTC, ISO 8601 with Z. Use it to detect clock drift before sending the "at" parameter. |
2026-10-09T14:03:11Z |
{
"tenant": {
"id": 3,
"name": "Acme Media"
},
"key": {
"prefix": "7Hk2xQ9p",
"label": "BI export",
"created_at": "2026-10-09T10:00:00Z"
},
"rate_limit_per_minute": 60,
"screens": 12,
"server_time": "2026-10-09T14:03:11Z"
} The key is missing, unknown or revoked.
| Header | Type | Description | Example |
|---|---|---|---|
| WWW-Authenticate | string | Always "Bearer". | Bearer |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "unauthorized",
"message": "The API key is not valid.",
"param": null
}
} The per-minute limit of the key is exceeded. Wait for Retry-After seconds.
| Header | Type | Description | Example |
|---|---|---|---|
| X-RateLimit-Limit | integer | Requests per minute allowed for the key. | 60 |
| X-RateLimit-Remaining | integer | Requests left in the current 60 second window. | 59 |
| Retry-After | integer | Seconds to wait before the next request. | 17 |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "rate_limited",
"message": "The limit of 60 requests per minute for this key is exceeded.",
"param": null
}
} Unexpected failure on our side.
| Header | Type | Description | Example |
|---|---|---|---|
| X-RateLimit-Limit | integer | Requests per minute allowed for the key. | 60 |
| X-RateLimit-Remaining | integer | Requests left in the current 60 second window. | 59 |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "internal_error",
"message": "The service failed to process the request.",
"param": null
}
} The service cannot reach its data right now. Retry later.
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "service_unavailable",
"message": "The service is temporarily unavailable. Retry later.",
"param": null
}
} Example request
curl 'https://ots.programmatic-engine.ru/v1/me' \
-H "Authorization: Bearer $API_KEY"
Screens
Screens granted to the account and the inputs of their model.
List granted screens#
Returns every screen granted to the account, ordered by id. months_with_data lists the months for which OTS can be calculated; request other months and you get 422 no_data. The list is not paginated.
Responses
Granted screens.
| Header | Type | Description | Example |
|---|---|---|---|
| X-RateLimit-Limit | integer | Requests per minute allowed for the key. | 60 |
| X-RateLimit-Remaining | integer | Requests left in the current 60 second window. | 59 |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| itemsrequired | object[] | Granted screens ordered by id. |
[{"active":true,"city":"Москва","id":10403,"months_with_data":[1,2,3,4,5,6,7,8,9,10,11,12],"name":"Kutuzovsky Prospekt 48","schedule":{"name":"Москва","night_mode":"separate"},"utc_offset_hours":3}] |
| items[].idrequired | integer | Screen id. The same id is used by the unauthenticated OTS lookup used by ad platforms. |
10403 |
| items[].namerequired | string | Screen name. |
Kutuzovsky Prospekt 48 |
| items[].cityrequired | string | City where the screen stands. |
Москва |
| items[].utc_offset_hoursrequired | integer | Fixed offset of screen-local time from UTC, in whole hours. Daylight saving time is not applied. |
3 |
| items[].activerequired | boolean | False when the screen is switched off in the registry. Data stays readable. |
true |
| items[].schedulerequired | any of | Broadcast schedule of the screen, or null when none is assigned. Without a schedule no OTS can be calculated for the screen. |
|
| items[].schedule (option 1)optional | object | ||
| items[].schedule.namerequired | string | Broadcast schedule name. |
Москва |
| items[].schedule.night_moderequired | string one of: separate, same | "separate": the night has its own daily OTS value (a longer creative at night). "same": the day value applies around the clock. |
separate |
| items[].schedule (option 2)optional | null | ||
| items[].months_with_datarequired | integer[] | Months (1 to 12) for which OTS can be calculated: the day value exists, the night value exists when night_mode is "separate", and all 24 hourly shares exist. The list is empty when the screen has no usable schedule. |
[1,2,3,4,5,6,7,8,9,10,11,12] |
{
"items": [
{
"id": 10403,
"name": "Kutuzovsky Prospekt 48",
"city": "Москва",
"utc_offset_hours": 3,
"active": true,
"schedule": {
"name": "Москва",
"night_mode": "separate"
},
"months_with_data": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
}
]
} The key is missing, unknown or revoked.
| Header | Type | Description | Example |
|---|---|---|---|
| WWW-Authenticate | string | Always "Bearer". | Bearer |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "unauthorized",
"message": "The API key is not valid.",
"param": null
}
} The per-minute limit of the key is exceeded. Wait for Retry-After seconds.
| Header | Type | Description | Example |
|---|---|---|---|
| X-RateLimit-Limit | integer | Requests per minute allowed for the key. | 60 |
| X-RateLimit-Remaining | integer | Requests left in the current 60 second window. | 59 |
| Retry-After | integer | Seconds to wait before the next request. | 17 |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "rate_limited",
"message": "The limit of 60 requests per minute for this key is exceeded.",
"param": null
}
} Unexpected failure on our side.
| Header | Type | Description | Example |
|---|---|---|---|
| X-RateLimit-Limit | integer | Requests per minute allowed for the key. | 60 |
| X-RateLimit-Remaining | integer | Requests left in the current 60 second window. | 59 |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "internal_error",
"message": "The service failed to process the request.",
"param": null
}
} The service cannot reach its data right now. Retry later.
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "service_unavailable",
"message": "The service is temporarily unavailable. Retry later.",
"param": null
}
} Example request
curl 'https://ots.programmatic-engine.ru/v1/screens' \
-H "Authorization: Bearer $API_KEY"
Get one screen#
Returns one granted screen. A screen that is not granted to the account returns 404 not_found, the same as a screen that does not exist.
Parameters
| Name | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| screen_id | path | integermin 1 · max 2147483647 | yes | Screen id from GET /screens. |
10403 |
Responses
The screen.
| Header | Type | Description | Example |
|---|---|---|---|
| X-RateLimit-Limit | integer | Requests per minute allowed for the key. | 60 |
| X-RateLimit-Remaining | integer | Requests left in the current 60 second window. | 59 |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| idrequired | integer | Screen id. The same id is used by the unauthenticated OTS lookup used by ad platforms. |
10403 |
| namerequired | string | Screen name. |
Kutuzovsky Prospekt 48 |
| cityrequired | string | City where the screen stands. |
Москва |
| utc_offset_hoursrequired | integer | Fixed offset of screen-local time from UTC, in whole hours. Daylight saving time is not applied. |
3 |
| activerequired | boolean | False when the screen is switched off in the registry. Data stays readable. |
true |
| schedulerequired | any of | Broadcast schedule of the screen, or null when none is assigned. Without a schedule no OTS can be calculated for the screen. |
|
| schedule (option 1)optional | object | ||
| schedule.namerequired | string | Broadcast schedule name. |
Москва |
| schedule.night_moderequired | string one of: separate, same | "separate": the night has its own daily OTS value (a longer creative at night). "same": the day value applies around the clock. |
separate |
| schedule (option 2)optional | null | ||
| months_with_datarequired | integer[] | Months (1 to 12) for which OTS can be calculated: the day value exists, the night value exists when night_mode is "separate", and all 24 hourly shares exist. The list is empty when the screen has no usable schedule. |
[1,2,3,4,5,6,7,8,9,10,11,12] |
{
"id": 10403,
"name": "Kutuzovsky Prospekt 48",
"city": "Москва",
"utc_offset_hours": 3,
"active": true,
"schedule": {
"name": "Москва",
"night_mode": "separate"
},
"months_with_data": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
} A parameter or body field is missing, malformed or out of range.
| Header | Type | Description | Example |
|---|---|---|---|
| X-RateLimit-Limit | integer | Requests per minute allowed for the key. | 60 |
| X-RateLimit-Remaining | integer | Requests left in the current 60 second window. | 59 |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "invalid_parameter",
"message": "Parameter 'screen_id' is invalid. Input should be a valid integer.",
"param": "screen_id"
}
} The key is missing, unknown or revoked.
| Header | Type | Description | Example |
|---|---|---|---|
| WWW-Authenticate | string | Always "Bearer". | Bearer |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "unauthorized",
"message": "The API key is not valid.",
"param": null
}
} The screen does not exist or is not granted to the account.
| Header | Type | Description | Example |
|---|---|---|---|
| X-RateLimit-Limit | integer | Requests per minute allowed for the key. | 60 |
| X-RateLimit-Remaining | integer | Requests left in the current 60 second window. | 59 |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "not_found",
"message": "Screen 99999 was not found.",
"param": null
}
} The per-minute limit of the key is exceeded. Wait for Retry-After seconds.
| Header | Type | Description | Example |
|---|---|---|---|
| X-RateLimit-Limit | integer | Requests per minute allowed for the key. | 60 |
| X-RateLimit-Remaining | integer | Requests left in the current 60 second window. | 59 |
| Retry-After | integer | Seconds to wait before the next request. | 17 |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "rate_limited",
"message": "The limit of 60 requests per minute for this key is exceeded.",
"param": null
}
} Unexpected failure on our side.
| Header | Type | Description | Example |
|---|---|---|---|
| X-RateLimit-Limit | integer | Requests per minute allowed for the key. | 60 |
| X-RateLimit-Remaining | integer | Requests left in the current 60 second window. | 59 |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "internal_error",
"message": "The service failed to process the request.",
"param": null
}
} The service cannot reach its data right now. Retry later.
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "service_unavailable",
"message": "The service is temporarily unavailable. Retry later.",
"param": null
}
} Example request
curl 'https://ots.programmatic-engine.ru/v1/screens/10403' \
-H "Authorization: Bearer $API_KEY"
Model inputs of a screen for one month#
Returns the values behind the calculation for one month: the daily OTS values, the 24 hourly shares and the broadcast schedule with all its day windows. Use it to run your own calculation or to check ours with POST /calculate. daily_ots.night is null when the schedule has night_mode "same". Returns 422 no_data when the month is not in months_with_data.
Parameters
| Name | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| screen_id | path | integermin 1 · max 2147483647 | yes | Screen id from GET /screens. |
10403 |
| month | query | integermin 1 · max 12 | no | Calendar month, 1 to 12. Defaults to the current month in screen-local time. |
10 |
Responses
Inputs for the month.
| Header | Type | Description | Example |
|---|---|---|---|
| X-RateLimit-Limit | integer | Requests per minute allowed for the key. | 60 |
| X-RateLimit-Remaining | integer | Requests left in the current 60 second window. | 59 |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| screen_idrequired | integer | Screen id. |
10403 |
| monthrequired | integer | Calendar month, 1 to 12. |
10 |
| daily_otsrequired | object | Daily OTS values for the month. |
|
| daily_ots.dayrequired | integer | Daily OTS of the day creative (10 seconds). |
60500 |
| daily_ots.nightrequired | any of | Daily OTS of the night creative (60 seconds). Null when night_mode is "same". |
|
| daily_ots.night (option 1)optional | integer | ||
| daily_ots.night (option 2)optional | null | ||
| hourly_sharerequired | number[] | 24 fractions, index 0 is the hour starting at 00:00 screen-local time. They sum to 1 within 0.005. |
[0.036,0.024,0.019,0.013,0.013,0.018,0.026,0.029,0.036,0.042,0.051,0.057,0.062,0.064,0.062,0.061,0.057,0.053,0.051,0.05,0.048,0.046,0.043,0.039] |
| schedulerequired | any of | Schedule with all its day windows, or null when none is assigned. |
|
| schedule (option 1)optional | object | ||
| schedule.namerequired | string | Broadcast schedule name. |
Москва |
| schedule.night_moderequired | string one of: separate, same | "separate": the night has its own daily OTS value (a longer creative at night). "same": the day value applies around the clock. |
separate |
| schedule.periodsrequired | object[] | All day windows of the schedule, ordered by effective_from. |
[{"day_end":19,"day_start":6,"effective_from":"2026-01-01"}] |
| schedule.periods[].effective_fromrequired | string | First screen-local date on which this window applies, YYYY-MM-DD. The period in force is the latest one that has started. |
2026-01-01 |
| schedule.periods[].day_startrequired | integer | First hour of the day regime, 0 to 23. |
6 |
| schedule.periods[].day_endrequired | integer | Last hour of the day regime, 0 to 23, inclusive. The window does not wrap past midnight. |
19 |
| schedule (option 2)optional | null |
{
"screen_id": 10403,
"month": 10,
"daily_ots": {
"day": 60500,
"night": 151100
},
"hourly_share": [
0.036, 0.024, 0.019, 0.013, 0.013, 0.018, 0.026, 0.029, 0.036,
0.042, 0.051, 0.057, 0.062, 0.064, 0.062, 0.061, 0.057, 0.053,
0.051, 0.05, 0.048, 0.046, 0.043, 0.039
],
"schedule": {
"name": "Москва",
"night_mode": "separate",
"periods": [
{
"effective_from": "2026-01-01",
"day_start": 6,
"day_end": 19
}
]
}
} A parameter or body field is missing, malformed or out of range.
| Header | Type | Description | Example |
|---|---|---|---|
| X-RateLimit-Limit | integer | Requests per minute allowed for the key. | 60 |
| X-RateLimit-Remaining | integer | Requests left in the current 60 second window. | 59 |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "invalid_parameter",
"message": "Parameter 'month' is invalid. Input should be less than or equal to 12.",
"param": "month"
}
} The key is missing, unknown or revoked.
| Header | Type | Description | Example |
|---|---|---|---|
| WWW-Authenticate | string | Always "Bearer". | Bearer |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "unauthorized",
"message": "The API key is not valid.",
"param": null
}
} The screen does not exist or is not granted to the account.
| Header | Type | Description | Example |
|---|---|---|---|
| X-RateLimit-Limit | integer | Requests per minute allowed for the key. | 60 |
| X-RateLimit-Remaining | integer | Requests left in the current 60 second window. | 59 |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "not_found",
"message": "Screen 99999 was not found.",
"param": null
}
} The screen exists but its data for the requested month or date is incomplete.
| Header | Type | Description | Example |
|---|---|---|---|
| X-RateLimit-Limit | integer | Requests per minute allowed for the key. | 60 |
| X-RateLimit-Remaining | integer | Requests left in the current 60 second window. | 59 |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "no_data",
"message": "Screen 10403 has no complete OTS data for month 11.",
"param": null
}
} The per-minute limit of the key is exceeded. Wait for Retry-After seconds.
| Header | Type | Description | Example |
|---|---|---|---|
| X-RateLimit-Limit | integer | Requests per minute allowed for the key. | 60 |
| X-RateLimit-Remaining | integer | Requests left in the current 60 second window. | 59 |
| Retry-After | integer | Seconds to wait before the next request. | 17 |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "rate_limited",
"message": "The limit of 60 requests per minute for this key is exceeded.",
"param": null
}
} Unexpected failure on our side.
| Header | Type | Description | Example |
|---|---|---|---|
| X-RateLimit-Limit | integer | Requests per minute allowed for the key. | 60 |
| X-RateLimit-Remaining | integer | Requests left in the current 60 second window. | 59 |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "internal_error",
"message": "The service failed to process the request.",
"param": null
}
} The service cannot reach its data right now. Retry later.
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "service_unavailable",
"message": "The service is temporarily unavailable. Retry later.",
"param": null
}
} Example request
curl 'https://ots.programmatic-engine.ru/v1/screens/10403/inputs' \
-H "Authorization: Bearer $API_KEY"
OTS
Calculated OTS for granted screens.
OTS per output at one instant#
Calculates OTS for one output of the creative at the instant at. The instant is converted to screen-local time with the fixed offset of the screen. The local hour selects the hourly share and, through the broadcast schedule, the day or night value. The value is daily_ots x hourly_share / 12, rounded to 1 decimal, with no random spread. Returns 422 no_data when the month has no complete data or no schedule period is in force on that local date.
Parameters
| Name | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| screen_id | path | integermin 1 · max 2147483647 | yes | Screen id from GET /screens. |
10403 |
| at | query | string | no | Instant to calculate for, ISO 8601 with Z or a UTC offset. A naive timestamp is rejected. Defaults to the current time. Percent-encode "+" as %2B. Accepted from 2000-01-01T00:00:00Z to 2099-12-31T23:59:59Z. |
2026-10-09T14:00:00Z |
Responses
OTS for the hour that contains the instant.
| Header | Type | Description | Example |
|---|---|---|---|
| X-RateLimit-Limit | integer | Requests per minute allowed for the key. | 60 |
| X-RateLimit-Remaining | integer | Requests left in the current 60 second window. | 59 |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| screen_idrequired | integer | Screen id. |
10403 |
| atrequired | string | The requested instant, UTC, ISO 8601 with Z. |
2026-10-09T14:00:00Z |
| local_timerequired | string | The same instant in screen-local time, ISO 8601 with an explicit offset. |
2026-10-09T17:00:00+03:00 |
| daypartrequired | string one of: day, night | Which regime applies at that local hour according to the schedule. |
day |
| daily_otsrequired | integer | Daily OTS value used: the day value in the day regime, the night value in the night regime when night_mode is "separate", otherwise the day value. |
60500 |
| hourly_sharerequired | number | Share of daily traffic that falls into this local hour, as a fraction. |
0.062 |
| outputs_per_hourrequired | integer | Fixed divisor of the formula: 12 outputs per hour. |
12 |
| otsrequired | number | OTS for one output of the creative, rounded to 1 decimal. daily_ots x hourly_share / outputs_per_hour. No random spread is applied. |
312.6 |
{
"screen_id": 10403,
"at": "2026-10-09T14:00:00Z",
"local_time": "2026-10-09T17:00:00+03:00",
"daypart": "day",
"daily_ots": 60500,
"hourly_share": 0.053,
"outputs_per_hour": 12,
"ots": 267.2
} A parameter or body field is missing, malformed or out of range.
| Header | Type | Description | Example |
|---|---|---|---|
| X-RateLimit-Limit | integer | Requests per minute allowed for the key. | 60 |
| X-RateLimit-Remaining | integer | Requests left in the current 60 second window. | 59 |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "invalid_parameter",
"message": "Parameter 'at' must be an ISO 8601 timestamp with Z or a UTC offset, for example 2026-10-09T14:00:00Z. A '+' in an offset must be percent-encoded as %2B.",
"param": "at"
}
} The key is missing, unknown or revoked.
| Header | Type | Description | Example |
|---|---|---|---|
| WWW-Authenticate | string | Always "Bearer". | Bearer |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "unauthorized",
"message": "The API key is not valid.",
"param": null
}
} The screen does not exist or is not granted to the account.
| Header | Type | Description | Example |
|---|---|---|---|
| X-RateLimit-Limit | integer | Requests per minute allowed for the key. | 60 |
| X-RateLimit-Remaining | integer | Requests left in the current 60 second window. | 59 |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "not_found",
"message": "Screen 99999 was not found.",
"param": null
}
} The screen exists but its data for the requested month or date is incomplete.
| Header | Type | Description | Example |
|---|---|---|---|
| X-RateLimit-Limit | integer | Requests per minute allowed for the key. | 60 |
| X-RateLimit-Remaining | integer | Requests left in the current 60 second window. | 59 |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "no_data",
"message": "Screen 10403 has no complete OTS data for month 11.",
"param": null
}
} The per-minute limit of the key is exceeded. Wait for Retry-After seconds.
| Header | Type | Description | Example |
|---|---|---|---|
| X-RateLimit-Limit | integer | Requests per minute allowed for the key. | 60 |
| X-RateLimit-Remaining | integer | Requests left in the current 60 second window. | 59 |
| Retry-After | integer | Seconds to wait before the next request. | 17 |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "rate_limited",
"message": "The limit of 60 requests per minute for this key is exceeded.",
"param": null
}
} Unexpected failure on our side.
| Header | Type | Description | Example |
|---|---|---|---|
| X-RateLimit-Limit | integer | Requests per minute allowed for the key. | 60 |
| X-RateLimit-Remaining | integer | Requests left in the current 60 second window. | 59 |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "internal_error",
"message": "The service failed to process the request.",
"param": null
}
} The service cannot reach its data right now. Retry later.
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "service_unavailable",
"message": "The service is temporarily unavailable. Retry later.",
"param": null
}
} Example request
curl 'https://ots.programmatic-engine.ru/v1/screens/10403/ots' \
-H "Authorization: Bearer $API_KEY"
OTS for each hour of a local day#
Returns 24 rows for one screen-local calendar date. ots_per_output is the value for one output, ots_hour is that value times 12 outputs, and total_ots is the sum of ots_hour over the day. The day and night windows come from the schedule period in force on that date. Returns 422 no_data when the month has no complete data or no schedule period is in force on that date.
Parameters
| Name | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| screen_id | path | integermin 1 · max 2147483647 | yes | Screen id from GET /screens. |
10403 |
| date | query | string | no | Screen-local calendar date, YYYY-MM-DD, from 2000-01-01 to 2099-12-31. Defaults to today in screen-local time. |
2026-10-09 |
Responses
Hourly OTS for the date.
| Header | Type | Description | Example |
|---|---|---|---|
| X-RateLimit-Limit | integer | Requests per minute allowed for the key. | 60 |
| X-RateLimit-Remaining | integer | Requests left in the current 60 second window. | 59 |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| screen_idrequired | integer | Screen id. |
10403 |
| daterequired | string | Screen-local calendar date, YYYY-MM-DD. |
2026-10-09 |
| utc_offset_hoursrequired | integer | Screen offset from UTC used to build the "start" values. |
3 |
| outputs_per_hourrequired | integer | Fixed divisor of the formula: 12. |
12 |
| hoursrequired | object[] | Exactly 24 rows, hour 0 to 23. |
[{"daily_ots":60500,"daypart":"day","hour":12,"hourly_share":0.062,"ots_hour":3751.2,"ots_per_output":312.6,"start":"2026-10-09T12:00:00+03:00"}] |
| hours[].hourrequired | integer | Screen-local hour of day, 0 to 23. |
12 |
| hours[].startrequired | string | Start of the hour in screen-local time, ISO 8601 with offset. |
2026-10-09T12:00:00+03:00 |
| hours[].daypartrequired | string one of: day, night | Regime that applies in this hour. |
day |
| hours[].daily_otsrequired | integer | Daily OTS value used for this hour. |
60500 |
| hours[].hourly_sharerequired | number | Fraction of daily traffic in this hour. |
0.062 |
| hours[].ots_per_outputrequired | number | OTS for one output in this hour, rounded to 1 decimal. |
312.6 |
| hours[].ots_hourrequired | number | OTS for all 12 outputs of the hour: ots_per_output x 12, rounded to 1 decimal. |
3751.2 |
| total_otsrequired | number | Sum of ots_hour over the 24 rows, rounded to 1 decimal. |
87589.2 |
{
"screen_id": 10403,
"date": "2026-10-09",
"utc_offset_hours": 3,
"outputs_per_hour": 12,
"hours": [
{
"hour": 0,
"start": "2026-10-09T00:00:00+03:00",
"daypart": "night",
"daily_ots": 151100,
"hourly_share": 0.036,
"ots_per_output": 453.3,
"ots_hour": 5439.6
},
{
"hour": 1,
"start": "2026-10-09T01:00:00+03:00",
"daypart": "night",
"daily_ots": 151100,
"hourly_share": 0.024,
"ots_per_output": 302.2,
"ots_hour": 3626.4
},
{
"hour": 2,
"start": "2026-10-09T02:00:00+03:00",
"daypart": "night",
"daily_ots": 151100,
"hourly_share": 0.019,
"ots_per_output": 239.2,
"ots_hour": 2870.4
},
{
"hour": 3,
"start": "2026-10-09T03:00:00+03:00",
"daypart": "night",
"daily_ots": 151100,
"hourly_share": 0.013,
"ots_per_output": 163.7,
"ots_hour": 1964.4
},
{
"hour": 4,
"start": "2026-10-09T04:00:00+03:00",
"daypart": "night",
"daily_ots": 151100,
"hourly_share": 0.013,
"ots_per_output": 163.7,
"ots_hour": 1964.4
},
{
"hour": 5,
"start": "2026-10-09T05:00:00+03:00",
"daypart": "night",
"daily_ots": 151100,
"hourly_share": 0.018,
"ots_per_output": 226.6,
"ots_hour": 2719.2
},
{
"hour": 6,
"start": "2026-10-09T06:00:00+03:00",
"daypart": "day",
"daily_ots": 60500,
"hourly_share": 0.026,
"ots_per_output": 131.1,
"ots_hour": 1573.2
},
{
"hour": 7,
"start": "2026-10-09T07:00:00+03:00",
"daypart": "day",
"daily_ots": 60500,
"hourly_share": 0.029,
"ots_per_output": 146.2,
"ots_hour": 1754.4
},
{
"hour": 8,
"start": "2026-10-09T08:00:00+03:00",
"daypart": "day",
"daily_ots": 60500,
"hourly_share": 0.036,
"ots_per_output": 181.5,
"ots_hour": 2178
},
{
"hour": 9,
"start": "2026-10-09T09:00:00+03:00",
"daypart": "day",
"daily_ots": 60500,
"hourly_share": 0.042,
"ots_per_output": 211.8,
"ots_hour": 2541.6
},
{
"hour": 10,
"start": "2026-10-09T10:00:00+03:00",
"daypart": "day",
"daily_ots": 60500,
"hourly_share": 0.051,
"ots_per_output": 257.1,
"ots_hour": 3085.2
},
{
"hour": 11,
"start": "2026-10-09T11:00:00+03:00",
"daypart": "day",
"daily_ots": 60500,
"hourly_share": 0.057,
"ots_per_output": 287.4,
"ots_hour": 3448.8
},
{
"hour": 12,
"start": "2026-10-09T12:00:00+03:00",
"daypart": "day",
"daily_ots": 60500,
"hourly_share": 0.062,
"ots_per_output": 312.6,
"ots_hour": 3751.2
},
{
"hour": 13,
"start": "2026-10-09T13:00:00+03:00",
"daypart": "day",
"daily_ots": 60500,
"hourly_share": 0.064,
"ots_per_output": 322.7,
"ots_hour": 3872.4
},
{
"hour": 14,
"start": "2026-10-09T14:00:00+03:00",
"daypart": "day",
"daily_ots": 60500,
"hourly_share": 0.062,
"ots_per_output": 312.6,
"ots_hour": 3751.2
},
{
"hour": 15,
"start": "2026-10-09T15:00:00+03:00",
"daypart": "day",
"daily_ots": 60500,
"hourly_share": 0.061,
"ots_per_output": 307.5,
"ots_hour": 3690
},
{
"hour": 16,
"start": "2026-10-09T16:00:00+03:00",
"daypart": "day",
"daily_ots": 60500,
"hourly_share": 0.057,
"ots_per_output": 287.4,
"ots_hour": 3448.8
},
{
"hour": 17,
"start": "2026-10-09T17:00:00+03:00",
"daypart": "day",
"daily_ots": 60500,
"hourly_share": 0.053,
"ots_per_output": 267.2,
"ots_hour": 3206.4
},
{
"hour": 18,
"start": "2026-10-09T18:00:00+03:00",
"daypart": "day",
"daily_ots": 60500,
"hourly_share": 0.051,
"ots_per_output": 257.1,
"ots_hour": 3085.2
},
{
"hour": 19,
"start": "2026-10-09T19:00:00+03:00",
"daypart": "day",
"daily_ots": 60500,
"hourly_share": 0.05,
"ots_per_output": 252.1,
"ots_hour": 3025.2
},
{
"hour": 20,
"start": "2026-10-09T20:00:00+03:00",
"daypart": "night",
"daily_ots": 151100,
"hourly_share": 0.048,
"ots_per_output": 604.4,
"ots_hour": 7252.8
},
{
"hour": 21,
"start": "2026-10-09T21:00:00+03:00",
"daypart": "night",
"daily_ots": 151100,
"hourly_share": 0.046,
"ots_per_output": 579.2,
"ots_hour": 6950.4
},
{
"hour": 22,
"start": "2026-10-09T22:00:00+03:00",
"daypart": "night",
"daily_ots": 151100,
"hourly_share": 0.043,
"ots_per_output": 541.4,
"ots_hour": 6496.8
},
{
"hour": 23,
"start": "2026-10-09T23:00:00+03:00",
"daypart": "night",
"daily_ots": 151100,
"hourly_share": 0.039,
"ots_per_output": 491.1,
"ots_hour": 5893.2
}
],
"total_ots": 87589.2
} A parameter or body field is missing, malformed or out of range.
| Header | Type | Description | Example |
|---|---|---|---|
| X-RateLimit-Limit | integer | Requests per minute allowed for the key. | 60 |
| X-RateLimit-Remaining | integer | Requests left in the current 60 second window. | 59 |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "invalid_parameter",
"message": "Parameter 'date' must be a calendar date in the form YYYY-MM-DD.",
"param": "date"
}
} The key is missing, unknown or revoked.
| Header | Type | Description | Example |
|---|---|---|---|
| WWW-Authenticate | string | Always "Bearer". | Bearer |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "unauthorized",
"message": "The API key is not valid.",
"param": null
}
} The screen does not exist or is not granted to the account.
| Header | Type | Description | Example |
|---|---|---|---|
| X-RateLimit-Limit | integer | Requests per minute allowed for the key. | 60 |
| X-RateLimit-Remaining | integer | Requests left in the current 60 second window. | 59 |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "not_found",
"message": "Screen 99999 was not found.",
"param": null
}
} The screen exists but its data for the requested month or date is incomplete.
| Header | Type | Description | Example |
|---|---|---|---|
| X-RateLimit-Limit | integer | Requests per minute allowed for the key. | 60 |
| X-RateLimit-Remaining | integer | Requests left in the current 60 second window. | 59 |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "no_data",
"message": "Screen 10403 has no complete OTS data for month 11.",
"param": null
}
} The per-minute limit of the key is exceeded. Wait for Retry-After seconds.
| Header | Type | Description | Example |
|---|---|---|---|
| X-RateLimit-Limit | integer | Requests per minute allowed for the key. | 60 |
| X-RateLimit-Remaining | integer | Requests left in the current 60 second window. | 59 |
| Retry-After | integer | Seconds to wait before the next request. | 17 |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "rate_limited",
"message": "The limit of 60 requests per minute for this key is exceeded.",
"param": null
}
} Unexpected failure on our side.
| Header | Type | Description | Example |
|---|---|---|---|
| X-RateLimit-Limit | integer | Requests per minute allowed for the key. | 60 |
| X-RateLimit-Remaining | integer | Requests left in the current 60 second window. | 59 |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "internal_error",
"message": "The service failed to process the request.",
"param": null
}
} The service cannot reach its data right now. Retry later.
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "service_unavailable",
"message": "The service is temporarily unavailable. Retry later.",
"param": null
}
} Example request
curl 'https://ots.programmatic-engine.ru/v1/screens/10403/ots/hourly' \
-H "Authorization: Bearer $API_KEY"
Generator
Run the calculation on your own inputs.
Calculate OTS from your own inputs#
Runs the same calculation as the screen endpoints on inputs you send. It reads no data of any account and stores nothing. Send the daily OTS values, 24 hourly shares as fractions, the day window and the night mode. With night_mode "separate", hours inside day_hours (both ends included) use daily_ots.day and the other hours use daily_ots.night. With "same", daily_ots.day is used for all 24 hours. The day window does not wrap past midnight. The response has one row per hour of the day, hour 0 to 23, and total_ots for the whole day.
Request body · application/json
| Field | Type | Description | Example |
|---|---|---|---|
| daily_otsrequired | object | Daily OTS values of the screen. |
|
| daily_ots.dayrequired | integermax 1000000000 · above 0 | Daily OTS of the day creative. |
60500 |
| daily_ots.nightoptional | any of | Daily OTS of the night creative. Required when night_mode is "separate". Ignored when night_mode is "same". |
|
| daily_ots.night (option 1)optional | integermax 1000000000 · above 0 | ||
| daily_ots.night (option 2)optional | null | ||
| hourly_sharerequired | number[]minItems 24 · maxItems 24 | Exactly 24 fractions of daily traffic, index 0 is hour 00. Use fractions, not percent: 0.062, not 6.2. Each value is between 0 and 1 and the sum is 1 within 0.005. |
[0.036,0.024,0.019,0.013,0.013,0.018,0.026,0.029,0.036,0.042,0.051,0.057,0.062,0.064,0.062,0.061,0.057,0.053,0.051,0.05,0.048,0.046,0.043,0.039] |
| day_hoursoptional | any of | Hours that belong to the day regime. Required when night_mode is "separate". When night_mode is "same" it only labels the dayparts and defaults to the whole day. |
|
| day_hours (option 1)optional | object | ||
| day_hours.startrequired | integermin 0 · max 23 | First hour of the day regime. |
6 |
| day_hours.endrequired | integermin 0 · max 23 | Last hour of the day regime, inclusive. Must not be less than start. A window that wraps past midnight is not supported. |
19 |
| day_hours (option 2)optional | null | ||
| night_moderequired | string one of: separate, same | "separate": hours outside day_hours use daily_ots.night. "same": daily_ots.day is used for all 24 hours. |
separate |
{
"daily_ots": {
"day": 60500,
"night": 151100
},
"hourly_share": [
0.036, 0.024, 0.019, 0.013, 0.013, 0.018, 0.026, 0.029, 0.036,
0.042, 0.051, 0.057, 0.062, 0.064, 0.062, 0.061, 0.057, 0.053,
0.051, 0.05, 0.048, 0.046, 0.043, 0.039
],
"day_hours": {
"start": 6,
"end": 19
},
"night_mode": "separate"
}
Responses
Hourly OTS for the inputs.
| Header | Type | Description | Example |
|---|---|---|---|
| X-RateLimit-Limit | integer | Requests per minute allowed for the key. | 60 |
| X-RateLimit-Remaining | integer | Requests left in the current 60 second window. | 59 |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| outputs_per_hourrequired | integer | Fixed divisor of the formula: 12. |
12 |
| hoursrequired | object[] | Exactly 24 rows, hour 0 to 23. |
[{"daily_ots":60500,"daypart":"day","hour":12,"hourly_share":0.062,"ots_hour":3751.2,"ots_per_output":312.6}] |
| hours[].hourrequired | integer | Hour of day, 0 to 23. |
12 |
| hours[].daypartrequired | string one of: day, night | Regime that applies in this hour. |
day |
| hours[].daily_otsrequired | integer | Daily OTS value used for this hour. |
60500 |
| hours[].hourly_sharerequired | number | Fraction of daily traffic in this hour. |
0.062 |
| hours[].ots_per_outputrequired | number | OTS for one output in this hour, rounded to 1 decimal. |
312.6 |
| hours[].ots_hourrequired | number | OTS for all 12 outputs of the hour: ots_per_output x 12, rounded to 1 decimal. |
3751.2 |
| total_otsrequired | number | Sum of ots_hour over the 24 rows, rounded to 1 decimal. |
87589.2 |
{
"outputs_per_hour": 12,
"hours": [
{
"hour": 0,
"daypart": "night",
"daily_ots": 151100,
"hourly_share": 0.036,
"ots_per_output": 453.3,
"ots_hour": 5439.6
},
{
"hour": 1,
"daypart": "night",
"daily_ots": 151100,
"hourly_share": 0.024,
"ots_per_output": 302.2,
"ots_hour": 3626.4
},
{
"hour": 2,
"daypart": "night",
"daily_ots": 151100,
"hourly_share": 0.019,
"ots_per_output": 239.2,
"ots_hour": 2870.4
},
{
"hour": 3,
"daypart": "night",
"daily_ots": 151100,
"hourly_share": 0.013,
"ots_per_output": 163.7,
"ots_hour": 1964.4
},
{
"hour": 4,
"daypart": "night",
"daily_ots": 151100,
"hourly_share": 0.013,
"ots_per_output": 163.7,
"ots_hour": 1964.4
},
{
"hour": 5,
"daypart": "night",
"daily_ots": 151100,
"hourly_share": 0.018,
"ots_per_output": 226.6,
"ots_hour": 2719.2
},
{
"hour": 6,
"daypart": "day",
"daily_ots": 60500,
"hourly_share": 0.026,
"ots_per_output": 131.1,
"ots_hour": 1573.2
},
{
"hour": 7,
"daypart": "day",
"daily_ots": 60500,
"hourly_share": 0.029,
"ots_per_output": 146.2,
"ots_hour": 1754.4
},
{
"hour": 8,
"daypart": "day",
"daily_ots": 60500,
"hourly_share": 0.036,
"ots_per_output": 181.5,
"ots_hour": 2178
},
{
"hour": 9,
"daypart": "day",
"daily_ots": 60500,
"hourly_share": 0.042,
"ots_per_output": 211.8,
"ots_hour": 2541.6
},
{
"hour": 10,
"daypart": "day",
"daily_ots": 60500,
"hourly_share": 0.051,
"ots_per_output": 257.1,
"ots_hour": 3085.2
},
{
"hour": 11,
"daypart": "day",
"daily_ots": 60500,
"hourly_share": 0.057,
"ots_per_output": 287.4,
"ots_hour": 3448.8
},
{
"hour": 12,
"daypart": "day",
"daily_ots": 60500,
"hourly_share": 0.062,
"ots_per_output": 312.6,
"ots_hour": 3751.2
},
{
"hour": 13,
"daypart": "day",
"daily_ots": 60500,
"hourly_share": 0.064,
"ots_per_output": 322.7,
"ots_hour": 3872.4
},
{
"hour": 14,
"daypart": "day",
"daily_ots": 60500,
"hourly_share": 0.062,
"ots_per_output": 312.6,
"ots_hour": 3751.2
},
{
"hour": 15,
"daypart": "day",
"daily_ots": 60500,
"hourly_share": 0.061,
"ots_per_output": 307.5,
"ots_hour": 3690
},
{
"hour": 16,
"daypart": "day",
"daily_ots": 60500,
"hourly_share": 0.057,
"ots_per_output": 287.4,
"ots_hour": 3448.8
},
{
"hour": 17,
"daypart": "day",
"daily_ots": 60500,
"hourly_share": 0.053,
"ots_per_output": 267.2,
"ots_hour": 3206.4
},
{
"hour": 18,
"daypart": "day",
"daily_ots": 60500,
"hourly_share": 0.051,
"ots_per_output": 257.1,
"ots_hour": 3085.2
},
{
"hour": 19,
"daypart": "day",
"daily_ots": 60500,
"hourly_share": 0.05,
"ots_per_output": 252.1,
"ots_hour": 3025.2
},
{
"hour": 20,
"daypart": "night",
"daily_ots": 151100,
"hourly_share": 0.048,
"ots_per_output": 604.4,
"ots_hour": 7252.8
},
{
"hour": 21,
"daypart": "night",
"daily_ots": 151100,
"hourly_share": 0.046,
"ots_per_output": 579.2,
"ots_hour": 6950.4
},
{
"hour": 22,
"daypart": "night",
"daily_ots": 151100,
"hourly_share": 0.043,
"ots_per_output": 541.4,
"ots_hour": 6496.8
},
{
"hour": 23,
"daypart": "night",
"daily_ots": 151100,
"hourly_share": 0.039,
"ots_per_output": 491.1,
"ots_hour": 5893.2
}
],
"total_ots": 87589.2
} A parameter or body field is missing, malformed or out of range.
| Header | Type | Description | Example |
|---|---|---|---|
| X-RateLimit-Limit | integer | Requests per minute allowed for the key. | 60 |
| X-RateLimit-Remaining | integer | Requests left in the current 60 second window. | 59 |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "invalid_parameter",
"message": "Parameter 'hourly_share' is invalid. The shares must sum to 1 within 0.005 (fractions, not percent), got 100.0000.",
"param": "hourly_share"
}
} The key is missing, unknown or revoked.
| Header | Type | Description | Example |
|---|---|---|---|
| WWW-Authenticate | string | Always "Bearer". | Bearer |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "unauthorized",
"message": "The API key is not valid.",
"param": null
}
} The request body is larger than 64 KiB.
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "invalid_parameter",
"message": "The request body is larger than 64 KiB.",
"param": null
}
} The per-minute limit of the key is exceeded. Wait for Retry-After seconds.
| Header | Type | Description | Example |
|---|---|---|---|
| X-RateLimit-Limit | integer | Requests per minute allowed for the key. | 60 |
| X-RateLimit-Remaining | integer | Requests left in the current 60 second window. | 59 |
| Retry-After | integer | Seconds to wait before the next request. | 17 |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "rate_limited",
"message": "The limit of 60 requests per minute for this key is exceeded.",
"param": null
}
} Unexpected failure on our side.
| Header | Type | Description | Example |
|---|---|---|---|
| X-RateLimit-Limit | integer | Requests per minute allowed for the key. | 60 |
| X-RateLimit-Remaining | integer | Requests left in the current 60 second window. | 59 |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "internal_error",
"message": "The service failed to process the request.",
"param": null
}
} The service cannot reach its data right now. Retry later.
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| errorrequired | object | Details of the failure. |
|
| error.coderequired | string one of: invalid_parameter, unauthorized, not_found, no_data, rate_limited, internal_error, service_unavailable | Stable machine-readable error code. Branch on this field, not on the message. |
not_found |
| error.messagerequired | string | English sentence for a human. The wording can change between releases. |
Screen 99999 was not found. |
| error.paramrequired | any of | Name of the request parameter or body field that caused the error, or null when the error is not tied to one parameter. Nested body fields use dots, for example "daily_ots.night". |
|
| error.param (option 1)optional | string | ||
| error.param (option 2)optional | null |
{
"error": {
"code": "service_unavailable",
"message": "The service is temporarily unavailable. Retry later.",
"param": null
}
} Example request
curl -X POST 'https://ots.programmatic-engine.ru/v1/calculate' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"daily_ots": {
"day": 60500,
"night": 151100
},
"hourly_share": [
0.036,
0.024,
0.019,
0.013,
0.013,
0.018,
0.026,
0.029,
0.036,
0.042,
0.051,
0.057,
0.062,
0.064,
0.062,
0.061,
0.057,
0.053,
0.051,
0.05,
0.048,
0.046,
0.043,
0.039
],
"day_hours": {
"start": 6,
"end": 19
},
"night_mode": "separate"
}'