@tuppence/node 0.0.0-stage → 0.1.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.
@@ -0,0 +1,1816 @@
1
+ import { EncodedBody } from "./http.js";
2
+ const id = (value) => encodeURIComponent(value);
3
+ /** Every list, as an async iterator that fetches the next page only when it is needed. */
4
+ async function* paginate(fetchPage, params = {}) {
5
+ let cursor = params.starting_after;
6
+ for (;;) {
7
+ const page = await fetchPage({ ...params, ...(cursor ? { starting_after: cursor } : {}) });
8
+ for (const item of page.data)
9
+ yield item;
10
+ const last = page.data[page.data.length - 1];
11
+ if (!page.has_more || !last)
12
+ return;
13
+ cursor = last.id;
14
+ }
15
+ }
16
+ function lister(http, path) {
17
+ const list = (params = {}, options) => http.request("GET", path, { query: params, ...options });
18
+ return {
19
+ list,
20
+ /** `for await (const item of listAll())` — every item, page by page. */
21
+ listAll: (params = {}, options) => paginate((p) => list({ ...params, ...p }, options)),
22
+ };
23
+ }
24
+ /** A list under one parent — `accounts.persons.list("acct_…")` — and its `listAll`. */
25
+ function childLister(http, path) {
26
+ return {
27
+ list: (parentId, params = {}, options) => lister(http, path(parentId)).list(params, options),
28
+ listAll: (parentId, params = {}, options) => lister(http, path(parentId)).listAll(params, options),
29
+ };
30
+ }
31
+ /**
32
+ * The upload, as multipart — encoded ONCE, so every retry sends the same bytes under the same
33
+ * idempotency key. A stream is read whole first (the API takes up to 10 MB).
34
+ */
35
+ async function multipart(fields, { file, filename }) {
36
+ // A copy the Blob can own: a view may sit on a SharedArrayBuffer.
37
+ const own = (view) => new Uint8Array(new Uint8Array(view.buffer, view.byteOffset, view.byteLength));
38
+ let blob;
39
+ if (file instanceof Blob)
40
+ blob = file;
41
+ else if (file instanceof ArrayBuffer)
42
+ blob = new Blob([file]);
43
+ else if (ArrayBuffer.isView(file))
44
+ blob = new Blob([own(file)]);
45
+ else {
46
+ const chunks = [];
47
+ for await (const chunk of file)
48
+ chunks.push(typeof chunk === "string" ? chunk : own(chunk));
49
+ blob = new Blob(chunks);
50
+ }
51
+ const form = new FormData();
52
+ for (const [name, value] of Object.entries(fields))
53
+ form.append(name, value);
54
+ form.append("file", blob, filename ?? (typeof File !== "undefined" && file instanceof File ? file.name : "upload"));
55
+ const encoded = new Response(form);
56
+ return new EncodedBody(new Uint8Array(await encoded.arrayBuffer()), encoded.headers.get("content-type") ?? "multipart/form-data");
57
+ }
58
+ export function resources(http) {
59
+ /** create / retrieve / update / list, the shape most resources share. */
60
+ const crud = (path) => ({
61
+ create: (body, options) => http.request("POST", path, { body, ...options }),
62
+ retrieve: (objectId, options) => http.request("GET", `${path}/${id(objectId)}`, options),
63
+ update: (objectId, body, options) => http.request("POST", `${path}/${id(objectId)}`, { body, ...options }),
64
+ ...lister(http, path),
65
+ });
66
+ return {
67
+ /** The AI agents a business runs — what its cards belong to (14-03). */
68
+ agents: {
69
+ ...crud("/v1/agents"),
70
+ /** What's normal for this agent's spending, and its latest unusual purchases (19-07). */
71
+ profile: (agentId, options) => http.request("GET", `/v1/agents/${id(agentId)}/profile`, options),
72
+ /**
73
+ * Funding mandates (54-15, E13): what a person lets an agent top the cards up with. Only a
74
+ * person signed in to the dashboard gives one (fresh second factor); a key lists and revokes.
75
+ */
76
+ fundingMandates: {
77
+ list: (agentId, params = {}, options) => http.request("GET", `/v1/agents/${id(agentId)}/funding_mandates`, { query: params, ...options }),
78
+ retrieve: (agentId, mandateId, options) => http.request("GET", `/v1/agents/${id(agentId)}/funding_mandates/${id(mandateId)}`, options),
79
+ /** Revoked at once: the agent's next top-up asks a person. */
80
+ revoke: (agentId, mandateId, options) => http.request("DELETE", `/v1/agents/${id(agentId)}/funding_mandates/${id(mandateId)}`, options),
81
+ },
82
+ },
83
+ /** Who cards are issued to. Secret keys only (14-03). */
84
+ cardholders: crud("/v1/cardholders"),
85
+ /** The rules cards spend under: on a card, or an agent's default. Secret keys only (14-04). */
86
+ spendPolicies: crud("/v1/spend_policies"),
87
+ /**
88
+ * Cards (14-05): virtual — the business's own, or an agent's (`agent`) — or physical, a
89
+ * person's. A person sees a card's number in Stripe's own fields, in the dashboard or the app
90
+ * (14-12, 16-07); the SDK never has a method for that.
91
+ */
92
+ cards: {
93
+ create: (body, options) => http.request("POST", "/v1/cards", { body, ...options }),
94
+ retrieve: (cardId, options) => http.request("GET", `/v1/cards/${id(cardId)}`, options),
95
+ update: (cardId, body, options) => http.request("POST", `/v1/cards/${id(cardId)}`, { body, ...options }),
96
+ /** `null` removes a limit; a card always keeps at least one. */
97
+ setLimits: (cardId, body, options) => http.request("POST", `/v1/cards/${id(cardId)}/limits`, { body, ...options }),
98
+ activate: (cardId, options) => http.request("POST", `/v1/cards/${id(cardId)}/activate`, options),
99
+ freeze: (cardId, options) => http.request("POST", `/v1/cards/${id(cardId)}/freeze`, options),
100
+ unfreeze: (cardId, options) => http.request("POST", `/v1/cards/${id(cardId)}/unfreeze`, options),
101
+ cancel: (cardId, options) => http.request("POST", `/v1/cards/${id(cardId)}/cancel`, options),
102
+ /**
103
+ * An active virtual card's number, CVC and expiry — the business's own or an agent's — to
104
+ * fill in a merchant's checkout (14-22). Only a restricted key made with `card_details:read`, on an account whose
105
+ * owner has allowed it; ten a minute per key; every read is audited and sent as
106
+ * `card.details_retrieved`. The SDK keeps nothing: never store, print or log the answer.
107
+ */
108
+ retrieveDetails: (cardId, options) => http.request("GET", `/v1/cards/${id(cardId)}/details`, options),
109
+ ...lister(http, "/v1/cards"),
110
+ },
111
+ /** Every purchase a card attempted, and what was decided (14-07). */
112
+ cardAuthorizations: {
113
+ retrieve: (authorizationId, options) => http.request("GET", `/v1/card_authorizations/${id(authorizationId)}`, options),
114
+ ...lister(http, "/v1/card_authorizations"),
115
+ },
116
+ /** What settled on the cards — captures and refunds (14-08) — and each purchase's story (14-10). */
117
+ cardTransactions: {
118
+ /** With `timeline`: asked, approved, authorised, captured, refunded — oldest first. */
119
+ retrieve: (transactionId, options) => http.request("GET", `/v1/card_transactions/${id(transactionId)}`, options),
120
+ ...lister(http, "/v1/card_transactions"),
121
+ },
122
+ /**
123
+ * Disputing a card purchase (53-05): a draft until submitted. Fill in the evidence, attach
124
+ * files, then submit — once; a person's act (an agent's key gets
125
+ * `dispute_submission_needs_person`, or an approval of `kind: "card_dispute_submission"`).
126
+ * Refusals: `dispute_evidence_incomplete` (`missing_evidence` in the error's `raw`),
127
+ * `dispute_window_closed` (`dispute_by`), `dispute_not_allowed` (`available_at`).
128
+ */
129
+ cardDisputes: {
130
+ /** `submit: true` sends it at once; `prefill: true` fills the evidence from what we know. */
131
+ create: (cardTransactionId, body = {}, options) => http.request("POST", `/v1/card_transactions/${id(cardTransactionId)}/disputes`, { body, ...options }),
132
+ retrieve: (disputeId, options) => http.request("GET", `/v1/card_disputes/${id(disputeId)}`, options),
133
+ /** A draft's evidence: fields you send replace what is saved; `null` clears one. */
134
+ update: (disputeId, body, options) => http.request("POST", `/v1/card_disputes/${id(disputeId)}`, {
135
+ body,
136
+ ...options,
137
+ }),
138
+ /** Attaches a PDF or JPEG (up to 5 MB) to a draft's evidence, as multipart. */
139
+ uploadFile: async (disputeId, params, options) => http.request("POST", `/v1/card_disputes/${id(disputeId)}/files`, {
140
+ body: await multipart(params.field ? { field: params.field } : {}, params),
141
+ ...options,
142
+ }),
143
+ /** Sends it to the card network. Nothing can be added after. */
144
+ submit: (disputeId, options) => http.request("POST", `/v1/card_disputes/${id(disputeId)}/submit`, options),
145
+ ...lister(http, "/v1/card_disputes"),
146
+ },
147
+ /** The cards' own balance, its top-ups (M54) and Issuing's limits (53-03). */
148
+ issuing: {
149
+ /**
150
+ * Each card limit: its value, what is used, when it resets and where it comes from. Over
151
+ * one, a request fails with `issuing_card_limit` / `issuing_cardholder_limit` (`limit`,
152
+ * `used`, `max`, `resets_at`, `increase_url` in the error's `raw`).
153
+ */
154
+ limits: {
155
+ retrieve: (options) => http.request("GET", "/v1/issuing/limits", options),
156
+ },
157
+ /**
158
+ * What the cards can spend right now (`spendable`) — read it before buying. `spends_from`:
159
+ * `issuing_balance` (UK, topped up) or `payments_balance` (US, the earnings directly).
160
+ */
161
+ balance: {
162
+ retrieve: (options) => http.request("GET", "/v1/issuing/balance", options),
163
+ },
164
+ /** The card balance's own bank details (UK: sort code and account number). */
165
+ fundingInstructions: {
166
+ retrieve: (options) => http.request("GET", "/v1/issuing/funding_instructions", options),
167
+ },
168
+ /**
169
+ * Money on its way to the card balance, whatever the method. Until it is `available` a
170
+ * top-up says what it waits on (`delay`) and when it should be spendable
171
+ * (`expected_available_at`); `issuing_topup.*` webhooks carry every change.
172
+ */
173
+ topups: {
174
+ /**
175
+ * `{ method: "bank_transfer", amount }` (UK, free): `requires_action`, with your card
176
+ * balance's bank details and a reference in `next_action.bank_transfer`; nothing moves
177
+ * until you send it. `{ method: "balance", speed: "instant" }`: pending money onto the
178
+ * cards now, for 0.99%. Every call carries an `Idempotency-Key` (pass `idempotencyKey`
179
+ * to choose it), reused by its retries, so a retry never makes a second top-up.
180
+ */
181
+ /**
182
+ * Every way to top up that can be made now (54-07): for each `method` and `speed`,
183
+ * `available` — or `reason`, `message` and a `fix_url` — the `fee`, the `total` you pay for
184
+ * `amount` to arrive, `expected_available_at`, the `delay` it would wait on, and for
185
+ * `bank_transfer` the bank details. Leave `amount` out for rates and timings only.
186
+ */
187
+ options: (params = {}, options) => http.request("GET", "/v1/issuing/topups/options", {
188
+ query: Object.fromEntries(Object.entries(params)
189
+ .filter(([, v]) => v !== undefined)
190
+ .map(([k, v]) => [k, String(v)])),
191
+ ...options,
192
+ }),
193
+ create: (body, options) => http.request("POST", "/v1/issuing/topups", { body, ...options }),
194
+ retrieve: (topupId, options) => http.request("GET", `/v1/issuing/topups/${id(topupId)}`, options),
195
+ /** Calls off one still `requires_action` — before any money moves. */
196
+ cancel: (topupId, options) => http.request("POST", `/v1/issuing/topups/${id(topupId)}/cancel`, options),
197
+ /** Newest first; `status` and `method` filter. */
198
+ ...lister(http, "/v1/issuing/topups"),
199
+ },
200
+ /**
201
+ * Hosted top-up pages (54-18): a person tops up the card balance by card, or sees its bank
202
+ * details. Single use, good for 24 hours; a connected account's page wears its platform's
203
+ * branding. In a browser, `@tuppence/js`'s `tuppence.topups.redirect({ url })` sends them.
204
+ */
205
+ topupLinks: {
206
+ /** `{ return_url, amount? }`: the answer's `url` is shown only now — send it on. */
207
+ create: (body, options) => http.request("POST", "/v1/issuing/topup_links", { body, ...options }),
208
+ /** `open`, `used` (with the `topup` made on it) or `expired`. */
209
+ retrieve: (linkId, options) => http.request("GET", `/v1/issuing/topup_links/${id(linkId)}`, options),
210
+ },
211
+ /**
212
+ * The auto top-up rule (54-15): when Spendable, plus top-ups on their way, falls below
213
+ * `threshold`, top up by `amount` — `card` (a saved top-up card) or `balance` (UK). Paused
214
+ * after a failure (`status: paused`, `fix_url`). `update` changes only what it is sent.
215
+ */
216
+ autoTopup: {
217
+ retrieve: (options) => http.request("GET", "/v1/issuing/auto_topup", options),
218
+ update: (body, options) => http.request("POST", "/v1/issuing/auto_topup", { body, ...options }),
219
+ },
220
+ /**
221
+ * Your own cards saved for top-ups (54-15) — saved by a card top-up with
222
+ * `save_payment_method: true`, charged later with `{ method: "card", payment_method }`.
223
+ */
224
+ topupPaymentMethods: {
225
+ retrieve: (methodId, options) => http.request("GET", `/v1/issuing/topup_payment_methods/${id(methodId)}`, options),
226
+ /** Removed at Stripe too: it can't be charged again. */
227
+ remove: (methodId, options) => http.request("DELETE", `/v1/issuing/topup_payment_methods/${id(methodId)}`, options),
228
+ ...lister(http, "/v1/issuing/topup_payment_methods"),
229
+ },
230
+ },
231
+ /** TEST MODE: make things happen that a person, a bank or a card network would. */
232
+ testHelpers: {
233
+ issuing: {
234
+ topups: {
235
+ /**
236
+ * The bank transfer for a `requires_action` bank-transfer top-up arrives — Stripe's
237
+ * test transfer, through the real arrival path. It is usually `available` in the answer;
238
+ * on a slow sandbox, retrieve it again a few seconds later.
239
+ */
240
+ arrive: (topupId, options) => http.request("POST", `/v1/test_helpers/issuing/topups/${id(topupId)}/arrive`, options),
241
+ },
242
+ },
243
+ },
244
+ /** A person's say over a purchase at or over the threshold (14-09). Ask; poll; buy. */
245
+ approvals: {
246
+ /** Ask BEFORE buying — the merchant never sees a decline. */
247
+ create: (body, options) => http.request("POST", "/v1/approvals", { body, ...options }),
248
+ retrieve: (approvalId, options) => http.request("GET", `/v1/approvals/${id(approvalId)}`, options),
249
+ ...lister(http, "/v1/approvals"),
250
+ },
251
+ account: {
252
+ retrieve: (options) => http.request("GET", "/v1/account", options),
253
+ update: (body, options) => http.request("POST", "/v1/account", { body, ...options }),
254
+ /**
255
+ * Every price the account pays now (61-12): the card rate, surcharges, next-day and instant
256
+ * payouts, the dispute fee — each the list price or one agreed with Tuppence, with its dates.
257
+ */
258
+ retrievePricing: (params = {}, options) => http.request("GET", "/v1/account/pricing", {
259
+ query: params.currency ? { currency: params.currency } : {},
260
+ ...options,
261
+ }),
262
+ },
263
+ /**
264
+ * Bacs Direct Debit, by application (59-11): where the business is (`status`, its limits and
265
+ * usage, the price, and `fix_url` when something stops it), applying with a reason, answering
266
+ * what we asked, withdrawing, and asking for higher limits. Tuppence staff decide; a Connect
267
+ * platform may apply for one of its connected accounts with `{ tuppenceAccount }`.
268
+ */
269
+ directDebit: {
270
+ retrieve: (options) => http.request("GET", "/v1/direct_debit", options),
271
+ apply: (body, options) => http.request("POST", "/v1/direct_debit/application", {
272
+ body,
273
+ ...options,
274
+ }),
275
+ respond: (body, options) => http.request("POST", "/v1/direct_debit/application/respond", {
276
+ body,
277
+ ...options,
278
+ }),
279
+ withdraw: (options) => http.request("POST", "/v1/direct_debit/application/withdraw", options),
280
+ requestLimitIncrease: (body, options) => http.request("POST", "/v1/direct_debit/limit_increase", {
281
+ body,
282
+ ...options,
283
+ }),
284
+ },
285
+ /**
286
+ * Tuppence Connect: your connected accounts (M40) — each a full Tuppence account, which you
287
+ * act as with `{ tuppenceAccount }` on any request, or through `tuppence.as("acct_…")`.
288
+ */
289
+ accounts: {
290
+ /** Made in your key's mode, with Stripe's requirements for it in `requirements`. */
291
+ create: (body, options) => http.request("POST", "/v1/accounts", { body, ...options }),
292
+ retrieve: (accountId, options) => http.request("GET", `/v1/accounts/${id(accountId)}`, options),
293
+ update: (accountId, body, options) => http.request("POST", `/v1/accounts/${id(accountId)}`, {
294
+ body,
295
+ ...options,
296
+ }),
297
+ /** Closes it. In live mode, only once it holds no money. */
298
+ del: (accountId, options) => http.request("DELETE", `/v1/accounts/${id(accountId)}`, options),
299
+ /** Its store as you see it (94-09): address, status, and this month's orders, revenue and your fees. */
300
+ retrieveStore: (accountId, options) => http.request("GET", `/v1/accounts/${id(accountId)}/store`, options),
301
+ /** Stops it for good: `fraud`, `terms_of_service` or `other`. */
302
+ reject: (accountId, body, options) => http.request("POST", `/v1/accounts/${id(accountId)}/reject`, {
303
+ body,
304
+ ...options,
305
+ }),
306
+ ...lister(http, "/v1/accounts"),
307
+ /** The people behind a connected account (41-04): their names and roles come back, never the details. */
308
+ persons: {
309
+ create: (accountId, body, options) => http.request("POST", `/v1/accounts/${id(accountId)}/persons`, {
310
+ body,
311
+ ...options,
312
+ }),
313
+ retrieve: (accountId, personId, options) => http.request("GET", `/v1/accounts/${id(accountId)}/persons/${id(personId)}`, options),
314
+ update: (accountId, personId, body, options) => http.request("POST", `/v1/accounts/${id(accountId)}/persons/${id(personId)}`, {
315
+ body,
316
+ ...options,
317
+ }),
318
+ del: (accountId, personId, options) => http.request("DELETE", `/v1/accounts/${id(accountId)}/persons/${id(personId)}`, options),
319
+ /** Their identity check: a Stripe Identity session to send them to. */
320
+ createIdentitySession: (accountId, personId, options) => http.request("POST", `/v1/accounts/${id(accountId)}/persons/${id(personId)}/identity_sessions`, options),
321
+ /** Filter by role: `{ "relationship[owner]": true }`. */
322
+ ...childLister(http, (accountId) => `/v1/accounts/${id(accountId)}/persons`),
323
+ },
324
+ /**
325
+ * Where a connected account is paid out (41-05, 52-09, 52-17): the details, as
326
+ * `@tuppence/js` `bankAccountDetails` shapes them — kept encrypted by Tuppence, never
327
+ * returned or logged. A bank account token (`btok_…`) is refused.
328
+ */
329
+ externalAccounts: {
330
+ create: (accountId, body, options) => http.request("POST", `/v1/accounts/${id(accountId)}/external_accounts`, {
331
+ body,
332
+ ...options,
333
+ }),
334
+ retrieve: (accountId, bankId, options) => http.request("GET", `/v1/accounts/${id(accountId)}/external_accounts/${id(bankId)}`, options),
335
+ /** `default_for_currency: true` — another becomes the default by being chosen. */
336
+ update: (accountId, bankId, body, options) => http.request("POST", `/v1/accounts/${id(accountId)}/external_accounts/${id(bankId)}`, { body, ...options }),
337
+ /** Never the only default for its currency. */
338
+ del: (accountId, bankId, options) => http.request("DELETE", `/v1/accounts/${id(accountId)}/external_accounts/${id(bankId)}`, options),
339
+ ...childLister(http, (accountId) => `/v1/accounts/${id(accountId)}/external_accounts`),
340
+ },
341
+ /** What a connected account may do — `card_payments`, `transfers` — and what each needs. */
342
+ capabilities: {
343
+ list: (accountId, options) => http.request("GET", `/v1/accounts/${id(accountId)}/capabilities`, options),
344
+ retrieve: (accountId, capability, options) => http.request("GET", `/v1/accounts/${id(accountId)}/capabilities/${id(capability)}`, options),
345
+ update: (accountId, capability, body, options) => http.request("POST", `/v1/accounts/${id(accountId)}/capabilities/${id(capability)}`, { body, ...options }),
346
+ },
347
+ },
348
+ /** Onboarding a connected account (41-01): hand the link's `url` to the account's owner. */
349
+ accountLinks: {
350
+ /** Good once and for five minutes — make it when they click, not before. */
351
+ create: (body, options) => http.request("POST", "/v1/account_links", { body, ...options }),
352
+ },
353
+ /** Files for a connected account's verification (41-06), uploaded as that account. */
354
+ files: {
355
+ /** Send it as the account: `{ tuppenceAccount }`, or through `tuppence.as("acct_…")`. */
356
+ create: async (params, options) => http.request("POST", "/v1/files", {
357
+ body: await multipart({ purpose: params.purpose }, params),
358
+ ...options,
359
+ }),
360
+ retrieve: (fileId, options) => http.request("GET", `/v1/files/${id(fileId)}`, options),
361
+ },
362
+ /** Your fees on your connected accounts' payments (42-01), and any you gave back. */
363
+ applicationFees: {
364
+ retrieve: (feeId, options) => http.request("GET", `/v1/application_fees/${id(feeId)}`, options),
365
+ ...lister(http, "/v1/application_fees"),
366
+ refunds: {
367
+ /** All of what is left of the fee, or `amount` of it — from your Connect balance. */
368
+ create: (feeId, body = {}, options) => http.request("POST", `/v1/application_fees/${id(feeId)}/refunds`, {
369
+ body,
370
+ ...options,
371
+ }),
372
+ retrieve: (feeId, refundId, options) => http.request("GET", `/v1/application_fees/${id(feeId)}/refunds/${id(refundId)}`, options),
373
+ ...childLister(http, (feeId) => `/v1/application_fees/${id(feeId)}/refunds`),
374
+ },
375
+ },
376
+ /** Money from your Connect balance to a connected account (42-03), and back. */
377
+ transfers: {
378
+ create: (body, options) => http.request("POST", "/v1/transfers", { body, ...options }),
379
+ retrieve: (transferId, options) => http.request("GET", `/v1/transfers/${id(transferId)}`, options),
380
+ ...lister(http, "/v1/transfers"),
381
+ reversals: {
382
+ /** All of what is left of the transfer, or `amount` of it. */
383
+ create: (transferId, body = {}, options) => http.request("POST", `/v1/transfers/${id(transferId)}/reversals`, {
384
+ body,
385
+ ...options,
386
+ }),
387
+ retrieve: (transferId, reversalId, options) => http.request("GET", `/v1/transfers/${id(transferId)}/reversals/${id(reversalId)}`, options),
388
+ ...childLister(http, (transferId) => `/v1/transfers/${id(transferId)}/reversals`),
389
+ },
390
+ },
391
+ paymentLinks: {
392
+ create: (body, options) => http.request("POST", "/v1/payment_links", { body, ...options }),
393
+ retrieve: (linkId, options) => http.request("GET", `/v1/payment_links/${id(linkId)}`, options),
394
+ update: (linkId, body, options) => http.request("POST", `/v1/payment_links/${id(linkId)}`, { body, ...options }),
395
+ expire: (linkId, options) => http.request("POST", `/v1/payment_links/${id(linkId)}/expire`, options),
396
+ /** Takes payments again on a link the card-testing check paused (13-03), once you have looked. */
397
+ unpause: (linkId, options) => http.request("POST", `/v1/payment_links/${id(linkId)}/unpause`, options),
398
+ ...lister(http, "/v1/payment_links"),
399
+ },
400
+ /** What a business sells on repeat. A plan's price never changes: a new price is a new plan. */
401
+ plans: {
402
+ create: (body, options) => http.request("POST", "/v1/plans", { body, ...options }),
403
+ retrieve: (planId, options) => http.request("GET", `/v1/plans/${id(planId)}`, options),
404
+ /** Renaming and metadata only — the price, interval and trial cannot be changed. */
405
+ update: (planId, body, options) => http.request("POST", `/v1/plans/${id(planId)}`, { body, ...options }),
406
+ /** Stops new subscriptions; the ones already on it carry on. */
407
+ archive: (planId, options) => http.request("POST", `/v1/plans/${id(planId)}/archive`, options),
408
+ ...lister(http, "/v1/plans"),
409
+ },
410
+ /** Discounts on subscriptions: a percentage or an amount off, for some charges or for ever. */
411
+ coupons: {
412
+ create: (body, options) => http.request("POST", "/v1/coupons", { body, ...options }),
413
+ retrieve: (couponId, options) => http.request("GET", `/v1/coupons/${id(couponId)}`, options),
414
+ /** Stops new redemptions; subscriptions already carrying it keep it. */
415
+ archive: (couponId, options) => http.request("POST", `/v1/coupons/${id(couponId)}/archive`, options),
416
+ ...lister(http, "/v1/coupons"),
417
+ },
418
+ /** What each subscription charge was for, numbered without gaps. No tax is calculated. */
419
+ invoices: {
420
+ retrieve: (invoiceId, options) => http.request("GET", `/v1/invoices/${id(invoiceId)}`, options),
421
+ ...lister(http, "/v1/invoices"),
422
+ },
423
+ /** The customer portal: a one-hour link for one customer, doing only what you allow. */
424
+ portalSessions: {
425
+ create: (body, options) => http.request("POST", "/v1/portal_sessions", { body, ...options }),
426
+ },
427
+ /** Codes a customer types for a coupon, matched in any case. */
428
+ promoCodes: {
429
+ create: (body, options) => http.request("POST", "/v1/promo_codes", { body, ...options }),
430
+ retrieve: (promoCodeId, options) => http.request("GET", `/v1/promo_codes/${id(promoCodeId)}`, options),
431
+ deactivate: (promoCodeId, options) => http.request("POST", `/v1/promo_codes/${id(promoCodeId)}/deactivate`, options),
432
+ ...lister(http, "/v1/promo_codes"),
433
+ },
434
+ /** Someone paying for a plan, over and over, on a card they saved. */
435
+ subscriptions: {
436
+ /** Charges the first period now, unless the plan has a trial. */
437
+ create: (body, options) => http.request("POST", "/v1/subscriptions", { body, ...options }),
438
+ retrieve: (subscriptionId, options) => http.request("GET", `/v1/subscriptions/${id(subscriptionId)}`, options),
439
+ /**
440
+ * What moving to another plan would cost — the unused time credited, the remaining time
441
+ * charged. Pass the `proration_at` it returns back to `change` and the charge is this
442
+ * number to the penny.
443
+ */
444
+ preview: (subscriptionId, body, options) => http.request("POST", `/v1/subscriptions/${id(subscriptionId)}/preview`, {
445
+ body,
446
+ ...options,
447
+ }),
448
+ /** A dearer plan is charged and takes effect now; a cheaper one waits for the period. */
449
+ change: (subscriptionId, body, options) => http.request("POST", `/v1/subscriptions/${id(subscriptionId)}/change`, {
450
+ body,
451
+ ...options,
452
+ }),
453
+ /** Ends it — now, or with `at_period_end: true` when the period they have paid for ends. */
454
+ cancel: (subscriptionId, body, options) => http.request("POST", `/v1/subscriptions/${id(subscriptionId)}/cancel`, {
455
+ ...(body ? { body } : {}),
456
+ ...options,
457
+ }),
458
+ /** Nothing is charged until it resumes — on `resumes_at`, or when `resume` is called. */
459
+ pause: (subscriptionId, body, options) => http.request("POST", `/v1/subscriptions/${id(subscriptionId)}/pause`, {
460
+ ...(body ? { body } : {}),
461
+ ...options,
462
+ }),
463
+ /** Charged now if the period it had paid for is over; otherwise it simply carries on. */
464
+ resume: (subscriptionId, options) => http.request("POST", `/v1/subscriptions/${id(subscriptionId)}/resume`, options),
465
+ /** Takes back a cancellation set for the end of the period, before it lands. */
466
+ reactivate: (subscriptionId, options) => http.request("POST", `/v1/subscriptions/${id(subscriptionId)}/reactivate`, options),
467
+ ...lister(http, "/v1/subscriptions"),
468
+ },
469
+ payments: {
470
+ /** Creates the payment; the payer pays at its `approval_url` (or your page, with the JS SDK). */
471
+ create: (body, options) => http.request("POST", "/v1/payments", { body, ...options }),
472
+ /** Charges a card the customer saved for off-session use, under its mandate. */
473
+ chargeSaved: (body, options) => http.request("POST", "/v1/payments/charge_saved", { body, ...options }),
474
+ retrieve: (paymentId, options) => http.request("GET", `/v1/payments/${id(paymentId)}`, options),
475
+ /** Presents a card — in test mode, one of Stripe's test cards by name (`pm_card_gb`). */
476
+ confirm: (paymentId, body, options) => http.request("POST", `/v1/payments/${id(paymentId)}/confirm`, {
477
+ body,
478
+ ...options,
479
+ }),
480
+ /** Takes a held (`requires_capture`) payment — all of it, or `amount_to_capture`. */
481
+ capture: (paymentId, body = {}, options) => http.request("POST", `/v1/payments/${id(paymentId)}/capture`, {
482
+ body,
483
+ ...options,
484
+ }),
485
+ cancel: (paymentId, options) => http.request("POST", `/v1/payments/${id(paymentId)}/cancel`, options),
486
+ ...lister(http, "/v1/payments"),
487
+ },
488
+ refunds: {
489
+ create: (body, options) => http.request("POST", "/v1/refunds", { body, ...options }),
490
+ retrieve: (refundId, options) => http.request("GET", `/v1/refunds/${id(refundId)}`, options),
491
+ ...lister(http, "/v1/refunds"),
492
+ },
493
+ customers: {
494
+ create: (body, options) => http.request("POST", "/v1/customers", { body, ...options }),
495
+ retrieve: (customerId, options) => http.request("GET", `/v1/customers/${id(customerId)}`, options),
496
+ update: (customerId, body, options) => http.request("POST", `/v1/customers/${id(customerId)}`, { body, ...options }),
497
+ ...lister(http, "/v1/customers"),
498
+ /**
499
+ * What the customer told your store's quiz they like (91-07), kept only when they ticked
500
+ * *Remember my answers*: all of it, by attribute. It orders their search, never their prices.
501
+ */
502
+ preferences: (customerId, options) => http.request("GET", `/v1/customers/${id(customerId)}/preferences`, options),
503
+ },
504
+ balance: {
505
+ retrieve: (options) => http.request("GET", "/v1/balance", options),
506
+ /**
507
+ * Everything that moved the balance, newest first. Filters: `type` (comma-separated),
508
+ * `payout` (what that payout covered); a platform's Connect balance with `balance: "connect"`.
509
+ */
510
+ listTransactions: (params = {}, options) => http.request("GET", "/v1/balance/transactions", {
511
+ query: params,
512
+ ...options,
513
+ }),
514
+ listAllTransactions: (params = {}, options) => lister(http, "/v1/balance/transactions").listAll(params, options),
515
+ },
516
+ payouts: {
517
+ create: (body, options) => http.request("POST", "/v1/payouts", { body, ...options }),
518
+ retrieve: (payoutId, options) => http.request("GET", `/v1/payouts/${id(payoutId)}`, options),
519
+ ...lister(http, "/v1/payouts"),
520
+ /** What the payout covered, from the books: the balance before, its activity, after. */
521
+ reconciliation: (payoutId, options) => http.request("GET", `/v1/payouts/${id(payoutId)}/reconciliation`, options),
522
+ /**
523
+ * What an instant move would cost (0.99%, taken out of it) and what arrives — at the bank
524
+ * (the default) or, with `destination: "card_balance"`, on the card balance — and when.
525
+ * Omit `amount` for the most that could go now. A destination that can't be used still
526
+ * answers, `available: false`, with the `reason`, `message` and `fix_url`.
527
+ */
528
+ instantQuote: (params = {}, options) => http.request("GET", "/v1/payouts/instant/quote", {
529
+ query: {
530
+ ...(params.amount !== undefined ? { amount: String(params.amount) } : {}),
531
+ ...(params.destination ? { destination: params.destination } : {}),
532
+ },
533
+ ...options,
534
+ }),
535
+ /** The schedule, the bank, the limits, and instant access per destination. */
536
+ settings: (options) => http.request("GET", "/v1/payout_settings", options),
537
+ /**
538
+ * Next-day payouts (UK) on or off: 0.2% on each payment from then on, paid out the day after
539
+ * it's taken. Refused with `next_day_unavailable` (and its `reason`) until
540
+ * `settings().next_day.available` says so.
541
+ */
542
+ setNextDay: (body, options) => http.request("POST", "/v1/payout_settings/next_day", { body, ...options }),
543
+ },
544
+ disputes: {
545
+ retrieve: (disputeId, options) => http.request("GET", `/v1/disputes/${id(disputeId)}`, options),
546
+ update: (disputeId, body, options) => http.request("POST", `/v1/disputes/${id(disputeId)}`, { body, ...options }),
547
+ submit: (disputeId, options) => http.request("POST", `/v1/disputes/${id(disputeId)}/submit`, options),
548
+ ...lister(http, "/v1/disputes"),
549
+ },
550
+ events: {
551
+ retrieve: (eventId, options) => http.request("GET", `/v1/events/${id(eventId)}`, options),
552
+ ...lister(http, "/v1/events"),
553
+ },
554
+ webhookEndpoints: {
555
+ /** The response carries the endpoint's signing `secret` — once. Store it. */
556
+ create: (body, options) => http.request("POST", "/v1/webhook_endpoints", {
557
+ body,
558
+ ...options,
559
+ }),
560
+ retrieve: (endpointId, options) => http.request("GET", `/v1/webhook_endpoints/${id(endpointId)}`, options),
561
+ update: (endpointId, body, options) => http.request("POST", `/v1/webhook_endpoints/${id(endpointId)}`, {
562
+ body,
563
+ ...options,
564
+ }),
565
+ del: (endpointId, options) => http.request("DELETE", `/v1/webhook_endpoints/${id(endpointId)}`, options),
566
+ ...lister(http, "/v1/webhook_endpoints"),
567
+ },
568
+ /** The domains your own checkout runs on, so Apple Pay and Google Pay show there (09-13). */
569
+ paymentMethodDomains: {
570
+ create: (body, options) => http.request("POST", "/v1/payment_method_domains", {
571
+ body,
572
+ ...options,
573
+ }),
574
+ retrieve: (domainId, options) => http.request("GET", `/v1/payment_method_domains/${id(domainId)}`, options),
575
+ /** Asks Stripe to check the domain's wallets again now. */
576
+ validate: (domainId, options) => http.request("POST", `/v1/payment_method_domains/${id(domainId)}/validate`, options),
577
+ del: (domainId, options) => http.request("DELETE", `/v1/payment_method_domains/${id(domainId)}`, options),
578
+ ...lister(http, "/v1/payment_method_domains"),
579
+ },
580
+ meters: {
581
+ create: (body, options) => http.request("POST", "/v1/meters", { body, ...options }),
582
+ list: (options) => http.request("GET", "/v1/meters", options),
583
+ },
584
+ credits: {
585
+ /** Every customer holding credit, with the totals topped up and used. */
586
+ ...lister(http, "/v1/credits"),
587
+ retrieve: (customerId, options) => http.request("GET", `/v1/credits/${id(customerId)}`, options),
588
+ /** Sells credit: returns the top-up payment to be paid. */
589
+ topup: (customerId, body, options) => http.request("POST", `/v1/credits/${id(customerId)}/topups`, {
590
+ body,
591
+ ...options,
592
+ }),
593
+ /** A customer's top-ups, newest first. */
594
+ listTopups: (customerId, params = {}, options) => http.request("GET", `/v1/credits/${id(customerId)}/topups`, {
595
+ query: params,
596
+ ...options,
597
+ }),
598
+ },
599
+ meterEvents: {
600
+ /**
601
+ * Records usage and draws the customer's credit down. Naturally idempotent on
602
+ * `identifier` — the same event twice is one charge, and says `replayed`.
603
+ */
604
+ create: (body, options) => http.request("POST", "/v1/meter_events", { body, ...options }),
605
+ /** Recorded usage, newest first — one `customer`'s, or one `meter`'s (name or id). */
606
+ ...lister(http, "/v1/meter_events"),
607
+ /**
608
+ * Usage per meter and per UTC day, `from`–`to` (YYYY-MM-DD, inclusive; default the last
609
+ * 30 days) — summed from the events themselves.
610
+ */
611
+ summary: (params = {}, options) => http.request("GET", "/v1/meter_events/summary", {
612
+ query: params,
613
+ ...options,
614
+ }),
615
+ },
616
+ // ---- Tuppence Events (M114): ticketed events, their ticket types, orders and tickets. ----
617
+ // `/v1/events` is the webhook event log, so the events themselves live under `ticketing`.
618
+ ticketing: {
619
+ /** Events: a draft from a title and `starts_at`, then on sale, off sale or cancelled. */
620
+ events: {
621
+ create: (body, options) => http.request("POST", "/v1/ticketing/events", { body, ...options }),
622
+ retrieve: (eventId, options) => http.request("GET", `/v1/ticketing/events/${id(eventId)}`, options),
623
+ update: (eventId, body, options) => http.request("POST", `/v1/ticketing/events/${id(eventId)}`, {
624
+ body,
625
+ ...options,
626
+ }),
627
+ /** On sale: its page opens and `event.published` is sent. */
628
+ publish: (eventId, options) => http.request("POST", `/v1/ticketing/events/${id(eventId)}/publish`, {
629
+ body: {},
630
+ ...options,
631
+ }),
632
+ /** Off sale, back to a draft. Tickets already sold stay valid. */
633
+ unpublish: (eventId, options) => http.request("POST", `/v1/ticketing/events/${id(eventId)}/unpublish`, {
634
+ body: {},
635
+ ...options,
636
+ }),
637
+ /** For good: every ticket voided, every buyer refunded in full, once. */
638
+ cancel: (eventId, options) => http.request("POST", `/v1/ticketing/events/${id(eventId)}/cancel`, {
639
+ body: {},
640
+ ...options,
641
+ }),
642
+ /** The guest list a door device checks guests in from, with the key to verify codes. */
643
+ checkInManifest: (eventId, options) => http.request("GET", `/v1/ticketing/events/${id(eventId)}/check_in_manifest`, options),
644
+ /** Gross, refunds, fees, held and released for one event. */
645
+ settlement: (eventId, options) => http.request("GET", `/v1/ticketing/events/${id(eventId)}/settlement`, options),
646
+ /** More dates (118-01): one (`starts_at`), a list (`dates`), or a series (`repeat`). */
647
+ addDates: (eventId, body, options) => http.request("POST", `/v1/ticketing/events/${id(eventId)}/dates`, {
648
+ body,
649
+ ...options,
650
+ }),
651
+ /** Moves one date or changes its capacity; its funds hold's release follows. */
652
+ updateDate: (eventId, dateId, body, options) => http.request("POST", `/v1/ticketing/events/${id(eventId)}/dates/${id(dateId)}`, { body, ...options }),
653
+ /** Removes a date nobody has ordered for; an event keeps one date at least. */
654
+ removeDate: (eventId, dateId, options) => http.request("DELETE", `/v1/ticketing/events/${id(eventId)}/dates/${id(dateId)}`, options),
655
+ /** The door, live: tickets in by gate and by type (116-07). */
656
+ checkInCounts: (eventId, options) => http.request("GET", `/v1/ticketing/events/${id(eventId)}/check_in_counts`, options),
657
+ ...lister(http, "/v1/ticketing/events"),
658
+ },
659
+ /** Events a door can check guests in for, soonest first (116-05). */
660
+ checkInEvents: {
661
+ list: (options) => http.request("GET", "/v1/ticketing/check_in_events", options),
662
+ },
663
+ /** Messages to an event's attendees by email, text or WhatsApp, now or scheduled (118-04). */
664
+ messages: {
665
+ create: (eventId, body, options) => http.request("POST", `/v1/ticketing/events/${id(eventId)}/messages`, {
666
+ body,
667
+ ...options,
668
+ }),
669
+ retrieve: (messageId, options) => http.request("GET", `/v1/ticketing/messages/${id(messageId)}`, options),
670
+ /** A scheduled message that has not gone yet. */
671
+ cancel: (messageId, options) => http.request("POST", `/v1/ticketing/messages/${id(messageId)}/cancel`, {
672
+ body: {},
673
+ ...options,
674
+ }),
675
+ ...childLister(http, (eventId) => `/v1/ticketing/events/${id(eventId)}/messages`),
676
+ },
677
+ /** Places on sold-out ticket types' waitlists, in turn (117-07). */
678
+ waitlist: lister(http, "/v1/ticketing/waitlist"),
679
+ /** Partners' commissions on orders made with affiliate codes (118-03). */
680
+ commissions: lister(http, "/v1/ticketing/commissions"),
681
+ /** The account's settings for every event: its ad pixels (118-06). */
682
+ settings: {
683
+ retrieve: (options) => http.request("GET", "/v1/ticketing/settings", options),
684
+ update: (body, options) => http.request("POST", "/v1/ticketing/settings", { body, ...options }),
685
+ },
686
+ /** Promo and access codes, typed by the buyer at checkout (114-07). */
687
+ promoCodes: {
688
+ create: (body, options) => http.request("POST", "/v1/ticketing/promo_codes", { body, ...options }),
689
+ retrieve: (codeId, options) => http.request("GET", `/v1/ticketing/promo_codes/${id(codeId)}`, options),
690
+ update: (codeId, body, options) => http.request("POST", `/v1/ticketing/promo_codes/${id(codeId)}`, {
691
+ body,
692
+ ...options,
693
+ }),
694
+ del: (codeId, options) => http.request("DELETE", `/v1/ticketing/promo_codes/${id(codeId)}`, options),
695
+ ...lister(http, "/v1/ticketing/promo_codes"),
696
+ },
697
+ /** Scans at the door: a `code`, a `short_code` or a `ticket`; the first scan admits. */
698
+ checkIns: {
699
+ create: (body, options) => http.request("POST", "/v1/ticketing/check_ins", { body, ...options }),
700
+ /** A device's offline scans, applied in the order they were made. */
701
+ sync: (body, options) => http.request("POST", "/v1/ticketing/check_ins/sync", { body, ...options }),
702
+ /** Newest first; `event` or `ticket` for one's. A refused scan has no id, so no `listAll`. */
703
+ list: (params = {}, options) => http.request("GET", "/v1/ticketing/check_ins", {
704
+ query: params,
705
+ ...options,
706
+ }),
707
+ },
708
+ /** Ticket money held until after each date, and when it is released (114-05). */
709
+ fundsHolds: lister(http, "/v1/ticketing/funds_holds"),
710
+ reports: {
711
+ /** Sales by event, ticket type and source; `from` and `to` are `YYYY-MM-DD`. */
712
+ sales: (params = {}, options) => http.request("GET", "/v1/ticketing/reports/sales", {
713
+ query: params,
714
+ ...options,
715
+ }),
716
+ },
717
+ },
718
+ /** What an event sells: free or paid, with up to five price phases before the base price. */
719
+ ticketTypes: {
720
+ create: (body, options) => http.request("POST", "/v1/ticket_types", { body, ...options }),
721
+ retrieve: (typeId, options) => http.request("GET", `/v1/ticket_types/${id(typeId)}`, options),
722
+ update: (typeId, body, options) => http.request("POST", `/v1/ticket_types/${id(typeId)}`, { body, ...options }),
723
+ /** Off sale for good; tickets already sold stay valid. */
724
+ archive: (typeId, options) => http.request("DELETE", `/v1/ticket_types/${id(typeId)}`, options),
725
+ ...lister(http, "/v1/ticket_types"),
726
+ },
727
+ /** Buyers' orders, placed on the event page; a key reads and refunds them. */
728
+ ticketOrders: {
729
+ retrieve: (orderId, options) => http.request("GET", `/v1/ticket_orders/${id(orderId)}`, options),
730
+ /** In full, or `tickets` by id: they are voided and their seats go back on sale. */
731
+ refund: (orderId, body = {}, options) => http.request("POST", `/v1/ticket_orders/${id(orderId)}/refund`, {
732
+ body,
733
+ ...options,
734
+ }),
735
+ /** An approval-only event's request (118-02): approve it, and the buyer is asked to pay. */
736
+ approve: (orderId, options) => http.request("POST", `/v1/ticket_orders/${id(orderId)}/approve`, {
737
+ body: {},
738
+ ...options,
739
+ }),
740
+ /** Decline a request; its seats go back on sale. */
741
+ decline: (orderId, options) => http.request("POST", `/v1/ticket_orders/${id(orderId)}/decline`, {
742
+ body: {},
743
+ ...options,
744
+ }),
745
+ ...lister(http, "/v1/ticket_orders"),
746
+ },
747
+ /** One admission each: its holder, status and short code. */
748
+ tickets: {
749
+ retrieve: (ticketId, options) => http.request("GET", `/v1/tickets/${id(ticketId)}`, options),
750
+ /** Give it to someone else (117-06): it is voided and a new ticket issued to them. */
751
+ transfer: (ticketId, body, options) => http.request("POST", `/v1/tickets/${id(ticketId)}/transfer`, {
752
+ body,
753
+ ...options,
754
+ }),
755
+ /** Back to a sold-out type's waitlist to sell at face value (117-08). */
756
+ return: (ticketId, options) => http.request("POST", `/v1/tickets/${id(ticketId)}/return`, {
757
+ body: {},
758
+ ...options,
759
+ }),
760
+ ...lister(http, "/v1/tickets"),
761
+ },
762
+ // ---- Bookings (M23) ----
763
+ /** Where services happen (23-03). Every account has one from the first look. */
764
+ locations: {
765
+ create: (body, options) => http.request("POST", "/v1/locations", { body, ...options }),
766
+ retrieve: (locationId, options) => http.request("GET", `/v1/locations/${id(locationId)}`, options),
767
+ update: (locationId, body, options) => http.request("POST", `/v1/locations/${id(locationId)}`, { body, ...options }),
768
+ archive: (locationId, options) => http.request("POST", `/v1/locations/${id(locationId)}/archive`, options),
769
+ /** Does a mobile location cover a client — by `postcode`, or `lat` and `lng`? */
770
+ coverage: (locationId, params, options) => http.request("GET", `/v1/locations/${id(locationId)}/coverage`, {
771
+ query: params,
772
+ ...options,
773
+ }),
774
+ ...lister(http, "/v1/locations"),
775
+ },
776
+ /**
777
+ * The country packs (31-19): a country's tax components and classes, location tax defaults,
778
+ * receipt rules, rounding and conventions, as data. Reference data — the same for every account,
779
+ * readable with any key.
780
+ */
781
+ countryPacks: {
782
+ /** A country's pack (`GB`, `CA`, `US`…) — or a province's or state's with `region` (`QC`, `TX`). */
783
+ retrieve: (country, params = {}, options) => http.request("GET", `/v1/country_packs/${id(country)}`, {
784
+ query: params,
785
+ ...options,
786
+ }),
787
+ },
788
+ /** Headings services are grouped under (23-04). */
789
+ serviceCategories: {
790
+ create: (body, options) => http.request("POST", "/v1/service_categories", { body, ...options }),
791
+ retrieve: (categoryId, options) => http.request("GET", `/v1/service_categories/${id(categoryId)}`, options),
792
+ update: (categoryId, body, options) => http.request("POST", `/v1/service_categories/${id(categoryId)}`, {
793
+ body,
794
+ ...options,
795
+ }),
796
+ archive: (categoryId, options) => http.request("POST", `/v1/service_categories/${id(categoryId)}/archive`, options),
797
+ ...lister(http, "/v1/service_categories"),
798
+ },
799
+ /** What a business offers (23-04): duration, price, options, add-ons, what it needs, who does it. */
800
+ services: {
801
+ create: (body, options) => http.request("POST", "/v1/services", { body, ...options }),
802
+ retrieve: (serviceId, options) => http.request("GET", `/v1/services/${id(serviceId)}`, options),
803
+ update: (serviceId, body, options) => http.request("POST", `/v1/services/${id(serviceId)}`, { body, ...options }),
804
+ archive: (serviceId, options) => http.request("POST", `/v1/services/${id(serviceId)}/archive`, options),
805
+ createVariant: (serviceId, body, options) => http.request("POST", `/v1/services/${id(serviceId)}/variants`, {
806
+ body,
807
+ ...options,
808
+ }),
809
+ updateVariant: (serviceId, variantId, body, options) => http.request("POST", `/v1/services/${id(serviceId)}/variants/${id(variantId)}`, { body, ...options }),
810
+ createAddon: (serviceId, body, options) => http.request("POST", `/v1/services/${id(serviceId)}/addons`, {
811
+ body,
812
+ ...options,
813
+ }),
814
+ updateAddon: (serviceId, addonId, body, options) => http.request("POST", `/v1/services/${id(serviceId)}/addons/${id(addonId)}`, {
815
+ body,
816
+ ...options,
817
+ }),
818
+ /** The whole list of what it needs — `[{kind, count}]`; what is not here is no longer needed. */
819
+ setResources: (serviceId, body, options) => http.request("POST", `/v1/services/${id(serviceId)}/resources`, {
820
+ body,
821
+ ...options,
822
+ }),
823
+ /** The whole list of who performs it; empty means everyone active does. */
824
+ setStaff: (serviceId, body, options) => http.request("POST", `/v1/services/${id(serviceId)}/staff`, {
825
+ body,
826
+ ...options,
827
+ }),
828
+ setImage: (serviceId, body, options) => http.request("POST", `/v1/services/${id(serviceId)}/image`, {
829
+ body,
830
+ ...options,
831
+ }),
832
+ removeImage: (serviceId, options) => http.request("DELETE", `/v1/services/${id(serviceId)}/image`, options),
833
+ /** What it would take and cost as chosen — an option, add-ons, a person, a group. */
834
+ quote: (serviceId, body = {}, options) => http.request("POST", `/v1/services/${id(serviceId)}/quote`, {
835
+ body,
836
+ ...options,
837
+ }),
838
+ ...lister(http, "/v1/services"),
839
+ },
840
+ /** The people who perform services (23-05), and their hours. */
841
+ staff: {
842
+ create: (body, options) => http.request("POST", "/v1/staff", { body, ...options }),
843
+ retrieve: (staffId, options) => http.request("GET", `/v1/staff/${id(staffId)}`, options),
844
+ update: (staffId, body, options) => http.request("POST", `/v1/staff/${id(staffId)}`, { body, ...options }),
845
+ archive: (staffId, options) => http.request("POST", `/v1/staff/${id(staffId)}/archive`, options),
846
+ setLocations: (staffId, body, options) => http.request("POST", `/v1/staff/${id(staffId)}/locations`, {
847
+ body,
848
+ ...options,
849
+ }),
850
+ setServices: (staffId, body, options) => http.request("POST", `/v1/staff/${id(staffId)}/services`, {
851
+ body,
852
+ ...options,
853
+ }),
854
+ setImage: (staffId, body, options) => http.request("POST", `/v1/staff/${id(staffId)}/image`, { body, ...options }),
855
+ removeImage: (staffId, options) => http.request("DELETE", `/v1/staff/${id(staffId)}/image`, options),
856
+ /** Hours: a weekly pattern or a two-week rotation at a location, from a date. */
857
+ createSchedule: (staffId, body, options) => http.request("POST", `/v1/staff/${id(staffId)}/schedules`, {
858
+ body,
859
+ ...options,
860
+ }),
861
+ updateSchedule: (staffId, scheduleId, body, options) => http.request("POST", `/v1/staff/${id(staffId)}/schedules/${id(scheduleId)}`, {
862
+ body,
863
+ ...options,
864
+ }),
865
+ listSchedules: (staffId, options) => http.request("GET", `/v1/staff/${id(staffId)}/schedules`, options),
866
+ /** When they actually work between two dates: hours, less time off, plus extra hours. */
867
+ workingHours: (staffId, params, options) => http.request("GET", `/v1/staff/${id(staffId)}/working_hours`, {
868
+ query: params,
869
+ ...options,
870
+ }),
871
+ ...lister(http, "/v1/staff"),
872
+ },
873
+ /** Time off, breaks, blocked time and extra hours (23-05). */
874
+ scheduleExceptions: {
875
+ create: (body, options) => http.request("POST", "/v1/schedule_exceptions", { body, ...options }),
876
+ retrieve: (exceptionId, options) => http.request("GET", `/v1/schedule_exceptions/${id(exceptionId)}`, options),
877
+ del: (exceptionId, options) => http.request("DELETE", `/v1/schedule_exceptions/${id(exceptionId)}`, options),
878
+ ...lister(http, "/v1/schedule_exceptions"),
879
+ },
880
+ /** Rooms, chairs, baths — what a service needs besides a person (23-06). */
881
+ resources: {
882
+ create: (body, options) => http.request("POST", "/v1/resources", { body, ...options }),
883
+ retrieve: (resourceId, options) => http.request("GET", `/v1/resources/${id(resourceId)}`, options),
884
+ update: (resourceId, body, options) => http.request("POST", `/v1/resources/${id(resourceId)}`, { body, ...options }),
885
+ archive: (resourceId, options) => http.request("POST", `/v1/resources/${id(resourceId)}/archive`, options),
886
+ /** Could these requirements be met at a location — and if not, what is short? */
887
+ check: (body, options) => http.request("POST", "/v1/resources/check", { body, ...options }),
888
+ ...lister(http, "/v1/resources"),
889
+ },
890
+ /** The account's booking policy (23-07): deposits, cancellation, notice, approval, holds. */
891
+ bookingPolicy: {
892
+ retrieve: (options) => http.request("GET", "/v1/booking_policy", options),
893
+ /** Every change is a new version; bookings keep the one their client accepted. */
894
+ update: (body, options) => http.request("POST", "/v1/booking_policy", { body, ...options }),
895
+ listVersions: (params = {}, options) => http.request("GET", "/v1/booking_policy/versions", {
896
+ query: params,
897
+ ...options,
898
+ }),
899
+ /** The policy's words as a client sees them — for a service, an amount, or a draft. */
900
+ render: (body = {}, options) => http.request("POST", "/v1/booking_policy/render", { body, ...options }),
901
+ },
902
+ /** The business's public booking page (24-01): its address, look, content, flow — and whether it is published. */
903
+ bookingPage: {
904
+ retrieve: (options) => http.request("GET", "/v1/booking_page", options),
905
+ /** Each of `theme`, `content`, `flow` and `seo` is a patch; a new `slug` keeps the old one redirecting for 90 days. */
906
+ update: (body, options) => http.request("POST", "/v1/booking_page", { body, ...options }),
907
+ publish: (options) => http.request("POST", "/v1/booking_page/publish", { body: {}, ...options }),
908
+ unpublish: (options) => http.request("POST", "/v1/booking_page/unpublish", { body: {}, ...options }),
909
+ /** Shown once; minting another retires the last. */
910
+ createPreviewToken: (options) => http.request("POST", "/v1/booking_page/preview_token", {
911
+ body: {},
912
+ ...options,
913
+ }),
914
+ /** A picture (base64 PNG or JPEG), re-encoded and shown last; at most 20. */
915
+ addGalleryImage: (body, options) => http.request("POST", "/v1/booking_page/gallery", { body, ...options }),
916
+ setCover: (body, options) => http.request("POST", "/v1/booking_page/cover", { body, ...options }),
917
+ },
918
+ /** When a client could book (23-10). */
919
+ availability: {
920
+ /**
921
+ * The starts between `from` and `to` (`YYYY-MM-DD`, up to 62 days) for a `service` (with
922
+ * `variant` and `addons`) or `items` (`svc_…` or `svc_…:svar_…`, a visit of several), at a
923
+ * `location`, with a `staff_member` or anyone.
924
+ */
925
+ query: (params, options) => {
926
+ const { addons, items, ...rest } = params;
927
+ return http.request("GET", "/v1/availability", {
928
+ query: {
929
+ ...rest,
930
+ ...(addons ? { addons: addons.join(",") } : {}),
931
+ ...(items ? { items: items.join(",") } : {}),
932
+ },
933
+ ...options,
934
+ });
935
+ },
936
+ /** The first start a client could book, on or after `from` (today by default). */
937
+ next: (params, options) => {
938
+ const { addons, items, ...rest } = params;
939
+ return http.request("GET", "/v1/availability/next", {
940
+ query: {
941
+ ...rest,
942
+ ...(addons ? { addons: addons.join(",") } : {}),
943
+ ...(items ? { items: items.join(",") } : {}),
944
+ },
945
+ ...options,
946
+ });
947
+ },
948
+ },
949
+ /** Bookings (23-11, 23-12): made from what availability offered, then their whole life. */
950
+ bookings: {
951
+ /** Needs an idempotency key — the SDK always sends one. `409 slot_unavailable` names other starts. */
952
+ create: (body, options) => http.request("POST", "/v1/bookings", { body, ...options }),
953
+ retrieve: (bookingId, options) => http.request("GET", `/v1/bookings/${id(bookingId)}`, options),
954
+ /** Notes and metadata. When, and with whom, is `reschedule`. */
955
+ update: (bookingId, body, options) => http.request("POST", `/v1/bookings/${id(bookingId)}`, { body, ...options }),
956
+ /** Takes the slot for the policy's `hold_minutes` with no client yet; confirm it to book. */
957
+ hold: (body, options) => http.request("POST", "/v1/bookings/holds", { body, ...options }),
958
+ extendHold: (bookingId, options) => http.request("POST", `/v1/bookings/holds/${id(bookingId)}/extend`, options),
959
+ releaseHold: (bookingId, options) => http.request("POST", `/v1/bookings/holds/${id(bookingId)}/release`, options),
960
+ confirm: (bookingId, body = {}, options) => http.request("POST", `/v1/bookings/${id(bookingId)}/confirm`, {
961
+ body,
962
+ ...options,
963
+ }),
964
+ reschedule: (bookingId, body, options) => http.request("POST", `/v1/bookings/${id(bookingId)}/reschedule`, {
965
+ body,
966
+ ...options,
967
+ }),
968
+ /** `by: "client"` applies the policy's outcome; the business owes nothing and returns everything. */
969
+ cancel: (bookingId, body = {}, options) => http.request("POST", `/v1/bookings/${id(bookingId)}/cancel`, {
970
+ body,
971
+ ...options,
972
+ }),
973
+ checkIn: (bookingId, options) => http.request("POST", `/v1/bookings/${id(bookingId)}/check_in`, options),
974
+ start: (bookingId, options) => http.request("POST", `/v1/bookings/${id(bookingId)}/start`, options),
975
+ complete: (bookingId, options) => http.request("POST", `/v1/bookings/${id(bookingId)}/complete`, options),
976
+ noShow: (bookingId, options) => http.request("POST", `/v1/bookings/${id(bookingId)}/no_show`, options),
977
+ approve: (bookingId, options) => http.request("POST", `/v1/bookings/${id(bookingId)}/approve`, options),
978
+ decline: (bookingId, body = {}, options) => http.request("POST", `/v1/bookings/${id(bookingId)}/decline`, {
979
+ body,
980
+ ...options,
981
+ }),
982
+ ...lister(http, "/v1/bookings"),
983
+ },
984
+ /** A class's sessions (23-13): scheduled, with seats. */
985
+ classSessions: {
986
+ create: (body, options) => http.request("POST", "/v1/class_sessions", { body, ...options }),
987
+ retrieve: (sessionId, options) => http.request("GET", `/v1/class_sessions/${id(sessionId)}`, options),
988
+ update: (sessionId, body, options) => http.request("POST", `/v1/class_sessions/${id(sessionId)}`, {
989
+ body,
990
+ ...options,
991
+ }),
992
+ cancel: (sessionId, body = {}, options) => http.request("POST", `/v1/class_sessions/${id(sessionId)}/cancel`, {
993
+ body,
994
+ ...options,
995
+ }),
996
+ ...lister(http, "/v1/class_sessions"),
997
+ },
998
+ /** "Every Monday at 10:00 with Ana" (23-14): a rule, kept as bookings eight weeks ahead. */
999
+ bookingSeries: {
1000
+ create: (body, options) => http.request("POST", "/v1/booking_series", { body, ...options }),
1001
+ retrieve: (seriesId, options) => http.request("GET", `/v1/booking_series/${id(seriesId)}`, options),
1002
+ /** "This and following": a new time or person from a date. */
1003
+ update: (seriesId, body, options) => http.request("POST", `/v1/booking_series/${id(seriesId)}`, {
1004
+ body,
1005
+ ...options,
1006
+ }),
1007
+ skip: (seriesId, body, options) => http.request("POST", `/v1/booking_series/${id(seriesId)}/skip`, {
1008
+ body,
1009
+ ...options,
1010
+ }),
1011
+ end: (seriesId, body = {}, options) => http.request("POST", `/v1/booking_series/${id(seriesId)}/end`, {
1012
+ body,
1013
+ ...options,
1014
+ }),
1015
+ ...lister(http, "/v1/booking_series"),
1016
+ },
1017
+ /** Wishes for a slot that is not there yet (23-15), offered the moment one frees up. */
1018
+ waitlist: {
1019
+ create: (body, options) => http.request("POST", "/v1/waitlist", { body, ...options }),
1020
+ retrieve: (entryId, options) => http.request("GET", `/v1/waitlist/${id(entryId)}`, options),
1021
+ update: (entryId, body, options) => http.request("POST", `/v1/waitlist/${id(entryId)}`, { body, ...options }),
1022
+ cancel: (entryId, options) => http.request("POST", `/v1/waitlist/${id(entryId)}/cancel`, options),
1023
+ /** Takes up the open offer: the held slot becomes the client's booking. */
1024
+ accept: (entryId, options) => http.request("POST", `/v1/waitlist/${id(entryId)}/accept`, options),
1025
+ ...lister(http, "/v1/waitlist"),
1026
+ },
1027
+ // ---- The store (94-02): every store operation has a method here and in Python, which
1028
+ // `scripts/check-sdk-coverage.mjs` holds to as each store resource ships. ----
1029
+ /** Customers' reviews (M91): read them, reply, hide one, publish one. */
1030
+ reviews: {
1031
+ retrieve: (reviewId, options) => http.request("GET", `/v1/reviews/${id(reviewId)}`, options),
1032
+ /** The average and the count, as the store shows them. */
1033
+ summary: (options) => http.request("GET", "/v1/reviews/summary", options),
1034
+ reply: (reviewId, body, options) => http.request("POST", `/v1/reviews/${id(reviewId)}/reply`, { body, ...options }),
1035
+ hide: (reviewId, options) => http.request("POST", `/v1/reviews/${id(reviewId)}/hide`, { body: {}, ...options }),
1036
+ publish: (reviewId, options) => http.request("POST", `/v1/reviews/${id(reviewId)}/publish`, {
1037
+ body: {},
1038
+ ...options,
1039
+ }),
1040
+ ...lister(http, "/v1/reviews"),
1041
+ },
1042
+ /** What changed in the store and who changed it, each with its undo (92-01). */
1043
+ changeSets: {
1044
+ retrieve: (changeSetId, options) => http.request("GET", `/v1/change_sets/${id(changeSetId)}`, options),
1045
+ /** Undoes the change, if nothing since depends on it. */
1046
+ revert: (changeSetId, options) => http.request("POST", `/v1/change_sets/${id(changeSetId)}/revert`, {
1047
+ body: {},
1048
+ ...options,
1049
+ }),
1050
+ ...lister(http, "/v1/change_sets"),
1051
+ },
1052
+ /** Moving a store from another platform (93-01): files, a preview, then the run. */
1053
+ storeImports: {
1054
+ create: (body, options) => http.request("POST", "/v1/store_imports", { body, ...options }),
1055
+ retrieve: (importId, options) => http.request("GET", `/v1/store_imports/${id(importId)}`, options),
1056
+ /**
1057
+ * What a completed import's last 12 months of orders would have cost on Tuppence, beside the
1058
+ * plan you paid: a confirmed `plan`, or your own `monthly_fee`, `card_bps` and `card_fixed`.
1059
+ */
1060
+ savings: (importId, params = {}, options) => http.request("GET", `/v1/store_imports/${id(importId)}/savings`, {
1061
+ query: Object.fromEntries(Object.entries(params)
1062
+ .filter(([, v]) => v !== undefined)
1063
+ .map(([k, v]) => [k, String(v)])),
1064
+ ...options,
1065
+ }),
1066
+ update: (importId, body, options) => http.request("POST", `/v1/store_imports/${id(importId)}`, {
1067
+ body,
1068
+ ...options,
1069
+ }),
1070
+ /** An export file, in parts of up to 800,000 characters. */
1071
+ addFile: (importId, body, options) => http.request("POST", `/v1/store_imports/${id(importId)}/files`, {
1072
+ body,
1073
+ ...options,
1074
+ }),
1075
+ /** What would come across, writing nothing. */
1076
+ preview: (importId, options) => http.request("POST", `/v1/store_imports/${id(importId)}/preview`, {
1077
+ body: {},
1078
+ ...options,
1079
+ }),
1080
+ run: (importId, options) => http.request("POST", `/v1/store_imports/${id(importId)}/run`, {
1081
+ body: {},
1082
+ ...options,
1083
+ }),
1084
+ /** The stock mirror that keeps the old store and this one level while you move (live mode). */
1085
+ retrieveStockMirror: (importId, options) => http.request("GET", `/v1/store_imports/${id(importId)}/stock_mirror`, options),
1086
+ /** Turn the stock mirror on (with `credentials` after it was off) or off. */
1087
+ setStockMirror: (importId, body, options) => http.request("POST", `/v1/store_imports/${id(importId)}/stock_mirror`, {
1088
+ body,
1089
+ ...options,
1090
+ }),
1091
+ ...lister(http, "/v1/store_imports"),
1092
+ },
1093
+ /** The store's operator jobs (M92): what each does, its runs, briefs and examples. */
1094
+ assistantJobs: {
1095
+ list: (options) => http.request("GET", "/v1/assistant_jobs", options),
1096
+ retrieve: (jobId, options) => http.request("GET", `/v1/assistant_jobs/${id(jobId)}`, options),
1097
+ runs: childLister(http, (jobId) => `/v1/assistant_jobs/${id(jobId)}/runs`),
1098
+ listBriefs: (jobId, options) => http.request("GET", `/v1/assistant_jobs/${id(jobId)}/briefs`, options),
1099
+ listExamples: (jobId, options) => http.request("GET", `/v1/assistant_jobs/${id(jobId)}/examples`, options),
1100
+ },
1101
+ /**
1102
+ * Sales per channel (90-17): orders, units, gross, discounts, refunds, the channel's own
1103
+ * fees (estimated and final apart, never Tuppence's) and net; `from`/`to` are business days.
1104
+ */
1105
+ channelReports: {
1106
+ retrieve: (params = {}, options) => http.request("GET", "/v1/reports/channels", {
1107
+ query: params,
1108
+ ...options,
1109
+ }),
1110
+ },
1111
+ /** The store's daily briefs (M92). */
1112
+ storeBriefs: {
1113
+ retrieve: (briefId, options) => http.request("GET", `/v1/store_briefs/${id(briefId)}`, options),
1114
+ ...lister(http, "/v1/store_briefs"),
1115
+ },
1116
+ /**
1117
+ * The business's one store site (85-02): settings, domains, fonts, pages, publishing and
1118
+ * its versions. `list` answers the one site, so `data[0].id` is the site to work on.
1119
+ */
1120
+ sites: {
1121
+ list: (options) => http.request("GET", "/v1/sites", options),
1122
+ retrieve: (siteId, options) => http.request("GET", `/v1/sites/${id(siteId)}`, options),
1123
+ update: (siteId, body, options) => http.request("POST", `/v1/sites/${id(siteId)}`, { body, ...options }),
1124
+ /** Takes checkouts again after the store paused them. */
1125
+ resumeCheckouts: (siteId, options) => http.request("POST", `/v1/sites/${id(siteId)}/resume_checkouts`, {
1126
+ body: {},
1127
+ ...options,
1128
+ }),
1129
+ /** A new free address; the old one redirects to it. */
1130
+ changeSlug: (siteId, body, options) => http.request("POST", `/v1/sites/${id(siteId)}/slug`, { body, ...options }),
1131
+ /** Publishes the draft as a new version, live at once. */
1132
+ publish: (siteId, body = {}, options) => http.request("POST", `/v1/sites/${id(siteId)}/publish`, { body, ...options }),
1133
+ /** Publishes the draft at `at` (Unix seconds). */
1134
+ schedule: (siteId, body, options) => http.request("POST", `/v1/sites/${id(siteId)}/schedule`, {
1135
+ body,
1136
+ ...options,
1137
+ }),
1138
+ cancelSchedule: (siteId, options) => http.request("DELETE", `/v1/sites/${id(siteId)}/schedule`, options),
1139
+ /** A short-lived link to the draft, for someone without a dashboard login. */
1140
+ createPreviewToken: (siteId, options) => http.request("POST", `/v1/sites/${id(siteId)}/preview_token`, {
1141
+ body: {},
1142
+ ...options,
1143
+ }),
1144
+ /** What a page would render with: the site's data for blocks you send, saving nothing. */
1145
+ renderContext: (siteId, body = {}, options) => http.request("POST", `/v1/sites/${id(siteId)}/render_context`, {
1146
+ body,
1147
+ ...options,
1148
+ }),
1149
+ /** What stands between the store and taking orders, each with its fix. */
1150
+ readiness: (siteId, options) => http.request("GET", `/v1/sites/${id(siteId)}/readiness`, options),
1151
+ sellingAbroad: (siteId, options) => http.request("GET", `/v1/sites/${id(siteId)}/selling_abroad`, options),
1152
+ checklist: (siteId, options) => http.request("GET", `/v1/sites/${id(siteId)}/checklist`, options),
1153
+ retrieveReturnPolicy: (siteId, options) => http.request("GET", `/v1/sites/${id(siteId)}/return_policy`, options),
1154
+ updateReturnPolicy: (siteId, body, options) => http.request("POST", `/v1/sites/${id(siteId)}/return_policy`, {
1155
+ body,
1156
+ ...options,
1157
+ }),
1158
+ /** Your own domains: add one, check its DNS records, remove it. */
1159
+ domains: {
1160
+ list: (siteId, options) => http.request("GET", `/v1/sites/${id(siteId)}/domains`, options),
1161
+ add: (siteId, body, options) => http.request("POST", `/v1/sites/${id(siteId)}/domains`, {
1162
+ body,
1163
+ ...options,
1164
+ }),
1165
+ check: (siteId, hostname, options) => http.request("POST", `/v1/sites/${id(siteId)}/domains/${id(hostname)}/check`, { body: {}, ...options }),
1166
+ remove: (siteId, hostname, options) => http.request("DELETE", `/v1/sites/${id(siteId)}/domains/${id(hostname)}`, options),
1167
+ },
1168
+ /** Moving the old store's domain here, the certificate first and the email records kept (live mode). */
1169
+ domainSwitch: {
1170
+ retrieve: (siteId, options) => http.request("GET", `/v1/sites/${id(siteId)}/domain_switch`, options),
1171
+ start: (siteId, body, options) => http.request("POST", `/v1/sites/${id(siteId)}/domain_switch`, {
1172
+ body,
1173
+ ...options,
1174
+ }),
1175
+ check: (siteId, options) => http.request("POST", `/v1/sites/${id(siteId)}/domain_switch/check`, {
1176
+ body: {},
1177
+ ...options,
1178
+ }),
1179
+ switch: (siteId, options) => http.request("POST", `/v1/sites/${id(siteId)}/domain_switch/switch`, {
1180
+ body: {},
1181
+ ...options,
1182
+ }),
1183
+ rollBack: (siteId, options) => http.request("POST", `/v1/sites/${id(siteId)}/domain_switch/roll_back`, {
1184
+ body: {},
1185
+ ...options,
1186
+ }),
1187
+ },
1188
+ /** The site's fonts: a Google font by name, or your own file with its licence confirmed. */
1189
+ fonts: {
1190
+ list: (siteId, options) => http.request("GET", `/v1/sites/${id(siteId)}/fonts`, options),
1191
+ add: (siteId, body, options) => http.request("POST", `/v1/sites/${id(siteId)}/fonts`, { body, ...options }),
1192
+ remove: (siteId, family, options) => http.request("DELETE", `/v1/sites/${id(siteId)}/fonts/${id(family)}`, options),
1193
+ },
1194
+ /** The draft's pages; a change shows on the store once the site is published. */
1195
+ pages: {
1196
+ list: (siteId, options) => http.request("GET", `/v1/sites/${id(siteId)}/pages`, options),
1197
+ create: (siteId, body, options) => http.request("POST", `/v1/sites/${id(siteId)}/pages`, { body, ...options }),
1198
+ retrieve: (siteId, pageId, options) => http.request("GET", `/v1/sites/${id(siteId)}/pages/${id(pageId)}`, options),
1199
+ update: (siteId, pageId, body, options) => http.request("POST", `/v1/sites/${id(siteId)}/pages/${id(pageId)}`, {
1200
+ body,
1201
+ ...options,
1202
+ }),
1203
+ /** Archives the page; the home page cannot be archived. */
1204
+ archive: (siteId, pageId, options) => http.request("DELETE", `/v1/sites/${id(siteId)}/pages/${id(pageId)}`, options),
1205
+ },
1206
+ /** Every published version; reverting makes an old one the draft and publishes it. */
1207
+ versions: {
1208
+ list: (siteId, options) => http.request("GET", `/v1/sites/${id(siteId)}/versions`, options),
1209
+ retrieve: (siteId, versionId, options) => http.request("GET", `/v1/sites/${id(siteId)}/versions/${id(versionId)}`, options),
1210
+ revert: (siteId, versionId, options) => http.request("POST", `/v1/sites/${id(siteId)}/versions/${id(versionId)}/revert`, { body: {}, ...options }),
1211
+ },
1212
+ /** The design file: export the look, sections and layouts; import one into the draft. */
1213
+ exportDesign: (siteId, options) => http.request("GET", `/v1/sites/${id(siteId)}/design`, options),
1214
+ importDesign: (siteId, body, options) => http.request("POST", `/v1/sites/${id(siteId)}/design/import`, {
1215
+ body,
1216
+ ...options,
1217
+ }),
1218
+ /** Runs a section's source through the checks, saving nothing. */
1219
+ checkSection: (siteId, body, options) => http.request("POST", `/v1/sites/${id(siteId)}/section_checks`, {
1220
+ body,
1221
+ ...options,
1222
+ }),
1223
+ retrieveSectionVersion: (siteId, versionId, options) => http.request("GET", `/v1/sites/${id(siteId)}/section_versions/${id(versionId)}`, options),
1224
+ /** Paths shoppers asked for three or more times in a day that had no page, with suggestions. */
1225
+ listNotFound: (siteId, options) => http.request("GET", `/v1/sites/${id(siteId)}/not_found`, options),
1226
+ /** The site's translations in one of the business's languages (91-15): draft, approved or stale. */
1227
+ listTranslations: (siteId, params = {}, options) => http.request("GET", `/v1/sites/${id(siteId)}/translations`, {
1228
+ query: params,
1229
+ ...options,
1230
+ }),
1231
+ /** Drafts the site's products in a language, in the brand voice; a person approves them. */
1232
+ draftTranslations: (siteId, body, options) => http.request("POST", `/v1/sites/${id(siteId)}/translations/draft`, {
1233
+ body,
1234
+ ...options,
1235
+ }),
1236
+ /** The site's redirects (93-06), newest first, each with how often it was answered. */
1237
+ listRedirects: (siteId, params = {}, options) => http.request("GET", `/v1/sites/${id(siteId)}/redirects`, {
1238
+ query: params,
1239
+ ...options,
1240
+ }),
1241
+ /** Redirect an old path (301): a chain is flattened to one hop, a loop is refused. */
1242
+ createRedirect: (siteId, body, options) => http.request("POST", `/v1/sites/${id(siteId)}/redirects`, {
1243
+ body,
1244
+ ...options,
1245
+ }),
1246
+ /** Remove a redirect: the old path answers 404 again. */
1247
+ deleteRedirect: (siteId, redirectId, options) => http.request("DELETE", `/v1/sites/${id(siteId)}/redirects/${id(redirectId)}`, options),
1248
+ /** The design agent: a change to how the store looks, proposed for a person to approve. */
1249
+ designRuns: {
1250
+ create: (siteId, body, options) => http.request("POST", `/v1/sites/${id(siteId)}/design_runs`, {
1251
+ body,
1252
+ ...options,
1253
+ }),
1254
+ retrieve: (siteId, runId, options) => http.request("GET", `/v1/sites/${id(siteId)}/design_runs/${id(runId)}`, options),
1255
+ },
1256
+ /** The site's custom sections, each through the same checks as the agent's. */
1257
+ sections: {
1258
+ list: (siteId, options) => http.request("GET", `/v1/sites/${id(siteId)}/sections`, options),
1259
+ create: (siteId, body, options) => http.request("POST", `/v1/sites/${id(siteId)}/sections`, {
1260
+ body,
1261
+ ...options,
1262
+ }),
1263
+ retrieve: (siteId, sectionId, options) => http.request("GET", `/v1/sites/${id(siteId)}/sections/${id(sectionId)}`, options),
1264
+ rename: (siteId, sectionId, body, options) => http.request("POST", `/v1/sites/${id(siteId)}/sections/${id(sectionId)}`, {
1265
+ body,
1266
+ ...options,
1267
+ }),
1268
+ /** Takes it off every draft page; the live site keeps it until the next publish. */
1269
+ del: (siteId, sectionId, options) => http.request("DELETE", `/v1/sites/${id(siteId)}/sections/${id(sectionId)}`, options),
1270
+ duplicate: (siteId, sectionId, options) => http.request("POST", `/v1/sites/${id(siteId)}/sections/${id(sectionId)}/duplicate`, { body: {}, ...options }),
1271
+ /** An earlier version's source becomes the next version. */
1272
+ restore: (siteId, sectionId, body, options) => http.request("POST", `/v1/sites/${id(siteId)}/sections/${id(sectionId)}/restore`, { body, ...options }),
1273
+ /** The next version from source edited by hand; it becomes the current one. */
1274
+ edit: (siteId, sectionId, body, options) => http.request("POST", `/v1/sites/${id(siteId)}/sections/${id(sectionId)}/versions`, { body, ...options }),
1275
+ },
1276
+ /** Code sections, only with them switched on for the site (S25). */
1277
+ codeSections: {
1278
+ list: (siteId, options) => http.request("GET", `/v1/sites/${id(siteId)}/code_sections`, options),
1279
+ create: (siteId, body, options) => http.request("POST", `/v1/sites/${id(siteId)}/code_sections`, {
1280
+ body,
1281
+ ...options,
1282
+ }),
1283
+ retrieve: (siteId, codeId, options) => http.request("GET", `/v1/sites/${id(siteId)}/code_sections/${id(codeId)}`, options),
1284
+ },
1285
+ },
1286
+ /**
1287
+ * The store builder and its helpers (M86): a change from a sentence, the builder's proposals,
1288
+ * a product from a photo, and the store's settings. A proposal or a snap also streams its
1289
+ * progress as Server-Sent Events for a browser; from a server, `retrieve` answers the same.
1290
+ */
1291
+ store: {
1292
+ /** A change from a sentence, proposed as a change set; nothing changes until approved. */
1293
+ proposeChange: (body, options) => http.request("POST", "/v1/store/changes", { body, ...options }),
1294
+ retrieveSettings: (options) => http.request("GET", "/v1/store/settings", options),
1295
+ /** `po_limit`: the most a restock drafts on its own; `null` restores the default. */
1296
+ updateSettings: (body, options) => http.request("POST", "/v1/store/settings", { body, ...options }),
1297
+ proposals: {
1298
+ /** Newest first, without items; `{ status: "open" }` answers the one still open. */
1299
+ list: (params = {}, options) => http.request("GET", "/v1/store/proposals", {
1300
+ query: params,
1301
+ ...options,
1302
+ }),
1303
+ /** Starts the builder from any mix of a sentence, the till, a website, socials and files. */
1304
+ create: (body = {}, options) => http.request("POST", "/v1/store/proposals", { body, ...options }),
1305
+ /** The proposal with a page of its items (`group`, `limit` up to 200, `starting_after`). */
1306
+ retrieve: (proposalId, params = {}, options) => http.request("GET", `/v1/store/proposals/${id(proposalId)}`, {
1307
+ query: params,
1308
+ ...options,
1309
+ }),
1310
+ /** Discards it; nothing it proposed is kept. */
1311
+ discard: (proposalId, options) => http.request("DELETE", `/v1/store/proposals/${id(proposalId)}`, options),
1312
+ /** `accept`, `reject` or `edit` (with `payload`) one item. */
1313
+ decideItem: (proposalId, itemId, body, options) => http.request("POST", `/v1/store/proposals/${id(proposalId)}/items/${id(itemId)}`, { body, ...options }),
1314
+ /** Redoes one item on your words, at most 3 times an item. */
1315
+ redoItem: (proposalId, itemId, body, options) => http.request("POST", `/v1/store/proposals/${id(proposalId)}/items/${id(itemId)}/redo`, { body, ...options }),
1316
+ /** A link to the store as the proposal would make it, never written or cached. */
1317
+ preview: (proposalId, options) => http.request("POST", `/v1/store/proposals/${id(proposalId)}/preview`, {
1318
+ body: {},
1319
+ ...options,
1320
+ }),
1321
+ acceptAll: (proposalId, options) => http.request("POST", `/v1/store/proposals/${id(proposalId)}/accept_all`, { body: {}, ...options }),
1322
+ /** Applies every accepted item with no guess left. */
1323
+ publish: (proposalId, body = {}, options) => http.request("POST", `/v1/store/proposals/${id(proposalId)}/publish`, {
1324
+ body,
1325
+ ...options,
1326
+ }),
1327
+ },
1328
+ /** A product from 1 to 5 photos: a draft to price, count and publish. */
1329
+ snaps: {
1330
+ create: (body, options) => http.request("POST", "/v1/store/snaps", { body, ...options }),
1331
+ retrieve: (snapId, options) => http.request("GET", `/v1/store/snaps/${id(snapId)}`, options),
1332
+ /** Prices a ready snap's draft, counts its stock in and puts it on its channels. */
1333
+ publish: (snapId, body, options) => http.request("POST", `/v1/store/snaps/${id(snapId)}/publish`, {
1334
+ body,
1335
+ ...options,
1336
+ }),
1337
+ /** A studio or lifestyle shot of the main photo, added to the draft. */
1338
+ addPhoto: (snapId, body, options) => http.request("POST", `/v1/store/snaps/${id(snapId)}/photos`, {
1339
+ body,
1340
+ ...options,
1341
+ }),
1342
+ },
1343
+ },
1344
+ /**
1345
+ * Fulfilment (M87): the pick list, packing, labels from the balance or your own carrier
1346
+ * account, shipping, local delivery and collection.
1347
+ */
1348
+ fulfilments: {
1349
+ /** The pick list: what is still to leave, oldest promise first. */
1350
+ ...lister(http, "/v1/fulfilments"),
1351
+ retrieve: (fulfilmentId, options) => http.request("GET", `/v1/fulfilments/${id(fulfilmentId)}`, options),
1352
+ /** Packs it by scans, with the package and weight. */
1353
+ pack: (fulfilmentId, body, options) => http.request("POST", `/v1/fulfilments/${id(fulfilmentId)}/pack`, {
1354
+ body,
1355
+ ...options,
1356
+ }),
1357
+ /** The packing slip: where it goes and what is in the box, no prices. */
1358
+ packingSlip: (fulfilmentId, options) => http.request("GET", `/v1/fulfilments/${id(fulfilmentId)}/packing_slip`, options),
1359
+ /** What a label costs for the packed parcel, by service. */
1360
+ rates: (fulfilmentId, options) => http.request("GET", `/v1/fulfilments/${id(fulfilmentId)}/rates`, options),
1361
+ /** Buys a label; `confirm_amount` must equal the quoted price. */
1362
+ buyLabel: (fulfilmentId, body, options) => http.request("POST", `/v1/fulfilments/${id(fulfilmentId)}/label`, {
1363
+ body,
1364
+ ...options,
1365
+ }),
1366
+ voidLabel: (fulfilmentId, options) => http.request("POST", `/v1/fulfilments/${id(fulfilmentId)}/label/void`, {
1367
+ body: {},
1368
+ ...options,
1369
+ }),
1370
+ /** Labels for many packed parcels at once. */
1371
+ buyLabels: (body, options) => http.request("POST", "/v1/fulfilments/labels", { body, ...options }),
1372
+ /** Marks it shipped, with your own tracking number when the label was not ours. */
1373
+ ship: (fulfilmentId, body = {}, options) => http.request("POST", `/v1/fulfilments/${id(fulfilmentId)}/ship`, {
1374
+ body,
1375
+ ...options,
1376
+ }),
1377
+ /** Ready to collect: the shopper is told. */
1378
+ ready: (fulfilmentId, options) => http.request("POST", `/v1/fulfilments/${id(fulfilmentId)}/ready`, {
1379
+ body: {},
1380
+ ...options,
1381
+ }),
1382
+ /** Hands over a collection by the shopper's code. */
1383
+ collect: (body, options) => http.request("POST", "/v1/fulfilments/collect", { body, ...options }),
1384
+ /** A local delivery leaves. */
1385
+ outForDelivery: (fulfilmentId, options) => http.request("POST", `/v1/fulfilments/${id(fulfilmentId)}/out_for_delivery`, {
1386
+ body: {},
1387
+ ...options,
1388
+ }),
1389
+ delivered: (fulfilmentId, options) => http.request("POST", `/v1/fulfilments/${id(fulfilmentId)}/delivered`, {
1390
+ body: {},
1391
+ ...options,
1392
+ }),
1393
+ },
1394
+ /** Returns and exchanges (87-09): requested, approved, on their way back, received, closed. */
1395
+ returns: {
1396
+ ...lister(http, "/v1/returns"),
1397
+ create: (body, options) => http.request("POST", "/v1/returns", { body, ...options }),
1398
+ retrieve: (returnId, options) => http.request("GET", `/v1/returns/${id(returnId)}`, options),
1399
+ /** Finds the order a parcel or a receipt's code belongs to, at the counter. */
1400
+ scan: (body, options) => http.request("POST", "/v1/returns/scan", { body, ...options }),
1401
+ approve: (returnId, body = {}, options) => http.request("POST", `/v1/returns/${id(returnId)}/approve`, { body, ...options }),
1402
+ reject: (returnId, body = {}, options) => http.request("POST", `/v1/returns/${id(returnId)}/reject`, { body, ...options }),
1403
+ /** Received back; the refund or exchange follows the return's terms. */
1404
+ receive: (returnId, body = {}, options) => http.request("POST", `/v1/returns/${id(returnId)}/receive`, { body, ...options }),
1405
+ /** How the parcel can come back: a label, a drop-off, a shop. */
1406
+ waysBack: (returnId, options) => http.request("GET", `/v1/returns/${id(returnId)}/ways_back`, options),
1407
+ chooseWayBack: (returnId, body, options) => http.request("POST", `/v1/returns/${id(returnId)}/way_back`, { body, ...options }),
1408
+ close: (returnId, options) => http.request("POST", `/v1/returns/${id(returnId)}/close`, {
1409
+ body: {},
1410
+ ...options,
1411
+ }),
1412
+ },
1413
+ /** Closing the shipping day (87-10): the manifest for the carrier. */
1414
+ shippingManifests: {
1415
+ ...lister(http, "/v1/shipping_manifests"),
1416
+ retrieve: (manifestId, options) => http.request("GET", `/v1/shipping_manifests/${id(manifestId)}`, options),
1417
+ closeDay: (body = {}, options) => http.request("POST", "/v1/shipping_manifests", { body, ...options }),
1418
+ },
1419
+ /** A carrier collecting from a location (87-10). */
1420
+ carrierPickups: {
1421
+ ...lister(http, "/v1/carrier_pickups"),
1422
+ retrieve: (pickupId, options) => http.request("GET", `/v1/carrier_pickups/${id(pickupId)}`, options),
1423
+ book: (body, options) => http.request("POST", "/v1/carrier_pickups", { body, ...options }),
1424
+ },
1425
+ /** Postage owed for labels bought from the balance, and the credit limit (87-03). */
1426
+ postage: {
1427
+ retrieve: (options) => http.request("GET", "/v1/postage", options),
1428
+ },
1429
+ /** Your own carrier accounts for labels (87-03b); the balance is the fallback if allowed. */
1430
+ carrierAccounts: {
1431
+ /** The connected accounts, with every carrier and the fields each needs. */
1432
+ list: (options) => http.request("GET", "/v1/carrier_accounts", options),
1433
+ connect: (body, options) => http.request("POST", "/v1/carrier_accounts", { body, ...options }),
1434
+ update: (accountId, body, options) => http.request("POST", `/v1/carrier_accounts/${id(accountId)}`, {
1435
+ body,
1436
+ ...options,
1437
+ }),
1438
+ disconnect: (accountId, options) => http.request("DELETE", `/v1/carrier_accounts/${id(accountId)}`, options),
1439
+ },
1440
+ /** What delivery costs where (87-01): profiles of zones, each with its rates. */
1441
+ shippingProfiles: {
1442
+ ...lister(http, "/v1/shipping_profiles"),
1443
+ create: (body = {}, options) => http.request("POST", "/v1/shipping_profiles", { body, ...options }),
1444
+ retrieve: (profileId, options) => http.request("GET", `/v1/shipping_profiles/${id(profileId)}`, options),
1445
+ update: (profileId, body, options) => http.request("POST", `/v1/shipping_profiles/${id(profileId)}`, {
1446
+ body,
1447
+ ...options,
1448
+ }),
1449
+ del: (profileId, options) => http.request("DELETE", `/v1/shipping_profiles/${id(profileId)}`, options),
1450
+ /** Moves these products onto the profile. */
1451
+ assignProducts: (profileId, body, options) => http.request("POST", `/v1/shipping_profiles/${id(profileId)}/products`, {
1452
+ body,
1453
+ ...options,
1454
+ }),
1455
+ /** Products' weights where none was given, as delivery estimates them. */
1456
+ estimatedWeights: (params = {}, options) => http.request("GET", "/v1/shipping_profiles/weights", {
1457
+ query: params,
1458
+ ...options,
1459
+ }),
1460
+ /** The delivery options a shopper would see for an address and basket. */
1461
+ preview: (params, options) => http.request("GET", "/v1/shipping_profiles/preview", {
1462
+ query: params,
1463
+ ...options,
1464
+ }),
1465
+ createZone: (profileId, body, options) => http.request("POST", `/v1/shipping_profiles/${id(profileId)}/zones`, {
1466
+ body,
1467
+ ...options,
1468
+ }),
1469
+ updateZone: (profileId, zoneId, body, options) => http.request("POST", `/v1/shipping_profiles/${id(profileId)}/zones/${id(zoneId)}`, { body, ...options }),
1470
+ deleteZone: (profileId, zoneId, options) => http.request("DELETE", `/v1/shipping_profiles/${id(profileId)}/zones/${id(zoneId)}`, options),
1471
+ createRate: (profileId, zoneId, body, options) => http.request("POST", `/v1/shipping_profiles/${id(profileId)}/zones/${id(zoneId)}/rates`, { body, ...options }),
1472
+ updateRate: (profileId, zoneId, rateId, body, options) => http.request("POST", `/v1/shipping_profiles/${id(profileId)}/zones/${id(zoneId)}/rates/${id(rateId)}`, { body, ...options }),
1473
+ deleteRate: (profileId, zoneId, rateId, options) => http.request("DELETE", `/v1/shipping_profiles/${id(profileId)}/zones/${id(zoneId)}/rates/${id(rateId)}`, options),
1474
+ },
1475
+ /** The boxes you pack in, for label rates (87-02). */
1476
+ shippingPackages: {
1477
+ ...lister(http, "/v1/shipping_packages"),
1478
+ create: (body, options) => http.request("POST", "/v1/shipping_packages", { body, ...options }),
1479
+ update: (packageId, body, options) => http.request("POST", `/v1/shipping_packages/${id(packageId)}`, {
1480
+ body,
1481
+ ...options,
1482
+ }),
1483
+ del: (packageId, options) => http.request("DELETE", `/v1/shipping_packages/${id(packageId)}`, options),
1484
+ },
1485
+ /** The carriers' services a rate or a label can use. */
1486
+ shippingServices: {
1487
+ list: (params = {}, options) => http.request("GET", "/v1/shipping_services", {
1488
+ query: params,
1489
+ ...options,
1490
+ }),
1491
+ },
1492
+ /** The media library (85-04): photos and videos for products and pages. */
1493
+ media: {
1494
+ ...lister(http, "/v1/media"),
1495
+ /** A photo (base64 `data`), or a video from a finished upload; same bytes, same asset. */
1496
+ create: (body, options) => http.request("POST", "/v1/media", { body, ...options }),
1497
+ /** A resumable upload for a video up to 50 MB: send the bytes to `upload_url`. */
1498
+ createUpload: (body, options) => http.request("POST", "/v1/media/uploads", { body, ...options }),
1499
+ retrieve: (assetId, options) => http.request("GET", `/v1/media/${id(assetId)}`, options),
1500
+ update: (assetId, body, options) => http.request("POST", `/v1/media/${id(assetId)}`, { body, ...options }),
1501
+ /** 90-11: the products a video shows, proposed from up to six frames; they wait for you. */
1502
+ proposeVideoTags: (assetId, body, options) => http.request("POST", `/v1/media/${id(assetId)}/video_tags/propose`, {
1503
+ body,
1504
+ ...options,
1505
+ }),
1506
+ /** 90-11: a video's product tags, confirmed: only these show on the store. */
1507
+ setVideoTags: (assetId, body, options) => http.request("POST", `/v1/media/${id(assetId)}/video_tags`, {
1508
+ body,
1509
+ ...options,
1510
+ }),
1511
+ del: (assetId, options) => http.request("DELETE", `/v1/media/${id(assetId)}`, options),
1512
+ },
1513
+ /** The files digital products deliver to buyers (88-12). */
1514
+ digitalAssets: {
1515
+ ...lister(http, "/v1/digital_assets"),
1516
+ create: (body, options) => http.request("POST", "/v1/digital_assets", { body, ...options }),
1517
+ retrieve: (assetId, options) => http.request("GET", `/v1/digital_assets/${id(assetId)}`, options),
1518
+ del: (assetId, options) => http.request("DELETE", `/v1/digital_assets/${id(assetId)}`, options),
1519
+ },
1520
+ /** Product photo edits (86-13): clean, studio, relight or scene, each a new asset. */
1521
+ imageStudio: {
1522
+ retrieve: (params = {}, options) => http.request("GET", "/v1/image_studio", { query: params, ...options }),
1523
+ createEdit: (body, options) => http.request("POST", "/v1/image_studio/edits", { body, ...options }),
1524
+ },
1525
+ /** Store collections (85-05): chosen products, or rules that pick them. */
1526
+ collections: {
1527
+ ...lister(http, "/v1/collections"),
1528
+ create: (body = {}, options) => http.request("POST", "/v1/collections", { body, ...options }),
1529
+ retrieve: (collectionId, options) => http.request("GET", `/v1/collections/${id(collectionId)}`, options),
1530
+ update: (collectionId, body, options) => http.request("POST", `/v1/collections/${id(collectionId)}`, {
1531
+ body,
1532
+ ...options,
1533
+ }),
1534
+ del: (collectionId, options) => http.request("DELETE", `/v1/collections/${id(collectionId)}`, options),
1535
+ /** The collection's products in its order. */
1536
+ products: childLister(http, (collectionId) => `/v1/collections/${id(collectionId)}/products`),
1537
+ },
1538
+ /** Drops (85-12): a limited release at a set time, sold through a fair queue. */
1539
+ drops: {
1540
+ ...lister(http, "/v1/drops"),
1541
+ create: (body, options) => http.request("POST", "/v1/drops", { body, ...options }),
1542
+ retrieve: (dropId, options) => http.request("GET", `/v1/drops/${id(dropId)}`, options),
1543
+ update: (dropId, body, options) => http.request("POST", `/v1/drops/${id(dropId)}`, { body, ...options }),
1544
+ /** The queue as counts: joined, drawing, waiting, checking out, done, and the waitlist. */
1545
+ queue: (dropId, options) => http.request("GET", `/v1/drops/${id(dropId)}/queue`, options),
1546
+ },
1547
+ /**
1548
+ * Products, one catalogue for the till and the store: their web fields (85-03), going
1549
+ * online, variants, the image, licence keys for digital products and return insights.
1550
+ */
1551
+ products: {
1552
+ ...lister(http, "/v1/products"),
1553
+ create: (body, options) => http.request("POST", "/v1/products", { body, ...options }),
1554
+ retrieve: (productId, options) => http.request("GET", `/v1/products/${id(productId)}`, options),
1555
+ /** Web fields too: `web_title`, `web_description`, `web_path`, `seo`, `media`, `channels`. */
1556
+ update: (productId, body, options) => http.request("POST", `/v1/products/${id(productId)}`, { body, ...options }),
1557
+ /** The product with this barcode or SKU. */
1558
+ lookup: (params, options) => http.request("GET", "/v1/products/lookup", { query: params, ...options }),
1559
+ bulkUpdate: (body, options) => http.request("POST", "/v1/products/bulk", { body, ...options }),
1560
+ archive: (productId, options) => http.request("POST", `/v1/products/${id(productId)}/archive`, {
1561
+ body: {},
1562
+ ...options,
1563
+ }),
1564
+ /** Sold out or back, on every channel at once. */
1565
+ setAvailable: (productId, body, options) => http.request("POST", `/v1/products/${id(productId)}/available`, {
1566
+ body,
1567
+ ...options,
1568
+ }),
1569
+ /** What it still needs to go online, each with its fix. */
1570
+ onlineChecklist: (productId, options) => http.request("GET", `/v1/products/${id(productId)}/online_checklist`, options),
1571
+ publishOnline: (productId, options) => http.request("POST", `/v1/products/${id(productId)}/publish_online`, {
1572
+ body: {},
1573
+ ...options,
1574
+ }),
1575
+ unpublishOnline: (productId, options) => http.request("POST", `/v1/products/${id(productId)}/unpublish_online`, {
1576
+ body: {},
1577
+ ...options,
1578
+ }),
1579
+ variants: childLister(http, (productId) => `/v1/products/${id(productId)}/variants`),
1580
+ updateVariant: (productId, variantId, body, options) => http.request("POST", `/v1/products/${id(productId)}/variants/${id(variantId)}`, { body, ...options }),
1581
+ setImage: (productId, body, options) => http.request("POST", `/v1/products/${id(productId)}/image`, { body, ...options }),
1582
+ removeImage: (productId, options) => http.request("DELETE", `/v1/products/${id(productId)}/image`, options),
1583
+ /** A digital product's licence keys: how many are left. */
1584
+ retrieveLicenceKeys: (productId, options) => http.request("GET", `/v1/products/${id(productId)}/licence_keys`, options),
1585
+ addLicenceKeys: (productId, body, options) => http.request("POST", `/v1/products/${id(productId)}/licence_keys`, {
1586
+ body,
1587
+ ...options,
1588
+ }),
1589
+ /** Why it comes back, from its returns (87-09). */
1590
+ returnInsights: (productId, options) => http.request("GET", `/v1/products/${id(productId)}/return_insights`, options),
1591
+ },
1592
+ /**
1593
+ * Orders, one list for the till, the store and every channel (`source`): find them,
1594
+ * change them, take tenders, return lines and send receipts.
1595
+ */
1596
+ orders: {
1597
+ ...lister(http, "/v1/orders"),
1598
+ create: (body, options) => http.request("POST", "/v1/orders", { body, ...options }),
1599
+ retrieve: (orderId, options) => http.request("GET", `/v1/orders/${id(orderId)}`, options),
1600
+ /** The order's lines, totals, fulfilment, payments and contact details. */
1601
+ details: (orderId, options) => http.request("GET", `/v1/orders/${id(orderId)}/details`, options),
1602
+ /** The order found by a receipt's number or code. */
1603
+ findByReceipt: (body, options) => http.request("POST", "/v1/orders/by_receipt", { body, ...options }),
1604
+ events: childLister(http, (orderId) => `/v1/orders/${id(orderId)}/events`),
1605
+ /** A till's offline events, applied in order; replays are ignored. */
1606
+ appendEvents: (orderId, body, options) => http.request("POST", `/v1/orders/${id(orderId)}/events`, { body, ...options }),
1607
+ hold: (orderId, body = {}, options) => http.request("POST", `/v1/orders/${id(orderId)}/hold`, { body, ...options }),
1608
+ resume: (orderId, body = {}, options) => http.request("POST", `/v1/orders/${id(orderId)}/resume`, { body, ...options }),
1609
+ void: (orderId, body = {}, options) => http.request("POST", `/v1/orders/${id(orderId)}/void`, { body, ...options }),
1610
+ setOrderType: (orderId, body, options) => http.request("POST", `/v1/orders/${id(orderId)}/order_type`, { body, ...options }),
1611
+ applyDiscount: (orderId, body, options) => http.request("POST", `/v1/orders/${id(orderId)}/discounts`, { body, ...options }),
1612
+ setTaxExemption: (orderId, body, options) => http.request("POST", `/v1/orders/${id(orderId)}/tax_exemption`, {
1613
+ body,
1614
+ ...options,
1615
+ }),
1616
+ setCustomer: (orderId, body, options) => http.request("POST", `/v1/orders/${id(orderId)}/customer`, { body, ...options }),
1617
+ tenders: childLister(http, (orderId) => `/v1/orders/${id(orderId)}/tenders`),
1618
+ createTender: (orderId, body, options) => http.request("POST", `/v1/orders/${id(orderId)}/tenders`, {
1619
+ body,
1620
+ ...options,
1621
+ }),
1622
+ complete: (orderId, body = {}, options) => http.request("POST", `/v1/orders/${id(orderId)}/complete`, { body, ...options }),
1623
+ /** Lines back from a completed order, refunded to their tenders. */
1624
+ createReturn: (orderId, body, options) => http.request("POST", `/v1/orders/${id(orderId)}/returns`, {
1625
+ body,
1626
+ ...options,
1627
+ }),
1628
+ /** What a return of these lines would refund, writing nothing. */
1629
+ previewReturn: (orderId, body, options) => http.request("POST", `/v1/orders/${id(orderId)}/returns/preview`, {
1630
+ body,
1631
+ ...options,
1632
+ }),
1633
+ /** A store order's delivery address, while it has not shipped. */
1634
+ changeDeliveryAddress: (orderId, body, options) => http.request("POST", `/v1/orders/${id(orderId)}/delivery_address`, {
1635
+ body,
1636
+ ...options,
1637
+ }),
1638
+ /** Release the hold on a store order's sending, so it can be packed and sent (92-11b). */
1639
+ releaseHold: (orderId, options) => http.request("POST", `/v1/orders/${id(orderId)}/release_hold`, {
1640
+ body: {},
1641
+ ...options,
1642
+ }),
1643
+ resendConfirmation: (orderId, options) => http.request("POST", `/v1/orders/${id(orderId)}/resend_confirmation`, { body: {}, ...options }),
1644
+ setEReceipt: (orderId, body, options) => http.request("POST", `/v1/orders/${id(orderId)}/e_receipt`, {
1645
+ body,
1646
+ ...options,
1647
+ }),
1648
+ retrieveReceipt: (orderId, params = {}, options) => http.request("GET", `/v1/orders/${id(orderId)}/receipt`, {
1649
+ query: params,
1650
+ ...options,
1651
+ }),
1652
+ sendReceipt: (orderId, body, options) => http.request("POST", `/v1/orders/${id(orderId)}/receipts`, {
1653
+ body,
1654
+ ...options,
1655
+ }),
1656
+ reprint: (orderId, options) => http.request("POST", `/v1/orders/${id(orderId)}/reprint`, {
1657
+ body: {},
1658
+ ...options,
1659
+ }),
1660
+ },
1661
+ /** The store's policy pages: generated, put in your own words, approved by a person. */
1662
+ sitePolicies: {
1663
+ list: (params = {}, options) => http.request("GET", "/v1/site_policies", { query: params, ...options }),
1664
+ /** Drafts every policy the site needs from what it sells and where; nothing goes live. */
1665
+ generate: (body, options) => http.request("POST", "/v1/site_policies/generate", { body, ...options }),
1666
+ retrieve: (policyId, options) => http.request("GET", `/v1/site_policies/${id(policyId)}`, options),
1667
+ versions: (policyId, options) => http.request("GET", `/v1/site_policies/${id(policyId)}/versions`, options),
1668
+ /** A new version in your own words, to approve. */
1669
+ setOwnWords: (policyId, body, options) => http.request("POST", `/v1/site_policies/${id(policyId)}/own_words`, {
1670
+ body,
1671
+ ...options,
1672
+ }),
1673
+ retrieveVersion: (versionId, options) => http.request("GET", `/v1/site_policy_versions/${id(versionId)}`, options),
1674
+ /** A person approves the version; it goes live on the store. */
1675
+ approveVersion: (versionId, options) => http.request("POST", `/v1/site_policy_versions/${id(versionId)}/approve`, {
1676
+ body: {},
1677
+ ...options,
1678
+ }),
1679
+ },
1680
+ /** Shoppers' requests to see or erase their data, to complete within the legal time. */
1681
+ storePrivacyRequests: {
1682
+ ...lister(http, "/v1/store_privacy_requests"),
1683
+ retrieve: (requestId, options) => http.request("GET", `/v1/store_privacy_requests/${id(requestId)}`, options),
1684
+ complete: (requestId, options) => http.request("POST", `/v1/store_privacy_requests/${id(requestId)}/complete`, { body: {}, ...options }),
1685
+ },
1686
+ /** Your own say over "you might also like": products pinned first, or never shown (91-03). */
1687
+ recommendationRules: {
1688
+ ...lister(http, "/v1/recommendation_rules"),
1689
+ create: (body, options) => http.request("POST", "/v1/recommendation_rules", { body, ...options }),
1690
+ retrieve: (ruleId, options) => http.request("GET", `/v1/recommendation_rules/${id(ruleId)}`, options),
1691
+ update: (ruleId, body, options) => http.request("POST", `/v1/recommendation_rules/${id(ruleId)}`, {
1692
+ body,
1693
+ ...options,
1694
+ }),
1695
+ /** Takes the rule away: recommendations go back to the store's own. */
1696
+ del: (ruleId, options) => http.request("DELETE", `/v1/recommendation_rules/${id(ruleId)}`, options),
1697
+ },
1698
+ /** Subscribe and save: a product on repeat for less, priced at each order (91-08). */
1699
+ subscriptionOffers: {
1700
+ ...lister(http, "/v1/subscription_offers"),
1701
+ create: (body, options) => http.request("POST", "/v1/subscription_offers", { body, ...options }),
1702
+ retrieve: (offerId, options) => http.request("GET", `/v1/subscription_offers/${id(offerId)}`, options),
1703
+ /** Turn it off with `active: false`: offers are never deleted. */
1704
+ update: (offerId, body, options) => http.request("POST", `/v1/subscription_offers/${id(offerId)}`, {
1705
+ body,
1706
+ ...options,
1707
+ }),
1708
+ },
1709
+ /**
1710
+ * Store campaigns (91-09b): a one-off email to a segment of the customers who said yes.
1711
+ * Who it goes to is worked out when it sends; no method takes a list of people.
1712
+ */
1713
+ storeCampaigns: {
1714
+ ...lister(http, "/v1/store_campaigns"),
1715
+ create: (body, options) => http.request("POST", "/v1/store_campaigns", { body, ...options }),
1716
+ retrieve: (campaignId, options) => http.request("GET", `/v1/store_campaigns/${id(campaignId)}`, options),
1717
+ /** A draft only: only what is sent changes. */
1718
+ update: (campaignId, body, options) => http.request("POST", `/v1/store_campaigns/${id(campaignId)}`, {
1719
+ body,
1720
+ ...options,
1721
+ }),
1722
+ /** How many it would reach now, a few first names, and the words. */
1723
+ preview: (campaignId, options) => http.request("GET", `/v1/store_campaigns/${id(campaignId)}/preview`, options),
1724
+ /** To the signed-in person's own email only (a dashboard session, not an API key). */
1725
+ test: (campaignId, options) => http.request("POST", `/v1/store_campaigns/${id(campaignId)}/test`, options),
1726
+ /** `send_at` on the business's clock, `YYYY-MM-DDTHH:MM`, or null for now. */
1727
+ schedule: (campaignId, body = {}, options) => http.request("POST", `/v1/store_campaigns/${id(campaignId)}/schedule`, {
1728
+ body,
1729
+ ...options,
1730
+ }),
1731
+ unschedule: (campaignId, options) => http.request("POST", `/v1/store_campaigns/${id(campaignId)}/unschedule`, options),
1732
+ results: (campaignId, options) => http.request("GET", `/v1/store_campaigns/${id(campaignId)}/results`, options),
1733
+ },
1734
+ /**
1735
+ * Store flows (91-17): the six emails that go on their own to customers who said yes. Turn one
1736
+ * off, change its words, or turn it back on after the guardrail paused it.
1737
+ */
1738
+ storeFlows: {
1739
+ list: (options) => http.request("GET", "/v1/store_flows", options),
1740
+ retrieve: (flowId, options) => http.request("GET", `/v1/store_flows/${id(flowId)}`, options),
1741
+ /** `enabled`, `copy` (one for each message) or `use_default_copy`. */
1742
+ update: (flowId, body, options) => http.request("POST", `/v1/store_flows/${id(flowId)}`, { body, ...options }),
1743
+ /** After reviewing its email: only sends from now count towards the next pause. */
1744
+ resume: (flowId, options) => http.request("POST", `/v1/store_flows/${id(flowId)}/resume`, options),
1745
+ },
1746
+ /** The store's connections to other places it sells: marketplaces, social shops, feeds (M90). */
1747
+ salesChannels: {
1748
+ ...lister(http, "/v1/sales_channels"),
1749
+ retrieve: (channelId, options) => http.request("GET", `/v1/sales_channels/${id(channelId)}`, options),
1750
+ /** Nothing is sent to the channel until it resumes. */
1751
+ pause: (channelId, options) => http.request("POST", `/v1/sales_channels/${id(channelId)}/pause`, {
1752
+ body: {},
1753
+ ...options,
1754
+ }),
1755
+ /** What changed while paused is sent. */
1756
+ resume: (channelId, options) => http.request("POST", `/v1/sales_channels/${id(channelId)}/resume`, {
1757
+ body: {},
1758
+ ...options,
1759
+ }),
1760
+ },
1761
+ /** Each variant's place on a channel, with its state and the channel's issues (M90). */
1762
+ listings: {
1763
+ ...lister(http, "/v1/listings"),
1764
+ retrieve: (listingId, options) => http.request("GET", `/v1/listings/${id(listingId)}`, options),
1765
+ /** Keeps this variant off the channel; it stays on the store. */
1766
+ exclude: (listingId, options) => http.request("POST", `/v1/listings/${id(listingId)}/exclude`, {
1767
+ body: {},
1768
+ ...options,
1769
+ }),
1770
+ /** Lists this variant on the channel again. */
1771
+ include: (listingId, options) => http.request("POST", `/v1/listings/${id(listingId)}/include`, {
1772
+ body: {},
1773
+ ...options,
1774
+ }),
1775
+ },
1776
+ /** The store inbox: shoppers' conversations with the store, by chat and email (91-10). */
1777
+ storeThreads: {
1778
+ ...lister(http, "/v1/store_threads"),
1779
+ /** With its messages. */
1780
+ retrieve: (threadId, options) => http.request("GET", `/v1/store_threads/${id(threadId)}`, options),
1781
+ /** `status` and `assignee` (a team member's `usr_` id, or null). */
1782
+ update: (threadId, body, options) => http.request("POST", `/v1/store_threads/${id(threadId)}`, {
1783
+ body,
1784
+ ...options,
1785
+ }),
1786
+ /** By email from the store's sender when the shopper left an address. */
1787
+ reply: (threadId, body, options) => http.request("POST", `/v1/store_threads/${id(threadId)}/messages`, {
1788
+ body,
1789
+ ...options,
1790
+ }),
1791
+ /** A WhatsApp conversation's approved templates (91-11). */
1792
+ templates: (threadId, options) => http.request("GET", `/v1/store_threads/${id(threadId)}/templates`, options),
1793
+ /** An approved WhatsApp template: the only reply WhatsApp takes after 24 hours (91-11). */
1794
+ sendTemplate: (threadId, body, options) => http.request("POST", `/v1/store_threads/${id(threadId)}/templates`, {
1795
+ body,
1796
+ ...options,
1797
+ }),
1798
+ },
1799
+ /** Your store's own sending domain: store emails go from it once it verifies (91-13). */
1800
+ merchantSendingDomains: {
1801
+ ...lister(http, "/v1/merchant_sending_domains"),
1802
+ /** `mail.` on your store's own domain, or null. */
1803
+ suggestion: (options) => http.request("GET", "/v1/merchant_sending_domains/suggestion", options),
1804
+ /** The suggestion when `domain` is left out. Answers the records to add. */
1805
+ create: (body = {}, options) => http.request("POST", "/v1/merchant_sending_domains", {
1806
+ body,
1807
+ ...options,
1808
+ }),
1809
+ retrieve: (domainId, options) => http.request("GET", `/v1/merchant_sending_domains/${id(domainId)}`, options),
1810
+ /** Checks the records now. */
1811
+ check: (domainId, options) => http.request("POST", `/v1/merchant_sending_domains/${id(domainId)}/check`, options),
1812
+ /** Store emails go from Tuppence in your name again. */
1813
+ remove: (domainId, options) => http.request("DELETE", `/v1/merchant_sending_domains/${id(domainId)}`, options),
1814
+ },
1815
+ };
1816
+ }