@pabilo/sdk 0.1.6 → 0.1.7

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.
package/README.md CHANGED
@@ -43,9 +43,15 @@ Returns the authenticated user's profile.
43
43
  ```typescript
44
44
  const user = await pabilo.me.getMe();
45
45
 
46
- console.log(user.id); // string
47
- console.log(user.email); // string | undefined
48
- console.log(user.name); // string | undefined
46
+ console.log(user.id); // string
47
+ console.log(user.email); // string | undefined
48
+ console.log(user.username); // string | undefined
49
+ console.log(user.fullName); // string | undefined
50
+ console.log(user.companyName); // string | undefined
51
+ console.log(user.credits); // number | undefined
52
+ console.log(user.planIsActive);// boolean | undefined
53
+ console.log(user.isDemo); // boolean | undefined
54
+ console.log(user.userType); // 'user' | 'admin' | 'commerce' | ... | undefined
49
55
  ```
50
56
 
51
57
  **Returns:** `User`
@@ -54,8 +60,16 @@ console.log(user.name); // string | undefined
54
60
  interface User {
55
61
  id: string;
56
62
  email?: string;
57
- name?: string;
63
+ username?: string;
64
+ fullName?: string;
65
+ companyName?: string;
66
+ credits?: number;
67
+ planIsActive?: boolean;
68
+ isDemo?: boolean;
69
+ userType?: UserType;
58
70
  }
71
+
72
+ type UserType = 'system' | 'user' | 'admin' | 'test' | 'commerce' | string;
59
73
  ```
60
74
 
61
75
  ---
@@ -67,16 +81,38 @@ Returns the current subscription plan for the authenticated account.
67
81
  ```typescript
68
82
  const plan = await pabilo.me.getPlan();
69
83
 
70
- console.log(plan.name); // e.g. 'basic', 'pro'
71
- console.log(plan.planType); // string | undefined
84
+ console.log(plan.name); // e.g. 'Pro'
85
+ console.log(plan.planType); // 'credit' | 'unlimited' | 'counter'
86
+ console.log(plan.period); // 'month' | 'six_months' | 'year'
87
+ console.log(plan.requestLimit); // number (-1 = unlimited)
88
+ console.log(plan.bankAccountLimit); // number (-1 = unlimited)
89
+ console.log(plan.initialCredits); // number
90
+ console.log(plan.price); // number
91
+ console.log(plan.benefits); // PlanBenefit[]
72
92
  ```
73
93
 
74
94
  **Returns:** `Plan`
75
95
 
76
96
  ```typescript
77
97
  interface Plan {
98
+ id?: string;
78
99
  name: string;
79
- planType?: string;
100
+ description?: string;
101
+ planType?: PlanType; // 'credit' | 'unlimited' | 'counter'
102
+ period?: PlanPeriod; // 'month' | 'six_months' | 'year'
103
+ price?: number;
104
+ requestLimit?: number;
105
+ bankAccountLimit?: number;
106
+ initialCredits?: number;
107
+ maxAcumulatedCredits?: number;
108
+ benefits?: PlanBenefit[];
109
+ salient?: boolean;
110
+ hidden?: boolean;
111
+ }
112
+
113
+ interface PlanBenefit {
114
+ description: string;
115
+ contain: boolean;
80
116
  }
81
117
  ```
82
118
 
@@ -106,7 +142,7 @@ for (const bank of banks) {
106
142
  interface UserBank {
107
143
  id: string;
108
144
  description: string;
109
- provider: string;
145
+ provider: BankProvider;
110
146
  bank_accounts: BankAccountEntry[];
111
147
  payment_link?: boolean;
112
148
  to_trash?: boolean;
@@ -116,6 +152,17 @@ interface BankAccountEntry {
116
152
  account_number: string;
117
153
  account_type: string; // e.g. 'AHORRO', 'CORRIENTE'
118
154
  }
155
+
156
+ type BankProvider =
157
+ | 'VE_BAN' // BDV personal
158
+ | 'VE_BAN_EMP' // BDV empresa v1
159
+ | 'VE_BAN_EMP_V2' // BDV empresa v2
160
+ | 'VE_PROV' // Provincial personal
161
+ | 'VE_PROV_EMP' // Provincial empresa
162
+ | 'MERCANTIL_EMP_V1' // Mercantil empresa
163
+ | 'MERCANTIL_EMP_TEST_V1' // Mercantil test
164
+ | 'BANK_TEST' // Sandbox
165
+ | string;
119
166
  ```
120
167
 
121
168
  ---
@@ -135,21 +182,17 @@ const bank = await pabilo.bankAccounts.create({
135
182
  username: 'usuario_portal_bdv',
136
183
  password: 'contraseña_portal_bdv',
137
184
  });
138
-
139
- console.log(bank.id); // use this id when creating payment links
140
185
  ```
141
186
 
142
187
  **BDV empresa — `VE_BAN_EMP_V2`**
143
188
 
144
- The `accountNumber` and `apiKey` fields are mapped to `username` and `password` in the API — the SDK exposes semantic names.
145
-
146
189
  ```typescript
147
190
  const bank = await pabilo.bankAccounts.create({
148
191
  bankProvider: 'VE_BAN_EMP_V2',
149
192
  description: 'Cuenta empresa BDV',
150
193
  userBankPhone: '04241234567',
151
194
  userBankDni: '12345678',
152
- accountNumber: '01020000000000000000', // número de cuenta
195
+ accountNumber: '01020000000000000000',
153
196
  apiKey: 'bdv_api_key_here',
154
197
  metadata: [
155
198
  { key_name: 'SHOW_DATE_IN_GENERIC_MOVEMENTS', key_value: 'true' },
@@ -165,59 +208,62 @@ A sandboxed bank for testing. Always has a payment with reference `67890` availa
165
208
  const bank = await pabilo.bankAccounts.create({ bankProvider: 'BANK_TEST' });
166
209
  ```
167
210
 
168
- **Request types:**
211
+ ---
212
+
213
+ ### `bankAccounts.delete(id): Promise<void>`
214
+
215
+ Soft-deletes a bank account. The bank no longer appears in `list()` results.
169
216
 
170
217
  ```typescript
171
- // Shared base (not needed for BANK_TEST)
172
- interface BaseCreateUserBankRequest {
173
- description: string;
174
- userBankPhone: string;
175
- userBankDni: string;
176
- metadata?: UserBankMetadataEntry[]; // [{ key_name: string, key_value: string }]
177
- }
218
+ await pabilo.bankAccounts.delete(bank.id);
219
+ ```
178
220
 
179
- interface CreateVeBanRequest extends BaseCreateUserBankRequest {
180
- bankProvider: 'VE_BAN';
181
- username: string;
182
- password: string;
183
- }
221
+ ---
184
222
 
185
- interface CreateVeBanEmpV2Request extends BaseCreateUserBankRequest {
186
- bankProvider: 'VE_BAN_EMP_V2';
187
- accountNumber: string;
188
- apiKey: string;
189
- }
223
+ ## `pabilo.paymentLinks`
190
224
 
191
- interface CreateBankTestRequest {
192
- bankProvider: 'BANK_TEST';
193
- }
225
+ ### `paymentLinks.list(req?): Promise<PaymentLinksPage>`
194
226
 
195
- type CreateUserBankRequest =
196
- | CreateVeBanRequest
197
- | CreateVeBanEmpV2Request
198
- | CreateBankTestRequest;
199
- ```
227
+ Returns a paginated list of the authenticated user's payment links.
228
+
229
+ ```typescript
230
+ const page = await pabilo.paymentLinks.list({
231
+ limit: 10,
232
+ page: 1,
233
+ status: 'pending', // filter by status
234
+ type: 'default', // filter by type
235
+ search: 'orden', // search by name/description
236
+ });
200
237
 
201
- **Returns:** `UserBank` (same shape as `list()` entries)
238
+ console.log(page.total); // total count
239
+ console.log(page.page); // current page
240
+ console.log(page.limit); // page size
241
+ console.log(page.items); // PaymentLink[]
242
+ ```
202
243
 
203
- ---
244
+ **Request fields (all optional):**
204
245
 
205
- ### `bankAccounts.delete(id): Promise<void>`
246
+ | Field | Type | Default | Description |
247
+ |---|---|---|---|
248
+ | `page` | `number` | `1` | Page number |
249
+ | `limit` | `number` | `10` | Items per page |
250
+ | `status` | `PaymentLinkStatus` | — | Filter by status |
251
+ | `type` | `PaymentLinkType` | — | Filter by type |
252
+ | `search` | `string` | — | Text search |
206
253
 
207
- Soft-deletes a bank account (moves it to trash). The bank no longer appears in `list()` results.
254
+ **Returns:** `PaymentLinksPage`
208
255
 
209
256
  ```typescript
210
- await pabilo.bankAccounts.delete(bank.id);
257
+ interface PaymentLinksPage {
258
+ items: PaymentLink[];
259
+ total: number;
260
+ page: number;
261
+ limit: number;
262
+ }
211
263
  ```
212
264
 
213
- | Parameter | Type | Description |
214
- |---|---|---|
215
- | `id` | `string` | The `UserBank.id` to delete |
216
-
217
265
  ---
218
266
 
219
- ## `pabilo.paymentLinks`
220
-
221
267
  ### `paymentLinks.create(req): Promise<PaymentLink>`
222
268
 
223
269
  Creates a new payment link that customers can use to pay via Pago Móvil.
@@ -236,9 +282,9 @@ const link = await pabilo.paymentLinks.create({
236
282
  currency: 'VES',
237
283
  });
238
284
 
239
- console.log(link.url); // https://pabilo.app/pay/... share this with the customer
240
- console.log(link.id); // use for getInfo / isPaid / update
241
- console.log(link.status); // 'pending' | 'active' | 'paid' | 'expired' | 'cancelled'
285
+ console.log(link.url); // https://pabilo.app/pay/...
286
+ console.log(link.id);
287
+ console.log(link.status); // 'pending' | 'active' | 'paid' | 'failed' | 'canceled' | 'expired' | 'stopped'
242
288
  ```
243
289
 
244
290
  **Request fields:**
@@ -263,111 +309,96 @@ interface PaymentLink {
263
309
  id: string;
264
310
  url: string;
265
311
  amount?: number;
266
- status?: 'pending' | 'paid' | 'active' | 'expired' | 'cancelled';
267
- type?: 'default' | 'fixed';
312
+ status?: PaymentLinkStatus;
313
+ statusDetail?: string;
314
+ type?: PaymentLinkType;
268
315
  userId?: string;
316
+ userBankId?: string;
317
+ withSubscriptionId?: string;
269
318
  name?: string;
270
319
  description?: string;
271
320
  isUsd?: boolean;
272
321
  redirectUrl?: string;
273
322
  webhookUrl?: string;
323
+ webhookMethod?: string;
274
324
  notificationByWhatsapp?: boolean;
275
325
  expirationTime?: number;
276
- paymentLinkOrigin?: string;
326
+ paymentLinkOrigin?: PaymentLinkOrigin;
277
327
  createdAt?: string;
278
328
  updatedAt?: string;
279
329
  }
330
+
331
+ type PaymentLinkStatus = 'pending' | 'active' | 'paid' | 'failed' | 'canceled' | 'expired' | 'stopped' | string;
332
+ type PaymentLinkType = 'default' | 'fixed' | 'subscription' | 'donation' | string;
333
+ type PaymentLinkOrigin = 'pabilo' | 'api' | string;
280
334
  ```
281
335
 
282
336
  ---
283
337
 
284
338
  ### `paymentLinks.getInfo(id): Promise<PaymentLink>`
285
339
 
286
- Fetches current state of a payment link (status, amount, etc.).
340
+ Fetches current state of a payment link.
287
341
 
288
342
  ```typescript
289
343
  const link = await pabilo.paymentLinks.getInfo('69d0083b691af50b78e07921');
290
344
 
291
- console.log(link.status); // 'paid'
292
- console.log(link.amount); // 4000
293
- console.log(link.createdAt); // ISO date string
345
+ console.log(link.status); // 'paid'
346
+ console.log(link.statusDetail); // string — reason for current status
347
+ console.log(link.amount);
348
+ console.log(link.createdAt);
294
349
  ```
295
350
 
296
- | Parameter | Type | Description |
297
- |---|---|---|
298
- | `id` | `string` | The `PaymentLink.id` |
299
-
300
351
  ---
301
352
 
302
353
  ### `paymentLinks.isPaid(id): Promise<boolean>`
303
354
 
304
- Convenience method — returns `true` if the payment link's status is `'paid'`.
355
+ Returns `true` if the payment link's status is `'paid'`.
305
356
 
306
357
  ```typescript
307
- const paid = await pabilo.paymentLinks.isPaid('69d0083b691af50b78e07921');
358
+ const paid = await pabilo.paymentLinks.isPaid(link.id);
308
359
 
309
360
  if (paid) {
310
361
  // fulfill the order
311
362
  }
312
363
  ```
313
364
 
314
- | Parameter | Type | Description |
315
- |---|---|---|
316
- | `id` | `string` | The `PaymentLink.id` |
317
-
318
- > Internally calls `getInfo()` and checks `status === 'paid'`.
319
-
320
365
  ---
321
366
 
322
367
  ### `paymentLinks.update(id, req): Promise<PaymentLink>`
323
368
 
324
- Updates a payment link's amount, description, redirect URL, or currency.
369
+ Updates a payment link's amount or description.
325
370
 
326
371
  ```typescript
327
- const updated = await pabilo.paymentLinks.update('69d0083b691af50b78e07921', {
372
+ const updated = await pabilo.paymentLinks.update(link.id, {
328
373
  amount: 5000,
329
374
  description: 'Orden actualizada',
330
- redirectUrl: 'https://myapp.com/nueva-ruta',
331
- currency: 'VES',
332
375
  });
333
-
334
- console.log(updated.amount); // 5000
335
376
  ```
336
377
 
337
- **Request fields (all optional):**
338
-
339
- | Field | Type | Description |
340
- |---|---|---|
341
- | `amount` | `number` | New amount |
342
- | `description` | `string` | New description |
343
- | `redirectUrl` | `string` | New redirect URL |
344
- | `currency` | `string` | New currency code |
345
-
346
378
  ---
347
379
 
348
380
  ## `pabilo.payments`
349
381
 
350
382
  ### `payments.verify(userBankId, req): Promise<VerifyPaymentResult>`
351
383
 
352
- Checks whether a specific bank transfer exists in a connected bank account. Used to confirm that a customer's Pago Móvil transfer matches an expected payment.
384
+ Checks whether a specific bank transfer exists in a connected bank account.
353
385
 
354
386
  ```typescript
355
387
  const result = await pabilo.payments.verify(bank.id, {
356
388
  amount: 4000,
357
389
  bankReference: '12345678',
358
- movementType: 'GENERIC', // optional, defaults to 'GENERIC'
390
+ movementType: 'GENERIC', // 'GENERIC' | 'MOVIL_PAY' | 'TRANSFER' | 'C2P'
359
391
  });
360
392
 
361
393
  if (result.found) {
362
- console.log(result.isNew); // true if first time this reference was seen
394
+ console.log(result.isNew);
363
395
  console.log(result.data.credit_cost);
364
- console.log(result.data.is_new);
365
396
 
366
397
  const payment = result.data.user_bank_payment;
367
398
  if (payment) {
368
399
  console.log(payment.id);
369
400
  console.log(payment.amount);
370
- console.log(payment.status); // 'paid'
401
+ console.log(payment.status); // 'pending' | 'paid' | 'failed'
371
402
  console.log(payment.bank_reference_id);
372
403
  console.log(payment.payment_params.fecha_pago);
373
404
  console.log(payment.payment_params.banco_origen);
@@ -378,20 +409,17 @@ if (result.found) {
378
409
  if (result.reason === 'BANK_NOT_AVAILABLE') {
379
410
  // bank is offline or credentials expired
380
411
  }
381
- if (result.reason === 'PAYMENT_NOT_FOUND') {
382
- // transfer does not exist or does not match
383
- }
384
412
  }
385
413
  ```
386
414
 
387
- **Request fields:**
415
+ **`movementType` values:**
388
416
 
389
- | Field | Type | Required | Description |
390
- |---|---|---|---|
391
- | `userBankId` (first arg) | `string` | yes | ID of the bank account to search |
392
- | `amount` | `number` | yes | Expected transfer amount |
393
- | `bankReference` | `string` | yes | Bank transfer reference number |
394
- | `movementType` | `string` | no | Defaults to `'GENERIC'` |
417
+ | Value | Description |
418
+ |---|---|
419
+ | `'GENERIC'` | Default any movement type (default) |
420
+ | `'MOVIL_PAY'` | Pago Móvil |
421
+ | `'TRANSFER'` | Bank transfer |
422
+ | `'C2P'` | Cuenta a Persona (C2P) |
395
423
 
396
424
  **Returns:** `VerifyPaymentResult` — a discriminated union on `found`:
397
425
 
@@ -399,46 +427,59 @@ if (result.found) {
399
427
  type VerifyPaymentResult =
400
428
  | { found: false; reason: 'BANK_NOT_AVAILABLE' | 'PAYMENT_NOT_FOUND' }
401
429
  | { found: true; isNew: boolean; data: PaymentData };
430
+ ```
402
431
 
403
- interface PaymentData {
404
- is_new: boolean;
405
- credit_cost: number;
406
- user_bank_payment?: UserBankPayment;
407
- user_credits_total?: number;
408
- user_credits_total_in_usd?: number;
432
+ > The API returns HTTP 200 for `BANK_NOT_AVAILABLE` and `PAYMENT_NOT_FOUND`. The SDK handles this transparently — these cases are never thrown as errors.
433
+
434
+ ---
435
+
436
+ ## Webhooks
437
+
438
+ When a payment link is paid, the API sends a `POST` to the `webhookUrl` with the following payload. Import `PaymentLinkWebhookPayload` to type your webhook handler:
439
+
440
+ ```typescript
441
+ import type { PaymentLinkWebhookPayload } from '@pabilo/sdk';
442
+
443
+ // Next.js App Router
444
+ export async function POST(req: Request) {
445
+ const payload: PaymentLinkWebhookPayload = await req.json();
446
+
447
+ console.log(payload.payment_link_id);
448
+ console.log(payload.status); // 'paid'
449
+ console.log(payload.credit_balance);
450
+
451
+ const payment = payload.user_bank_payment;
452
+ if (payment) {
453
+ console.log(payment.amount);
454
+ console.log(payment.bank_reference_id);
455
+ console.log(payment.payment_params.fecha_pago);
456
+ }
457
+
458
+ return Response.json({ ok: true });
409
459
  }
460
+ ```
410
461
 
411
- interface UserBankPayment {
462
+ **`PaymentLinkWebhookPayload` shape:**
463
+
464
+ ```typescript
465
+ interface PaymentLinkWebhookPayload {
412
466
  id: string;
413
- amount: number;
414
- status: string;
415
- user_id: string;
416
- user_bank_id: string;
417
- bank_reference_id: string;
418
- confirmed_status: boolean;
419
- credit_cost: number;
420
467
  created_at: string;
421
468
  updated_at: string;
422
- payment_params: {
423
- amount: number;
424
- cedula_pagador: string | null;
425
- telefono_pagador: string;
426
- fecha_pago: string;
427
- banco_origen: string;
428
- cuenta_pagador: string;
429
- invoice_number: string;
430
- movement_type: string;
431
- };
469
+ payment_link_id: string;
470
+ status: PaymentLinkStatus;
471
+ payment_link?: PaymentLink;
472
+ user_bank_payment?: UserBankPayment;
473
+ credit_balance: number;
474
+ metadata: Array<{ key: string; value: string }>;
432
475
  }
433
476
  ```
434
477
 
435
- > The API returns HTTP 200 for `BANK_NOT_AVAILABLE` and `PAYMENT_NOT_FOUND`. The SDK handles this transparently — these cases are never thrown as errors.
436
-
437
478
  ---
438
479
 
439
480
  ## Error handling
440
481
 
441
- All methods throw `PabiloError` on API errors (non-2xx HTTP responses) or network failures.
482
+ All methods throw `PabiloError` on API errors or network failures.
442
483
 
443
484
  ```typescript
444
485
  import { PabiloClient, PabiloError } from '@pabilo/sdk';
@@ -447,10 +488,10 @@ try {
447
488
  const link = await pabilo.paymentLinks.create({ ... });
448
489
  } catch (err) {
449
490
  if (err instanceof PabiloError) {
450
- console.error(err.code); // PabiloErrorCode string
451
- console.error(err.message); // human-readable message from the API
452
- console.error(err.raw); // raw API response body
453
- console.error(err.status); // HTTP status code (if available)
491
+ console.error(err.code); // PabiloErrorCode string
492
+ console.error(err.message); // human-readable message from the API
493
+ console.error(err.statusCode); // HTTP status code
494
+ console.error(err.raw); // raw API response body
454
495
  }
455
496
  }
456
497
  ```
@@ -461,30 +502,42 @@ try {
461
502
  |---|---|
462
503
  | `BAD_REQUEST` | Invalid request body or parameters |
463
504
  | `UNAUTHORIZED` | API key is missing or invalid |
505
+ | `FORBIDDEN` | Action not permitted |
464
506
  | `NOT_FOUND` | Resource not found |
465
507
  | `USER_BANK_ALREADY_EXISTS` | Bank account is already connected |
466
- | `INTERNAL_SERVER_ERROR` | API server error |
508
+ | `USER_BANCK_BAD_PASSWORD` | Wrong bank portal credentials |
509
+ | `USER_BANCK_PASSWORD_EXPIRED` | Bank portal password expired |
510
+ | `NOT_ENOUGH_CREDITS` | Insufficient credits in the account |
511
+ | `PLAN_IS_NOT_ACTIVE` | Account plan is inactive |
512
+ | `REQUEST_LIMIT_REACHED` | Plan request limit exceeded |
513
+ | `BANK_ACCOUNT_LIMIT_REACHED` | Plan bank account limit exceeded |
514
+ | `BANK_NOT_AVAILABLE` | Bank is temporarily offline |
515
+ | `BANK_TEMPORARILY_INACTIVE` | Bank is temporarily disabled |
516
+ | `BANK_TOO_MANY_REQUESTS` | Rate limit from the bank |
517
+ | `PAYMENT_NOT_FOUND` | Transfer reference not found |
518
+ | `PAYMENT_ALREADY_EXISTS` | Transfer already verified |
519
+ | `INTERNAL_ERROR` | API server error |
467
520
  | `NETWORK_ERROR` | Request could not reach the API |
468
- | `REQUEST_FAILED` | HTTP error with no specific code |
469
521
 
470
522
  ---
471
523
 
472
524
  ## Testing with BANK_TEST
473
525
 
474
- Use `BANK_TEST` to test the full payment flow without connecting a real bank. It has a pre-configured payment with reference `67890`.
526
+ Use `BANK_TEST` to test the full payment flow without connecting a real bank. Reference `67890` always returns a found payment.
475
527
 
476
528
  ```typescript
477
529
  // 1. Create test bank
478
530
  const bank = await pabilo.bankAccounts.create({ bankProvider: 'BANK_TEST' });
479
531
 
480
- // 2. Create a payment link using the test bank
532
+ // 2. Create a payment link
481
533
  const link = await pabilo.paymentLinks.create({
482
534
  amount: 100,
483
535
  description: 'Test payment',
484
536
  userBankId: bank.id,
537
+ webhookUrl: 'https://myapp.com/webhook',
485
538
  });
486
539
 
487
- // 3. Verify the test payment reference
540
+ // 3. Verify the test payment
488
541
  const result = await pabilo.payments.verify(bank.id, {
489
542
  amount: 0,
490
543
  bankReference: '67890',
@@ -536,15 +589,18 @@ export async function POST(req: Request) {
536
589
  ```
537
590
 
538
591
  ```typescript
539
- // app/api/webhook/pabilo/route.ts — poll-based alternative to webhooks
592
+ // app/api/webhook/pabilo/route.ts
593
+ import type { PaymentLinkWebhookPayload } from '@pabilo/sdk';
540
594
  import { pabilo } from '@/lib/pabilo';
541
595
 
542
- export async function GET(req: Request) {
543
- const { searchParams } = new URL(req.url);
544
- const linkId = searchParams.get('linkId')!;
596
+ export async function POST(req: Request) {
597
+ const payload: PaymentLinkWebhookPayload = await req.json();
598
+
599
+ if (payload.status === 'paid') {
600
+ // fulfill the order linked to payload.payment_link_id
601
+ }
545
602
 
546
- const paid = await pabilo.paymentLinks.isPaid(linkId);
547
- return Response.json({ paid });
603
+ return Response.json({ ok: true });
548
604
  }
549
605
  ```
550
606
 
@@ -552,10 +608,8 @@ export async function GET(req: Request) {
552
608
 
553
609
  ## Advanced: custom HTTP client
554
610
 
555
- The SDK accepts an `IHttpClient` implementation for logging, retries, or proxying requests.
556
-
557
611
  ```typescript
558
- import { PabiloClient, FetchHttpClient, type IHttpClient, type RequestOptions } from '@pabilo/sdk';
612
+ import { PabiloClient, FetchHttpClient, type RequestOptions } from '@pabilo/sdk';
559
613
 
560
614
  class LoggingHttpClient extends FetchHttpClient {
561
615
  async request<T>(opts: RequestOptions): Promise<T> {
@@ -566,11 +620,11 @@ class LoggingHttpClient extends FetchHttpClient {
566
620
 
567
621
  const pabilo = new PabiloClient({
568
622
  apiKey: 'YOUR_API_KEY',
569
- httpClient: new LoggingHttpClient({ baseUrl: 'https://api.pabilo.app', apiKey: 'YOUR_API_KEY' }),
623
+ httpClient: new LoggingHttpClient(),
570
624
  });
571
625
  ```
572
626
 
573
- Custom base URL (e.g. staging):
627
+ Custom base URL:
574
628
 
575
629
  ```typescript
576
630
  const pabilo = new PabiloClient({
@@ -591,9 +645,11 @@ import type {
591
645
  // Resources
592
646
  User,
593
647
  Plan,
648
+ PlanBenefit,
594
649
  UserBank,
595
650
  BankAccountEntry,
596
651
  PaymentLink,
652
+ PaymentLinksPage,
597
653
  PaymentData,
598
654
  UserBankPayment,
599
655
  PaymentParams,
@@ -606,15 +662,23 @@ import type {
606
662
  UserBankMetadataEntry,
607
663
  CreatePaymentLinkRequest,
608
664
  UpdatePaymentLinkRequest,
665
+ ListPaymentLinksRequest,
609
666
  VerifyPaymentRequest,
610
667
 
611
- // Results
668
+ // Results & Webhooks
612
669
  VerifyPaymentResult,
613
-
614
- // Enums / literals
615
- PaymentLinkStatus, // 'pending' | 'paid' | 'active' | 'expired' | 'cancelled'
616
- PaymentLinkType, // 'default' | 'fixed'
617
- BankProvider,
670
+ PaymentLinkWebhookPayload,
671
+
672
+ // Literals / enums
673
+ PaymentLinkStatus, // 'pending' | 'active' | 'paid' | 'failed' | 'canceled' | 'expired' | 'stopped'
674
+ PaymentLinkType, // 'default' | 'fixed' | 'subscription' | 'donation'
675
+ PaymentLinkOrigin, // 'pabilo' | 'api'
676
+ BankProvider, // 'VE_BAN' | 'VE_BAN_EMP_V2' | ...
677
+ MovementType, // 'GENERIC' | 'MOVIL_PAY' | 'TRANSFER' | 'C2P'
678
+ UserBankPaymentStatus,// 'pending' | 'paid' | 'failed'
679
+ UserType, // 'user' | 'admin' | 'commerce' | ...
680
+ PlanType, // 'credit' | 'unlimited' | 'counter'
681
+ PlanPeriod, // 'month' | 'six_months' | 'year'
618
682
  AccountType,
619
683
  PabiloErrorCode,
620
684