/*
* 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.104.0
* 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 [`archive_lead_form`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum ArchiveLeadFormError {
Status400(models::ErrorResponse),
Status401(models::InlineObject1),
Status404(),
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`create_lead_form`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum CreateLeadFormError {
Status400(models::ErrorResponse),
Status401(models::InlineObject1),
Status403(),
Status422(),
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`create_test_lead`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum CreateTestLeadError {
Status400(models::ErrorResponse),
Status401(models::InlineObject1),
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`delete_test_lead`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum DeleteTestLeadError {
Status400(models::ErrorResponse),
Status401(models::InlineObject1),
Status404(),
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`get_lead_form`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum GetLeadFormError {
Status400(models::ErrorResponse),
Status401(models::InlineObject1),
Status404(),
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`list_form_leads`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum ListFormLeadsError {
Status400(models::ErrorResponse),
Status401(models::InlineObject1),
Status404(models::ErrorResponse),
Status409(models::ErrorResponse),
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`list_lead_forms`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum ListLeadFormsError {
Status400(models::ErrorResponse),
Status401(models::InlineObject1),
Status403(),
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`list_leads`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum ListLeadsError {
Status400(models::ErrorResponse),
Status401(models::InlineObject1),
Status403(),
Status502(models::ErrorResponse),
Status503(models::ErrorResponse),
UnknownValue(serde_json::Value),
}
/// Neither platform hard-deletes a form; this archives it (Meta status=ARCHIVED; LinkedIn state=ARCHIVED via PARTIAL_UPDATE). Meta forms must belong to the Page the accountId manages.
pub async fn archive_lead_form(
configuration: &configuration::Configuration,
form_id: &str,
account_id: &str,
) -> Result<models::ArchiveLeadForm200Response, Error<ArchiveLeadFormError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_path_form_id = form_id;
let p_query_account_id = account_id;
let uri_str = format!(
"{}/v1/ads/lead-forms/{formId}",
configuration.base_path,
formId = crate::apis::urlencode(p_path_form_id)
);
let mut req_builder = configuration
.client
.request(reqwest::Method::DELETE, &uri_str);
req_builder = req_builder.query(&[("accountId", &p_query_account_id.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::ArchiveLeadForm200Response`"))),
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::ArchiveLeadForm200Response`")))),
}
} else {
let content = resp.text().await?;
let entity: Option<ArchiveLeadFormError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent {
status,
content,
entity,
}))
}
}
/// Creates a Lead Gen form. The form content goes inside `platformSpecificData` for both platforms (the shape is selected by the accountId's platform). Meta: created on the connected Facebook Page (POST /{page-id}/leadgen_forms), where `accountId` may be the `metaads` ads connection (its Page comes from the Facebook account linked to the same profile) or the Facebook account itself; the old top-level Meta fields (questions, thankYou*, contextCard, …) are DEPRECATED but still accepted while platformSpecificData is absent; mixing both shapes is a 400. LinkedIn: created on the ad account's Company Page. NOT idempotent: a retry creates a second form. Meta prefilled question types (EMAIL, PHONE, FULL_NAME, …) must omit label/key; CUSTOM questions require both. LinkedIn exposes only free-text and multiple-choice questions via API (prefilled-from-profile fields are Campaign Manager UI-only). Requires the Ads add-on.
pub async fn create_lead_form(
configuration: &configuration::Configuration,
create_lead_form_request: models::CreateLeadFormRequest,
) -> Result<models::CreateLeadForm200Response, Error<CreateLeadFormError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_create_lead_form_request = create_lead_form_request;
let uri_str = format!("{}/v1/ads/lead-forms", 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(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_create_lead_form_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::CreateLeadForm200Response`"))),
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::CreateLeadForm200Response`")))),
}
} else {
let content = resp.text().await?;
let entity: Option<CreateLeadFormError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent {
status,
content,
entity,
}))
}
}
/// Submits a test lead against the form (POST /{form-id}/test_leads) to exercise retrieval without waiting for real ad impressions. Meta allows one test lead per form at a time.
pub async fn create_test_lead(
configuration: &configuration::Configuration,
form_id: &str,
create_test_lead_request: models::CreateTestLeadRequest,
) -> Result<models::CreateTestLead200Response, Error<CreateTestLeadError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_path_form_id = form_id;
let p_body_create_test_lead_request = create_test_lead_request;
let uri_str = format!(
"{}/v1/ads/lead-forms/{formId}/test-leads",
configuration.base_path,
formId = crate::apis::urlencode(p_path_form_id)
);
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(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_create_test_lead_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::CreateTestLead200Response`"))),
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::CreateTestLead200Response`")))),
}
} else {
let content = resp.text().await?;
let entity: Option<CreateTestLeadError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent {
status,
content,
entity,
}))
}
}
/// Removes a test lead created for the form (DELETE /{leadgen_id}), so a new one can be submitted: Meta keeps one test lead per form and refuses a second until the first is gone. The same test lead appears in Meta's Lead Ads Testing Tool. Meta only deletes test leads; a real lead is refused.
pub async fn delete_test_lead(
configuration: &configuration::Configuration,
form_id: &str,
account_id: &str,
lead_id: Option<&str>,
) -> Result<models::DeleteTestLead200Response, Error<DeleteTestLeadError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_path_form_id = form_id;
let p_query_account_id = account_id;
let p_query_lead_id = lead_id;
let uri_str = format!(
"{}/v1/ads/lead-forms/{formId}/test-leads",
configuration.base_path,
formId = crate::apis::urlencode(p_path_form_id)
);
let mut req_builder = configuration
.client
.request(reqwest::Method::DELETE, &uri_str);
req_builder = req_builder.query(&[("accountId", &p_query_account_id.to_string())]);
if let Some(ref param_value) = p_query_lead_id {
req_builder = req_builder.query(&[("leadId", ¶m_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::DeleteTestLead200Response`"))),
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::DeleteTestLead200Response`")))),
}
} else {
let content = resp.text().await?;
let entity: Option<DeleteTestLeadError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent {
status,
content,
entity,
}))
}
}
/// Returns the full form, including the thank-you page, so a form can be diffed against what was created. Meta forms are scoped to the Page the accountId manages: a form on any other Page is a 404, never a read.
pub async fn get_lead_form(
configuration: &configuration::Configuration,
form_id: &str,
account_id: &str,
fields: Option<&str>,
) -> Result<models::GetLeadForm200Response, Error<GetLeadFormError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_path_form_id = form_id;
let p_query_account_id = account_id;
let p_query_fields = fields;
let uri_str = format!(
"{}/v1/ads/lead-forms/{formId}",
configuration.base_path,
formId = crate::apis::urlencode(p_path_form_id)
);
let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
req_builder = req_builder.query(&[("accountId", &p_query_account_id.to_string())]);
if let Some(ref param_value) = p_query_fields {
req_builder = req_builder.query(&[("fields", ¶m_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::GetLeadForm200Response`"))),
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::GetLeadForm200Response`")))),
}
} else {
let content = resp.text().await?;
let entity: Option<GetLeadFormError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent {
status,
content,
entity,
}))
}
}
/// Returns leads for one form. Serves persisted leads (ingested via the leadgen webhook) when available, falling back to a live Graph read. Accepts a Facebook account or a metaads business-login account with leads_retrieval access to the form; the latter uses its system-user token without a posting parent.
pub async fn list_form_leads(
configuration: &configuration::Configuration,
form_id: &str,
account_id: &str,
limit: Option<i32>,
cursor: Option<&str>,
since: Option<i32>,
) -> Result<models::ListFormLeads200Response, Error<ListFormLeadsError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_path_form_id = form_id;
let p_query_account_id = account_id;
let p_query_limit = limit;
let p_query_cursor = cursor;
let p_query_since = since;
let uri_str = format!(
"{}/v1/ads/lead-forms/{formId}/leads",
configuration.base_path,
formId = crate::apis::urlencode(p_path_form_id)
);
let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
req_builder = req_builder.query(&[("accountId", &p_query_account_id.to_string())]);
if let Some(ref param_value) = p_query_limit {
req_builder = req_builder.query(&[("limit", ¶m_value.to_string())]);
}
if let Some(ref param_value) = p_query_cursor {
req_builder = req_builder.query(&[("cursor", ¶m_value.to_string())]);
}
if let Some(ref param_value) = p_query_since {
req_builder = req_builder.query(&[("since", ¶m_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::ListFormLeads200Response`"))),
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::ListFormLeads200Response`")))),
}
} else {
let content = resp.text().await?;
let entity: Option<ListFormLeadsError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent {
status,
content,
entity,
}))
}
}
/// Lists the Lead Gen forms owned by the account. Meta: forms on the connected Facebook Page. Pass either the `metaads` ads connection (the Page is taken from the Facebook account linked to it) or the Facebook account itself. LinkedIn: forms owned by the ad account's Company Page. Pass `adAccountId` (LinkedIn forms are org-owned). Requires the Ads add-on.
pub async fn list_lead_forms(
configuration: &configuration::Configuration,
account_id: &str,
ad_account_id: Option<&str>,
limit: Option<i32>,
cursor: Option<&str>,
) -> Result<models::ListLeadForms200Response, Error<ListLeadFormsError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_query_account_id = account_id;
let p_query_ad_account_id = ad_account_id;
let p_query_limit = limit;
let p_query_cursor = cursor;
let uri_str = format!("{}/v1/ads/lead-forms", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
req_builder = req_builder.query(&[("accountId", &p_query_account_id.to_string())]);
if let Some(ref param_value) = p_query_ad_account_id {
req_builder = req_builder.query(&[("adAccountId", ¶m_value.to_string())]);
}
if let Some(ref param_value) = p_query_limit {
req_builder = req_builder.query(&[("limit", ¶m_value.to_string())]);
}
if let Some(ref param_value) = p_query_cursor {
req_builder = req_builder.query(&[("cursor", ¶m_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::ListLeadForms200Response`"))),
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::ListLeadForms200Response`")))),
}
} else {
let content = resp.text().await?;
let entity: Option<ListLeadFormsError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent {
status,
content,
entity,
}))
}
}
/// Returns submitted Lead Gen leads for your team, newest-first, with keyset pagination on `cursor`. For Meta (default) leads are served from the persisted cache, ingested in real time from the `leadgen` webhook. When `accountId` is a LinkedIn ads account, leads are fetched live from LinkedIn's `leadFormResponses` (LinkedIn has no webhook and enforces 90-day retention, so nothing is persisted) and `adAccountId` is required. Reading LinkedIn responses needs the `r_marketing_leadgen_automation` permission; accounts connected before it was added must reconnect. Requires the Ads add-on.
pub async fn list_leads(
configuration: &configuration::Configuration,
form_id: Option<&str>,
account_id: Option<&str>,
ad_account_id: Option<&str>,
limit: Option<i32>,
since: Option<i32>,
cursor: Option<&str>,
) -> Result<models::ListLeads200Response, Error<ListLeadsError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_query_form_id = form_id;
let p_query_account_id = account_id;
let p_query_ad_account_id = ad_account_id;
let p_query_limit = limit;
let p_query_since = since;
let p_query_cursor = cursor;
let uri_str = format!("{}/v1/ads/leads", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
if let Some(ref param_value) = p_query_form_id {
req_builder = req_builder.query(&[("formId", ¶m_value.to_string())]);
}
if let Some(ref param_value) = p_query_account_id {
req_builder = req_builder.query(&[("accountId", ¶m_value.to_string())]);
}
if let Some(ref param_value) = p_query_ad_account_id {
req_builder = req_builder.query(&[("adAccountId", ¶m_value.to_string())]);
}
if let Some(ref param_value) = p_query_limit {
req_builder = req_builder.query(&[("limit", ¶m_value.to_string())]);
}
if let Some(ref param_value) = p_query_since {
req_builder = req_builder.query(&[("since", ¶m_value.to_string())]);
}
if let Some(ref param_value) = p_query_cursor {
req_builder = req_builder.query(&[("cursor", ¶m_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::ListLeads200Response`"))),
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::ListLeads200Response`")))),
}
} else {
let content = resp.text().await?;
let entity: Option<ListLeadsError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent {
status,
content,
entity,
}))
}
}