Skip to main content

sellapp/
lib.rs

1use reqwest::{
2    self,
3    header::{HeaderMap, HeaderValue},
4    Client, Error, Method, Response,
5};
6
7pub struct SellAppClient {
8    api_key: String,
9    store_slug: String,
10    http_client: Client,
11}
12
13impl SellAppClient {
14    fn generate_headers(&self, headers_vec: Vec<[&'static str; 2]>) -> HeaderMap {
15        let mut headers = HeaderMap::new();
16        headers.insert(
17            "Authorization",
18            HeaderValue::from_str(format!("Bearer {}", self.api_key).as_str()).unwrap(),
19        );
20        if !self.store_slug.is_empty() {
21            headers.insert(
22                "X-STORE",
23                HeaderValue::from_str(self.store_slug.as_str()).unwrap(),
24            );
25        }
26        for header in headers_vec {
27            let header_key = header[0];
28            let header_value = HeaderValue::from_str(header[1]).unwrap();
29            headers.insert(header_key, header_value);
30        }
31        return headers;
32    }
33
34    async fn send_request(&self, url: String, method: Method) -> Result<Response, Error> {
35        let req_headers = self.generate_headers(vec![["Accept", "application/json"]]);
36        let req_url = format!("https://sell.app/api/{}", url);
37
38        let req = self
39            .http_client
40            .request(method, req_url)
41            .headers(req_headers)
42            .send()
43            .await;
44
45        return req;
46    }
47
48    async fn send_request_data(
49        &self,
50        url: String,
51        method: Method,
52        body: String,
53    ) -> Result<Response, Error> {
54        let req_headers = self.generate_headers(vec![
55            ["Accept", "application/json"],
56            ["Content-Type", "application/json"],
57        ]);
58        let req_url = format!("https://sell.app/api/{}", url);
59
60        let req = self
61            .http_client
62            .request(method, req_url)
63            .headers(req_headers)
64            .body(body)
65            .send()
66            .await;
67
68        return req;
69    }
70
71    /// Fetch all of your blacklist rules.
72    ///
73    /// ``url_params``: Optional attributes to append to the request URL, e.g. **"?limit=50&page=1"**
74    ///
75    /// https://developer.sell.app/blacklists#list-all-blacklist-rules
76    pub async fn blacklist_list_all_rules(&self, url_params: &str) -> Result<Response, Error> {
77        return self
78            .send_request(format!("v1/blacklists{}", url_params), Method::GET)
79            .await;
80    }
81
82    /// Create a new blacklist rule.
83    ///
84    /// ``data``: JSON with the attributes of the new rule, required.
85    ///
86    /// https://developer.sell.app/blacklists#create-a-blacklist-rule
87    pub async fn blacklist_create_rule(&self, data: String) -> Result<Response, Error> {
88        return self
89            .send_request_data("v1/blacklists".to_string(), Method::POST, data)
90            .await;
91    }
92
93    /// Get a blacklist rule by ID.
94    ///
95    /// ``rule_id``: The ID of the rule you want to fetch, required.
96    ///
97    /// https://developer.sell.app/blacklists#retrieve-a-blacklist-rule
98    pub async fn blacklist_get_rule(&self, rule_id: String) -> Result<Response, Error> {
99        return self
100            .send_request(format!("v1/blacklists/{}", rule_id), Method::GET)
101            .await;
102    }
103
104    /// Update a blacklist rule by ID.
105    ///
106    /// ``rule_id``: The ID of the rule you want to update, required.
107    ///
108    /// ``data``: JSON with the updated attributes of the rule, required.
109    ///
110    /// https://developer.sell.app/blacklists#update-a-blacklist-rule
111    pub async fn blacklist_update_rule(
112        &self,
113        rule_id: String,
114        data: String,
115    ) -> Result<Response, Error> {
116        return self
117            .send_request_data(format!("v1/blacklists/{}", rule_id), Method::PATCH, data)
118            .await;
119    }
120
121    /// Delete a blacklist rule by ID.
122    ///
123    /// ``rule_id``: The ID of the rule you want to delete, required.
124    ///
125    /// https://developer.sell.app/blacklists#delete-a-blacklist-rule
126    pub async fn blacklist_delete_rule(&self, rule_id: String) -> Result<Response, Error> {
127        return self
128            .send_request(format!("v1/blacklists/{}", rule_id), Method::DELETE)
129            .await;
130    }
131
132    /// Get all existing coupons.
133    ///
134    /// ``url_params``: Optional attributes to append to the request URL, e.g. **"?limit=50&with_trashed=false"**
135    ///
136    /// https://developer.sell.app/coupons#list-all-coupons
137    pub async fn coupons_list_all(&self, url_params: &str) -> Result<Response, Error> {
138        return self
139            .send_request(format!("v1/coupons{}", url_params), Method::GET)
140            .await;
141    }
142
143    /// Create a new coupon.
144    ///
145    /// ``data``: JSON with the attributes of the new coupon, required.
146    ///
147    /// https://developer.sell.app/coupons#create-a-coupon
148    pub async fn coupons_create(&self, data: String) -> Result<Response, Error> {
149        return self
150            .send_request_data("v1/coupons".to_owned(), Method::POST, data)
151            .await;
152    }
153
154    /// Get a coupon by ID.
155    ///
156    /// ``coupon_id``: The ID of the coupon you want to fetch, required.
157    ///
158    /// https://developer.sell.app/coupons#retrieve-a-coupon
159    pub async fn coupons_get(&self, coupon_id: String) -> Result<Response, Error> {
160        return self
161            .send_request(format!("v1/coupons/{}", coupon_id), Method::GET)
162            .await;
163    }
164
165    /// Update a coupon by ID.
166    ///
167    /// ``coupon_id``: The ID of the coupon you want to update, required.
168    ///
169    /// ``data``: JSON with the updated attributes of the coupon, required.
170    ///
171    /// https://developer.sell.app/coupons#update-a-coupon
172    pub async fn coupons_update(&self, coupon_id: String, data: String) -> Result<Response, Error> {
173        return self
174            .send_request_data(format!("v1/coupons/{}", coupon_id), Method::PATCH, data)
175            .await;
176    }
177
178    /// Delete a coupon by ID.
179    ///
180    /// ``coupon_id``: The ID of the coupon you want to delete, required.
181    ///
182    /// https://developer.sell.app/coupons#delete-a-coupon
183    pub async fn coupons_delete(&self, coupon_id: String) -> Result<Response, Error> {
184        return self
185            .send_request(format!("v1/coupons/{}", coupon_id), Method::DELETE)
186            .await;
187    }
188
189    /// Get all feedback (reviews).
190    ///
191    /// ``url_params``: Optional attributes to append to the request URL, e.g. **"?limit=50&page=1"**
192    ///
193    /// https://developer.sell.app/feedback#list-all-feedback
194    pub async fn feedback_list_all(&self, url_params: &str) -> Result<Response, Error> {
195        return self
196            .send_request(format!("v1/feedback{}", url_params), Method::GET)
197            .await;
198    }
199
200    /// Get specific feedback by ID.
201    ///
202    /// ``feedback_id``: The ID of the feedback you want to fetch, required.
203    ///
204    /// https://developer.sell.app/feedback#retrieve-specific-feedback
205    pub async fn feedback_get(&self, feedback_id: String) -> Result<Response, Error> {
206        return self
207            .send_request(format!("v1/feedback/{}", feedback_id), Method::GET)
208            .await;
209    }
210
211    /// Reply to specifc feedback by ID.
212    ///
213    /// ``feedback_id``: The ID of the feedback you want to reply to, required.
214    ///
215    /// ``data``: JSON with the reply, required.
216    ///
217    /// https://developer.sell.app/feedback#reply-to-feedback
218    pub async fn feedback_reply(
219        &self,
220        feedback_id: String,
221        data: String,
222    ) -> Result<Response, Error> {
223        return self
224            .send_request_data(format!("v1/coupons/{}", feedback_id), Method::PATCH, data)
225            .await;
226    }
227
228    /// Get all existing product groups.
229    ///
230    /// ``url_params``: Optional attributes to append to the request URL, e.g. **"?limit=50&page=1"**
231    ///
232    /// https://developer.sell.app/groups#list-all-groups
233    pub async fn groups_list_all(&self, url_params: &str) -> Result<Response, Error> {
234        return self
235            .send_request(format!("v2/groups{}", url_params), Method::GET)
236            .await;
237    }
238
239    /// Create a product group.
240    ///
241    /// ``data``: JSON with the attributes of the group, required.
242    ///
243    /// https://developer.sell.app/groups#create-a-group
244    pub async fn groups_create(&self, data: String) -> Result<Response, Error> {
245        return self
246            .send_request_data("v2/groups".to_string(), Method::POST, data)
247            .await;
248    }
249
250    /// Get specific product group by ID.
251    ///
252    /// ``group_id``: The ID of the group you want to fetch, required.
253    ///
254    /// https://developer.sell.app/groups#retrieve-a-group
255    pub async fn groups_get(&self, group_id: String) -> Result<Response, Error> {
256        return self
257            .send_request(format!("v2/groups/{}", group_id), Method::GET)
258            .await;
259    }
260
261    /// Update a specific product group by ID.
262    ///
263    /// ``group_id``: The ID of the group you want to update, required.
264    ///
265    /// ``data``: JSON with the updated attributes, required.
266    ///
267    /// https://developer.sell.app/groups#update-a-group
268    pub async fn groups_update(&self, group_id: String, data: String) -> Result<Response, Error> {
269        return self
270            .send_request_data(format!("v2/groups/{}", group_id), Method::PATCH, data)
271            .await;
272    }
273
274    /// Delete a product group by ID.
275    ///
276    /// ``group_id``: The ID of the group you want to delete, required.
277    ///
278    /// https://developer.sell.app/groups#delete-a-group
279    pub async fn groups_delete(&self, group_id: String) -> Result<Response, Error> {
280        return self
281            .send_request(format!("v2/groups/{}", group_id), Method::DELETE)
282            .await;
283    }
284
285    /// Add products to an existing product group.
286    ///
287    /// ``group_id``: The ID of the group you want to add products to, required.
288    ///
289    /// ``data``: JSON with the product ID's you want to add, required.
290    ///
291    /// https://developer.sell.app/groups#add-products-to-group
292    pub async fn groups_add_products(
293        &self,
294        group_id: String,
295        data: String,
296    ) -> Result<Response, Error> {
297        return self
298            .send_request_data(
299                format!("v2/groups/{}/products/attach", group_id),
300                Method::POST,
301                data,
302            )
303            .await;
304    }
305
306    /// Remove products from an existing product group.
307    ///
308    /// ``group_id``: The ID of the group you want to remove products from, required.
309    ///
310    /// ``data``: JSON with the product ID's you want to remove, required.
311    ///
312    /// https://developer.sell.app/groups#remove-products-from-group
313    pub async fn groups_remove_products(
314        &self,
315        group_id: String,
316        data: String,
317    ) -> Result<Response, Error> {
318        return self
319            .send_request_data(
320                format!("v2/groups/{}/products/detach", group_id),
321                Method::DELETE,
322                data,
323            )
324            .await;
325    }
326
327    /// Get all products within a product group.
328    ///
329    /// ``group_id``: The ID of the group you want to list the products from, required.
330    ///
331    /// ``url_params``: Optional attributes to append to the request URL, e.g. **"?limit=50&page=1"**
332    ///
333    /// https://developer.sell.app/groups#list-all-products-within-group
334    pub async fn groups_list_products(
335        &self,
336        group_id: String,
337        url_params: &str,
338    ) -> Result<Response, Error> {
339        return self
340            .send_request(
341                format!("v2/groups/{}/products{}", group_id, url_params),
342                Method::GET,
343            )
344            .await;
345    }
346
347    /// Get a specific product within a product group.
348    ///
349    /// ``group_id``: The ID of the group you want to get the product from, required.
350    ///
351    /// ``product_id``: The ID of the product you want to fetch, required.
352    ///
353    /// https://developer.sell.app/groups#list-specific-product-within-group
354    pub async fn groups_get_product(
355        &self,
356        group_id: String,
357        product_id: String,
358    ) -> Result<Response, Error> {
359        return self
360            .send_request(
361                format!("v2/groups/{}/products/{}", group_id, product_id),
362                Method::GET,
363            )
364            .await;
365    }
366
367    /// Get all existing invoices (orders).
368    ///
369    /// ``url_params``: Optional attributes to append to the request URL, e.g. **"?limit=50&page=1"**
370    ///
371    /// https://developer.sell.app/invoices-v2#list-all-invoices
372    pub async fn invoices_list_all(&self, url_params: &str) -> Result<Response, Error> {
373        return self
374            .send_request(format!("v2/invoices{}", url_params), Method::GET)
375            .await;
376    }
377
378    /// Create a new invoice for a customer.
379    ///
380    /// ``data``: JSON with the invoice data, required.
381    ///
382    /// https://developer.sell.app/invoices-v2#create-an-invoice
383    pub async fn invoices_create(&self, data: String) -> Result<Response, Error> {
384        return self
385            .send_request_data("v2/invoices".to_string(), Method::POST, data)
386            .await;
387    }
388
389    /// Get specific invoice by ID.
390    ///
391    /// ``invoice_id``: The ID of the invoice you want to fetch, required.
392    ///
393    /// https://developer.sell.app/invoices-v2#retrieve-an-invoice
394    pub async fn invoices_get(&self, invoice_id: String) -> Result<Response, Error> {
395        return self
396            .send_request(format!("v2/invoices/{}", invoice_id), Method::GET)
397            .await;
398    }
399
400    /// Start a checkout session for a speficic invoice.
401    ///
402    /// ``invoice_id``: The ID of the invoice you want to start checkout for, required.
403    ///
404    /// https://developer.sell.app/invoices-v2#create-a-checkout-session
405    pub async fn invoices_checkout(&self, invoice_id: String) -> Result<Response, Error> {
406        return self
407            .send_request(format!("v2/invoices/{}/checkout", invoice_id), Method::POST)
408            .await;
409    }
410
411    /// Get the deliverables included in a specific invoice.
412    ///
413    /// ``invoice_id``: The ID of the invoice you want to get the items for, required.
414    ///
415    /// https://developer.sell.app/invoices-v2#view-invoice-deliverables
416    pub async fn invoices_get_items(&self, invoice_id: String) -> Result<Response, Error> {
417        return self
418            .send_request(
419                format!("v2/invoices/{}/deliverables", invoice_id),
420                Method::GET,
421            )
422            .await;
423    }
424
425    /// **Note: SellApp automatically marks payments as completed, you shouldn't need to call this.**
426    ///
427    /// Mark a specific (pending) invoice as completed.
428    ///
429    /// ``invoice_id``: The ID of the invoice you want to set as completed, required.
430    ///
431    /// https://developer.sell.app/invoices-v2#mark-pending-invoice-completed
432    pub async fn invoices_mark_completed(&self, invoice_id: String) -> Result<Response, Error> {
433        return self
434            .send_request(
435                format!("v2/invoices/{}/mark-completed", invoice_id),
436                Method::PATCH,
437            )
438            .await;
439    }
440
441    /// Mark a specific (pending) invoice as voided.
442    ///
443    /// ``invoice_id``: The ID of the invoice you want to set as voided, required.
444    ///
445    /// https://developer.sell.app/invoices-v2#mark-pending-invoice-voided
446    pub async fn invoices_mark_voided(&self, invoice_id: String) -> Result<Response, Error> {
447        return self
448            .send_request(
449                format!("v2/invoices/{}/mark-voided", invoice_id),
450                Method::PATCH,
451            )
452            .await;
453    }
454
455    /// Issue a replacement for a specific invoice.
456    ///
457    /// ``invoice_id``: The ID of the invoice you want to issue a replacement for, required.
458    ///
459    /// ``data``: JSON with the product variant ID's to get the replacements from.
460    ///
461    /// https://developer.sell.app/invoices-v2#issue-replacement-for-completed-invoice
462    pub async fn invoices_issue_replacement(
463        &self,
464        invoice_id: String,
465        data: String,
466    ) -> Result<Response, Error> {
467        return self
468            .send_request_data(
469                format!("v2/invoices/{}/issue-replacement", invoice_id),
470                Method::PATCH,
471                data,
472            )
473            .await;
474    }
475
476    /// Get all existing products.
477    ///
478    /// ``url_params``: Optional attributes to append to the request URL, e.g. **"?limit=50&page=1"**
479    ///
480    /// https://developer.sell.app/products-v2#list-all-products
481    pub async fn products_list_all(&self, url_params: &str) -> Result<Response, Error> {
482        return self
483            .send_request(format!("v2/products{}", url_params), Method::GET)
484            .await;
485    }
486
487    /// Create a new product. Support for uploading images is WIP.
488    ///
489    /// ``data``: JSON with the attributes of the product, required.
490    ///
491    /// https://developer.sell.app/products-v2#create-a-product
492    pub async fn products_create(&self, data: String) -> Result<Response, Error> {
493        return self
494            .send_request_data("v2/products".to_string(), Method::POST, data)
495            .await;
496    }
497
498    /// Get a specific product by ID.
499    ///
500    /// ``product_id``: The ID of the product you want to fetch, required.
501    ///
502    /// https://developer.sell.app/products-v2#retrieve-a-product
503    pub async fn products_get(&self, product_id: String) -> Result<Response, Error> {
504        return self
505            .send_request(format!("v2/products/{}", product_id), Method::GET)
506            .await;
507    }
508
509    /// Update a specific product.
510    ///
511    /// ``product_id``: The ID of the product you want to update, required.
512    ///
513    /// ``data``: JSON with the new product attributes, required.
514    ///
515    /// https://developer.sell.app/products-v2#update-a-product
516    pub async fn products_update(
517        &self,
518        product_id: String,
519        data: String,
520    ) -> Result<Response, Error> {
521        return self
522            .send_request_data(format!("v2/products/{}", product_id), Method::PATCH, data)
523            .await;
524    }
525
526    /// Delete a specific product.
527    ///
528    /// ``product_id``: The ID of the product you want to delete, required.
529    ///
530    /// https://developer.sell.app/products-v2#delete-a-product
531    pub async fn products_delete(&self, product_id: String) -> Result<Response, Error> {
532        return self
533            .send_request(format!("v2/products/{}", product_id), Method::DELETE)
534            .await;
535    }
536
537    /// Get all existing product variants.
538    ///
539    /// ``product_id``: The ID of the product you want to get the variants of, required.
540    ///
541    /// ``url_params``: Optional attributes to append to the request URL, e.g. **"?limit=50&page=1"**
542    ///
543    /// https://developer.sell.app/product-variants-v2#list-all-product-variants
544    pub async fn variants_list_all(
545        &self,
546        product_id: String,
547        url_params: &str,
548    ) -> Result<Response, Error> {
549        return self
550            .send_request(
551                format!("v2/products/{}/variants{}", product_id, url_params),
552                Method::GET,
553            )
554            .await;
555    }
556
557    /// Create a new product variant.
558    ///
559    /// ``product_id``: The ID of the product you want to add a new variant to, required.
560    ///
561    /// ``data``: JSON with the attributes of the variant, required.
562    ///
563    /// https://developer.sell.app/product-variants-v2#create-a-product-variant
564    pub async fn variants_create(
565        &self,
566        product_id: String,
567        data: String,
568    ) -> Result<Response, Error> {
569        return self
570            .send_request_data(
571                format!("v2/products/{}/variants", product_id),
572                Method::POST,
573                data,
574            )
575            .await;
576    }
577
578    /// Get a specific variant of a specific product.
579    ///
580    /// ``product_id``: The ID of the product, required.
581    ///
582    /// ``variant_id``: The ID of the variant you want to fetch, required.
583    ///
584    /// https://developer.sell.app/product-variants-v2#retrieve-a-product-variant
585    pub async fn variants_get(
586        &self,
587        product_id: String,
588        variant_id: String,
589    ) -> Result<Response, Error> {
590        return self
591            .send_request(
592                format!("v2/products/{}/variants/{}", product_id, variant_id),
593                Method::GET,
594            )
595            .await;
596    }
597
598    /// Update a specific variant of a specific product.
599    ///
600    /// ``product_id``: The ID of the product, required.
601    ///
602    /// ``variant_id``: The ID of the variant you want to update, required.
603    ///
604    /// ``data``: JSON with the new variant attributes, required.
605    ///
606    /// https://developer.sell.app/product-variants-v2#update-a-product-variant
607    pub async fn variants_update(
608        &self,
609        product_id: String,
610        variant_id: String,
611        data: String,
612    ) -> Result<Response, Error> {
613        return self
614            .send_request_data(
615                format!("v2/products/{}/variants/{}", product_id, variant_id),
616                Method::PATCH,
617                data,
618            )
619            .await;
620    }
621
622    /// Delete a specific product variant.
623    ///
624    /// ``product_id``: The ID of the product, required.
625    ///
626    /// ``variant_id``: The ID of the variant you want to delete, required.
627    ///
628    /// https://developer.sell.app/products-v2#delete-a-product
629    pub async fn variants_delete(
630        &self,
631        product_id: String,
632        variant_id: String,
633    ) -> Result<Response, Error> {
634        return self
635            .send_request(
636                format!("v2/products/{}/variants/{}", product_id, variant_id),
637                Method::DELETE,
638            )
639            .await;
640    }
641
642    /// Get all existing sections.
643    ///
644    /// ``url_params``: Optional attributes to append to the request URL, e.g. **"?limit=50&page=1"**
645    ///
646    /// https://developer.sell.app/sections#list-all-sections
647    pub async fn sections_list_all(&self, url_params: &str) -> Result<Response, Error> {
648        return self
649            .send_request(format!("v1/sections{}", url_params), Method::GET)
650            .await;
651    }
652
653    /// Create a new section.
654    ///
655    /// ``data``: JSON with the attributes of the secton, required.
656    ///
657    /// https://developer.sell.app/sections#create-a-section
658    pub async fn sections_create(&self, data: String) -> Result<Response, Error> {
659        return self
660            .send_request_data("v1/sections".to_string(), Method::POST, data)
661            .await;
662    }
663
664    /// Get a specific section by ID.
665    ///
666    /// ``section_id``: The ID of the section, required.
667    ///
668    /// https://developer.sell.app/sections#retrieve-a-section
669    pub async fn sections_get(&self, section_id: String) -> Result<Response, Error> {
670        return self
671            .send_request(format!("v1/sections/{}", section_id), Method::GET)
672            .await;
673    }
674
675    /// Update a specific section.
676    ///
677    /// ``section_id``: The ID of the section you want to update, required.
678    ///
679    /// ``data``: JSON with the new section attributes, required.
680    ///
681    /// https://developer.sell.app/sections#update-a-section
682    pub async fn sections_update(
683        &self,
684        section_id: String,
685        data: String,
686    ) -> Result<Response, Error> {
687        return self
688            .send_request_data(format!("v1/sections/{}", section_id), Method::PATCH, data)
689            .await;
690    }
691
692    /// Delete a specific product section.
693    ///
694    /// ``section_id``: The ID of the section you want to delete, required.
695    ///
696    /// https://developer.sell.app/sections#delete-a-section
697    pub async fn sections_delete(&self, section_id: String) -> Result<Response, Error> {
698        return self
699            .send_request(format!("v1/sections/{}", section_id), Method::DELETE)
700            .await;
701    }
702
703    /// Get all existing tickets.
704    ///
705    /// ``url_params``: Optional attributes to append to the request URL, e.g. **"?limit=50&page=1"**
706    ///
707    /// https://developer.sell.app/tickets#list-all-tickets
708    pub async fn tickets_list_all(&self, url_params: &str) -> Result<Response, Error> {
709        return self
710            .send_request(format!("v1/tickets{}", url_params), Method::GET)
711            .await;
712    }
713
714    /// Get a specific ticket.
715    ///
716    /// ``ticket_id``: The ID of the ticket you want to fetch, required.
717    ///
718    /// https://developer.sell.app/tickets#retrieve-specific-ticket
719    pub async fn tickets_get(&self, ticket_id: String) -> Result<Response, Error> {
720        return self
721            .send_request(format!("v1/tickets/{}", ticket_id), Method::GET)
722            .await;
723    }
724
725    /// Get the messages from a specific ticket.
726    ///
727    /// ``ticket_id``: The ID of the ticket you want to get the messages from, required.
728    ///
729    /// ``url_params``: Optional attributes to append to the request URL, e.g. **"?limit=50&page=1"**
730    ///
731    /// https://developer.sell.app/tickets#list-all-ticket-messages
732    pub async fn tickets_list_messages(
733        &self,
734        ticket_id: String,
735        url_params: &str,
736    ) -> Result<Response, Error> {
737        return self
738            .send_request(
739                format!("v1/tickets/{}/messages{}", ticket_id, url_params),
740                Method::GET,
741            )
742            .await;
743    }
744
745    /// Send a message to a specific ticket.
746    ///
747    /// ``ticket_id``: The ID of the ticket you want to send a messages to, required.
748    ///
749    /// ``data``: JSON with the message, required.
750    ///
751    /// https://developer.sell.app/tickets#reply-to-ticket
752    pub async fn tickets_reply(&self, ticket_id: String, data: String) -> Result<Response, Error> {
753        return self
754            .send_request_data(
755                format!("v1/tickets/{}/messages", ticket_id),
756                Method::POST,
757                data,
758            )
759            .await;
760    }
761
762    /// Get the a specific message from a specific ticket.
763    ///
764    /// ``ticket_id``: The ID of the ticket you want to get the message from, required.
765    ///
766    /// ``msg_id``: The ID of the message you want to get, required.
767    ///
768    /// https://developer.sell.app/tickets#retrieve-specific-ticket-message
769    pub async fn tickets_get_message(
770        &self,
771        ticket_id: String,
772        msg_id: String,
773    ) -> Result<Response, Error> {
774        return self
775            .send_request(
776                format!("v1/tickets/{}/messages/{}", ticket_id, msg_id),
777                Method::GET,
778            )
779            .await;
780    }
781}
782
783/// Initialize the client to make calls with your SellApp API key.
784///
785/// **Note**: ``store_slug`` is required if you are part of multiple stores, and wish to access a specific one.
786///
787/// Leave an empty &str to default to the first store from your storefront list.
788///
789/// ```
790/// let sellapp_api = sellapp::init("your_api_key", "your_store_slug");
791/// ```
792pub fn init(api_key: &str, store_slug: &str) -> SellAppClient {
793    let key = api_key.to_string();
794    let slug = store_slug.to_string();
795    let http_client = reqwest::Client::new();
796    return SellAppClient {
797        api_key: key,
798        store_slug: slug,
799        http_client,
800    };
801}