@siglume/direct-request-payment 0.3.5 → 0.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.
@@ -7,7 +7,7 @@ external merchant.
7
7
 
8
8
  - Merchant server: owns the order, amount, currency, challenge secret, webhook
9
9
  endpoint, and order fulfillment.
10
- - Buyer: owns the Siglume wallet that pays the DirectPaymentHub transaction.
10
+ - Buyer: owns the Siglume wallet that pays the on-chain payment transaction.
11
11
  - Siglume: creates the payment requirement, prepares the wallet transaction,
12
12
  verifies the receipt, and emits signed webhooks.
13
13
 
@@ -15,9 +15,128 @@ The merchant server must not create charges with a customer wallet. It signs the
15
15
  order challenge; the buyer-facing Siglume payment flow pays it.
16
16
 
17
17
  This quickstart is for SDRP Standard Payment in an external merchant product.
18
- Micro Payment and Nano Payment use the SDRP metered-payment server flow instead.
19
- Micro/Nano run a server-side meter gate before provider execution and settle
20
- later; they are not browser checkout requirements created by this merchant SDK.
18
+ Micro Payment and Nano Payment are applied automatically by amount and settled on
19
+ a weekly / monthly cadence (see [Pricing](./pricing.md#settlement-schedule)); they
20
+ are not browser checkout requirements you create with this SDK. Their provider
21
+ revenue remains unsettled until the later on-chain settlement succeeds.
22
+
23
+ ## Two Buyer Systems
24
+
25
+ There are two ways a buyer reaches you, and you integrate each differently:
26
+
27
+ - **Human web shopper → Hosted Checkout.** Create a checkout session and
28
+ redirect the shopper to the Siglume-hosted page (the
29
+ [section below](#hosted-checkout-human-web-shoppers)). This is the path that
30
+ resembles a Stripe-style hosted checkout.
31
+ - **AI agent / agent-to-agent (AtoA) → direct API / tools.** An autonomous
32
+ buyer pays through `DirectRequestPaymentClient` or the marketplace tool
33
+ `market_confirm_direct_payment_and_execute`, as in sections 2-4 below.
34
+
35
+ In both cases the buyer pays from a Siglume wallet (JPYC / USDC, not a card),
36
+ the merchant SDK never authenticates the buyer, and you fulfill on the same
37
+ `direct_payment.confirmed` webhook.
38
+
39
+ ## Hosted Checkout (Human Web Shoppers)
40
+
41
+ When a person clicks "Pay with Siglume" on your site, create a session and
42
+ redirect them to the returned `checkout_url`. They sign into Siglume on the
43
+ hosted page, approve, and pay from their own wallet, then return to your
44
+ `success_url`. Siglume fixes the amount, currency, challenge, and return URLs
45
+ server-side, so the browser cannot tamper with the price or the redirect target.
46
+
47
+ Register your return-URL origins once (open-redirect defense). The origin of
48
+ your `webhook_callback_url` is auto-allowed in addition to these.
49
+
50
+ TypeScript:
51
+
52
+ ```ts
53
+ import { DirectRequestPaymentMerchantClient } from "@siglume/direct-request-payment";
54
+
55
+ const merchant = new DirectRequestPaymentMerchantClient({
56
+ auth_token: process.env.SIGLUME_MERCHANT_AUTH_TOKEN!,
57
+ });
58
+
59
+ // Once, at setup: register the return-URL origin allowlist.
60
+ await merchant.setupCheckout({
61
+ merchant: "example_merchant",
62
+ display_name: "Example Merchant",
63
+ billing_plan: "launch",
64
+ billing_currency: "JPY",
65
+ webhook_callback_url: "https://merchant.example/siglume/webhook",
66
+ checkout_allowed_origins: ["https://www.example.com"],
67
+ });
68
+
69
+ // Per order: create a session and redirect the shopper to checkout_url.
70
+ const session = await merchant.createCheckoutSession({
71
+ merchant: "example_merchant",
72
+ amount_minor: 500, // server-fixed; the browser cannot change it
73
+ currency: "JPY",
74
+ nonce: order.id, // unique per order
75
+ success_url: "https://www.example.com/thanks",
76
+ cancel_url: "https://www.example.com/cart",
77
+ metadata: { order_id: order.id },
78
+ });
79
+
80
+ await orders.update(order.id, {
81
+ siglume_challenge_hash: session.challenge_hash,
82
+ siglume_payment_status: "pending",
83
+ });
84
+
85
+ redirect(session.checkout_url); // -> https://siglume.com/pay/<session_id>
86
+ ```
87
+
88
+ Python:
89
+
90
+ ```py
91
+ import os
92
+
93
+ from siglume_direct_request_payment import DirectRequestPaymentMerchantClient
94
+
95
+ merchant = DirectRequestPaymentMerchantClient(
96
+ auth_token=os.environ["SIGLUME_MERCHANT_AUTH_TOKEN"],
97
+ )
98
+
99
+ # Once, at setup: register the return-URL origin allowlist.
100
+ merchant.setup_checkout(
101
+ merchant="example_merchant",
102
+ display_name="Example Merchant",
103
+ billing_plan="launch",
104
+ billing_currency="JPY",
105
+ webhook_callback_url="https://merchant.example/siglume/webhook",
106
+ checkout_allowed_origins=["https://www.example.com"],
107
+ )
108
+
109
+ # Per order: create a session and redirect the shopper to checkout_url.
110
+ session = merchant.create_checkout_session(
111
+ merchant="example_merchant",
112
+ amount_minor=500, # server-fixed; the browser cannot change it
113
+ currency="JPY",
114
+ nonce=order["id"], # unique per order
115
+ success_url="https://www.example.com/thanks",
116
+ cancel_url="https://www.example.com/cart",
117
+ metadata={"order_id": order["id"]},
118
+ )
119
+
120
+ orders.update(
121
+ order["id"],
122
+ {
123
+ "siglume_challenge_hash": session["challenge_hash"],
124
+ "siglume_payment_status": "pending",
125
+ },
126
+ )
127
+
128
+ # Redirect the shopper to session["checkout_url"]
129
+ # -> https://siglume.com/pay/<session_id>
130
+ ```
131
+
132
+ Fulfill exactly as in [section 4](#4-fulfill-from-webhook): on the signed
133
+ `direct_payment.confirmed` webhook, look up the order by `challenge_hash` and
134
+ mark it paid once. The session is single-use and expires (~30 minutes); you can
135
+ poll `getCheckoutSession` / `get_checkout_session` if you also want to show
136
+ status in your own UI, but the webhook is the source of truth. Honest framing:
137
+ the merchant plumbing integrates quickly, but human web payment still requires
138
+ the shopper to have — or create — a Siglume wallet and pay from it; it is not a
139
+ card-style "instant" checkout for first-time buyers.
21
140
 
22
141
  ## 1. Run Merchant Setup
23
142
 
@@ -42,7 +161,9 @@ const setup = await merchantClient.setupCheckout({
42
161
  max_amount_minor: 100000,
43
162
  });
44
163
 
45
- console.log(setup.env);
164
+ // setup.env holds the merchant key plus the challenge and webhook secrets.
165
+ // Store them in your server-side secret manager; do not log the secret values.
166
+ console.log(`Configured merchant: ${setup.env.SIGLUME_DIRECT_PAYMENT_MERCHANT}`);
46
167
  ```
47
168
 
48
169
  Python:
@@ -65,7 +186,9 @@ setup = merchant_client.setup_checkout(
65
186
  max_amount_minor=100000,
66
187
  )
67
188
 
68
- print(setup["env"])
189
+ # setup["env"] holds the merchant key plus the challenge and webhook secrets.
190
+ # Persist them to your server-side secret store; do not log the secret values.
191
+ print("Configured merchant:", setup["env"]["SIGLUME_DIRECT_PAYMENT_MERCHANT"])
69
192
  ```
70
193
 
71
194
  `setupCheckout` / `setup_checkout` performs:
@@ -157,6 +280,18 @@ The nonce must be unique per order payment attempt and must not contain `:`.
157
280
 
158
281
  ## 3. Buyer Creates and Pays the Requirement
159
282
 
283
+ This is the AI agent / AtoA path: the buyer pays directly through
284
+ `DirectRequestPaymentClient` (or the marketplace tool
285
+ `market_confirm_direct_payment_and_execute`), rather than through Hosted
286
+ Checkout. It assumes the buyer agent is **already connected to Siglume before
287
+ the payment**: an AI client (Claude / ChatGPT / Cursor) connects through the
288
+ Siglume MCP server (OAuth authorization with a consent screen), or a custom app
289
+ holds the buyer's Siglume bearer token (JWT). Either way a Siglume
290
+ authentication context is established first — the merchant SDK does not log the
291
+ buyer in. Unattended runs are bounded by Siglume's approval gates / spending
292
+ budgets (per-run / daily / monthly auto-pay budgets, or Works approval), not by
293
+ the merchant.
294
+
160
295
  After the buyer authenticates with Siglume, create the payment requirement with
161
296
  the buyer's Siglume bearer token. Do not use a Developer Portal `cli_` API key
162
297
  or merchant API key here.
package/docs/pricing.md CHANGED
@@ -26,13 +26,14 @@ quoted per currency.
26
26
 
27
27
  | Payment amount | Applied automatically | What you select | Fee | Settlement |
28
28
  | --- | --- | --- | --- | --- |
29
- | Over JPY 500 / over USD 3.00, or whenever immediate finality is required | Standard Payment | Select one Standard plan: Launch, Starter, Growth, or Pro | Launch: JPY 0 / USD 0 monthly, 1.8%; Starter: JPY 980 / USD 6 monthly, 1.0%; Growth: JPY 2,980 / USD 18 monthly, 0.7%; Pro: JPY 9,800 / USD 60 monthly, 0.5%. Minimum JPY 30 / USD 0.20 per payment. | Immediate on-chain split through DirectPaymentHub after payment confirmation |
30
- | JPY 50-500 / about USD 0.30-3.00 | Micro Payment | No selection. Applied automatically by amount. | USD 0.01 / Tx, about JPY 2 | Meter gate before provider execution; weekly delayed settlement |
31
- | Under JPY 1 to JPY 49 / under USD 0.01 to about USD 0.30 | Nano Payment | No selection. Applied automatically by amount. | USD 0.001 / usage, about JPY 0.2 | Meter gate before provider execution; monthly delayed settlement |
29
+ | Over JPY 500 / over USD 3.00, or whenever immediate finality is required | Standard Payment | Select one Standard plan: Launch, Starter, Growth, or Pro | Launch: JPY 0 / USD 0 monthly, 1.8%; Starter: JPY 980 / USD 6 monthly, 1.0%; Growth: JPY 2,980 / USD 18 monthly, 0.7%; Pro: JPY 9,800 / USD 60 monthly, 0.5%. Minimum JPY 30 / USD 0.20 per payment. | Settled on-chain immediately after the payment confirms |
30
+ | JPY 50-500 / about USD 0.30-3.00 | Micro Payment | Applied automatically by amount | USD 0.01 / Tx, about JPY 2 | Aggregated and settled **weekly** (see [Settlement schedule](#settlement-schedule)) |
31
+ | Under JPY 1 to JPY 49 / under USD 0.01 to about USD 0.30 | Nano Payment | Applied automatically by amount | USD 0.001 / usage, about JPY 0.2 | Aggregated and settled **monthly** (see [Settlement schedule](#settlement-schedule)) |
32
32
 
33
- For Micro Payment and Nano Payment, the SDRP meter gate runs before provider
34
- execution. Budget or scope failures are recorded as `rejected_no_charge`; the
35
- provider API is not called and no pending provider revenue is created.
33
+ Standard Payment settles per payment. Micro Payment and Nano Payment are
34
+ aggregated and settled on a fixed weekly / monthly cadence — see
35
+ [Settlement schedule](#settlement-schedule) for exactly when each band closes,
36
+ when revenue becomes settled, and how rejected requests behave.
36
37
 
37
38
  USD pricing is the JPY tier converted at roughly 160 JPY/USD and rounded to
38
39
  clean price points that keep the same 1:3:10 tier ratio.
@@ -41,21 +42,95 @@ If no paid plan is selected during merchant setup, the merchant account uses the
41
42
  Launch plan. A merchant billing mandate is still required before accepting
42
43
  payments so Siglume can collect the monthly base fee automatically.
43
44
 
44
- The current Siglume API and merchant registry may still expose the internal
45
- `billing_plan` value `free` for the Launch tier. Treat `free` as an internal
46
- compatibility key, not the public plan name. (Until 2026-06-12 the Launch plan
47
- included a free monthly allowance of 100 payments; that allowance has been
48
- retired — the platform `fee_bps` response is always the source of truth.)
49
-
50
- Per-payment fees are collected during payment settlement through the
51
- DirectPaymentHub split. The merchant receives the net amount after that fee.
52
- Monthly base fees are collected separately through the merchant billing mandate.
45
+ Per-payment fees are deducted at settlement, so the merchant receives the net
46
+ amount for each payment. Monthly base fees are collected separately through the
47
+ merchant billing mandate.
53
48
 
54
49
  The same fee schedule applies in JPY and USD. The Siglume platform returns
55
50
  `fee_bps` in the merchant's settlement currency on every payment requirement, so
56
51
  the SDK never has to know which currency table to read — it just trusts the
57
52
  value Siglume returns.
58
53
 
54
+ ## Settlement schedule
55
+
56
+ Standard Payment, Micro Payment, and Nano Payment differ mainly in *when* a
57
+ confirmed payment turns into money in your settlement wallet.
58
+
59
+ | Band | Cadence | Period | You are paid |
60
+ | --- | --- | --- | --- |
61
+ | Standard Payment | Per payment | n/a | On-chain, immediately after each payment confirms |
62
+ | Micro Payment | Weekly | Buyer settlement timezone Monday 00:00 to the next Monday 00:00; default timezone is UTC | After the week closes, in aggregated on-chain settlement(s) grouped per buyer, payee, token, and period |
63
+ | Nano Payment | Monthly | Buyer settlement timezone 1st 00:00 to the 1st of the next month 00:00; default timezone is UTC | After the month closes, in aggregated on-chain settlement(s) grouped per buyer, payee, token, and period |
64
+
65
+ ### Micro weekly settlement
66
+
67
+ - **Closing period.** Micro-band payments accrue across one calendar week:
68
+ Monday 00:00 to the following Monday 00:00 in the buyer settlement timezone.
69
+ - **Timezone.** Period boundaries are evaluated in the buyer's configured
70
+ settlement timezone, defaulting to UTC, so different buyers can close on
71
+ slightly different local boundaries.
72
+ - **Settlement.** After the week closes, Siglume aggregates that week's Micro
73
+ payments — grouped per buyer, payee, token, and period — into on-chain
74
+ settlement(s). Aggregation and payment run automatically on the next settlement
75
+ pass after the period closes; there is a short, platform-managed lag between
76
+ the close and the on-chain transaction.
77
+ - **Revenue recognition.** A Micro payment is final only once its weekly
78
+ settlement confirms on-chain. Until then it is accrued, not settled.
79
+
80
+ ### Nano monthly settlement
81
+
82
+ - **Closing period.** Nano-band payments accrue across one calendar month:
83
+ the 1st at 00:00 to the 1st of the next month at 00:00 in the buyer
84
+ settlement timezone.
85
+ - **Timezone.** As with Micro, period boundaries use the buyer's configured
86
+ settlement timezone, defaulting to UTC.
87
+ - **Settlement.** After the month closes, Siglume aggregates that month's Nano
88
+ payments — grouped per buyer, payee, token, and period — into on-chain
89
+ settlement(s), on the next settlement pass after the period closes.
90
+ - **Revenue recognition.** A Nano payment is final only once its monthly
91
+ settlement confirms on-chain.
92
+
93
+ ### Failures, retries, and carry-over
94
+
95
+ - Settlement is on-chain, so there are no banking-holiday gaps — periods close on
96
+ the calendar boundary regardless of weekday.
97
+ - If a settlement fails because of insufficient balance, insufficient allowance,
98
+ inactive BudgetVault authorization, a per-payout cap, or an on-chain failure,
99
+ the affected batch is treated as past due. Siglume currently retries every 6
100
+ hours for up to 28 automatic attempts. After that, the batch remains past due
101
+ and requires manual resolution before another attempt.
102
+ - While a buyer has an unresolved failed Micro/Nano settlement for the same
103
+ payment band and token, new Micro/Nano usage is paused with the machine-readable
104
+ error `METERED_SETTLEMENT_PAST_DUE`; the provider API is not called.
105
+ - Outstanding amounts remain attached to the failed settlement and are retried
106
+ under this policy. They are not settled revenue, and Siglume does not advance,
107
+ guarantee, or insure provider revenue before on-chain settlement succeeds.
108
+
109
+ ### Rejected / no-charge behavior
110
+
111
+ Micro and Nano run a budget check before the buyer's paid request is fulfilled:
112
+
113
+ - A buyer's wallet budget is consumed at the **gross amount** (your price plus
114
+ the protocol fee), held from the moment a request is accepted until its
115
+ settlement confirms.
116
+ - If the buyer's budget, scope, or amount band does not allow a request, it is
117
+ **rejected with no charge**: the request is not fulfilled, no amount is
118
+ accrued, and nothing is added to a settlement. A buyer near their budget
119
+ ceiling can have a request rejected even though earlier requests in the same
120
+ period succeeded.
121
+ - Treat Siglume's settled status and webhooks as the source of truth for what has
122
+ actually been paid.
123
+
124
+ ### What is fixed vs platform-managed
125
+
126
+ The cadence is fixed: **Micro settles weekly, Nano settles monthly**, and a
127
+ payment is final only after its on-chain settlement confirms. The buyer-timezone
128
+ period boundaries and the current retry policy above are the public behavior as
129
+ of 2026-06-18. The scheduler lag between a period close and the on-chain
130
+ transaction is platform-managed; treat the platform's settlement status and
131
+ `fee_bps` response as authoritative rather than hard-coding local revenue
132
+ recognition.
133
+
59
134
  ## SDK Behavior
60
135
 
61
136
  The SDK does not calculate merchant invoices or enforce plan limits locally.
@@ -72,3 +147,11 @@ The trial pricing is intended for:
72
147
  - Membership services
73
148
  - Paid API access
74
149
  - Scheduled autopay for external merchant workflows
150
+
151
+ ## Compatibility note
152
+
153
+ The Siglume API and merchant registry may still expose the legacy `billing_plan`
154
+ value `free` for the Launch tier. Treat `free` as a wire-compatibility key, not a
155
+ public plan name. (Until 2026-06-12 the Launch plan included a free monthly
156
+ allowance of 100 payments; that allowance has been retired — the platform
157
+ `fee_bps` response is always the source of truth.)
package/docs/security.md CHANGED
@@ -49,6 +49,23 @@ autopay approval tag; it does not itself limit occurrences to once per day.
49
49
  Scheduled autopay execution is bounded by the buyer-approved per-run, daily, and
50
50
  monthly auto-pay budget.
51
51
 
52
+ ## Hosted Checkout Return URLs
53
+
54
+ Hosted Checkout adds a return-URL origin allowlist as open-redirect defense.
55
+ Register your allowed origins once via `checkout_allowed_origins` on
56
+ `setupCheckout` / `setupMerchant`. A checkout session's `success_url` and
57
+ `cancel_url` must be on a registered origin; the origin of your
58
+ `webhook_callback_url` is auto-allowed in addition. Each entry must be an
59
+ absolute origin such as `https://shop.example.com`; entries are normalized to
60
+ bare, lowercased origins and deduped. A return URL that is not on an allowed
61
+ origin is rejected, so an attacker cannot point a session at an arbitrary
62
+ redirect target.
63
+
64
+ For a Hosted Checkout session, Siglume authors the amount, currency, challenge,
65
+ and return URLs server-side at session creation. The browser cannot tamper with
66
+ the price or the redirect target, and the raw challenge is never exposed to the
67
+ browser or returned by `getCheckoutSession`.
68
+
52
69
  ## Do Not Trust Browser Amounts
53
70
 
54
71
  The merchant server owns:
@@ -106,9 +123,14 @@ Direct Request Payment is not:
106
123
  - escrow
107
124
  - a platform balance
108
125
  - a card payment fallback
109
- - the Micro Payment or Nano Payment meter
110
126
 
111
- It is a Standard Payment wallet gate backed by an on-chain receipt. Micro
112
- Payment and Nano Payment are SDRP amount bands with internal-meter,
113
- delayed-settlement behavior; they must fail closed before provider API
114
- execution when the buyer's metered budget, scope, or amount band is invalid.
127
+ Each payment is an individual wallet payment backed by an on-chain receipt. Small
128
+ payments in the Micro and Nano amount bands are aggregated and settled on a
129
+ weekly / monthly cadence instead of one transaction at a time (see the
130
+ [pricing guide](./pricing.md#settlement-schedule)), but they are still wallet
131
+ payments, not a stored balance. Before a small payment is fulfilled, Siglume
132
+ checks the buyer's wallet budget and fails closed when it is invalid, so a
133
+ rejected request is never charged. Provider revenue for Micro and Nano remains
134
+ unsettled until the weekly or monthly on-chain settlement succeeds; Siglume does
135
+ not advance or guarantee revenue when a buyer's balance, allowance, BudgetVault
136
+ authorization, cap, or on-chain transaction fails.
@@ -99,8 +99,10 @@ app.post("/siglume/webhook", express.raw({ type: "application/json" }), asyncRou
99
99
  }));
100
100
 
101
101
  app.use((error: unknown, _req: express.Request, res: express.Response, _next: express.NextFunction) => {
102
- const message = error instanceof Error ? error.message : "internal_error";
103
- res.status(500).json({ error: message });
102
+ // Log the detail server-side; never return raw error messages to the client —
103
+ // a payment error can otherwise leak internal API details or configuration.
104
+ console.error("checkout error:", error);
105
+ res.status(500).json({ error: "internal_error" });
104
106
  });
105
107
 
106
108
  app.listen(port);
@@ -14,4 +14,12 @@ const setup = await merchant.setupCheckout({
14
14
  create_webhook_subscription: Boolean(process.env.SIGLUME_DIRECT_PAYMENT_WEBHOOK_URL),
15
15
  });
16
16
 
17
- console.log(JSON.stringify(setup, null, 2));
17
+ // setup.env contains the merchant key PLUS the challenge and webhook secrets.
18
+ // Store these in your server-side secret manager. Never log the secret values —
19
+ // log only non-secret confirmation.
20
+ const env = setup.env ?? {};
21
+ console.log("Merchant configured:", {
22
+ merchant: env.SIGLUME_DIRECT_PAYMENT_MERCHANT,
23
+ challenge_secret: env.SIGLUME_DIRECT_PAYMENT_CHALLENGE_SECRET ? "****" : undefined,
24
+ webhook_secret: env.SIGLUME_WEBHOOK_SECRET ? "****" : undefined,
25
+ });
package/package.json CHANGED
@@ -1,13 +1,18 @@
1
1
  {
2
2
  "name": "@siglume/direct-request-payment",
3
- "version": "0.3.5",
3
+ "version": "0.4.0",
4
4
  "description": "SDK for the Siglume Direct Request Payment SDRP payment protocol",
5
5
  "keywords": [
6
6
  "siglume",
7
+ "sdrp",
8
+ "direct-request-payment",
7
9
  "payment",
8
- "checkout",
9
- "external-402",
10
+ "micropayments",
11
+ "metered-billing",
10
12
  "wallet",
13
+ "jpyc",
14
+ "usdc",
15
+ "checkout",
11
16
  "sdk"
12
17
  ],
13
18
  "license": "MIT",