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}