square_api_client/api/
catalog_api.rs

1//! Programmatically catalogs a Square seller’s products for sale and services for hire.
2//!
3//! The Catalog API allows you to programmatically catalog products or services, including items,
4//! variations, categories, discounts, taxes, modifiers, and more.
5
6use crate::{
7    config::Configuration,
8    http::client::HttpClient,
9    models::{
10        errors::ApiError, BatchDeleteCatalogObjectsRequest, BatchDeleteCatalogObjectsResponse,
11        BatchRetrieveCatalogObjectsRequest, BatchRetrieveCatalogObjectsResponse,
12        BatchUpsertCatalogObjectsRequest, BatchUpsertCatalogObjectsResponse, CatalogInfoResponse,
13        CreateCatalogImageRequest, CreateCatalogImageResponse, DeleteCatalogObjectResponse,
14        ListCatalogParameters, ListCatalogResponse, RetrieveCatalogObjectParameters,
15        RetrieveCatalogObjectResponse, SearchCatalogItemsRequest, SearchCatalogItemsResponse,
16        SearchCatalogObjectsRequest, SearchCatalogObjectsResponse, UpdateCatalogImageRequest,
17        UpdateCatalogImageResponse, UpdateItemModifierListsRequest,
18        UpdateItemModifierListsResponse, UpdateItemTaxesRequest, UpdateItemTaxesResponse,
19        UpsertCatalogObjectRequest, UpsertCatalogObjectResponse,
20    },
21};
22
23const DEFAULT_URI: &str = "/catalog";
24
25/// Programmatically catalogs a Square seller’s products for sale and services for hire.
26pub struct CatalogApi {
27    /// App config information
28    config: Configuration,
29    /// HTTP Client for requests to the Catalog API endpoints
30    client: HttpClient,
31}
32
33impl CatalogApi {
34    /// Instantiates a new `CatalogApi`
35    pub fn new(config: Configuration, client: HttpClient) -> Self {
36        Self { config, client }
37    }
38
39    /// Deletes a set of [CatalogItem]s based on the provided list of target IDs and returns a set
40    /// of successfully deleted IDs in the response.
41    ///
42    /// Deletion is a cascading event such that all children of the targeted object are also
43    /// deleted. For example, deleting a CatalogItem will also delete all of its
44    /// [CatalogItemVariation] children.
45    ///
46    /// `BatchDeleteCatalogObjects` succeeds even if only a portion of the targeted IDs can be
47    /// deleted. The response will only include IDs that were actually deleted.
48    pub async fn batch_delete_catalog_objects(
49        &self,
50        body: &BatchDeleteCatalogObjectsRequest,
51    ) -> Result<BatchDeleteCatalogObjectsResponse, ApiError> {
52        let url = format!("{}/batch-delete", &self.url());
53        let response = self.client.post(&url, body).await?;
54
55        response.deserialize().await
56    }
57
58    /// Returns a set of objects based on the provided ID.
59    ///
60    /// Each [CatalogItem] returned in the set includes all of its child information including: all
61    /// of its [CatalogItemVariation] objects, references to its [CatalogModifierList] objects, and
62    /// the ids of any [CatalogTax] objects that apply to it.
63    pub async fn batch_retrieve_catalog_objects(
64        &self,
65        body: &BatchRetrieveCatalogObjectsRequest,
66    ) -> Result<BatchRetrieveCatalogObjectsResponse, ApiError> {
67        let url = format!("{}/batch-retrieve", &self.url());
68        let response = self.client.post(&url, body).await?;
69
70        response.deserialize().await
71    }
72
73    /// Creates or updates up to 10,000 target objects based on the provided list of objects.
74    ///
75    /// The target objects are grouped into batches and each batch is inserted/updated in an
76    /// all-or-nothing manner. If an object within a batch is malformed in some way, or violates a
77    /// database constraint, the entire batch containing that item will be disregarded. However,
78    /// other batches in the same request may still succeed. Each batch may contain up to 1,000
79    /// objects, and batches will be processed in order as long as the total object count for the
80    /// request (items, variations, modifier lists, discounts, and taxes) is no more than 10,000.
81    pub async fn batch_upsert_catalog_objects(
82        &self,
83        body: &BatchUpsertCatalogObjectsRequest,
84    ) -> Result<BatchUpsertCatalogObjectsResponse, ApiError> {
85        let url = format!("{}/batch-upsert", &self.url());
86        let response = self.client.post(&url, body).await?;
87
88        response.deserialize().await
89    }
90
91    /// Uploads an image file to be represented by a [CatalogImage] object that can be linked to an
92    /// existing [CatalogObject] instance.
93    ///
94    /// The resulting `CatalogImage` is unattached to any `CatalogObject` if the object_id is not
95    /// specified.
96    ///
97    /// This `CreateCatalogImage` endpoint accepts HTTP multipart/form-data requests with a JSON
98    /// part and an image file part in JPEG, PJPEG, PNG, or GIF format. The maximum file size is
99    /// 15MB.
100    pub async fn create_catalog_image(
101        &self,
102        body: &CreateCatalogImageRequest,
103        image_filepath: &str,
104    ) -> Result<CreateCatalogImageResponse, ApiError> {
105        let url = format!("{}/images", &self.url());
106        let response = self.client.post_multipart(&url, body, image_filepath).await?;
107
108        response.deserialize().await
109    }
110
111    /// Uploads a new image file to replace the existing one in the specified [CatalogImage] object.
112    ///
113    /// This `UpdateCatalogImage` endpoint accepts HTTP multipart/form-data requests with a JSON
114    /// part and an image file part in JPEG, PJPEG, PNG, or GIF format. The maximum file size is
115    /// 15MB.
116    pub async fn update_catalog_image(
117        &self,
118        image_id: &str,
119        body: &UpdateCatalogImageRequest,
120        image_filepath: &str,
121    ) -> Result<UpdateCatalogImageResponse, ApiError> {
122        let url = format!("{}/images/{}", &self.url(), image_id);
123        let response = self.client.put_multipart(&url, body, image_filepath).await?;
124
125        response.deserialize().await
126    }
127
128    /// Retrieves information about the Square Catalog API, such as batch size limits that can be
129    /// used by the `BatchUpsertCatalogObjects` endpoint.
130    pub async fn catalog_info(&self) -> Result<CatalogInfoResponse, ApiError> {
131        let url = format!("{}/info", &self.url());
132        let response = self.client.get(&url).await?;
133
134        response.deserialize().await
135    }
136
137    /// Returns a list of all [CatalogObject]s of the specified types in the catalog.
138    ///
139    /// The `types` parameter is specified as a comma-separated list of the [CatalogObjectType]
140    /// values, for example, "`ITEM`, `ITEM_VARIATION`, `MODIFIER`, `MODIFIER_LIST`, `CATEGORY`,
141    /// `DISCOUNT`, `TAX`, `IMAGE`".
142    ///
143    /// **Important:** ListCatalog does not return deleted catalog items. To retrieve deleted
144    /// catalog items, use [SearchCatalogObjects] and set the `include_deleted_objects` attribute
145    /// value to `true`.
146    pub async fn list_catalog(
147        &self,
148        params: &ListCatalogParameters,
149    ) -> Result<ListCatalogResponse, ApiError> {
150        let url = format!("{}/list{}", &self.url(), params.to_query_string());
151        let response = self.client.get(&url).await?;
152
153        response.deserialize().await
154    }
155
156    /// Creates or updates the target [CatalogObject].
157    pub async fn upsert_catalog_object(
158        &self,
159        body: &UpsertCatalogObjectRequest,
160    ) -> Result<UpsertCatalogObjectResponse, ApiError> {
161        let url = format!("{}/object", &self.url());
162        let response = self.client.post(&url, body).await?;
163
164        response.deserialize().await
165    }
166
167    /// Deletes a single [CatalogObject] based on the provided ID and returns the set of
168    /// successfully deleted IDs in the response.
169    ///
170    /// Deletion is a cascading event such that all children of the targeted object are also
171    /// deleted. For example, deleting a [CatalogItem] will also delete all of its
172    /// [CatalogItemVariation] children.
173    pub async fn delete_catalog_object(
174        &self,
175        object_id: &str,
176    ) -> Result<DeleteCatalogObjectResponse, ApiError> {
177        let url = format!("{}/object/{}", &self.url(), object_id);
178        let response = self.client.delete(&url).await?;
179
180        response.deserialize().await
181    }
182
183    /// Returns a single [CatalogItem] as a [CatalogObject] based on the provided ID.
184    ///
185    /// The returned object includes all of the relevant [CatalogItem] information including:
186    /// [CatalogItemVariation] children, references to its [CatalogModifierList] objects, and the
187    /// ids of any [CatalogTax] objects that apply to it.
188    pub async fn retrieve_catalog_object(
189        &self,
190        object_id: &str,
191        params: &RetrieveCatalogObjectParameters,
192    ) -> Result<RetrieveCatalogObjectResponse, ApiError> {
193        let url = format!("{}/object/{}{}", &self.url(), object_id, params.to_query_string());
194        let response = self.client.get(&url).await?;
195
196        response.deserialize().await
197    }
198
199    /// Searches for [CatalogObject] of any type by matching supported search attribute values,
200    /// excluding custom attribute values on items or item variations, against one or more of the
201    /// specified query filters.
202    ///
203    /// This (`SearchCatalogObjects`) endpoint differs from the `SearchCatalogItems` endpoint in the
204    /// following aspects:
205    ///
206    /// * `SearchCatalogItems` can only search for items or item variations, whereas
207    ///   `SearchCatalogObjects` can search for any type of catalog objects.
208    /// * `SearchCatalogItems` supports the custom attribute query filters to return items or item
209    ///   variations that contain custom attribute values, where `SearchCatalogObjects` does not.
210    /// * `SearchCatalogItems` does not support the include_deleted_objects filter to search for
211    ///   deleted items or item variations, whereas `SearchCatalogObjects` does.
212    /// * The both endpoints have different call conventions, including the query filter formats.
213    pub async fn search_catalog_objects(
214        &self,
215        body: &SearchCatalogObjectsRequest,
216    ) -> Result<SearchCatalogObjectsResponse, ApiError> {
217        let url = format!("{}/search", &self.url());
218        let response = self.client.post(&url, body).await?;
219
220        response.deserialize().await
221    }
222
223    /// Searches for catalog items or item variations by matching supported search attribute values,
224    /// including custom attribute values, against one or more of the specified query filters.
225    ///
226    /// This (`SearchCatalogItems`) endpoint differs from the `SearchCatalogObjects` endpoint in the
227    /// following aspects:
228    ///
229    /// * `SearchCatalogItems` can only search for items or item variations, whereas
230    ///   `SearchCatalogObjects` can search for any type of catalog objects.
231    /// * `SearchCatalogItems` supports the custom attribute query filters to return items or item
232    ///   variations that contain custom attribute values, where `SearchCatalogObjects` does not.
233    /// * `SearchCatalogItems` does not support the include_deleted_objects filter to search for
234    ///   deleted items or item variations, whereas `SearchCatalogObjects` does.
235    /// * The both endpoints use different call conventions, including the query filter formats.
236    pub async fn search_catalog_items(
237        &self,
238        body: &SearchCatalogItemsRequest,
239    ) -> Result<SearchCatalogItemsResponse, ApiError> {
240        let url = format!("{}/search-catalog-items", &self.url());
241        let response = self.client.post(&url, body).await?;
242
243        response.deserialize().await
244    }
245
246    /// Updates the [CatalogModifierList] objects that apply to the targeted [CatalogItem] without
247    /// having to perform an upsert on the entire item.
248    pub async fn update_item_modifier_lists(
249        &self,
250        body: &UpdateItemModifierListsRequest,
251    ) -> Result<UpdateItemModifierListsResponse, ApiError> {
252        let url = format!("{}/update-item-modifier-lists", &self.url());
253        let response = self.client.post(&url, body).await?;
254
255        response.deserialize().await
256    }
257
258    /// Updates the [CatalogTax] objects that apply to the targeted [CatalogItem] without having to
259    /// perform an upsert on the entire item.
260    pub async fn update_item_taxes(
261        &self,
262        body: &UpdateItemTaxesRequest,
263    ) -> Result<UpdateItemTaxesResponse, ApiError> {
264        let url = format!("{}/update-item-taxes", &self.url());
265        let response = self.client.post(&url, body).await?;
266
267        response.deserialize().await
268    }
269
270    /// Constructs the basic entity URL including domain and entity path. Any additional path
271    /// elements (e.g. path parameters) will need to be appended to this URL.
272    fn url(&self) -> String {
273        format!("{}{}", &self.config.get_base_url(), DEFAULT_URI)
274    }
275}