frontpage-host 0.1.29 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +8 -2
- package/CUSTOMER-INBOX.md +38 -5
- package/PAYMENTS.md +411 -0
- package/README.md +6 -0
- package/dist/argv.d.ts +2 -0
- package/dist/argv.js +8 -0
- package/dist/bin.js +3 -0
- package/dist/commands/payments.d.ts +1 -0
- package/dist/commands/payments.js +315 -0
- package/dist/commands/shop.js +42 -87
- package/dist/completions/generate.js +12 -6
- package/dist/registry.js +92 -43
- package/llms.txt +8 -2
- package/package.json +4 -3
package/AGENTS.md
CHANGED
|
@@ -119,7 +119,7 @@ Sites are Astro 6 + Tailwind v4. More detail: `frontpage help site-building` or
|
|
|
119
119
|
## Modules & articles
|
|
120
120
|
|
|
121
121
|
- Forms: `data-fp-form` markup in pages + `frontpage modules` for enable/config. No submit JS / honeypot / `action`. Do not put a CRM webhook or token in HTML.
|
|
122
|
-
- Connect-once modules: Store Stripe connect is `frontpage
|
|
122
|
+
- Connect-once modules: Store Stripe connect is `frontpage payments connect`. `--no-open` for CI. `request-setup` remains valid when you want the **editor amber bar** instead. Payments and Store share one Stripe account. Pause Payments through its availability action; generic module writes cannot bypass invoice/recurring stop rules. Auto-active modules (forms/callbar/…) need markup, not request-setup. Typed settings: `frontpage modules callbar|forms|booking|signups get|set` (forms set needs `--instance`; do not target `default`). Form destinations (HubSpot / Pipedrive / Privyr): connect once, then attach each form. `frontpage modules forms destinations|connect-destination|attach-destination|detach-destination|remove-destination --yes|request-destination-setup`. Token write is **admin**; `request-destination-setup` lights the editor amber bar (**editor** key). Do not use `request-setup forms` for a CRM (no-op). Connecting does not attach every form. Privyr: paste the Incoming Webhook URL from Automations → Lead Sources → Webhooks (`https://www.privyr.com/api/v1/incoming-leads/…`), not a token and not Outgoing Webhooks. HubSpot: Development → Keys → Service keys or Development → Legacy apps → Auth → Show token. Pipedrive: profile → Company settings → Personal preferences → API. Full docs: https://frontpage.host/developers/modules#forms-destinations. `frontpage modules <key>` prints that key's CLI usage (exit 2). Index: https://frontpage.host/developers/modules. Store: https://frontpage.host/developers/store
|
|
123
123
|
- Google reviews: platform nodes only (`data-fp-google-reviews` / `data-fp-google-ask` + required `data-fp-requires="google_reviews"`). `data-layout` is `feed` (default), `badge`, or `link`. Never invent stars, quotes, a 1–10, or a Maps URL. Do not pick a Place ID via Autocomplete and do not write `placeId` through `modules config`. Owner-supplied Place ID / Maps URL: `frontpage modules google_reviews connect --place-id …` or `--maps-url …` (server resolves + seeds). Curation: `list-reviews`, `hide --id`, `show --id`, `set-stars`, `set-sort`, `set-weight`, `reset-weights`, `refresh`, `disconnect`. Usage: `frontpage modules google_reviews`. Docs: https://frontpage.host/developers/modules/google-reviews. Ask-widget scores: `frontpage inbox google_reviews`.
|
|
124
124
|
- Articles: `frontpage articles …` for lifecycle; bodies via sync under `content/` or `articles content get|set`. Section landing is an owned `src/pages/<section>/index.astro`.
|
|
125
125
|
- Migrate a folder into Articles: prefer `frontpage prompt "migrate … into articles"` — do not invent a mass delete+write migration.
|
|
@@ -129,7 +129,7 @@ Sites are Astro 6 + Tailwind v4. More detail: `frontpage help site-building` or
|
|
|
129
129
|
- Analytics: bare `frontpage analytics` = dashboard; also `summary|query|funnel|timeseries|compare|sql` for structured reads (SQL is guard + RLS site-scoped).
|
|
130
130
|
- People CRM: `frontpage people list|get|add|set|note|rm-note|follow-up|hide|unhide|tag|export`. Site-scoped person graph (email or phone). Inbox stays the raw ledger. Hide is not forget. List export is CSV (not a one-person legal dump). Full guide: https://frontpage.host/developers/people
|
|
131
131
|
- Routines: `frontpage routines list|get|add|set|pause|resume|rm|run|runs`. One routine can hold several hours and several days. `8am,12pm,4pm` on `tue,thu,fri` stores hours `[8, 12, 16]` and weekdays `[2, 4, 5]`. Ask for an IANA timezone. Do not guess UTC. Full guide: https://frontpage.host/developers/routines
|
|
132
|
-
- Store catalog: `frontpage store items|variants|categories|settings|orders|
|
|
132
|
+
- Store catalog: `frontpage store items|variants|categories|settings|orders|import`. Integer cents only (`$49.99` is `4999`). `--price-cents` is the usual cost. Optional `--discount-cents` is the sale the buyer pays (must be lower). Create a category before assigning it. Photos are a site path `/__media/uploads/<this-slug>/…` or an HTTPS URL already saved on this site. `frontpage payments connect [--no-open]` opens Frontpage then Stripe. Store always uses Add to cart. Use Payments for standalone Pay now and invoices. Service fee is `settings set-checkout-fee`. The cart starts hidden. Product pages are the default: unless they said they do not want product pages, write one `src/pages/products/item.astro` (or shop) with `data-fp-store-product`. If they said no, skip that file and do not bind `href` or `url`. Description is a small markdown subset; product-page bind is `<div data-fp-store-bind="description">`. Every store control carries `data-fp-requires="store"`. Do not bake titles or prices. Full guide: https://frontpage.host/developers/store
|
|
133
133
|
|
|
134
134
|
## Agent prompt loop
|
|
135
135
|
|
|
@@ -261,3 +261,9 @@ Use `frontpage people overview`, `groups`, `stages`, `membership`, `rules`, `att
|
|
|
261
261
|
## Customer Inbox
|
|
262
262
|
|
|
263
263
|
Internal, allowlisted sites only. Use `frontpage customer-inbox get|put|post RESOURCE`, stable write keys and current versions. Full guide: [CUSTOMER-INBOX.md](./CUSTOMER-INBOX.md). `export CONVERSATION_ID --out FILE` writes authorized paginated history and file metadata; `download FILE_ID --out FILE` downloads through a file grant. Outputs never overwrite existing files. `frontpage usage` reports shared site credits, mail and storage. Human owners may handle conversations; website agents use `manage_customer_inbox` for setup/settings/widget/internal knowledge only, never a human CLI key to read or join customer threads.
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
Payments, invoices and recurring billing: see packaged [PAYMENTS.md](./PAYMENTS.md), `frontpage help payments`, and https://frontpage.host/developers/payments. Version 0.2.0 removes writable currency, Store checkout mode and Store-owned money commands; Store stays cart-only. Preview/review before sends; keep stable operation keys on retries. Autopay requires the customer’s own verified authorization.
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
Offerings own every standalone Pay now payment. Use `frontpage payments buttons list|get|create|update|archive|restore`; create the saved offering before adding its returned `data-fp-pay` markup. Supports `--receipt-template-id UUID`, `--default-receipt`, `--active true|false`, combined price/details updates and JSON payloads. Archive deletes from active checkout but preserves history. The website agent uses the same service automatically for ordinary payment-button requests. Store stays cart-only; invoices stay saved customer-addressed records. Full instructions: PAYMENTS.md and https://frontpage.host/developers/payments.
|
package/CUSTOMER-INBOX.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Customer Inbox
|
|
2
2
|
|
|
3
|
-
Customer Inbox uses the site's existing AI credits and storage allowance. It is available on internal plans and approved pilot sites. The support agent uses fixed GPT-6 Luna and bills AI usage at 10× raw provider cost.
|
|
3
|
+
Customer Inbox uses the site's existing AI credits and storage allowance. It is available on internal plans and approved pilot sites. The support agent uses fixed GPT-6 Luna and bills AI usage at 10× raw provider cost. During human handling, customer messages use ordinary routing. Each authenticated owner email uses a small metered Luna Decisions call to keep private guidance, ownership controls and customer-facing replies distinct; the full support agent stays paused. UI and CLI controls need no intent call.
|
|
4
4
|
|
|
5
5
|
Run `frontpage help customer-inbox`. Use the site's normal CLI key:
|
|
6
6
|
|
|
@@ -28,6 +28,12 @@ Setup binds private guidance to the verified owner who requested it. That identi
|
|
|
28
28
|
|
|
29
29
|
Settings allow `enabled`, `instructions`, `tools`, `maxSteps` (1–12), `maxOutputTokens` (256–2400), and `maxInputBytes` (4000–64000). Supported tools: `knowledge_read`, `knowledge_update`, `customer_read`, `customer_update`, `notes_read`, `note_add`, `ask_owner`, `reply_customer`, `wait`, `finish`. Keep `wait` and `finish` enabled. Defaults: 8 steps, 1200 output tokens per call, 32000 bytes of public text. Model, billing multiplier and recipients are not caller-selectable fields. The worker also enforces platform concurrency, deadlines and input limits.
|
|
30
30
|
|
|
31
|
+
`maxContextTokens` (12000–96000, default 32000) sets a conservative per-call input plus output allowance. UTF-8 text bytes, tool definitions, instructions, transcript and image capacity count toward admission; exact provider tokens still determine billing. Optional older history and preloaded notes drop first. Essential evidence is never clipped: if it cannot fit, the job pauses for review. History stays stored without a lifetime message-count stop. The agent receives up to 40 recent messages plus required current input and owner guidance, and can retrieve older messages in bounded pages under its existing `knowledge_read` grant.
|
|
32
|
+
|
|
33
|
+
`reviewAfterReplies` (0–200, default 0/off) and `reviewWindowHours` (1–168, default 24) request private owner guidance after that many recent automated replies since the last guidance. Pending requests deduplicate. This is a rolling work control, not a cap on returning customers or retained history.
|
|
34
|
+
|
|
35
|
+
Customer replies commit before optional knowledge, People enrichment and notes. The same durable jobs table carries separate internal maintenance with the same credits, exact receipts and 10× pricing. It cannot send messages, request owner help, change ownership or edit public content. The workspace shows unfinished internal work separately and offers the existing safe retry controls for recoverable failures. Identical note content does not create another revision.
|
|
36
|
+
|
|
31
37
|
Aliases use 3–48 ASCII letters, numbers and single hyphens. The service normalizes case and checks collisions in one transaction. Reserved platform names and routing namespaces cannot be claimed. Retired addresses remain reserved; they never move to another site.
|
|
32
38
|
|
|
33
39
|
## Internal knowledge and approved sources
|
|
@@ -64,9 +70,21 @@ Lock a knowledge note with `locked:true`. The support agent cannot change locked
|
|
|
64
70
|
|
|
65
71
|
Private guidance stays in the same internal thread. The agent asks by a private email and stores its question in the history. Replying by email or UI gives context and leaves the agent responsible for the customer. The agent uses that context to answer and can update unlocked internal knowledge.
|
|
66
72
|
|
|
67
|
-
|
|
73
|
+
General owner facts, such as support hours and standard policies, update related unlocked knowledge without an explicit save request. One-time customer exceptions and private staffing details stay in the conversation. The agent reads the full note and records verified evidence before changing it. Late private guidance can still update knowledge after the customer has an answer; that work cannot send a duplicate customer reply. Locks, manual handling, paused automation and work limits still apply.
|
|
74
|
+
|
|
75
|
+
Shared knowledge must remain useful and true for other customers when the current customer, order and case are removed. Individual delivery estimates, arrangements and fee waivers stay in that conversation or its bound People contact's factual notes. A “customer-specific” disclaimer does not make them shared business policy. Maintenance can finish successfully without writing any knowledge.
|
|
76
|
+
|
|
77
|
+
Search results contain previews. The support agent reads the complete matching note or approved source before deciding an answer is missing. A verified owner reply can provide lasting facts on a different topic from the customer's question; the agent answers the customer first, then separate internal maintenance processes lasting facts. The worker verifies the message kind and owner identity. Customer text cannot claim that authority. A specific offer to one customer stays in that thread even when the same owner reply also contains a general policy.
|
|
78
|
+
|
|
79
|
+
Email replies route through opaque, recipient-bound Reply-To addresses linked to the site, conversation, purpose, owner and handler version. These are local addresses on one domain, not a new subdomain per thread. Subjects and message text never select the customer thread. The service checks the exact verified sender, current owner membership, route and receiving-server DMARC proof before interpreting owner mail.
|
|
80
|
+
|
|
81
|
+
Every owner email and its files enter private custody first. A Luna Decisions call reads the fresh text and bounded, labeled thread context to distinguish guidance, takeover, return, customer reply or unclear input. Use ordinary language to ask to handle the customer, or ask the agent to resume. Questions, quoted commands, negations and future conditions do not transfer control. UI/CLI `control` remains a typed, model-free action. No phrase whitelist controls ownership. A valid but uncertain control answer can use one bounded Luna tool-call fallback. It can choose only private guidance, takeover, return or unclear, with an exact fresh-text excerpt; it cannot authorize a customer reply. Both calls require current credits and distinct once-only receipts. Invalid responses, unknown paid calls and provider outages stay private rather than triggering another inference.
|
|
82
|
+
|
|
83
|
+
Guidance keeps the agent responsible. Takeover sends the owner a separate customer-visible transcript; reply through that relay address so Inbox preserves the history. A customer-facing email creates a separate public message only after a settled decision and current owner-session check. The original intake remains private for audit. Mixed or uncertain input, unavailable inference and exhausted credits stay private with an attention notice. Retry recoverable budget/receipt pauses using the existing job operation; an unknown paid attempt is never inferred again. A fresh reply to the original guidance address can also request return, while stale customer-relay sessions cannot publish.
|
|
68
84
|
|
|
69
|
-
|
|
85
|
+
Private owner help, customer relay and customer email use separate threading chains. Inbox stores Resend's actual Message-ID and sends In-Reply-To/References; it never invents provider message IDs. Missing metadata uses scoped reconciliation without another send. Mail clients still control their own grouping. Owners and customers do not share a CC help thread. If the owner already addressed the customer, Inbox records the canonical public reply but does not send a second customer email.
|
|
86
|
+
|
|
87
|
+
Return checks current settings, site eligibility, unanswered work and site credits before support can resume. It cancels stale automatic work rather than replaying an old answer.
|
|
70
88
|
|
|
71
89
|
Set `enabled:false` in settings to use manual handling for new conversations. The service binds that relay to the configured verified owner. Existing agent threads switch to manual handling on the next customer message or public owner reply. Re-enable the agent before returning a thread to it. Private guidance alone always stays private and never transfers control.
|
|
72
90
|
|
|
@@ -160,6 +178,10 @@ const identity = encoded + "." + createHmac("sha256", process.env.INBOX_IDENTITY
|
|
|
160
178
|
|
|
161
179
|
The service verifies the signature, site, origin and expiry. Assertions can last at most five minutes. They grant customer identity only, never owner or manager authority. Every app-session request must include the current signed identity matching that session's subject and email. Put a server-rendered assertion in `data-identity`, or preferably provide `data-identity-url="/api/support-identity"`. That same-origin HTTPS endpoint authenticates the current app user and returns `{"identity":"<signed assertion>"}`. The widget refreshes it; after logout or account changes, old app sessions cannot be read without the matching identity. Anonymous widgets need no assertion. Each approved origin has its own visitor session; email continues the bound conversation.
|
|
162
180
|
|
|
181
|
+
Browser access lasts 30 days from creation or successful email verification/recovery. Verification links last one hour and work once; confirming rotates the credential. The widget retains access in that browser's storage and keeps it through temporary network failures. Returning browsers with valid access reopen their history automatically. When access is missing, the ordinary **Continue** and email-confirmation flow can reconnect an empty replacement session to the latest open conversation with a matching verified email on that same website origin. A typed email alone never restores history. Nonempty conversations remain separate; revoked access and authenticated app identities cannot use this path. The developer recovery endpoint remains available, but customers do not need a separate Recover workflow. Email continuation uses an inline email field. An empty unverified saved session with an email requests confirmation automatically; a stable receipt prevents reloads from sending duplicate emails.
|
|
182
|
+
|
|
183
|
+
The same conversation's customer-visible email and chat messages load together, including owner replies relayed through Inbox. They stay stored after browser access expires. Private guidance, internal notes and system notices never enter that public history. Recovery restores access to the saved conversation rather than starting its history over.
|
|
184
|
+
|
|
163
185
|
## Conversation state, exports and shared usage
|
|
164
186
|
|
|
165
187
|
| Resource | Method | Body or behavior |
|
|
@@ -199,11 +221,12 @@ On app logout or account change, call `window.dispatchEvent(new Event("frontpage
|
|
|
199
221
|
|
|
200
222
|
## Support agent tool contract
|
|
201
223
|
|
|
202
|
-
The support agent has its own system prompt plus the versioned private business instructions. Tool calls stay in Inbox's tenant, conversation, handler, configuration and job context. All ten
|
|
224
|
+
The support agent has its own system prompt plus the versioned private business instructions. Tool calls stay in Inbox's tenant, conversation, handler, configuration and job context. All ten configurable tool grants start enabled; `wait` and `finish` cannot be removed. A disabled tool fails at the server.
|
|
203
225
|
|
|
204
226
|
| Tool | Inputs | Effect and limits |
|
|
205
227
|
| --- | --- | --- |
|
|
206
228
|
| `knowledge_read` | `query`, `id` or `sourceId` | Search internal notes or read complete approved evidence. |
|
|
229
|
+
| `history_read` | `before`, optional `query` | Retrieve up to ten older eligible messages in the assigned conversation under the `knowledge_read` grant; bounded to 6000 text characters. |
|
|
207
230
|
| `knowledge_update` | Optional `id`; `title`, `body`, `expectedVersion`, `reason`, `evidenceKind`, `evidenceId`; source `evidenceVersion` | Update unlocked internal facts from verified guidance in this thread or an approved source revision. One-off guidance stays in the conversation. No public editing. |
|
|
208
231
|
| `customer_read` | None | Read only this thread's verified People contact. |
|
|
209
232
|
| `customer_update` | `name`/`phone`, `evidenceMessageId` | Enrich from an explicit customer statement; cannot change identity or permission. |
|
|
@@ -214,4 +237,14 @@ The support agent has its own system prompt plus the versioned private business
|
|
|
214
237
|
| `wait` | `reason` | Pause safely without sending. |
|
|
215
238
|
| `finish` | None | Complete this bounded job. |
|
|
216
239
|
|
|
217
|
-
Decisions screens malicious input
|
|
240
|
+
Decisions screens malicious customer input and interprets authenticated owner-email intent. It never chooses IDs, recipients, permissions, business answers, support tools or knowledge changes. Owner intent uses bounded labeled context, one primary Luna call, at most one bounded same-Luna control fallback, and the same exact-token, raw-cost, 10× ledger receipt as support. Shared inference utilities provide the existing same-model credential/transport fallback; no expensive model substitution or customer model picker is added.
|
|
241
|
+
|
|
242
|
+
The installed widget loads two public static scripts: `/customer-inbox/widget.js` and `/customer-inbox/view.js` on `https://app.frontpage.host`. The shared renderer contains no session, owner data or credentials. If your app sets a Content Security Policy, allow those script URLs and connections to `https://frontpage-inbox-api.fly.dev`; keep the existing widget origin and identity checks. Owner Inbox pages remain authenticated.
|
|
243
|
+
|
|
244
|
+
## Live updates and email continuation
|
|
245
|
+
|
|
246
|
+
The workspace uses a short authenticated stream through its cookie bridge; the installed widget uses authenticated fetch with its existing visitor/app-identity headers. Streams carry empty invalidation hints, never message text, private counters, recipients or file metadata. Clients re-read their authorized history/status. One restricted Postgres listener per Inbox process wakes the existing outbox publisher and fans out hints. Notifications are best-effort; durable rows, leases, recovery scans and receipt reconciliation remain authoritative. Disconnected clients refresh and use bounded fallback polling. No token enters a stream URL, and each short stream reauthorizes on reconnect.
|
|
247
|
+
|
|
248
|
+
A new unverified chat with an email requests a generic verification email automatically. It does not send private history or assume that typing an address proves identity. The owner can still answer in chat while the visitor verifies. Confirmation rotates the session and binds future public replies to that email; if the latest customer input already has an unsent public answer, Inbox queues that one answer once. It does not mail a backlog or an answer that predates a newer customer question. Verified replies mirror to email whether the page is open or closed; no presence-tracking service is needed.
|
|
249
|
+
|
|
250
|
+
The workspace shows customer name/email first, latest public message in each row, and a copyable reference in conversation details. Conversation list and history scroll independently inside a bounded viewport. Settings use shared workspace controls and a presentation-only preview built from the same renderer as the installed widget. Preview changes send no email or model request. Internal note history/locks/revert stay on the note's own page.
|
package/PAYMENTS.md
ADDED
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
# Payments reference
|
|
2
|
+
|
|
3
|
+
Frontpage keeps one Stripe Express account per site. Store owns products, cart
|
|
4
|
+
checkout, fulfillment, buyer service fees, receipt selection and orders. Payments
|
|
5
|
+
owns Stripe setup, tax, payment activity, standalone Pay now and merchant invoices.
|
|
6
|
+
Frontpage subscription billing stays separate.
|
|
7
|
+
|
|
8
|
+
Use `frontpage help payments --json` for discoverable command help. Normal
|
|
9
|
+
`--site`, authentication, `--json`, `--quiet` and exit-code rules apply. The API
|
|
10
|
+
requires Scale, Enterprise or Internal CLI access. This does not remove product
|
|
11
|
+
permissions or invoice entitlements.
|
|
12
|
+
|
|
13
|
+
## Access and output
|
|
14
|
+
|
|
15
|
+
| Operation | Minimum role | Additional rule |
|
|
16
|
+
| --- | --- | --- |
|
|
17
|
+
| Connection status | Viewer | Site membership |
|
|
18
|
+
| Private activity, invoices, arrangements, tax and Pay now reads | Editor | Site membership |
|
|
19
|
+
| Existing tax settings and registration writes | Editor | Explicit supplied jurisdiction/address and confirmation |
|
|
20
|
+
| Stripe browser setup, payment availability, Pay now writes, invoice sends and billing links | Admin | Confirmation where specified |
|
|
21
|
+
| New invoice, new arrangement or resume | Admin | Growth or higher and Payments ready |
|
|
22
|
+
| Historical reads, refresh, void and future cancellation after downgrade | Existing role above | No new invoice entitlement required |
|
|
23
|
+
|
|
24
|
+
All routes authorize the API-key owner against the requested site. A different
|
|
25
|
+
site's record returns 404. Request fields cannot grant a role, change the trusted
|
|
26
|
+
site or choose a connected account. JSON success uses the existing CLI envelope
|
|
27
|
+
`{ "ok": true, "command": "payments", "data": { ... } }`. Failure uses the
|
|
28
|
+
existing error envelope with request ID and exit code. Human mode prints the
|
|
29
|
+
returned fields, including partial outcomes. A successful HTTP request does not
|
|
30
|
+
mean a payment settled or an email arrived.
|
|
31
|
+
|
|
32
|
+
## Setup, availability and history
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
frontpage payments status
|
|
36
|
+
frontpage payments settings --json
|
|
37
|
+
frontpage payments connect --no-open
|
|
38
|
+
frontpage payments availability preview --json
|
|
39
|
+
frontpage payments availability off --yes
|
|
40
|
+
frontpage payments availability on --yes
|
|
41
|
+
frontpage payments activity list --json
|
|
42
|
+
frontpage payments activity get <record-uuid> --source order
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Connect returns the existing signed-in admin browser URL. Without `--no-open`,
|
|
46
|
+
human mode opens it. The CLI does not accept Stripe terms, finish onboarding or
|
|
47
|
+
create another account to get around a restriction. Recheck `status` after the
|
|
48
|
+
browser flow. Account existence or a return URL alone does not prove readiness.
|
|
49
|
+
Currency comes from Stripe and is read-only.
|
|
50
|
+
|
|
51
|
+
Payments off first blocks new charges, then stops recurring billing and voids
|
|
52
|
+
unpaid issued invoices. It preserves paid history and the Express account. Review
|
|
53
|
+
the counts with `availability preview`. `off` reads current counts before its
|
|
54
|
+
confirmed write; a changed set returns 409. A bounded request may return
|
|
55
|
+
`pause.complete:false`, remaining counts and failed record IDs. New charging stays
|
|
56
|
+
blocked. Resolve errors and repeat `off`; do not turn Payments on while a pause is
|
|
57
|
+
incomplete. A payment already processing may settle and keeps its real result.
|
|
58
|
+
|
|
59
|
+
Turning Payments on rechecks Stripe readiness. It does not enable Store, restore
|
|
60
|
+
void invoices, resume arrangements or collect missed periods. Store off affects
|
|
61
|
+
only Store; it leaves standalone payments and billing running.
|
|
62
|
+
|
|
63
|
+
Activity combines the latest 200 Store orders and 200 Pay now payments with up to
|
|
64
|
+
100 invoices and 100 recurring arrangements each. `mayHaveMore` states when older
|
|
65
|
+
records may exist. It preserves captured currencies, amounts and payment states.
|
|
66
|
+
Recurring amounts are per-period amounts before tax. Use invoice/recurring list
|
|
67
|
+
commands for their paginated history. Get an order/payment with its explicit
|
|
68
|
+
source; equal IDs in different tables do not identify the same record.
|
|
69
|
+
|
|
70
|
+
## Tax
|
|
71
|
+
|
|
72
|
+
```sh
|
|
73
|
+
frontpage payments tax get --json
|
|
74
|
+
frontpage payments tax settings --file tax-settings.json --yes
|
|
75
|
+
frontpage payments tax registrations list
|
|
76
|
+
frontpage payments tax registrations add --country US --state CA --yes
|
|
77
|
+
frontpage payments tax registrations end <tax-registration-id> --yes
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Tax settings JSON contains `country`, `line1`, `city`, optional `state`, `postal`
|
|
81
|
+
and an existing supported `taxCode`. GET returns current choices and registrations.
|
|
82
|
+
Use the business's actual address and registrations. Frontpage does not choose
|
|
83
|
+
jurisdictions or provide tax advice. End uses the exact registration ID returned
|
|
84
|
+
by Stripe. These operations reuse current connected-account tax helpers. They do
|
|
85
|
+
not expose Account Session secrets or a second tax calculator. An invoice preview
|
|
86
|
+
blocks if tax settings cannot be confirmed; it does not silently drop tax.
|
|
87
|
+
|
|
88
|
+
## Invoice input and review
|
|
89
|
+
|
|
90
|
+
For an existing CRM person:
|
|
91
|
+
|
|
92
|
+
```json
|
|
93
|
+
{
|
|
94
|
+
"recipient": { "personId": "<crm-person-uuid>" },
|
|
95
|
+
"description": "Website maintenance",
|
|
96
|
+
"amountCents": 12500,
|
|
97
|
+
"kind": "once",
|
|
98
|
+
"collection": "manual",
|
|
99
|
+
"dueDays": 14
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
To add or match a CRM customer when sending, replace `recipient` with:
|
|
104
|
+
|
|
105
|
+
```json
|
|
106
|
+
{
|
|
107
|
+
"name": "Customer name",
|
|
108
|
+
"email": "customer@example.com",
|
|
109
|
+
"address": {
|
|
110
|
+
"line1": "Customer billing street",
|
|
111
|
+
"city": "City",
|
|
112
|
+
"region": "CA",
|
|
113
|
+
"postal": "94080",
|
|
114
|
+
"country": "US"
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
`address` also accepts `line2`. Supply a real billing address when automatic tax
|
|
120
|
+
needs it. A CRM person must be visible and have a valid billing email. Inline
|
|
121
|
+
matching stays within the site and does not grant marketing permission. Preview
|
|
122
|
+
creates no CRM person, Stripe Customer, invoice, invitation or charge.
|
|
123
|
+
|
|
124
|
+
Money fields use integer minor units in the account currency despite the existing
|
|
125
|
+
`Cents` field names. USD 12500 means $125.00; JPY 12500 means ¥12500. The current
|
|
126
|
+
amount range is 50 through 10,000,000 minor units. Description contains 1–500
|
|
127
|
+
characters. `dueDays` is 7, 14 or 30; omitted means 7. A one-time invoice uses
|
|
128
|
+
manual collection and cannot carry recurring date/cadence fields.
|
|
129
|
+
|
|
130
|
+
```sh
|
|
131
|
+
frontpage payments invoices preview --file invoice.json --json
|
|
132
|
+
frontpage payments invoices send --file invoice.json \
|
|
133
|
+
--preview-hash <hash-from-preview> --operation-key <stable-uuid> --yes --json
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Preview returns the normalized recipient/terms, currency, subtotal, tax, total,
|
|
137
|
+
tax status and `previewHash`. When `billingContactChanged` is true, review the CRM email, name and address and pass `--confirm-billing-contact` to update the saved Stripe contact for future billing. This does not rewrite issued invoices or prior consent. Send repeats those exact terms and hash. It rechecks
|
|
138
|
+
readiness and totals before finalization/delivery. Changed terms or totals return
|
|
139
|
+
409. Common flags can replace simple JSON fields: `--person` or `--email` with
|
|
140
|
+
`--name`, `--description`, `--amount-cents`, `--kind`, `--collection`, `--due-days`,
|
|
141
|
+
`--cadence`, `--first-date`, `--time-zone`. Nested addresses use `--file`.
|
|
142
|
+
|
|
143
|
+
The operation key contains 16–120 letters, digits, dots, colons, underscores or
|
|
144
|
+
hyphens and starts with a letter/digit. A UUID is suitable. Preserve the same key
|
|
145
|
+
and input after a timeout or uncertain result. Do not use a new key to force a
|
|
146
|
+
send. Repeated requests return the same local/Stripe invoice rather than charging
|
|
147
|
+
again. If Stripe's safe retry window has passed, reconcile the saved object first.
|
|
148
|
+
|
|
149
|
+
## Invoice management
|
|
150
|
+
|
|
151
|
+
```sh
|
|
152
|
+
frontpage payments invoices list --limit 50 --offset 0 --json
|
|
153
|
+
frontpage payments invoices list --arrangement <arrangement-uuid> --json
|
|
154
|
+
frontpage payments invoices get <invoice-uuid>
|
|
155
|
+
frontpage payments invoices refresh <invoice-uuid>
|
|
156
|
+
frontpage payments invoices resend <invoice-uuid> --operation-key <stable-uuid> --yes
|
|
157
|
+
frontpage payments invoices void <invoice-uuid> --yes
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
List accepts limit 1–100 and offset 0–100000; it returns `nextOffset` or null.
|
|
161
|
+
Records include immutable recipient/terms, actual currency/subtotal/tax/total,
|
|
162
|
+
paid/remaining amounts, due/issued/paid dates, Hosted Invoice Page/PDF, delivery
|
|
163
|
+
and any last error. Expected platform fee and actual collected fee are separate.
|
|
164
|
+
An unpaid invoice does not claim a collected fee. Source account/setup secrets
|
|
165
|
+
and customer-access nonces are not returned.
|
|
166
|
+
|
|
167
|
+
Resend only accepts an open invoice and uses its existing saved billing customer.
|
|
168
|
+
It never creates a replacement invoice. Void requires confirmation and cannot
|
|
169
|
+
restore an invoice after Stripe confirms it is void. A payment race preserves an
|
|
170
|
+
actual paid result. An unsent draft's cancellation is recorded separately from
|
|
171
|
+
Stripe's real draft state. There is no manual mark-paid, refund or raw charge API.
|
|
172
|
+
|
|
173
|
+
Stripe sends invoice emails and hosts payment/recovery. `delivery:accepted` means
|
|
174
|
+
the send API accepted the request, not that the email arrived or was opened.
|
|
175
|
+
Stripe test mode may suppress email delivery; provider acceptance is the most
|
|
176
|
+
that a test-mode report may claim.
|
|
177
|
+
|
|
178
|
+
## Recurring manual invoices and autopay
|
|
179
|
+
|
|
180
|
+
Use the same recipient, description, amount and due window. Set `kind:recurring`,
|
|
181
|
+
`cadence`, `firstDate` and `timeZone`. Collection is `manual` or `autopay`.
|
|
182
|
+
|
|
183
|
+
```json
|
|
184
|
+
{
|
|
185
|
+
"recipient": { "personId": "<crm-person-uuid>" },
|
|
186
|
+
"description": "Monthly maintenance",
|
|
187
|
+
"amountCents": 12500,
|
|
188
|
+
"kind": "recurring",
|
|
189
|
+
"collection": "manual",
|
|
190
|
+
"cadence": "monthly",
|
|
191
|
+
"firstDate": "2026-12-01",
|
|
192
|
+
"timeZone": "America/Chicago",
|
|
193
|
+
"dueDays": 14
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Supported cadences are `weekly`, `fortnightly`, `monthly`, `quarterly`, `yearly`.
|
|
198
|
+
The first date is YYYY-MM-DD in an explicit IANA zone. Billing begins at 09:00 in
|
|
199
|
+
that zone. Choose a future date. Stripe owns later native calendar periods,
|
|
200
|
+
including short months/leap years. No Frontpage recurring scheduler, backfill or
|
|
201
|
+
proration is added.
|
|
202
|
+
|
|
203
|
+
New recurring arrangements use Stripe's native platform fee: 2% of the invoice
|
|
204
|
+
total, including tax, unless the existing server fee setting is zero. The saved
|
|
205
|
+
arrangement freezes that server-controlled rate before billing starts. For
|
|
206
|
+
example, a $100 invoice plus $9.88 tax has a $2.20 platform fee. The fee is
|
|
207
|
+
deducted from the business's proceeds, not added as a customer surcharge.
|
|
208
|
+
Stripe's own processing and Billing/Invoicing charges are separate. Store,
|
|
209
|
+
Pay now and one-time invoice fee calculations keep their existing basis.
|
|
210
|
+
Reconciliation records expected and actual fees; it does not set the fee or
|
|
211
|
+
collect recurring payments. Stripe handles collection even if a webhook is late.
|
|
212
|
+
|
|
213
|
+
```sh
|
|
214
|
+
frontpage payments recurring preview --file recurring.json --json
|
|
215
|
+
frontpage payments recurring create --file recurring.json \
|
|
216
|
+
--preview-hash <hash> --operation-key <stable-uuid> --yes
|
|
217
|
+
frontpage payments recurring list --limit 50 --offset 0 --json
|
|
218
|
+
frontpage payments recurring get <arrangement-uuid>
|
|
219
|
+
frontpage payments recurring refresh <arrangement-uuid>
|
|
220
|
+
frontpage payments recurring cancel <arrangement-uuid> --yes
|
|
221
|
+
frontpage payments recurring resend-invitation <arrangement-uuid> \
|
|
222
|
+
--operation-key <stable-uuid> --yes
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Manual collection creates a native future Stripe schedule. It does not issue an
|
|
226
|
+
immediate first invoice. Stripe creates one invoice per period and emails the
|
|
227
|
+
hosted payment link. Autopay create saves a pending authorization and sends an
|
|
228
|
+
invitation. The customer reviews the amount, tax, cadence and first date, agrees,
|
|
229
|
+
and finishes Stripe-hosted setup on the same connected account/customer. Only
|
|
230
|
+
verified setup can start the schedule. A saved method, setup return query or owner
|
|
231
|
+
flag alone never supplies consent. Setup itself is not a payment.
|
|
232
|
+
|
|
233
|
+
Arrangement cancellation stops future billing without changing issued invoices
|
|
234
|
+
or adding a final prorated charge. Payments off pauses arrangements by stopping
|
|
235
|
+
their native future schedule. Only paused arrangements may resume. Preview the
|
|
236
|
+
same recipient/amount/cadence/collection with a new future date, then:
|
|
237
|
+
|
|
238
|
+
```sh
|
|
239
|
+
frontpage payments recurring resume <paused-arrangement-uuid> \
|
|
240
|
+
--first-date 2026-12-01 --preview-hash <hash-from-preview> \
|
|
241
|
+
--operation-key <stable-uuid> --yes
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
Resume creates a linked future arrangement with no missed-period invoices. A
|
|
245
|
+
second different resume request is refused. Autopay seeks fresh customer consent.
|
|
246
|
+
Changed terms require cancellation and a new reviewed request; there is no hidden
|
|
247
|
+
edit/proration action. Invitation resend applies only while awaiting authorization.
|
|
248
|
+
It expires/replaces an unfinished old setup and keeps its own retry key.
|
|
249
|
+
|
|
250
|
+
## Customer billing access
|
|
251
|
+
|
|
252
|
+
```sh
|
|
253
|
+
frontpage payments customers send-billing-link <customerMapId> \
|
|
254
|
+
--operation-key <stable-uuid> --yes
|
|
255
|
+
frontpage payments customers billing-link <customerMapId> \
|
|
256
|
+
--operation-key <stable-uuid> --json
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
Use `customerMapId` from the site's invoice/arrangement. It is not a raw Stripe
|
|
260
|
+
customer ID. Send uses the mapped customer's current saved Stripe billing email;
|
|
261
|
+
the caller cannot choose another recipient. Links expire after 30 minutes. A raw
|
|
262
|
+
returned link is sensitive: do not log/share it. The website agent only sends
|
|
263
|
+
links; it cannot request raw customer access.
|
|
264
|
+
|
|
265
|
+
Customer access needs no owner login. It stays scoped to site/account/customer
|
|
266
|
+
and uses a small customer page plus the connected-account Stripe portal. The
|
|
267
|
+
customer can pay an invoice, change the saved method, cancel future billing or
|
|
268
|
+
choose manual payment for future invoices. These actions do not pay an existing
|
|
269
|
+
balance, authorize another arrangement or expose Frontpage subscription billing.
|
|
270
|
+
Authorization invitations expire after 24 hours; an expired link requires a new
|
|
271
|
+
invitation. A completed authorization exposes Manage billing.
|
|
272
|
+
|
|
273
|
+
## Standalone Pay now
|
|
274
|
+
|
|
275
|
+
```sh
|
|
276
|
+
frontpage payments buttons list --limit 50 --offset 0 --json
|
|
277
|
+
frontpage payments buttons get consultation
|
|
278
|
+
frontpage payments buttons create --id consultation --title Consultation --price-cents 5000
|
|
279
|
+
frontpage payments buttons update consultation --price-cents 7500
|
|
280
|
+
frontpage payments buttons update consultation --file button-details.json
|
|
281
|
+
frontpage payments buttons archive consultation --yes
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
These reuse current item/variant pricing and visitor `/__pay`. Creation registers
|
|
285
|
+
the exact ID atomically with the item in existing Store settings; it returns
|
|
286
|
+
markup for an explicit `data-fp-pay` button. Only saved, explicitly registered
|
|
287
|
+
Offerings authorize standalone payments; page markup never establishes ownership. A Store card/CTA, no-shipping flag or old
|
|
288
|
+
instant setting is not proof of Pay now ownership. No new button table or fleet
|
|
289
|
+
conversion exists. Price, details, questions and receipt selection save together. Open amount
|
|
290
|
+
creation uses `--amount open --min-cents N` and a minimum variant price. Item IDs
|
|
291
|
+
remain existing 2–40-character kebab IDs. Lists are bounded with `nextOffset`.
|
|
292
|
+
|
|
293
|
+
## REST paths
|
|
294
|
+
|
|
295
|
+
All paths below use `/api/v1/sites/{slug}/payments`. GET query fields match the
|
|
296
|
+
documented filters. POST/PATCH fields match the reviewed domain inputs above.
|
|
297
|
+
Financial consequences need `confirm:true`; stable retryable sends additionally
|
|
298
|
+
need `operationKey`. This is a resource API, not arbitrary action dispatch.
|
|
299
|
+
|
|
300
|
+
| Method | Resource | Result |
|
|
301
|
+
| --- | --- | --- |
|
|
302
|
+
| GET | `/status`, `/settings` | Safe current connection/readiness and read-only currency |
|
|
303
|
+
| POST | `/connect` | Signed-in admin browser handoff |
|
|
304
|
+
| GET / POST | `/availability` | Pause counts/hash or confirmed availability outcome |
|
|
305
|
+
| GET | `/activity`, `/activity/{order\|payment}/{id}` | Current source-aware activity/detail |
|
|
306
|
+
| GET | `/tax`, `/tax/registrations` | Existing tax state/options/registrations |
|
|
307
|
+
| POST | `/tax/settings`, `/tax/registrations` | Existing tax settings/registration write |
|
|
308
|
+
| POST | `/tax/registrations/{id}/end` | End the specified registration |
|
|
309
|
+
| GET / POST | `/buttons` | List / create an explicit Pay now item |
|
|
310
|
+
| GET / PATCH | `/buttons/{id}` | Read / update that explicit Pay now item |
|
|
311
|
+
| POST | `/buttons/{id}/archive` | Confirmed archive |
|
|
312
|
+
| POST | `/invoices/preview`, `/invoices/send` | Read-only review / send |
|
|
313
|
+
| GET | `/invoices`, `/invoices/{id}` | Paginated invoices / detail |
|
|
314
|
+
| POST | `/invoices/{id}/{refresh\|resend\|void}` | Reconcile, resend or confirmed void |
|
|
315
|
+
| POST | `/recurring/preview`, `/recurring` | Read-only review / create request |
|
|
316
|
+
| GET | `/recurring`, `/recurring/{id}` | Paginated arrangements / detail |
|
|
317
|
+
| POST | `/recurring/{id}/{refresh\|cancel\|resume\|resend-invitation}` | Scoped lifecycle action |
|
|
318
|
+
| POST | `/customers/{customerMapId}/{billing-link\|send-billing-link}` | Private customer access |
|
|
319
|
+
|
|
320
|
+
Common failures: 400 invalid input/retired write; 401 no authentication; 403 role,
|
|
321
|
+
CLI tier or product entitlement; 404 wrong site/record; 409 stale review, conflict,
|
|
322
|
+
unfinished pause or unknown provider outcome; 429 existing rate limit; 503 missing
|
|
323
|
+
rate-limit service, tax-read failure or provider failure. Keep the request ID when
|
|
324
|
+
reporting a failure. Never retry a financial send with a new key just because an
|
|
325
|
+
HTTP response was lost.
|
|
326
|
+
|
|
327
|
+
## Breaking release
|
|
328
|
+
|
|
329
|
+
Version 0.2.0 removes Store `connect/status/disconnect/payments`, writable currency
|
|
330
|
+
and checkout mode from CLI/public API/agent contracts. Use `payments` for money
|
|
331
|
+
operations. Store remains cart-only and keeps existing resource paths under
|
|
332
|
+
`/shop`. Saved products/orders, Express accounts, current visitor hooks,
|
|
333
|
+
`/__pay`, Connect webhooks and old browser callbacks remain intact. Old binaries
|
|
334
|
+
may fail on retired endpoints; no compatibility alias or data conversion runs.
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
## Offerings: the required object behind Pay now
|
|
338
|
+
|
|
339
|
+
Every website Pay now payment must reference a registered Offering. Website markup, a price attribute, a Store item's instant flag, and direct checkout requests cannot create or authorize a payment. Store carts and saved invoices retain their own platform-owned flows. The existing `payments buttons` commands manage Offerings through the same service as the workspace and website agent.
|
|
340
|
+
|
|
341
|
+
```bash
|
|
342
|
+
frontpage payments buttons list
|
|
343
|
+
frontpage payments buttons create --id consultation --title "Initial consultation" --price-cents 10000
|
|
344
|
+
frontpage payments buttons get consultation
|
|
345
|
+
frontpage payments buttons update consultation --title "Consultation" --price-cents 12500 --active true
|
|
346
|
+
frontpage payments buttons update consultation --receipt-template-id TEMPLATE_UUID
|
|
347
|
+
frontpage payments buttons update consultation --default-receipt
|
|
348
|
+
frontpage payments buttons update consultation --active false
|
|
349
|
+
frontpage payments buttons archive consultation --yes
|
|
350
|
+
frontpage payments buttons list --archived true
|
|
351
|
+
frontpage payments buttons restore consultation --yes
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
`--file payload.json` supports the same fields. `--receipt-template-id` and `--default-receipt` are mutually exclusive. A template must be a saved Emails template owned by the same site. Price, details and template choice save together. Archive is deletion from new checkout: buttons stop taking payments, history remains, and restore can bring the offering back. Do not delete financial history. For a customer-chosen amount, create with `--amount open --min-cents 100 --price-cents 100` (integer minor units in the account currency).
|
|
355
|
+
|
|
356
|
+
Create/get/update return the saved object; create/update also return bound markup:
|
|
357
|
+
|
|
358
|
+
```html
|
|
359
|
+
<button data-fp-pay="consultation" data-fp-requires="pay">Pay now <span data-fp-pay-bind="price"></span></button>
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
The platform loads the saved price, minimum and availability. Do not put a fixed charge in `data-amount`, build a card form, call Stripe directly or substitute a Store item ID. A deleted, paused, unregistered or wrong-site offering cannot charge. Existing connected Stripe onboarding, payment readiness, tax, fees and currency rules still apply. Saved templates send confirmations only after verified payment, subject to current email limits; they do not subscribe a payer to marketing.
|
|
363
|
+
|
|
364
|
+
The website agent can do this automatically from a normal request such as “add a $100 consultation button”: it finds/reuses or creates the offering and then writes its bound markup. The owner does not have to visit Payments or know any object IDs. Ask for a missing essential business fact, such as an unknown price, rather than invent a fixed charge.
|
|
365
|
+
|
|
366
|
+
Payments Activity uses Customer, Type, Status, Amount and Date. Date is a verified payment timestamp; unpaid invoices and recurring schedules have no payment date. Historic records without a verified timestamp remain unknown. Summary counts cover the full scoped records even when the recent activity view is capped.
|
|
367
|
+
|
|
368
|
+
## Customer details on Offerings
|
|
369
|
+
|
|
370
|
+
Use the existing buttons create/update commands with `--file offering.json`.
|
|
371
|
+
The same service powers the workspace and agent. For example:
|
|
372
|
+
|
|
373
|
+
```json
|
|
374
|
+
{
|
|
375
|
+
"title": "Home consultation",
|
|
376
|
+
"priceCents": 10000,
|
|
377
|
+
"customizations": [
|
|
378
|
+
{ "customizationId": "job-address", "label": "Property address", "kind": "address", "required": true },
|
|
379
|
+
{ "customizationId": "contact", "label": "Preferred contact", "kind": "choice", "values": ["Phone", "Email"] },
|
|
380
|
+
{ "customizationId": "instructions", "label": "Access instructions", "kind": "textarea", "maxLength": 1000, "includeInReceipt": false }
|
|
381
|
+
]
|
|
382
|
+
}
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
```sh
|
|
386
|
+
frontpage payments buttons update consultation --file offering.json --json
|
|
387
|
+
frontpage payments buttons get consultation --json
|
|
388
|
+
frontpage payments activity get ORDER_UUID --source order --json
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
At most eight questions. Supported kinds: text (max 200 characters), textarea
|
|
392
|
+
(max 2000), choice (max 20 values), checkbox, email, phone, number, date and
|
|
393
|
+
address. Text supports maxLength; number supports min/max. Required checkboxes
|
|
394
|
+
need an affirmative check. Offering choices require explicit selection. Dates
|
|
395
|
+
use YYYY-MM-DD and express a preference, not a confirmed booking. An address
|
|
396
|
+
question collects a service address; Store owns shipping and Stripe owns billing
|
|
397
|
+
addresses. Fields cannot change the saved price, fees or currency.
|
|
398
|
+
|
|
399
|
+
Stable customizationId values survive renames and reordering. Replacing the
|
|
400
|
+
customizations array edits future checkouts; completed payments retain captured
|
|
401
|
+
labels, types and answers. Offering answers default out of confirmations; opt in
|
|
402
|
+
per field with includeInReceipt:true. Read captured answers through activity get.
|
|
403
|
+
Do not put intake answers in page markup, URL parameters or Stripe product names.
|
|
404
|
+
The standard payment drawer renders the saved questions; an unrelated form does
|
|
405
|
+
not automatically join its submission to a payment.
|
|
406
|
+
|
|
407
|
+
## Payments drawer design
|
|
408
|
+
|
|
409
|
+
Offerings work without Store markup. The platform supplies a Payments drawer for buyer-chosen amounts and saved questions; fixed payments without questions proceed to Stripe Checkout. Never add a Cart button or Store drawer for an Offering.
|
|
410
|
+
|
|
411
|
+
For custom appearance, include one shared `<template data-fp-payment-drawer>` using the required panel, title, close, amount, fields, error and confirm hooks documented by the Payments agent module. Style it with normal site CSS and payment-specific variables. Keep dynamic questions in the saved Offering, not in page HTML. UI, CLI and agent question edits appear on the next opening without republishing. Template/style edits use normal website publishing. Payments never changes the Store cart or its saved delivery choices.
|
package/README.md
CHANGED
|
@@ -60,3 +60,9 @@ See [AGENTS.md](./AGENTS.md) and [llms.txt](./llms.txt) in this package.
|
|
|
60
60
|
## People groups, stages, rules, and imports
|
|
61
61
|
|
|
62
62
|
Use `frontpage people overview`, `groups`, `stages`, `membership`, `rules`, `attachments`, `import`, and `company`. Use `frontpage mail campaign` for one-off group/stage/list audiences in Emails. Every editor action is available through these commands or `frontpage people workspace OPERATION --file payload.json`. Full operations and examples: [PEOPLE.md](./PEOPLE.md); public guide: https://frontpage.host/developers/people. Automated emails select a saved template or series. Campaigns use their own drafts.
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
Payments, invoices and recurring billing: see packaged [PAYMENTS.md](./PAYMENTS.md), `frontpage help payments`, and https://frontpage.host/developers/payments. Version 0.2.0 removes writable currency, Store checkout mode and Store-owned money commands; Store stays cart-only. Preview/review before sends; keep stable operation keys on retries. Autopay requires the customer’s own verified authorization.
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
Offerings own every standalone Pay now payment. Use `frontpage payments buttons list|get|create|update|archive|restore`; create the saved offering before adding its returned `data-fp-pay` markup. Supports `--receipt-template-id UUID`, `--default-receipt`, `--active true|false`, combined price/details updates and JSON payloads. Archive deletes from active checkout but preserves history. The website agent uses the same service automatically for ordinary payment-button requests. Store stays cart-only; invoices stay saved customer-addressed records. Full instructions: PAYMENTS.md and https://frontpage.host/developers/payments.
|
package/dist/argv.d.ts
CHANGED
|
@@ -10,3 +10,5 @@ export declare function looksLikeFlag(token: string): boolean;
|
|
|
10
10
|
* caller also checks them.
|
|
11
11
|
*/
|
|
12
12
|
export declare function assertNoUnknownFlags(rest: string[], command: string): void;
|
|
13
|
+
/** Required value for new command parsers; keep existing parsers unchanged. */
|
|
14
|
+
export declare function takeFlagValue(rest: string[], name: string): string | undefined;
|
package/dist/argv.js
CHANGED
|
@@ -46,3 +46,11 @@ export function assertNoUnknownFlags(rest, command) {
|
|
|
46
46
|
return;
|
|
47
47
|
throw new CliHttpError(`Unknown flag: ${unknown}. Run: frontpage help ${command}`, EXIT_USAGE, 0, "bad_request");
|
|
48
48
|
}
|
|
49
|
+
/** Required value for new command parsers; keep existing parsers unchanged. */
|
|
50
|
+
export function takeFlagValue(rest, name) {
|
|
51
|
+
const present = rest.some(token => token === name || token.startsWith(`${name}=`));
|
|
52
|
+
const value = takeFlag(rest, name);
|
|
53
|
+
if (present && (!value || looksLikeFlag(value)))
|
|
54
|
+
throw new CliHttpError(`${name} requires a value.`, EXIT_USAGE, 0, "bad_request");
|
|
55
|
+
return value;
|
|
56
|
+
}
|
package/dist/bin.js
CHANGED
|
@@ -32,6 +32,7 @@ import { runRedirects } from "./commands/redirects.js";
|
|
|
32
32
|
import { runPeople } from "./commands/people.js";
|
|
33
33
|
import { runRoutines } from "./commands/routines.js";
|
|
34
34
|
import { runShop } from "./commands/shop.js";
|
|
35
|
+
import { runPayments } from "./commands/payments.js";
|
|
35
36
|
import { runMail } from "./commands/mail.js";
|
|
36
37
|
import { runArticles } from "./commands/articles.js";
|
|
37
38
|
import { runSettings } from "./commands/settings.js";
|
|
@@ -63,6 +64,8 @@ async function main() {
|
|
|
63
64
|
return runHelp([cmd, ...args]);
|
|
64
65
|
}
|
|
65
66
|
switch (cmd) {
|
|
67
|
+
case "payments":
|
|
68
|
+
return runPayments(args);
|
|
66
69
|
case "login":
|
|
67
70
|
return runLogin(args);
|
|
68
71
|
case "logout":
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runPayments(args: string[]): Promise<number>;
|