tango-api-client 0.1.1 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: aaca119882836f7c7ce028b229ef0bab2e57766b388aaab5825a6e8a03b336c1
4
- data.tar.gz: c32dd9d3e4ae82a78731d7408ade3a22a08f69e9c39b558b51700ca141d9d80b
3
+ metadata.gz: f7475c292cfcb29d85404d80d86cb94f47c4d0497dcfd97743366be0af176933
4
+ data.tar.gz: 69d61b9a8d860fd5734557d61aec61ae8d969634803c3a97e87f23db9ead35e1
5
5
  SHA512:
6
- metadata.gz: 7ed6160b4286d4628a79d961581bc6165a01f9a4446255a65663e0ff27a5145138da42b958b04bba2209168a103c74df4f29d3bdc930a02bb6f74202578414cb
7
- data.tar.gz: b2a464703e63b4a5869a3c61f0d670aafb906b757c020a58abd62935dbaea23b1331be6d342830ca439dc9018fe0e990e477e4730a3c2a74451091c57943784d
6
+ metadata.gz: 1243790a92ce6dba4870e506fb86e00a9436bf7c9c6e206e6d7d908b7011a0a06139ee0ba2decd3f6d0b4dd1341bd856484b66c7ad252886b88f091cb0faebc3
7
+ data.tar.gz: 6205cc363c7e1d2ef985b31fedb377a53c242d9d7339568d1bb5480be0aa8aecfc249fb1b71dc3b05efc4d208ef8e65311c405cb40244f31b0029404fa2262be
data/CHANGELOG.md CHANGED
@@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file.
5
5
  ## [Unreleased]
6
6
  - Nothing yet.
7
7
 
8
+ ## [0.2.0] - 2026-11-09
9
+ - Add Webhooks resource for subscription management: `create`, `list`, `get`, `update`, `delete`, `renew`
10
+ - Add webhook event history and redelivery: `events` (cursor paging, revision range) and `replay` (`fromRevision`/`toRevision` query params)
11
+ - Add `test` to trigger Tango's test deliveries (`ConnectivityTest`, or an event type such as `ItemAvailability` in the sandbox)
12
+ - `Resources::Base#post_without_body` for POST action endpoints that take only path and query parameters
13
+
14
+ ## [0.1.2] - 2025-11-12
15
+ - Add Brand Categories resource: `get` method for `/brandCategories` endpoint
16
+
17
+ ## [0.1.1] - 2025-11-12
18
+ - (Version already published)
19
+
8
20
  ## [0.1.0] - 2025-11-07
9
21
  - Initial release
10
22
  - Basic and OAuth2 auth strategies
data/README.md CHANGED
@@ -115,6 +115,19 @@ client.orders.create(
115
115
 
116
116
  # Resend with Idempotency-Key (prevents duplicate resends)
117
117
  client.orders.resend('ORDER-123', idempotency_key: idempotency)
118
+
119
+ # Webhook subscriptions (HMAC-signed ItemAvailability events)
120
+ sub = client.webhooks.create(
121
+ url: 'https://example.com/v1/tango/webhooks',
122
+ eventTypes: ['ItemAvailability'],
123
+ headers: [{ name: 'X-Subscription-Generation', value: '1' }],
124
+ payloadVerificationMethod: 'HMAC',
125
+ hmacSharedSecretKey: Base64.strict_encode64(SecureRandom.bytes(32))
126
+ )
127
+ client.webhooks.renew(sub['webhookId']) # => { 'webhookId', 'expiresAt' }
128
+ client.webhooks.events(sub['webhookId'], fromRevision: 0, maxResults: 100)
129
+ client.webhooks.replay(sub['webhookId'], from_revision: 0) # redeliver up to 3 months back
130
+ client.webhooks.test(sub['webhookId'], 'ItemAvailability') # sandbox only
118
131
  ```
119
132
 
120
133
  ### Resources overview
@@ -122,6 +135,7 @@ client.orders.resend('ORDER-123', idempotency_key: idempotency)
122
135
  | Resource | Class | Methods (args) | HTTP / Path |
123
136
  |-----------|-----------------------------------|----------------------------------------------------------------------------------------|----------------------------------------------------|
124
137
  | Catalogs | `Tango::Api::Resources::Catalogs` | `get(params = {})` | GET `/catalogs` |
138
+ | Brand Categories | `Tango::Api::Resources::BrandCategories` | `get` | GET `/brandCategories` |
125
139
  | Orders | `Tango::Api::Resources::Orders` | `create(body)`, `get(order_id)`, `list(params = {})`, `resend(order_id)` | POST `/orders`; GET `/orders/{id}`; GET `/orders`; POST `/orders/{id}/resend` |
126
140
  | Accounts | `Tango::Api::Resources::Accounts` | `get(account_identifier)`, `list_for_customer(customer_identifier, params)`, `create(customer_identifier, body)`, `update_under_customer(customer_identifier, account_identifier, body)`, low balance alerts: `list_low_balance_alerts`, `set_low_balance_alert`, `get_low_balance_alert`, `update_low_balance_alert`, `delete_low_balance_alert` | GET `/accounts/{accountIdentifier}`; GET/POST/PATCH/DELETE under `/customers/{customerIdentifier}/accounts/...` |
127
141
  | Customers | `Tango::Api::Resources::Customers`| `list(params = {})`, `get(customer_identifier)`, `create(body)`, `accounts(customer_identifier, params)` | GET `/customers`; GET `/customers/{customerIdentifier}`; POST `/customers`; GET `/customers/{customerIdentifier}/accounts` |
@@ -129,6 +143,7 @@ client.orders.resend('ORDER-123', idempotency_key: idempotency)
129
143
  | Status | `Tango::Api::Resources::Status` | `get` | GET `/status` |
130
144
  | Exchange Rates | `Tango::Api::Resources::ExchangeRates` | `get(params = {})`, `get_for_utid(utid, params = {})` | GET `/exchangeRates`; GET `/exchangeRates/{utid}` |
131
145
  | Choice Products | `Tango::Api::Resources::ChoiceProducts` | `get(params = {})`, `get_for_utid(utid)`, `catalog(choice_product_utid, params = {})` | GET `/choiceProducts`; GET `/choiceProducts/{utid}`; GET `/choiceProducts/{utid}/catalog` |
146
+ | Webhooks | `Tango::Api::Resources::Webhooks` | `create(body)`, `list(params = {})`, `get(webhook_id)`, `update(webhook_id, body)`, `delete(webhook_id)`, `renew(webhook_id)`, `events(webhook_id, params = {})`, `replay(webhook_id, from_revision:, to_revision: nil)`, `test(webhook_id, test_name)` | POST/GET `/webhooks`; GET/PATCH/DELETE `/webhooks/{webhookId}`; POST `/webhooks/{webhookId}/renew`; GET `/webhooks/{webhookId}/events`; POST `/webhooks/{webhookId}/replay`; POST `/webhooks/{webhookId}/tests/{testName}` |
132
147
 
133
148
  ### Smoke test
134
149
 
@@ -3,7 +3,7 @@
3
3
  module Tango
4
4
  module Api
5
5
  class Client
6
- VERSION = "0.1.1"
6
+ VERSION = "0.2.0"
7
7
  end
8
8
  end
9
9
  end
@@ -19,6 +19,8 @@ require_relative "resources/customers"
19
19
  require_relative "resources/status"
20
20
  require_relative "resources/exchange_rates"
21
21
  require_relative "resources/choice_products"
22
+ require_relative "resources/brand_categories"
23
+ require_relative "resources/webhooks"
22
24
 
23
25
  module Tango
24
26
  module Api
@@ -78,6 +80,14 @@ module Tango
78
80
  Resources::ChoiceProducts.new(@conn)
79
81
  end
80
82
 
83
+ def brand_categories
84
+ Resources::BrandCategories.new(@conn)
85
+ end
86
+
87
+ def webhooks
88
+ Resources::Webhooks.new(@conn)
89
+ end
90
+
81
91
  private
82
92
 
83
93
  def build_connection
@@ -53,6 +53,19 @@ module Tango
53
53
  raise map_faraday_error(e)
54
54
  end
55
55
 
56
+ # POST with no request body, for action endpoints that take only path and query
57
+ # parameters (e.g. webhook renew, replay, tests). Empty or non-JSON success bodies
58
+ # such as "OK" are returned as {} or { "raw" => body }.
59
+ def post_without_body(path, params = nil)
60
+ response = @conn.post(path) { |req| req.params.update(params) if params }
61
+ ensure_success_or_raise(response)
62
+ return {} if response.body.to_s.strip.empty?
63
+
64
+ parse_json_response(response)
65
+ rescue Faraday::Error => e
66
+ raise map_faraday_error(e)
67
+ end
68
+
56
69
  def delete_json(path)
57
70
  response = @conn.delete(path)
58
71
  ensure_success_or_raise(response)
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tango
4
+ module Api
5
+ module Resources
6
+ # Resource for Brand Categories endpoints.
7
+ class BrandCategories < Base
8
+ # GET /brandCategories
9
+ def get
10
+ get_json("brandCategories")
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tango
4
+ module Api
5
+ module Resources
6
+ # Webhook subscriptions: create, manage, renew, and read or redeliver past events.
7
+ class Webhooks < Base
8
+ # POST /webhooks
9
+ # Body keys: url (required), eventTypes and/or categories, headers ([{ name:, value: }]),
10
+ # payloadVerificationMethod ("HMAC", "X509" or "NONE"), hmacSharedSecretKey (base64),
11
+ # signingCertificate (base64).
12
+ # Returns { "webhookId" => ..., "expiresAt" => ... }.
13
+ def create(body)
14
+ post_json("webhooks", body)
15
+ end
16
+
17
+ # GET /webhooks
18
+ # Params may include: prevCursor, nextCursor, maxResults (default 10, max 200), url,
19
+ # headerName, headerValue, categories, eventTypes, expiresAtFrom/To, createdAtFrom/To.
20
+ def list(params = {})
21
+ get_json("webhooks", params)
22
+ end
23
+
24
+ # GET /webhooks/{webhookId}
25
+ def get(webhook_id)
26
+ get_json("webhooks/#{webhook_id}")
27
+ end
28
+
29
+ # PATCH /webhooks/{webhookId}
30
+ # Body keys as for #create; all optional.
31
+ def update(webhook_id, body)
32
+ patch_json("webhooks/#{webhook_id}", body)
33
+ end
34
+
35
+ # DELETE /webhooks/{webhookId}
36
+ def delete(webhook_id)
37
+ delete_json("webhooks/#{webhook_id}")
38
+ end
39
+
40
+ # POST /webhooks/{webhookId}/renew
41
+ # Returns { "webhookId" => ..., "expiresAt" => ... }.
42
+ def renew(webhook_id)
43
+ post_without_body("webhooks/#{webhook_id}/renew")
44
+ end
45
+
46
+ # GET /webhooks/{webhookId}/events
47
+ # Params may include: fromRevision, toRevision, prevCursor, nextCursor, maxResults.
48
+ # Returns a page: { "items" => [...], "nextCursor", "nextPageAvailable", ... }.
49
+ def events(webhook_id, params = {})
50
+ get_json("webhooks/#{webhook_id}/events", params)
51
+ end
52
+
53
+ # POST /webhooks/{webhookId}/replay?fromRevision=&toRevision=
54
+ # Redelivers past events (up to three months old). Omitting to_revision replays
55
+ # through the latest event.
56
+ def replay(webhook_id, from_revision:, to_revision: nil)
57
+ params = { fromRevision: from_revision }
58
+ params[:toRevision] = to_revision unless to_revision.nil?
59
+ post_without_body("webhooks/#{webhook_id}/replay", params)
60
+ end
61
+
62
+ # POST /webhooks/{webhookId}/tests/{testName}
63
+ # testName: ConnectivityTest (any environment) or, in the sandbox only, an event type
64
+ # such as ItemAvailability.
65
+ def test(webhook_id, test_name)
66
+ post_without_body("webhooks/#{webhook_id}/tests/#{test_name}")
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -15,6 +15,7 @@ module Tango
15
15
  def status: Resources::Status
16
16
  def exchange_rates: Resources::ExchangeRates
17
17
  def choice_products: Resources::ChoiceProducts
18
+ def brand_categories: Resources::BrandCategories
18
19
  end
19
20
  end
20
21
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tango-api-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Puneeth Kumar DN
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2025-11-12 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: activesupport
@@ -88,6 +87,7 @@ files:
88
87
  - lib/tango/api/errors.rb
89
88
  - lib/tango/api/resources/accounts.rb
90
89
  - lib/tango/api/resources/base.rb
90
+ - lib/tango/api/resources/brand_categories.rb
91
91
  - lib/tango/api/resources/catalogs.rb
92
92
  - lib/tango/api/resources/choice_products.rb
93
93
  - lib/tango/api/resources/customers.rb
@@ -95,6 +95,7 @@ files:
95
95
  - lib/tango/api/resources/funds.rb
96
96
  - lib/tango/api/resources/orders.rb
97
97
  - lib/tango/api/resources/status.rb
98
+ - lib/tango/api/resources/webhooks.rb
98
99
  - sig/tango/api/client.rbs
99
100
  homepage: https://github.com/Engagedly-Inc/tango-api-client
100
101
  licenses:
@@ -104,7 +105,6 @@ metadata:
104
105
  source_code_uri: https://github.com/Engagedly-Inc/tango-api-client
105
106
  changelog_uri: https://github.com/Engagedly-Inc/tango-api-client/blob/master/CHANGELOG.md
106
107
  rubygems_mfa_required: 'true'
107
- post_install_message:
108
108
  rdoc_options: []
109
109
  require_paths:
110
110
  - lib
@@ -119,8 +119,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
119
119
  - !ruby/object:Gem::Version
120
120
  version: '0'
121
121
  requirements: []
122
- rubygems_version: 3.3.7
123
- signing_key:
122
+ rubygems_version: 3.6.9
124
123
  specification_version: 4
125
124
  summary: Ruby client for Tango (BHN) API with dual auth and robust errors.
126
125
  test_files: []