@timbro/payments 0.1.0-next.1 → 0.1.0-next.2

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
@@ -1,6 +1,12 @@
1
1
  # `@timbro/payments`
2
2
 
3
- Node 24 ESM SDK for merchant Payments and their payment-linked fiscal documents.
3
+ Node 24 ESM SDK for merchant Payments, their payment-linked fiscal documents, and the merchant
4
+ business that onboards them.
5
+
6
+ `apiKey` takes either merchant key. A secret key (`sk_test_…` or `sk_live_…`) creates and reads
7
+ Payments; an administrator key, which the owner creates and names in the Workspace business
8
+ settings, also administers the business and its Merchant Accounts. Keys are additive: creating another one,
9
+ of either kind, never retires the keys you already use.
4
10
 
5
11
  Each Payment create request supplies one immutable `source` coordinate and one tagged `sale` snapshot. `source.id` and `source.version` remain stable across credential rotation and retries; `idempotencyKey` remains the HTTP command retry key.
6
12
 
@@ -13,7 +19,7 @@ Use `amount_only` when the adapter has only a payable amount. This variant canno
13
19
  ```ts
14
20
  import { createTimbroPayments } from "@timbro/payments";
15
21
 
16
- const timbro = createTimbroPayments({ secretKey: process.env.TIMBRO_PAYMENTS_SECRET_KEY });
22
+ const timbro = createTimbroPayments({ apiKey: process.env.TIMBRO_PAYMENTS_SECRET_KEY });
17
23
  const payment = await timbro.payments.create({
18
24
  idempotencyKey: "create-order-123",
19
25
  source: { id: "odoo:pos.order:123", version: "7" },
@@ -166,13 +172,96 @@ CardNet Ztrans full refunds are implemented for test mode with deterministic rec
166
172
 
167
173
  Before collecting the rest of a merchant's onboarding details, verify its RNC
168
174
  against the current DGII directory snapshot. The operation is read-only and
169
- returns the canonical taxpayer name for the form to use. It currently requires
170
- an existing merchant secret key; tenant bootstrap and human administrator
171
- authentication are separate onboarding work:
175
+ returns the canonical taxpayer name for the form to use. Either merchant key
176
+ calls it:
172
177
 
173
178
  ```ts
174
179
  const verification = await timbro.merchantOnboarding.verifyRnc({ rnc: "101000155" });
175
180
  // verification.legalName is the Directory's registered name.
176
181
  ```
177
182
 
183
+ ## Onboard the merchant business
184
+
185
+ The business belongs to the key's tenant, so no call names it. Claiming the business and handing
186
+ over the certificate file stay with the person who holds them; everything else is one resource.
187
+ Read it, act on the first requirement your integration owns, and read it again:
188
+
189
+ ```ts
190
+ const admin = createTimbroPayments({ apiKey: process.env.TIMBRO_ADMIN_KEY });
191
+
192
+ let business = await admin.merchantBusiness.retrieve();
193
+ business = await admin.merchantBusiness.update({
194
+ capabilities: { electronicInvoicing: { requested: true } },
195
+ fiscalDetails: {
196
+ commercialName: "Café Duarte",
197
+ address: "Calle El Conde 101",
198
+ location: { municipalityCode: "320100" },
199
+ phone: "+18095550142",
200
+ defaultIncomeType: "01",
201
+ },
202
+ });
203
+ business = await admin.merchantBusiness.importSigningCertificate({
204
+ certificateP12Base64: p12.toString("base64"),
205
+ password: certificatePassword,
206
+ });
207
+ // Timbro sends the TesteCF document itself; poll until DGII answers.
208
+ business = await admin.merchantBusiness.retrieve();
209
+ if (business.capabilities.electronicInvoicing.status === "active") {
210
+ const { credential, fiscalOrigin } = await admin.merchantBusiness.issueSandboxCredential({
211
+ idempotencyKey: "sandbox-credential-1",
212
+ });
213
+ }
214
+ ```
215
+
216
+ Each entry of `business.requirements` names its `owner`: `merchant` entries are yours to resolve,
217
+ and `field` points into the representation when a field answers it. `dgii` and `timbro` entries
218
+ wait, `provider` entries wait on the acquirer, and `operator` entries need Timbro support. `update` replaces each member it carries, and
219
+ an `expectedRevision` refuses a stale write with `merchant_business_revision_conflict`.
220
+ Electronic invoicing onboards against DGII's TesteCF environment only. The certificate import is
221
+ the one call that carries the PKCS#12 archive; send it only from a machine that already holds the
222
+ file, and do not resend it once `fiscalSetup.signingCertificate.sha256` matches.
223
+ `retryTestFiscalDocument()` sends a new TesteCF document only when none is processing or
224
+ accepted. `issueSandboxCredential` returns the ERP credential once and retires the one issued
225
+ before it; the same `idempotencyKey` replays it.
226
+
227
+ ## Every published operation
228
+
229
+ `timbro.client` is the typed low-level client for every operation in the published document,
230
+ with the same key and transport. Requests, responses, and Problem bodies are typed from the
231
+ generated `paths`, `components`, and `operations`, which the package also exports:
232
+
233
+ ```ts
234
+ import { createTimbroPayments, type components } from "@timbro/payments";
235
+
236
+ const { data, error, response } = await timbro.client.POST("/v1/api_keys/rotate", {
237
+ params: { header: { "idempotency-key": "rotate-2026-09" } },
238
+ });
239
+ if (error !== undefined) {
240
+ console.error(response.status, error.code);
241
+ }
242
+ type Requirement = components["schemas"]["MerchantBusinessRequirement"];
243
+ ```
244
+
245
+ The facade covers every published merchant operation except `rotateApiKey`,
246
+ `createPreCreationJourneyRequest`, and `chooseFiscalDocument`, which the client reaches directly.
247
+
248
+ ## From a terminal
249
+
250
+ The published document is served at `https://api.timbro.dev/openapi.json`, so a
251
+ generic OpenAPI client needs nothing from Timbro. With [Restish](https://rest.sh), register the
252
+ API once and pass a test administrator key on each call, from an environment variable rather than
253
+ your shell history:
254
+
255
+ ```sh
256
+ restish api configure timbro https://api.timbro.dev
257
+ restish timbro retrieve-merchant-business -H "Authorization: Bearer $TIMBRO_ADMIN_KEY"
258
+ restish timbro update-merchant-business -H "Authorization: Bearer $TIMBRO_ADMIN_KEY" \
259
+ 'capabilities.electronicInvoicing.requested: true'
260
+ jq -n --arg p12 "$(base64 -w0 certificate.p12)" --arg password "$CERTIFICATE_PASSWORD" \
261
+ '{certificateP12Base64: $p12, password: $password}' |
262
+ restish timbro import-merchant-business-signing-certificate -H "Authorization: Bearer $TIMBRO_ADMIN_KEY"
263
+ ```
264
+
265
+ Restish names each command after the operation ID in kebab case. Timbro ships no CLI of its own.
266
+
178
267
  `@timbro/payments` serves payment consumers. `@timbro/sdk` is the consumer-neutral fiscal SDK for ERPs, POS systems, payment systems, and other direct fiscal integrations. Neither package depends on or re-exports the other.