late 0.0.1369

API reference for Zernio. Authenticate with a Bearer API key. Base URL: https://zernio.com/api Versioning and deprecation: all endpoints are versioned in the URL path (current version: /v1). Breaking changes only ship in a new path version; existing versions keep working. Deprecated operations are marked 'deprecated: true' in this spec and announced in the changelog (https://zernio.com/changelog) before removal. Errors: every 4xx/5xx response is application/json with a machine-readable 'code' and a human-readable 'error' message (see the ErrorResponse schema). Request ids: responses carry an X-Request-Id header with the id we log the request under. Quote it when reporting a problem. A valid x-request-id you send is reused as that id.
Documentation
/*
 * Zernio API
 *
 * API reference for Zernio. Authenticate with a Bearer API key. Base URL: https://zernio.com/api  Versioning and deprecation: all endpoints are versioned in the URL path (current version: /v1). Breaking changes only ship in a new path version; existing versions keep working. Deprecated operations are marked 'deprecated: true' in this spec and announced in the changelog (https://zernio.com/changelog) before removal.  Errors: every 4xx/5xx response is application/json with a machine-readable 'code' and a human-readable 'error' message (see the ErrorResponse schema).  Request ids: responses carry an X-Request-Id header with the id we log the request under. Quote it when reporting a problem. A valid x-request-id you send is reused as that id.
 *
 * The version of the OpenAPI document: 1.565.5
 * Contact: support@zernio.com
 * Generated by: https://openapi-generator.tech
 */

use super::{configuration, ContentType, Error};
use crate::{apis::ResponseContent, models};
use reqwest;
use serde::{de::Error as _, Deserialize, Serialize};

/// struct for typed errors of method [`get_campaign_results_totals`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum GetCampaignResultsTotalsError {
    Status400(models::ErrorResponse),
    Status401(models::ErrorResponse),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`get_campaign_results_upload`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum GetCampaignResultsUploadError {
    Status401(models::ErrorResponse),
    Status404(models::InlineObject2),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`list_campaign_result_metrics`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum ListCampaignResultMetricsError {
    Status401(models::ErrorResponse),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`list_campaign_results`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum ListCampaignResultsError {
    Status400(models::ErrorResponse),
    Status401(models::ErrorResponse),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`set_campaign_result_metric`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum SetCampaignResultMetricError {
    Status400(models::ErrorResponse),
    Status401(models::ErrorResponse),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`upload_campaign_results`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum UploadCampaignResultsError {
    Status400(models::ErrorResponse),
    Status401(models::ErrorResponse),
    Status403(),
    Status409(),
    Status413(),
    Status422(),
    Status429(models::ErrorResponse),
    UnknownValue(serde_json::Value),
}

/// Each metric you send summed over a date range across every campaign of the ad accounts your key can see, or of the ones you name. Each day counts its newest uploaded value only, plus the events sent to `POST /v1/events` that are tied to a campaign.  An event counts here up to 15 minutes after it arrives.  Formulas are not computed here, since they also read the platform's numbers: apply one to these totals and the account's spend for the same range, or read it per campaign from `GET /v1/ads/tree?results=true`.
pub async fn get_campaign_results_totals(
    configuration: &configuration::Configuration,
    from_date: String,
    to_date: String,
    ad_account_ids: Option<&str>,
) -> Result<models::GetCampaignResultsTotals200Response, Error<GetCampaignResultsTotalsError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_query_from_date = from_date;
    let p_query_to_date = to_date;
    let p_query_ad_account_ids = ad_account_ids;

    let uri_str = format!("{}/v1/ads/campaign-results/totals", configuration.base_path);
    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);

    req_builder = req_builder.query(&[("fromDate", &p_query_from_date.to_string())]);
    req_builder = req_builder.query(&[("toDate", &p_query_to_date.to_string())]);
    if let Some(ref param_value) = p_query_ad_account_ids {
        req_builder = req_builder.query(&[("adAccountIds", &param_value.to_string())]);
    }
    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref token) = configuration.bearer_access_token {
        req_builder = req_builder.bearer_auth(token.to_owned());
    };

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::GetCampaignResultsTotals200Response`"))),
            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::GetCampaignResultsTotals200Response`")))),
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<GetCampaignResultsTotalsError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}

/// How an upload was matched: rows matched and unmatched, and up to 100 unmatched rows with why (`no_campaign` or `ambiguous`).  `status` turns `done` once every row is processed, usually within seconds. Uploads are kept for 30 days.  A `failed` upload says why in `failureReason`. Send it again: re-sending a day replaces it, so nothing is counted twice.
pub async fn get_campaign_results_upload(
    configuration: &configuration::Configuration,
    upload_id: &str,
) -> Result<models::GetCampaignResultsUpload200Response, Error<GetCampaignResultsUploadError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_path_upload_id = upload_id;

    let uri_str = format!(
        "{}/v1/ads/campaign-results/uploads/{uploadId}",
        configuration.base_path,
        uploadId = crate::apis::urlencode(p_path_upload_id)
    );
    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);

    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref token) = configuration.bearer_access_token {
        req_builder = req_builder.bearer_auth(token.to_owned());
    };

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::GetCampaignResultsUpload200Response`"))),
            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::GetCampaignResultsUpload200Response`")))),
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<GetCampaignResultsUploadError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}

/// The metric keys your team has sent, with their label and kind, then the formulas: your own and the built-in ones (`cac_percent`, `cost_per_sale`, `cost_per_qualified_lead`, `lead_to_sale`). A new key appears as a `count` labelled from the key; name it, or define a formula, with `PUT /v1/ads/campaign-results/metrics/{key}`.
pub async fn list_campaign_result_metrics(
    configuration: &configuration::Configuration,
) -> Result<models::ListCampaignResultMetrics200Response, Error<ListCampaignResultMetricsError>> {
    let uri_str = format!(
        "{}/v1/ads/campaign-results/metrics",
        configuration.base_path
    );
    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);

    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref token) = configuration.bearer_access_token {
        req_builder = req_builder.bearer_auth(token.to_owned());
    };

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::ListCampaignResultMetrics200Response`"))),
            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::ListCampaignResultMetrics200Response`")))),
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<ListCampaignResultMetricsError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}

/// Your results summed per campaign over a date range, one entry per campaign with every metric it has, for the ad accounts your key can see. Each day counts its newest uploaded value only, plus the events sent to `POST /v1/events` that are tied to the campaign (`sales`, `revenue`, `leads`, `qualified_leads`).  An event counts here up to 15 minutes after it arrives.  Paginated by campaign: pass `nextCursor` back as `cursor` until it is null.
pub async fn list_campaign_results(
    configuration: &configuration::Configuration,
    from_date: String,
    to_date: String,
    campaign_ids: Option<&str>,
    limit: Option<i32>,
    cursor: Option<&str>,
) -> Result<models::ListCampaignResults200Response, Error<ListCampaignResultsError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_query_from_date = from_date;
    let p_query_to_date = to_date;
    let p_query_campaign_ids = campaign_ids;
    let p_query_limit = limit;
    let p_query_cursor = cursor;

    let uri_str = format!("{}/v1/ads/campaign-results", configuration.base_path);
    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);

    req_builder = req_builder.query(&[("fromDate", &p_query_from_date.to_string())]);
    req_builder = req_builder.query(&[("toDate", &p_query_to_date.to_string())]);
    if let Some(ref param_value) = p_query_campaign_ids {
        req_builder = req_builder.query(&[("campaignIds", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_limit {
        req_builder = req_builder.query(&[("limit", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_cursor {
        req_builder = req_builder.query(&[("cursor", &param_value.to_string())]);
    }
    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref token) = configuration.bearer_access_token {
        req_builder = req_builder.bearer_auth(token.to_owned());
    };

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::ListCampaignResults200Response`"))),
            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::ListCampaignResults200Response`")))),
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<ListCampaignResultsError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}

/// Sets a metric key's label and kind: `count` for things you count (leads, sales), `money` with its currency (revenue), `percent` or `ratio`.  Send `formula` to make it a computed metric: `+ - * /` and parentheses over `spend`, `impressions`, `clicks`, `conversions`, `purchase_value` and the metrics you send, at most 200 characters. A formula cannot read another formula.  It is computed per campaign over the summed values of the range, and has no value when an input is missing or a division is by zero.
pub async fn set_campaign_result_metric(
    configuration: &configuration::Configuration,
    key: &str,
    set_campaign_result_metric_request: models::SetCampaignResultMetricRequest,
) -> Result<models::SetCampaignResultMetric200Response, Error<SetCampaignResultMetricError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_path_key = key;
    let p_body_set_campaign_result_metric_request = set_campaign_result_metric_request;

    let uri_str = format!(
        "{}/v1/ads/campaign-results/metrics/{key}",
        configuration.base_path,
        key = crate::apis::urlencode(p_path_key)
    );
    let mut req_builder = configuration.client.request(reqwest::Method::PUT, &uri_str);

    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref token) = configuration.bearer_access_token {
        req_builder = req_builder.bearer_auth(token.to_owned());
    };
    req_builder = req_builder.json(&p_body_set_campaign_result_metric_request);

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::SetCampaignResultMetric200Response`"))),
            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::SetCampaignResultMetric200Response`")))),
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<SetCampaignResultMetricError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}

/// Sends your own daily numbers per campaign (qualified leads, sales, revenue...) so rules and reports can use them next to spend.  Name each row's campaign by `campaignId`, `utmCampaign` or `campaignName`. Rows are matched in the background: the `202` returns an `uploadId`, and `Location` points to `GET /v1/ads/campaign-results/uploads/{uploadId}`.  Re-sending a day replaces it. Send an `Idempotency-Key` to retry safely. Limits per team: 60 requests and 20,000 rows per hour, 512 KB per request.
pub async fn upload_campaign_results(
    configuration: &configuration::Configuration,
    upload_campaign_results_request: models::UploadCampaignResultsRequest,
    idempotency_key: Option<&str>,
) -> Result<models::UploadCampaignResults202Response, Error<UploadCampaignResultsError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_body_upload_campaign_results_request = upload_campaign_results_request;
    let p_header_idempotency_key = idempotency_key;

    let uri_str = format!("{}/v1/ads/campaign-results", configuration.base_path);
    let mut req_builder = configuration
        .client
        .request(reqwest::Method::POST, &uri_str);

    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(param_value) = p_header_idempotency_key {
        req_builder = req_builder.header("Idempotency-Key", param_value.to_string());
    }
    if let Some(ref token) = configuration.bearer_access_token {
        req_builder = req_builder.bearer_auth(token.to_owned());
    };
    req_builder = req_builder.json(&p_body_upload_campaign_results_request);

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::UploadCampaignResults202Response`"))),
            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::UploadCampaignResults202Response`")))),
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<UploadCampaignResultsError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}