Skip to main content

hanzo_client/apis/
affiliate_api.rs

1/*
2 * Hanzo Cloud API
3 *
4 * The Hanzo Cloud API as a customer calls it: every operation under /v1/ except the operator's admin product, relay routes, legacy spellings and capabilities still reached by flag. Tagged by product: the first path segment after /v1/.
5 *
6 * The version of the OpenAPI document: v1
7 * 
8 * Generated by: https://openapi-generator.tech
9 */
10
11
12use reqwest;
13use serde::{Deserialize, Serialize, de::Error as _};
14use crate::{apis::ResponseContent, models};
15use super::{Error, configuration, ContentType};
16
17
18/// struct for typed errors of method [`get_affiliate`]
19#[derive(Debug, Clone, Serialize, Deserialize)]
20#[serde(untagged)]
21pub enum GetAffiliateError {
22    UnknownValue(serde_json::Value),
23}
24
25/// struct for typed errors of method [`get_affiliate_leaderboard`]
26#[derive(Debug, Clone, Serialize, Deserialize)]
27#[serde(untagged)]
28pub enum GetAffiliateLeaderboardError {
29    UnknownValue(serde_json::Value),
30}
31
32/// struct for typed errors of method [`get_affiliate_me`]
33#[derive(Debug, Clone, Serialize, Deserialize)]
34#[serde(untagged)]
35pub enum GetAffiliateMeError {
36    UnknownValue(serde_json::Value),
37}
38
39/// struct for typed errors of method [`get_affiliate_me_earnings`]
40#[derive(Debug, Clone, Serialize, Deserialize)]
41#[serde(untagged)]
42pub enum GetAffiliateMeEarningsError {
43    UnknownValue(serde_json::Value),
44}
45
46/// struct for typed errors of method [`get_affiliate_me_links`]
47#[derive(Debug, Clone, Serialize, Deserialize)]
48#[serde(untagged)]
49pub enum GetAffiliateMeLinksError {
50    UnknownValue(serde_json::Value),
51}
52
53/// struct for typed errors of method [`post_affiliate_apply`]
54#[derive(Debug, Clone, Serialize, Deserialize)]
55#[serde(untagged)]
56pub enum PostAffiliateApplyError {
57    UnknownValue(serde_json::Value),
58}
59
60/// struct for typed errors of method [`post_affiliate_attribute`]
61#[derive(Debug, Clone, Serialize, Deserialize)]
62#[serde(untagged)]
63pub enum PostAffiliateAttributeError {
64    UnknownValue(serde_json::Value),
65}
66
67/// struct for typed errors of method [`post_affiliate_click`]
68#[derive(Debug, Clone, Serialize, Deserialize)]
69#[serde(untagged)]
70pub enum PostAffiliateClickError {
71    UnknownValue(serde_json::Value),
72}
73
74/// struct for typed errors of method [`post_affiliate_me_handle`]
75#[derive(Debug, Clone, Serialize, Deserialize)]
76#[serde(untagged)]
77pub enum PostAffiliateMeHandleError {
78    UnknownValue(serde_json::Value),
79}
80
81/// struct for typed errors of method [`post_affiliate_me_links`]
82#[derive(Debug, Clone, Serialize, Deserialize)]
83#[serde(untagged)]
84pub enum PostAffiliateMeLinksError {
85    UnknownValue(serde_json::Value),
86}
87
88
89/// Answers the caller org's OWN affiliate standing: status, referral code and share link, commission rate, how many orgs it has referred, and its lifetime accrued, still-pending and already-paid commission in integer cents, with its payout history.  An org that never applied gets an honest `isAffiliate:false` and the default rate rather than a 404 — the console renders the apply form off that answer.  The affiliate is resolved from the VALIDATED org, never from a field, so this can only ever read the caller's own row; without a principal it is refused. It is a PURE READ: nothing accrues until the sweep runs. Commission is earned on Hanzo's MARGIN, never on the referred customer's bill, so nothing here changes what that customer pays.
90pub async fn get_affiliate(configuration: &configuration::Configuration, ) -> Result<models::AffiliateStanding, Error<GetAffiliateError>> {
91
92    let uri_str = format!("{}/v1/affiliate", configuration.base_path);
93    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
94
95    if let Some(ref user_agent) = configuration.user_agent {
96        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
97    }
98    if let Some(ref token) = configuration.bearer_access_token {
99        req_builder = req_builder.bearer_auth(token.to_owned());
100    };
101
102    let req = req_builder.build()?;
103    let resp = configuration.client.execute(req).await?;
104
105    let status = resp.status();
106    let content_type = resp
107        .headers()
108        .get("content-type")
109        .and_then(|v| v.to_str().ok())
110        .unwrap_or("application/octet-stream");
111    let content_type = super::ContentType::from(content_type);
112
113    if !status.is_client_error() && !status.is_server_error() {
114        let content = resp.text().await?;
115        match content_type {
116            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
117            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::AffiliateStanding`"))),
118            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::AffiliateStanding`")))),
119        }
120    } else {
121        let content = resp.text().await?;
122        let entity: Option<GetAffiliateError> = serde_json::from_str(&content).ok();
123        Err(Error::ResponseError(ResponseContent { status, content, entity }))
124    }
125}
126
127/// Answers the top affiliates by lifetime accrued commission, shown by OPT-IN HANDLE with aggregate figures only, plus the caller's own exact rank.  It never discloses an org identity and never a referred org's usage. An affiliate that has set no handle still OCCUPIES its rank but is not listed — so opting out hides the name, not the position, and the visible board must not be read as a complete roster.  The caller's own row carries its exact GLOBAL rank, computed over the whole approved set rather than over the page, so it is right well outside the top of the board. Only an approved affiliate has a rank. Requires a validated principal; a signed-in non-affiliate may read the board but gets no personal row.
128pub async fn get_affiliate_leaderboard(configuration: &configuration::Configuration, ) -> Result<models::AffiliateBoard, Error<GetAffiliateLeaderboardError>> {
129
130    let uri_str = format!("{}/v1/affiliate/leaderboard", configuration.base_path);
131    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
132
133    if let Some(ref user_agent) = configuration.user_agent {
134        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
135    }
136    if let Some(ref token) = configuration.bearer_access_token {
137        req_builder = req_builder.bearer_auth(token.to_owned());
138    };
139
140    let req = req_builder.build()?;
141    let resp = configuration.client.execute(req).await?;
142
143    let status = resp.status();
144    let content_type = resp
145        .headers()
146        .get("content-type")
147        .and_then(|v| v.to_str().ok())
148        .unwrap_or("application/octet-stream");
149    let content_type = super::ContentType::from(content_type);
150
151    if !status.is_client_error() && !status.is_server_error() {
152        let content = resp.text().await?;
153        match content_type {
154            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
155            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::AffiliateBoard`"))),
156            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::AffiliateBoard`")))),
157        }
158    } else {
159        let content = resp.text().await?;
160        let entity: Option<GetAffiliateLeaderboardError> = serde_json::from_str(&content).ok();
161        Err(Error::ResponseError(ResponseContent { status, content, entity }))
162    }
163}
164
165/// Answers the richer self-view: the same lifetime accrued, pending and paid commission and payout history, plus the caller's downline broken out by upline LEVEL — direct, second, third — each with the rate paid at that level and how many orgs sit there.  Commission is MULTI-LEVEL: a referred org's spend pays up its referral chain, three levels deep and no further. The direct level is the affiliate's own negotiated rate; the second and third are platform-wide switches, read live, so the schedule shown is the one actually in force rather than one compiled in. A caller that has not applied still gets that schedule alongside `isAffiliate:false`, so the console can show what it would earn.  Scoped to the validated org and nothing else, and refused without a principal. A PURE READ — it reports the downline but accrues nothing.
166pub async fn get_affiliate_me(configuration: &configuration::Configuration, ) -> Result<models::AffiliateSelf, Error<GetAffiliateMeError>> {
167
168    let uri_str = format!("{}/v1/affiliate/me", configuration.base_path);
169    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
170
171    if let Some(ref user_agent) = configuration.user_agent {
172        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
173    }
174    if let Some(ref token) = configuration.bearer_access_token {
175        req_builder = req_builder.bearer_auth(token.to_owned());
176    };
177
178    let req = req_builder.build()?;
179    let resp = configuration.client.execute(req).await?;
180
181    let status = resp.status();
182    let content_type = resp
183        .headers()
184        .get("content-type")
185        .and_then(|v| v.to_str().ok())
186        .unwrap_or("application/octet-stream");
187    let content_type = super::ContentType::from(content_type);
188
189    if !status.is_client_error() && !status.is_server_error() {
190        let content = resp.text().await?;
191        match content_type {
192            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
193            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::AffiliateSelf`"))),
194            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::AffiliateSelf`")))),
195        }
196    } else {
197        let content = resp.text().await?;
198        let entity: Option<GetAffiliateMeError> = serde_json::from_str(&content).ok();
199        Err(Error::ResponseError(ResponseContent { status, content, entity }))
200    }
201}
202
203/// Answers the caller's own commission ledger: per period, the margin it earned against and the commission taken from that margin; and per referred org, that referral's aggregate contribution. Integer cents throughout.  The per-org view deliberately carries the affiliate's OWN earned share and NOT the referred org's spend or margin. An affiliate is entitled to what it earned, not to a restatement of its customer's usage — the period view is where the margin base appears, aggregated across every referral.  Scoped server-side to the validated caller's affiliate; a caller that is not one gets `isAffiliate:false`.
204pub async fn get_affiliate_me_earnings(configuration: &configuration::Configuration, ) -> Result<models::AffiliateEarnings, Error<GetAffiliateMeEarningsError>> {
205
206    let uri_str = format!("{}/v1/affiliate/me/earnings", configuration.base_path);
207    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
208
209    if let Some(ref user_agent) = configuration.user_agent {
210        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
211    }
212    if let Some(ref token) = configuration.bearer_access_token {
213        req_builder = req_builder.bearer_auth(token.to_owned());
214    };
215
216    let req = req_builder.build()?;
217    let resp = configuration.client.execute(req).await?;
218
219    let status = resp.status();
220    let content_type = resp
221        .headers()
222        .get("content-type")
223        .and_then(|v| v.to_str().ok())
224        .unwrap_or("application/octet-stream");
225    let content_type = super::ContentType::from(content_type);
226
227    if !status.is_client_error() && !status.is_server_error() {
228        let content = resp.text().await?;
229        match content_type {
230            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
231            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::AffiliateEarnings`"))),
232            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::AffiliateEarnings`")))),
233        }
234    } else {
235        let content = resp.text().await?;
236        let entity: Option<GetAffiliateMeEarningsError> = serde_json::from_str(&content).ok();
237        Err(Error::ResponseError(ResponseContent { status, content, entity }))
238    }
239}
240
241/// Answers the caller's share links, each with its URL and its funnel: clicks tracked, signups — orgs attributed with that code — and conversions, meaning how many of those signups have actually produced commission.  Signups and conversions are DERIVED from the commission ledger and never stored, so they cannot drift from the money. Clicks are the one stored counter and the one that is pure vanity.  Any pending public click pings are folded into the store before the read, in one batch — which is how the counters stay current without a database write per click. Scoped to the validated caller's own affiliate; a non-affiliate gets `isAffiliate:false` and the link cap.
242pub async fn get_affiliate_me_links(configuration: &configuration::Configuration, ) -> Result<models::AffiliateLinks, Error<GetAffiliateMeLinksError>> {
243
244    let uri_str = format!("{}/v1/affiliate/me/links", configuration.base_path);
245    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
246
247    if let Some(ref user_agent) = configuration.user_agent {
248        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
249    }
250    if let Some(ref token) = configuration.bearer_access_token {
251        req_builder = req_builder.bearer_auth(token.to_owned());
252    };
253
254    let req = req_builder.build()?;
255    let resp = configuration.client.execute(req).await?;
256
257    let status = resp.status();
258    let content_type = resp
259        .headers()
260        .get("content-type")
261        .and_then(|v| v.to_str().ok())
262        .unwrap_or("application/octet-stream");
263    let content_type = super::ContentType::from(content_type);
264
265    if !status.is_client_error() && !status.is_server_error() {
266        let content = resp.text().await?;
267        match content_type {
268            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
269            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::AffiliateLinks`"))),
270            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::AffiliateLinks`")))),
271        }
272    } else {
273        let content = resp.text().await?;
274        let entity: Option<GetAffiliateMeLinksError> = serde_json::from_str(&content).ok();
275        Err(Error::ResponseError(ResponseContent { status, content, entity }))
276    }
277}
278
279/// Enrolls the caller's OWN org as an affiliate at status `applied`, optionally requesting a vanity code, and answers the record — 201 on the first apply, 200 with `created:false` afterwards.  IDEMPOTENT, first apply wins: one affiliate per org, so re-applying never creates a second row and never resets an existing approval. Applying is not joining — no code is minted and nothing accrues until staff approve, which is where both the code and the commission rate come from.  The org is the validated caller's, never a field. A malformed vanity code is refused up front; the code is only REQUESTED here, and approval may mint a different one if the requested code is taken.
280pub async fn post_affiliate_apply(configuration: &configuration::Configuration, apply_request: models::ApplyRequest) -> Result<models::Application, Error<PostAffiliateApplyError>> {
281    // add a prefix to parameters to efficiently prevent name collisions
282    let p_apply_request = apply_request;
283
284    let uri_str = format!("{}/v1/affiliate/apply", configuration.base_path);
285    let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
286
287    if let Some(ref user_agent) = configuration.user_agent {
288        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
289    }
290    if let Some(ref token) = configuration.bearer_access_token {
291        req_builder = req_builder.bearer_auth(token.to_owned());
292    };
293    req_builder = req_builder.json(&p_apply_request);
294
295    let req = req_builder.build()?;
296    let resp = configuration.client.execute(req).await?;
297
298    let status = resp.status();
299    let content_type = resp
300        .headers()
301        .get("content-type")
302        .and_then(|v| v.to_str().ok())
303        .unwrap_or("application/octet-stream");
304    let content_type = super::ContentType::from(content_type);
305
306    if !status.is_client_error() && !status.is_server_error() {
307        let content = resp.text().await?;
308        match content_type {
309            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
310            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::Application`"))),
311            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::Application`")))),
312        }
313    } else {
314        let content = resp.text().await?;
315        let entity: Option<PostAffiliateApplyError> = serde_json::from_str(&content).ok();
316        Err(Error::ResponseError(ResponseContent { status, content, entity }))
317    }
318}
319
320/// Records the first-touch edge every later commission is computed from: the caller's org was referred by the affiliate that owns this code.  The REFERRED org is the validated caller, never a field. A caller that could name the referred org could attach itself to somebody else's revenue. The affiliate is resolved from the code, and only an APPROVED affiliate's code resolves.  FIRST TOUCH WINS, set once: one affiliate per referred org, so a re-post answers the existing edge with `created:false` rather than moving the attribution. Self-attribution is refused, and so is a code that would make a cycle in the upline chain. An unknown code is a 404, deliberately: an affiliate code IS a public shareable link, so whether one is real is public by design, and the caller legitimately needs to know its link resolved.  A user-level mirror of the edge is written best-effort; a conflict there never fails the org attribution, which is the money-bearing one.
321pub async fn post_affiliate_attribute(configuration: &configuration::Configuration, attribute_request: models::AttributeRequest) -> Result<models::Attribution, Error<PostAffiliateAttributeError>> {
322    // add a prefix to parameters to efficiently prevent name collisions
323    let p_attribute_request = attribute_request;
324
325    let uri_str = format!("{}/v1/affiliate/attribute", configuration.base_path);
326    let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
327
328    if let Some(ref user_agent) = configuration.user_agent {
329        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
330    }
331    if let Some(ref token) = configuration.bearer_access_token {
332        req_builder = req_builder.bearer_auth(token.to_owned());
333    };
334    req_builder = req_builder.json(&p_attribute_request);
335
336    let req = req_builder.build()?;
337    let resp = configuration.client.execute(req).await?;
338
339    let status = resp.status();
340    let content_type = resp
341        .headers()
342        .get("content-type")
343        .and_then(|v| v.to_str().ok())
344        .unwrap_or("application/octet-stream");
345    let content_type = super::ContentType::from(content_type);
346
347    if !status.is_client_error() && !status.is_server_error() {
348        let content = resp.text().await?;
349        match content_type {
350            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
351            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::Attribution`"))),
352            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::Attribution`")))),
353        }
354    } else {
355        let content = resp.text().await?;
356        let entity: Option<PostAffiliateAttributeError> = serde_json::from_str(&content).ok();
357        Err(Error::ResponseError(ResponseContent { status, content, entity }))
358    }
359}
360
361/// Counts a click on a share link. PUBLIC — it takes no principal, because a visitor clicking a shareable link has no session yet.  The ping folds into an in-memory buffer and NEVER writes the money database synchronously, so a click flood cannot contend with the accrual and payout write path; tallies are flushed in one batch on the next authenticated links read and at shutdown. Clicks are a vanity metric: no accrual and no payout ever reads them — those key on real metered spend — so click inflation cannot move money.  Any well-formed code is accepted WITHOUT checking that it exists, deliberately: this is not a code-existence oracle. `counted` reports that the buffer took the ping, not that the code is real; an unknown code simply no-ops at flush time.
362pub async fn post_affiliate_click(configuration: &configuration::Configuration, click_request: models::ClickRequest) -> Result<models::ClickCount, Error<PostAffiliateClickError>> {
363    // add a prefix to parameters to efficiently prevent name collisions
364    let p_click_request = click_request;
365
366    let uri_str = format!("{}/v1/affiliate/click", configuration.base_path);
367    let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
368
369    if let Some(ref user_agent) = configuration.user_agent {
370        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
371    }
372    if let Some(ref token) = configuration.bearer_access_token {
373        req_builder = req_builder.bearer_auth(token.to_owned());
374    };
375    req_builder = req_builder.json(&p_click_request);
376
377    let req = req_builder.build()?;
378    let resp = configuration.client.execute(req).await?;
379
380    let status = resp.status();
381    let content_type = resp
382        .headers()
383        .get("content-type")
384        .and_then(|v| v.to_str().ok())
385        .unwrap_or("application/octet-stream");
386    let content_type = super::ContentType::from(content_type);
387
388    if !status.is_client_error() && !status.is_server_error() {
389        let content = resp.text().await?;
390        match content_type {
391            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
392            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::ClickCount`"))),
393            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::ClickCount`")))),
394        }
395    } else {
396        let content = resp.text().await?;
397        let entity: Option<PostAffiliateClickError> = serde_json::from_str(&content).ok();
398        Err(Error::ResponseError(ResponseContent { status, content, entity }))
399    }
400}
401
402/// Sets the caller's public leaderboard display name, or clears it.  The handle IS the opt-in. An empty handle opts out: the affiliate keeps its rank and can still see its own row, it simply stops being listed to anyone else. That is the whole privacy control — there is no separate visibility flag, and no way to be listed without choosing a name.  Requires a validated principal and an existing affiliate record; apply first. The handle is bounded and restricted to letters, digits, space, hyphen, underscore and dot.
403pub async fn post_affiliate_me_handle(configuration: &configuration::Configuration, handle_request: models::HandleRequest) -> Result<models::HandleSet, Error<PostAffiliateMeHandleError>> {
404    // add a prefix to parameters to efficiently prevent name collisions
405    let p_handle_request = handle_request;
406
407    let uri_str = format!("{}/v1/affiliate/me/handle", configuration.base_path);
408    let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
409
410    if let Some(ref user_agent) = configuration.user_agent {
411        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
412    }
413    if let Some(ref token) = configuration.bearer_access_token {
414        req_builder = req_builder.bearer_auth(token.to_owned());
415    };
416    req_builder = req_builder.json(&p_handle_request);
417
418    let req = req_builder.build()?;
419    let resp = configuration.client.execute(req).await?;
420
421    let status = resp.status();
422    let content_type = resp
423        .headers()
424        .get("content-type")
425        .and_then(|v| v.to_str().ok())
426        .unwrap_or("application/octet-stream");
427    let content_type = super::ContentType::from(content_type);
428
429    if !status.is_client_error() && !status.is_server_error() {
430        let content = resp.text().await?;
431        match content_type {
432            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
433            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::HandleSet`"))),
434            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::HandleSet`")))),
435        }
436    } else {
437        let content = resp.text().await?;
438        let entity: Option<PostAffiliateMeHandleError> = serde_json::from_str(&content).ok();
439        Err(Error::ResponseError(ResponseContent { status, content, entity }))
440    }
441}
442
443/// Mints a new share link for the caller's own affiliate and answers it with its full URL, 201.  APPROVAL IS REQUIRED: an org that has applied but is not approved is refused, because a link that cannot accrue is a link that quietly loses the referral. A requested vanity code must be valid and free across the WHOLE directory — codes are one global namespace, so a taken code is a 409 rather than a silent alias. Omit the code and a random one is minted.  Bounded per affiliate. The label is cosmetic: it is trimmed, stripped of control characters and capped, and it is never part of a code.
444pub async fn post_affiliate_me_links(configuration: &configuration::Configuration, create_link_request: models::CreateLinkRequest) -> Result<models::LinkMint, Error<PostAffiliateMeLinksError>> {
445    // add a prefix to parameters to efficiently prevent name collisions
446    let p_create_link_request = create_link_request;
447
448    let uri_str = format!("{}/v1/affiliate/me/links", configuration.base_path);
449    let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
450
451    if let Some(ref user_agent) = configuration.user_agent {
452        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
453    }
454    if let Some(ref token) = configuration.bearer_access_token {
455        req_builder = req_builder.bearer_auth(token.to_owned());
456    };
457    req_builder = req_builder.json(&p_create_link_request);
458
459    let req = req_builder.build()?;
460    let resp = configuration.client.execute(req).await?;
461
462    let status = resp.status();
463    let content_type = resp
464        .headers()
465        .get("content-type")
466        .and_then(|v| v.to_str().ok())
467        .unwrap_or("application/octet-stream");
468    let content_type = super::ContentType::from(content_type);
469
470    if !status.is_client_error() && !status.is_server_error() {
471        let content = resp.text().await?;
472        match content_type {
473            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
474            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::LinkMint`"))),
475            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::LinkMint`")))),
476        }
477    } else {
478        let content = resp.text().await?;
479        let entity: Option<PostAffiliateMeLinksError> = serde_json::from_str(&content).ok();
480        Err(Error::ResponseError(ResponseContent { status, content, entity }))
481    }
482}
483