# Reporting API V2 > ### Documentation WIP We are actively working on improving these docs. Please reach out if you have any comments or suggestions. ## Concepts This is the new Reporting API. It's designed to be more flexible and easier to work with programmatically. A few differences with our V1 API: * All responses are in JSON instead of CSV. This allows for more flexibility and better error handling. * There are now 2 types of responses: Paginated and Streaming. The latter is more efficient for large results. * Authentication is only done via JWT tokens. Cookie `adama_session` is no longer supported. * The HTTP method to perform requests is now `POST` instead of `GET`. * `fields` is used for both `dimensions` and `metrics`. ### Dataset *This was known as a Report in the previous version of the API.* A dataset is a collection of dimensions and metrics that can be queried. > ### Beta datasets Datasets marked as **(beta)** are subject to change or removal without prior notice, and are offered as is with no support. ### Date fields All datetime fields will be in RFC3339 format. For example: `2023-07-27T12:00:00Z`. > Requests must use this format for `start_time` and `end_time`. When using a `rollup` other than `all`, a field `agg_timestamp` will be included in the response and it will also be available for ordering. This field will have truncated datetime values based on the `rollup` value. ### Time Windows Time windows are used to specify a relative period of time to query. The possible values are: * `current_date`: Today * `yesterday`: Yesterday * `last_N_hours`: Last `N` hours (e.g. `last_12_hours`) up to but not including the current hour. * `last_N_days`: Last `N` days (e.g. `last_7_days`) up to but not including today. * `campaign_to_date`: From the campaign start date to today. * `flight_to_date`: From the flight start date to today. > Not all datasets support all time windows. ### Rollups Rollups are used to aggregate data at different levels. The possible values are: * `all`: No rollup * `by_hour`: Rollup by hour * `by_day`: Rollup by day * `by_week`: Rollup by week, truncated to the first day of the week * `by_month`: Rollup by month, truncated to the first day of the month ## Requests The base URL for the API is https://api.mediamath.com/reporting/v2. Each dataset has its own endpoint, for example: https://api.mediamath.com/reporting/v2/performance. All requests must be made using the `POST` method. The body of the request must be a JSON object with the following schema: ```json { // Array of fields to include in the response "fields": [ "string", "..." ], // Filters to apply to the query "filters": [ { "field": "filter1", "value": 1 } ], // Order to apply to the results "order": [ { // Descending order "desc": false, "field": "agg_timestamp" } ], // Pagination is optional and not all datasets support it "pagination": { "page_size": 100, "page_index": 0 }, "rollup": "by_hour", "time_window": "last_7_days", "start_time": "2023-07-27T00:00:00Z", // end_time is optional "end_time": "2023-07-28T12:00:00Z" } ``` `time_window` and `start_time` are required but mutually exclusive. If both are present, `time_window` will be used. ### Filter A filter is an object with 4 fields: * `field`: The field to filter by * `value`: The value to filter by. Ignored if `op` is `and` or `or`. * `op`: The operator to use for the filter. Defaults to `=`. Possible values: * `=`: Equals or contains if `value` is an array * `!=`: Not equals * `>`: Greater than * `>=`: Greater than or equals * `<`: Less than * `<=`: Less than or equals * `=~`: Text contains (case-insensitive) * `and`: All filters must match * `or`: At least one filter must match * `filters`: An array of filters. Required if `op` is `and` or `or`. ```json { "field": "dimension1", "op": "=~", "value": "Test Campaign" } ``` #### Complex filters When using `and` or `or` operators, the `filters` field must be present. Nesting filters is supported. ```json { "field": "dimension1", "op": "and", "filters": [ { "field": "dimension2", "op": ">=", "value": 100000 }, { "field": "dimension3", "op": "<", "value": 110000 } ] } ``` ## Responses All examples in these docs are formatted and may include comments. The actual responses won't have indentation and will always include a JSON object per line. This is an important clarification because the same type of error message is used for both Paginated and Streaming responses. ### Error responses When an error occurs, the response will include an error code, a request ID, and a message. **When reaching out to support, please include the complete response**. ```json { "error_code": "BadRequest", "request_id": "74K33s47Yd1ns97E9RZsfFhn1Gj0ehYs", "message": "field does not exist in this dataset: campaign_id_test" } ``` ### Paginated response Paginated responses will include a `meta` object with pagination information and a `results` array with the actual data. To use pagination, the request must include a `pagination` object with `page_size` and `page_index`. * `page_size`: The number of records to return per page. The minimum value is `1` and the maximum value is `1000`. * `page_index`: The index of the page to return. The first page is `0`. ```json { // ... "pagination": { "page_size": 100, "page_index": 0 }, // ... } ``` ### Streaming response The response consists of a header followed by the result-set. In case of failure, a special error message will be returned and the stream will finish. Also, at any time there can be a **Metadata** message with additional information. The client is responsible for any validation checks such as checking that `total_items_count` matches the number of records returned. #### Header ```json { "fields": [ { "name": "agg_timestamp" }, { "name": "campaign_id" }, { "name": "impressions" } ], // An integer or -1 if the total number of records couldn't be calculated "total_items_count": 14 } ``` #### Data ```json { "field1": "value1", "field2": 2, "agg_timestamp": "2023-07-27T12:00:00Z" } ``` #### Error A regular error message will be returned in case of failure. The stream will finish after this message. #### Metadata Information such as progress, warnings, or other details that are not part of the result-set. *At the moment there aren't any metadata messages.* ```json { "meta": {} } ``` ## Examples ### Paginated response #### Request ```json { "fields": [ "campaign_id", "impressions" ], "filters": [ { "field": "organization_id", "op": "=", "value": 123456 }, { "field": "advertiser_id", "value": 123456 }, { "field": "campaign_name", "op": "=~", "value": "Test Campaign" } ], "order": [ { "desc": false, "field": "agg_timestamp", "nulls_last": true } ], "pagination": { "page_size": 100, "page_index": 0 }, "rollup": "by_hour", "time_window": "last_7_days" } ``` #### Response ```json { "meta": { "page_index": 0, "total_pages": 1, "items_count": 3, "total_items_count": 3, "status": "OK" }, "results": [ { "campaign_id": 1, "impressions": 93283, "agg_timestamp": "2023-07-27T12:00:00Z" }, { "campaign_id": 2, "impressions": 474, "agg_timestamp": "2023-07-27T12:00:00Z" }, { "campaign_id": 3, "impressions": 45775, "agg_timestamp": "2023-07-27T12:00:00Z" } ] } ``` ### Streaming response #### Request ```json { "fields": [ "campaign_id", "impressions" ], "filters": [ { "field": "organization_id", "op": "=", "value": 123456 }, { "field": "advertiser_id", "value": 123456 }, { "field": "campaign_name", "op": "=~", "value": "Test Campaign" } ], "order": [ { "desc": false, "field": "agg_timestamp", "nulls_last": true } ], "rollup": "by_hour", "time_window": "last_7_days" } ``` #### Successful response > This is formatted for readability but the real response will be a single line per object. ```json { "fields": [ { "name": "agg_timestamp" }, { "name": "campaign_id" }, { "name": "impressions" } ], "total_items_count": 14 } { "campaign_id": 1, "impressions": 93283, "agg_timestamp": "2023-07-27T12:00:00Z" } { "campaign_id": 2, "impressions": 474, "agg_timestamp": "2023-07-27T12:00:00Z" } { "meta": {} } { "campaign_id": 3, "impressions": 45775, "agg_timestamp": "2023-07-27T12:00:00Z" } ``` ### cURL ```bash curl --location 'https://api.mediamath.com/reporting/v2/performance' \ --header 'Content-Type: application/json' \ --header "Authorization: Bearer $JWT_TOKEN" \ --data '{ "fields": [ "campaign_id", "impressions" ], "filters": [ { "field": "organization_id", "op": "=", "value": 123456 }, { "field": "advertiser_id", "value": 123456 }, { "field": "campaign_name", "op": "=~", "value": "Test Campaign" } ], "order": [ { "desc": false, "field": "agg_timestamp", "nulls_last": true } ], "rollup": "by_day", "time_window": "last_7_days" }' ```