perata-sdk 0.3.0 → 0.4.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 +4 -4
- data/README.md +23 -2
- data/lib/perata/client.rb +3 -0
- data/lib/perata/error.rb +13 -7
- data/lib/perata/models.rb +64 -0
- data/lib/perata/params.rb +141 -2
- data/lib/perata/services.rb +16 -0
- data/lib/perata/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ffb21818636a4985aed2e37bed5c804482d4e33f36d59ac855170d95747dac5b
|
|
4
|
+
data.tar.gz: 2201ef7ba61a245ccf70aed0c7d48d11999f81fd8025a84acaf551ccec09441b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e9d0be391bcc52e48eeee7fca3ac3ded3bd246aaf5aa595f7c568a231ed6195e7b70cb01bd12df25f2731d3e4ceece23f3c03cf7b9e7f233896f09ebb917e062
|
|
7
|
+
data.tar.gz: daee592161aed12eaabe847b9d8f43b4651ea18d8cf1ab98decf477343c1153fc356cc78d8443594c694c55cbab2c32b9a2226105b97bf5ab0982333db9749ee
|
data/README.md
CHANGED
|
@@ -38,15 +38,36 @@ end
|
|
|
38
38
|
| `perata.products` | `archive`, `create`, `get`, `list`, `list_iter`, `update` |
|
|
39
39
|
| `perata.refunds` | `create`, `list`, `list_iter` |
|
|
40
40
|
| `perata.subscriptions` | `cancel`, `get`, `list`, `list_iter`, `update` |
|
|
41
|
+
| `perata.usage` | `ingest` |
|
|
41
42
|
| `perata.webhooks` | `create_endpoint`, `delete_endpoint`, `get_endpoint`, `list_deliveries`, `list_deliveries_iter`, `list_endpoints`, `list_endpoints_iter`, `update_endpoint` |
|
|
42
43
|
|
|
43
44
|
Os modelos são objetos imutáveis com leitores em snake_case (`payment.amount_cents`). O corpo de uma escrita é a classe de parâmetros do método (`Perata::ProductsCreateParams.new(name: "Curso")`) ou um `Hash` com os mesmos nomes; um campo opcional não informado fica fora do JSON. Os métodos `_iter` devolvem um `Enumerator` que percorre todas as páginas a partir de `page:` (ou recebem um bloco).
|
|
44
45
|
|
|
45
46
|
As escritas aceitam `idempotency_key:`, e todas aceitam `api_key:` para usar a chave de outra organização numa chamada. `Perata::Client.new` aceita `base_url:`, `timeout:` (30 segundos) e `transport:`. Um POST sem chave de idempotência é enviado com uma `Idempotency-Key` própria (UUID v4 aleatório, uma por chamada); passe a sua para poder repetir a mesma operação com segurança.
|
|
46
47
|
|
|
48
|
+
## Consumo (ingestão de eventos)
|
|
49
|
+
|
|
50
|
+
A ingestão de consumo usa outra credencial: a de uma fonte de ingestão (**Configurações › Fontes de ingestão**), `pus_test_…` em teste e `pus_live_…` em produção. Monte um cliente com ela; a chave de API da organização (`prk_…`) é recusada aqui com 401, e uma credencial de um ambiente nunca escreve no outro.
|
|
51
|
+
|
|
52
|
+
```ruby
|
|
53
|
+
usage = Perata::Client.new(ENV.fetch("PERATA_USAGE_KEY")) # pus_test_… ou pus_live_…
|
|
54
|
+
|
|
55
|
+
receipt = usage.usage.ingest({ events: [{
|
|
56
|
+
customer_id: customer_id,
|
|
57
|
+
external_event_id: "requisicao-001", # a mesma fonte repetindo o id com o mesmo conteúdo é replay
|
|
58
|
+
input_tokens: "1200",
|
|
59
|
+
output_tokens: "300",
|
|
60
|
+
cached_tokens: "0",
|
|
61
|
+
occurred_at: Time.now.utc.strftime("%Y-%m-%dT%H:%M:%SZ") # segundos inteiros, até 90 dias atrás
|
|
62
|
+
}] })
|
|
63
|
+
# receipt.created, receipt.replayed
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
De 1 a 100 eventos por chamada, até 64 KiB, todos gravados ou nenhum. Não há `Idempotency-Key` aqui: a identidade de um evento é o `external_event_id` da fonte, e repetir uma chamada é seguro (`replayed`); o mesmo id com outro conteúdo responde 409 (`conflict`), e um evento inválido, 422 (`invalid_request`) com `record` dizendo qual, a partir de 1.
|
|
67
|
+
|
|
47
68
|
## Erros
|
|
48
69
|
|
|
49
|
-
Uma recusa da API levanta `Perata::Error`, com `status`, `code` (`invalid_request`, `not_found`…), `message`, `fields` (o problema de cada campo) e, num 429, `retry_after` em segundos.
|
|
70
|
+
Uma recusa da API levanta `Perata::Error`, com `status`, `code` (`invalid_request`, `not_found`…), `message`, `fields` (o problema de cada campo), `record` (na ingestão, o evento recusado) e, num 429, `retry_after` em segundos.
|
|
50
71
|
|
|
51
72
|
## Webhooks
|
|
52
73
|
|
|
@@ -63,4 +84,4 @@ A assinatura é a do Standard Webhooks (`webhook-id`, `webhook-timestamp`, `webh
|
|
|
63
84
|
|
|
64
85
|
O evento é tipado: um tipo para cada dado que o webhook carrega (`OrderWebhookEvent` traz um `Order`, `DisputeWebhookEvent` a disputa, `IdentifiersWebhookEvent` os identificadores…), e o `type` diz o que aconteceu; um tipo que esta versão do SDK ainda não conhece chega como `UnknownWebhookEvent`, com os dados como vieram. Durante a rotação do segredo o cabeçalho traz mais de uma assinatura, e basta uma conferir. `Perata.verify_webhook_signature` só confere a assinatura.
|
|
65
86
|
|
|
66
|
-
Versão do SDK: 0.
|
|
87
|
+
Versão do SDK: 0.4.0 · contrato da API: 0.1.0
|
data/lib/perata/client.rb
CHANGED
|
@@ -64,6 +64,8 @@ module Perata
|
|
|
64
64
|
attr_reader :refunds
|
|
65
65
|
# @return [SubscriptionsService]
|
|
66
66
|
attr_reader :subscriptions
|
|
67
|
+
# @return [UsageService]
|
|
68
|
+
attr_reader :usage
|
|
67
69
|
# @return [WebhooksService]
|
|
68
70
|
attr_reader :webhooks
|
|
69
71
|
|
|
@@ -91,6 +93,7 @@ module Perata
|
|
|
91
93
|
@products = ProductsService.new(self)
|
|
92
94
|
@refunds = RefundsService.new(self)
|
|
93
95
|
@subscriptions = SubscriptionsService.new(self)
|
|
96
|
+
@usage = UsageService.new(self)
|
|
94
97
|
@webhooks = WebhooksService.new(self)
|
|
95
98
|
end
|
|
96
99
|
|
data/lib/perata/error.rb
CHANGED
|
@@ -6,19 +6,22 @@ module Perata
|
|
|
6
6
|
# A request the API refused.
|
|
7
7
|
#
|
|
8
8
|
# +code+ is the API's: invalid_credential, forbidden, not_found,
|
|
9
|
-
# invalid_request, conflict, idempotency_conflict, body_too_large or
|
|
10
|
-
# unavailable.
|
|
11
|
-
#
|
|
12
|
-
#
|
|
9
|
+
# invalid_request, conflict, idempotency_conflict, unsupported_media_type, body_too_large, rate_limited or
|
|
10
|
+
# unavailable.
|
|
11
|
+
# +message+ is the API's explanation, +fields+ says, for invalid_request,
|
|
12
|
+
# what is wrong with each field, +record+ is, for the usage ingestion, the
|
|
13
|
+
# position (from 1) in the batch of the event the API refused (0 for any other
|
|
14
|
+
# error), and +retry_after+ is how many seconds to wait on a 429.
|
|
13
15
|
class Error < StandardError
|
|
14
|
-
attr_reader :status, :code, :message, :fields, :retry_after
|
|
16
|
+
attr_reader :status, :code, :message, :fields, :retry_after, :record
|
|
15
17
|
|
|
16
|
-
def initialize(status, code, message = "", fields = {}, retry_after = nil)
|
|
18
|
+
def initialize(status, code, message = "", fields = {}, retry_after = nil, record = 0)
|
|
17
19
|
@status = status
|
|
18
20
|
@code = code
|
|
19
21
|
@message = message
|
|
20
22
|
@fields = fields
|
|
21
23
|
@retry_after = retry_after
|
|
24
|
+
@record = record
|
|
22
25
|
super(message.empty? ? "perata: #{status} #{code}" : "perata: #{status} #{code}: #{message}")
|
|
23
26
|
end
|
|
24
27
|
|
|
@@ -35,9 +38,12 @@ module Perata
|
|
|
35
38
|
rescue JSON::ParserError
|
|
36
39
|
{} # A refusal without a JSON body is still a refusal.
|
|
37
40
|
end
|
|
41
|
+
# Every error is the problem itself (error, message, fields). Servers from before
|
|
42
|
+
# that document wrapped the usage ingestion's errors in data: still read.
|
|
43
|
+
data = data["data"] if !data.key?("error") && data["data"].is_a?(Hash)
|
|
38
44
|
retry_after = headers["retry-after"].to_s
|
|
39
45
|
new(status, data["error"].to_s, data["message"].to_s, data["fields"] || {},
|
|
40
|
-
retry_after.match?(/\A\d+\z/) ? retry_after.to_i : nil)
|
|
46
|
+
retry_after.match?(/\A\d+\z/) ? retry_after.to_i : nil, data["record"].is_a?(Integer) ? data["record"] : 0)
|
|
41
47
|
end
|
|
42
48
|
end
|
|
43
49
|
end
|
data/lib/perata/models.rb
CHANGED
|
@@ -1693,6 +1693,45 @@ module Perata
|
|
|
1693
1693
|
end
|
|
1694
1694
|
end
|
|
1695
1695
|
|
|
1696
|
+
# UsageError is a resource of Peráta's API.
|
|
1697
|
+
class UsageError < Model
|
|
1698
|
+
MEMBERS = %i[error fields message record].freeze
|
|
1699
|
+
|
|
1700
|
+
# Código do erro: invalid_credential, invalid_request, conflict, unsupported_media_type, body_too_large, rate_limited ou unavailable.
|
|
1701
|
+
# @return [String]
|
|
1702
|
+
attr_reader :error
|
|
1703
|
+
|
|
1704
|
+
# Em invalid_request, o que há de errado em cada campo do evento.
|
|
1705
|
+
# @return [Hash{String => Array<String>}, nil]
|
|
1706
|
+
attr_reader :fields
|
|
1707
|
+
|
|
1708
|
+
# O que explica a recusa, em inglês.
|
|
1709
|
+
# @return [String, nil]
|
|
1710
|
+
attr_reader :message
|
|
1711
|
+
|
|
1712
|
+
# Posição, a partir de 1, do evento do lote que causou a recusa (invalid_request e conflict); o lote inteiro foi revertido.
|
|
1713
|
+
# @return [Integer, nil]
|
|
1714
|
+
attr_reader :record
|
|
1715
|
+
|
|
1716
|
+
def initialize(error:, fields: nil, message: nil, record: nil)
|
|
1717
|
+
@error = error
|
|
1718
|
+
@fields = fields
|
|
1719
|
+
@message = message
|
|
1720
|
+
@record = record
|
|
1721
|
+
freeze
|
|
1722
|
+
end
|
|
1723
|
+
|
|
1724
|
+
# Builds a UsageError from the API's JSON.
|
|
1725
|
+
def self.from_hash(data)
|
|
1726
|
+
new(
|
|
1727
|
+
error: data.fetch("error"),
|
|
1728
|
+
fields: data["fields"],
|
|
1729
|
+
message: data["message"],
|
|
1730
|
+
record: data["record"]
|
|
1731
|
+
)
|
|
1732
|
+
end
|
|
1733
|
+
end
|
|
1734
|
+
|
|
1696
1735
|
# WebhookBenefit is a resource of Peráta's API.
|
|
1697
1736
|
class WebhookBenefit < Model
|
|
1698
1737
|
MEMBERS = %i[created_at description id modified_at name status type visibility].freeze
|
|
@@ -2208,4 +2247,29 @@ module Perata
|
|
|
2208
2247
|
)
|
|
2209
2248
|
end
|
|
2210
2249
|
end
|
|
2250
|
+
|
|
2251
|
+
# What usage.ingest answers.
|
|
2252
|
+
class UsageIngestReceipt < Model
|
|
2253
|
+
MEMBERS = %i[created replayed].freeze
|
|
2254
|
+
|
|
2255
|
+
# @return [Integer]
|
|
2256
|
+
attr_reader :created
|
|
2257
|
+
|
|
2258
|
+
# @return [Integer]
|
|
2259
|
+
attr_reader :replayed
|
|
2260
|
+
|
|
2261
|
+
def initialize(created:, replayed:)
|
|
2262
|
+
@created = created
|
|
2263
|
+
@replayed = replayed
|
|
2264
|
+
freeze
|
|
2265
|
+
end
|
|
2266
|
+
|
|
2267
|
+
# Builds a UsageIngestReceipt from the API's JSON.
|
|
2268
|
+
def self.from_hash(data)
|
|
2269
|
+
new(
|
|
2270
|
+
created: data.fetch("created"),
|
|
2271
|
+
replayed: data.fetch("replayed")
|
|
2272
|
+
)
|
|
2273
|
+
end
|
|
2274
|
+
end
|
|
2211
2275
|
end
|
data/lib/perata/params.rb
CHANGED
|
@@ -346,6 +346,7 @@ module Perata
|
|
|
346
346
|
# @return [String]
|
|
347
347
|
attr_reader :email
|
|
348
348
|
|
|
349
|
+
# Até 120 caracteres, sem barra (/) nem caracteres de controle.
|
|
349
350
|
# @return [String, nil]
|
|
350
351
|
attr_reader :external_id
|
|
351
352
|
|
|
@@ -376,7 +377,7 @@ module Perata
|
|
|
376
377
|
# @return [String, nil]
|
|
377
378
|
attr_reader :email
|
|
378
379
|
|
|
379
|
-
# Só pode ser definido uma vez.
|
|
380
|
+
# Só pode ser definido uma vez. Até 120 caracteres, sem barra (/) nem caracteres de controle.
|
|
380
381
|
# @return [String, nil]
|
|
381
382
|
attr_reader :external_id
|
|
382
383
|
|
|
@@ -559,7 +560,7 @@ module Perata
|
|
|
559
560
|
# @return [String, nil]
|
|
560
561
|
attr_reader :email
|
|
561
562
|
|
|
562
|
-
# Só pode ser definido uma vez.
|
|
563
|
+
# Só pode ser definido uma vez. Até 120 caracteres, sem barra (/) nem caracteres de controle.
|
|
563
564
|
# @return [String, nil]
|
|
564
565
|
attr_reader :external_id
|
|
565
566
|
|
|
@@ -590,6 +591,7 @@ module Perata
|
|
|
590
591
|
# @return [Integer]
|
|
591
592
|
attr_reader :amount_cents
|
|
592
593
|
|
|
594
|
+
# Obrigatório no preço recorrente; o preço one_time não tem intervalo.
|
|
593
595
|
# @return [String ("month", "year"), nil]
|
|
594
596
|
attr_reader :interval
|
|
595
597
|
|
|
@@ -761,6 +763,143 @@ module Perata
|
|
|
761
763
|
end
|
|
762
764
|
end
|
|
763
765
|
|
|
766
|
+
# The body of usage.ingest.
|
|
767
|
+
class UsageIngestParams < Params
|
|
768
|
+
MEMBERS = %i[events].freeze
|
|
769
|
+
|
|
770
|
+
# @return [Array<UsageIngestEvent>]
|
|
771
|
+
attr_reader :events
|
|
772
|
+
|
|
773
|
+
def initialize(events:)
|
|
774
|
+
@events = events
|
|
775
|
+
freeze
|
|
776
|
+
end
|
|
777
|
+
|
|
778
|
+
# The body as the API reads it.
|
|
779
|
+
def to_wire
|
|
780
|
+
wire = {}
|
|
781
|
+
wire["events"] = Perata.wire(@events)
|
|
782
|
+
wire
|
|
783
|
+
end
|
|
784
|
+
end
|
|
785
|
+
|
|
786
|
+
# Opcional. O custo de atender o evento para o vendedor, em metadata._cost; alimenta Análises › Custos e as margens.
|
|
787
|
+
class UsageIngestEventCost < Params
|
|
788
|
+
MEMBERS = %i[amount currency].freeze
|
|
789
|
+
|
|
790
|
+
# Custo em centavos, como string decimal com até seis casas.
|
|
791
|
+
# @return [String]
|
|
792
|
+
attr_reader :amount
|
|
793
|
+
|
|
794
|
+
# Moeda do custo. Apenas brl.
|
|
795
|
+
# @return [String ("brl")]
|
|
796
|
+
attr_reader :currency
|
|
797
|
+
|
|
798
|
+
def initialize(amount:, currency:)
|
|
799
|
+
@amount = amount
|
|
800
|
+
@currency = currency
|
|
801
|
+
freeze
|
|
802
|
+
end
|
|
803
|
+
|
|
804
|
+
# The body as the API reads it.
|
|
805
|
+
def to_wire
|
|
806
|
+
wire = {}
|
|
807
|
+
wire["amount"] = @amount
|
|
808
|
+
wire["currency"] = @currency
|
|
809
|
+
wire
|
|
810
|
+
end
|
|
811
|
+
end
|
|
812
|
+
|
|
813
|
+
# Opcional. O modelo e o fornecedor que atenderam o evento, em metadata._llm; os contadores continuam nos campos de tokens.
|
|
814
|
+
class UsageIngestEventLlm < Params
|
|
815
|
+
MEMBERS = %i[model vendor].freeze
|
|
816
|
+
|
|
817
|
+
# Modelo que atendeu o evento.
|
|
818
|
+
# @return [String]
|
|
819
|
+
attr_reader :model
|
|
820
|
+
|
|
821
|
+
# Fornecedor do modelo.
|
|
822
|
+
# @return [String]
|
|
823
|
+
attr_reader :vendor
|
|
824
|
+
|
|
825
|
+
def initialize(model:, vendor:)
|
|
826
|
+
@model = model
|
|
827
|
+
@vendor = vendor
|
|
828
|
+
freeze
|
|
829
|
+
end
|
|
830
|
+
|
|
831
|
+
# The body as the API reads it.
|
|
832
|
+
def to_wire
|
|
833
|
+
wire = {}
|
|
834
|
+
wire["model"] = @model
|
|
835
|
+
wire["vendor"] = @vendor
|
|
836
|
+
wire
|
|
837
|
+
end
|
|
838
|
+
end
|
|
839
|
+
|
|
840
|
+
# One item of events in UsageIngestParams.
|
|
841
|
+
class UsageIngestEvent < Params
|
|
842
|
+
MEMBERS = %i[_cost _llm cached_tokens customer_id external_event_id input_tokens occurred_at output_tokens parent_id].freeze
|
|
843
|
+
|
|
844
|
+
# Opcional. O custo de atender o evento para o vendedor, em metadata._cost; alimenta Análises › Custos e as margens.
|
|
845
|
+
# @return [UsageIngestEventCost, nil]
|
|
846
|
+
attr_reader :_cost
|
|
847
|
+
|
|
848
|
+
# Opcional. O modelo e o fornecedor que atenderam o evento, em metadata._llm; os contadores continuam nos campos de tokens.
|
|
849
|
+
# @return [UsageIngestEventLlm, nil]
|
|
850
|
+
attr_reader :_llm
|
|
851
|
+
|
|
852
|
+
# @return [String]
|
|
853
|
+
attr_reader :cached_tokens
|
|
854
|
+
|
|
855
|
+
# @return [String]
|
|
856
|
+
attr_reader :customer_id
|
|
857
|
+
|
|
858
|
+
# @return [String]
|
|
859
|
+
attr_reader :external_event_id
|
|
860
|
+
|
|
861
|
+
# @return [String]
|
|
862
|
+
attr_reader :input_tokens
|
|
863
|
+
|
|
864
|
+
# @return [String]
|
|
865
|
+
attr_reader :occurred_at
|
|
866
|
+
|
|
867
|
+
# @return [String]
|
|
868
|
+
attr_reader :output_tokens
|
|
869
|
+
|
|
870
|
+
# Opcional. O evento pai, pelo id da Peráta ou pelo external_event_id que a mesma fonte enviou; o pai precisa chegar antes, inclusive antes no mesmo lote.
|
|
871
|
+
# @return [String, nil]
|
|
872
|
+
attr_reader :parent_id
|
|
873
|
+
|
|
874
|
+
def initialize(_cost: nil, _llm: nil, cached_tokens:, customer_id:, external_event_id:, input_tokens:, occurred_at:, output_tokens:, parent_id: nil)
|
|
875
|
+
@_cost = _cost
|
|
876
|
+
@_llm = _llm
|
|
877
|
+
@cached_tokens = cached_tokens
|
|
878
|
+
@customer_id = customer_id
|
|
879
|
+
@external_event_id = external_event_id
|
|
880
|
+
@input_tokens = input_tokens
|
|
881
|
+
@occurred_at = occurred_at
|
|
882
|
+
@output_tokens = output_tokens
|
|
883
|
+
@parent_id = parent_id
|
|
884
|
+
freeze
|
|
885
|
+
end
|
|
886
|
+
|
|
887
|
+
# The body as the API reads it.
|
|
888
|
+
def to_wire
|
|
889
|
+
wire = {}
|
|
890
|
+
wire["_cost"] = Perata.wire(@_cost) unless @_cost.nil?
|
|
891
|
+
wire["_llm"] = Perata.wire(@_llm) unless @_llm.nil?
|
|
892
|
+
wire["cached_tokens"] = @cached_tokens
|
|
893
|
+
wire["customer_id"] = @customer_id
|
|
894
|
+
wire["external_event_id"] = @external_event_id
|
|
895
|
+
wire["input_tokens"] = @input_tokens
|
|
896
|
+
wire["occurred_at"] = @occurred_at
|
|
897
|
+
wire["output_tokens"] = @output_tokens
|
|
898
|
+
wire["parent_id"] = @parent_id unless @parent_id.nil?
|
|
899
|
+
wire
|
|
900
|
+
end
|
|
901
|
+
end
|
|
902
|
+
|
|
764
903
|
# The body of webhooks:create_endpoint.
|
|
765
904
|
class WebhooksCreateEndpointParams < Params
|
|
766
905
|
MEMBERS = %i[description events format url].freeze
|
data/lib/perata/services.rb
CHANGED
|
@@ -730,6 +730,22 @@ module Perata
|
|
|
730
730
|
end
|
|
731
731
|
end
|
|
732
732
|
|
|
733
|
+
# The API's usage.
|
|
734
|
+
class UsageService
|
|
735
|
+
def initialize(client)
|
|
736
|
+
@client = client
|
|
737
|
+
end
|
|
738
|
+
|
|
739
|
+
# Ingerir lote atômico de eventos de uso. Autentica com a credencial de uma fonte de ingestão (pus_test_… ou pus_live_…), não com a chave de API da organização.
|
|
740
|
+
#
|
|
741
|
+
# @param params [UsageIngestParams, Hash]
|
|
742
|
+
# @return [UsageIngestReceipt]
|
|
743
|
+
def ingest(params, api_key: nil)
|
|
744
|
+
data = @client.request("POST", "/api/v1/usage/token-events", body: UsageIngestParams.coerce(params).to_wire, api_key: api_key)
|
|
745
|
+
UsageIngestReceipt.from_hash(data)
|
|
746
|
+
end
|
|
747
|
+
end
|
|
748
|
+
|
|
733
749
|
# The API's webhooks.
|
|
734
750
|
class WebhooksService
|
|
735
751
|
def initialize(client)
|
data/lib/perata/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: perata-sdk
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Peráta
|
|
@@ -45,7 +45,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
45
45
|
- !ruby/object:Gem::Version
|
|
46
46
|
version: '0'
|
|
47
47
|
requirements: []
|
|
48
|
-
rubygems_version:
|
|
48
|
+
rubygems_version: 4.0.20
|
|
49
49
|
specification_version: 4
|
|
50
50
|
summary: 'Peráta''s SDK for Ruby: products, customers, checkouts, payments, subscriptions
|
|
51
51
|
and webhooks.'
|