shopify_api 13.0.0 → 13.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (202) hide show
  1. checksums.yaml +4 -4
  2. data/BREAKING_CHANGES_FOR_V10.md +231 -0
  3. data/CHANGELOG.md +14 -1
  4. data/Gemfile.lock +8 -8
  5. data/README.md +10 -41
  6. data/docs/README.md +0 -1
  7. data/docs/getting_started.md +21 -11
  8. data/docs/usage/custom_apps.md +75 -0
  9. data/docs/usage/graphql.md +63 -18
  10. data/docs/usage/oauth.md +160 -27
  11. data/docs/usage/rest.md +204 -62
  12. data/docs/usage/webhooks.md +22 -4
  13. data/lib/shopify_api/admin_versions.rb +3 -1
  14. data/lib/shopify_api/context.rb +6 -3
  15. data/lib/shopify_api/rest/base.rb +27 -15
  16. data/lib/shopify_api/rest/resources/2022_04/fulfillment_order.rb +3 -7
  17. data/lib/shopify_api/rest/resources/2022_04/shop.rb +2 -2
  18. data/lib/shopify_api/rest/resources/2022_07/fulfillment_order.rb +3 -7
  19. data/lib/shopify_api/rest/resources/2022_07/shop.rb +2 -2
  20. data/lib/shopify_api/rest/resources/2022_10/assigned_fulfillment_order.rb +5 -3
  21. data/lib/shopify_api/rest/resources/2022_10/customer_address.rb +10 -0
  22. data/lib/shopify_api/rest/resources/2022_10/fulfillment_order.rb +3 -7
  23. data/lib/shopify_api/rest/resources/2022_10/fulfillment_request.rb +10 -0
  24. data/lib/shopify_api/rest/resources/2022_10/order_risk.rb +5 -3
  25. data/lib/shopify_api/rest/resources/2022_10/shop.rb +2 -2
  26. data/lib/shopify_api/rest/resources/2023_01/assigned_fulfillment_order.rb +5 -3
  27. data/lib/shopify_api/rest/resources/2023_01/balance.rb +4 -0
  28. data/lib/shopify_api/rest/resources/2023_01/customer_address.rb +10 -0
  29. data/lib/shopify_api/rest/resources/2023_01/fulfillment_order.rb +3 -7
  30. data/lib/shopify_api/rest/resources/2023_01/fulfillment_request.rb +10 -0
  31. data/lib/shopify_api/rest/resources/2023_01/order.rb +3 -0
  32. data/lib/shopify_api/rest/resources/2023_01/order_risk.rb +5 -3
  33. data/lib/shopify_api/rest/resources/2023_01/shop.rb +2 -5
  34. data/lib/shopify_api/rest/resources/2023_01/variant.rb +1 -5
  35. data/lib/shopify_api/rest/resources/2023_04/assigned_fulfillment_order.rb +5 -3
  36. data/lib/shopify_api/rest/resources/2023_04/balance.rb +4 -0
  37. data/lib/shopify_api/rest/resources/2023_04/customer_address.rb +10 -0
  38. data/lib/shopify_api/rest/resources/2023_04/fulfillment_request.rb +10 -0
  39. data/lib/shopify_api/rest/resources/2023_04/order.rb +3 -0
  40. data/lib/shopify_api/rest/resources/2023_04/order_risk.rb +5 -3
  41. data/lib/shopify_api/rest/resources/2023_04/shop.rb +2 -5
  42. data/lib/shopify_api/rest/resources/2023_04/variant.rb +1 -5
  43. data/lib/shopify_api/rest/resources/2023_07/abandoned_checkout.rb +190 -0
  44. data/lib/shopify_api/rest/resources/2023_07/access_scope.rb +58 -0
  45. data/lib/shopify_api/rest/resources/2023_07/apple_pay_certificate.rb +105 -0
  46. data/lib/shopify_api/rest/resources/2023_07/application_charge.rb +109 -0
  47. data/lib/shopify_api/rest/resources/2023_07/application_credit.rb +91 -0
  48. data/lib/shopify_api/rest/resources/2023_07/article.rb +265 -0
  49. data/lib/shopify_api/rest/resources/2023_07/asset.rb +118 -0
  50. data/lib/shopify_api/rest/resources/2023_07/assigned_fulfillment_order.rb +88 -0
  51. data/lib/shopify_api/rest/resources/2023_07/balance.rb +54 -0
  52. data/lib/shopify_api/rest/resources/2023_07/blog.rb +162 -0
  53. data/lib/shopify_api/rest/resources/2023_07/cancellation_request.rb +83 -0
  54. data/lib/shopify_api/rest/resources/2023_07/carrier_service.rb +116 -0
  55. data/lib/shopify_api/rest/resources/2023_07/checkout.rb +209 -0
  56. data/lib/shopify_api/rest/resources/2023_07/collect.rb +142 -0
  57. data/lib/shopify_api/rest/resources/2023_07/collection.rb +110 -0
  58. data/lib/shopify_api/rest/resources/2023_07/collection_listing.rb +155 -0
  59. data/lib/shopify_api/rest/resources/2023_07/comment.rb +283 -0
  60. data/lib/shopify_api/rest/resources/2023_07/country.rb +137 -0
  61. data/lib/shopify_api/rest/resources/2023_07/currency.rb +57 -0
  62. data/lib/shopify_api/rest/resources/2023_07/custom_collection.rb +187 -0
  63. data/lib/shopify_api/rest/resources/2023_07/customer.rb +329 -0
  64. data/lib/shopify_api/rest/resources/2023_07/customer_address.rb +211 -0
  65. data/lib/shopify_api/rest/resources/2023_07/customer_saved_search.rb +169 -0
  66. data/lib/shopify_api/rest/resources/2023_07/deprecated_api_call.rb +57 -0
  67. data/lib/shopify_api/rest/resources/2023_07/discount_code.rb +222 -0
  68. data/lib/shopify_api/rest/resources/2023_07/dispute.rb +111 -0
  69. data/lib/shopify_api/rest/resources/2023_07/dispute_evidence.rb +117 -0
  70. data/lib/shopify_api/rest/resources/2023_07/dispute_file_upload.rb +81 -0
  71. data/lib/shopify_api/rest/resources/2023_07/draft_order.rb +275 -0
  72. data/lib/shopify_api/rest/resources/2023_07/event.rb +148 -0
  73. data/lib/shopify_api/rest/resources/2023_07/fulfillment.rb +231 -0
  74. data/lib/shopify_api/rest/resources/2023_07/fulfillment_event.rb +166 -0
  75. data/lib/shopify_api/rest/resources/2023_07/fulfillment_order.rb +312 -0
  76. data/lib/shopify_api/rest/resources/2023_07/fulfillment_request.rb +97 -0
  77. data/lib/shopify_api/rest/resources/2023_07/fulfillment_service.rb +130 -0
  78. data/lib/shopify_api/rest/resources/2023_07/gift_card.rb +218 -0
  79. data/lib/shopify_api/rest/resources/2023_07/gift_card_adjustment.rb +118 -0
  80. data/lib/shopify_api/rest/resources/2023_07/image.rb +157 -0
  81. data/lib/shopify_api/rest/resources/2023_07/inventory_item.rb +108 -0
  82. data/lib/shopify_api/rest/resources/2023_07/inventory_level.rb +179 -0
  83. data/lib/shopify_api/rest/resources/2023_07/location.rb +167 -0
  84. data/lib/shopify_api/rest/resources/2023_07/locations_for_move.rb +56 -0
  85. data/lib/shopify_api/rest/resources/2023_07/marketing_event.rb +209 -0
  86. data/lib/shopify_api/rest/resources/2023_07/metafield.rb +344 -0
  87. data/lib/shopify_api/rest/resources/2023_07/mobile_platform_application.rb +110 -0
  88. data/lib/shopify_api/rest/resources/2023_07/order.rb +491 -0
  89. data/lib/shopify_api/rest/resources/2023_07/order_risk.rb +144 -0
  90. data/lib/shopify_api/rest/resources/2023_07/page.rb +194 -0
  91. data/lib/shopify_api/rest/resources/2023_07/payment.rb +140 -0
  92. data/lib/shopify_api/rest/resources/2023_07/payment_gateway.rb +143 -0
  93. data/lib/shopify_api/rest/resources/2023_07/payment_transaction.rb +107 -0
  94. data/lib/shopify_api/rest/resources/2023_07/payout.rb +97 -0
  95. data/lib/shopify_api/rest/resources/2023_07/policy.rb +69 -0
  96. data/lib/shopify_api/rest/resources/2023_07/price_rule.rb +223 -0
  97. data/lib/shopify_api/rest/resources/2023_07/product.rb +223 -0
  98. data/lib/shopify_api/rest/resources/2023_07/product_listing.rb +196 -0
  99. data/lib/shopify_api/rest/resources/2023_07/product_resource_feedback.rb +88 -0
  100. data/lib/shopify_api/rest/resources/2023_07/province.rb +132 -0
  101. data/lib/shopify_api/rest/resources/2023_07/recurring_application_charge.rb +172 -0
  102. data/lib/shopify_api/rest/resources/2023_07/redirect.rb +139 -0
  103. data/lib/shopify_api/rest/resources/2023_07/refund.rb +151 -0
  104. data/lib/shopify_api/rest/resources/2023_07/report.rb +121 -0
  105. data/lib/shopify_api/rest/resources/2023_07/resource_feedback.rb +73 -0
  106. data/lib/shopify_api/rest/resources/2023_07/script_tag.rb +155 -0
  107. data/lib/shopify_api/rest/resources/2023_07/shipping_zone.rb +83 -0
  108. data/lib/shopify_api/rest/resources/2023_07/shop.rb +218 -0
  109. data/lib/shopify_api/rest/resources/2023_07/smart_collection.rb +216 -0
  110. data/lib/shopify_api/rest/resources/2023_07/storefront_access_token.rb +87 -0
  111. data/lib/shopify_api/rest/resources/2023_07/tender_transaction.rb +93 -0
  112. data/lib/shopify_api/rest/resources/2023_07/theme.rb +123 -0
  113. data/lib/shopify_api/rest/resources/2023_07/transaction.rb +184 -0
  114. data/lib/shopify_api/rest/resources/2023_07/usage_charge.rb +102 -0
  115. data/lib/shopify_api/rest/resources/2023_07/user.rb +138 -0
  116. data/lib/shopify_api/rest/resources/2023_07/variant.rb +208 -0
  117. data/lib/shopify_api/rest/resources/2023_07/webhook.rb +168 -0
  118. data/lib/shopify_api/rest/resources/2023_10/abandoned_checkout.rb +190 -0
  119. data/lib/shopify_api/rest/resources/2023_10/access_scope.rb +58 -0
  120. data/lib/shopify_api/rest/resources/2023_10/apple_pay_certificate.rb +105 -0
  121. data/lib/shopify_api/rest/resources/2023_10/application_charge.rb +109 -0
  122. data/lib/shopify_api/rest/resources/2023_10/application_credit.rb +91 -0
  123. data/lib/shopify_api/rest/resources/2023_10/article.rb +265 -0
  124. data/lib/shopify_api/rest/resources/2023_10/asset.rb +118 -0
  125. data/lib/shopify_api/rest/resources/2023_10/assigned_fulfillment_order.rb +88 -0
  126. data/lib/shopify_api/rest/resources/2023_10/balance.rb +54 -0
  127. data/lib/shopify_api/rest/resources/2023_10/blog.rb +162 -0
  128. data/lib/shopify_api/rest/resources/2023_10/cancellation_request.rb +83 -0
  129. data/lib/shopify_api/rest/resources/2023_10/carrier_service.rb +116 -0
  130. data/lib/shopify_api/rest/resources/2023_10/checkout.rb +209 -0
  131. data/lib/shopify_api/rest/resources/2023_10/collect.rb +142 -0
  132. data/lib/shopify_api/rest/resources/2023_10/collection.rb +110 -0
  133. data/lib/shopify_api/rest/resources/2023_10/collection_listing.rb +155 -0
  134. data/lib/shopify_api/rest/resources/2023_10/comment.rb +283 -0
  135. data/lib/shopify_api/rest/resources/2023_10/country.rb +137 -0
  136. data/lib/shopify_api/rest/resources/2023_10/currency.rb +57 -0
  137. data/lib/shopify_api/rest/resources/2023_10/custom_collection.rb +187 -0
  138. data/lib/shopify_api/rest/resources/2023_10/customer.rb +329 -0
  139. data/lib/shopify_api/rest/resources/2023_10/customer_address.rb +211 -0
  140. data/lib/shopify_api/rest/resources/2023_10/deprecated_api_call.rb +57 -0
  141. data/lib/shopify_api/rest/resources/2023_10/discount_code.rb +222 -0
  142. data/lib/shopify_api/rest/resources/2023_10/dispute.rb +111 -0
  143. data/lib/shopify_api/rest/resources/2023_10/dispute_evidence.rb +117 -0
  144. data/lib/shopify_api/rest/resources/2023_10/dispute_file_upload.rb +81 -0
  145. data/lib/shopify_api/rest/resources/2023_10/draft_order.rb +275 -0
  146. data/lib/shopify_api/rest/resources/2023_10/event.rb +148 -0
  147. data/lib/shopify_api/rest/resources/2023_10/fulfillment.rb +231 -0
  148. data/lib/shopify_api/rest/resources/2023_10/fulfillment_event.rb +166 -0
  149. data/lib/shopify_api/rest/resources/2023_10/fulfillment_order.rb +312 -0
  150. data/lib/shopify_api/rest/resources/2023_10/fulfillment_request.rb +97 -0
  151. data/lib/shopify_api/rest/resources/2023_10/fulfillment_service.rb +130 -0
  152. data/lib/shopify_api/rest/resources/2023_10/gift_card.rb +218 -0
  153. data/lib/shopify_api/rest/resources/2023_10/gift_card_adjustment.rb +118 -0
  154. data/lib/shopify_api/rest/resources/2023_10/image.rb +157 -0
  155. data/lib/shopify_api/rest/resources/2023_10/inventory_item.rb +108 -0
  156. data/lib/shopify_api/rest/resources/2023_10/inventory_level.rb +179 -0
  157. data/lib/shopify_api/rest/resources/2023_10/location.rb +167 -0
  158. data/lib/shopify_api/rest/resources/2023_10/locations_for_move.rb +56 -0
  159. data/lib/shopify_api/rest/resources/2023_10/marketing_event.rb +209 -0
  160. data/lib/shopify_api/rest/resources/2023_10/metafield.rb +344 -0
  161. data/lib/shopify_api/rest/resources/2023_10/mobile_platform_application.rb +110 -0
  162. data/lib/shopify_api/rest/resources/2023_10/order.rb +491 -0
  163. data/lib/shopify_api/rest/resources/2023_10/order_risk.rb +144 -0
  164. data/lib/shopify_api/rest/resources/2023_10/page.rb +194 -0
  165. data/lib/shopify_api/rest/resources/2023_10/payment.rb +140 -0
  166. data/lib/shopify_api/rest/resources/2023_10/payment_gateway.rb +143 -0
  167. data/lib/shopify_api/rest/resources/2023_10/payment_transaction.rb +107 -0
  168. data/lib/shopify_api/rest/resources/2023_10/payout.rb +97 -0
  169. data/lib/shopify_api/rest/resources/2023_10/policy.rb +69 -0
  170. data/lib/shopify_api/rest/resources/2023_10/price_rule.rb +223 -0
  171. data/lib/shopify_api/rest/resources/2023_10/product.rb +223 -0
  172. data/lib/shopify_api/rest/resources/2023_10/product_listing.rb +196 -0
  173. data/lib/shopify_api/rest/resources/2023_10/product_resource_feedback.rb +88 -0
  174. data/lib/shopify_api/rest/resources/2023_10/province.rb +132 -0
  175. data/lib/shopify_api/rest/resources/2023_10/recurring_application_charge.rb +172 -0
  176. data/lib/shopify_api/rest/resources/2023_10/redirect.rb +139 -0
  177. data/lib/shopify_api/rest/resources/2023_10/refund.rb +151 -0
  178. data/lib/shopify_api/rest/resources/2023_10/report.rb +121 -0
  179. data/lib/shopify_api/rest/resources/2023_10/resource_feedback.rb +73 -0
  180. data/lib/shopify_api/rest/resources/2023_10/script_tag.rb +155 -0
  181. data/lib/shopify_api/rest/resources/2023_10/shipping_zone.rb +83 -0
  182. data/lib/shopify_api/rest/resources/2023_10/shop.rb +218 -0
  183. data/lib/shopify_api/rest/resources/2023_10/smart_collection.rb +216 -0
  184. data/lib/shopify_api/rest/resources/2023_10/storefront_access_token.rb +87 -0
  185. data/lib/shopify_api/rest/resources/2023_10/tender_transaction.rb +93 -0
  186. data/lib/shopify_api/rest/resources/2023_10/theme.rb +123 -0
  187. data/lib/shopify_api/rest/resources/2023_10/transaction.rb +184 -0
  188. data/lib/shopify_api/rest/resources/2023_10/usage_charge.rb +102 -0
  189. data/lib/shopify_api/rest/resources/2023_10/user.rb +138 -0
  190. data/lib/shopify_api/rest/resources/2023_10/variant.rb +208 -0
  191. data/lib/shopify_api/rest/resources/2023_10/webhook.rb +168 -0
  192. data/lib/shopify_api/version.rb +1 -1
  193. data/lib/shopify_api/webhooks/registration.rb +19 -4
  194. data/lib/shopify_api/webhooks/registrations/event_bridge.rb +1 -1
  195. data/lib/shopify_api/webhooks/registrations/http.rb +1 -1
  196. data/lib/shopify_api/webhooks/registrations/pub_sub.rb +2 -1
  197. data/lib/shopify_api/webhooks/registry.rb +9 -5
  198. data/shopify_api.gemspec +1 -1
  199. metadata +154 -12
  200. data/.github/workflows/stale.yml +0 -43
  201. data/docs/issues.md +0 -39
  202. data/docs/usage/session_storage.md +0 -46
data/docs/usage/rest.md CHANGED
@@ -1,10 +1,153 @@
1
1
  # Make a REST API call
2
2
 
3
- Once OAuth is complete, we can use the `ShopifyAPI::Clients::Rest::Admin` client to make an API call to the Shopify Admin API. To do this, you can create an instance of `ShopifyAPI::Clients::Rest::Admin` using the current session to make requests to the Admin API.
3
+ Once OAuth is complete, we can use `ShopifyAPI`'s REST library to make authenticated API calls to the Shopify Admin API.
4
+ #### Required Session
5
+ Every API request requires a valid
6
+ [ShopifyAPI::Auth::Session](https://github.com/Shopify/shopify-api-ruby/blob/main/lib/shopify_api/auth/session.rb).
7
+
8
+ To instantiate a session, we recommend you either use the `shopify_app` if working in Rails, or refer to our OAuth docs on constructing a session:
9
+ - ["Custom Apps"](https://github.com/Shopify/shopify-api-ruby/blob/main/docs/usage/custom_apps.md) - documentation on how to create Session from a custom app API token.
10
+ - ["Performing OAuth"](https://github.com/Shopify/shopify-api-ruby/blob/main/docs/usage/oauth.md) - documentation on how to create new sessions
11
+ - [[ShopifyApp] - "Session"](https://github.com/Shopify/shopify_app/blob/main/docs/shopify_app/sessions.md) - documentation on session handling if you're using the [`ShopifyApp`](https://github.com/Shopify/shopify_app) gem.
12
+
13
+ #### There are 2 methods you can use to make REST API calls to Shopify:
14
+ - [Using REST Resources](#using-rest-resources)
15
+ - Resource classes with similar syntax as `ActiveResource`, and follows our REST convention. Example:
16
+ ``` ruby
17
+ # Update product title
18
+ product = ShopifyAPI::Product.find(id: <product_id>)
19
+ product.title = "My awesome product"
20
+ product.save!
21
+ ```
22
+
23
+ - [Using REST Admin Client](#using-rest-admin-client)
24
+ - More manual input method to make the API call. Example:
25
+ ```ruby
26
+ # Create a new client.
27
+ rest_client = ShopifyAPI::Clients::Rest::Admin.new
28
+
29
+ # Update product title
30
+ body = {
31
+ product: {
32
+ title: "My cool product"
33
+ }
34
+ }
35
+
36
+ # Use `client.put` to send your request to the specified Shopify Admin REST API endpoint.
37
+ rest_client.put(path: "products/<id>.json", body: body)
38
+ ```
39
+
40
+ ## Using REST Resources
41
+ We provide a templated class library to access REST resources similar to `ActiveResource`. Format of the methods closely resemble our [REST API schema](https://shopify.dev/docs/api/admin-rest).
42
+
43
+ The version of REST resource that's loaded and used is set from [`ShopifyAPI::Context.setup`](https://github.com/Shopify/shopify-api-ruby/blob/main/README.md#setup-shopify-context)
44
+
45
+ ### Instantiation
46
+ Create an instance of the REST resource you'd like to use and optionally provide the following parameters.
47
+ #### Constructor parameters
48
+ | Parameter | Type | Notes |
49
+ | ----------|------|-------|
50
+ | `session` | `ShopifyAPI::Auth::Session` | Default value is `nil`. <br><br>When `nil` is passed in, active session information is inferred from `ShopifyAPI::Context.active_session`. <br>To set active session, use `ShopifyAPI::Context.activate_session`. <br><br>This is handled automatically behind the scenes if you use ShopifyApp's [session controllers](https://github.com/Shopify/shopify_app/blob/main/docs/shopify_app/sessions.md). |
51
+ | `from_hash` | `Hash` | Default value is `nil`. Sets the resource properties to the values provided from the hash. |
52
+
53
+ Examples:
54
+
55
+ ```ruby
56
+ # To construct an Orders object using default session
57
+ # This creates a new order object with properties provided from the hash
58
+ order = ShopifyAPI::Orders.new(from_hash: {property: value})
59
+ order.save!
60
+ ```
4
61
 
5
- ## Methods
62
+ ### Methods
63
+ Typical methods provided for each resources are:
64
+ - `find`
65
+ - `delete`
66
+ - `all`
67
+ - `count`
68
+
69
+ Full list of methods can be found on each of the resource class.
70
+ - Path:
71
+ - https://github.com/Shopify/shopify-api-ruby/blob/main/lib/shopify_api/rest/resources/#{version}/#{resource}.rb
72
+ - Example for `Order` resource on `2023-04` version:
73
+ - https://github.com/Shopify/shopify-api-ruby/blob/main/lib/shopify_api/rest/resources/2023_04/order.rb
74
+
75
+ ### Usage Examples
76
+ ⚠️ Reference documentation on [shopify.dev](https://shopify.dev/docs/api/admin-rest) contains more examples on how to use each REST Resources.
77
+
78
+ ```Ruby
79
+ # Find and update a customer email
80
+ customer = ShopifyAPI::Customer.find(id: customer_id)
81
+ customer.email = "steve-lastnameson@example.com"
82
+ customer.save!
83
+
84
+ # Create a new product from hash
85
+ product_properties = {
86
+ title: "My awesome product"
87
+ }
88
+ product = ShopifyAPI::Product.new(from_hash: product_properties)
89
+ product.save!
90
+
91
+ # Create a product manually
92
+ product = ShopifyAPI::Product.new
93
+ product.title = "Another one"
94
+ product.save!
95
+
96
+ # Get all orders
97
+ orders = ShopifyAPI::Orders.all
6
98
 
7
- The Rest Admin client offers the 4 core request methods: `get`, `delete`, `post`, and `put`. These methods each take the parameters outlined in the table below. If the request is successful these methods will all return a `ShopifyAPI::Clients::HttpResponse` object, which has properties `code`, `headers`, and `body` otherwise an error will be raised describing what went wrong.
99
+ # Retrieve a specific fulfillment order
100
+ fulfillment_order_id = 123456789
101
+ fulfillment_order = ShopifyAPI::FulfillmentOrder.find(id: fulfillment_order_id)
102
+
103
+ # Remove an existing product image
104
+ product_id = 1234567
105
+ image_id = 1233211234567
106
+ ShopifyAPI::Image.delete(product_id: product_id, id: image_id)
107
+ ```
108
+
109
+ More examples can be found in each resource's documentation on [shopify.dev](https://shopify.dev/docs/api/admin-rest), e.g.:
110
+ - [Order](https://shopify.dev/docs/api/admin-rest/current/resources/order)
111
+ - [Product](https://shopify.dev/docs/api/admin-rest/current/resources/product)
112
+
113
+ ## Using REST Admin Client
114
+
115
+ ### Instantiation
116
+ Create an instance of [`ShopifyAPI::Clients::Rest::Admin`](https://github.com/Shopify/shopify-api-ruby/blob/main/lib/shopify_api/clients/rest/admin.rb) using the current session to make requests to the Admin API.
117
+ #### Constructor parameters
118
+ | Parameter | Type | Notes |
119
+ | ----------|------|-------|
120
+ | `session` | `ShopifyAPI::Auth::Session` | Default value is `nil`. <br><br>When `nil` is passed in, active session information is inferred from `ShopifyAPI::Context.active_session`. <br>To set active session, use `ShopifyAPI::Context.activate_session`. <br><br>This is handled automatically behind the scenes if you use ShopifyApp's [session controllers](https://github.com/Shopify/shopify_app/blob/main/docs/shopify_app/sessions.md). |
121
+ | `api_version` | `String` | Default value is `nil`. When `nil` is passed in, api version is inferred from [`ShopifyAPI::Context.setup`](https://github.com/Shopify/shopify-api-ruby/blob/main/README.md#setup-shopify-context).|
122
+
123
+ Examples:
124
+ ```ruby
125
+ # Create a default client with `ShopifyAPI::Context.api_version`
126
+ # and the active session from `ShopifyAPI::Context.active_session`
127
+ client = ShopifyAPI::Clients::Rest::Admin.new
128
+
129
+ # Create a client with a specific session "my_session"
130
+ client = ShopifyAPI::Clients::Rest::Admin.new(session: my_session)
131
+
132
+ # Create a client with active session from `ShopifyAPI::Context.active_session`
133
+ # and a specific api_version - "unstable"
134
+ client = ShopifyAPI::Clients::Rest::Admin.new(api_version: "unstable")
135
+
136
+ # Create a client with a specific session "my_session" and api_version "unstable"
137
+ client = ShopifyAPI::Clients::Rest::Admin.new(session: my_session, api_version: "unstable")
138
+ ```
139
+
140
+ ### Methods
141
+
142
+ The `ShopifyAPI::Clients::Rest::Admin` client offers the 4 core request methods:
143
+ - `get`
144
+ - `delete`
145
+ - `post`
146
+ - `put`
147
+
148
+ #### Input Parameters
149
+
150
+ Each method can take the parameters outlined in the table below.
8
151
 
9
152
  | Parameter | Type | Required in Methods | Default Value | Notes |
10
153
  | -------------- | -------------------------------------------------------- | :-----------------: | :-----------: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
@@ -14,16 +157,40 @@ The Rest Admin client offers the 4 core request methods: `get`, `delete`, `post`
14
157
  | `extraHeaders` | `Hash(any(Symbol, String), any(String, Integer, Float))` | none | none | Any additional headers you want to send with your request |
15
158
  | `tries` | `Integer` | None | `1` | The maximum number of times to try the request _(must be >= 0)_ |
16
159
 
17
- **Note:** _These paramaters can still be used in all methods regardless of if they are required._
160
+ **Note:** _These parameters can still be used in all methods regardless of if they are required._
18
161
 
19
- ## Usage Examples:
162
+ #### Output
163
+ ##### Success
164
+ If the request is successful these methods will all return a [`ShopifyAPI::Clients::HttpResponse`](https://github.com/Shopify/shopify-api-ruby/blob/main/lib/shopify_api/clients/http_response.rb) object, which has the following methods:
165
+ | Methods | Type | Notes |
166
+ |---------|------|-------|
167
+ | `code` |`Integer`| HTTP Response code, e.g. `200`|
168
+ | `header` |`Hash{String, [String]}` | HTTP Response headers |
169
+ | `body` | `Hash{String, Untyped}` | HTTP Response body |
170
+ | `prev_page_info` | `String` | See [Pagination](#pagination)|
171
+ | `next_page_info` | `String` | See [Pagination](#pagination)|
20
172
 
21
- ### Perform a `GET` request:
173
+ ##### Failure
174
+ If the request has failed, an error will be raised describing what went wrong.
175
+ You can rescue [`ShopifyAPI::Errors::HttpResponseError`](https://github.com/Shopify/shopify-api-ruby/blob/main/lib/shopify_api/errors/http_response_error.rb)
176
+ and output error messages with `errors.full_messages`
177
+
178
+ See example:
22
179
 
23
180
  ```ruby
24
- # Load the current session to get the `accessToken`.
25
- session = ShopifyAPI::Utils::SessionUtils.load_current_session(headers, cookies, is_online)
181
+ client = ShopifyAPI::Clients::Rest::Admin.new(session: session)
182
+ response = client.get(path: "NOT-REAL")
183
+ some_function(response.body)
184
+ rescue ShopifyAPI::Errors::HttpResponseError => e
185
+ puts fulfillment.errors.full_messages
186
+ # {"errors"=>"Not Found"}
187
+ # If you report this error, please include this id: bce76672-40c6-4047-b598-46208ab076f0.
188
+ ```
189
+ ### Usage Examples
190
+
191
+ #### Perform a `GET` request
26
192
 
193
+ ```ruby
27
194
  # Create a new client.
28
195
  client = ShopifyAPI::Clients::Rest::Admin.new(session: session)
29
196
 
@@ -33,13 +200,11 @@ response = client.get(path: "products")
33
200
  # Do something with the returned data
34
201
  some_function(response.body)
35
202
  ```
203
+ _For more information on the `products` endpoint, [check out our API reference guide](https://shopify.dev/docs/api/admin-rest/latest/resources/product)._
36
204
 
37
- ### Perform a `POST` request:
205
+ #### Perform a `POST` request
38
206
 
39
207
  ```ruby
40
- # Load the current session to get the `accessToken`.
41
- session = ShopifyAPI::Utils::SessionUtils.load_current_session(headers, cookies, is_online)
42
-
43
208
  # Create a new client.
44
209
  client = ShopifyAPI::Clients::Rest::Admin.new(session: session)
45
210
 
@@ -54,49 +219,61 @@ body = {
54
219
  }
55
220
 
56
221
  # Use `client.post` to send your request to the specified Shopify Admin REST API endpoint.
222
+ # This POST request will create a new product.
57
223
  client.post({
58
224
  path: "products",
59
225
  body: body,
60
226
  });
61
227
  ```
62
228
 
63
- _for more information on the `products` endpoint, [check out our API reference guide](https://shopify.dev/docs/api/admin-rest/unstable/resources/product)._
229
+ _For more information on the `products` endpoint, [check out our API reference guide](https://shopify.dev/docs/api/admin-rest/latest/resources/product)._
64
230
 
65
- ### Override the `api_version`:
231
+ #### Perform a `PUT` request
232
+ ```ruby
233
+ # Create a new client.
234
+ client = ShopifyAPI::Clients::Rest::Admin.new
66
235
 
67
- ```ruby
68
- # To experiment with prerelease features, pass the api_version "unstable".
69
- client = ShopifyAPI::Clients::Rest::Admin.new(session: session, api_version: "unstable")
236
+ # Update product title
237
+ body = {
238
+ product: {
239
+ title: "My cool product"
240
+ }
241
+ }
242
+
243
+ # Use `client.put` to send your request to the specified Shopify Admin REST API endpoint.
244
+ # This will update product title for product with ID <id>
245
+ client.put(path: "products/<id>.json", body: body)
70
246
  ```
71
247
 
72
- ## Pagination
248
+ _For more information on the `products` endpoint, [check out our API reference guide](https://shopify.dev/docs/api/admin-rest/latest/resources/product)._
249
+
250
+ ### Pagination
73
251
 
74
252
  This library also supports cursor-based pagination for REST Admin API requests. [Learn more about REST request pagination](https://shopify.dev/docs/api/usage/pagination-rest).
75
253
 
76
- After making a request, the `next_page_info` and `prev_page_info` can be found on the response object and passed as the page_info query param in other requests.
254
+ #### REST Admin Client
255
+ After making a request, the `next_page_info` and `prev_page_info` can be found on the response object and passed as the `page_info` query param in other requests.
77
256
 
78
257
  An example of this is shown below:
79
258
 
80
259
  ```ruby
81
- session = ShopifyAPI::Utils::SessionUtils.load_current_session(headers, cookies, is_online)
82
260
  client = ShopifyAPI::Clients::Rest::Admin.new(session: session)
83
261
 
84
262
  response = client.get(path: "products", query: { limit: 10 })
263
+ next_page_info = response.next_page_info
85
264
 
86
- loop do
87
- some_function(response.body)
88
- break unless response.next_page_info
89
- response = client.get(path: "products", query: { limit: 10, page_info: response.next_page_info })
265
+ if next_page_info
266
+ next_page_response =client.get(path: "products", query: { limit: 10, page_info: next_page_info })
267
+ some_function(next_page_response)
90
268
  end
91
269
  ```
92
270
 
93
- Similarly, when using REST resources the `next_page_info` and `prev_page_info` can be found on the Resource class and passed as the page_info query param in other requests.
271
+ #### REST Resource
272
+ Similarly, when using REST resources the `next_page_info` and `prev_page_info` can be found on the Resource class and passed as the `page_info` query param in other requests.
94
273
 
95
274
  An example of this is shown below:
96
275
 
97
276
  ```ruby
98
- session = ShopifyAPI::Utils::SessionUtils.load_current_session(headers, cookies, is_online)
99
-
100
277
  products = ShopifyAPI::Product.all(session: session, limit: 10)
101
278
 
102
279
  loop do
@@ -106,39 +283,4 @@ loop do
106
283
  end
107
284
  ```
108
285
 
109
- The next/previous page_info strings can also be retrieved from the response object and added to a request query to retrieve the next/previous pages.
110
-
111
- An example of this is shown below:
112
-
113
- ```ruby
114
- session = ShopifyAPI::Utils::SessionUtils.load_current_session(headers, cookies, is_online)
115
- client = ShopifyAPI::Clients::Rest::Admin.new(session: session)
116
-
117
- response = client.get(path: "products", query: { limit: 10 })
118
- next_page_info = response.next_page_info
119
-
120
- if next_page_info
121
- next_page_response =client.get(path: "products", query: { limit: 10, page_info: next_page_info })
122
- some_function(next_page_response)
123
- end
124
- ```
125
-
126
- ### Error Messages
127
-
128
- You can rescue `ShopifyAPI::Errors::HttpResponseError` and output error messages with `errors.full_messages`
129
-
130
- See example:
131
-
132
- ```ruby
133
- fulfillment = ShopifyAPI::Fulfillment.new(session: @session)
134
- fulfillment.order_id = 2776493818000
135
- ...
136
- fulfillment.tracking_company = "Jack Black's Pack, Stack and Track"
137
- fulfillment.save()
138
- rescue ShopifyAPI::Errors::HttpResponseError => e
139
- puts fulfillment.errors.full_messages
140
- # {"base"=>["Line items are already fulfilled"]}
141
- # If you report this error, please include this id: e712dde0-1270-4258-8cdb-d198792c917e.
142
- ```
143
-
144
286
  [Back to guide index](../README.md)
@@ -2,13 +2,16 @@
2
2
 
3
3
  The `shopify_api` gem provides webhook functionality to make it easy to both subscribe to and process webhooks. To implement in your app follow the steps outlined below.
4
4
 
5
+ ## Use with Rails
6
+ If using in the Rails framework, we highly recommend you use the [shopify_app](https://github.com/Shopify/shopify_app) gem to interact with this gem. That gem handles [webhooks with a declarative configuration](https://github.com/Shopify/shopify_app/blob/main/docs/shopify_app/webhooks.md).
7
+
5
8
  ## Create a Webhook Handler
6
9
 
7
10
  If you want to register for an http webhook you need to implement a webhook handler which the `shopify_api` gem can use to determine how to process your webhook. You can make multiple implementations (one per topic) or you can make one implementation capable of handling all the topics you want to subscribe to. To do this simply make a module or class that includes or extends `ShopifyAPI::Webhooks::WebhookHandler` and implement the handle method which accepts the following named parameters: topic: `String`, shop: `String`, and body: `Hash[String, untyped]`. An example implementation is shown below:
8
11
 
9
12
  ```ruby
10
13
  module WebhookHandler
11
- include ShopifyAPI::Webhooks::Handler
14
+ extend ShopifyAPI::Webhooks::Handler
12
15
 
13
16
  class << self
14
17
  def handle(topic:, shop:, body:)
@@ -25,7 +28,10 @@ end
25
28
  The next step is to add all the webhooks you would like to subscribe to for any shop to the webhook registry. To do this you can call `ShopifyAPI::Webhooks::Registry.add_registration` for each webhook you would like to handle. `add_registration` accepts a topic string, a delivery_method symbol (currently supporting `:http`, `:event_bridge`, and `:pub_sub`), a webhook path (the relative path for an http webhook) and a handler. This only needs to be done once when the app is started and we recommend doing this at the same time that you setup `ShopifyAPI::Context`. An example is shown below to register an http webhook:
26
29
 
27
30
  ```ruby
28
- registration = ShopifyAPI::Webhooks::Registry.add_registration(topic: "orders/create", delivery_method: :http, handler: WebhookHandler)
31
+ registration = ShopifyAPI::Webhooks::Registry.add_registration(topic: "orders/create",
32
+ delivery_method: :http,
33
+ handler: WebhookHandler,
34
+ path: 'callback/orders/create')
29
35
  ```
30
36
  If you are only interested in particular fields, you can optionally filter the data sent by Shopify by specifying the `fields` parameter. Note that you will still receive a webhook request from Shopify every time the resource is updated, but only the specified fields will be sent:
31
37
 
@@ -34,8 +40,20 @@ registration = ShopifyAPI::Webhooks::Registry.add_registration(
34
40
  topic: "orders/create",
35
41
  delivery_method: :http,
36
42
  handler: WebhookHandler,
43
+ path: 'callback/orders/create',
37
44
  fields: ["number","note"] # this can also be a single comma separated string
38
- )
45
+ )
46
+ ```
47
+
48
+ If you are storing metafields on an object you are receiving webhooks for, you can specify them on registration to make sure that they are also sent through the `metafieldNamespaces` parameter. Note if you are also using the `fields` parameter you will need to add `metafields` into that as well.
49
+
50
+ ```ruby
51
+ registration = ShopifyAPI::Webhooks::Registry.add_registration(
52
+ topic: "orders/create",
53
+ delivery_method: :http,
54
+ handler: WebhookHandler,
55
+ metafieldNamespaces: ["custom"]
56
+ )
39
57
  ```
40
58
 
41
59
  **Note**: The webhooks you register with Shopify are saved in the Shopify platform, but the local `ShopifyAPI::Webhooks::Registry` needs to be reloaded whenever your server restarts.
@@ -75,7 +93,7 @@ ShopifyAPI::Webhooks::Registry.register(topic: "<specific-topic>", session: shop
75
93
 
76
94
  This will return a single `ShopifyAPI::Webhooks::RegisterResult`.
77
95
 
78
- ## Unregister a Webhook
96
+ ## Unregister a Webhook
79
97
 
80
98
  To unregister a topic from a shop you can simply call:
81
99
  ```ruby
@@ -5,6 +5,8 @@ module ShopifyAPI
5
5
  module AdminVersions
6
6
  SUPPORTED_ADMIN_VERSIONS = T.let([
7
7
  "unstable",
8
+ "2023-10",
9
+ "2023-07",
8
10
  "2023-04",
9
11
  "2023-01",
10
12
  "2022-10",
@@ -13,7 +15,7 @@ module ShopifyAPI
13
15
  "2022-01",
14
16
  ], T::Array[String])
15
17
 
16
- LATEST_SUPPORTED_ADMIN_VERSION = T.let("2023-04", String)
18
+ LATEST_SUPPORTED_ADMIN_VERSION = T.let("2023-10", String)
17
19
  end
18
20
 
19
21
  SUPPORTED_ADMIN_VERSIONS = ShopifyAPI::AdminVersions::SUPPORTED_ADMIN_VERSIONS
@@ -12,7 +12,9 @@ module ShopifyAPI
12
12
  @is_private = T.let(false, T::Boolean)
13
13
  @private_shop = T.let(nil, T.nilable(String))
14
14
  @is_embedded = T.let(true, T::Boolean)
15
- @logger = T.let(::Logger.new($stdout), ::Logger)
15
+ # Logger can either be a Logger or an ActiveSupport::BroadcastLogger, which is new in Rails 7.1.0. To avoid adding a
16
+ # dependency Active Support >= 7.1.0, we go with T.untyped
17
+ @logger = T.let(::Logger.new($stdout), T.untyped)
16
18
  @log_level = T.let(:info, Symbol)
17
19
  @notified_missing_resources_folder = T.let({}, T::Hash[String, T::Boolean])
18
20
  @active_session = T.let(Concurrent::ThreadLocalVar.new { nil }, T.nilable(Concurrent::ThreadLocalVar))
@@ -33,7 +35,7 @@ module ShopifyAPI
33
35
  is_private: T::Boolean,
34
36
  is_embedded: T::Boolean,
35
37
  log_level: T.any(String, Symbol),
36
- logger: ::Logger,
38
+ logger: T.untyped,
37
39
  host_name: T.nilable(String),
38
40
  host: T.nilable(String),
39
41
  private_shop: T.nilable(String),
@@ -84,6 +86,7 @@ module ShopifyAPI
84
86
  sig { params(api_version: String).void }
85
87
  def load_rest_resources(api_version:)
86
88
  # Unload any previous instances - mostly useful for tests where we need to reset the version
89
+ @rest_resource_loader&.setup
87
90
  @rest_resource_loader&.unload
88
91
 
89
92
  # No resources for the unstable version
@@ -115,7 +118,7 @@ module ShopifyAPI
115
118
  sig { returns(Auth::AuthScopes) }
116
119
  attr_reader :scope
117
120
 
118
- sig { returns(::Logger) }
121
+ sig { returns(T.untyped) }
119
122
  attr_reader :logger
120
123
 
121
124
  sig { returns(Symbol) }
@@ -97,9 +97,9 @@ module ShopifyAPI
97
97
  class_name.underscore
98
98
  end
99
99
 
100
- sig { returns(String) }
101
- def json_response_body_name
102
- class_name
100
+ sig { returns(T::Array[String]) }
101
+ def json_response_body_names
102
+ [class_name]
103
103
  end
104
104
 
105
105
  sig { returns(T.nilable(String)) }
@@ -210,14 +210,16 @@ module ShopifyAPI
210
210
 
211
211
  body = T.cast(response.body, T::Hash[String, T.untyped])
212
212
 
213
- response_name = json_response_body_name
213
+ response_names = json_response_body_names
214
214
 
215
- if body.key?(response_name.pluralize) || (body.key?(response_name) && body[response_name].is_a?(Array))
216
- (body[response_name.pluralize] || body[response_name]).each do |entry|
217
- objects << create_instance(data: entry, session: session)
215
+ response_names.each do |response_name|
216
+ if body.key?(response_name.pluralize) || (body.key?(response_name) && body[response_name].is_a?(Array))
217
+ (body[response_name.pluralize] || body[response_name]).each do |entry|
218
+ objects << create_instance(data: entry, session: session)
219
+ end
220
+ elsif body.key?(response_name)
221
+ objects << create_instance(data: body[response_name], session: session)
218
222
  end
219
- elsif body.key?(response_name)
220
- objects << create_instance(data: body[response_name], session: session)
221
223
  end
222
224
 
223
225
  objects
@@ -347,10 +349,8 @@ module ShopifyAPI
347
349
  )
348
350
 
349
351
  if update_object
350
- self.class.create_instance(
351
- data: response.body[self.class.class_name.downcase],
352
- session: @session, instance: self
353
- )
352
+ response_name = self.class.json_response_body_names & response.body.keys
353
+ self.class.create_instance(data: response.body[response_name.first], session: @session, instance: self)
354
354
  end
355
355
  rescue ShopifyAPI::Errors::HttpResponseError => e
356
356
  @errors.errors << e
@@ -361,10 +361,22 @@ module ShopifyAPI
361
361
 
362
362
  sig { returns(T::Hash[String, String]) }
363
363
  def attributes_to_update
364
- HashDiff::Comparison.new(
365
- deep_stringify_keys(original_state),
364
+ original_state_for_update = original_state.reject do |attribute, _|
365
+ self.class.read_only_attributes&.include?("@#{attribute}".to_sym)
366
+ end
367
+
368
+ diff = HashDiff::Comparison.new(
369
+ deep_stringify_keys(original_state_for_update),
366
370
  deep_stringify_keys(to_hash(true)),
367
371
  ).left_diff
372
+
373
+ diff.each do |attribute, value|
374
+ if value.is_a?(Hash) && value[0] == HashDiff::NO_VALUE
375
+ diff[attribute] = send(attribute)
376
+ end
377
+ end
378
+
379
+ diff
368
380
  end
369
381
 
370
382
  sig { returns(Symbol) }
@@ -169,17 +169,13 @@ module ShopifyAPI
169
169
 
170
170
  sig do
171
171
  params(
172
- reason: T.untyped,
173
- reason_notes: T.untyped,
174
- notify_merchant: T.untyped,
172
+ fulfillment_hold: T.untyped,
175
173
  body: T.untyped,
176
174
  kwargs: T.untyped
177
175
  ).returns(T.untyped)
178
176
  end
179
177
  def hold(
180
- reason: nil,
181
- reason_notes: nil,
182
- notify_merchant: nil,
178
+ fulfillment_hold: nil,
183
179
  body: nil,
184
180
  **kwargs
185
181
  )
@@ -188,7 +184,7 @@ module ShopifyAPI
188
184
  operation: :hold,
189
185
  session: @session,
190
186
  ids: {id: @id},
191
- params: {reason: reason, reason_notes: reason_notes, notify_merchant: notify_merchant}.merge(kwargs).compact,
187
+ params: {fulfillment_hold: fulfillment_hold}.merge(kwargs).compact,
192
188
  body: body,
193
189
  entity: self,
194
190
  )
@@ -65,7 +65,7 @@ module ShopifyAPI
65
65
  @shop_owner = T.let(nil, T.nilable(String))
66
66
  @source = T.let(nil, T.nilable(String))
67
67
  @tax_shipping = T.let(nil, T.nilable(String))
68
- @taxes_included = T.let(nil, T.nilable(String))
68
+ @taxes_included = T.let(nil, T.nilable(T::Boolean))
69
69
  @timezone = T.let(nil, T.nilable(String))
70
70
  @transactional_sms_disabled = T.let(nil, T.nilable(T::Boolean))
71
71
  @updated_at = T.let(nil, T.nilable(String))
@@ -177,7 +177,7 @@ module ShopifyAPI
177
177
  attr_reader :source
178
178
  sig { returns(T.nilable(String)) }
179
179
  attr_reader :tax_shipping
180
- sig { returns(T.nilable(String)) }
180
+ sig { returns(T.nilable(T::Boolean)) }
181
181
  attr_reader :taxes_included
182
182
  sig { returns(T.nilable(String)) }
183
183
  attr_reader :timezone
@@ -170,17 +170,13 @@ module ShopifyAPI
170
170
 
171
171
  sig do
172
172
  params(
173
- reason: T.untyped,
174
- reason_notes: T.untyped,
175
- notify_merchant: T.untyped,
173
+ fulfillment_hold: T.untyped,
176
174
  body: T.untyped,
177
175
  kwargs: T.untyped
178
176
  ).returns(T.untyped)
179
177
  end
180
178
  def hold(
181
- reason: nil,
182
- reason_notes: nil,
183
- notify_merchant: nil,
179
+ fulfillment_hold: nil,
184
180
  body: nil,
185
181
  **kwargs
186
182
  )
@@ -189,7 +185,7 @@ module ShopifyAPI
189
185
  operation: :hold,
190
186
  session: @session,
191
187
  ids: {id: @id},
192
- params: {reason: reason, reason_notes: reason_notes, notify_merchant: notify_merchant}.merge(kwargs).compact,
188
+ params: {fulfillment_hold: fulfillment_hold}.merge(kwargs).compact,
193
189
  body: body,
194
190
  entity: self,
195
191
  )
@@ -65,7 +65,7 @@ module ShopifyAPI
65
65
  @shop_owner = T.let(nil, T.nilable(String))
66
66
  @source = T.let(nil, T.nilable(String))
67
67
  @tax_shipping = T.let(nil, T.nilable(String))
68
- @taxes_included = T.let(nil, T.nilable(String))
68
+ @taxes_included = T.let(nil, T.nilable(T::Boolean))
69
69
  @timezone = T.let(nil, T.nilable(String))
70
70
  @transactional_sms_disabled = T.let(nil, T.nilable(T::Boolean))
71
71
  @updated_at = T.let(nil, T.nilable(String))
@@ -177,7 +177,7 @@ module ShopifyAPI
177
177
  attr_reader :source
178
178
  sig { returns(T.nilable(String)) }
179
179
  attr_reader :tax_shipping
180
- sig { returns(T.nilable(String)) }
180
+ sig { returns(T.nilable(T::Boolean)) }
181
181
  attr_reader :taxes_included
182
182
  sig { returns(T.nilable(String)) }
183
183
  attr_reader :timezone
@@ -51,10 +51,12 @@ module ShopifyAPI
51
51
 
52
52
  class << self
53
53
  sig do
54
- returns(String)
54
+ returns(T::Array[String])
55
55
  end
56
- def json_response_body_name()
57
- "fulfillment_order"
56
+ def json_response_body_names()
57
+ [
58
+ "fulfillment_order"
59
+ ]
58
60
  end
59
61
 
60
62
  sig do
@@ -87,6 +87,16 @@ module ShopifyAPI
87
87
  "address"
88
88
  end
89
89
 
90
+ sig do
91
+ returns(T::Array[String])
92
+ end
93
+ def json_response_body_names()
94
+ [
95
+ "customer_address",
96
+ "address"
97
+ ]
98
+ end
99
+
90
100
  sig do
91
101
  params(
92
102
  id: T.any(Integer, String),