Skip to main content

ghl_sdk/services/
conversations.rs

1// @generated by xtask/generate_services.py — do not edit by hand.
2//! `conversations` — typed methods for all 29 API v2 operations
3//! in this module.
4//!
5//! These methods live on the same [`ConversationsService`](crate::conversations::ConversationsService) you get from [`Ghl::conversations`](crate::Ghl::conversations), alongside the hand-written helpers.
6//!
7//! Request and response types come from [`ghl_models::v2::conversations`](https://docs.rs/ghl-models/latest/ghl_models/v2/conversations/); every endpoint is also documented in the
8//! [`conversations` API reference](https://github.com/Shahroz/ghl-rs/blob/main/docs/api/conversations.md).
9//!
10//! Enable with `features = ["conversations"]`.
11
12#![allow(clippy::too_many_arguments)]
13
14use crate::error::Result;
15use ghl_models::v2::conversations as models;
16
17use crate::conversations::ConversationsService;
18
19/// Query parameters for [`ConversationsService::export_messages_by_location_id`].
20#[derive(Debug, Clone, Default)]
21pub struct ExportMessagesByLocationIdParams {
22    /// Location ID to filter messages by
23    /// Required by the API.
24    pub location_id: String,
25    /// Number of messages to return per page
26    pub limit: Option<f64>,
27    /// Cursor for pagination. Pass the nextCursor from previous response to get next page.
28    pub cursor: Option<String>,
29    /// Field to sort by
30    /// Allowed values: `createdAt`, `updatedAt`.
31    pub sort_by: Option<String>,
32    /// Sort order
33    /// Allowed values: `asc`, `desc`.
34    pub sort_order: Option<String>,
35    /// Filter messages by conversation ID
36    pub conversation_id: Option<String>,
37    /// Filter messages by contact ID
38    pub contact_id: Option<String>,
39    /// Filter by message channel. If not provided, all non-email message types will be
40    /// returned including activity messages (opportunity updates, appointments, etc.)
41    /// Allowed values: `Call`, `SMS`, `Email`, `WhatsApp`, `Instagram`, `Facebook`.
42    pub channel: Option<String>,
43    /// Start date to filter messages by
44    pub start_date: Option<String>,
45    /// End date to filter messages by
46    pub end_date: Option<String>,
47}
48
49impl ExportMessagesByLocationIdParams {
50    /// Start from the parameters the API requires.
51    pub fn new(location_id: impl Into<String>) -> Self {
52        Self {
53            location_id: location_id.into(),
54            ..Default::default()
55        }
56    }
57
58    /// Number of messages to return per page
59    pub fn limit(mut self, v: f64) -> Self {
60        self.limit = Some(v);
61        self
62    }
63
64    /// Cursor for pagination. Pass the nextCursor from previous response to get next page.
65    pub fn cursor(mut self, v: impl Into<String>) -> Self {
66        self.cursor = Some(v.into());
67        self
68    }
69
70    /// Field to sort by
71    pub fn sort_by(mut self, v: impl Into<String>) -> Self {
72        self.sort_by = Some(v.into());
73        self
74    }
75
76    /// Sort order
77    pub fn sort_order(mut self, v: impl Into<String>) -> Self {
78        self.sort_order = Some(v.into());
79        self
80    }
81
82    /// Filter messages by conversation ID
83    pub fn conversation_id(mut self, v: impl Into<String>) -> Self {
84        self.conversation_id = Some(v.into());
85        self
86    }
87
88    /// Filter messages by contact ID
89    pub fn contact_id(mut self, v: impl Into<String>) -> Self {
90        self.contact_id = Some(v.into());
91        self
92    }
93
94    /// Filter by message channel. If not provided, all non-email message types will be
95    /// returned including activity messages (opportunity updates, appointments, etc.)
96    pub fn channel(mut self, v: impl Into<String>) -> Self {
97        self.channel = Some(v.into());
98        self
99    }
100
101    /// Start date to filter messages by
102    pub fn start_date(mut self, v: impl Into<String>) -> Self {
103        self.start_date = Some(v.into());
104        self
105    }
106
107    /// End date to filter messages by
108    pub fn end_date(mut self, v: impl Into<String>) -> Self {
109        self.end_date = Some(v.into());
110        self
111    }
112
113    fn to_query(&self) -> Vec<(String, String)> {
114        let mut q: Vec<(String, String)> = vec![("locationId".into(), self.location_id.clone())];
115        if let Some(v) = &self.limit {
116            q.push(("limit".into(), v.to_string()));
117        }
118        if let Some(v) = &self.cursor {
119            q.push(("cursor".into(), v.to_string()));
120        }
121        if let Some(v) = &self.sort_by {
122            q.push(("sortBy".into(), v.to_string()));
123        }
124        if let Some(v) = &self.sort_order {
125            q.push(("sortOrder".into(), v.to_string()));
126        }
127        if let Some(v) = &self.conversation_id {
128            q.push(("conversationId".into(), v.to_string()));
129        }
130        if let Some(v) = &self.contact_id {
131            q.push(("contactId".into(), v.to_string()));
132        }
133        if let Some(v) = &self.channel {
134            q.push(("channel".into(), v.to_string()));
135        }
136        if let Some(v) = &self.start_date {
137            q.push(("startDate".into(), v.to_string()));
138        }
139        if let Some(v) = &self.end_date {
140            q.push(("endDate".into(), v.to_string()));
141        }
142        q
143    }
144}
145
146/// Query parameters for [`ConversationsService::get_all_custom_subtypes`].
147#[derive(Debug, Clone, Default)]
148pub struct GetAllCustomSubtypesParams {
149    /// Location Id
150    /// Required by the API.
151    pub location_id: String,
152}
153
154impl GetAllCustomSubtypesParams {
155    /// Start from the parameters the API requires.
156    pub fn new(location_id: impl Into<String>) -> Self {
157        Self {
158            location_id: location_id.into(),
159        }
160    }
161
162    fn to_query(&self) -> Vec<(String, String)> {
163        let q: Vec<(String, String)> = vec![("locationId".into(), self.location_id.clone())];
164        q
165    }
166}
167
168/// Query parameters for [`ConversationsService::create_custom_subtype`].
169#[derive(Debug, Clone, Default)]
170pub struct CreateCustomSubtypeParams {
171    /// Location Id
172    /// Required by the API.
173    pub location_id: String,
174}
175
176impl CreateCustomSubtypeParams {
177    /// Start from the parameters the API requires.
178    pub fn new(location_id: impl Into<String>) -> Self {
179        Self {
180            location_id: location_id.into(),
181        }
182    }
183
184    fn to_query(&self) -> Vec<(String, String)> {
185        let q: Vec<(String, String)> = vec![("locationId".into(), self.location_id.clone())];
186        q
187    }
188}
189
190/// Query parameters for [`ConversationsService::update_custom_subtype`].
191#[derive(Debug, Clone, Default)]
192pub struct UpdateCustomSubtypeParams {
193    /// Location Id
194    /// Required by the API.
195    pub location_id: String,
196}
197
198impl UpdateCustomSubtypeParams {
199    /// Start from the parameters the API requires.
200    pub fn new(location_id: impl Into<String>) -> Self {
201        Self {
202            location_id: location_id.into(),
203        }
204    }
205
206    fn to_query(&self) -> Vec<(String, String)> {
207        let q: Vec<(String, String)> = vec![("locationId".into(), self.location_id.clone())];
208        q
209    }
210}
211
212/// Query parameters for [`ConversationsService::get_contact_unsubscription_status`].
213#[derive(Debug, Clone, Default)]
214pub struct GetContactUnsubscriptionStatusParams {
215    /// Location Id
216    /// Required by the API.
217    pub location_id: String,
218    /// Contact Id
219    /// Required by the API.
220    pub contact_id: String,
221    /// Email address (optional - if not provided, gets all emails for contact)
222    pub email: Option<String>,
223}
224
225impl GetContactUnsubscriptionStatusParams {
226    /// Start from the parameters the API requires.
227    pub fn new(location_id: impl Into<String>, contact_id: impl Into<String>) -> Self {
228        Self {
229            location_id: location_id.into(),
230            contact_id: contact_id.into(),
231            ..Default::default()
232        }
233    }
234
235    /// Email address (optional - if not provided, gets all emails for contact)
236    pub fn email(mut self, v: impl Into<String>) -> Self {
237        self.email = Some(v.into());
238        self
239    }
240
241    fn to_query(&self) -> Vec<(String, String)> {
242        let mut q: Vec<(String, String)> = vec![
243            ("locationId".into(), self.location_id.clone()),
244            ("contactId".into(), self.contact_id.clone()),
245        ];
246        if let Some(v) = &self.email {
247            q.push(("email".into(), v.to_string()));
248        }
249        q
250    }
251}
252
253/// Query parameters for [`ConversationsService::search_conversations`].
254#[derive(Debug, Clone, Default)]
255pub struct SearchConversationsParams {
256    /// Location Id
257    /// Required by the API.
258    pub location_id: String,
259    /// Contact Id
260    pub contact_id: Option<String>,
261    /// User IDs that conversations are assigned to. Multiple IDs can be provided as
262    /// comma-separated values. Use "unassigned" to fetch conversations not assigned to any
263    /// user.
264    pub assigned_to: Option<String>,
265    /// User IDs of followers to filter conversations by. Multiple IDs can be provided as
266    /// comma-separated values.
267    pub followers: Option<String>,
268    /// User Id of the mention. Multiple values are comma separated.
269    pub mentions: Option<String>,
270    /// Search paramater as a string
271    pub query: Option<String>,
272    /// Sort paramater - asc or desc
273    /// Allowed values: `asc`, `desc`.
274    pub sort: Option<String>,
275    /// Search to begin after the specified date - should contain the sort value of the last
276    /// document
277    pub start_after_date: Option<String>,
278    /// Id of the conversation
279    pub id: Option<String>,
280    /// Limit of conversations - Default is 20
281    pub limit: Option<f64>,
282    /// Type of the last message in the conversation as a string
283    /// Allowed values: `TYPE_CALL`, `TYPE_SMS`, `TYPE_RCS`, `TYPE_EMAIL`,
284    /// `TYPE_SMS_REVIEW_REQUEST`, `TYPE_WEBCHAT`, `TYPE_SMS_NO_SHOW_REQUEST`,
285    /// `TYPE_CAMPAIGN_SMS`, `TYPE_CAMPAIGN_CALL`, `TYPE_CAMPAIGN_EMAIL`.
286    pub last_message_type: Option<String>,
287    /// Action of the last outbound message in the conversation as string.
288    /// Allowed values: `automated`, `manual`.
289    pub last_message_action: Option<String>,
290    /// Direction of the last message in the conversation as string.
291    /// Allowed values: `inbound`, `outbound`.
292    pub last_message_direction: Option<String>,
293    /// The status of the conversation to be filtered - all, read, unread, starred
294    /// Allowed values: `all`, `read`, `unread`, `starred`, `recents`.
295    pub status: Option<String>,
296    /// The sorting of the conversation to be filtered as - manual messages or all messages
297    /// Allowed values: `last_manual_message_date`, `last_message_date`, `score_profile`,
298    /// `overdue_at`, `due_at`.
299    pub sort_by: Option<String>,
300    /// Id of score profile on which sortBy.ScoreProfile should sort on
301    pub sort_score_profile: Option<String>,
302    /// Id of score profile on which conversations should get filtered out, works with
303    /// scoreProfileMin & scoreProfileMax
304    pub score_profile: Option<String>,
305    /// Minimum value for score
306    pub score_profile_min: Option<f64>,
307    /// Maximum value for score
308    pub score_profile_max: Option<f64>,
309    /// Start date filter for dateAdded field (Unix timestamp in milliseconds)
310    pub start_date: Option<f64>,
311    /// End date filter for dateAdded field (Unix timestamp in milliseconds)
312    pub end_date: Option<f64>,
313}
314
315impl SearchConversationsParams {
316    /// Start from the parameters the API requires.
317    pub fn new(location_id: impl Into<String>) -> Self {
318        Self {
319            location_id: location_id.into(),
320            ..Default::default()
321        }
322    }
323
324    /// Contact Id
325    pub fn contact_id(mut self, v: impl Into<String>) -> Self {
326        self.contact_id = Some(v.into());
327        self
328    }
329
330    /// User IDs that conversations are assigned to. Multiple IDs can be provided as
331    /// comma-separated values. Use "unassigned" to fetch conversations not assigned to any
332    /// user.
333    pub fn assigned_to(mut self, v: impl Into<String>) -> Self {
334        self.assigned_to = Some(v.into());
335        self
336    }
337
338    /// User IDs of followers to filter conversations by. Multiple IDs can be provided as
339    /// comma-separated values.
340    pub fn followers(mut self, v: impl Into<String>) -> Self {
341        self.followers = Some(v.into());
342        self
343    }
344
345    /// User Id of the mention. Multiple values are comma separated.
346    pub fn mentions(mut self, v: impl Into<String>) -> Self {
347        self.mentions = Some(v.into());
348        self
349    }
350
351    /// Search paramater as a string
352    pub fn query(mut self, v: impl Into<String>) -> Self {
353        self.query = Some(v.into());
354        self
355    }
356
357    /// Sort paramater - asc or desc
358    pub fn sort(mut self, v: impl Into<String>) -> Self {
359        self.sort = Some(v.into());
360        self
361    }
362
363    /// Search to begin after the specified date - should contain the sort value of the last
364    /// document
365    pub fn start_after_date(mut self, v: impl Into<String>) -> Self {
366        self.start_after_date = Some(v.into());
367        self
368    }
369
370    /// Id of the conversation
371    pub fn id(mut self, v: impl Into<String>) -> Self {
372        self.id = Some(v.into());
373        self
374    }
375
376    /// Limit of conversations - Default is 20
377    pub fn limit(mut self, v: f64) -> Self {
378        self.limit = Some(v);
379        self
380    }
381
382    /// Type of the last message in the conversation as a string
383    pub fn last_message_type(mut self, v: impl Into<String>) -> Self {
384        self.last_message_type = Some(v.into());
385        self
386    }
387
388    /// Action of the last outbound message in the conversation as string.
389    pub fn last_message_action(mut self, v: impl Into<String>) -> Self {
390        self.last_message_action = Some(v.into());
391        self
392    }
393
394    /// Direction of the last message in the conversation as string.
395    pub fn last_message_direction(mut self, v: impl Into<String>) -> Self {
396        self.last_message_direction = Some(v.into());
397        self
398    }
399
400    /// The status of the conversation to be filtered - all, read, unread, starred
401    pub fn status(mut self, v: impl Into<String>) -> Self {
402        self.status = Some(v.into());
403        self
404    }
405
406    /// The sorting of the conversation to be filtered as - manual messages or all messages
407    pub fn sort_by(mut self, v: impl Into<String>) -> Self {
408        self.sort_by = Some(v.into());
409        self
410    }
411
412    /// Id of score profile on which sortBy.ScoreProfile should sort on
413    pub fn sort_score_profile(mut self, v: impl Into<String>) -> Self {
414        self.sort_score_profile = Some(v.into());
415        self
416    }
417
418    /// Id of score profile on which conversations should get filtered out, works with
419    /// scoreProfileMin & scoreProfileMax
420    pub fn score_profile(mut self, v: impl Into<String>) -> Self {
421        self.score_profile = Some(v.into());
422        self
423    }
424
425    /// Minimum value for score
426    pub fn score_profile_min(mut self, v: f64) -> Self {
427        self.score_profile_min = Some(v);
428        self
429    }
430
431    /// Maximum value for score
432    pub fn score_profile_max(mut self, v: f64) -> Self {
433        self.score_profile_max = Some(v);
434        self
435    }
436
437    /// Start date filter for dateAdded field (Unix timestamp in milliseconds)
438    pub fn start_date(mut self, v: f64) -> Self {
439        self.start_date = Some(v);
440        self
441    }
442
443    /// End date filter for dateAdded field (Unix timestamp in milliseconds)
444    pub fn end_date(mut self, v: f64) -> Self {
445        self.end_date = Some(v);
446        self
447    }
448
449    fn to_query(&self) -> Vec<(String, String)> {
450        let mut q: Vec<(String, String)> = vec![("locationId".into(), self.location_id.clone())];
451        if let Some(v) = &self.contact_id {
452            q.push(("contactId".into(), v.to_string()));
453        }
454        if let Some(v) = &self.assigned_to {
455            q.push(("assignedTo".into(), v.to_string()));
456        }
457        if let Some(v) = &self.followers {
458            q.push(("followers".into(), v.to_string()));
459        }
460        if let Some(v) = &self.mentions {
461            q.push(("mentions".into(), v.to_string()));
462        }
463        if let Some(v) = &self.query {
464            q.push(("query".into(), v.to_string()));
465        }
466        if let Some(v) = &self.sort {
467            q.push(("sort".into(), v.to_string()));
468        }
469        if let Some(v) = &self.start_after_date {
470            q.push(("startAfterDate".into(), v.to_string()));
471        }
472        if let Some(v) = &self.id {
473            q.push(("id".into(), v.to_string()));
474        }
475        if let Some(v) = &self.limit {
476            q.push(("limit".into(), v.to_string()));
477        }
478        if let Some(v) = &self.last_message_type {
479            q.push(("lastMessageType".into(), v.to_string()));
480        }
481        if let Some(v) = &self.last_message_action {
482            q.push(("lastMessageAction".into(), v.to_string()));
483        }
484        if let Some(v) = &self.last_message_direction {
485            q.push(("lastMessageDirection".into(), v.to_string()));
486        }
487        if let Some(v) = &self.status {
488            q.push(("status".into(), v.to_string()));
489        }
490        if let Some(v) = &self.sort_by {
491            q.push(("sortBy".into(), v.to_string()));
492        }
493        if let Some(v) = &self.sort_score_profile {
494            q.push(("sortScoreProfile".into(), v.to_string()));
495        }
496        if let Some(v) = &self.score_profile {
497            q.push(("scoreProfile".into(), v.to_string()));
498        }
499        if let Some(v) = &self.score_profile_min {
500            q.push(("scoreProfileMin".into(), v.to_string()));
501        }
502        if let Some(v) = &self.score_profile_max {
503            q.push(("scoreProfileMax".into(), v.to_string()));
504        }
505        if let Some(v) = &self.start_date {
506            q.push(("startDate".into(), v.to_string()));
507        }
508        if let Some(v) = &self.end_date {
509            q.push(("endDate".into(), v.to_string()));
510        }
511        q
512    }
513}
514
515/// Query parameters for [`ConversationsService::get_messages_by_conversation_id`].
516#[derive(Debug, Clone, Default)]
517pub struct GetMessagesByConversationIdParams {
518    /// Message ID of the last message in the list as a string
519    pub last_message_id: Option<String>,
520    /// Number of messages to be fetched from the conversation. Default limit is 20
521    pub limit: Option<f64>,
522    /// Types of message to fetched separated with comma
523    /// Allowed values: `TYPE_CALL`, `TYPE_SMS`, `TYPE_RCS`, `TYPE_EMAIL`, `TYPE_FACEBOOK`,
524    /// `TYPE_GMB`, `TYPE_INSTAGRAM`, `TYPE_WHATSAPP`, `TYPE_ACTIVITY_APPOINTMENT`,
525    /// `TYPE_ACTIVITY_CONTACT`.
526    pub type_: Option<String>,
527}
528
529impl GetMessagesByConversationIdParams {
530    /// Start from the parameters the API requires.
531    pub fn new() -> Self {
532        Self {
533            ..Default::default()
534        }
535    }
536
537    /// Message ID of the last message in the list as a string
538    pub fn last_message_id(mut self, v: impl Into<String>) -> Self {
539        self.last_message_id = Some(v.into());
540        self
541    }
542
543    /// Number of messages to be fetched from the conversation. Default limit is 20
544    pub fn limit(mut self, v: f64) -> Self {
545        self.limit = Some(v);
546        self
547    }
548
549    /// Types of message to fetched separated with comma
550    pub fn type_(mut self, v: impl Into<String>) -> Self {
551        self.type_ = Some(v.into());
552        self
553    }
554
555    fn to_query(&self) -> Vec<(String, String)> {
556        let mut q: Vec<(String, String)> = Vec::new();
557        if let Some(v) = &self.last_message_id {
558            q.push(("lastMessageId".into(), v.to_string()));
559        }
560        if let Some(v) = &self.limit {
561            q.push(("limit".into(), v.to_string()));
562        }
563        if let Some(v) = &self.type_ {
564            q.push(("type".into(), v.to_string()));
565        }
566        q
567    }
568}
569
570impl ConversationsService {
571    /// Create Conversation
572    ///
573    /// Creates a new conversation with the data provided
574    ///
575    /// `POST /conversations/`
576    ///
577    /// Requires scope: `conversations.write`.
578    pub async fn create_conversation(
579        &self,
580        body: &models::CreateConversationDto,
581    ) -> Result<models::CreateConversationSuccessResponse> {
582        let query = Vec::new();
583        self.client
584            .send_versioned(
585                reqwest::Method::POST,
586                "/conversations/",
587                &query,
588                Some(body),
589                Some("2021-04-15"),
590            )
591            .await
592    }
593
594    /// Get transcription by Message ID
595    ///
596    /// Get the recording transcription for a message by passing the message id
597    ///
598    /// `GET /conversations/locations/{locationId}/messages/{messageId}/transcription`
599    ///
600    /// Requires scope: `conversations/message.readonly`.
601    pub async fn get_transcription_by_message_id(
602        &self,
603        location_id: &str,
604        message_id: &str,
605    ) -> Result<models::GetMessageTranscriptionResponseDto> {
606        let path = format!(
607            "/conversations/locations/{}/messages/{}/transcription",
608            crate::services::encode(location_id),
609            crate::services::encode(message_id)
610        );
611        let query = Vec::new();
612        self.client
613            .send_versioned(
614                reqwest::Method::GET,
615                &path,
616                &query,
617                None::<&()>,
618                Some("2021-04-15"),
619            )
620            .await
621    }
622
623    /// Download transcription by Message ID
624    ///
625    /// Download the recording transcription for a message by passing the message id
626    ///
627    /// `GET /conversations/locations/{locationId}/messages/{messageId}/transcription/download`
628    ///
629    /// Requires scope: `conversations/message.readonly`.
630    pub async fn download_transcription_by_message_id(
631        &self,
632        location_id: &str,
633        message_id: &str,
634    ) -> Result<serde_json::Value> {
635        let path = format!(
636            "/conversations/locations/{}/messages/{}/transcription/download",
637            crate::services::encode(location_id),
638            crate::services::encode(message_id)
639        );
640        let query = Vec::new();
641        self.client
642            .send_versioned(
643                reqwest::Method::GET,
644                &path,
645                &query,
646                None::<&()>,
647                Some("2021-04-15"),
648            )
649            .await
650    }
651
652    /// Send a new message
653    ///
654    /// Post the necessary fields for the API to send a new message.
655    ///
656    /// `POST /conversations/messages`
657    ///
658    /// Requires scope: `conversations/message.write`.
659    pub async fn send_a_new_message(
660        &self,
661        body: &models::SendMessageBodyDto,
662    ) -> Result<models::SendMessageResponseDto> {
663        let query = Vec::new();
664        self.client
665            .send_versioned(
666                reqwest::Method::POST,
667                "/conversations/messages",
668                &query,
669                Some(body),
670                Some("2021-04-15"),
671            )
672            .await
673    }
674
675    /// Cancel a scheduled email message.
676    ///
677    /// Post the messageId for the API to delete a scheduled email message.
678    ///
679    /// `DELETE /conversations/messages/email/{emailMessageId}/schedule`
680    pub async fn cancel_a_scheduled_email_message(
681        &self,
682        email_message_id: &str,
683    ) -> Result<models::CancelScheduledResponseDto> {
684        let path = format!(
685            "/conversations/messages/email/{}/schedule",
686            crate::services::encode(email_message_id)
687        );
688        let query = Vec::new();
689        self.client
690            .send_versioned(reqwest::Method::DELETE, &path, &query, None::<&()>, None)
691            .await
692    }
693
694    /// Get email by Id
695    ///
696    /// `GET /conversations/messages/email/{id}`
697    pub async fn get_email_by_id(&self, id: &str) -> Result<models::GetEmailMessageResponseDto> {
698        let path = format!(
699            "/conversations/messages/email/{}",
700            crate::services::encode(id)
701        );
702        let query = Vec::new();
703        self.client
704            .send_versioned(reqwest::Method::GET, &path, &query, None::<&()>, None)
705            .await
706    }
707
708    /// Export messages by location ID
709    ///
710    /// Export messages for a specific location with cursor-based pagination support.
711    /// Response includes messageType (string), source, and subType fields. The channel
712    /// parameter is optional - if not provided, all non-email message types will be
713    /// returned including activity messages (opportunity updates, appointments, etc.).
714    ///
715    /// `GET /conversations/messages/export`
716    ///
717    /// Requires scope: `conversations/message.readonly`.
718    pub async fn export_messages_by_location_id(
719        &self,
720        params: &ExportMessagesByLocationIdParams,
721    ) -> Result<models::ExportMessagesResponseDto> {
722        let query = params.to_query();
723        self.client
724            .send_versioned(
725                reqwest::Method::GET,
726                "/conversations/messages/export",
727                &query,
728                None::<&()>,
729                Some("2021-04-15"),
730            )
731            .await
732    }
733
734    /// Add an inbound message
735    ///
736    /// Post the necessary fields for the API to add a new inbound message.
737    ///
738    /// `POST /conversations/messages/inbound`
739    ///
740    /// Requires scope: `conversations/message.write`.
741    pub async fn add_an_inbound_message(
742        &self,
743        body: &models::ProcessMessageBodyDto,
744    ) -> Result<models::ProcessMessageResponseDto> {
745        let query = Vec::new();
746        self.client
747            .send_versioned(
748                reqwest::Method::POST,
749                "/conversations/messages/inbound",
750                &query,
751                Some(body),
752                Some("2021-04-15"),
753            )
754            .await
755    }
756
757    /// Add an external outbound call
758    ///
759    /// Post the necessary fields for the API to add a new outbound call.
760    ///
761    /// `POST /conversations/messages/outbound`
762    ///
763    /// Requires scope: `conversations/message.write`.
764    pub async fn add_an_external_outbound_call(
765        &self,
766        body: &models::ProcessOutboundMessageBodyDto,
767    ) -> Result<models::ProcessMessageResponseDto> {
768        let query = Vec::new();
769        self.client
770            .send_versioned(
771                reqwest::Method::POST,
772                "/conversations/messages/outbound",
773                &query,
774                Some(body),
775                Some("2021-04-15"),
776            )
777            .await
778    }
779
780    /// Send a review reply to Google My Business
781    ///
782    /// Post a reply to a customer review on Google My Business
783    ///
784    /// `POST /conversations/messages/review-reply`
785    ///
786    /// Requires scope: `conversations/message.write`.
787    pub async fn send_a_review_reply_to_google_my_business(
788        &self,
789        body: &models::SendReviewReplyDto,
790    ) -> Result<models::SendMessageResponseDto> {
791        let query = Vec::new();
792        self.client
793            .send_versioned(
794                reqwest::Method::POST,
795                "/conversations/messages/review-reply",
796                &query,
797                Some(body),
798                Some("2021-04-15"),
799            )
800            .await
801    }
802
803    /// Upload file attachments
804    ///
805    /// Post the necessary fields for the API to upload files. The files need to be a buffer
806    /// with the key "fileAttachment". The allowed file types are: JPG JPEG PNG MP4 MPEG ZIP
807    /// RAR PDF DOC DOCX TXT MP3 WAV The API will return an object with the URLs
808    ///
809    /// `POST /conversations/messages/upload`
810    ///
811    /// Requires scope: `conversations/message.write`.
812    pub async fn upload_file_attachments(
813        &self,
814        body: &serde_json::Value,
815    ) -> Result<models::UploadFilesResponseDto> {
816        let query = Vec::new();
817        self.client
818            .send_versioned(
819                reqwest::Method::POST,
820                "/conversations/messages/upload",
821                &query,
822                Some(body),
823                Some("2021-04-15"),
824            )
825            .await
826    }
827
828    /// Complete file upload
829    ///
830    /// Validates the uploaded file in GCS and returns the public URL. Call this endpoint
831    /// after successfully uploading the file to the signed URL.
832    ///
833    /// `POST /conversations/messages/upload/complete`
834    ///
835    /// Requires scope: `conversations/message.write`.
836    pub async fn complete_file_upload(
837        &self,
838        body: &models::CompleteFileUploadDto,
839    ) -> Result<models::CompleteFileUploadResponseDto> {
840        let query = Vec::new();
841        self.client
842            .send_versioned(
843                reqwest::Method::POST,
844                "/conversations/messages/upload/complete",
845                &query,
846                Some(body),
847                Some("2021-04-15"),
848            )
849            .await
850    }
851
852    /// Initiate file upload to GCS
853    ///
854    /// Generates a signed URL for direct file upload to Google Cloud Storage. Returns a
855    /// signed URL valid for 15 minutes. Upload file via PUT request, then call /complete to
856    /// finalize.
857    ///
858    /// `POST /conversations/messages/upload/initiate`
859    ///
860    /// Requires scope: `conversations/message.write`.
861    pub async fn initiate_file_upload_to_gcs(
862        &self,
863        body: &models::InitiateFileUploadDto,
864    ) -> Result<models::InitiateFileUploadResponseDto> {
865        let query = Vec::new();
866        self.client
867            .send_versioned(
868                reqwest::Method::POST,
869                "/conversations/messages/upload/initiate",
870                &query,
871                Some(body),
872                Some("2021-04-15"),
873            )
874            .await
875    }
876
877    /// Get message by message id
878    ///
879    /// Get message by message id.
880    ///
881    /// `GET /conversations/messages/{id}`
882    ///
883    /// Requires scope: `conversations/message.readonly`.
884    pub async fn get_message_by_message_id(
885        &self,
886        id: &str,
887    ) -> Result<models::GetMessageResponseDto> {
888        let path = format!("/conversations/messages/{}", crate::services::encode(id));
889        let query = Vec::new();
890        self.client
891            .send_versioned(
892                reqwest::Method::GET,
893                &path,
894                &query,
895                None::<&()>,
896                Some("2021-04-15"),
897            )
898            .await
899    }
900
901    /// Add message attachments
902    ///
903    /// Set attachments on an existing message (replaces existing). Maximum 5 URLs.
904    /// Supported for TYPE_CUSTOM_CALL (34) and TYPE_CALL (1) with subType EXTERNAL_CALL.
905    ///
906    /// `PUT /conversations/messages/{messageId}/attachments`
907    ///
908    /// Requires scope: `conversations/message.write`.
909    pub async fn add_message_attachments(
910        &self,
911        message_id: &str,
912        body: &models::AddMessageAttachmentsDto,
913    ) -> Result<serde_json::Value> {
914        let path = format!(
915            "/conversations/messages/{}/attachments",
916            crate::services::encode(message_id)
917        );
918        let query = Vec::new();
919        self.client
920            .send_versioned(
921                reqwest::Method::PUT,
922                &path,
923                &query,
924                Some(body),
925                Some("2021-04-15"),
926            )
927            .await
928    }
929
930    /// Get Recording by Message ID
931    ///
932    /// Get the recording for a message by passing the message id
933    ///
934    /// `GET /conversations/messages/{messageId}/locations/{locationId}/recording`
935    ///
936    /// Requires scope: `conversations/message.readonly`.
937    pub async fn get_recording_by_message_id(
938        &self,
939        message_id: &str,
940        location_id: &str,
941    ) -> Result<serde_json::Value> {
942        let path = format!(
943            "/conversations/messages/{}/locations/{}/recording",
944            crate::services::encode(message_id),
945            crate::services::encode(location_id)
946        );
947        let query = Vec::new();
948        self.client
949            .send_versioned(
950                reqwest::Method::GET,
951                &path,
952                &query,
953                None::<&()>,
954                Some("2021-04-15"),
955            )
956            .await
957    }
958
959    /// Cancel a scheduled message.
960    ///
961    /// Post the messageId for the API to delete a scheduled message.
962    ///
963    /// `DELETE /conversations/messages/{messageId}/schedule`
964    ///
965    /// Requires scope: `conversations/message.write`.
966    pub async fn cancel_a_scheduled_message(
967        &self,
968        message_id: &str,
969    ) -> Result<models::CancelScheduledResponseDto> {
970        let path = format!(
971            "/conversations/messages/{}/schedule",
972            crate::services::encode(message_id)
973        );
974        let query = Vec::new();
975        self.client
976            .send_versioned(
977                reqwest::Method::DELETE,
978                &path,
979                &query,
980                None::<&()>,
981                Some("2021-04-15"),
982            )
983            .await
984    }
985
986    /// Update message status
987    ///
988    /// Post the necessary fields for the API to update message status.
989    ///
990    /// `PUT /conversations/messages/{messageId}/status`
991    ///
992    /// Requires scope: `conversations/message.write`.
993    pub async fn update_message_status(
994        &self,
995        message_id: &str,
996        body: &models::UpdateMessageStatusDto,
997    ) -> Result<models::SendMessageResponseDto> {
998        let path = format!(
999            "/conversations/messages/{}/status",
1000            crate::services::encode(message_id)
1001        );
1002        let query = Vec::new();
1003        self.client
1004            .send_versioned(
1005                reqwest::Method::PUT,
1006                &path,
1007                &query,
1008                Some(body),
1009                Some("2021-04-15"),
1010            )
1011            .await
1012    }
1013
1014    /// Get All Custom Subtypes
1015    ///
1016    /// Get all custom subtypes for a location
1017    ///
1018    /// `GET /conversations/preferences/custom-subtypes`
1019    pub async fn get_all_custom_subtypes(
1020        &self,
1021        params: &GetAllCustomSubtypesParams,
1022    ) -> Result<serde_json::Value> {
1023        let query = params.to_query();
1024        self.client
1025            .send_versioned(
1026                reqwest::Method::GET,
1027                "/conversations/preferences/custom-subtypes",
1028                &query,
1029                None::<&()>,
1030                Some("2021-04-15"),
1031            )
1032            .await
1033    }
1034
1035    /// Create Custom Subtype
1036    ///
1037    /// Create a new custom subtype for a location. Requires agency or account admin role.
1038    ///
1039    /// `POST /conversations/preferences/custom-subtypes`
1040    pub async fn create_custom_subtype(
1041        &self,
1042        params: &CreateCustomSubtypeParams,
1043        body: &models::CreateCustomSubtypeDto,
1044    ) -> Result<serde_json::Value> {
1045        let query = params.to_query();
1046        self.client
1047            .send_versioned(
1048                reqwest::Method::POST,
1049                "/conversations/preferences/custom-subtypes",
1050                &query,
1051                Some(body),
1052                Some("2021-04-15"),
1053            )
1054            .await
1055    }
1056
1057    /// Update Custom Subtype
1058    ///
1059    /// Update or archive a custom subtype. Requires agency or account admin role.
1060    ///
1061    /// `PUT /conversations/preferences/custom-subtypes/{id}`
1062    pub async fn update_custom_subtype(
1063        &self,
1064        id: &str,
1065        params: &UpdateCustomSubtypeParams,
1066        body: &models::UpdateCustomSubtypeDto,
1067    ) -> Result<serde_json::Value> {
1068        let path = format!(
1069            "/conversations/preferences/custom-subtypes/{}",
1070            crate::services::encode(id)
1071        );
1072        let query = params.to_query();
1073        self.client
1074            .send_versioned(
1075                reqwest::Method::PUT,
1076                &path,
1077                &query,
1078                Some(body),
1079                Some("2021-04-15"),
1080            )
1081            .await
1082    }
1083
1084    /// Get Contact Unsubscription Status
1085    ///
1086    /// Get all subscription statuses for a contact (all emails or specific email)
1087    ///
1088    /// `GET /conversations/preferences/unsubscriptions/status`
1089    pub async fn get_contact_unsubscription_status(
1090        &self,
1091        params: &GetContactUnsubscriptionStatusParams,
1092    ) -> Result<serde_json::Value> {
1093        let query = params.to_query();
1094        self.client
1095            .send_versioned(
1096                reqwest::Method::GET,
1097                "/conversations/preferences/unsubscriptions/status",
1098                &query,
1099                None::<&()>,
1100                Some("2021-04-15"),
1101            )
1102            .await
1103    }
1104
1105    /// User Subscription Change
1106    ///
1107    /// Process subscription change initiated by a user (admin/agent). Supports individual
1108    /// custom subscription changes and resub all functionality. Legal forms are
1109    /// automatically created for user-initiated resubscribe actions on custom
1110    /// subscriptions.
1111    ///
1112    /// `POST /conversations/preferences/unsubscriptions/user-change`
1113    pub async fn user_subscription_change(
1114        &self,
1115        body: &models::UserSubscriptionChangeDto,
1116    ) -> Result<serde_json::Value> {
1117        let query = Vec::new();
1118        self.client
1119            .send_versioned(
1120                reqwest::Method::POST,
1121                "/conversations/preferences/unsubscriptions/user-change",
1122                &query,
1123                Some(body),
1124                Some("2021-04-15"),
1125            )
1126            .await
1127    }
1128
1129    /// Agent/Ai-Bot is typing a message indicator for live chat
1130    ///
1131    /// Agent/AI-Bot will call this when they are typing a message in live chat message
1132    ///
1133    /// `POST /conversations/providers/live-chat/typing`
1134    ///
1135    /// Requires scope: `conversations/livechat.write`.
1136    pub async fn agent_ai_bot_is_typing_a_message_indicator_for_live_chat(
1137        &self,
1138        body: &models::UserTypingBody,
1139    ) -> Result<models::CreateLiveChatMessageFeedbackResponse> {
1140        let query = Vec::new();
1141        self.client
1142            .send_versioned(
1143                reqwest::Method::POST,
1144                "/conversations/providers/live-chat/typing",
1145                &query,
1146                Some(body),
1147                Some("2021-04-15"),
1148            )
1149            .await
1150    }
1151
1152    /// Search Conversations
1153    ///
1154    /// Returns a list of all conversations matching the search criteria along with the sort
1155    /// and filter options selected.
1156    ///
1157    /// `GET /conversations/search`
1158    ///
1159    /// Requires scope: `conversations.readonly`.
1160    pub async fn search_conversations(
1161        &self,
1162        params: &SearchConversationsParams,
1163    ) -> Result<models::SendConversationResponseDto> {
1164        let query = params.to_query();
1165        self.client
1166            .send_versioned(
1167                reqwest::Method::GET,
1168                "/conversations/search",
1169                &query,
1170                None::<&()>,
1171                Some("2021-04-15"),
1172            )
1173            .await
1174    }
1175
1176    /// Delete Conversation
1177    ///
1178    /// Delete the conversation details based on the conversation ID
1179    ///
1180    /// `DELETE /conversations/{conversationId}`
1181    ///
1182    /// Requires scope: `conversations.write`.
1183    pub async fn delete_conversation(
1184        &self,
1185        conversation_id: &str,
1186    ) -> Result<models::DeleteConversationSuccessfulResponse> {
1187        let path = format!(
1188            "/conversations/{}",
1189            crate::services::encode(conversation_id)
1190        );
1191        let query = Vec::new();
1192        self.client
1193            .send_versioned(
1194                reqwest::Method::DELETE,
1195                &path,
1196                &query,
1197                None::<&()>,
1198                Some("2021-04-15"),
1199            )
1200            .await
1201    }
1202
1203    /// Get Conversation
1204    ///
1205    /// Get the conversation details based on the conversation ID
1206    ///
1207    /// `GET /conversations/{conversationId}`
1208    ///
1209    /// Requires scope: `conversations.readonly`.
1210    pub async fn get_conversation(
1211        &self,
1212        conversation_id: &str,
1213    ) -> Result<models::GetConversationByIdResponse> {
1214        let path = format!(
1215            "/conversations/{}",
1216            crate::services::encode(conversation_id)
1217        );
1218        let query = Vec::new();
1219        self.client
1220            .send_versioned(
1221                reqwest::Method::GET,
1222                &path,
1223                &query,
1224                None::<&()>,
1225                Some("2021-04-15"),
1226            )
1227            .await
1228    }
1229
1230    /// Update Conversation
1231    ///
1232    /// Update the conversation details based on the conversation ID
1233    ///
1234    /// `PUT /conversations/{conversationId}`
1235    ///
1236    /// Requires scope: `conversations.write`.
1237    pub async fn update_conversation(
1238        &self,
1239        conversation_id: &str,
1240        body: &models::UpdateConversationDto,
1241    ) -> Result<models::GetConversationSuccessfulResponse> {
1242        let path = format!(
1243            "/conversations/{}",
1244            crate::services::encode(conversation_id)
1245        );
1246        let query = Vec::new();
1247        self.client
1248            .send_versioned(
1249                reqwest::Method::PUT,
1250                &path,
1251                &query,
1252                Some(body),
1253                Some("2021-04-15"),
1254            )
1255            .await
1256    }
1257
1258    /// Get messages by conversation id
1259    ///
1260    /// Get messages by conversation id.
1261    ///
1262    /// `GET /conversations/{conversationId}/messages`
1263    ///
1264    /// Requires scope: `conversations/message.readonly`.
1265    pub async fn get_messages_by_conversation_id(
1266        &self,
1267        conversation_id: &str,
1268        params: &GetMessagesByConversationIdParams,
1269    ) -> Result<models::GetMessagesByConversationResponseDto> {
1270        let path = format!(
1271            "/conversations/{}/messages",
1272            crate::services::encode(conversation_id)
1273        );
1274        let query = params.to_query();
1275        self.client
1276            .send_versioned(
1277                reqwest::Method::GET,
1278                &path,
1279                &query,
1280                None::<&()>,
1281                Some("2021-04-15"),
1282            )
1283            .await
1284    }
1285}