@siglume/direct-request-payment 0.4.14 → 0.4.16

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.
@@ -353,6 +353,11 @@ Returns:
353
353
  - `webhook_subscription`: webhook subscription response, when created
354
354
  - `env`: server environment values to store, including returned secrets
355
355
 
356
+ `merchant.merchant_account.metadata_jsonb.metered_risk_acceptance` records the
357
+ merchant's Micro / Nano delayed-settlement risk acceptance receipt with
358
+ `terms_version`, `accepted_at`, `principal_user_id`, `receipt_id`, and fixed
359
+ market thresholds `JPY: 10000` / `USD: 10000`.
360
+
356
361
  Secrets are returned only when created or rotated. Existing secrets are not
357
362
  replayed by `getMerchant` / `get_merchant`.
358
363
 
@@ -537,15 +542,20 @@ accepted by these user-authenticated routes.
537
542
  This client creates SDRP Standard Payment requirements for external merchant
538
543
  checkout flows. Micro Payment and Nano Payment are applied automatically by
539
544
  amount and settled on account-assigned weekly / monthly slots, or earlier when a
540
- buyer/payee/token batch reaches JPY 10,000 / USD 100.00; they are not created
541
- explicitly through this client. Use the statement APIs below to see open-period
542
- usage, the close time, the final-notice schedule, and settled / unsettled /
543
- past-due revenue.
545
+ buyer / provider / token / pricing-band batch reaches JPY 10,000 / USD 100.00;
546
+ they are not created explicitly through this client. Use the statement APIs
547
+ below to see open-period usage, the close time, the final-notice schedule, and
548
+ settled / unsettled / past-due revenue.
544
549
 
545
550
  Standard Payment requirements include `fee_bps` from the Siglume platform. The
546
551
  SDK does not calculate merchant plan fees locally. For Micro / Nano, use the
547
552
  statement API amount fields (`protocol_fee_minor`, `gross_buyer_debit_minor`,
548
- `buyer_debit_minor`, and `rounding_delta_minor`); see [Pricing](./pricing.md).
553
+ `buyer_debit_minor`, `provider_gross_amount_minor`, and
554
+ `rounding_delta_minor`); see [Pricing](./pricing.md).
555
+ `provider_gross_amount_minor` is canonical; `provider_usage_amount_minor` and
556
+ `gross_buyer_debit_minor` are compatibility aliases of the same provider gross
557
+ amount. Micro / Nano protocol fees are seller-borne, so
558
+ `buyer_debit_minor = provider_gross_amount_minor`.
549
559
 
550
560
  ```ts
551
561
  const siglume = new DirectRequestPaymentClient({
@@ -772,6 +782,7 @@ returns `{items, next_cursor}`. When `next_cursor` is non-null, pass it back as
772
782
  Buyer-facing amount names are centered on the debit:
773
783
 
774
784
  - `estimated_buyer_debit_minor`
785
+ - `provider_gross_amount_minor`
775
786
  - `provider_usage_amount_minor`
776
787
  - `gross_buyer_debit_minor`
777
788
  - `buyer_debit_minor`
@@ -837,6 +848,7 @@ back as `cursor` to fetch the next page.
837
848
 
838
849
  Provider-facing amount names:
839
850
 
851
+ - `provider_gross_amount_minor`
840
852
  - `provider_usage_amount_minor`
841
853
  - `provider_receivable_minor`
842
854
  - `gross_buyer_debit_minor`
@@ -845,6 +857,9 @@ Provider-facing amount names:
845
857
  - `settled_provider_receivable_minor`
846
858
  - `unsettled_provider_receivable_minor`
847
859
  - `past_due_provider_receivable_minor`
860
+ - `terminal_provider_receivable_minor`
861
+ - `uncollectible_provider_receivable_minor`
862
+ - `written_off_provider_receivable_minor`
848
863
 
849
864
  Schedule and execution fields:
850
865
 
@@ -862,6 +877,9 @@ Schedule and execution fields:
862
877
  - `usage_event_digest`
863
878
  - `attempt_count`
864
879
  - `next_attempt_at`
880
+ - `terminal_status`
881
+ - `terminal_marked_at`
882
+ - `terminal_reason_code`
865
883
 
866
884
  Failure fields are sanitized for public display:
867
885
 
@@ -875,6 +893,14 @@ address, relayer id, nonce, gas data, raw RPC errors, or raw
875
893
  `failure_message`. Use `buyer_period_ref` for provider-side reconciliation
876
894
  within a period.
877
895
 
896
+ Terminal statuses `uncollectible` and `written_off` are operator resolutions
897
+ after past-due manual review. Their receivable fields are reported separately
898
+ from settled, unsettled, and past-due revenue.
899
+
900
+ If a Micro / Nano execution idempotency key is reused with a different input
901
+ payload, execution fails closed before provider execution with
902
+ `IDEMPOTENCY_KEY_REUSED_WITH_DIFFERENT_PAYLOAD` and HTTP status `409`.
903
+
878
904
  ### Provider CSV export
879
905
 
880
906
  ```text
@@ -892,13 +918,14 @@ curl https://siglume.com/v1/sdrp/metered/provider/settlement-batches/<batch-id>/
892
918
  Columns:
893
919
 
894
920
  ```text
895
- metered_usage_id,created_at,plan_type,settlement_cadence,period_start,period_end,listing_id,capability_key,operation_key,currency,token_symbol,provider_usage_amount_minor,provider_receivable_minor,protocol_fee_minor,gross_buyer_debit_minor,rounding_delta_minor,buyer_debit_minor,status,settlement_batch_id,buyer_period_ref
921
+ metered_usage_id,created_at,plan_type,settlement_cadence,period_start,period_end,listing_id,capability_key,operation_key,currency,token_symbol,provider_gross_amount_minor,provider_usage_amount_minor,provider_receivable_minor,protocol_fee_minor,gross_buyer_debit_minor,rounding_delta_minor,buyer_debit_minor,status,settlement_batch_id,buyer_period_ref
896
922
  ```
897
923
 
898
924
  The CSV uses `buyer_period_ref`, not raw buyer account identifiers.
899
925
  The CSV keeps the `rounding_delta_minor` column for schema stability, but usage
900
- rows report `0`; the authoritative rounding adjustment is the settlement batch
901
- field `rounding_delta_minor`.
926
+ rows report `0`. If a batch-level `rounding_delta_minor` appears in historical
927
+ or internal records, do not add it to buyer debit and do not allocate it to
928
+ provider revenue.
902
929
 
903
930
  Micro / Nano amount fields are decimal minor-unit strings. In JavaScript, do
904
931
  not aggregate them with `number`; parse them with a decimal library. In Python,
@@ -950,14 +977,17 @@ Returns the prepared-transaction payload object.
950
977
  Returns the bare HMAC-SHA256 hex digest over `"<timestamp>.<body>"`. This is the
951
978
  primitive `buildWebhookSignatureHeader` / `verifyWebhookSignature` use. In
952
979
  TypeScript `options` is `{ timestamp: number }`; in Python `timestamp` is a
953
- keyword-only `int`. `body` may be raw bytes, a string, or a JSON object.
980
+ keyword-only `int`. `body` may be raw bytes, a string, or a JSON object when you
981
+ are building a test signature. Production webhook verification must use the
982
+ exact raw request body.
954
983
 
955
984
  ### `buildWebhookSignatureHeader(secret, body, options)` / `build_webhook_signature_header(secret, body, *, timestamp=None)`
956
985
 
957
986
  Returns a `t=<timestamp>,v1=<signature>` header string. Mainly for tests /
958
987
  mocking inbound webhooks. In TypeScript `options` is an optional
959
988
  `{ timestamp?: number }` (defaults to now); in Python `timestamp` is a
960
- keyword-only optional `int`.
989
+ keyword-only optional `int`. This helper accepts JSON objects for tests; the
990
+ verification helpers below do not.
961
991
 
962
992
  ### `verifyWebhookSignature(secret, body, signature_header, options)` / `verify_webhook_signature(secret, body, signature_header, *, tolerance_seconds=300, now=None)`
963
993
 
@@ -966,7 +996,9 @@ Verifies the `Siglume-Signature` header against the raw `body`. Throws
966
996
  the timestamp is outside tolerance or the signature does not match. In TypeScript
967
997
  `options` is `{ tolerance_seconds?, now? }`; in Python those are keyword-only
968
998
  (`tolerance_seconds` defaults to `DEFAULT_WEBHOOK_TOLERANCE_SECONDS` = 300).
969
- Returns `{ timestamp, signature }`.
999
+ Returns `{ timestamp, signature }`. Pass the exact raw request body bytes or raw
1000
+ body string captured by your web framework. Passing a parsed JSON object is
1001
+ rejected because re-stringifying changes the signed bytes.
970
1002
 
971
1003
  ### `parseDirectRequestPaymentWebhookEvent(payload)` / `parse_direct_request_payment_webhook_event(payload)`
972
1004
 
@@ -1029,7 +1061,8 @@ return `kind: "unknown"` with a machine-readable `reason`.
1029
1061
 
1030
1062
  Verifies the signature and parses the event in one call. Returns
1031
1063
  `{ event, verification }` (TS) / `{"event": ..., "verification": ...}` (Py). Same
1032
- options shape as `verifyWebhookSignature` (keyword-only in Python).
1064
+ options shape as `verifyWebhookSignature` (keyword-only in Python). The `body`
1065
+ argument is raw bytes or a raw body string only; do not pass parsed JSON.
1033
1066
 
1034
1067
  Webhook-verification trio (typical inbound webhook handler):
1035
1068
 
@@ -1058,6 +1091,45 @@ event = verified["event"]
1058
1091
  # or equivalent fail-closed field checks before marking an order paid or fulfilled.
1059
1092
  ```
1060
1093
 
1094
+ Express example:
1095
+
1096
+ ```ts
1097
+ app.post("/siglume/webhook", express.raw({ type: "application/json" }), async (req, res) => {
1098
+ const { event } = await verifyDirectRequestPaymentWebhook(
1099
+ process.env.SIGLUME_WEBHOOK_SECRET!,
1100
+ req.body,
1101
+ req.header("siglume-signature") ?? "",
1102
+ );
1103
+ res.json({ received: event.id });
1104
+ });
1105
+ ```
1106
+
1107
+ FastAPI example:
1108
+
1109
+ ```py
1110
+ @app.post("/siglume/webhook")
1111
+ async def siglume_webhook(request: Request):
1112
+ raw_body = await request.body()
1113
+ verified = verify_direct_request_payment_webhook(
1114
+ os.environ["SIGLUME_WEBHOOK_SECRET"],
1115
+ raw_body,
1116
+ request.headers.get("siglume-signature", ""),
1117
+ )
1118
+ return {"received": verified["event"]["id"]}
1119
+ ```
1120
+
1121
+ Django example:
1122
+
1123
+ ```py
1124
+ def siglume_webhook(request):
1125
+ verified = verify_direct_request_payment_webhook(
1126
+ os.environ["SIGLUME_WEBHOOK_SECRET"],
1127
+ request.body,
1128
+ request.headers.get("Siglume-Signature", ""),
1129
+ )
1130
+ return JsonResponse({"received": verified["event"]["id"]})
1131
+ ```
1132
+
1061
1133
  ## Exported Constants
1062
1134
 
1063
1135
  Both packages export these importable constants:
@@ -31,6 +31,10 @@ setup and the billing mandate means accepting this Micro/Nano delayed aggregated
31
31
  settlement model for low-price items. If your product requires immediate
32
32
  on-chain settlement, keep its price above the Micro/Nano thresholds instead of
33
33
  offering JPY 500-and-under or USD 3-and-under amounts.
34
+ The setup response records this acceptance at
35
+ `merchant.merchant_account.metadata_jsonb.metered_risk_acceptance` with a
36
+ `terms_version`, `accepted_at`, `principal_user_id`, `receipt_id`, and fixed
37
+ market thresholds `JPY: 10000` / `USD: 10000`.
34
38
 
35
39
  ## Two Buyer Systems
36
40
 
@@ -91,38 +91,34 @@ open period. It can report `wallet_balance_checked: false` or
91
91
  `allowance_checked: false`; in that case it is guidance, not a final on-chain
92
92
  guarantee.
93
93
 
94
- ## Amount Rounding
94
+ ## Seller-borne Micro / Nano Amounts
95
95
 
96
96
  Micro / Nano usage rows keep provider price and protocol fee values as decimal
97
97
  minor-unit amounts. This allows Nano fees such as JPY 0.2 per SDRP Tx to be
98
98
  accounted without rounding every accepted payment.
99
99
 
100
- Rounding happens once when a settlement batch is created:
100
+ The buyer is charged only the provider-visible usage amount. Micro / Nano
101
+ protocol fees are seller-borne and are deducted from provider receivable:
101
102
 
102
103
  ```text
103
- provider_usage_amount_minor = sum(provider price minor units for accepted metered rows)
104
+ provider_gross_amount_minor = sum(provider price minor units for accepted metered rows)
105
+ provider_usage_amount_minor = provider_gross_amount_minor # legacy alias
106
+ gross_buyer_debit_minor = provider_gross_amount_minor # legacy alias
107
+ buyer_debit_minor = provider_gross_amount_minor
104
108
  protocol_fee_minor = sum(Micro/Nano fixed protocol fee minor units for accepted metered rows)
105
- provider_receivable_minor = max(provider_usage_amount_minor - protocol_fee_minor, 0)
106
- gross_buyer_debit_minor = provider_usage_amount_minor
107
- buyer_debit_minor = ceil(gross_buyer_debit_minor)
108
- rounding_delta_minor = buyer_debit_minor - gross_buyer_debit_minor
109
+ provider_receivable_minor = provider_gross_amount_minor - protocol_fee_minor
110
+ rounding_delta_minor = 0 for buyer/provider accounting
109
111
  ```
110
112
 
111
- For low-count Nano batches, the ceiling can make the effective rounded debit per
112
- SDRP Tx higher than the decimal provider usage amount. Here, `Tx` means one
113
- accepted SDRP payment, not an on-chain settlement transaction. The protocol fee
114
- remains the decimal statement amount and is deducted from provider receivable;
115
- the extra integer-minor-unit adjustment is recorded as `rounding_delta_minor` on
116
- the settlement batch. Each settlement batch can add a positive rounding
117
- adjustment of less than 1 token minor unit; if a buyer uses many providers /
118
- payees in one period, that adjustment can occur once per settlement batch.
119
-
120
- `rounding_delta_minor` belongs to the buyer debit and Siglume's rounding
121
- adjustment accounting for that batch. It is not provider revenue.
122
- `protocol_fee_minor` is provider-borne and is not added to the buyer debit.
123
- Provider reports should use `provider_receivable_minor`,
124
- `settled_provider_receivable_minor`, `unsettled_provider_receivable_minor`, and
125
- `past_due_provider_receivable_minor`.
113
+ Example: a JPY 100 Micro usage event has `buyer_debit_minor = 100`,
114
+ `protocol_fee_minor = 2`, and `provider_receivable_minor = 98`.
115
+
116
+ The `rounding_delta_minor` field remains in some statement schemas for
117
+ compatibility. It is not added to `buyer_debit_minor`, not added to
118
+ `provider_gross_amount_minor`, and not deducted again from
119
+ `provider_receivable_minor`. If non-zero in a historical or internal record,
120
+ treat it as a Siglume platform accounting adjustment, not buyer debit or
121
+ provider revenue.
126
122
 
127
123
  Micro / Nano amount fields are decimal minor-unit strings. JavaScript
128
124
  integrations should aggregate them with a decimal library, not `number`. Python
@@ -149,7 +145,9 @@ Buyer usage event amount fields:
149
145
 
150
146
  - `provider_usage_amount_minor`: provider price for the usage event
151
147
  - `protocol_fee_minor`: provider-borne metered protocol fee
152
- - `gross_buyer_debit_minor`: provider usage amount before integer-token rounding
148
+ - `provider_gross_amount_minor`: provider price before protocol fee
149
+ - `gross_buyer_debit_minor`: legacy alias of `provider_gross_amount_minor`
150
+ - `buyer_debit_minor`: buyer debit; equals `provider_gross_amount_minor`
153
151
  - `expected_scheduled_debit_at`: derived schedule for an open period before a
154
152
  settlement batch exists
155
153
 
@@ -175,8 +173,10 @@ Buyer batch amount fields:
175
173
 
176
174
  - `estimated_buyer_debit_minor`: total buyer debit for the batch
177
175
  - `provider_usage_amount_minor`: provider usage amount before protocol fee
178
- - `gross_buyer_debit_minor`: provider usage amount before integer-token rounding
176
+ - `provider_gross_amount_minor`: provider gross before protocol fee
177
+ - `gross_buyer_debit_minor`: legacy alias of `provider_gross_amount_minor`
179
178
  - `buyer_debit_minor`: amount scheduled for the debit transaction
179
+ - `provider_receivable_minor`: provider gross minus provider-borne protocol fee
180
180
 
181
181
  Past-due batches include:
182
182
 
@@ -197,7 +197,7 @@ Threshold-control fields:
197
197
  - `threshold_reached_at`: set when the fixed amount threshold closed the batch
198
198
  - `total_unsettled_exposure_minor`: open plus `notice_pending`, `ready`,
199
199
  `submitted`, retrying, and `past_due` provider gross exposure for the same
200
- buyer / provider / token
200
+ buyer / provider / token / pricing band
201
201
 
202
202
  JPY 10,000 and USD 100.00 are market-specific fixed thresholds, not FX
203
203
  conversions of one another.
@@ -248,7 +248,9 @@ Use:
248
248
  - `totals.unsettled_provider_receivable_minor` for expected but not yet settled
249
249
  revenue,
250
250
  - `totals.past_due_provider_receivable_minor` for provider revenue blocked on a
251
- past-due buyer settlement.
251
+ past-due buyer settlement,
252
+ - `totals.terminal_provider_receivable_minor` for provider receivable that an
253
+ operator has marked `uncollectible` or `written_off` after past-due review.
252
254
 
253
255
  ### Usage Events
254
256
 
@@ -310,13 +312,13 @@ Important batch fields:
310
312
 
311
313
  | Field | Meaning |
312
314
  | --- | --- |
313
- | `status` | Batch lifecycle state such as `notice_pending`, `ready`, `submitted`, `settled`, `failed`, `past_due`, or `notice_delivery_failed` |
315
+ | `status` | Batch lifecycle state such as `notice_pending`, `ready`, `submitted`, `settled`, `failed`, `past_due`, `uncollectible`, `written_off`, or `notice_delivery_failed` |
314
316
  | `notice_status` | Final debit notice delivery status |
315
317
  | `period_start`, `period_end`, `close_at` | Statement period boundaries |
316
318
  | `settlement_trigger` | `amount_threshold` for early threshold close, or `scheduled_close` for weekly/monthly close |
317
319
  | `settlement_threshold_minor` | Fixed market threshold for early settlement: JPY `10000` or USD `10000` minor units |
318
320
  | `threshold_reached_at` | Timestamp when the fixed threshold closed the batch, otherwise null |
319
- | `total_unsettled_exposure_minor` | Current open plus notice/ready/submitted/retrying/past-due provider gross exposure for the same buyer / provider / token |
321
+ | `total_unsettled_exposure_minor` | Current open plus notice/ready/submitted/retrying/past-due provider gross exposure for the same buyer / provider / token / pricing band |
320
322
  | `expected_scheduled_debit_at` | Expected debit time for an open period before a batch exists |
321
323
  | `scheduled_debit_at` | Scheduled debit time after batch creation |
322
324
  | `not_before_attempt_at` | Earliest allowed debit attempt; this is the close-plus-3-day gate |
@@ -324,14 +326,19 @@ Important batch fields:
324
326
  | `latest_execution_attempt_status` | Latest non-sensitive execution attempt status |
325
327
  | `chain_receipt_id` | On-chain receipt id when available |
326
328
  | `usage_event_digest` | Digest of usage rows included in the batch |
329
+ | `provider_gross_amount_minor` | Provider gross before provider-borne protocol fee |
327
330
  | `provider_usage_amount_minor` | Provider usage amount before protocol fee |
328
331
  | `provider_receivable_minor` | Provider amount for the batch after provider-borne protocol fee |
329
332
  | `settled_provider_receivable_minor` | Provider receivable that is settled on-chain |
330
333
  | `unsettled_provider_receivable_minor` | Provider receivable not yet settled |
331
334
  | `past_due_provider_receivable_minor` | Provider receivable blocked on past-due settlement |
332
- | `gross_buyer_debit_minor` | Provider usage amount before integer-token rounding |
335
+ | `terminal_provider_receivable_minor` | Provider receivable marked terminal after operator review |
336
+ | `uncollectible_provider_receivable_minor` | Terminal provider receivable classified as uncollectible |
337
+ | `written_off_provider_receivable_minor` | Terminal provider receivable classified as written off |
338
+ | `terminal_status`, `terminal_marked_at`, `terminal_reason_code` | Public terminal resolution fields, present only for terminal batches |
339
+ | `gross_buyer_debit_minor` | Legacy alias of provider gross; protocol fee is not added |
333
340
  | `protocol_fee_minor` | Micro / Nano protocol fee deducted from provider receivable |
334
- | `buyer_debit_minor` | Amount scheduled for the buyer debit |
341
+ | `buyer_debit_minor` | Amount scheduled for the buyer debit; equals provider gross |
335
342
  | `attempt_count`, `next_attempt_at` | Retry state |
336
343
  | `failure_reason_code`, `failure_reason_label`, `failure_reason_help` | Sanitized public failure reason |
337
344
  | `support_reference` | Non-secret support reference |
@@ -350,14 +357,14 @@ curl https://siglume.com/v1/sdrp/metered/provider/settlement-batches/<batch-id>/
350
357
  The CSV contains exactly these columns:
351
358
 
352
359
  ```text
353
- metered_usage_id,created_at,plan_type,settlement_cadence,period_start,period_end,listing_id,capability_key,operation_key,currency,token_symbol,provider_usage_amount_minor,provider_receivable_minor,protocol_fee_minor,gross_buyer_debit_minor,rounding_delta_minor,buyer_debit_minor,status,settlement_batch_id,buyer_period_ref
360
+ metered_usage_id,created_at,plan_type,settlement_cadence,period_start,period_end,listing_id,capability_key,operation_key,currency,token_symbol,provider_gross_amount_minor,provider_usage_amount_minor,provider_receivable_minor,protocol_fee_minor,gross_buyer_debit_minor,rounding_delta_minor,buyer_debit_minor,status,settlement_batch_id,buyer_period_ref
354
361
  ```
355
362
 
356
363
  The CSV uses `buyer_period_ref`, not `buyer_user_id`.
357
364
  `rounding_delta_minor` is present for a stable usage-event schema, but per-row
358
- values are `0`. The authoritative rounding adjustment is the settlement batch
359
- `rounding_delta_minor`; do not allocate that adjustment to provider revenue
360
- from individual CSV rows.
365
+ values are `0`. If a batch-level `rounding_delta_minor` appears in historical or
366
+ internal records, do not add it to buyer debit and do not allocate it to provider
367
+ revenue.
361
368
 
362
369
  ## Notifications
363
370
 
@@ -471,13 +478,24 @@ settled only when `status === "settled"` and `chain_receipt_id` is present.
471
478
 
472
479
  Buyer summary `past_due_blocks` returns `METERED_SETTLEMENT_PAST_DUE` with a
473
480
  sanitized reason and support reference. The buyer must repair the listed balance
474
- or authorization issue. Requeue is operator-only in the MVP.
481
+ or authorization issue. Requeue is operator-only in the MVP. If operator review
482
+ marks a past-due batch `uncollectible` or `written_off`, new usage may resume,
483
+ but the provider receivable moves to terminal accounting instead of settled,
484
+ unsettled, or past-due revenue.
485
+
486
+ If the same execution idempotency key is reused with a different Micro / Nano
487
+ input payload, the platform fails closed before provider execution with
488
+ `IDEMPOTENCY_KEY_REUSED_WITH_DIFFERENT_PAYLOAD` and HTTP status `409`.
475
489
 
476
490
  ### "What should our accounting system book?"
477
491
 
478
492
  Book `settled_provider_receivable_minor` as settled revenue. Keep
479
493
  `unsettled_provider_receivable_minor` and `past_due_provider_receivable_minor`
480
- separate from settled revenue.
494
+ separate from settled revenue. Keep
495
+ `terminal_provider_receivable_minor`, `uncollectible_provider_receivable_minor`,
496
+ and `written_off_provider_receivable_minor` outside settled, unsettled, and
497
+ past-due revenue; they represent operator terminal resolution, not successful
498
+ on-chain settlement.
481
499
 
482
500
  ## Go-Live Checklist
483
501
 
@@ -487,6 +505,8 @@ separate from settled revenue.
487
505
  `settlement_status` show settled per-payment finality.
488
506
  - Micro / Nano accounting uses statement APIs or CSV, not only webhooks.
489
507
  - Your dashboard separates settled, unsettled, and past-due provider amounts.
508
+ - Your dashboard separates terminal `uncollectible` / `written_off` provider
509
+ amounts from settled, unsettled, and past-due revenue.
490
510
  - Your support UI shows sanitized failure fields and `support_reference`.
491
511
  - You do not store or display raw buyer IDs from provider APIs; use
492
512
  `buyer_period_ref`.
package/docs/pricing.md CHANGED
@@ -151,8 +151,8 @@ confirmed payment turns into money in your settlement wallet.
151
151
  the affected batch is treated as past due. Siglume currently retries every 6
152
152
  hours for up to 28 automatic attempts. After that, the batch remains past due
153
153
  and requires manual resolution before another attempt.
154
- - While the same buyer / provider / token has total unsettled exposure at or
155
- above the fixed threshold, new Micro/Nano usage is paused with the
154
+ - While the same buyer / provider / token / pricing band has total unsettled
155
+ exposure at or above the fixed threshold, new Micro/Nano usage is paused with the
156
156
  machine-readable error `METERED_SETTLEMENT_PAST_DUE`; the provider API is not
157
157
  called. Exposure includes open usage plus `notice_pending`, `ready`,
158
158
  `submitted`, retrying, and `past_due` batches, and remains paused while
@@ -167,7 +167,7 @@ confirmed payment turns into money in your settlement wallet.
167
167
 
168
168
  Micro and Nano run a budget check before the buyer's paid request is fulfilled:
169
169
 
170
- - A buyer's wallet budget reservation is consumed at the **gross buyer debit
170
+ - A buyer's wallet budget reservation is consumed at the **provider gross
171
171
  amount** (your usage price, before any provider-borne protocol fee) from
172
172
  acceptance until settlement confirms. This
173
173
  is a reservation against Siglume spending limits; it does not lock, escrow,
@@ -185,51 +185,43 @@ Micro and Nano run a budget check before the buyer's paid request is fulfilled:
185
185
  ### What is fixed vs platform-managed
186
186
 
187
187
  The cadence fields are fixed: **Micro is weekly, Nano is monthly**. In both
188
- bands, Siglume can close a buyer/payee/token batch early once it reaches JPY
189
- 10,000 or USD 100.00. A payment is final only after its on-chain settlement
190
- confirms. Micro and Nano are automatic amount bands, not customer-selected
191
- options. The account-assigned period boundaries, roughly 3-day pre-debit notice
192
- window, early settlement threshold, and current retry policy above are the
193
- public behavior as of 2026-06-19. Treat the platform's statement status,
194
- `not_before_attempt_at`, Standard `fee_bps`, and Micro / Nano statement amount
195
- fields as authoritative rather than hard-coding local revenue recognition.
196
-
197
- ## Micro / Nano Amount Rounding
188
+ bands, Siglume can close a buyer / provider / token / pricing-band batch early
189
+ once provider gross reaches JPY 10,000 or USD 100.00. These are fixed
190
+ market-specific thresholds, not FX conversions of one another. A payment is
191
+ final only after its on-chain settlement confirms. Micro and Nano are automatic
192
+ amount bands, not customer-selected options. The account-assigned period
193
+ boundaries, roughly 3-day pre-debit notice window, early settlement threshold,
194
+ and current retry policy above are the public behavior as of 2026-06-19. Treat
195
+ the platform's statement status, `not_before_attempt_at`, Standard `fee_bps`,
196
+ and Micro / Nano statement amount fields as authoritative rather than
197
+ hard-coding local revenue recognition.
198
+
199
+ ## Micro / Nano Seller-borne Amounts
198
200
 
199
201
  Micro / Nano fees are stored internally as decimal minor-unit values so
200
- sub-yen and sub-cent Nano fees are not silently rounded per accepted SDRP Tx. The
201
- current settlement rule is:
202
+ sub-yen and sub-cent Nano fees are not silently rounded per accepted SDRP Tx.
203
+ The buyer is charged only the provider-visible usage amount; the protocol fee is
204
+ not added to the buyer debit:
202
205
 
203
206
  ```text
204
- provider_usage_amount_minor = sum(provider price minor units for accepted metered rows)
207
+ provider_gross_amount_minor = sum(provider price minor units for accepted metered rows)
208
+ provider_usage_amount_minor = provider_gross_amount_minor # legacy alias
209
+ gross_buyer_debit_minor = provider_gross_amount_minor # legacy alias
210
+ buyer_debit_minor = provider_gross_amount_minor
205
211
  protocol_fee_minor = sum(Micro/Nano fixed protocol fee minor units for accepted metered rows)
206
- provider_receivable_minor = max(provider_usage_amount_minor - protocol_fee_minor, 0)
207
- gross_buyer_debit_minor = provider_usage_amount_minor
208
- buyer_debit_minor = ceil(gross_buyer_debit_minor)
209
- rounding_delta_minor = buyer_debit_minor - gross_buyer_debit_minor
212
+ provider_receivable_minor = provider_gross_amount_minor - protocol_fee_minor
213
+ rounding_delta_minor = 0 for buyer/provider accounting
210
214
  ```
211
215
 
212
- Rounding happens once when the settlement batch is created, not per accepted
213
- SDRP Tx.
214
- The rounding mode is ceiling to the next integer token minor unit because
215
- on-chain settlement cannot debit fractional JPYC/USDC minor units. The positive
216
- `rounding_delta_minor` is part of the buyer debit for that batch and is retained
217
- as a rounding adjustment in Siglume's settlement accounting; it is not provider
218
- revenue. `protocol_fee_minor` is provider-borne and is deducted from provider
219
- receivable, not added to the buyer debit. Providers should reconcile their
220
- revenue with
221
- `provider_receivable_minor`, `settled_provider_receivable_minor`,
222
- `unsettled_provider_receivable_minor`, and
223
- `past_due_provider_receivable_minor`, not with `buyer_debit_minor`.
224
-
225
- For low-count Nano batches, the integer ceiling can make the effective buyer
226
- rounded debit per SDRP Tx higher than the decimal provider usage amount. The
227
- decimal protocol fee remains visible as `protocol_fee_minor` and is deducted
228
- from provider receivable; the difference created by integer-token settlement is
229
- visible as `rounding_delta_minor` on the batch. Each settlement batch can add a
230
- positive rounding adjustment of less than 1 token minor unit. If a buyer uses
231
- many providers / payees in one period, that adjustment can occur once per
232
- settlement batch. JavaScript integrations should not sum Micro / Nano minor
216
+ Example: a JPY 100 Micro usage event has buyer debit JPY 100, protocol fee JPY
217
+ 2, and provider receivable JPY 98.
218
+
219
+ The `rounding_delta_minor` field is retained in some schemas for compatibility.
220
+ It is not added to `buyer_debit_minor`, not added to
221
+ `provider_gross_amount_minor`, and not deducted again from
222
+ `provider_receivable_minor`. If non-zero in a historical or internal record,
223
+ treat it as a Siglume platform accounting adjustment, not buyer debit or
224
+ provider revenue. JavaScript integrations should not sum Micro / Nano minor
233
225
  amounts with `number`; use a decimal library. Python integrations should use
234
226
  `Decimal`.
235
227
 
@@ -241,12 +233,17 @@ but it does not replace the Micro / Nano statement APIs.
241
233
 
242
234
  Use [Micro / Nano Statements and Notices](./metered-statements.md) to integrate:
243
235
 
244
- - provider summary of open, settled, unsettled, and past-due revenue,
236
+ - provider summary of open, settled, unsettled, past-due, and terminal
237
+ `uncollectible` / `written_off` revenue buckets,
245
238
  - provider usage-event CSV export,
246
239
  - buyer summaries for open-period estimated debit and past-due blocks,
247
240
  - sanitized public failure reasons and support references,
248
241
  - the fixed final notice plus close-plus-3-day debit window.
249
242
 
243
+ Reusing the same Micro / Nano execution idempotency key with a different input
244
+ payload fails closed before provider execution with
245
+ `IDEMPOTENCY_KEY_REUSED_WITH_DIFFERENT_PAYLOAD` and HTTP status `409`.
246
+
250
247
  ## SDK Behavior
251
248
 
252
249
  The SDK does not calculate merchant invoices or enforce plan limits locally.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@siglume/direct-request-payment",
3
- "version": "0.4.14",
3
+ "version": "0.4.16",
4
4
  "description": "SDK for the Siglume Direct Request Payment SDRP payment protocol",
5
5
  "keywords": [
6
6
  "siglume",