@dime-technology/dime-js-sdk 1.3.1 → 1.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.
package/README.md CHANGED
@@ -69,15 +69,20 @@ them, in a `filters` object). All amounts are returned as strings to avoid float
69
69
 
70
70
  | Property | Endpoints |
71
71
  | ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
72
- | `dime.transactions` | chargeCard, chargeAch, tokenizeCard, refund, void, show, list |
72
+ | `dime.transactions` | chargeCard, chargeAch, tokenizeCard, authorize, capture, refund, void, show, list |
73
73
  | `dime.customers` | list, show, create, update, delete |
74
74
  | `dime.paymentMethods` | list, show, create, update, delete |
75
- | `dime.merchants` | list, show, create, update, getFormLink |
75
+ | `dime.merchants` | list, show, create, update, getFormLink, applicationStatus |
76
76
  | `dime.addresses` | list, show, create, update, delete |
77
77
  | `dime.deposits` | list, listWithTransactions, show |
78
78
  | `dime.recurringPayments` | list, show, create, edit, pause, cancel, activate, delete |
79
79
  | `dime.invoices` | list, show, create, update, delete, send, markSent, void, duplicate, pay, getLink, addLineItem, updateLineItem, deleteLineItem, listItems, createItem |
80
80
  | `dime.recurringInvoices` | list, show, create, cancel |
81
+ | `dime.chargebacks` | list, show |
82
+ | `dime.documents` | upload, list |
83
+ | `dime.funds` | balance, transactions, release |
84
+ | `dime.subscriptionPlans` | list, show, create, edit, delete, publish, archive, unarchive, subscribe |
85
+ | `dime.subscriptions` | list, show, pause, resume, cancel |
81
86
 
82
87
  ### Transactions
83
88
 
@@ -123,6 +128,40 @@ await dime.transactions.void('000010', 'CC', 123456)
123
128
  const txn = await dime.transactions.show('000010', { transaction_info_id: 123456 })
124
129
  ```
125
130
 
131
+ #### Authorize and capture
132
+
133
+ `authorize()` places a hold on a card without moving money; `capture()` collects it. The returned
134
+ `transactionNumber` is your handle on the hold. An authorization is captured once — capturing less
135
+ than the full amount settles that and releases the rest — so capture the true final amount, and
136
+ capture promptly (typically within 24 hours), since the issuer releases an uncaptured hold on its
137
+ own schedule.
138
+
139
+ ```ts
140
+ const auth = await dime.transactions.authorize('000010', {
141
+ amount: '100.00',
142
+ token: 'tok_abc123', // or raw card fields, as for chargeCard
143
+ })
144
+
145
+ await dime.transactions.capture('000010', auth.transactionNumber!) // full amount
146
+ await dime.transactions.capture('000010', auth.transactionNumber!, '80.00') // or part of it
147
+
148
+ // Release the hold instead of capturing it
149
+ await dime.transactions.void('000010', 'CC', auth.transactionNumber!)
150
+ ```
151
+
152
+ ### Merchant onboarding status
153
+
154
+ Follow up an application sent with `getFormLink()`. `boarded` is the ground truth for "can they
155
+ take money"; while `status` is `underwriting`, read `applicationStatus` — only `needs_documents`
156
+ asks anything of the merchant. Prefer the `application_status_changed` webhook to polling.
157
+
158
+ ```ts
159
+ const onboarding = await dime.merchants.applicationStatus('000010')
160
+ onboarding.status // 'underwriting'
161
+ onboarding.applicationStatus // 'needs_documents'
162
+ onboarding.boarded // false
163
+ ```
164
+
126
165
  ### Customers, payment methods, addresses
127
166
 
128
167
  ```ts
@@ -299,6 +338,126 @@ await dime.recurringInvoices.cancel('000010', template.id!)
299
338
  const page = await dime.recurringInvoices.list('000010', { status: 'Active' })
300
339
  ```
301
340
 
341
+ ### Chargebacks and documents
342
+
343
+ Chargebacks come from the processor's once-daily file, so they reflect the latest import rather
344
+ than live dispute activity. Pair these calls with the `chargeback_*` webhooks and use them to
345
+ reconcile. They need the `chargeback:read` ability.
346
+
347
+ ```ts
348
+ const page = await dime.chargebacks.list('000010', {
349
+ start_date: '2026-04-01 00:00:00',
350
+ end_date: '2026-04-30 23:59:59',
351
+ representment_status: 'New', // optional
352
+ })
353
+
354
+ const chargeback = await dime.chargebacks.show('000010', '1134722723')
355
+ chargeback.chargebackAmount // '391.48'
356
+ chargeback.representmentDate // deadline for evidence
357
+ ```
358
+
359
+ `documents.upload()` sends underwriting paperwork, identity verification and chargeback evidence
360
+ — up to 10 PDF, JPG, PNG, DOC, DOCX or RTF files of 9 MB or less per call. Pass `Blob`/`File`
361
+ objects, or raw bytes with a file name. It is the one `multipart/form-data` request in the API;
362
+ the SDK builds the form for you. Files are stored independently, so check `failed` and re-send
363
+ only those.
364
+
365
+ ```ts
366
+ import { readFile } from 'node:fs/promises'
367
+
368
+ const result = await dime.documents.upload(
369
+ '000010',
370
+ 'RetrievalRequest', // Verification | FraudHolds | Underwriting | RetrievalRequest
371
+ [{ content: await readFile('receipt.pdf'), filename: 'receipt.pdf' }],
372
+ chargeback.transactionInfoId, // optional: attach as evidence to this chargeback
373
+ )
374
+ result.failed // [] when everything stored
375
+
376
+ const documents = await dime.documents.list('000010', { doc_type: 'RetrievalRequest' })
377
+ ```
378
+
379
+ Uploading does not forward a document to the processor; our team reviews it and does that.
380
+ `sentToProcessorAt` is set once they have.
381
+
382
+ ### Held funds
383
+
384
+ For merchants on a tier that holds their balance rather than sweeping it to their bank (others get
385
+ a 422). Reading needs `funds:read`; releasing needs `funds:release` and an affiliate key.
386
+
387
+ ```ts
388
+ const balance = await dime.funds.balance('000010')
389
+ balance.releasable // '5172.72' — what a release is checked against
390
+
391
+ const { transactions } = await dime.funds.transactions('000010')
392
+
393
+ // Release by amount, or by transaction_info_ids (all or nothing)
394
+ const result = await dime.funds.release('000010', 'payout-2026-10-06-0001', { amount: '1500.00' })
395
+ await dime.funds.release('000010', 'payout-2026-10-06-0002', {
396
+ transaction_info_ids: transactions.map((t) => t.transactionInfoId!),
397
+ })
398
+
399
+ result.release.status // 'released' | 'failed' | 'unknown'
400
+ ```
401
+
402
+ Use a fresh idempotency key per intended release and **reuse it when retrying**: a release that
403
+ timed out may still have gone through, and the same key returns the original instead of sending the
404
+ money twice. Always check `release.status` — a declined (`failed`) release is returned, not thrown.
405
+ Requests that release nothing (an ineligible transaction, more than is releasable, a reused key, a
406
+ release already in flight) throw an `ApiException`; `getResponseBody()` carries the detail.
407
+
408
+ ### Subscription plans and subscriptions
409
+
410
+ A plan is a recurring bundle of line items. It starts as a draft, is published to take
411
+ subscribers, and is archived to stop new ones. Subscribers keep the snapshot they signed up to, so
412
+ editing or archiving a plan never changes an existing subscription.
413
+
414
+ ```ts
415
+ const plan = await dime.subscriptionPlans.create('000010', {
416
+ name: 'Monthly Membership',
417
+ recurrence_schedule: 'Monthly', // Weekly | Biweekly | FirstFifteenth | Monthly | Yearly
418
+ allow_public: true, // optional: list it in the public catalog
419
+ lines: [{ item_id: 96, name: 'Membership', quantity: 1, unit_price: 25 }],
420
+ })
421
+
422
+ await dime.subscriptionPlans.publish('000010', plan.id!)
423
+ plan.publicUrl // hosted subscribe page
424
+
425
+ // Charge the first payment to a saved payment method and enroll the customer
426
+ const { subscriptionId } = await dime.subscriptionPlans.subscribe(
427
+ '000010',
428
+ plan.id!,
429
+ customer.uuid!,
430
+ pm.id!,
431
+ )
432
+
433
+ // edit() replaces the plan wholesale — send every field, not just what changed
434
+ await dime.subscriptionPlans.edit('000010', plan.id!, {
435
+ name: 'Membership',
436
+ recurrence_schedule: 'Monthly',
437
+ lines: [{ item_id: 96, name: 'Membership', quantity: 1, unit_price: 30 }],
438
+ })
439
+ await dime.subscriptionPlans.archive('000010', plan.id!)
440
+ await dime.subscriptionPlans.unarchive('000010', plan.id!) // back to draft
441
+ await dime.subscriptionPlans.delete('000010', plan.id!) // only with no subscribers
442
+
443
+ const plans = await dime.subscriptionPlans.list('000010', 'active') // draft | active | archived
444
+ ```
445
+
446
+ ```ts
447
+ const page = await dime.subscriptions.list('000010', {
448
+ status: 'Active', // Active | Failed | Paused | Cancelled | Ended
449
+ customer_uuid: customer.uuid, // optional
450
+ })
451
+
452
+ const subscription = await dime.subscriptions.show('000010', subscriptionId!)
453
+ subscription.nextRunDate
454
+ subscription.items // the line items snapshotted at subscribe time
455
+
456
+ await dime.subscriptions.pause('000010', subscriptionId!, '2026-12-01') // omit the date to pause indefinitely
457
+ await dime.subscriptions.resume('000010', subscriptionId!)
458
+ await dime.subscriptions.cancel('000010', subscriptionId!)
459
+ ```
460
+
302
461
  ## Pagination
303
462
 
304
463
  List endpoints return a `CursorPage`. Iterate one page, walk pages manually, or stream every
@@ -366,8 +525,9 @@ try {
366
525
 
367
526
  ## Notes
368
527
 
369
- - **GET requests carry a JSON body.** The Dime API expects read parameters in the request body
370
- even for `GET` endpoints; the SDK handles this transparently.
528
+ - **GET parameters travel in the query string.** The Dime API reads the same `{ data, filters }`
529
+ envelope from a JSON body or from bracketed query parameters (`data[sid]=…`). Fetch forbids a
530
+ body on `GET`, so the SDK sends reads as query parameters; you never build either by hand.
371
531
  - **No API versioning.** Endpoints live under `/api` with no version prefix.
372
532
  - **Browser use:** API tokens should generally not be exposed in browser environments. This SDK
373
533
  is designed primarily for server-side use (Node.js, Next.js API routes, etc.).