listo-delivery 0.1.1

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.
Files changed (77) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +152 -0
  4. data/lib/listo_delivery/client.rb +170 -0
  5. data/lib/listo_delivery/errors.rb +53 -0
  6. data/lib/listo_delivery/generated/api_version.rb +12 -0
  7. data/lib/listo_delivery/generated/client_operations.rb +82 -0
  8. data/lib/listo_delivery/generated/loader.rb +69 -0
  9. data/lib/listo_delivery/generated/models/balance.rb +48 -0
  10. data/lib/listo_delivery/generated/models/cancel_delivery_request.rb +29 -0
  11. data/lib/listo_delivery/generated/models/card_onboarding_link.rb +21 -0
  12. data/lib/listo_delivery/generated/models/card_status.rb +22 -0
  13. data/lib/listo_delivery/generated/models/connect_request.rb +28 -0
  14. data/lib/listo_delivery/generated/models/courier_ping.rb +58 -0
  15. data/lib/listo_delivery/generated/models/create_connect_request_request.rb +35 -0
  16. data/lib/listo_delivery/generated/models/create_connection_request.rb +21 -0
  17. data/lib/listo_delivery/generated/models/create_delivery_request.rb +189 -0
  18. data/lib/listo_delivery/generated/models/create_quote_request.rb +111 -0
  19. data/lib/listo_delivery/generated/models/create_store_owner_request.rb +26 -0
  20. data/lib/listo_delivery/generated/models/create_store_request.rb +104 -0
  21. data/lib/listo_delivery/generated/models/create_withdrawal_request.rb +29 -0
  22. data/lib/listo_delivery/generated/models/delivery.rb +879 -0
  23. data/lib/listo_delivery/generated/models/delivery_courier_location_event.rb +23 -0
  24. data/lib/listo_delivery/generated/models/delivery_list.rb +34 -0
  25. data/lib/listo_delivery/generated/models/delivery_message_skipped.rb +37 -0
  26. data/lib/listo_delivery/generated/models/delivery_message_skipped_event.rb +23 -0
  27. data/lib/listo_delivery/generated/models/delivery_status_changed_event.rb +23 -0
  28. data/lib/listo_delivery/generated/models/delivery_updated_event.rb +23 -0
  29. data/lib/listo_delivery/generated/models/error.rb +56 -0
  30. data/lib/listo_delivery/generated/models/error_response.rb +20 -0
  31. data/lib/listo_delivery/generated/models/event_list.rb +34 -0
  32. data/lib/listo_delivery/generated/models/ledger_entry.rb +62 -0
  33. data/lib/listo_delivery/generated/models/ledger_entry_list.rb +34 -0
  34. data/lib/listo_delivery/generated/models/manifest.rb +20 -0
  35. data/lib/listo_delivery/generated/models/manifest_item.rb +36 -0
  36. data/lib/listo_delivery/generated/models/owner_invitation.rb +27 -0
  37. data/lib/listo_delivery/generated/models/ping.rb +56 -0
  38. data/lib/listo_delivery/generated/models/quote.rb +99 -0
  39. data/lib/listo_delivery/generated/models/refund_delivery_request.rb +28 -0
  40. data/lib/listo_delivery/generated/models/request_log.rb +91 -0
  41. data/lib/listo_delivery/generated/models/request_log_detail.rb +105 -0
  42. data/lib/listo_delivery/generated/models/request_log_list.rb +34 -0
  43. data/lib/listo_delivery/generated/models/reschedule_delivery_request.rb +41 -0
  44. data/lib/listo_delivery/generated/models/same_day_terms.rb +106 -0
  45. data/lib/listo_delivery/generated/models/send_test_webhook_request.rb +22 -0
  46. data/lib/listo_delivery/generated/models/store.rb +235 -0
  47. data/lib/listo_delivery/generated/models/store_balance.rb +48 -0
  48. data/lib/listo_delivery/generated/models/store_connected_event.rb +23 -0
  49. data/lib/listo_delivery/generated/models/store_list.rb +34 -0
  50. data/lib/listo_delivery/generated/models/store_updated_event.rb +23 -0
  51. data/lib/listo_delivery/generated/models/update_store_request.rb +94 -0
  52. data/lib/listo_delivery/generated/models/webhook_delivery.rb +99 -0
  53. data/lib/listo_delivery/generated/models/webhook_delivery_list.rb +34 -0
  54. data/lib/listo_delivery/generated/models/webhook_event.rb +69 -0
  55. data/lib/listo_delivery/generated/models/webhook_event_envelope.rb +35 -0
  56. data/lib/listo_delivery/generated/models/withdrawal.rb +91 -0
  57. data/lib/listo_delivery/generated/models/withdrawal_list.rb +34 -0
  58. data/lib/listo_delivery/generated/models/withdrawal_updated_event.rb +23 -0
  59. data/lib/listo_delivery/generated/resources/balance.rb +43 -0
  60. data/lib/listo_delivery/generated/resources/card_onboarding.rb +70 -0
  61. data/lib/listo_delivery/generated/resources/connect_requests.rb +31 -0
  62. data/lib/listo_delivery/generated/resources/connections.rb +31 -0
  63. data/lib/listo_delivery/generated/resources/deliveries.rb +128 -0
  64. data/lib/listo_delivery/generated/resources/events.rb +59 -0
  65. data/lib/listo_delivery/generated/resources/ledger.rb +47 -0
  66. data/lib/listo_delivery/generated/resources/quotes.rb +31 -0
  67. data/lib/listo_delivery/generated/resources/request_logs.rb +45 -0
  68. data/lib/listo_delivery/generated/resources/stores.rb +143 -0
  69. data/lib/listo_delivery/generated/resources/webhooks.rb +46 -0
  70. data/lib/listo_delivery/generated/resources/withdrawals.rb +60 -0
  71. data/lib/listo_delivery/model.rb +69 -0
  72. data/lib/listo_delivery/util.rb +76 -0
  73. data/lib/listo_delivery/version.rb +7 -0
  74. data/lib/listo_delivery/webhooks.rb +98 -0
  75. data/lib/listo_delivery.rb +16 -0
  76. data/listo_delivery.gemspec +27 -0
  77. metadata +120 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 4550bd5dde54839887c33c6e4b6d3503f76511ff792fbe42a3892b3cfc8f4023
4
+ data.tar.gz: b03b099ec41ea855d5f64a65a43a61c72f75c6cd8c0941dcd84ed14016870e8e
5
+ SHA512:
6
+ metadata.gz: 3fb3e87d92ffe548aae67303864a604ab4f3b998bbcd1e83d0c3a1622d02757273c59c3c57d90d0caa702e438536b3d29dd3e5d8c3f0cdbfce397711bee02779
7
+ data.tar.gz: c805469a01fcb20b242b100aceee19d3a5f662eeac069ba1836583172b1ef9a4ec7c4ecac629c23731363fc10e1ab1515b3b75d336c7daecfa69e0419a1e7f85
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Cheto Labs, S.A.P.I. de C.V.
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,152 @@
1
+ # listo-delivery (Ruby)
2
+
3
+ The official Ruby client for the Listo Delivery API. Standard library only
4
+ (`net/http`, `json`, `openssl`, `securerandom`), Ruby 3.1 or newer.
5
+
6
+ ## Install
7
+
8
+ ```sh
9
+ gem install listo-delivery
10
+ ```
11
+
12
+ ## Quickstart
13
+
14
+ ```ruby
15
+ require "listo_delivery"
16
+
17
+ client = ListoDelivery::Client.new(api_key: ENV.fetch("LISTO_API_KEY")) # lst_test_... or lst_live_...
18
+ client.mode # => "test"
19
+
20
+ store = "st_4bR8kM2wQ7xT1nV5cZ9pLdYe"
21
+ quote = client.quotes.create(
22
+ store_id: store,
23
+ dropoff: {street: "Blvd. Puerta de Hierro 4965, Zapopan, Jalisco 45116"},
24
+ payment_method: "cash",
25
+ order_value_cents: 19_600
26
+ )
27
+ puts quote.fee_cents
28
+
29
+ delivery = client.deliveries.create(
30
+ store_id: store,
31
+ quote_id: quote.id,
32
+ external_id: "order-1042",
33
+ payment_method: "cash",
34
+ order_value_cents: 19_600,
35
+ dropoff: {name: "Ana", phone: "+523312345678", street: "Blvd. Puerta de Hierro 4965, Zapopan, Jalisco 45116"},
36
+ idempotency_key: "order-1042" # your own order id makes a retry safe
37
+ )
38
+ puts delivery.id, delivery.status
39
+ ```
40
+
41
+ The request fields are the API's wire names (`store_id`, `order_value_cents`).
42
+ Pass them as keywords, as one Hash (`create({"store_id" => "..."})`), or both.
43
+ Responses are model objects with a reader per documented field, `#to_h` and
44
+ `#[]` by wire name; a field the API adds later is kept in `#to_h`, never a
45
+ parsing error.
46
+
47
+ Path parameters are positional: `client.deliveries.cancel(delivery_id, reason: "customer_canceled")`.
48
+ Reads take their filters the same way: `client.deliveries.list(status: "pending")`.
49
+ Every operation of the API is a method, named after it in snake_case
50
+ (`deliveries.retrieve`, `stores.cancel_plan`, `ledger.list_for_store`, ...;
51
+ `client.ping` lives on the client itself); the API reference at
52
+ [docs.listo.delivery](https://docs.listo.delivery) lists them all.
53
+
54
+ ## Verify a webhook
55
+
56
+ Verification needs the secret, not an API key, so it is also a plain module.
57
+ Pass the body exactly as received (never re-serialized JSON):
58
+
59
+ ```ruby
60
+ begin
61
+ event = ListoDelivery::Webhooks.construct_event(
62
+ request.body.read, request.headers["X-Listo-Signature"], ENV.fetch("LISTO_WEBHOOK_SECRET")
63
+ )
64
+ rescue ListoDelivery::Error
65
+ head 400 # invalid_signature or invalid_payload: do not act on it
66
+ else
67
+ case event
68
+ when ListoDelivery::Models::DeliveryStatusChangedEvent then event.data.status
69
+ end
70
+ end
71
+ ```
72
+
73
+ `construct_event` raises `ListoDelivery::SignatureError` when the signature
74
+ does not verify, and `ListoDelivery::Error` with code `invalid_payload` when the
75
+ signed body is not a JSON object; both are `ListoDelivery::Error`, so a receiver
76
+ that answers 400 rescues `ListoDelivery::Error`. `ListoDelivery::Webhooks.verify(raw_body, signature_header, secrets)`
77
+ returns true or false and never raises. `secrets` is one string or a list (two
78
+ during a rotation); `tolerance:` (default 300 seconds, in both directions) and
79
+ `now:` (unix seconds) are keywords. `client.webhooks.verify` and
80
+ `client.webhooks.construct_event` are the same functions. An event whose
81
+ `type` this SDK does not know comes back as a plain `Models::WebhookEvent`
82
+ (`id`, `type`, `created_at`, and `data` as the raw Hash), never an error.
83
+
84
+ ## Errors
85
+
86
+ Every non-2xx answer raises `ListoDelivery::Error` with `code` (branch on this),
87
+ `message`, `param`, `retryable`, `status`, `request_id`, `doc_url` and the
88
+ parsed `body`. A body that is not the API's error envelope (a proxy's HTML
89
+ page) raises the same class with `code` `"http_<status>"`. A request that got
90
+ no answer (DNS, refused, timeout) raises `ListoDelivery::ConnectionError`
91
+ (`code` `"connection_error"`, `status` nil, `retryable` false: a write may
92
+ have happened, so you decide). The API key is never put in an error message.
93
+
94
+ ```ruby
95
+ begin
96
+ client.deliveries.retrieve("dlv_missing")
97
+ rescue ListoDelivery::Error => e
98
+ warn "#{e.code} (#{e.status}) request #{e.request_id}"
99
+ end
100
+ ```
101
+
102
+ ## Idempotency
103
+
104
+ `deliveries.create`, `deliveries.refund`, `stores.create`, `stores.reactivate_plan`
105
+ and `stores.cancel_plan` (the operations whose schema declares the
106
+ `Idempotency-Key` header) accept `idempotency_key:`. Without one, a fresh UUID
107
+ is sent per call and reused only by that call's own retries. No other
108
+ operation sends the header, and passing `idempotency_key:` to one raises
109
+ `ArgumentError` before any request (a body field really named that goes inside
110
+ the Hash argument). An empty or blank key raises `ArgumentError` too.
111
+
112
+ ## Pagination
113
+
114
+ Lists return the page as the API has it: `data`, `has_more` and `cursor`. Pass
115
+ the cursor back to read the next page:
116
+
117
+ ```ruby
118
+ cursor = nil
119
+ loop do
120
+ page = client.deliveries.list(cursor: cursor)
121
+ page.data.each { |delivery| puts delivery.id }
122
+ break unless page.has_more
123
+
124
+ cursor = page.cursor
125
+ end
126
+ ```
127
+
128
+ ## Retries and timeouts
129
+
130
+ Nothing is retried by default. With `max_retries: n`, only a 429 is retried,
131
+ after its `Retry-After` (seconds or an HTTP date, one second when missing,
132
+ capped at 60), at most `n` times, with the same idempotency key. 5xx answers
133
+ and network failures are never retried for you. `timeout:` (seconds, default
134
+ 30) bounds connecting, writing and reading.
135
+
136
+ ```ruby
137
+ ListoDelivery::Client.new(api_key: key, max_retries: 2, timeout: 10, base_url: "https://api.listo.delivery")
138
+ ```
139
+
140
+ ## Differences from the other SDKs
141
+
142
+ Ruby spells operations in snake_case, takes
143
+ request fields as keywords or one Hash, and has no top-level `Listo`
144
+ constant (it could clash with an application's own); the client is
145
+ `ListoDelivery::Client`.
146
+
147
+ ## About this repository
148
+
149
+ This code is generated from Listo's API definition. Issues and questions are
150
+ welcome in this repository. Changes are made upstream by Listo and released
151
+ here, so a pull request cannot be merged as it stands: open an issue and the
152
+ change is made at the source.
@@ -0,0 +1,170 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+ require "net/http"
5
+ require "openssl"
6
+ require "securerandom"
7
+ require "time"
8
+ require "uri"
9
+
10
+ module ListoDelivery
11
+ # The entry point: one Client per API key.
12
+ #
13
+ # client = ListoDelivery::Client.new(api_key: ENV.fetch("LISTO_API_KEY"))
14
+ # client.deliveries.retrieve("dlv_...")
15
+ #
16
+ # Resources (`deliveries`, `stores`, ...) and the root `ping` come from
17
+ # ClientOperations (generated); `client.webhooks` carries both the webhook
18
+ # operations and the signature helpers (`verify`, `construct_event`).
19
+ class Client
20
+ include ClientOperations
21
+
22
+ KEY_PREFIXES = {"lst_live_" => "live", "lst_test_" => "test"}.freeze
23
+ MAX_RETRY_WAIT = 60
24
+ DEFAULT_RETRY_WAIT = 1
25
+ # Transport failures that mean "no answer arrived".
26
+ NETWORK_ERRORS = [
27
+ SocketError, SystemCallError, IOError, Timeout::Error, OpenSSL::SSL::SSLError,
28
+ Net::HTTPBadResponse, Net::ProtocolError
29
+ ].freeze
30
+
31
+ # @return [String] "live" or "test", read from the key's prefix
32
+ attr_reader :mode
33
+ attr_reader :base_url, :max_retries, :timeout
34
+
35
+ # @param api_key [String] a `lst_live_` or `lst_test_` key
36
+ # @param base_url [String, nil] defaults to the schema's server
37
+ # @param max_retries [Integer] how many times a 429 is retried (0 = never)
38
+ # @param timeout [Numeric] seconds for connecting, writing and reading
39
+ def initialize(api_key:, base_url: nil, max_retries: 0, timeout: 30)
40
+ @mode = KEY_PREFIXES.find { |prefix, _| api_key.is_a?(String) && api_key.start_with?(prefix) }&.last
41
+ raise ArgumentError, "api_key must start with lst_live_ or lst_test_" unless @mode
42
+ raise ArgumentError, "max_retries must be a non-negative Integer" unless max_retries.is_a?(Integer) && max_retries >= 0
43
+ raise ArgumentError, "timeout must be a positive number" unless timeout.is_a?(Numeric) && timeout.positive?
44
+
45
+ @api_key = api_key
46
+ @base_url = (base_url || DEFAULT_BASE_URL).to_s.chomp("/")
47
+ raise ArgumentError, "base_url must be an http(s) URL" unless URI.parse(@base_url).is_a?(URI::HTTP)
48
+
49
+ @max_retries = max_retries
50
+ @timeout = timeout
51
+ end
52
+
53
+ # The key never shows up in logs or exception output.
54
+ def inspect
55
+ "#<#{self.class.name} mode=#{mode.inspect} base_url=#{base_url.inspect}>"
56
+ end
57
+
58
+ # Runs one operation. The generated resource methods call this; it is
59
+ # not meant for direct use.
60
+ # @api private
61
+ def execute(http_method, path, query: nil, body: nil, idempotent: false, idempotency_key: nil, model: nil)
62
+ check_idempotency_key(idempotency_key)
63
+ uri = URI.parse("#{base_url}#{path}")
64
+ uri.query = Util.encode_query(query) if query && !query.empty?
65
+ payload = body.nil? ? nil : JSON.generate(body)
66
+ headers = request_headers(payload, idempotent ? (idempotency_key || SecureRandom.uuid) : nil)
67
+
68
+ attempts = 0
69
+ loop do
70
+ response = perform(http_method, uri, headers, payload)
71
+ if response.code.to_i == 429 && attempts < max_retries
72
+ attempts += 1
73
+ sleep(retry_delay(response))
74
+ next
75
+ end
76
+ return handle(response, model)
77
+ end
78
+ end
79
+
80
+ private
81
+
82
+ # nil means "mint one"; a key that is present must be a real one, since
83
+ # an empty header would defeat the retry protection it stands for.
84
+ def check_idempotency_key(key)
85
+ return if key.nil?
86
+ return if key.is_a?(String) && !key.strip.empty?
87
+
88
+ raise ArgumentError, "idempotency_key must be a non-blank String"
89
+ end
90
+
91
+ def request_headers(payload, idempotency_key)
92
+ agent = "listo-ruby/#{VERSION} api/#{API_VERSION}"
93
+ headers = {
94
+ "Authorization" => "Bearer #{@api_key}",
95
+ "Accept" => "application/json",
96
+ "User-Agent" => agent,
97
+ "X-Listo-Client" => agent
98
+ }
99
+ headers["Content-Type"] = "application/json" if payload
100
+ headers["Idempotency-Key"] = idempotency_key if idempotency_key
101
+ headers
102
+ end
103
+
104
+ def perform(http_method, uri, headers, payload)
105
+ http = Net::HTTP.new(uri.host, uri.port)
106
+ http.use_ssl = uri.scheme == "https"
107
+ http.open_timeout = http.read_timeout = http.write_timeout = timeout
108
+ has_body = !payload.nil? || %w[POST PUT PATCH].include?(http_method)
109
+ request = Net::HTTPGenericRequest.new(http_method, has_body, true, uri.request_uri, headers)
110
+ # An empty body still sends Content-Length: 0, which a POST needs.
111
+ request.body = payload || "" if has_body
112
+ http.start { |conn| conn.request(request) }
113
+ rescue *NETWORK_ERRORS => e
114
+ raise ConnectionError, "Could not reach the Listo API (#{e.class}: #{e.message})"
115
+ end
116
+
117
+ # Retry-After is whole seconds or an HTTP date; anything else waits a second.
118
+ def retry_delay(response)
119
+ value = response["retry-after"].to_s.strip
120
+ seconds =
121
+ if value.match?(/\A\d+\z/)
122
+ value.to_i
123
+ else
124
+ begin
125
+ Time.httpdate(value) - Time.now
126
+ rescue ArgumentError
127
+ DEFAULT_RETRY_WAIT
128
+ end
129
+ end
130
+ seconds.clamp(0, MAX_RETRY_WAIT)
131
+ end
132
+
133
+ def handle(response, model)
134
+ status = response.code.to_i
135
+ text = response.body.to_s
136
+ parsed = parse(text)
137
+ raise api_error(response, status, text, parsed) unless status.between?(200, 299)
138
+ return nil if status == 204 || text.strip.empty?
139
+ raise api_error(response, status, text, parsed) if parsed == :invalid
140
+
141
+ model ? model.build(parsed) : parsed
142
+ end
143
+
144
+ def parse(text)
145
+ return nil if text.strip.empty?
146
+
147
+ JSON.parse(text)
148
+ rescue JSON::ParserError
149
+ :invalid
150
+ end
151
+
152
+ def api_error(response, status, text, parsed)
153
+ header_id = response["x-request-id"]
154
+ envelope = parsed.is_a?(Hash) ? parsed["error"] : nil
155
+ if envelope.is_a?(Hash) && envelope["code"].is_a?(String)
156
+ return Error.new(
157
+ envelope["message"].to_s, code: envelope["code"], param: envelope["param"],
158
+ retryable: envelope["retryable"], status: status, request_id: envelope["request_id"] || header_id,
159
+ doc_url: envelope["doc_url"], body: parsed
160
+ )
161
+ end
162
+
163
+ Error.new(
164
+ "Unexpected response with status #{status}",
165
+ code: "http_#{status}", retryable: [429, 502, 503, 504].include?(status), status: status,
166
+ request_id: header_id, body: (parsed == :invalid || parsed.nil?) ? text : parsed
167
+ )
168
+ end
169
+ end
170
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ListoDelivery
4
+ # Raised for every non-2xx answer. The fields come from the API's `error`
5
+ # envelope; a body that is not that envelope (a proxy's HTML page, other
6
+ # JSON) still raises this class, with `code` "http_<status>".
7
+ class Error < StandardError
8
+ # @return [String, nil] the stable code to branch on, never `message`
9
+ attr_reader :code
10
+ # @return [String, nil] the request field the error is about
11
+ attr_reader :param
12
+ # @return [Boolean, nil] whether the same call may be repeated
13
+ attr_reader :retryable
14
+ # @return [Integer, nil] the HTTP status; nil when no answer arrived
15
+ attr_reader :status
16
+ # @return [String, nil] quote this when asking for support
17
+ attr_reader :request_id
18
+ # @return [String, nil] the docs page for `code`
19
+ attr_reader :doc_url
20
+ # @return [Object, nil] the parsed response body, or the raw text when it is not JSON
21
+ attr_reader :body
22
+
23
+ def initialize(message = nil, code: nil, param: nil, retryable: nil, status: nil, request_id: nil, doc_url: nil, body: nil)
24
+ super(message)
25
+ @code = code
26
+ @param = param
27
+ @retryable = retryable
28
+ @status = status
29
+ @request_id = request_id
30
+ @doc_url = doc_url
31
+ @body = body
32
+ end
33
+
34
+ def retryable?
35
+ retryable == true
36
+ end
37
+ end
38
+
39
+ # The request never got an answer (DNS, refused, timeout). A write may or
40
+ # may not have happened, so this is never retried for you.
41
+ class ConnectionError < Error
42
+ def initialize(message = nil, **rest)
43
+ super(message, code: "connection_error", retryable: false, **rest)
44
+ end
45
+ end
46
+
47
+ # A webhook whose signature does not verify (see Webhooks.construct_event).
48
+ class SignatureError < Error
49
+ def initialize(message = "The webhook signature does not match.", **rest)
50
+ super(message, code: "invalid_signature", retryable: false, **rest)
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ # GENERATED from Listo's API definition (API 1.37.0). Do not edit by hand:
4
+ # this file is rewritten whenever the SDK is regenerated.
5
+
6
+ module ListoDelivery
7
+ # The API release this SDK was generated from (the schema's info.version).
8
+ API_VERSION = "1.37.0"
9
+
10
+ # The schema's first server.
11
+ DEFAULT_BASE_URL = "https://api.listo.delivery"
12
+ end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ # GENERATED from Listo's API definition (API 1.37.0). Do not edit by hand:
4
+ # this file is rewritten whenever the SDK is regenerated.
5
+
6
+ module ListoDelivery
7
+ # The resource readers and the root operations of Client, from Listo's API definition.
8
+ module ClientOperations
9
+ # @return [Resources::Balance]
10
+ def balance
11
+ @balance ||= Resources::Balance.new(self)
12
+ end
13
+
14
+ # @return [Resources::CardOnboarding]
15
+ def card_onboarding
16
+ @card_onboarding ||= Resources::CardOnboarding.new(self)
17
+ end
18
+
19
+ # @return [Resources::ConnectRequests]
20
+ def connect_requests
21
+ @connect_requests ||= Resources::ConnectRequests.new(self)
22
+ end
23
+
24
+ # @return [Resources::Connections]
25
+ def connections
26
+ @connections ||= Resources::Connections.new(self)
27
+ end
28
+
29
+ # @return [Resources::Deliveries]
30
+ def deliveries
31
+ @deliveries ||= Resources::Deliveries.new(self)
32
+ end
33
+
34
+ # @return [Resources::Events]
35
+ def events
36
+ @events ||= Resources::Events.new(self)
37
+ end
38
+
39
+ # @return [Resources::Ledger]
40
+ def ledger
41
+ @ledger ||= Resources::Ledger.new(self)
42
+ end
43
+
44
+ # @return [Resources::Quotes]
45
+ def quotes
46
+ @quotes ||= Resources::Quotes.new(self)
47
+ end
48
+
49
+ # @return [Resources::RequestLogs]
50
+ def request_logs
51
+ @request_logs ||= Resources::RequestLogs.new(self)
52
+ end
53
+
54
+ # @return [Resources::Stores]
55
+ def stores
56
+ @stores ||= Resources::Stores.new(self)
57
+ end
58
+
59
+ # @return [Resources::Webhooks]
60
+ def webhooks
61
+ @webhooks ||= Resources::Webhooks.new(self)
62
+ end
63
+
64
+ # @return [Resources::Withdrawals]
65
+ def withdrawals
66
+ @withdrawals ||= Resources::Withdrawals.new(self)
67
+ end
68
+
69
+ # Check that your API key works.
70
+ #
71
+ # GET /v1/ping
72
+ # @return [Models::Ping]
73
+ # @raise [ListoDelivery::Error]
74
+ def ping
75
+ execute(
76
+ "GET",
77
+ "/v1/ping",
78
+ model: Models::Ping
79
+ )
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ # GENERATED from Listo's API definition (API 1.37.0). Do not edit by hand:
4
+ # this file is rewritten whenever the SDK is regenerated.
5
+
6
+ require_relative "api_version"
7
+ require_relative "models/webhook_event"
8
+ require_relative "models/balance"
9
+ require_relative "models/cancel_delivery_request"
10
+ require_relative "models/card_onboarding_link"
11
+ require_relative "models/card_status"
12
+ require_relative "models/connect_request"
13
+ require_relative "models/courier_ping"
14
+ require_relative "models/create_connect_request_request"
15
+ require_relative "models/create_connection_request"
16
+ require_relative "models/create_delivery_request"
17
+ require_relative "models/create_quote_request"
18
+ require_relative "models/create_store_owner_request"
19
+ require_relative "models/create_store_request"
20
+ require_relative "models/create_withdrawal_request"
21
+ require_relative "models/delivery"
22
+ require_relative "models/delivery_courier_location_event"
23
+ require_relative "models/delivery_list"
24
+ require_relative "models/delivery_message_skipped"
25
+ require_relative "models/delivery_message_skipped_event"
26
+ require_relative "models/delivery_status_changed_event"
27
+ require_relative "models/delivery_updated_event"
28
+ require_relative "models/error"
29
+ require_relative "models/error_response"
30
+ require_relative "models/event_list"
31
+ require_relative "models/ledger_entry"
32
+ require_relative "models/ledger_entry_list"
33
+ require_relative "models/manifest"
34
+ require_relative "models/manifest_item"
35
+ require_relative "models/owner_invitation"
36
+ require_relative "models/ping"
37
+ require_relative "models/quote"
38
+ require_relative "models/refund_delivery_request"
39
+ require_relative "models/request_log"
40
+ require_relative "models/request_log_detail"
41
+ require_relative "models/request_log_list"
42
+ require_relative "models/reschedule_delivery_request"
43
+ require_relative "models/same_day_terms"
44
+ require_relative "models/send_test_webhook_request"
45
+ require_relative "models/store"
46
+ require_relative "models/store_balance"
47
+ require_relative "models/store_connected_event"
48
+ require_relative "models/store_list"
49
+ require_relative "models/store_updated_event"
50
+ require_relative "models/update_store_request"
51
+ require_relative "models/webhook_delivery"
52
+ require_relative "models/webhook_delivery_list"
53
+ require_relative "models/webhook_event_envelope"
54
+ require_relative "models/withdrawal"
55
+ require_relative "models/withdrawal_list"
56
+ require_relative "models/withdrawal_updated_event"
57
+ require_relative "resources/balance"
58
+ require_relative "resources/card_onboarding"
59
+ require_relative "resources/connect_requests"
60
+ require_relative "resources/connections"
61
+ require_relative "resources/deliveries"
62
+ require_relative "resources/events"
63
+ require_relative "resources/ledger"
64
+ require_relative "resources/quotes"
65
+ require_relative "resources/request_logs"
66
+ require_relative "resources/stores"
67
+ require_relative "resources/webhooks"
68
+ require_relative "resources/withdrawals"
69
+ require_relative "client_operations"
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ # GENERATED from Listo's API definition (API 1.37.0). Do not edit by hand:
4
+ # this file is rewritten whenever the SDK is regenerated.
5
+
6
+ module ListoDelivery
7
+ module Models
8
+ # Your prepaid balance for the world the key acts in.
9
+ class Balance < Model
10
+ TYPES = {
11
+ "balance_cents" => nil,
12
+ "available_cents" => nil,
13
+ "currency" => nil,
14
+ "same_day" => ["model", "SameDayTerms"],
15
+ "in_review_cents" => nil
16
+ }.freeze
17
+
18
+ # Everything in the account, in centavos.
19
+ # @return [Integer]
20
+ def balance_cents
21
+ read("balance_cents")
22
+ end
23
+
24
+ # What you can withdraw today.
25
+ # @return [Integer]
26
+ def available_cents
27
+ read("available_cents")
28
+ end
29
+
30
+ # One of: "MXN".
31
+ # @return [String]
32
+ def currency
33
+ read("currency")
34
+ end
35
+
36
+ # @return [Models::SameDayTerms]
37
+ def same_day
38
+ read("same_day")
39
+ end
40
+
41
+ # The part of `balance_cents` that is cash from an order we are still reviewing.
42
+ # @return [Integer]
43
+ def in_review_cents
44
+ read("in_review_cents")
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ # GENERATED from Listo's API definition (API 1.37.0). Do not edit by hand:
4
+ # this file is rewritten whenever the SDK is regenerated.
5
+
6
+ module ListoDelivery
7
+ module Models
8
+ # Why the order is being canceled.
9
+ class CancelDeliveryRequest < Model
10
+ TYPES = {
11
+ "reason" => nil,
12
+ "description" => nil
13
+ }.freeze
14
+
15
+ # Why the order is canceled.
16
+ # One of: "customer_canceled", "store_closed", "item_unavailable", "wrong_address", "no_longer_needed", "other".
17
+ # @return [String]
18
+ def reason
19
+ read("reason")
20
+ end
21
+
22
+ # A sentence of explanation.
23
+ # @return [String, nil]
24
+ def description
25
+ read("description")
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ # GENERATED from Listo's API definition (API 1.37.0). Do not edit by hand:
4
+ # this file is rewritten whenever the SDK is regenerated.
5
+
6
+ module ListoDelivery
7
+ module Models
8
+ # A one-time hosted link to complete card onboarding.
9
+ class CardOnboardingLink < Model
10
+ TYPES = {
11
+ "url" => nil
12
+ }.freeze
13
+
14
+ # Send this to whoever can answer for the business.
15
+ # @return [String]
16
+ def url
17
+ read("url")
18
+ end
19
+ end
20
+ end
21
+ end