loyverse_api 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.env.sample +1 -0
- data/.gitignore +54 -0
- data/.rspec +3 -0
- data/CHANGELOG.md +12 -0
- data/Gemfile +7 -0
- data/LICENSE +21 -0
- data/LICENSE.txt +21 -0
- data/README.md +516 -0
- data/Rakefile +6 -0
- data/examples/basic_usage.rb +115 -0
- data/examples/create_item.rb +71 -0
- data/examples/webhook_server.rb +120 -0
- data/lib/loyverse_api/client.rb +157 -0
- data/lib/loyverse_api/configuration.rb +13 -0
- data/lib/loyverse_api/endpoints/categories.rb +43 -0
- data/lib/loyverse_api/endpoints/customers.rb +131 -0
- data/lib/loyverse_api/endpoints/discounts.rb +91 -0
- data/lib/loyverse_api/endpoints/employees.rb +31 -0
- data/lib/loyverse_api/endpoints/inventory.rb +41 -0
- data/lib/loyverse_api/endpoints/items.rb +75 -0
- data/lib/loyverse_api/endpoints/modifiers.rb +51 -0
- data/lib/loyverse_api/endpoints/receipts.rb +115 -0
- data/lib/loyverse_api/endpoints/webhooks.rb +85 -0
- data/lib/loyverse_api/errors.rb +19 -0
- data/lib/loyverse_api/version.rb +3 -0
- data/lib/loyverse_api.rb +33 -0
- data/loyverse_api.gemspec +34 -0
- metadata +170 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 8617a119e948c3c8d187b2046710f71dd442eed9bbde9772cf8f21bdb00c6b3b
|
|
4
|
+
data.tar.gz: 503a06d272a520ff26e4cc37526f23dacd10df170a9b536e599b83f56f9f20d5
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: fa8bda79302447775991c4e267882f59c8e61bc4eed36aa1fa6f925f870de05f0f303b02bd309688a7715e5308c3c3ae90893f88fb338c13e836ba1a8e693b44
|
|
7
|
+
data.tar.gz: 4518e72787d2aa4ac351a2739568d1ddab7d80f076e204b646216a0dac342835242b6b97f55a0d6c3b31d9dc5daf1b0731e8aca0d16d8bf96e59931894805425
|
data/.env.sample
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
LOYVERSE_ACCESS_TOKEN=lv_1a2b3c4d5e6f7g8h9i0j_example_token_replace_with_your_actual_access_token
|
data/.gitignore
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
*.gem
|
|
2
|
+
*.rbc
|
|
3
|
+
/.config
|
|
4
|
+
/coverage/
|
|
5
|
+
/InstalledFiles
|
|
6
|
+
/pkg/
|
|
7
|
+
/spec/reports/
|
|
8
|
+
/spec/examples.txt
|
|
9
|
+
/test/tmp/
|
|
10
|
+
/test/version_tmp/
|
|
11
|
+
/tmp/
|
|
12
|
+
|
|
13
|
+
# Used by dotenv library to load environment variables.
|
|
14
|
+
.env
|
|
15
|
+
|
|
16
|
+
# Ignore Byebug command history file.
|
|
17
|
+
.byebug_history
|
|
18
|
+
|
|
19
|
+
# Ignore RubyMine files
|
|
20
|
+
.idea/
|
|
21
|
+
|
|
22
|
+
# Ignore VS Code files
|
|
23
|
+
.vscode/
|
|
24
|
+
|
|
25
|
+
# Ignore bundler config.
|
|
26
|
+
/.bundle/
|
|
27
|
+
|
|
28
|
+
# Ignore the default SQLite database.
|
|
29
|
+
/db/*.sqlite3
|
|
30
|
+
/db/*.sqlite3-*
|
|
31
|
+
|
|
32
|
+
# Ignore all logfiles and tempfiles.
|
|
33
|
+
/log/*
|
|
34
|
+
/tmp/*
|
|
35
|
+
!/log/.keep
|
|
36
|
+
!/tmp/.keep
|
|
37
|
+
|
|
38
|
+
# Ignore uploaded files in development.
|
|
39
|
+
/storage/*
|
|
40
|
+
!/storage/.keep
|
|
41
|
+
|
|
42
|
+
.DS_Store
|
|
43
|
+
|
|
44
|
+
# VCR cassettes
|
|
45
|
+
/spec/fixtures/vcr_cassettes/
|
|
46
|
+
|
|
47
|
+
# Vendor directory for bundled gems
|
|
48
|
+
/vendor/
|
|
49
|
+
|
|
50
|
+
# RSpec status file
|
|
51
|
+
.rspec_status
|
|
52
|
+
|
|
53
|
+
# Gemfile.lock for gems
|
|
54
|
+
Gemfile.lock
|
data/.rspec
ADDED
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [0.1.0] - 2026-01-26
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- Initial release of the Loyverse API Ruby gem
|
|
7
|
+
- Comprehensive error handling
|
|
8
|
+
- Custom exception classes for different error types
|
|
9
|
+
- Automatic retry logic with exponential backoff
|
|
10
|
+
- Rate limiting support
|
|
11
|
+
- Automatic retries for rate limit errors
|
|
12
|
+
- Configurable timeout settings
|
data/Gemfile
ADDED
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Álvaro Delgado
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Loyverse API Wrapper
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,516 @@
|
|
|
1
|
+
# Loyverse API Ruby Gem
|
|
2
|
+
|
|
3
|
+
A comprehensive Ruby wrapper for the [Loyverse API](https://developer.loyverse.com/docs/), providing easy access to all Loyverse resources including items, inventory, receipts, categories, and webhooks.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Complete API Coverage**: Support for all major Loyverse API resources
|
|
8
|
+
- **Authentication**: Personal Access Token and OAuth 2.0 support
|
|
9
|
+
- **Error Handling**: Comprehensive error handling with custom exception classes
|
|
10
|
+
- **Rate Limiting**: Automatic retry logic with exponential backoff
|
|
11
|
+
- **Type Safety**: Well-documented methods with clear parameter types
|
|
12
|
+
- **Webhook Support**: Signature verification for secure webhook handling
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
Add this line to your application's Gemfile:
|
|
17
|
+
|
|
18
|
+
```ruby
|
|
19
|
+
gem 'loyverse_api'
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
And then execute:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
$ bundle install
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Or install it yourself as:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
$ gem install loyverse_api
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Quick Start
|
|
35
|
+
|
|
36
|
+
### Configuration
|
|
37
|
+
|
|
38
|
+
Configure the gem with your Personal Access Token:
|
|
39
|
+
|
|
40
|
+
```ruby
|
|
41
|
+
require 'loyverse_api'
|
|
42
|
+
|
|
43
|
+
LoyverseApi.configure do |config|
|
|
44
|
+
config.access_token = 'your_access_token_here'
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Create a client instance
|
|
48
|
+
client = LoyverseApi.client
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Alternatively, you can create a client directly:
|
|
52
|
+
|
|
53
|
+
```ruby
|
|
54
|
+
configuration = LoyverseApi::Configuration.new
|
|
55
|
+
configuration.access_token = 'your_access_token_here'
|
|
56
|
+
|
|
57
|
+
client = LoyverseApi::Client.new(configuration)
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Getting Your Access Token
|
|
61
|
+
|
|
62
|
+
1. Login to [Loyverse Back Office](https://r.loyverse.com/dashboard)
|
|
63
|
+
2. Navigate to 'Access Tokens' section
|
|
64
|
+
3. Click '+ Add access token'
|
|
65
|
+
4. Fill in name and optional expiration date
|
|
66
|
+
5. Save and copy the token (shown only once)
|
|
67
|
+
|
|
68
|
+
## Usage
|
|
69
|
+
|
|
70
|
+
### Categories
|
|
71
|
+
|
|
72
|
+
<details>
|
|
73
|
+
<summary>Click to see Categories examples</summary>
|
|
74
|
+
|
|
75
|
+
```ruby
|
|
76
|
+
# List categories
|
|
77
|
+
categories = client.list_categories
|
|
78
|
+
|
|
79
|
+
# Get a specific category
|
|
80
|
+
category = client.get_category('category-uuid')
|
|
81
|
+
|
|
82
|
+
# Create a category
|
|
83
|
+
new_category = client.create_category(
|
|
84
|
+
name: 'Beverages',
|
|
85
|
+
color: 'BLUE'
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
# Delete a category
|
|
89
|
+
client.delete_category('category-uuid')
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
</details>
|
|
93
|
+
|
|
94
|
+
### Items
|
|
95
|
+
|
|
96
|
+
<details>
|
|
97
|
+
<summary>Click to see Items examples</summary>
|
|
98
|
+
|
|
99
|
+
```ruby
|
|
100
|
+
# List items
|
|
101
|
+
items = client.list_items(limit: 50)
|
|
102
|
+
|
|
103
|
+
# Get items updated after a specific date
|
|
104
|
+
recent_items = client.list_items(
|
|
105
|
+
updated_at_min: Time.now - (7 * 24 * 60 * 60)
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
# Get a specific item
|
|
109
|
+
item = client.get_item('item-uuid')
|
|
110
|
+
|
|
111
|
+
# Create an item with variants
|
|
112
|
+
new_item = client.create_item(
|
|
113
|
+
item_name: 'Coffee',
|
|
114
|
+
category_id: 'category-uuid',
|
|
115
|
+
track_stock: true,
|
|
116
|
+
variants: [
|
|
117
|
+
{
|
|
118
|
+
sku: 'COFFEE-S',
|
|
119
|
+
price: 3.50,
|
|
120
|
+
cost: 1.50
|
|
121
|
+
}
|
|
122
|
+
]
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
# Update an item
|
|
126
|
+
client.update_item(
|
|
127
|
+
'item-uuid',
|
|
128
|
+
item_name: 'Premium Coffee'
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
# Delete an item
|
|
132
|
+
client.delete_item('item-uuid')
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
</details>
|
|
136
|
+
|
|
137
|
+
### Inventory
|
|
138
|
+
|
|
139
|
+
<details>
|
|
140
|
+
<summary>Click to see Inventory examples</summary>
|
|
141
|
+
|
|
142
|
+
```ruby
|
|
143
|
+
# List inventory levels
|
|
144
|
+
inventory = client.list_inventory
|
|
145
|
+
|
|
146
|
+
# Filter by variant
|
|
147
|
+
variant_inventory = client.list_inventory(variant_id: 'variant-uuid')
|
|
148
|
+
|
|
149
|
+
# Filter by store
|
|
150
|
+
store_inventory = client.list_inventory(store_id: 'store-uuid')
|
|
151
|
+
|
|
152
|
+
# Update inventory level
|
|
153
|
+
client.update_inventory(
|
|
154
|
+
variant_id: 'variant-uuid',
|
|
155
|
+
store_id: 'store-uuid',
|
|
156
|
+
in_stock: 150
|
|
157
|
+
)
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
</details>
|
|
161
|
+
|
|
162
|
+
### Receipts
|
|
163
|
+
|
|
164
|
+
<details>
|
|
165
|
+
<summary>Click to see Receipts examples</summary>
|
|
166
|
+
|
|
167
|
+
```ruby
|
|
168
|
+
# List receipts
|
|
169
|
+
receipts = client.list_receipts(order: 'DESC')
|
|
170
|
+
|
|
171
|
+
# Filter by store
|
|
172
|
+
store_receipts = client.list_receipts(store_id: 'store-uuid')
|
|
173
|
+
|
|
174
|
+
# Filter by date range
|
|
175
|
+
receipts_by_date = client.list_receipts(
|
|
176
|
+
created_at_min: '2024-01-01T00:00:00Z',
|
|
177
|
+
created_at_max: '2024-01-31T23:59:59Z'
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
# Get a specific receipt
|
|
181
|
+
receipt = client.get_receipt('12345')
|
|
182
|
+
|
|
183
|
+
# Create a receipt
|
|
184
|
+
new_receipt = client.create_receipt(
|
|
185
|
+
receipt_date: Time.now,
|
|
186
|
+
store_id: 'store-uuid',
|
|
187
|
+
line_items: [
|
|
188
|
+
{
|
|
189
|
+
variant_id: 'variant-uuid',
|
|
190
|
+
quantity: 2,
|
|
191
|
+
price: 10.00
|
|
192
|
+
}
|
|
193
|
+
],
|
|
194
|
+
payments: [
|
|
195
|
+
{
|
|
196
|
+
payment_type_id: 'payment-type-uuid',
|
|
197
|
+
money_amount: 20.00
|
|
198
|
+
}
|
|
199
|
+
]
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
# Create a refund
|
|
203
|
+
refund = client.create_refund(
|
|
204
|
+
'12345',
|
|
205
|
+
refund_date: Time.now,
|
|
206
|
+
line_items: [...],
|
|
207
|
+
payments: [...]
|
|
208
|
+
)
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
</details>
|
|
212
|
+
|
|
213
|
+
### Customers
|
|
214
|
+
|
|
215
|
+
<details>
|
|
216
|
+
<summary>Click to see Customers examples</summary>
|
|
217
|
+
|
|
218
|
+
```ruby
|
|
219
|
+
# List customers
|
|
220
|
+
customers = client.list_customers
|
|
221
|
+
|
|
222
|
+
# Filter by email
|
|
223
|
+
customer = client.list_customers(email: 'customer@example.com')
|
|
224
|
+
|
|
225
|
+
# Filter by phone
|
|
226
|
+
customer = client.list_customers(phone_number: '+1234567890')
|
|
227
|
+
|
|
228
|
+
# Get a specific customer
|
|
229
|
+
customer = client.get_customer('customer-uuid')
|
|
230
|
+
|
|
231
|
+
# Create a customer
|
|
232
|
+
new_customer = client.create_customer(
|
|
233
|
+
name: 'John Doe',
|
|
234
|
+
email: 'john@example.com',
|
|
235
|
+
phone_number: '+1234567890',
|
|
236
|
+
address: '123 Main St',
|
|
237
|
+
city: 'New York',
|
|
238
|
+
postal_code: '10001'
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
# Update a customer
|
|
242
|
+
client.update_customer(
|
|
243
|
+
'customer-uuid',
|
|
244
|
+
name: 'Jane Doe',
|
|
245
|
+
email: 'jane@example.com'
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
# Delete a customer
|
|
249
|
+
client.delete_customer('customer-uuid')
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
</details>
|
|
253
|
+
|
|
254
|
+
### Discounts
|
|
255
|
+
|
|
256
|
+
<details>
|
|
257
|
+
<summary>Click to see Discounts examples</summary>
|
|
258
|
+
|
|
259
|
+
```ruby
|
|
260
|
+
# List discounts
|
|
261
|
+
discounts = client.list_discounts
|
|
262
|
+
|
|
263
|
+
# Get a specific discount
|
|
264
|
+
discount = client.get_discount('discount-uuid')
|
|
265
|
+
|
|
266
|
+
# Create a percentage discount
|
|
267
|
+
percentage_discount = client.create_discount(
|
|
268
|
+
name: '10% Off',
|
|
269
|
+
type: LoyverseApi::Endpoints::Discounts::TYPE_FIXED_PERCENT,
|
|
270
|
+
discount_amount: 10.0
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
# Create a fixed amount discount
|
|
274
|
+
fixed_discount = client.create_discount(
|
|
275
|
+
name: '$5 Off',
|
|
276
|
+
type: LoyverseApi::Endpoints::Discounts::TYPE_FIXED_AMOUNT,
|
|
277
|
+
discount_amount: 5.0,
|
|
278
|
+
applies_to: LoyverseApi::Endpoints::Discounts::APPLIES_TO_RECEIPT
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
# Update a discount
|
|
282
|
+
client.update_discount(
|
|
283
|
+
'discount-uuid',
|
|
284
|
+
name: '15% Off',
|
|
285
|
+
discount_amount: 15.0
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
# Delete a discount
|
|
289
|
+
client.delete_discount('discount-uuid')
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
</details>
|
|
293
|
+
|
|
294
|
+
### Employees
|
|
295
|
+
|
|
296
|
+
<details>
|
|
297
|
+
<summary>Click to see Employees examples</summary>
|
|
298
|
+
|
|
299
|
+
```ruby
|
|
300
|
+
# List employees
|
|
301
|
+
employees = client.list_employees
|
|
302
|
+
|
|
303
|
+
# Get a specific employee
|
|
304
|
+
employee = client.get_employee('employee-uuid')
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
**Note:** Employees can only be read via the API. Create, update, and delete operations must be done through the Loyverse Back Office.
|
|
308
|
+
|
|
309
|
+
</details>
|
|
310
|
+
|
|
311
|
+
### Modifiers
|
|
312
|
+
|
|
313
|
+
<details>
|
|
314
|
+
<summary>Click to see Modifiers examples</summary>
|
|
315
|
+
|
|
316
|
+
```ruby
|
|
317
|
+
# List modifiers
|
|
318
|
+
modifiers = client.list_modifiers
|
|
319
|
+
|
|
320
|
+
# Get a specific modifier
|
|
321
|
+
modifier = client.get_modifier('modifier-uuid')
|
|
322
|
+
|
|
323
|
+
# Create a modifier with options
|
|
324
|
+
new_modifier = client.create_modifier(
|
|
325
|
+
name: 'Size',
|
|
326
|
+
options: [
|
|
327
|
+
{ name: 'Small', price: 0 },
|
|
328
|
+
{ name: 'Medium', price: 1.0 },
|
|
329
|
+
{ name: 'Large', price: 2.0 }
|
|
330
|
+
]
|
|
331
|
+
)
|
|
332
|
+
|
|
333
|
+
# Delete a modifier
|
|
334
|
+
client.delete_modifier('modifier-uuid')
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
</details>
|
|
338
|
+
|
|
339
|
+
### Webhooks
|
|
340
|
+
|
|
341
|
+
Webhooks allow you to receive real-time notifications when events occur in your Loyverse account.
|
|
342
|
+
|
|
343
|
+
**Setting up a webhook:**
|
|
344
|
+
|
|
345
|
+
1. **Create the webhook** pointing to your server endpoint:
|
|
346
|
+
```ruby
|
|
347
|
+
webhook = client.create_webhook(
|
|
348
|
+
url: 'https://your-server.com/webhooks/loyverse',
|
|
349
|
+
event_types: ['ORDER_CREATED', 'ITEM_UPDATED', 'INVENTORY_UPDATED'],
|
|
350
|
+
description: 'Production webhook'
|
|
351
|
+
)
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
2. **Handle webhook requests** in your application (Rails example):
|
|
355
|
+
```ruby
|
|
356
|
+
# POST /webhooks/loyverse
|
|
357
|
+
def create
|
|
358
|
+
payload = request.raw_post
|
|
359
|
+
signature = request.headers['X-Loyverse-Signature']
|
|
360
|
+
|
|
361
|
+
# Verify signature
|
|
362
|
+
unless client.verify_webhook_signature(payload, signature, ENV['LOYVERSE_WEBHOOK_SECRET'])
|
|
363
|
+
return head :unauthorized
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
# Process the webhook
|
|
367
|
+
data = JSON.parse(payload)
|
|
368
|
+
case data['event_type']
|
|
369
|
+
when 'ORDER_CREATED'
|
|
370
|
+
# Handle new order
|
|
371
|
+
when 'ITEM_UPDATED'
|
|
372
|
+
# Handle item update
|
|
373
|
+
when 'INVENTORY_UPDATED'
|
|
374
|
+
# Handle inventory update
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
head :ok
|
|
378
|
+
end
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
**Available event types:**
|
|
382
|
+
- `ORDER_CREATED` - New receipts/sales
|
|
383
|
+
- `ITEM_UPDATED` - Product changes
|
|
384
|
+
- `INVENTORY_UPDATED` - Stock level changes
|
|
385
|
+
|
|
386
|
+
📖 **Full webhook documentation:** [Loyverse Webhooks Overview](https://developer.loyverse.com/docs/#section/Webhooks-overview/Adding-webhook)
|
|
387
|
+
|
|
388
|
+
<details>
|
|
389
|
+
<summary>Click to see more webhook management examples</summary>
|
|
390
|
+
|
|
391
|
+
```ruby
|
|
392
|
+
# List webhooks
|
|
393
|
+
webhooks = client.list_webhooks
|
|
394
|
+
|
|
395
|
+
# Get a specific webhook
|
|
396
|
+
webhook = client.get_webhook('webhook-uuid')
|
|
397
|
+
|
|
398
|
+
# Delete a webhook
|
|
399
|
+
client.delete_webhook('webhook-uuid')
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
</details>
|
|
403
|
+
|
|
404
|
+
### Pagination
|
|
405
|
+
|
|
406
|
+
```ruby
|
|
407
|
+
# Get first page
|
|
408
|
+
page = client.list_items(limit: 100)
|
|
409
|
+
|
|
410
|
+
# Get next page using cursor from response
|
|
411
|
+
next_page = client.list_items(limit: 100, cursor: page['cursor'])
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
### Error Handling
|
|
415
|
+
|
|
416
|
+
The gem provides specific exception classes for different error types:
|
|
417
|
+
|
|
418
|
+
```ruby
|
|
419
|
+
begin
|
|
420
|
+
item = client.get_item('invalid-uuid')
|
|
421
|
+
rescue LoyverseApi::NotFoundError => e
|
|
422
|
+
puts "Item not found: #{e.message}"
|
|
423
|
+
rescue LoyverseApi::AuthenticationError => e
|
|
424
|
+
puts "Authentication failed: #{e.message}"
|
|
425
|
+
rescue LoyverseApi::RateLimitError => e
|
|
426
|
+
puts "Rate limit exceeded: #{e.message}"
|
|
427
|
+
rescue LoyverseApi::BadRequestError => e
|
|
428
|
+
puts "Bad request: #{e.message}"
|
|
429
|
+
puts "Error code: #{e.code}"
|
|
430
|
+
puts "Error details: #{e.details}"
|
|
431
|
+
rescue LoyverseApi::Error => e
|
|
432
|
+
puts "API error: #{e.message}"
|
|
433
|
+
end
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
### Date and Time Handling
|
|
437
|
+
|
|
438
|
+
All dates in the Loyverse API use ISO 8601 format. The gem automatically handles Time objects:
|
|
439
|
+
|
|
440
|
+
```ruby
|
|
441
|
+
# Using Time objects (recommended)
|
|
442
|
+
items = client.items.list(
|
|
443
|
+
updated_at_min: Time.now - (7 * 24 * 60 * 60), # 7 days ago
|
|
444
|
+
updated_at_max: Time.now
|
|
445
|
+
)
|
|
446
|
+
|
|
447
|
+
# Using ISO 8601 strings
|
|
448
|
+
items = client.items.list(
|
|
449
|
+
updated_at_min: '2024-01-15T00:00:00Z',
|
|
450
|
+
updated_at_max: '2024-01-22T23:59:59Z'
|
|
451
|
+
)
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
## Configuration Options
|
|
455
|
+
|
|
456
|
+
```ruby
|
|
457
|
+
LoyverseApi.configure do |config|
|
|
458
|
+
# Required: Your Personal Access Token
|
|
459
|
+
config.access_token = 'your_token'
|
|
460
|
+
|
|
461
|
+
# Optional: API base URL (default: 'https://api.loyverse.com')
|
|
462
|
+
config.api_base_url = 'https://api.loyverse.com'
|
|
463
|
+
|
|
464
|
+
# Optional: API version (default: 'v1.0')
|
|
465
|
+
config.api_version = 'v1.0'
|
|
466
|
+
|
|
467
|
+
# Optional: Request timeout in seconds (default: 30)
|
|
468
|
+
config.timeout = 30
|
|
469
|
+
|
|
470
|
+
# Optional: Connection open timeout in seconds (default: 10)
|
|
471
|
+
config.open_timeout = 10
|
|
472
|
+
end
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
## Rate Limiting
|
|
476
|
+
|
|
477
|
+
The Loyverse API has the following rate limits:
|
|
478
|
+
|
|
479
|
+
- **Standard**: 60 requests per minute
|
|
480
|
+
- **Alternative**: 300 requests per 300 seconds
|
|
481
|
+
|
|
482
|
+
The gem automatically handles rate limiting with:
|
|
483
|
+
|
|
484
|
+
- Automatic retry with exponential backoff
|
|
485
|
+
- Maximum 3 retry attempts
|
|
486
|
+
- Retries for 429, 500, 502, 503, 504 status codes
|
|
487
|
+
|
|
488
|
+
## Available Event Types for Webhooks
|
|
489
|
+
|
|
490
|
+
- `ORDER_CREATED` - New receipts/sales
|
|
491
|
+
- `ITEM_UPDATED` - Product changes
|
|
492
|
+
- `INVENTORY_UPDATED` - Stock level changes
|
|
493
|
+
|
|
494
|
+
## Development
|
|
495
|
+
|
|
496
|
+
After checking out the repo, run `bundle install` to install dependencies. Then, run `rake spec` to run the tests.
|
|
497
|
+
|
|
498
|
+
## Contributing
|
|
499
|
+
|
|
500
|
+
Bug reports and pull requests are welcome on GitHub.
|
|
501
|
+
|
|
502
|
+
## License
|
|
503
|
+
|
|
504
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
|
505
|
+
|
|
506
|
+
## Resources
|
|
507
|
+
|
|
508
|
+
- [Loyverse API Documentation](https://developer.loyverse.com/docs/)
|
|
509
|
+
- [Loyverse Developer Portal](https://developer.loyverse.com)
|
|
510
|
+
- [Loyverse Back Office](https://r.loyverse.com/dashboard)
|
|
511
|
+
|
|
512
|
+
## Support
|
|
513
|
+
|
|
514
|
+
For issues related to the gem, please open an issue on GitHub.
|
|
515
|
+
|
|
516
|
+
For Loyverse API support, please contact [Loyverse Support](https://loyverse.com/support).
|