airwallex 0.10.0 → 0.11.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/CHANGELOG.md +26 -0
- data/README.md +61 -6
- data/lib/airwallex/resources/connected_account_transfer.rb +33 -0
- data/lib/airwallex/resources/funds_split.rb +20 -6
- data/lib/airwallex/resources/funds_split_reversal.rb +31 -0
- data/lib/airwallex/resources/transfer.rb +17 -8
- data/lib/airwallex/version.rb +1 -1
- data/lib/airwallex.rb +2 -0
- metadata +5 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f1288d75bff8a6f00a8c0dfffc318b6df1821cb26c945e062930de6035e83822
|
|
4
|
+
data.tar.gz: 5452a4a8aed172764129f05043646e9f074c1c9e62df84246ffe6ff575ba0140
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 02e3eea25661113f96af469d3154ede00aae144c671c42fcdf48d2e08d900c74ff2291b9b901ebc2b2072688b840d07d58f6b7eb21bd14aaf2c75d2e4625e6f2
|
|
7
|
+
data.tar.gz: 31bb06a6c4a99f4d433c63b5eb9e209e31deeec63dd3d98a516d259801530e874b66b70d4680d386eba0e569589a55e51c59640af3907fbade0e1da9171b6698
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [0.11.0] - 2026-10-01
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- `FundsSplitReversal` resource (`.create`, `.retrieve`, `.list`) for
|
|
8
|
+
`/api/v1/pa/funds_split_reversals`, which moves split funds back from a
|
|
9
|
+
connected account to the platform. `.list` takes the required `funds_split_id:`.
|
|
10
|
+
Partial reversals are allowed until the full split is reversed
|
|
11
|
+
- `ConnectedAccountTransfer` resource (`.create`, `.retrieve`, `.list`) for
|
|
12
|
+
`/api/v1/connected_account_transfers`, which moves funds between the platform
|
|
13
|
+
and a connected account. Pass `headers: { "x-on-behalf-of" => ... }` to
|
|
14
|
+
debit a connected account instead of the platform
|
|
15
|
+
- `Transfer.simulate_transition`, `Transfer#simulate_transition` and
|
|
16
|
+
`Transfer#cancel` accept `headers:`. A transfer created `x-on-behalf-of` a
|
|
17
|
+
connected account can only be found with that same header
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- `FundsSplit` docs (README and class comment) now show the real create body:
|
|
22
|
+
`request_id`, `source_id`, `source_type: "PAYMENT_INTENT"`, `amount` (string),
|
|
23
|
+
`destination`, `auto_release`, `metadata`, with one split per destination.
|
|
24
|
+
The docs previously showed `payment_intent_id:` and `splits: [...]`
|
|
25
|
+
- Documented that `funds_split.*` webhook payloads use `split_id` (not `id`)
|
|
26
|
+
and carry no `request_id`, and that the sandbox rejects a PROCESSING -> PAID
|
|
27
|
+
transfer transition (go through SENT)
|
|
28
|
+
|
|
3
29
|
## [0.10.0] - 2026-09-29
|
|
4
30
|
|
|
5
31
|
### Added
|
data/README.md
CHANGED
|
@@ -375,7 +375,7 @@ payment_source = Airwallex::PaymentSource.create(
|
|
|
375
375
|
)
|
|
376
376
|
```
|
|
377
377
|
|
|
378
|
-
### Scale (Connected Accounts, Funds Splits, Charges)
|
|
378
|
+
### Scale (Connected Accounts, Funds Splits, Reversals, Connected Account Transfers, Charges)
|
|
379
379
|
|
|
380
380
|
For platforms onboarding sub-merchants:
|
|
381
381
|
|
|
@@ -407,17 +407,56 @@ connected_account.submit
|
|
|
407
407
|
Airwallex::ConnectedAccount.current
|
|
408
408
|
Airwallex::ConnectedAccount.wallet_info
|
|
409
409
|
|
|
410
|
-
# Split a
|
|
410
|
+
# Split part of a PaymentIntent's funds to a connected account. One split per
|
|
411
|
+
# destination: create several splits to pay several connected accounts.
|
|
412
|
+
# A reused request_id raises BadRequestError (duplicate_request); splitting
|
|
413
|
+
# more than the PaymentIntent amount raises amount_above_limit.
|
|
411
414
|
split = Airwallex::FundsSplit.create(
|
|
412
|
-
|
|
413
|
-
|
|
415
|
+
request_id: 'split-order-123', # required, max 64
|
|
416
|
+
source_id: payment_intent.id, # required
|
|
417
|
+
source_type: 'PAYMENT_INTENT', # required
|
|
418
|
+
amount: '10.00', # required, string
|
|
419
|
+
destination: connected_account.id,
|
|
420
|
+
auto_release: false, # optional, default true
|
|
421
|
+
metadata: { order_id: '123' } # optional
|
|
422
|
+
)
|
|
423
|
+
split.release # only needed when auto_release: false
|
|
424
|
+
|
|
425
|
+
# Reverse split funds back to the platform. Partial reversals are allowed
|
|
426
|
+
# until the full split is reversed. Statuses: CREATED, RELEASED, SETTLED
|
|
427
|
+
reversal = Airwallex::FundsSplitReversal.create(
|
|
428
|
+
request_id: 'rev-order-123', # required, max 64
|
|
429
|
+
funds_split_id: split.id, # required
|
|
430
|
+
amount: '5.00', # required, string
|
|
431
|
+
metadata: { reason: 'refund' } # optional
|
|
414
432
|
)
|
|
415
|
-
|
|
433
|
+
Airwallex::FundsSplitReversal.retrieve(reversal.id)
|
|
434
|
+
Airwallex::FundsSplitReversal.list(funds_split_id: split.id) # funds_split_id is required
|
|
435
|
+
|
|
436
|
+
# Move funds between the platform and a connected account's wallet. Pass
|
|
437
|
+
# x-on-behalf-of to debit a connected account instead of the platform.
|
|
438
|
+
# Statuses: NEW, PENDING, SETTLED, SUSPENDED, FAILED
|
|
439
|
+
cat = Airwallex::ConnectedAccountTransfer.create(
|
|
440
|
+
request_id: 'top-up-123', # required, 1-50
|
|
441
|
+
amount: '100.00',
|
|
442
|
+
currency: 'AUD',
|
|
443
|
+
destination: connected_account.id,
|
|
444
|
+
reason: 'transfer_to_own_account',
|
|
445
|
+
reference: 'Ledger top-up' # required, 1-140
|
|
446
|
+
)
|
|
447
|
+
Airwallex::ConnectedAccountTransfer.retrieve(cat.id)
|
|
448
|
+
Airwallex::ConnectedAccountTransfer.list(destination: connected_account.id, status: 'SETTLED')
|
|
449
|
+
|
|
450
|
+
# Pay out from a connected account: create the Transfer on its behalf
|
|
451
|
+
Airwallex::Transfer.create(transfer_params, headers: { 'x-on-behalf-of' => connected_account.id })
|
|
416
452
|
|
|
417
453
|
# Charges (create, retrieve, list)
|
|
418
454
|
charge = Airwallex::Charge.retrieve('charge_id')
|
|
419
455
|
```
|
|
420
456
|
|
|
457
|
+
`funds_split.*` webhook payloads name the split `split_id`, not `id`, and carry
|
|
458
|
+
no `request_id`: `{ split_id, status, amount, currency, source_id, source_type, destination, ... }`.
|
|
459
|
+
|
|
421
460
|
### Requests for Information (RFIs)
|
|
422
461
|
|
|
423
462
|
RFIs are compliance questions Airwallex raises against an account. They use
|
|
@@ -555,8 +594,18 @@ transfer.simulate_transition(next_status: 'FAILED', failure_type: 'INSUFFICIENT_
|
|
|
555
594
|
|
|
556
595
|
# Class-level equivalent takes a transfer_id directly instead of an instance
|
|
557
596
|
Airwallex::Transfer.simulate_transition('tfr_123', next_status: 'CANCELLED')
|
|
597
|
+
|
|
598
|
+
# A transfer created x-on-behalf-of a connected account can only be found
|
|
599
|
+
# with the same header (cancel takes it too)
|
|
600
|
+
headers = { 'x-on-behalf-of' => 'acct_123' }
|
|
601
|
+
transfer.simulate_transition(next_status: 'SENT', headers: headers)
|
|
602
|
+
Airwallex::Transfer.simulate_transition('tfr_123', next_status: 'PAID', headers: headers)
|
|
603
|
+
transfer.cancel(headers: headers)
|
|
558
604
|
```
|
|
559
605
|
|
|
606
|
+
The sandbox rejects PROCESSING -> PAID with a 500 `operation_failed`. Move the
|
|
607
|
+
transfer to SENT first.
|
|
608
|
+
|
|
560
609
|
#### Connected Accounts & Offboarding
|
|
561
610
|
|
|
562
611
|
```ruby
|
|
@@ -746,6 +795,10 @@ begin
|
|
|
746
795
|
handle_successful_payment(event.data)
|
|
747
796
|
when 'payout.transfer.failed'
|
|
748
797
|
handle_failed_payout(event.data)
|
|
798
|
+
when 'funds_split.settled'
|
|
799
|
+
# funds_split.* payloads identify the split by split_id (not id) and
|
|
800
|
+
# carry no request_id — see the Scale section
|
|
801
|
+
handle_settled_split(event.data)
|
|
749
802
|
end
|
|
750
803
|
rescue Airwallex::SignatureVerificationError => e
|
|
751
804
|
# Invalid signature
|
|
@@ -849,7 +902,7 @@ end
|
|
|
849
902
|
- Customer (create, retrieve, list, update, delete)
|
|
850
903
|
- Dispute (retrieve, list, accept, challenge, related_payment_intents, simulate_create, simulate_escalate, simulate_resolve)
|
|
851
904
|
- **Payouts**:
|
|
852
|
-
- Transfer (create, retrieve, list, cancel, simulate_transition)
|
|
905
|
+
- Transfer (create, retrieve, list, cancel, simulate_transition; cancel/simulate_transition take headers: for x-on-behalf-of)
|
|
853
906
|
- Beneficiary (create, retrieve, list, update, delete, validate, verify_account, api_schema, form_schema, supported_financial_institutions)
|
|
854
907
|
- BatchTransfer (create, retrieve, list)
|
|
855
908
|
- **Foreign Exchange & Multi-Currency**:
|
|
@@ -876,6 +929,8 @@ end
|
|
|
876
929
|
- AccountAmendment (create, retrieve, simulate_approve, simulate_reject) - requires Admin-level API key permissions
|
|
877
930
|
- AccountOffboarding — sandbox Simulation only, scoped to a parent ConnectedAccount (simulate_complete, simulate_cancel)
|
|
878
931
|
- FundsSplit (create, retrieve, list, release)
|
|
932
|
+
- FundsSplitReversal (create, retrieve, list)
|
|
933
|
+
- ConnectedAccountTransfer (create, retrieve, list)
|
|
879
934
|
- Charge (create, retrieve, list)
|
|
880
935
|
- **Issuing** (sandbox Simulation only — no live Card/Cardholder resources yet):
|
|
881
936
|
- IssuingTransaction (simulate_create with single_phase, simulate_capture, simulate_reverse, simulate_refund, simulate_notify_three_ds)
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Airwallex
|
|
4
|
+
# Represents a Connected Account Transfer — moves funds between the platform
|
|
5
|
+
# account and a connected account's wallet. Send x-on-behalf-of to debit a
|
|
6
|
+
# connected account instead of the platform.
|
|
7
|
+
#
|
|
8
|
+
# Statuses: NEW, PENDING, SETTLED, SUSPENDED, FAILED. Create errors include
|
|
9
|
+
# insufficient_fund and request_id_duplicate.
|
|
10
|
+
#
|
|
11
|
+
# @example Fund a connected account from the platform
|
|
12
|
+
# transfer = Airwallex::ConnectedAccountTransfer.create(
|
|
13
|
+
# request_id: "cat-req-123", # required, 1-50
|
|
14
|
+
# amount: "100.00",
|
|
15
|
+
# currency: "AUD",
|
|
16
|
+
# destination: "acct_123", # connected account id
|
|
17
|
+
# reason: "transfer_to_own_account",
|
|
18
|
+
# reference: "Ledger top-up" # required, 1-140
|
|
19
|
+
# )
|
|
20
|
+
#
|
|
21
|
+
# @example List settled transfers to an account
|
|
22
|
+
# Airwallex::ConnectedAccountTransfer.list(destination: "acct_123", status: "SETTLED")
|
|
23
|
+
class ConnectedAccountTransfer < APIResource
|
|
24
|
+
extend APIOperations::Create
|
|
25
|
+
extend APIOperations::Retrieve
|
|
26
|
+
extend APIOperations::List
|
|
27
|
+
|
|
28
|
+
# @return [String] API resource path for connected account transfers
|
|
29
|
+
def self.resource_path
|
|
30
|
+
"/api/v1/connected_account_transfers"
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -1,18 +1,32 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Airwallex
|
|
4
|
-
# Represents a Funds Split —
|
|
5
|
-
#
|
|
6
|
-
#
|
|
4
|
+
# Represents a Funds Split — moves part of a PaymentIntent's funds from the
|
|
5
|
+
# platform account to a Connected Account. Each split has exactly one
|
|
6
|
+
# destination; create one split per connected account.
|
|
7
|
+
#
|
|
8
|
+
# Create errors include duplicate_request (reused request_id) and
|
|
9
|
+
# amount_above_limit (splits exceed the PaymentIntent amount).
|
|
10
|
+
#
|
|
11
|
+
# funds_split.* webhook payloads name the split split_id, not id, and carry
|
|
12
|
+
# no request_id: { split_id:, status:, amount:, currency:, source_id:,
|
|
13
|
+
# source_type:, destination:, ... }.
|
|
7
14
|
#
|
|
8
15
|
# @example Create a split
|
|
9
16
|
# split = Airwallex::FundsSplit.create(
|
|
10
|
-
#
|
|
11
|
-
#
|
|
17
|
+
# request_id: "split-req-123", # required, max 64
|
|
18
|
+
# source_id: intent.id, # required, PaymentIntent id
|
|
19
|
+
# source_type: "PAYMENT_INTENT", # required
|
|
20
|
+
# amount: "50.00", # required, string
|
|
21
|
+
# destination: connected_account.id,
|
|
22
|
+
# auto_release: true, # optional, default true
|
|
23
|
+
# metadata: { order_id: "123" } # optional
|
|
12
24
|
# )
|
|
13
25
|
#
|
|
14
|
-
# @example Release the split funds
|
|
26
|
+
# @example Release the split funds (when created with auto_release: false)
|
|
15
27
|
# split.release
|
|
28
|
+
#
|
|
29
|
+
# @see FundsSplitReversal to move split funds back to the platform
|
|
16
30
|
class FundsSplit < APIResource
|
|
17
31
|
extend APIOperations::Create
|
|
18
32
|
extend APIOperations::Retrieve
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Airwallex
|
|
4
|
+
# Represents a Funds Split Reversal — moves previously split funds back from
|
|
5
|
+
# the connected account (the split's destination) to the platform account.
|
|
6
|
+
# Partial reversals are allowed until the full split amount is reversed.
|
|
7
|
+
#
|
|
8
|
+
# Statuses: CREATED, RELEASED, SETTLED.
|
|
9
|
+
#
|
|
10
|
+
# @example Reverse part of a split
|
|
11
|
+
# reversal = Airwallex::FundsSplitReversal.create(
|
|
12
|
+
# request_id: "rev-req-123", # required, max 64
|
|
13
|
+
# funds_split_id: split.id, # required
|
|
14
|
+
# amount: "5.00", # required, string
|
|
15
|
+
# metadata: { reason: "refund" }
|
|
16
|
+
# )
|
|
17
|
+
# reversal.status # => "CREATED"
|
|
18
|
+
#
|
|
19
|
+
# @example List the reversals of a split
|
|
20
|
+
# Airwallex::FundsSplitReversal.list(funds_split_id: split.id)
|
|
21
|
+
class FundsSplitReversal < APIResource
|
|
22
|
+
extend APIOperations::Create
|
|
23
|
+
extend APIOperations::Retrieve
|
|
24
|
+
extend APIOperations::List
|
|
25
|
+
|
|
26
|
+
# @return [String] API resource path for funds split reversals
|
|
27
|
+
def self.resource_path
|
|
28
|
+
"/api/v1/pa/funds_split_reversals"
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -14,10 +14,14 @@ module Airwallex
|
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
# Cancel a pending transfer
|
|
17
|
-
|
|
17
|
+
#
|
|
18
|
+
# @param opts [Hash] headers: (e.g. { "x-on-behalf-of" => account_id })
|
|
19
|
+
# @return [Transfer] self
|
|
20
|
+
def cancel(opts = {})
|
|
18
21
|
response = Airwallex.client.post(
|
|
19
22
|
"#{self.class.resource_path}/#{id}/cancel",
|
|
20
|
-
{}
|
|
23
|
+
{},
|
|
24
|
+
opts[:headers] || {}
|
|
21
25
|
)
|
|
22
26
|
refresh_from(response)
|
|
23
27
|
self
|
|
@@ -25,18 +29,21 @@ module Airwallex
|
|
|
25
29
|
|
|
26
30
|
# Simulate this transfer's status advancing one step. The standard
|
|
27
31
|
# lifecycle is SCHEDULED -> PROCESSING -> SENT -> PAID, progressed one
|
|
28
|
-
# step at a time
|
|
29
|
-
#
|
|
32
|
+
# step at a time (the sandbox rejects PROCESSING -> PAID with a 500
|
|
33
|
+
# operation_failed; go through SENT); OVERDUE, FAILED, and CANCELLED can
|
|
34
|
+
# be jumped to directly.
|
|
30
35
|
#
|
|
31
36
|
# @param next_status [String] one of "OVERDUE", "PROCESSING", "SENT",
|
|
32
37
|
# "PAID", "FAILED", "CANCELLED"
|
|
33
38
|
# @param failure_type [String, nil] failure reason code, only
|
|
34
39
|
# meaningful when next_status is "FAILED"
|
|
40
|
+
# @param headers [Hash] e.g. { "x-on-behalf-of" => account_id } — required
|
|
41
|
+
# for a transfer created on behalf of a connected account
|
|
35
42
|
# @return [Transfer] self
|
|
36
|
-
def simulate_transition(next_status:, failure_type: nil)
|
|
43
|
+
def simulate_transition(next_status:, failure_type: nil, headers: {})
|
|
37
44
|
params = { next_status: next_status }
|
|
38
45
|
params[:failure_type] = failure_type if failure_type
|
|
39
|
-
response = Airwallex.client.post("#{SIMULATION_PATH}/#{id}/transition", params)
|
|
46
|
+
response = Airwallex.client.post("#{SIMULATION_PATH}/#{id}/transition", params, headers)
|
|
40
47
|
refresh_from(response)
|
|
41
48
|
self
|
|
42
49
|
end
|
|
@@ -48,11 +55,13 @@ module Airwallex
|
|
|
48
55
|
# "PAID", "FAILED", "CANCELLED"
|
|
49
56
|
# @param failure_type [String, nil] failure reason code, only
|
|
50
57
|
# meaningful when next_status is "FAILED"
|
|
58
|
+
# @param headers [Hash] e.g. { "x-on-behalf-of" => account_id } — required
|
|
59
|
+
# for a transfer created on behalf of a connected account
|
|
51
60
|
# @return [Transfer]
|
|
52
|
-
def self.simulate_transition(transfer_id, next_status:, failure_type: nil)
|
|
61
|
+
def self.simulate_transition(transfer_id, next_status:, failure_type: nil, headers: {})
|
|
53
62
|
params = { next_status: next_status }
|
|
54
63
|
params[:failure_type] = failure_type if failure_type
|
|
55
|
-
response = Airwallex.client.post("#{SIMULATION_PATH}/#{transfer_id}/transition", params)
|
|
64
|
+
response = Airwallex.client.post("#{SIMULATION_PATH}/#{transfer_id}/transition", params, headers)
|
|
56
65
|
new(response)
|
|
57
66
|
end
|
|
58
67
|
end
|
data/lib/airwallex/version.rb
CHANGED
data/lib/airwallex.rb
CHANGED
|
@@ -47,6 +47,8 @@ require_relative "airwallex/resources/payment_source"
|
|
|
47
47
|
require_relative "airwallex/resources/connected_account"
|
|
48
48
|
require_relative "airwallex/resources/account_amendment"
|
|
49
49
|
require_relative "airwallex/resources/funds_split"
|
|
50
|
+
require_relative "airwallex/resources/funds_split_reversal"
|
|
51
|
+
require_relative "airwallex/resources/connected_account_transfer"
|
|
50
52
|
require_relative "airwallex/resources/charge"
|
|
51
53
|
require_relative "airwallex/resources/deposit"
|
|
52
54
|
require_relative "airwallex/resources/issuing_transaction"
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: airwallex
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.11.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Chayut Orapinpatipat
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-10-01 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: faraday
|
|
@@ -93,11 +93,13 @@ files:
|
|
|
93
93
|
- lib/airwallex/resources/cardholder.rb
|
|
94
94
|
- lib/airwallex/resources/charge.rb
|
|
95
95
|
- lib/airwallex/resources/connected_account.rb
|
|
96
|
+
- lib/airwallex/resources/connected_account_transfer.rb
|
|
96
97
|
- lib/airwallex/resources/conversion.rb
|
|
97
98
|
- lib/airwallex/resources/customer.rb
|
|
98
99
|
- lib/airwallex/resources/deposit.rb
|
|
99
100
|
- lib/airwallex/resources/dispute.rb
|
|
100
101
|
- lib/airwallex/resources/funds_split.rb
|
|
102
|
+
- lib/airwallex/resources/funds_split_reversal.rb
|
|
101
103
|
- lib/airwallex/resources/global_account.rb
|
|
102
104
|
- lib/airwallex/resources/global_account_alias.rb
|
|
103
105
|
- lib/airwallex/resources/global_account_mandate.rb
|
|
@@ -144,7 +146,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
144
146
|
- !ruby/object:Gem::Version
|
|
145
147
|
version: '0'
|
|
146
148
|
requirements: []
|
|
147
|
-
rubygems_version: 3.5.
|
|
149
|
+
rubygems_version: 3.5.22
|
|
148
150
|
signing_key:
|
|
149
151
|
specification_version: 4
|
|
150
152
|
summary: Production-grade Ruby client for the Airwallex API
|