fintoc 1.2.0 → 1.5.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: a1a0932a63c0c93038089b3054adbe8c105e82248627ce22105fa7e785548ecf
4
- data.tar.gz: 03e8f9737a40f23f03dec7d293b0741e6b95477ef3330181f7d0d0396fa98b03
3
+ metadata.gz: 34910f21240b0f76d808c9ab4f22b8ea4a904c9280b11e3bb1d39eee6660a0b6
4
+ data.tar.gz: ce6b1ca7100789cb27067aaeccd80324e089cbaf7b819317f35472f1fd3dad6d
5
5
  SHA512:
6
- metadata.gz: 67767ca7af9b52848bb8224134b352c1e83999cb3e4650ee248a0b241d31d476521c2422fbb821130463968d18b4e828bf55aedcf9269702483f478bd4665cc9
7
- data.tar.gz: 934617f315dfb320eb14fe2974272e17b9b17b87bf942c1b6fa6fb23192bf56cf4bd113724e89390282b1966d53d3f7f7392a11c68644ccb372e36d13e00bb2c
6
+ metadata.gz: 963c67d86b28ec2a1215720a6ddc69ff102f2f4368bc32871167750418d49e0e1b46ad95ebb6406862be93bd80034ea9398eac3622b9ced2a8b13719c7f7a519
7
+ data.tar.gz: fb45a851b1ce805c9bfd31d9eeefb21646c0acccdff4e0a3be04e541e57778af090f553892127638ef2ebd623319c17c430f9a09168875fe1b94ec99392f25f5
@@ -0,0 +1,53 @@
1
+ name: release
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ bump:
7
+ description: 'Tipo de bump'
8
+ type: choice
9
+ required: true
10
+ default: minor
11
+ options: [patch, minor, major]
12
+ release-notes:
13
+ description: 'Release notes (markdown, opcional)'
14
+ type: string
15
+ required: false
16
+
17
+ jobs:
18
+ release:
19
+ if: github.ref == 'refs/heads/main'
20
+ runs-on: ubuntu-latest
21
+ permissions:
22
+ contents: write
23
+ id-token: write
24
+ steps:
25
+ - uses: actions/checkout@v4
26
+
27
+ - uses: ruby/setup-ruby@v1
28
+ with:
29
+ ruby-version: '3.4'
30
+ bundler-cache: true
31
+
32
+ - run: bundle exec rspec
33
+
34
+ # setup-ruby's bundler-cache sets BUNDLE_FROZEN; prepare needs to refresh Gemfile.lock
35
+ - run: bundle config unset --local deployment && bundle config unset --local frozen
36
+
37
+ - uses: fintoc-com/release-action/prepare@main
38
+ id: prep
39
+ with:
40
+ bump: ${{ inputs.bump }}
41
+ version-format: ruby
42
+ tag-prefix: v
43
+ app-id: ${{ vars.FIN_RELEASES_APP_ID }}
44
+ app-private-key: ${{ secrets.FIN_RELEASES_PRIVATE_KEY }}
45
+
46
+ - uses: rubygems/release-gem@v1
47
+
48
+ - uses: fintoc-com/release-action/finalize@main
49
+ with:
50
+ tag: ${{ steps.prep.outputs.tag }}
51
+ release-notes: ${{ inputs.release-notes }}
52
+ app-id: ${{ vars.FIN_RELEASES_APP_ID }}
53
+ app-private-key: ${{ secrets.FIN_RELEASES_PRIVATE_KEY }}
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.3.0 - 2026-08-25
4
+
5
+ ### 🚀 New Features
6
+
7
+ - **Entity Onboardings**: Added `entities` resource with `create`, and `onboardings` under entities, including legal representative document upload
8
+ - **Webhook Endpoints**: Added `webhook_endpoints` manager
9
+ - **Multipart Uploads**: HTTP client now supports `multipart/form-data` requests
10
+
11
+ ### 🐛 Bug Fixes
12
+
13
+ - **HTTP 6 Compatibility**: Request options are passed as keyword arguments
14
+
3
15
  ## 1.2.0 - 2026-04-08
4
16
 
5
17
  ### 🚀 New Features
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- fintoc (1.2.0)
4
+ fintoc (1.5.0)
5
5
  http
6
6
  money-rails
7
7
  tabulate
@@ -38,16 +38,16 @@ GEM
38
38
  securerandom (>= 0.3)
39
39
  tzinfo (~> 2.0, >= 2.0.5)
40
40
  uri (>= 0.13.1)
41
- addressable (2.8.7)
42
- public_suffix (>= 2.0.2, < 7.0)
41
+ addressable (2.9.0)
42
+ public_suffix (>= 2.0.2, < 8.0)
43
43
  ast (2.4.3)
44
44
  base64 (0.3.0)
45
45
  benchmark (0.4.1)
46
- bigdecimal (3.2.2)
46
+ bigdecimal (4.1.2)
47
47
  builder (3.3.0)
48
48
  concurrent-ruby (1.3.5)
49
49
  connection_pool (2.5.3)
50
- crack (1.0.0)
50
+ crack (1.0.1)
51
51
  bigdecimal
52
52
  rexml
53
53
  crass (1.0.6)
@@ -58,27 +58,12 @@ GEM
58
58
  drb (2.2.3)
59
59
  erb (5.0.2)
60
60
  erubi (1.13.1)
61
- ffi (1.17.2)
62
- ffi (1.17.2-aarch64-linux-gnu)
63
- ffi (1.17.2-aarch64-linux-musl)
64
- ffi (1.17.2-arm-linux-gnu)
65
- ffi (1.17.2-arm-linux-musl)
66
- ffi (1.17.2-arm64-darwin)
67
- ffi (1.17.2-x86_64-darwin)
68
- ffi (1.17.2-x86_64-linux-gnu)
69
- ffi (1.17.2-x86_64-linux-musl)
70
- ffi-compiler (1.3.2)
71
- ffi (>= 1.15.5)
72
- rake
73
- hashdiff (1.2.0)
74
- http (5.3.1)
75
- addressable (~> 2.8)
61
+ hashdiff (1.2.1)
62
+ http (6.0.4)
76
63
  http-cookie (~> 1.0)
77
- http-form_data (~> 2.2)
78
- llhttp-ffi (~> 0.5.0)
79
- http-cookie (1.0.8)
64
+ llhttp (~> 0.6.1)
65
+ http-cookie (1.1.6)
80
66
  domain_name (~> 0.5)
81
- http-form_data (2.3.0)
82
67
  i18n (1.14.7)
83
68
  concurrent-ruby (~> 1.0)
84
69
  io-console (0.8.1)
@@ -89,9 +74,7 @@ GEM
89
74
  json (2.13.2)
90
75
  language_server-protocol (3.17.0.5)
91
76
  lint_roller (1.1.0)
92
- llhttp-ffi (0.5.1)
93
- ffi-compiler (~> 1.0)
94
- rake (~> 13.0)
77
+ llhttp (0.6.2)
95
78
  logger (1.7.0)
96
79
  loofah (2.24.1)
97
80
  crass (~> 1.0.2)
@@ -133,7 +116,7 @@ GEM
133
116
  psych (5.2.6)
134
117
  date
135
118
  stringio
136
- public_suffix (6.0.2)
119
+ public_suffix (7.0.5)
137
120
  racc (1.8.1)
138
121
  rack (3.2.0)
139
122
  rack-session (2.1.1)
@@ -159,14 +142,14 @@ GEM
159
142
  thor (~> 1.0, >= 1.2.2)
160
143
  zeitwerk (~> 2.6)
161
144
  rainbow (3.1.1)
162
- rake (13.3.0)
145
+ rake (13.4.2)
163
146
  rdoc (6.14.2)
164
147
  erb
165
148
  psych (>= 4.0.0)
166
149
  regexp_parser (2.11.2)
167
150
  reline (0.6.2)
168
151
  io-console (~> 0.5)
169
- rexml (3.4.2)
152
+ rexml (3.4.4)
170
153
  rspec (3.13.1)
171
154
  rspec-core (~> 3.13.0)
172
155
  rspec-expectations (~> 3.13.0)
@@ -233,7 +216,7 @@ GEM
233
216
  useragent (0.16.11)
234
217
  vcr (6.3.1)
235
218
  base64
236
- webmock (3.25.1)
219
+ webmock (3.26.2)
237
220
  addressable (>= 2.8.0)
238
221
  crack (>= 0.3.2)
239
222
  hashdiff (>= 0.4.0, < 2.0.0)
data/README.md CHANGED
@@ -31,8 +31,10 @@ Do yourself a favor: go grab some ice cubes by installing this refreshing librar
31
31
  - [Accounts](#accounts)
32
32
  - [Account Numbers](#account-numbers)
33
33
  - [Transfers](#transfers)
34
+ - [Transfer Batches](#transfer-batches)
34
35
  - [Simulate](#simulate)
35
36
  - [Account Verifications](#account-verifications)
37
+ - [Entity onboardings API Examples](#entity-onboardings-api-examples)
36
38
  - [Idempotency Keys](#idempotency-keys)
37
39
  - [Idempotency Examples](#idempotency-examples)
38
40
  - [Account Methods with Idempotency Key](#account-methods-with-idempotency-key)
@@ -138,6 +140,15 @@ transfer = client.v2.transfers.create(
138
140
  )
139
141
  client.v2.transfers.return('transfer_id')
140
142
 
143
+ # Transfer Batches
144
+ transfer_batches = client.v2.transfer_batches.list
145
+ transfer_batch = client.v2.transfer_batches.get('transfer_batch_id')
146
+ transfer_batch = client.v2.transfer_batches.create(
147
+ description: 'Supplier payments',
148
+ currency: 'MXN',
149
+ transfers: [{...}]
150
+ )
151
+
141
152
  # Simulate
142
153
  simulated_transfer = client.v2.simulate.receive_transfer(
143
154
  account_number_id: 'account_number_id',
@@ -150,6 +161,11 @@ account_verifications = client.v2.account_verifications.list
150
161
  account_verification = client.v2.account_verifications.get('account_verification_id')
151
162
  account_verification = client.v2.account_verifications.create(account_number: 'account_number')
152
163
 
164
+ # Entity onboardings
165
+ entity = client.v2.entities.get('entity_id')
166
+ onboardings = entity.onboardings.list
167
+ onboarding = entity.onboardings.get('onboarding_id')
168
+
153
169
  # TODO: Movements
154
170
  ```
155
171
 
@@ -354,6 +370,42 @@ transfers = client.v2.transfers.list
354
370
  returned_transfer = client.v2.transfers.return('transfer_id')
355
371
  ```
356
372
 
373
+ #### Transfer Batches
374
+
375
+ ```ruby
376
+ require 'fintoc'
377
+
378
+ client = Fintoc::Client.new('api_key', jws_private_key: 'jws_private_key')
379
+
380
+ # Create a transfer batch. Each transfer has the same shape as `transfers.create`, without `currency`
381
+ transfer_batch = client.v2.transfer_batches.create(
382
+ description: 'Supplier payments',
383
+ currency: 'MXN',
384
+ transfers: [
385
+ {
386
+ account_id: 'account_id',
387
+ amount: 10000,
388
+ comment: 'Invoice 1234',
389
+ reference_id: '123456',
390
+ counterparty: { account_number: '735969000000203297' }
391
+ }
392
+ ]
393
+ )
394
+
395
+ # Get a specific transfer batch
396
+ transfer_batch = client.v2.transfer_batches.get('transfer_batch_id')
397
+
398
+ # List transfer batches, optionally filtered by status and creation date
399
+ transfer_batches = client.v2.transfer_batches.list(
400
+ 'status[]': %w[succeeded partially_succeeded],
401
+ since: '2026-10-01T00:00:00Z',
402
+ until: '2026-10-31T23:59:59Z'
403
+ )
404
+
405
+ # List the transfers of a batch
406
+ transfers = client.v2.transfers.list(transfer_batch_id: 'transfer_batch_id')
407
+ ```
408
+
357
409
  #### Simulate
358
410
 
359
411
  ```ruby
@@ -386,6 +438,90 @@ account_verification = client.v2.account_verifications.get('account_verification
386
438
  account_verifications = client.v2.account_verifications.list
387
439
  ```
388
440
 
441
+ ### Entity onboardings API Examples
442
+
443
+ An entity onboarding represents the onboarding process for an entity. You access it from
444
+ an `Entity` instance (`entity.onboardings`); the full lifecycle is available: list,
445
+ retrieve, create, submit, and upload documents to a slot.
446
+
447
+ ```ruby
448
+ require 'fintoc'
449
+
450
+ client = Fintoc::Client.new('api_key', jws_private_key: 'jws_private_key')
451
+ entity = client.v2.entities.get('entity_id')
452
+
453
+ # List the onboardings of an entity (cursor-paginated, light shape)
454
+ onboardings = entity.onboardings.list
455
+
456
+ # Retrieve a single onboarding (full shape, includes legal representatives,
457
+ # shareholders and documents)
458
+ onboarding = entity.onboardings.get('onboarding_id')
459
+ puts onboarding # 📋 Onboarding onbprc_0ujs... (in_progress)
460
+ onboarding.type # => 'account_holder'
461
+ onboarding.legal_representatives # => array of legal representative hashes
462
+ onboarding.shareholders # => array of shareholder hashes
463
+ onboarding.documents # => array of document hashes
464
+
465
+ # Create an onboarding. `type` selects the onboarding to run (`account_holder` or
466
+ # `settlement_recipient`) and `data` holds the nested structures, which are passed
467
+ # through as-is and validated by the API.
468
+ onboarding = entity.onboardings.create(
469
+ type: 'account_holder',
470
+ data: {
471
+ company_information: {
472
+ incorporation_date: '2020-01-15',
473
+ business_activity: 'Servicios financieros',
474
+ fiscal_address: 'Av. Reforma 123, CDMX',
475
+ business_address: 'Av. Insurgentes 456, CDMX',
476
+ settlement_account: '646180357600000013',
477
+ phone: '+521111111111'
478
+ },
479
+ legal_representatives: [
480
+ {
481
+ first_name: 'Jane',
482
+ last_name: 'Doe',
483
+ email: 'jane@acme.com',
484
+ nationality: 'mx',
485
+ identification_number: 'AAAA010101HDFAAA01',
486
+ position: 'Director General'
487
+ }
488
+ ],
489
+ transactional_profile: {
490
+ resource_origins: %w[trusts investments],
491
+ monthly_amount_range: '1_500000',
492
+ monthly_operations_range: '1_15000'
493
+ },
494
+ shareholders: [
495
+ {
496
+ type: 'natural_person',
497
+ name: 'Jane',
498
+ last_name: 'Doe',
499
+ holder_id: 'AAAA010101AAA',
500
+ nationality: 'mx',
501
+ percentage: 100
502
+ }
503
+ ]
504
+ }
505
+ )
506
+
507
+ # Upload a document for a given slot (multipart). `file:` accepts a path or an IO.
508
+ entity.onboardings.upload_document('onboarding_id', 'slot_key', file: 'path/to/file.pdf')
509
+
510
+ # Upload a document for a specific shareholder (multipart).
511
+ entity.onboardings.upload_shareholder_document(
512
+ 'onboarding_id', 'shareholder_id', file: 'path/to/file.pdf'
513
+ )
514
+
515
+ # Upload a document for a specific legal representative (multipart).
516
+ # Slots: `identification` and `power_of_attorney`.
517
+ entity.onboardings.upload_legal_representative_document(
518
+ 'onboarding_id', 'legal_representative_id', 'identification', file: 'path/to/file.pdf'
519
+ )
520
+
521
+ # Submit the onboarding for review.
522
+ onboarding = entity.onboardings.submit('onboarding_id')
523
+ ```
524
+
389
525
  ## Idempotency Keys
390
526
 
391
527
  The Fintoc API supports [idempotency](https://docs.fintoc.com/reference/idempotent-requests) for safely retrying requests without accidentally performing the same operation twice. This is particularly useful when creating transfers, account numbers, accounts, or other resources where you want to avoid duplicates due to network issues.
@@ -38,9 +38,13 @@ module Fintoc
38
38
  request('patch', version:, use_jws:, idempotency_key:)
39
39
  end
40
40
 
41
+ def put(version: :v1, use_jws: false, idempotency_key: nil)
42
+ request('put', version:, use_jws:, idempotency_key:)
43
+ end
44
+
41
45
  def request(method, version: :v1, use_jws: false, idempotency_key: nil)
42
- proc do |resource, **kwargs|
43
- parameters = params(method, **kwargs)
46
+ proc do |resource, form: nil, **kwargs|
47
+ parameters = form ? { form: build_form(form) } : params(method, **kwargs)
44
48
  response = make_request(method, resource, parameters, version:, use_jws:, idempotency_key:)
45
49
  content = JSON.parse(response.body, symbolize_names: true)
46
50
 
@@ -118,7 +122,7 @@ module Fintoc
118
122
  request_client = request_client.headers('Idempotency-Key' => idempotency_key)
119
123
  end
120
124
 
121
- request_client.send(method, url, parameters)
125
+ request_client.send(method, url, **parameters)
122
126
  end
123
127
 
124
128
  def params(method, **kwargs)
@@ -129,6 +133,16 @@ module Fintoc
129
133
  end
130
134
  end
131
135
 
136
+ def build_form(form)
137
+ form.transform_values do |value|
138
+ file?(value) ? HTTP::FormData::File.new(value) : value
139
+ end
140
+ end
141
+
142
+ def file?(value)
143
+ value.respond_to?(:read) || (value.is_a?(String) && File.file?(value))
144
+ end
145
+
132
146
  def raise_custom_error(error)
133
147
  raise error_class(error[:code]).new(error[:message], error[:doc_url])
134
148
  end
data/lib/fintoc/errors.rb CHANGED
@@ -66,6 +66,9 @@ module Fintoc
66
66
  class InvalidInstallmentsCurrencyError < FintocError; end
67
67
  class InvalidClabeError < FintocError; end
68
68
  class MismatchTransferAccountCurrencyError < FintocError; end
69
+ class InvalidTransfersError < FintocError; end
70
+ class InvalidTransfersSizeError < FintocError; end
71
+ class InvalidDescriptionSizeError < FintocError; end
69
72
 
70
73
  # 401 Unauthorized Errors
71
74
  class AuthenticationError < FintocError; end
@@ -124,6 +127,7 @@ module Fintoc
124
127
  class InvalidTransferDirectionError < FintocError; end
125
128
  class AccountNumberLimitReachedError < FintocError; end
126
129
  class AccountCannotBeBlockedError < FintocError; end
130
+ class InvalidSenderAccountsError < FintocError; end
127
131
 
128
132
  # 422 Unprocessable Entity Errors
129
133
  class InvalidOtpCodeError < FintocError; end
@@ -150,6 +154,9 @@ module Fintoc
150
154
  class UnrecognizedRequestError < FintocError; end
151
155
  class CoreResponseError < FintocError; end
152
156
 
157
+ # 501 Not Implemented Errors
158
+ class OperationNotImplementedError < FintocError; end
159
+
153
160
  # Webhook Errors
154
161
  class WebhookSignatureError < FintocError; end
155
162
 
@@ -1,5 +1,6 @@
1
1
  require 'fintoc/base_client'
2
2
  require 'fintoc/v1/managers/links_manager'
3
+ require 'fintoc/v1/managers/webhook_endpoints_manager'
3
4
 
4
5
  module Fintoc
5
6
  module V1
@@ -7,6 +8,10 @@ module Fintoc
7
8
  def links
8
9
  @links ||= Managers::LinksManager.new(self)
9
10
  end
11
+
12
+ def webhook_endpoints
13
+ @webhook_endpoints ||= Managers::WebhookEndpointsManager.new(self)
14
+ end
10
15
  end
11
16
  end
12
17
  end
@@ -0,0 +1,77 @@
1
+ require 'fintoc/v1/resources/webhook_endpoint'
2
+
3
+ module Fintoc
4
+ module V1
5
+ module Managers
6
+ class WebhookEndpointsManager
7
+ def initialize(client)
8
+ @client = client
9
+ end
10
+
11
+ def create(url:, enabled_events:, idempotency_key: nil, **params)
12
+ data = _create_webhook_endpoint(
13
+ url:, enabled_events:, idempotency_key:, **params
14
+ )
15
+ build_webhook_endpoint(data)
16
+ end
17
+
18
+ def get(webhook_endpoint_id)
19
+ data = _get_webhook_endpoint(webhook_endpoint_id)
20
+ build_webhook_endpoint(data)
21
+ end
22
+
23
+ def list(**params)
24
+ _list_webhook_endpoints(**params).map { |data| build_webhook_endpoint(data) }
25
+ end
26
+
27
+ def update(webhook_endpoint_id, idempotency_key: nil, **params)
28
+ data = _update_webhook_endpoint(webhook_endpoint_id, idempotency_key:, **params)
29
+ build_webhook_endpoint(data)
30
+ end
31
+
32
+ def delete(webhook_endpoint_id)
33
+ _delete_webhook_endpoint(webhook_endpoint_id)
34
+ end
35
+
36
+ def test(webhook_endpoint_id, type:)
37
+ data = _test_webhook_endpoint(webhook_endpoint_id, type:)
38
+ build_webhook_endpoint(data)
39
+ end
40
+
41
+ private
42
+
43
+ def _create_webhook_endpoint(url:, enabled_events:, idempotency_key: nil, **params)
44
+ request_params = { url:, enabled_events: }
45
+ request_params.merge!(params)
46
+
47
+ @client.post(version: :v1, idempotency_key:).call('webhook_endpoints', **request_params)
48
+ end
49
+
50
+ def _get_webhook_endpoint(webhook_endpoint_id)
51
+ @client.get(version: :v1).call("webhook_endpoints/#{webhook_endpoint_id}")
52
+ end
53
+
54
+ def _list_webhook_endpoints(**params)
55
+ @client.get(version: :v1).call('webhook_endpoints', **params)
56
+ end
57
+
58
+ def _update_webhook_endpoint(webhook_endpoint_id, idempotency_key: nil, **params)
59
+ @client.patch(version: :v1, idempotency_key:)
60
+ .call("webhook_endpoints/#{webhook_endpoint_id}", **params)
61
+ end
62
+
63
+ def _delete_webhook_endpoint(webhook_endpoint_id)
64
+ @client.delete(version: :v1).call("webhook_endpoints/#{webhook_endpoint_id}")
65
+ end
66
+
67
+ def _test_webhook_endpoint(webhook_endpoint_id, type:)
68
+ @client.post(version: :v1).call("webhook_endpoints/#{webhook_endpoint_id}/test", type:)
69
+ end
70
+
71
+ def build_webhook_endpoint(data)
72
+ Fintoc::V1::WebhookEndpoint.new(**data, client: @client)
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,38 @@
1
+ module Fintoc
2
+ module V1
3
+ class WebhookEndpoint
4
+ attr_reader :id, :object, :url, :mode, :enabled_events, :secret, :disabled, :created_at
5
+
6
+ def initialize(
7
+ id:,
8
+ object:,
9
+ url:,
10
+ mode:,
11
+ enabled_events:,
12
+ secret:,
13
+ disabled:,
14
+ created_at:,
15
+ client: nil,
16
+ **
17
+ )
18
+ @id = id
19
+ @object = object
20
+ @url = url
21
+ @mode = mode
22
+ @enabled_events = enabled_events
23
+ @secret = secret
24
+ @disabled = disabled
25
+ @created_at = created_at
26
+ @client = client
27
+ end
28
+
29
+ def to_s
30
+ "🔔 #{@url} (#{@id})"
31
+ end
32
+
33
+ def disabled?
34
+ @disabled
35
+ end
36
+ end
37
+ end
38
+ end
@@ -3,6 +3,7 @@ require 'fintoc/v2/managers/entities_manager'
3
3
  require 'fintoc/v2/managers/accounts_manager'
4
4
  require 'fintoc/v2/managers/account_numbers_manager'
5
5
  require 'fintoc/v2/managers/transfers_manager'
6
+ require 'fintoc/v2/managers/transfer_batches_manager'
6
7
  require 'fintoc/v2/managers/simulate_manager'
7
8
  require 'fintoc/v2/managers/account_verifications_manager'
8
9
 
@@ -25,6 +26,10 @@ module Fintoc
25
26
  @transfers ||= Managers::TransfersManager.new(self)
26
27
  end
27
28
 
29
+ def transfer_batches
30
+ @transfer_batches ||= Managers::TransferBatchesManager.new(self)
31
+ end
32
+
28
33
  def simulate
29
34
  @simulate ||= Managers::SimulateManager.new(self)
30
35
  end
@@ -8,6 +8,11 @@ module Fintoc
8
8
  @client = client
9
9
  end
10
10
 
11
+ def create(holder_name:, holder_id:, country_code:, idempotency_key: nil, **params)
12
+ data = _create_entity(holder_name:, holder_id:, country_code:, idempotency_key:, **params)
13
+ build_entity(data)
14
+ end
15
+
11
16
  def get(entity_id)
12
17
  data = _get_entity(entity_id)
13
18
  build_entity(data)
@@ -19,6 +24,11 @@ module Fintoc
19
24
 
20
25
  private
21
26
 
27
+ def _create_entity(holder_name:, holder_id:, country_code:, idempotency_key: nil, **params)
28
+ @client.post(version: :v2, idempotency_key:)
29
+ .call('entities', holder_name:, holder_id:, country_code:, **params)
30
+ end
31
+
22
32
  def _get_entity(entity_id)
23
33
  @client.get(version: :v2).call("entities/#{entity_id}")
24
34
  end
@@ -0,0 +1,105 @@
1
+ require 'fintoc/v2/resources/onboarding'
2
+
3
+ module Fintoc
4
+ module V2
5
+ module Managers
6
+ class OnboardingsManager
7
+ def initialize(client, entity_id)
8
+ @client = client
9
+ @entity_id = entity_id
10
+ end
11
+
12
+ def list(**params)
13
+ _list_onboardings(**params).map { |data| build_onboarding(data) }
14
+ end
15
+
16
+ def get(onboarding_id)
17
+ data = _get_onboarding(onboarding_id)
18
+ build_onboarding(data)
19
+ end
20
+
21
+ def create(idempotency_key: nil, **params)
22
+ data = _create_onboarding(idempotency_key:, **params)
23
+ build_onboarding(data)
24
+ end
25
+
26
+ def submit(onboarding_id, idempotency_key: nil)
27
+ data = _submit_onboarding(onboarding_id, idempotency_key:)
28
+ build_onboarding(data)
29
+ end
30
+
31
+ def upload_document(onboarding_id, slot_key, file:, idempotency_key: nil)
32
+ data = _upload_document(onboarding_id, slot_key, file:, idempotency_key:)
33
+ build_onboarding(data)
34
+ end
35
+
36
+ def upload_shareholder_document(onboarding_id, shareholder_id, file:, idempotency_key: nil)
37
+ data = _upload_shareholder_document(
38
+ onboarding_id, shareholder_id, file:, idempotency_key:
39
+ )
40
+ build_onboarding(data)
41
+ end
42
+
43
+ def upload_legal_representative_document(
44
+ onboarding_id, legal_representative_id, slot_key, file:, idempotency_key: nil
45
+ )
46
+ data = _upload_legal_representative_document(
47
+ onboarding_id, legal_representative_id, slot_key, file:, idempotency_key:
48
+ )
49
+ build_onboarding(data)
50
+ end
51
+
52
+ private
53
+
54
+ def base_path
55
+ "entities/#{@entity_id}/onboardings"
56
+ end
57
+
58
+ def _list_onboardings(**params)
59
+ @client.get(version: :v2).call(base_path, **params)
60
+ end
61
+
62
+ def _get_onboarding(onboarding_id)
63
+ @client.get(version: :v2).call("#{base_path}/#{onboarding_id}")
64
+ end
65
+
66
+ def _create_onboarding(idempotency_key: nil, **params)
67
+ @client.post(version: :v2, idempotency_key:).call(base_path, **params)
68
+ end
69
+
70
+ def _submit_onboarding(onboarding_id, idempotency_key: nil)
71
+ @client.post(version: :v2, idempotency_key:)
72
+ .call("#{base_path}/#{onboarding_id}/submit")
73
+ end
74
+
75
+ def _upload_document(onboarding_id, slot_key, file:, idempotency_key: nil)
76
+ @client.put(version: :v2, idempotency_key:).call(
77
+ "#{base_path}/#{onboarding_id}/documents/#{slot_key}",
78
+ form: { file: }
79
+ )
80
+ end
81
+
82
+ def _upload_shareholder_document(onboarding_id, shareholder_id, file:, idempotency_key: nil)
83
+ @client.put(version: :v2, idempotency_key:).call(
84
+ "#{base_path}/#{onboarding_id}/shareholders/#{shareholder_id}/document",
85
+ form: { file: }
86
+ )
87
+ end
88
+
89
+ def _upload_legal_representative_document(
90
+ onboarding_id, legal_representative_id, slot_key, file:, idempotency_key: nil
91
+ )
92
+ @client.put(version: :v2, idempotency_key:).call(
93
+ "#{base_path}/#{onboarding_id}/legal_representatives" \
94
+ "/#{legal_representative_id}/documents/#{slot_key}",
95
+ form: { file: }
96
+ )
97
+ end
98
+
99
+ def build_onboarding(data)
100
+ Fintoc::V2::Onboarding.new(**data, client: @client)
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,47 @@
1
+ require 'fintoc/v2/resources/transfer_batch'
2
+
3
+ module Fintoc
4
+ module V2
5
+ module Managers
6
+ class TransferBatchesManager
7
+ def initialize(client)
8
+ @client = client
9
+ end
10
+
11
+ def create(description:, currency:, transfers:, idempotency_key: nil)
12
+ data = _create_transfer_batch(description:, currency:, transfers:, idempotency_key:)
13
+ build_transfer_batch(data)
14
+ end
15
+
16
+ def get(transfer_batch_id)
17
+ data = _get_transfer_batch(transfer_batch_id)
18
+ build_transfer_batch(data)
19
+ end
20
+
21
+ def list(**params)
22
+ _list_transfer_batches(**params).map { |data| build_transfer_batch(data) }
23
+ end
24
+
25
+ private
26
+
27
+ def _create_transfer_batch(description:, currency:, transfers:, idempotency_key: nil)
28
+ @client
29
+ .post(version: :v2, use_jws: true, idempotency_key:)
30
+ .call('transfer_batches', description:, currency:, transfers:)
31
+ end
32
+
33
+ def _get_transfer_batch(transfer_batch_id)
34
+ @client.get(version: :v2).call("transfer_batches/#{transfer_batch_id}")
35
+ end
36
+
37
+ def _list_transfer_batches(**params)
38
+ @client.get(version: :v2).call('transfer_batches', **params)
39
+ end
40
+
41
+ def build_transfer_batch(data)
42
+ Fintoc::V2::TransferBatch.new(**data, client: @client)
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -1,7 +1,9 @@
1
+ require 'fintoc/v2/managers/onboardings_manager'
2
+
1
3
  module Fintoc
2
4
  module V2
3
5
  class Entity
4
- attr_reader :object, :mode, :id, :holder_name, :holder_id, :is_root
6
+ attr_reader :object, :mode, :id, :holder_name, :holder_id, :is_root, :status, :country_code
5
7
 
6
8
  def initialize(
7
9
  object:,
@@ -10,6 +12,8 @@ module Fintoc
10
12
  holder_name:,
11
13
  holder_id:,
12
14
  is_root:,
15
+ status: nil,
16
+ country_code: nil,
13
17
  client: nil,
14
18
  **
15
19
  )
@@ -19,6 +23,8 @@ module Fintoc
19
23
  @holder_name = holder_name
20
24
  @holder_id = holder_id
21
25
  @is_root = is_root
26
+ @status = status
27
+ @country_code = country_code
22
28
  @client = client
23
29
  end
24
30
 
@@ -31,6 +37,10 @@ module Fintoc
31
37
  refresh_from_entity(fresh_entity)
32
38
  end
33
39
 
40
+ def onboardings
41
+ @onboardings ||= Managers::OnboardingsManager.new(@client, @id)
42
+ end
43
+
34
44
  private
35
45
 
36
46
  def refresh_from_entity(entity)
@@ -43,6 +53,8 @@ module Fintoc
43
53
  @holder_name = entity.holder_name
44
54
  @holder_id = entity.holder_id
45
55
  @is_root = entity.is_root
56
+ @status = entity.status
57
+ @country_code = entity.country_code
46
58
 
47
59
  self
48
60
  end
@@ -0,0 +1,46 @@
1
+ module Fintoc
2
+ module V2
3
+ class Onboarding
4
+ attr_reader :object, :id, :entity_id, :type, :status, :source, :submitted_at,
5
+ :reviewed_at, :submittable, :data, :legal_representatives, :shareholders,
6
+ :documents
7
+
8
+ def initialize(
9
+ object:,
10
+ id:,
11
+ entity_id: nil,
12
+ type: nil,
13
+ status: nil,
14
+ source: nil,
15
+ submitted_at: nil,
16
+ reviewed_at: nil,
17
+ submittable: nil,
18
+ data: nil,
19
+ legal_representatives: nil,
20
+ shareholders: nil,
21
+ documents: nil,
22
+ client: nil,
23
+ **
24
+ )
25
+ @object = object
26
+ @id = id
27
+ @entity_id = entity_id
28
+ @type = type
29
+ @status = status
30
+ @source = source
31
+ @submitted_at = submitted_at
32
+ @reviewed_at = reviewed_at
33
+ @submittable = submittable
34
+ @data = data
35
+ @legal_representatives = legal_representatives
36
+ @shareholders = shareholders
37
+ @documents = documents
38
+ @client = client
39
+ end
40
+
41
+ def to_s
42
+ "📋 Onboarding #{@id} (#{@status})"
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,114 @@
1
+ require 'money'
2
+
3
+ module Fintoc
4
+ module V2
5
+ class TransferBatch
6
+ attr_reader :id, :object, :mode, :description, :status, :currency, :transfer_count,
7
+ :amount, :succeeded_count, :settled_amount, :created_at, :authorized_at,
8
+ :rejected_at, :expired_at, :succeeded_at, :partially_succeeded_at
9
+
10
+ def initialize( # rubocop:disable Metrics/MethodLength
11
+ id:,
12
+ object:,
13
+ mode:,
14
+ status:,
15
+ currency:,
16
+ transfer_count:,
17
+ amount:,
18
+ description: nil,
19
+ succeeded_count: nil,
20
+ settled_amount: nil,
21
+ created_at: nil,
22
+ authorized_at: nil,
23
+ rejected_at: nil,
24
+ expired_at: nil,
25
+ succeeded_at: nil,
26
+ partially_succeeded_at: nil,
27
+ client: nil,
28
+ **
29
+ )
30
+ @id = id
31
+ @object = object
32
+ @mode = mode
33
+ @description = description
34
+ @status = status
35
+ @currency = currency
36
+ @transfer_count = transfer_count
37
+ @amount = amount
38
+ @succeeded_count = succeeded_count
39
+ @settled_amount = settled_amount
40
+ @created_at = created_at
41
+ @authorized_at = authorized_at
42
+ @rejected_at = rejected_at
43
+ @expired_at = expired_at
44
+ @succeeded_at = succeeded_at
45
+ @partially_succeeded_at = partially_succeeded_at
46
+ @client = client
47
+ end
48
+
49
+ def to_s
50
+ amount_str = Money.from_cents(@amount, @currency).format
51
+ "📦 #{amount_str} (#{@id}) - #{@status}"
52
+ end
53
+
54
+ def refresh
55
+ fresh_transfer_batch = @client.transfer_batches.get(@id)
56
+ refresh_from_transfer_batch(fresh_transfer_batch)
57
+ end
58
+
59
+ def pending_authorization?
60
+ @status == 'pending_authorization'
61
+ end
62
+
63
+ def in_progress?
64
+ @status == 'in_progress'
65
+ end
66
+
67
+ def rejected?
68
+ @status == 'rejected'
69
+ end
70
+
71
+ def expired?
72
+ @status == 'expired'
73
+ end
74
+
75
+ def succeeded?
76
+ @status == 'succeeded'
77
+ end
78
+
79
+ def partially_succeeded?
80
+ @status == 'partially_succeeded'
81
+ end
82
+
83
+ def failed?
84
+ @status == 'failed'
85
+ end
86
+
87
+ private
88
+
89
+ def refresh_from_transfer_batch(transfer_batch) # rubocop:disable Metrics/MethodLength
90
+ unless transfer_batch.id == @id
91
+ raise ArgumentError, 'Transfer batch must be the same instance'
92
+ end
93
+
94
+ @object = transfer_batch.object
95
+ @mode = transfer_batch.mode
96
+ @description = transfer_batch.description
97
+ @status = transfer_batch.status
98
+ @currency = transfer_batch.currency
99
+ @transfer_count = transfer_batch.transfer_count
100
+ @amount = transfer_batch.amount
101
+ @succeeded_count = transfer_batch.succeeded_count
102
+ @settled_amount = transfer_batch.settled_amount
103
+ @created_at = transfer_batch.created_at
104
+ @authorized_at = transfer_batch.authorized_at
105
+ @rejected_at = transfer_batch.rejected_at
106
+ @expired_at = transfer_batch.expired_at
107
+ @succeeded_at = transfer_batch.succeeded_at
108
+ @partially_succeeded_at = transfer_batch.partially_succeeded_at
109
+
110
+ self
111
+ end
112
+ end
113
+ end
114
+ end
@@ -1,3 +1,3 @@
1
1
  module Fintoc
2
- VERSION = '1.2.0'
2
+ VERSION = '1.5.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fintoc
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Juan Ca Sardin
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2026-04-08 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: http
@@ -61,6 +60,7 @@ extra_rdoc_files: []
61
60
  files:
62
61
  - ".github/pull_request_template.md"
63
62
  - ".github/workflows/ci.yml"
63
+ - ".github/workflows/release.yml"
64
64
  - ".gitignore"
65
65
  - ".rspec"
66
66
  - ".rubocop.yml"
@@ -84,12 +84,14 @@ files:
84
84
  - lib/fintoc/utils.rb
85
85
  - lib/fintoc/v1/client/client.rb
86
86
  - lib/fintoc/v1/managers/links_manager.rb
87
+ - lib/fintoc/v1/managers/webhook_endpoints_manager.rb
87
88
  - lib/fintoc/v1/resources/account.rb
88
89
  - lib/fintoc/v1/resources/balance.rb
89
90
  - lib/fintoc/v1/resources/institution.rb
90
91
  - lib/fintoc/v1/resources/link.rb
91
92
  - lib/fintoc/v1/resources/movement.rb
92
93
  - lib/fintoc/v1/resources/transfer_account.rb
94
+ - lib/fintoc/v1/resources/webhook_endpoint.rb
93
95
  - lib/fintoc/v2/client/client.rb
94
96
  - lib/fintoc/v2/managers/account_numbers_manager.rb
95
97
  - lib/fintoc/v2/managers/account_statements_manager.rb
@@ -97,7 +99,9 @@ files:
97
99
  - lib/fintoc/v2/managers/accounts_manager.rb
98
100
  - lib/fintoc/v2/managers/entities_manager.rb
99
101
  - lib/fintoc/v2/managers/movements_manager.rb
102
+ - lib/fintoc/v2/managers/onboardings_manager.rb
100
103
  - lib/fintoc/v2/managers/simulate_manager.rb
104
+ - lib/fintoc/v2/managers/transfer_batches_manager.rb
101
105
  - lib/fintoc/v2/managers/transfers_manager.rb
102
106
  - lib/fintoc/v2/resources/account.rb
103
107
  - lib/fintoc/v2/resources/account_number.rb
@@ -105,7 +109,9 @@ files:
105
109
  - lib/fintoc/v2/resources/account_verification.rb
106
110
  - lib/fintoc/v2/resources/entity.rb
107
111
  - lib/fintoc/v2/resources/movement.rb
112
+ - lib/fintoc/v2/resources/onboarding.rb
108
113
  - lib/fintoc/v2/resources/transfer.rb
114
+ - lib/fintoc/v2/resources/transfer_batch.rb
109
115
  - lib/fintoc/version.rb
110
116
  - lib/fintoc/webhook_signature.rb
111
117
  - lib/tasks/simplecov_config.rb
@@ -115,7 +121,6 @@ metadata:
115
121
  homepage_uri: https://github.com/fintoc-com/fintoc-ruby
116
122
  source_code_uri: https://github.com/fintoc-com/fintoc-ruby
117
123
  rubygems_mfa_required: 'true'
118
- post_install_message:
119
124
  rdoc_options: []
120
125
  require_paths:
121
126
  - lib
@@ -130,8 +135,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
130
135
  - !ruby/object:Gem::Version
131
136
  version: '0'
132
137
  requirements: []
133
- rubygems_version: 3.0.3.1
134
- signing_key:
138
+ rubygems_version: 3.6.9
135
139
  specification_version: 4
136
140
  summary: The official Ruby client for the Fintoc API.
137
141
  test_files: []