@peable.to/contracts 2.0.0 → 3.1.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.
Files changed (44) hide show
  1. package/dist/cjs/resources/catalog/index.js +1 -5
  2. package/dist/cjs/resources/checkout/checkoutSessions.js +0 -4
  3. package/dist/cjs/resources/events/events.js +1 -32
  4. package/dist/cjs/resources/events/webhookDeliveries.js +1 -1
  5. package/dist/cjs/resources/events/webhookEndpoints.js +1 -1
  6. package/dist/cjs/resources/payments/disputes.js +16 -0
  7. package/dist/cjs/resources/payments/refunds.js +46 -11
  8. package/dist/cjs/vocabulary/catalog.js +1 -17
  9. package/dist/cjs/vocabulary/errors.js +0 -13
  10. package/dist/cjs/vocabulary/events.js +5 -1
  11. package/dist/esm/resources/catalog/index.js +1 -5
  12. package/dist/esm/resources/checkout/checkoutSessions.js +0 -4
  13. package/dist/esm/resources/events/events.js +0 -31
  14. package/dist/esm/resources/events/webhookDeliveries.js +1 -1
  15. package/dist/esm/resources/events/webhookEndpoints.js +1 -1
  16. package/dist/esm/resources/payments/disputes.js +16 -0
  17. package/dist/esm/resources/payments/refunds.js +46 -11
  18. package/dist/esm/vocabulary/catalog.js +0 -16
  19. package/dist/esm/vocabulary/errors.js +0 -13
  20. package/dist/esm/vocabulary/events.js +5 -1
  21. package/dist/types/resources/catalog/index.d.ts +1 -851
  22. package/dist/types/resources/checkout/checkoutSessions.d.ts +13 -61
  23. package/dist/types/resources/checkout/index.d.ts +10 -46
  24. package/dist/types/resources/connect/balance.d.ts +5 -5
  25. package/dist/types/resources/connect/index.d.ts +4 -4
  26. package/dist/types/resources/connect/payouts.d.ts +2 -2
  27. package/dist/types/resources/events/events.d.ts +0 -22
  28. package/dist/types/resources/events/index.d.ts +7 -15
  29. package/dist/types/resources/events/webhookDeliveries.d.ts +0 -3
  30. package/dist/types/resources/events/webhookEndpoints.d.ts +11 -16
  31. package/dist/types/resources/payments/disputes.d.ts +35 -0
  32. package/dist/types/resources/payments/index.d.ts +82 -10
  33. package/dist/types/resources/payments/paymentIntents.d.ts +10 -10
  34. package/dist/types/resources/payments/refunds.d.ts +56 -5
  35. package/dist/types/resources/payments/testHelpers.d.ts +1 -1
  36. package/dist/types/resources/tax/index.d.ts +1 -1
  37. package/dist/types/resources/tax/registrations.d.ts +2 -2
  38. package/dist/types/vocabulary/catalog.d.ts +0 -9
  39. package/dist/types/vocabulary/errors.d.ts +0 -13
  40. package/dist/types/vocabulary/events.d.ts +5 -2
  41. package/package.json +1 -1
  42. package/dist/cjs/resources/catalog/billing.js +0 -753
  43. package/dist/esm/resources/catalog/billing.js +0 -750
  44. package/dist/types/resources/catalog/billing.d.ts +0 -1723
@@ -17,7 +17,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  exports.catalogRoutes = exports.queryIdList = exports.queryFlag = exports.baseUnitAmountParam = void 0;
18
18
  // Contracts of this group: one module per resource, re-exported here, and
19
19
  // their routes concatenated into `catalogRoutes`.
20
- const billing_1 = require("./billing");
21
20
  const billingSettings_1 = require("./billingSettings");
22
21
  const coupons_1 = require("./coupons");
23
22
  const entitlements_1 = require("./entitlements");
@@ -26,7 +25,6 @@ const prices_1 = require("./prices");
26
25
  const products_1 = require("./products");
27
26
  const promotionCodes_1 = require("./promotionCodes");
28
27
  const testClocks_1 = require("./testClocks");
29
- __exportStar(require("./billing"), exports);
30
28
  __exportStar(require("./billingSettings"), exports);
31
29
  __exportStar(require("./coupons"), exports);
32
30
  __exportStar(require("./entitlements"), exports);
@@ -42,8 +40,7 @@ Object.defineProperty(exports, "queryFlag", { enumerable: true, get: function ()
42
40
  Object.defineProperty(exports, "queryIdList", { enumerable: true, get: function () { return shared_1.queryIdList; } });
43
41
  /**
44
42
  * The catalog (products, prices, coupons, promotion codes), entitlements, the
45
- * billing engine's platform objects (test clocks, billing settings, meters)
46
- * and the recurring billing transport (`/v1/billing/*`).
43
+ * billing engine's platform objects (test clocks, billing settings, meters).
47
44
  */
48
45
  exports.catalogRoutes = [
49
46
  ...products_1.productRoutes,
@@ -54,5 +51,4 @@ exports.catalogRoutes = [
54
51
  ...testClocks_1.testClockRoutes,
55
52
  ...billingSettings_1.billingSettingsRoutes,
56
53
  ...meters_1.meterRoutes,
57
- ...billing_1.billingRoutes,
58
54
  ];
@@ -4,7 +4,6 @@ exports.checkoutSessionRoutes = exports.expireCheckoutSessionTestHelperParams =
4
4
  const zod_1 = require("zod");
5
5
  const catalog_1 = require("../../vocabulary/catalog");
6
6
  const payments_1 = require("../../vocabulary/payments");
7
- const billing_1 = require("../catalog/billing");
8
7
  const objects_1 = require("../../common/objects");
9
8
  const envelopes_1 = require("../../common/envelopes");
10
9
  const objects_2 = require("../../common/objects");
@@ -183,9 +182,6 @@ exports.checkoutSessionPublicSchema = (0, objects_2.defineComponent)('CheckoutSe
183
182
  .string()
184
183
  .nullable()
185
184
  .describe("The card provider's PUBLIC key for this session's mode, so the payment fields can mount before the payment exists. `null` on FairCoin."),
186
- billing_quote: billing_1.billingFaircoinFxQuoteSchema
187
- .optional()
188
- .describe('FairCoin billing invoices: the frozen USD price and FAIR settlement quote.'),
189
185
  })
190
186
  .strict());
191
187
  // ---- Merchant create/update ---------------------------------------------------
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.eventRoutes = exports.WEBHOOK_EVENT_DESCRIPTIONS = exports.streamEventsQuery = exports.retrieveEventQuery = exports.listEventsQuery = exports.listEventsFilters = exports.eventSchema = exports.eventRequestSchema = exports.billingObservationSchema = void 0;
3
+ exports.eventRoutes = exports.WEBHOOK_EVENT_DESCRIPTIONS = exports.streamEventsQuery = exports.retrieveEventQuery = exports.listEventsQuery = exports.listEventsFilters = exports.eventSchema = exports.eventRequestSchema = void 0;
4
4
  exports.eventSchemaOf = eventSchemaOf;
5
5
  const zod_1 = require("zod");
6
6
  const envelopes_1 = require("../../common/envelopes");
@@ -16,36 +16,6 @@ const events_1 = require("../../vocabulary/events");
16
16
  * every matching webhook endpoint: a delivery's body and `GET /v1/events/:id`
17
17
  * are byte for byte the same object.
18
18
  */
19
- /**
20
- * The payload of `billing.observation.updated`: a wake-up, never paid or grant
21
- * authority. Re-read the owner-bound resource it names.
22
- */
23
- exports.billingObservationSchema = (0, objects_1.defineObject)('billing_observation', 'BillingObservation', zod_1.z
24
- .object({
25
- object: zod_1.z.literal('billing_observation'),
26
- livemode: primitives_1.livemode.describe('The mode of the billing cohort observed (ADR 0017).'),
27
- resource_kind: zod_1.z.enum(['subscription', 'invoice']),
28
- resource_id: zod_1.z.string().describe('The provider subscription or invoice observed.'),
29
- subscription_id: zod_1.z
30
- .string()
31
- .optional()
32
- .describe('Owner-scoped wake-up hint only; re-read the subscription before resolving a payer.'),
33
- revision: zod_1.z.number().int().describe('The observation revision; later revisions are newer.'),
34
- observed_at: primitives_1.unixSeconds,
35
- })
36
- .strict(), {
37
- examples: [
38
- {
39
- object: 'billing_observation',
40
- livemode: false,
41
- resource_kind: 'subscription',
42
- resource_id: 'sub_1Q2w3E4r5T6y7U8i',
43
- subscription_id: 'sub_1Q2w3E4r5T6y7U8i',
44
- revision: 3,
45
- observed_at: 1793750400,
46
- },
47
- ],
48
- });
49
19
  /**
50
20
  * What caused an event, when an API request did (Stripe's `event.request`).
51
21
  * Both `null` for an event caused by something else — the chain watcher, the
@@ -242,7 +212,6 @@ exports.WEBHOOK_EVENT_DESCRIPTIONS = {
242
212
  'setup_intent.succeeded': 'A SetupIntent succeeded: its PaymentMethod is saved.',
243
213
  'setup_intent.setup_failed': 'A SetupIntent attempt failed.',
244
214
  'setup_intent.canceled': 'A SetupIntent was canceled.',
245
- 'billing.observation.updated': 'A recurring billing resource was observed to change. A wake-up only: re-read the resource.',
246
215
  'connected_account.updated': "A seller's connected account changed — its readiness, in practice.",
247
216
  'product.created': 'A Product was created.',
248
217
  'product.updated': 'A Product was updated; `previous_attributes` names what moved.',
@@ -26,7 +26,7 @@ exports.webhookDeliverySchema = (0, objects_1.defineObject)('webhook_delivery',
26
26
  delivered: zod_1.z.boolean(),
27
27
  last_status: zod_1.z
28
28
  .enum(events_1.WEBHOOK_DELIVERY_STATUSES)
29
- .describe('`pending`: will be attempted (`next_attempt_at`). `delivered`: terminal success. `failed`: the endpoint refused it (a 4xx, a blocked address) or was disabled first — never retried. `dead`: every attempt failed transiently for three days; it can be redelivered.'),
29
+ .describe('`pending`: will be attempted (`next_attempt_at`). `delivered`: terminal success. `failed`: the endpoint refused it (a 4xx, a blocked address), was disabled first, or its stored url breaks the registration rules — never retried. `dead`: every attempt failed transiently for three days; it can be redelivered.'),
30
30
  last_error: zod_1.z
31
31
  .string()
32
32
  .optional()
@@ -29,7 +29,7 @@ const endpointShape = {
29
29
  disabled_reason: zod_1.z
30
30
  .enum(events_1.WEBHOOK_ENDPOINT_DISABLED_REASONS)
31
31
  .nullable()
32
- .describe('`null` exactly when `status` is `enabled`. `delivery_failures`: every delivery failed for three days straight.'),
32
+ .describe('`null` exactly when `status` is `enabled`. `delivery_failures`: every delivery failed for three days straight. `url_refused`: the stored `url` breaks the registration rules, judged before every delivery; re-enable it with a `url` that passes.'),
33
33
  api_version: zod_1.z.string().describe('The wire version events are rendered with for this endpoint.'),
34
34
  metadata: primitives_1.metadata,
35
35
  created: primitives_1.unixSeconds,
@@ -7,6 +7,7 @@ const objects_1 = require("../../common/objects");
7
7
  const params_1 = require("../../common/params");
8
8
  const primitives_1 = require("../../common/primitives");
9
9
  const route_1 = require("../../route");
10
+ const refunds_1 = require("./refunds");
10
11
  const payments_1 = require("../../vocabulary/payments");
11
12
  /**
12
13
  * Disputes (`dp_…`) — the card network holding a payment's money while a
@@ -201,4 +202,19 @@ exports.disputeRoutes = [
201
202
  response: exports.disputeSchema,
202
203
  sdk: 'disputes.close',
203
204
  }),
205
+ (0, route_1.defineRoute)({
206
+ operationId: 'retrieveDisputeSettlement',
207
+ method: 'get',
208
+ path: '/v1/disputes/{disputeId}/settlement',
209
+ tag: 'Disputes',
210
+ summary: "Retrieve a dispute's settlement",
211
+ description: 'What the dispute WITHDREW from the settlement balance — `gross` the principal, `fee` the dispute fee, a negative `net` — in the settlement currency, read live from the provider. An inquiry moves no money: `unknown`, every figure `null`, never `0`. A reinstatement after a won dispute is not this figure.',
212
+ auth: 'service',
213
+ scope: 'payments:read',
214
+ params: disputeId,
215
+ query: params_1.expandOnlyQuery,
216
+ response: refunds_1.settlementSchema,
217
+ sdk: 'disputes.settlement',
218
+ expandable: 'settlement',
219
+ }),
204
220
  ];
@@ -10,7 +10,8 @@ const route_1 = require("../../route");
10
10
  const money_1 = require("../../vocabulary/money");
11
11
  const payments_1 = require("../../vocabulary/payments");
12
12
  /**
13
- * Refunds (`re_…`) and a payment's settlement figures. The provider's own
13
+ * Refunds (`re_…`) and the settlement figures of a payment, a refund or a
14
+ * dispute. The provider's own
14
15
  * refund id never appears: a merchant integrates against Peable and never
15
16
  * learns which acquirer sat behind it (ADR 0001 D3).
16
17
  */
@@ -56,23 +57,42 @@ exports.refundSchema = (0, objects_1.defineObject)('refund', 'Refund', zod_1.z
56
57
  ],
57
58
  });
58
59
  /**
59
- * What a payment actually came to, as the PROVIDER reports it. Every figure is
60
- * nullable and that is the contract: "the fee was zero" and "the fee is not
61
- * known yet" are different facts, and `status` says which produced the nulls.
62
- * It reports what the provider took; it attributes that cost to nobody.
60
+ * One movement of the settlement balance, as the PROVIDER reports it: what a
61
+ * payment brought in (`GET /v1/payment_intents/{intentId}/settlement`), what a
62
+ * refund took out (`GET /v1/refunds/{id}/settlement`) or what a dispute
63
+ * withdrew (`GET /v1/disputes/{disputeId}/settlement`). `refund` and `dispute`
64
+ * say which: both `null` for a payment's.
65
+ *
66
+ * Every figure is nullable and that is the contract: "the fee was zero" and
67
+ * "the fee is not known yet" are different facts, and `status` says which
68
+ * produced the nulls. It reports what the provider took; it attributes that
69
+ * cost to nobody.
70
+ *
71
+ * The signs: `gross` is the MAGNITUDE of the movement, `fee` the provider's fee
72
+ * on it (positive when charged, negative when returned), `net` its SIGNED
73
+ * effect on the balance — so `net = gross − fee` for a payment and
74
+ * `net = −gross − fee` for a refund or a dispute.
63
75
  */
64
76
  exports.settlementSchema = (0, objects_1.defineObject)('settlement', 'Settlement', zod_1.z
65
77
  .object({
66
78
  object: zod_1.z.literal('settlement'),
67
79
  livemode: primitives_1.livemode,
68
- payment_intent: (0, objects_1.expandable)('payment_intent', 'The `pi_…` this describes, or the PaymentIntent with `expand[]=payment_intent`.'),
80
+ payment_intent: (0, objects_1.expandable)('payment_intent', 'The `pi_…` this describes (the refunded or disputed payment, for a refund or a dispute), or the PaymentIntent with `expand[]=payment_intent`.'),
81
+ refund: (0, objects_1.expandable)('refund', 'The `re_…` whose movement this is, or the Refund with `expand[]=refund`; `null` unless this is the settlement of a refund.').nullable(),
82
+ dispute: (0, objects_1.expandable)('dispute', 'The `dp_…` whose withdrawal this is, or the Dispute with `expand[]=dispute`; `null` unless this is the settlement of a dispute.').nullable(),
69
83
  status: zod_1.z
70
84
  .enum(payments_1.SETTLEMENT_STATUSES)
71
- .describe('`available`: settled, the figures are final; `pending`: not final yet; `unknown`: there is none to read — **not zero**.'),
72
- gross: primitives_1.amount.nullable().describe('Base units of `currency`.'),
73
- fee: primitives_1.amount.nullable(),
74
- net: primitives_1.signedAmount.nullable(),
75
- currency: primitives_1.nullableString.describe("The SETTLEMENT currency (uppercase ISO 4217), which may differ from the payment's."),
85
+ .describe('`available`: settled, the figures are final; `pending`: not final yet; `unknown`: there is none to read — **not zero**. A dispute inquiry, which moves no money, and a refund that failed or was canceled are `unknown`.'),
86
+ gross: primitives_1.amount
87
+ .nullable()
88
+ .describe('The MAGNITUDE of the movement, never negative, in base units of `currency`: what the payment brought in, the refund took out or the dispute withdrew.'),
89
+ fee: primitives_1.signedAmount
90
+ .nullable()
91
+ .describe("The provider's fee on THIS movement, as the provider signs it: positive when charged to the balance (a payment's processing fee, a dispute fee), negative when returned to it (part of the original fee on some refunds). A refund's is usually `0`."),
92
+ net: primitives_1.signedAmount
93
+ .nullable()
94
+ .describe('The SIGNED effect on the balance: positive for a payment, negative for a refund or a dispute. Always `gross − fee` for a payment and `−gross − fee` for a refund or a dispute.'),
95
+ currency: primitives_1.nullableString.describe("The SETTLEMENT currency (uppercase ISO 4217) every figure is in, which may differ from the payment's, refund's or dispute's."),
76
96
  available_on: primitives_1.unixSeconds.nullable().describe('When the funds become available.'),
77
97
  exchange_rate: zod_1.z
78
98
  .number()
@@ -228,6 +248,21 @@ exports.refundRoutes = [
228
248
  sdk: 'refunds.settlement',
229
249
  expandable: 'settlement',
230
250
  }),
251
+ (0, route_1.defineRoute)({
252
+ operationId: 'retrieveRefundSettlement',
253
+ method: 'get',
254
+ path: '/v1/refunds/{id}/settlement',
255
+ tag: 'Refunds',
256
+ summary: "Retrieve a refund's settlement",
257
+ description: 'What the refund took off the settlement balance — `gross`, `fee`, a negative `net` — in the settlement currency, read live from the provider. A missing figure is `null` with a `status`, never `0`; a refund that failed or was canceled is `unknown`.',
258
+ auth: 'service',
259
+ scope: 'payments:read',
260
+ params: refundId,
261
+ query: params_1.expandOnlyQuery,
262
+ response: exports.settlementSchema,
263
+ sdk: 'refunds.refundSettlement',
264
+ expandable: 'settlement',
265
+ }),
231
266
  (0, route_1.defineRoute)({
232
267
  operationId: 'searchRefunds',
233
268
  method: 'get',
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.BILLING_RAIL_RENEWALS = exports.BILLING_RAIL_SETTLEMENTS = exports.BILLING_SUBSCRIPTION_STATUSES = exports.METER_STATUSES = exports.METER_AGGREGATIONS = exports.BILLING_SETTINGS_LIMITS = exports.DUNNING_INVOICE_ACTIONS = exports.DUNNING_FINAL_ACTIONS = exports.TEST_CLOCK_STATUSES = exports.RECURRING_INTERVAL_COUNT_MAX = exports.CATALOG_MAX_WHOLE_UNITS = exports.CATALOG_LIMITS = exports.COUPON_DURATIONS = exports.TRANSFORM_QUANTITY_ROUNDS = exports.PRICE_TAX_BEHAVIORS = exports.RECURRING_USAGE_TYPES = exports.RECURRING_INTERVALS = exports.PRICE_TYPES = exports.PRICE_TIERS_MODES = exports.PRICE_BILLING_SCHEMES = void 0;
3
+ exports.METER_STATUSES = exports.METER_AGGREGATIONS = exports.BILLING_SETTINGS_LIMITS = exports.DUNNING_INVOICE_ACTIONS = exports.DUNNING_FINAL_ACTIONS = exports.TEST_CLOCK_STATUSES = exports.RECURRING_INTERVAL_COUNT_MAX = exports.CATALOG_MAX_WHOLE_UNITS = exports.CATALOG_LIMITS = exports.COUPON_DURATIONS = exports.TRANSFORM_QUANTITY_ROUNDS = exports.PRICE_TAX_BEHAVIORS = exports.RECURRING_USAGE_TYPES = exports.RECURRING_INTERVALS = exports.PRICE_TYPES = exports.PRICE_TIERS_MODES = exports.PRICE_BILLING_SCHEMES = void 0;
4
4
  exports.maxBaseUnits = maxBaseUnits;
5
5
  // The catalog's and the billing engine platform's closed value sets (ADR 0016,
6
6
  // ADR 0018): what a price, a coupon, a test clock, a meter and the billing
@@ -91,20 +91,4 @@ exports.BILLING_SETTINGS_LIMITS = Object.freeze({
91
91
  /** How a meter combines a period's events into the quantity billed. */
92
92
  exports.METER_AGGREGATIONS = ['sum', 'count', 'last'];
93
93
  exports.METER_STATUSES = ['active', 'inactive'];
94
- // ---- Recurring billing transport (`/v1/billing/*`) ---------------------------
95
- /** A provider subscription's status, as the recurring transport observes it. */
96
- exports.BILLING_SUBSCRIPTION_STATUSES = [
97
- 'incomplete',
98
- 'incomplete_expired',
99
- 'trialing',
100
- 'active',
101
- 'past_due',
102
- 'canceled',
103
- 'unpaid',
104
- 'paused',
105
- ];
106
- /** `fiat` (Stripe and any further provider) or `faircoin` (native, to the merchant's watch-only wallet). */
107
- exports.BILLING_RAIL_SETTLEMENTS = ['fiat', 'faircoin'];
108
- /** `automatic`: the provider charges each period. `payer_initiated`: each period is an explicit payment. */
109
- exports.BILLING_RAIL_RENEWALS = ['automatic', 'payer_initiated'];
110
94
  // Product tax codes are Peable Tax's vocabulary: `vocabulary/tax.ts` (`TAX_CODES`).
@@ -47,19 +47,15 @@ exports.ERROR_CODE_DESCRIPTIONS = {
47
47
  account_invalid: 'The `Peable-Account` header names no connected account of this platform.',
48
48
  account_missing: 'The merchant has no account object yet.',
49
49
  amount_not_representable: 'The amount does not fit the currency or the rail.',
50
- billing_not_enabled: 'Billing is not enabled for this merchant.',
51
- billing_provider_unavailable: 'The billing provider could not be reached; retry.',
52
50
  domain_taken: 'The domain is already registered by another merchant.',
53
51
  file_too_large: 'The uploaded file is larger than its purpose allows.',
54
52
  file_unavailable: 'The file exists but its contents cannot be served right now.',
55
53
  idempotency_error: 'The `Idempotency-Key` was used with a different request, or its first request is still running.',
56
54
  idempotency_key_invalid: 'The `Idempotency-Key` header is not a valid key.',
57
55
  insufficient_scope: 'The credential is valid but was not granted the Oxy scope this route requires (`payments:read`, `payments:write`, …); `message` names it.',
58
- invalid_billing_request: 'The billing request is not valid for this subscription or offer.',
59
56
  keyless_recipient: 'The recipient has no receive key, so no address can be derived for them.',
60
57
  link_not_found: 'The link does not exist or is no longer active.',
61
58
  live_payments_gated: 'Live payments are not enabled for this application yet.',
62
- local_test_request_required: 'This test helper only answers a local test request.',
63
59
  parameter_invalid: 'A parameter is invalid; `param` names it.',
64
60
  parameter_missing: 'A required parameter is missing; `param` names it.',
65
61
  parameter_unknown: 'The request carries a parameter this route does not accept; `param` names it.',
@@ -88,10 +84,7 @@ exports.ERROR_CODE_DESCRIPTIONS = {
88
84
  customer_location_invalid: "The tax provider could not use the customer's location.",
89
85
  dispute_already_submitted: 'Evidence for this dispute has already been submitted; it is one shot.',
90
86
  dispute_not_answerable: 'The dispute is in a status that no longer accepts evidence.',
91
- idempotency_conflict: 'The same operation key was used for a different billing request.',
92
- identity_conflict: 'The billing identity already belongs to another customer or subscription.',
93
87
  in_progress: 'The same operation is still running; retry with the same key.',
94
- invalid_provider_response: 'The provider answered with something Peable cannot trust; the operation was not applied.',
95
88
  invalid_registration: 'The tax registration is not valid.',
96
89
  invalid_registration_declaration: 'The tax registration declaration is not valid.',
97
90
  invalid_tax_code: 'The tax code does not exist.',
@@ -106,12 +99,9 @@ exports.ERROR_CODE_DESCRIPTIONS = {
106
99
  product_in_use: 'The product is referenced by a subscription or a link.',
107
100
  promotion_code_invalid: 'The promotion code does not exist, is inactive or does not apply.',
108
101
  promotion_code_taken: 'Another active promotion code already uses this `code`.',
109
- provider_unavailable: 'The payment provider could not be reached; retry.',
110
102
  rail_unavailable: 'The payment rail this request needs is not available.',
111
- reconciliation_required: 'The billing operation has an unknown outcome at the provider and is being reconciled.',
112
103
  registration_immutable: 'An approved or ended tax registration cannot be deleted or changed this way; end it instead.',
113
104
  resource_already_exists: 'An object with this identity already exists.',
114
- result_expired: 'The stored result of this operation has expired.',
115
105
  review_item_not_open: 'The review item is already resolved or dismissed.',
116
106
  rule_set_version_unavailable: 'The tax rule set version is not available.',
117
107
  subscription_line_invalid: 'A subscription line item is not valid for Checkout.',
@@ -119,9 +109,6 @@ exports.ERROR_CODE_DESCRIPTIONS = {
119
109
  tax_calculation_unavailable: 'Tax could not be calculated; a covered sale fails closed.',
120
110
  tax_provider_registration_mismatch: "The provider's registrations disagree with the ones Peable has approved.",
121
111
  tax_settings_not_active: 'Tax settings are not active for this merchant.',
122
- local_test_unavailable: 'The local test checkout is not available.',
123
- local_test_configuration_unavailable: 'The local test checkout has no provider configuration.',
124
- local_test_subscription_unavailable: 'The local test subscription cannot be read.',
125
112
  rail_mismatch: 'The operation does not apply to the rail this payment uses.',
126
113
  checkout_session_changed: 'The Checkout Session changed while this request ran (a price, a discount, its tax); read it again and retry.',
127
114
  checkout_session_locked: 'The Checkout Session is being confirmed and cannot change.',
@@ -61,7 +61,6 @@ exports.WEBHOOK_EVENT_OBJECTS = {
61
61
  'setup_intent.succeeded': 'setup_intent',
62
62
  'setup_intent.setup_failed': 'setup_intent',
63
63
  'setup_intent.canceled': 'setup_intent',
64
- 'billing.observation.updated': 'billing_observation',
65
64
  'connected_account.updated': 'connected_account',
66
65
  'product.created': 'product',
67
66
  'product.updated': 'product',
@@ -151,10 +150,15 @@ exports.WEBHOOK_ENDPOINT_STATUSES = ['enabled', 'disabled'];
151
150
  * - `delivery_failures` — every delivery to it failed for three days
152
151
  * straight, so Peable stopped sending. Re-enabling it (`disabled: false`)
153
152
  * starts the clock again.
153
+ * - `url_refused` — its stored `url` breaks the rules a URL is
154
+ * registered under (https in live mode, ports 80/443, no private, loopback
155
+ * or reserved address), judged again before every delivery, so Peable never
156
+ * sent to it. It is re-enabled only together with a `url` that passes.
154
157
  */
155
158
  exports.WEBHOOK_ENDPOINT_DISABLED_REASONS = [
156
159
  'disabled_by_merchant',
157
160
  'delivery_failures',
161
+ 'url_refused',
158
162
  ];
159
163
  /** At most this many endpoints per merchant (per mode). */
160
164
  exports.WEBHOOK_ENDPOINTS_MAX_PER_MERCHANT = 16;
@@ -1,6 +1,5 @@
1
1
  // Contracts of this group: one module per resource, re-exported here, and
2
2
  // their routes concatenated into `catalogRoutes`.
3
- import { billingRoutes } from './billing.js';
4
3
  import { billingSettingsRoutes } from './billingSettings.js';
5
4
  import { couponRoutes } from './coupons.js';
6
5
  import { entitlementRoutes } from './entitlements.js';
@@ -9,7 +8,6 @@ import { priceRoutes } from './prices.js';
9
8
  import { productRoutes } from './products.js';
10
9
  import { promotionCodeRoutes } from './promotionCodes.js';
11
10
  import { testClockRoutes } from './testClocks.js';
12
- export * from './billing.js';
13
11
  export * from './billingSettings.js';
14
12
  export * from './coupons.js';
15
13
  export * from './entitlements.js';
@@ -22,8 +20,7 @@ export * from './testClocks.js';
22
20
  export { baseUnitAmountParam, queryFlag, queryIdList } from './shared.js';
23
21
  /**
24
22
  * The catalog (products, prices, coupons, promotion codes), entitlements, the
25
- * billing engine's platform objects (test clocks, billing settings, meters)
26
- * and the recurring billing transport (`/v1/billing/*`).
23
+ * billing engine's platform objects (test clocks, billing settings, meters).
27
24
  */
28
25
  export const catalogRoutes = [
29
26
  ...productRoutes,
@@ -34,5 +31,4 @@ export const catalogRoutes = [
34
31
  ...testClockRoutes,
35
32
  ...billingSettingsRoutes,
36
33
  ...meterRoutes,
37
- ...billingRoutes,
38
34
  ];
@@ -1,7 +1,6 @@
1
1
  import { z } from 'zod';
2
2
  import { CATALOG_LIMITS, PRICE_TAX_BEHAVIORS, RECURRING_INTERVALS } from '../../vocabulary/catalog.js';
3
3
  import { SETUP_INTENT_STATUSES } from '../../vocabulary/payments.js';
4
- import { billingFaircoinFxQuoteSchema } from '../catalog/billing.js';
5
4
  import { embedded } from '../../common/objects.js';
6
5
  import { listOf } from '../../common/envelopes.js';
7
6
  import { defineComponent, defineObject, expandable } from '../../common/objects.js';
@@ -180,9 +179,6 @@ export const checkoutSessionPublicSchema = defineComponent('CheckoutSessionPubli
180
179
  .string()
181
180
  .nullable()
182
181
  .describe("The card provider's PUBLIC key for this session's mode, so the payment fields can mount before the payment exists. `null` on FairCoin."),
183
- billing_quote: billingFaircoinFxQuoteSchema
184
- .optional()
185
- .describe('FairCoin billing invoices: the frozen USD price and FAIR settlement quote.'),
186
182
  })
187
183
  .strict());
188
184
  // ---- Merchant create/update ---------------------------------------------------
@@ -12,36 +12,6 @@ import { WEBHOOK_EVENT_OBJECTS, WEBHOOK_EVENT_TYPES, } from '../../vocabulary/ev
12
12
  * every matching webhook endpoint: a delivery's body and `GET /v1/events/:id`
13
13
  * are byte for byte the same object.
14
14
  */
15
- /**
16
- * The payload of `billing.observation.updated`: a wake-up, never paid or grant
17
- * authority. Re-read the owner-bound resource it names.
18
- */
19
- export const billingObservationSchema = defineObject('billing_observation', 'BillingObservation', z
20
- .object({
21
- object: z.literal('billing_observation'),
22
- livemode: livemode.describe('The mode of the billing cohort observed (ADR 0017).'),
23
- resource_kind: z.enum(['subscription', 'invoice']),
24
- resource_id: z.string().describe('The provider subscription or invoice observed.'),
25
- subscription_id: z
26
- .string()
27
- .optional()
28
- .describe('Owner-scoped wake-up hint only; re-read the subscription before resolving a payer.'),
29
- revision: z.number().int().describe('The observation revision; later revisions are newer.'),
30
- observed_at: unixSeconds,
31
- })
32
- .strict(), {
33
- examples: [
34
- {
35
- object: 'billing_observation',
36
- livemode: false,
37
- resource_kind: 'subscription',
38
- resource_id: 'sub_1Q2w3E4r5T6y7U8i',
39
- subscription_id: 'sub_1Q2w3E4r5T6y7U8i',
40
- revision: 3,
41
- observed_at: 1793750400,
42
- },
43
- ],
44
- });
45
15
  /**
46
16
  * What caused an event, when an API request did (Stripe's `event.request`).
47
17
  * Both `null` for an event caused by something else — the chain watcher, the
@@ -238,7 +208,6 @@ export const WEBHOOK_EVENT_DESCRIPTIONS = {
238
208
  'setup_intent.succeeded': 'A SetupIntent succeeded: its PaymentMethod is saved.',
239
209
  'setup_intent.setup_failed': 'A SetupIntent attempt failed.',
240
210
  'setup_intent.canceled': 'A SetupIntent was canceled.',
241
- 'billing.observation.updated': 'A recurring billing resource was observed to change. A wake-up only: re-read the resource.',
242
211
  'connected_account.updated': "A seller's connected account changed — its readiness, in practice.",
243
212
  'product.created': 'A Product was created.',
244
213
  'product.updated': 'A Product was updated; `previous_attributes` names what moved.',
@@ -23,7 +23,7 @@ export const webhookDeliverySchema = defineObject('webhook_delivery', 'WebhookDe
23
23
  delivered: z.boolean(),
24
24
  last_status: z
25
25
  .enum(WEBHOOK_DELIVERY_STATUSES)
26
- .describe('`pending`: will be attempted (`next_attempt_at`). `delivered`: terminal success. `failed`: the endpoint refused it (a 4xx, a blocked address) or was disabled first — never retried. `dead`: every attempt failed transiently for three days; it can be redelivered.'),
26
+ .describe('`pending`: will be attempted (`next_attempt_at`). `delivered`: terminal success. `failed`: the endpoint refused it (a 4xx, a blocked address), was disabled first, or its stored url breaks the registration rules — never retried. `dead`: every attempt failed transiently for three days; it can be redelivered.'),
27
27
  last_error: z
28
28
  .string()
29
29
  .optional()
@@ -26,7 +26,7 @@ const endpointShape = {
26
26
  disabled_reason: z
27
27
  .enum(WEBHOOK_ENDPOINT_DISABLED_REASONS)
28
28
  .nullable()
29
- .describe('`null` exactly when `status` is `enabled`. `delivery_failures`: every delivery failed for three days straight.'),
29
+ .describe('`null` exactly when `status` is `enabled`. `delivery_failures`: every delivery failed for three days straight. `url_refused`: the stored `url` breaks the registration rules, judged before every delivery; re-enable it with a `url` that passes.'),
30
30
  api_version: z.string().describe('The wire version events are rendered with for this endpoint.'),
31
31
  metadata,
32
32
  created: unixSeconds,
@@ -4,6 +4,7 @@ import { defineComponent, defineObject, expandable } from '../../common/objects.
4
4
  import { expandOnlyQuery, idParam, listQuery, metadataUpdateParam } from '../../common/params.js';
5
5
  import { amount, currency, livemode, metadata, unixSeconds } from '../../common/primitives.js';
6
6
  import { defineRoute } from '../../route.js';
7
+ import { settlementSchema } from './refunds.js';
7
8
  import { DISPUTE_EVIDENCE_TEXT_MAX, DISPUTE_FILE_EVIDENCE_FIELDS, DISPUTE_REASONS, DISPUTE_STATUSES, DISPUTE_TEXT_EVIDENCE_FIELDS, } from '../../vocabulary/payments.js';
8
9
  /**
9
10
  * Disputes (`dp_…`) — the card network holding a payment's money while a
@@ -198,4 +199,19 @@ export const disputeRoutes = [
198
199
  response: disputeSchema,
199
200
  sdk: 'disputes.close',
200
201
  }),
202
+ defineRoute({
203
+ operationId: 'retrieveDisputeSettlement',
204
+ method: 'get',
205
+ path: '/v1/disputes/{disputeId}/settlement',
206
+ tag: 'Disputes',
207
+ summary: "Retrieve a dispute's settlement",
208
+ description: 'What the dispute WITHDREW from the settlement balance — `gross` the principal, `fee` the dispute fee, a negative `net` — in the settlement currency, read live from the provider. An inquiry moves no money: `unknown`, every figure `null`, never `0`. A reinstatement after a won dispute is not this figure.',
209
+ auth: 'service',
210
+ scope: 'payments:read',
211
+ params: disputeId,
212
+ query: expandOnlyQuery,
213
+ response: settlementSchema,
214
+ sdk: 'disputes.settlement',
215
+ expandable: 'settlement',
216
+ }),
201
217
  ];
@@ -7,7 +7,8 @@ import { defineRoute } from '../../route.js';
7
7
  import { isBaseUnitString } from '../../vocabulary/money.js';
8
8
  import { REFUND_ORIGINS, REFUND_REASONS, REFUND_STATUSES, SETTLEMENT_STATUSES, } from '../../vocabulary/payments.js';
9
9
  /**
10
- * Refunds (`re_…`) and a payment's settlement figures. The provider's own
10
+ * Refunds (`re_…`) and the settlement figures of a payment, a refund or a
11
+ * dispute. The provider's own
11
12
  * refund id never appears: a merchant integrates against Peable and never
12
13
  * learns which acquirer sat behind it (ADR 0001 D3).
13
14
  */
@@ -53,23 +54,42 @@ export const refundSchema = defineObject('refund', 'Refund', z
53
54
  ],
54
55
  });
55
56
  /**
56
- * What a payment actually came to, as the PROVIDER reports it. Every figure is
57
- * nullable and that is the contract: "the fee was zero" and "the fee is not
58
- * known yet" are different facts, and `status` says which produced the nulls.
59
- * It reports what the provider took; it attributes that cost to nobody.
57
+ * One movement of the settlement balance, as the PROVIDER reports it: what a
58
+ * payment brought in (`GET /v1/payment_intents/{intentId}/settlement`), what a
59
+ * refund took out (`GET /v1/refunds/{id}/settlement`) or what a dispute
60
+ * withdrew (`GET /v1/disputes/{disputeId}/settlement`). `refund` and `dispute`
61
+ * say which: both `null` for a payment's.
62
+ *
63
+ * Every figure is nullable and that is the contract: "the fee was zero" and
64
+ * "the fee is not known yet" are different facts, and `status` says which
65
+ * produced the nulls. It reports what the provider took; it attributes that
66
+ * cost to nobody.
67
+ *
68
+ * The signs: `gross` is the MAGNITUDE of the movement, `fee` the provider's fee
69
+ * on it (positive when charged, negative when returned), `net` its SIGNED
70
+ * effect on the balance — so `net = gross − fee` for a payment and
71
+ * `net = −gross − fee` for a refund or a dispute.
60
72
  */
61
73
  export const settlementSchema = defineObject('settlement', 'Settlement', z
62
74
  .object({
63
75
  object: z.literal('settlement'),
64
76
  livemode,
65
- payment_intent: expandable('payment_intent', 'The `pi_…` this describes, or the PaymentIntent with `expand[]=payment_intent`.'),
77
+ payment_intent: expandable('payment_intent', 'The `pi_…` this describes (the refunded or disputed payment, for a refund or a dispute), or the PaymentIntent with `expand[]=payment_intent`.'),
78
+ refund: expandable('refund', 'The `re_…` whose movement this is, or the Refund with `expand[]=refund`; `null` unless this is the settlement of a refund.').nullable(),
79
+ dispute: expandable('dispute', 'The `dp_…` whose withdrawal this is, or the Dispute with `expand[]=dispute`; `null` unless this is the settlement of a dispute.').nullable(),
66
80
  status: z
67
81
  .enum(SETTLEMENT_STATUSES)
68
- .describe('`available`: settled, the figures are final; `pending`: not final yet; `unknown`: there is none to read — **not zero**.'),
69
- gross: amount.nullable().describe('Base units of `currency`.'),
70
- fee: amount.nullable(),
71
- net: signedAmount.nullable(),
72
- currency: nullableString.describe("The SETTLEMENT currency (uppercase ISO 4217), which may differ from the payment's."),
82
+ .describe('`available`: settled, the figures are final; `pending`: not final yet; `unknown`: there is none to read — **not zero**. A dispute inquiry, which moves no money, and a refund that failed or was canceled are `unknown`.'),
83
+ gross: amount
84
+ .nullable()
85
+ .describe('The MAGNITUDE of the movement, never negative, in base units of `currency`: what the payment brought in, the refund took out or the dispute withdrew.'),
86
+ fee: signedAmount
87
+ .nullable()
88
+ .describe("The provider's fee on THIS movement, as the provider signs it: positive when charged to the balance (a payment's processing fee, a dispute fee), negative when returned to it (part of the original fee on some refunds). A refund's is usually `0`."),
89
+ net: signedAmount
90
+ .nullable()
91
+ .describe('The SIGNED effect on the balance: positive for a payment, negative for a refund or a dispute. Always `gross − fee` for a payment and `−gross − fee` for a refund or a dispute.'),
92
+ currency: nullableString.describe("The SETTLEMENT currency (uppercase ISO 4217) every figure is in, which may differ from the payment's, refund's or dispute's."),
73
93
  available_on: unixSeconds.nullable().describe('When the funds become available.'),
74
94
  exchange_rate: z
75
95
  .number()
@@ -225,6 +245,21 @@ export const refundRoutes = [
225
245
  sdk: 'refunds.settlement',
226
246
  expandable: 'settlement',
227
247
  }),
248
+ defineRoute({
249
+ operationId: 'retrieveRefundSettlement',
250
+ method: 'get',
251
+ path: '/v1/refunds/{id}/settlement',
252
+ tag: 'Refunds',
253
+ summary: "Retrieve a refund's settlement",
254
+ description: 'What the refund took off the settlement balance — `gross`, `fee`, a negative `net` — in the settlement currency, read live from the provider. A missing figure is `null` with a `status`, never `0`; a refund that failed or was canceled is `unknown`.',
255
+ auth: 'service',
256
+ scope: 'payments:read',
257
+ params: refundId,
258
+ query: expandOnlyQuery,
259
+ response: settlementSchema,
260
+ sdk: 'refunds.refundSettlement',
261
+ expandable: 'settlement',
262
+ }),
228
263
  defineRoute({
229
264
  operationId: 'searchRefunds',
230
265
  method: 'get',
@@ -87,20 +87,4 @@ export const BILLING_SETTINGS_LIMITS = Object.freeze({
87
87
  /** How a meter combines a period's events into the quantity billed. */
88
88
  export const METER_AGGREGATIONS = ['sum', 'count', 'last'];
89
89
  export const METER_STATUSES = ['active', 'inactive'];
90
- // ---- Recurring billing transport (`/v1/billing/*`) ---------------------------
91
- /** A provider subscription's status, as the recurring transport observes it. */
92
- export const BILLING_SUBSCRIPTION_STATUSES = [
93
- 'incomplete',
94
- 'incomplete_expired',
95
- 'trialing',
96
- 'active',
97
- 'past_due',
98
- 'canceled',
99
- 'unpaid',
100
- 'paused',
101
- ];
102
- /** `fiat` (Stripe and any further provider) or `faircoin` (native, to the merchant's watch-only wallet). */
103
- export const BILLING_RAIL_SETTLEMENTS = ['fiat', 'faircoin'];
104
- /** `automatic`: the provider charges each period. `payer_initiated`: each period is an explicit payment. */
105
- export const BILLING_RAIL_RENEWALS = ['automatic', 'payer_initiated'];
106
90
  // Product tax codes are Peable Tax's vocabulary: `vocabulary/tax.ts` (`TAX_CODES`).