@fragmentpay/server 0.3.4 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -23,7 +23,23 @@ declare class FragValidationError extends Error {
23
23
  type Chain = "solana" | "ethereum" | "base" | "arbitrum" | "optimism" | "polygon" | "bnb";
24
24
  type IntentStatus = "created" | "requires_payment" | "quoted" | "awaiting_signature" | "executing" | "partially_filled" | "settled" | "failed" | "expired" | "cancelled" | "refunded";
25
25
  type PayoutStatus = "queued" | "pending" | "paid" | "failed" | "paused";
26
- type RefundStatus = "pending" | "paid" | "failed" | "cancelled";
26
+ /**
27
+ * Raw refund status as stored on the backend. See {@link refundPhase} for a
28
+ * simplified 4-state bucket (`queued | sent | completed | failed`) suitable
29
+ * for rendering merchant/customer-facing status pills.
30
+ */
31
+ type RefundStatus = "pending" | "processing" | "retry_scheduled" | "succeeded" | "failed";
32
+ /** UI-friendly refund bucket. */
33
+ type RefundPhase = "queued" | "sent" | "completed" | "failed";
34
+ /**
35
+ * Map a raw {@link RefundStatus} onto a stable 4-bucket UI phase.
36
+ *
37
+ * - `queued` → `pending` | `retry_scheduled` (waiting to dispatch / retry)
38
+ * - `sent` → `processing` (broadcast on-chain / to payout provider, awaiting confirmation)
39
+ * - `completed` → `succeeded` (funds delivered, `paid_at` set, `tx_hash` present on-chain rails)
40
+ * - `failed` → `failed` (permanent — retry budget exhausted)
41
+ */
42
+ declare function refundPhase(status: RefundStatus | string | null | undefined): RefundPhase;
27
43
  interface Settlement {
28
44
  chain: Chain | string;
29
45
  token: string;
@@ -87,16 +103,59 @@ interface Refund {
87
103
  id: string;
88
104
  payment_intent_id: string;
89
105
  amount_usd: number;
90
- chain: string;
91
- token: string;
106
+ chain: string | null;
107
+ token: string | null;
108
+ /**
109
+ * Payout address. May be `""` when a refund was auto-enqueued (e.g. by the
110
+ * expiry sweeper) and Frag has not yet resolved the payer's originating
111
+ * address. In that case `failure_reason` is `"missing_destination"` and the
112
+ * refund waits until the merchant supplies one, or Frag derives it from a
113
+ * confirmed payer leg.
114
+ */
92
115
  destination: string;
93
116
  reason: string;
117
+ /** Raw backend status. Use {@link refundPhase} to bucket for UI. */
94
118
  status: RefundStatus;
119
+ /** On-chain hash once the refund broadcasts. `null` until then. */
95
120
  tx_hash: string | null;
121
+ /** Number of dispatch attempts already made against this refund. */
122
+ attempts: number;
123
+ /** ISO timestamp of the next scheduled retry (only set in `retry_scheduled`). */
124
+ next_attempt_at: string | null;
125
+ /** ISO timestamp when the refund settled. `null` until `status="succeeded"`. */
126
+ paid_at: string | null;
127
+ /** Optional payer email captured at intent time. */
128
+ customer_email?: string | null;
96
129
  created_at: string;
97
130
  updated_at: string;
98
131
  failure_reason?: string | null;
99
132
  }
133
+ /**
134
+ * Public payer-facing refund status returned by {@link RefundResource.status}.
135
+ * UNAUTHENTICATED — safe to render on a receipt page or email. `destination`
136
+ * is redacted to the last 6 chars via `destination_tail`. `phase` is a
137
+ * stable 4-bucket categorization computed with {@link refundPhase}.
138
+ */
139
+ interface PublicRefundStatus {
140
+ id: string;
141
+ payment_intent_id: string;
142
+ amount_usd: number;
143
+ chain: string | null;
144
+ token: string | null;
145
+ destination_tail: string;
146
+ reason: string;
147
+ status: RefundStatus;
148
+ /** UI bucket: `queued | sent | completed | failed`. */
149
+ phase: RefundPhase;
150
+ tx_hash: string | null;
151
+ failure_reason: string | null;
152
+ attempts: number;
153
+ created_at: string;
154
+ updated_at: string;
155
+ paid_at: string | null;
156
+ /** `true` once no further state change is possible (`completed` or `failed`). */
157
+ terminal: boolean;
158
+ }
100
159
  interface Payout {
101
160
  id: string;
102
161
  payment_intent_id: string | null;
@@ -170,7 +229,23 @@ declare class FragmentPay {
170
229
  readonly webhookEndpoints: WebhookEndpointResource;
171
230
  readonly webhooks: WebhookHelpers;
172
231
  readonly tokens: TokenResource;
232
+ readonly checkout: PublicCheckoutResource;
173
233
  constructor(opts: FragOptions);
234
+ /**
235
+ * Unauthenticated health probe against the API host. Safe to call from
236
+ * uptime monitors and CI. Returns `{ status: "ok" | "degraded" | "down", ... }`.
237
+ */
238
+ health(): Promise<{
239
+ status: "ok" | "degraded" | "down";
240
+ service: string;
241
+ version: string;
242
+ time: string;
243
+ latency_ms: number;
244
+ checks: {
245
+ env: Record<string, boolean>;
246
+ database: "ok" | "degraded" | "down";
247
+ };
248
+ }>;
174
249
  setDebug(on: boolean): void;
175
250
  }
176
251
  declare class PaymentIntentResource {
@@ -202,13 +277,20 @@ declare class RefundResource {
202
277
  create(input: {
203
278
  paymentIntentId: string;
204
279
  amountUsd: number;
205
- destination: string;
280
+ /**
281
+ * Payer address to refund to. Optional — omit to let Frag auto-fill from
282
+ * the intent's confirmed payer leg(s). If no payer address can be derived
283
+ * the refund is created in `pending` with `failure_reason: "missing_destination"`
284
+ * until the merchant provides one from the dashboard.
285
+ */
286
+ destination?: string;
206
287
  reason?: string;
207
288
  idempotencyKey?: string;
208
289
  }): Promise<Refund>;
209
290
  retrieve(id: string): Promise<Refund>;
210
291
  list(params?: {
211
292
  paymentIntentId?: string;
293
+ status?: RefundStatus;
212
294
  limit?: number;
213
295
  }): Promise<{
214
296
  data: Refund[];
@@ -216,24 +298,32 @@ declare class RefundResource {
216
298
  /**
217
299
  * Fetch the payer-facing safe status view for a refund. UNAUTHENTICATED —
218
300
  * safe to expose in a customer-facing page or email. Redacts the destination
219
- * address (only the last 6 chars) and omits merchant PII.
301
+ * address (only the last 6 chars) and omits merchant PII. The returned
302
+ * `phase` field is a stable 4-bucket categorization
303
+ * (`queued | sent | completed | failed`) computed on the client for
304
+ * convenient status pills.
220
305
  */
221
- status(id: string): Promise<{
306
+ status(id: string): Promise<PublicRefundStatus>;
307
+ /** Client-side helper: bucket a raw {@link RefundStatus} to a UI phase. */
308
+ phase(status: RefundStatus | string | null | undefined): RefundPhase;
309
+ }
310
+ /**
311
+ * Unauthenticated public checkout view used by hosted checkout pages and the
312
+ * @fragmentpay/react polling hook. Exposes only non-PII fields — no merchant
313
+ * data, no keys, no idempotency records. Rate-limited to 120 req/min per IP.
314
+ */
315
+ declare class PublicCheckoutResource {
316
+ private req;
317
+ constructor(req: Requester);
318
+ retrieve(id: string): Promise<{
222
319
  id: string;
223
- payment_intent_id: string;
224
- amount_usd: number;
225
- chain: string | null;
226
- token: string | null;
227
- destination_tail: string;
228
- reason: string;
229
- status: RefundStatus;
230
- tx_hash: string | null;
231
- failure_reason: string | null;
232
- attempts: number;
233
- created_at: string;
234
- updated_at: string;
235
- paid_at: string | null;
236
- terminal: boolean;
320
+ amount: string;
321
+ currency: string;
322
+ status: IntentStatus;
323
+ settlement_chain: string | null;
324
+ settlement_token: string | null;
325
+ expires_at: string;
326
+ metadata?: Record<string, unknown>;
237
327
  }>;
238
328
  }
239
329
  declare class PayoutResource {
@@ -306,4 +396,4 @@ declare class Frag extends FragmentPay {
306
396
  });
307
397
  }
308
398
 
309
- export { type Chain, type CreateIntentInput, Frag, FragError, type FragOptions, type FragToken, FragValidationError, FragmentPay, type IntentStatus, type IntentTransaction, type PaymentIntent, type Payout, type PayoutStatus, type Refund, type RefundStatus, type RouteCandidate, type Settlement, type VerifyWebhookInput, type WebhookEndpoint, type WebhookEvent, type WebhookEventType, verifyWebhook };
399
+ export { type Chain, type CreateIntentInput, Frag, FragError, type FragOptions, type FragToken, FragValidationError, FragmentPay, type IntentStatus, type IntentTransaction, type PaymentIntent, type Payout, type PayoutStatus, type PublicRefundStatus, type Refund, type RefundPhase, type RefundStatus, type RouteCandidate, type Settlement, type VerifyWebhookInput, type WebhookEndpoint, type WebhookEvent, type WebhookEventType, refundPhase, verifyWebhook };
package/dist/index.d.ts CHANGED
@@ -23,7 +23,23 @@ declare class FragValidationError extends Error {
23
23
  type Chain = "solana" | "ethereum" | "base" | "arbitrum" | "optimism" | "polygon" | "bnb";
24
24
  type IntentStatus = "created" | "requires_payment" | "quoted" | "awaiting_signature" | "executing" | "partially_filled" | "settled" | "failed" | "expired" | "cancelled" | "refunded";
25
25
  type PayoutStatus = "queued" | "pending" | "paid" | "failed" | "paused";
26
- type RefundStatus = "pending" | "paid" | "failed" | "cancelled";
26
+ /**
27
+ * Raw refund status as stored on the backend. See {@link refundPhase} for a
28
+ * simplified 4-state bucket (`queued | sent | completed | failed`) suitable
29
+ * for rendering merchant/customer-facing status pills.
30
+ */
31
+ type RefundStatus = "pending" | "processing" | "retry_scheduled" | "succeeded" | "failed";
32
+ /** UI-friendly refund bucket. */
33
+ type RefundPhase = "queued" | "sent" | "completed" | "failed";
34
+ /**
35
+ * Map a raw {@link RefundStatus} onto a stable 4-bucket UI phase.
36
+ *
37
+ * - `queued` → `pending` | `retry_scheduled` (waiting to dispatch / retry)
38
+ * - `sent` → `processing` (broadcast on-chain / to payout provider, awaiting confirmation)
39
+ * - `completed` → `succeeded` (funds delivered, `paid_at` set, `tx_hash` present on-chain rails)
40
+ * - `failed` → `failed` (permanent — retry budget exhausted)
41
+ */
42
+ declare function refundPhase(status: RefundStatus | string | null | undefined): RefundPhase;
27
43
  interface Settlement {
28
44
  chain: Chain | string;
29
45
  token: string;
@@ -87,16 +103,59 @@ interface Refund {
87
103
  id: string;
88
104
  payment_intent_id: string;
89
105
  amount_usd: number;
90
- chain: string;
91
- token: string;
106
+ chain: string | null;
107
+ token: string | null;
108
+ /**
109
+ * Payout address. May be `""` when a refund was auto-enqueued (e.g. by the
110
+ * expiry sweeper) and Frag has not yet resolved the payer's originating
111
+ * address. In that case `failure_reason` is `"missing_destination"` and the
112
+ * refund waits until the merchant supplies one, or Frag derives it from a
113
+ * confirmed payer leg.
114
+ */
92
115
  destination: string;
93
116
  reason: string;
117
+ /** Raw backend status. Use {@link refundPhase} to bucket for UI. */
94
118
  status: RefundStatus;
119
+ /** On-chain hash once the refund broadcasts. `null` until then. */
95
120
  tx_hash: string | null;
121
+ /** Number of dispatch attempts already made against this refund. */
122
+ attempts: number;
123
+ /** ISO timestamp of the next scheduled retry (only set in `retry_scheduled`). */
124
+ next_attempt_at: string | null;
125
+ /** ISO timestamp when the refund settled. `null` until `status="succeeded"`. */
126
+ paid_at: string | null;
127
+ /** Optional payer email captured at intent time. */
128
+ customer_email?: string | null;
96
129
  created_at: string;
97
130
  updated_at: string;
98
131
  failure_reason?: string | null;
99
132
  }
133
+ /**
134
+ * Public payer-facing refund status returned by {@link RefundResource.status}.
135
+ * UNAUTHENTICATED — safe to render on a receipt page or email. `destination`
136
+ * is redacted to the last 6 chars via `destination_tail`. `phase` is a
137
+ * stable 4-bucket categorization computed with {@link refundPhase}.
138
+ */
139
+ interface PublicRefundStatus {
140
+ id: string;
141
+ payment_intent_id: string;
142
+ amount_usd: number;
143
+ chain: string | null;
144
+ token: string | null;
145
+ destination_tail: string;
146
+ reason: string;
147
+ status: RefundStatus;
148
+ /** UI bucket: `queued | sent | completed | failed`. */
149
+ phase: RefundPhase;
150
+ tx_hash: string | null;
151
+ failure_reason: string | null;
152
+ attempts: number;
153
+ created_at: string;
154
+ updated_at: string;
155
+ paid_at: string | null;
156
+ /** `true` once no further state change is possible (`completed` or `failed`). */
157
+ terminal: boolean;
158
+ }
100
159
  interface Payout {
101
160
  id: string;
102
161
  payment_intent_id: string | null;
@@ -170,7 +229,23 @@ declare class FragmentPay {
170
229
  readonly webhookEndpoints: WebhookEndpointResource;
171
230
  readonly webhooks: WebhookHelpers;
172
231
  readonly tokens: TokenResource;
232
+ readonly checkout: PublicCheckoutResource;
173
233
  constructor(opts: FragOptions);
234
+ /**
235
+ * Unauthenticated health probe against the API host. Safe to call from
236
+ * uptime monitors and CI. Returns `{ status: "ok" | "degraded" | "down", ... }`.
237
+ */
238
+ health(): Promise<{
239
+ status: "ok" | "degraded" | "down";
240
+ service: string;
241
+ version: string;
242
+ time: string;
243
+ latency_ms: number;
244
+ checks: {
245
+ env: Record<string, boolean>;
246
+ database: "ok" | "degraded" | "down";
247
+ };
248
+ }>;
174
249
  setDebug(on: boolean): void;
175
250
  }
176
251
  declare class PaymentIntentResource {
@@ -202,13 +277,20 @@ declare class RefundResource {
202
277
  create(input: {
203
278
  paymentIntentId: string;
204
279
  amountUsd: number;
205
- destination: string;
280
+ /**
281
+ * Payer address to refund to. Optional — omit to let Frag auto-fill from
282
+ * the intent's confirmed payer leg(s). If no payer address can be derived
283
+ * the refund is created in `pending` with `failure_reason: "missing_destination"`
284
+ * until the merchant provides one from the dashboard.
285
+ */
286
+ destination?: string;
206
287
  reason?: string;
207
288
  idempotencyKey?: string;
208
289
  }): Promise<Refund>;
209
290
  retrieve(id: string): Promise<Refund>;
210
291
  list(params?: {
211
292
  paymentIntentId?: string;
293
+ status?: RefundStatus;
212
294
  limit?: number;
213
295
  }): Promise<{
214
296
  data: Refund[];
@@ -216,24 +298,32 @@ declare class RefundResource {
216
298
  /**
217
299
  * Fetch the payer-facing safe status view for a refund. UNAUTHENTICATED —
218
300
  * safe to expose in a customer-facing page or email. Redacts the destination
219
- * address (only the last 6 chars) and omits merchant PII.
301
+ * address (only the last 6 chars) and omits merchant PII. The returned
302
+ * `phase` field is a stable 4-bucket categorization
303
+ * (`queued | sent | completed | failed`) computed on the client for
304
+ * convenient status pills.
220
305
  */
221
- status(id: string): Promise<{
306
+ status(id: string): Promise<PublicRefundStatus>;
307
+ /** Client-side helper: bucket a raw {@link RefundStatus} to a UI phase. */
308
+ phase(status: RefundStatus | string | null | undefined): RefundPhase;
309
+ }
310
+ /**
311
+ * Unauthenticated public checkout view used by hosted checkout pages and the
312
+ * @fragmentpay/react polling hook. Exposes only non-PII fields — no merchant
313
+ * data, no keys, no idempotency records. Rate-limited to 120 req/min per IP.
314
+ */
315
+ declare class PublicCheckoutResource {
316
+ private req;
317
+ constructor(req: Requester);
318
+ retrieve(id: string): Promise<{
222
319
  id: string;
223
- payment_intent_id: string;
224
- amount_usd: number;
225
- chain: string | null;
226
- token: string | null;
227
- destination_tail: string;
228
- reason: string;
229
- status: RefundStatus;
230
- tx_hash: string | null;
231
- failure_reason: string | null;
232
- attempts: number;
233
- created_at: string;
234
- updated_at: string;
235
- paid_at: string | null;
236
- terminal: boolean;
320
+ amount: string;
321
+ currency: string;
322
+ status: IntentStatus;
323
+ settlement_chain: string | null;
324
+ settlement_token: string | null;
325
+ expires_at: string;
326
+ metadata?: Record<string, unknown>;
237
327
  }>;
238
328
  }
239
329
  declare class PayoutResource {
@@ -306,4 +396,4 @@ declare class Frag extends FragmentPay {
306
396
  });
307
397
  }
308
398
 
309
- export { type Chain, type CreateIntentInput, Frag, FragError, type FragOptions, type FragToken, FragValidationError, FragmentPay, type IntentStatus, type IntentTransaction, type PaymentIntent, type Payout, type PayoutStatus, type Refund, type RefundStatus, type RouteCandidate, type Settlement, type VerifyWebhookInput, type WebhookEndpoint, type WebhookEvent, type WebhookEventType, verifyWebhook };
399
+ export { type Chain, type CreateIntentInput, Frag, FragError, type FragOptions, type FragToken, FragValidationError, FragmentPay, type IntentStatus, type IntentTransaction, type PaymentIntent, type Payout, type PayoutStatus, type PublicRefundStatus, type Refund, type RefundPhase, type RefundStatus, type RouteCandidate, type Settlement, type VerifyWebhookInput, type WebhookEndpoint, type WebhookEvent, type WebhookEventType, refundPhase, verifyWebhook };
package/dist/index.js CHANGED
@@ -24,6 +24,7 @@ __export(index_exports, {
24
24
  FragError: () => FragError,
25
25
  FragValidationError: () => FragValidationError,
26
26
  FragmentPay: () => FragmentPay,
27
+ refundPhase: () => refundPhase,
27
28
  verifyWebhook: () => verifyWebhook
28
29
  });
29
30
  module.exports = __toCommonJS(index_exports);
@@ -118,6 +119,13 @@ var INTENT_STATUSES = [
118
119
  "refunded"
119
120
  ];
120
121
  var PAYOUT_STATUSES = ["queued", "pending", "paid", "failed", "paused"];
122
+ var REFUND_STATUSES = [
123
+ "pending",
124
+ "processing",
125
+ "retry_scheduled",
126
+ "succeeded",
127
+ "failed"
128
+ ];
121
129
  var WEBHOOK_EVENTS = [
122
130
  "payment_intent.created",
123
131
  "payment_intent.quoted",
@@ -139,6 +147,18 @@ var WEBHOOK_EVENTS = [
139
147
  ];
140
148
 
141
149
  // src/index.ts
150
+ function refundPhase(status) {
151
+ switch (status) {
152
+ case "succeeded":
153
+ return "completed";
154
+ case "processing":
155
+ return "sent";
156
+ case "failed":
157
+ return "failed";
158
+ default:
159
+ return "queued";
160
+ }
161
+ }
142
162
  var FragError = class extends Error {
143
163
  status;
144
164
  code;
@@ -160,6 +180,7 @@ var FragmentPay = class {
160
180
  webhookEndpoints;
161
181
  webhooks;
162
182
  tokens;
183
+ checkout;
163
184
  #opts;
164
185
  constructor(opts) {
165
186
  if (!opts || typeof opts !== "object") {
@@ -178,7 +199,7 @@ var FragmentPay = class {
178
199
  v.num("options.retries", opts.retries, { min: 0, max: 10, int: true });
179
200
  this.#opts = {
180
201
  apiKey: opts.apiKey,
181
- baseUrl: (opts.baseUrl ?? "https://api.frag.dev").replace(/\/$/, ""),
202
+ baseUrl: (opts.baseUrl ?? "https://frag.cash").replace(/\/$/, ""),
182
203
  fetch: opts.fetch ?? globalThis.fetch.bind(globalThis),
183
204
  timeout: opts.timeout ?? 3e4,
184
205
  retries: opts.retries ?? 2,
@@ -190,8 +211,16 @@ var FragmentPay = class {
190
211
  this.payouts = new PayoutResource(req);
191
212
  this.webhookEndpoints = new WebhookEndpointResource(req);
192
213
  this.tokens = new TokenResource(req);
214
+ this.checkout = new PublicCheckoutResource(req);
193
215
  this.webhooks = new WebhookHelpers();
194
216
  }
217
+ /**
218
+ * Unauthenticated health probe against the API host. Safe to call from
219
+ * uptime monitors and CI. Returns `{ status: "ok" | "degraded" | "down", ... }`.
220
+ */
221
+ health() {
222
+ return this.#req(`/api/public/health`, { skipAuth: true });
223
+ }
195
224
  setDebug(on) {
196
225
  this.#opts.debug = on;
197
226
  }
@@ -355,7 +384,7 @@ var RefundResource = class {
355
384
  throw new FragValidationError("refunds.create", "expected object");
356
385
  v.id("refunds.create.paymentIntentId", input.paymentIntentId);
357
386
  v.num("refunds.create.amountUsd", input.amountUsd, { min: 0.01, max: 1e7 });
358
- v.str("refunds.create.destination", input.destination, { min: 26, max: 128 });
387
+ v.optStr("refunds.create.destination", input.destination, { min: 26, max: 128 });
359
388
  v.optStr("refunds.create.reason", input.reason, { max: 500 });
360
389
  v.optStr("refunds.create.idempotencyKey", input.idempotencyKey, { min: 8, max: 128 });
361
390
  return this.req("/api/public/v1/refunds", {
@@ -376,21 +405,45 @@ var RefundResource = class {
376
405
  list(params = {}) {
377
406
  if (params.paymentIntentId !== void 0)
378
407
  v.id("refunds.list.paymentIntentId", params.paymentIntentId);
408
+ v.optEnum("refunds.list.status", params.status, REFUND_STATUSES);
379
409
  v.optNum("refunds.list.limit", params.limit, { min: 1, max: 100, int: true });
380
410
  return this.req(`/api/public/v1/refunds`, {
381
- query: { payment_intent_id: params.paymentIntentId, limit: params.limit }
411
+ query: {
412
+ payment_intent_id: params.paymentIntentId,
413
+ status: params.status,
414
+ limit: params.limit
415
+ }
382
416
  });
383
417
  }
384
418
  /**
385
419
  * Fetch the payer-facing safe status view for a refund. UNAUTHENTICATED —
386
420
  * safe to expose in a customer-facing page or email. Redacts the destination
387
- * address (only the last 6 chars) and omits merchant PII.
421
+ * address (only the last 6 chars) and omits merchant PII. The returned
422
+ * `phase` field is a stable 4-bucket categorization
423
+ * (`queued | sent | completed | failed`) computed on the client for
424
+ * convenient status pills.
388
425
  */
389
- status(id) {
426
+ async status(id) {
390
427
  v.id("refunds.status.id", id);
391
- return this.req(`/api/public/refunds/${encodeURIComponent(id)}/status`, {
392
- skipAuth: true
393
- });
428
+ const raw = await this.req(
429
+ `/api/public/refunds/${encodeURIComponent(id)}/status`,
430
+ { skipAuth: true }
431
+ );
432
+ return { ...raw, phase: refundPhase(raw.status) };
433
+ }
434
+ /** Client-side helper: bucket a raw {@link RefundStatus} to a UI phase. */
435
+ phase(status) {
436
+ return refundPhase(status);
437
+ }
438
+ };
439
+ var PublicCheckoutResource = class {
440
+ constructor(req) {
441
+ this.req = req;
442
+ }
443
+ req;
444
+ retrieve(id) {
445
+ v.id("checkout.retrieve.id", id);
446
+ return this.req(`/api/public/v1/checkout/${encodeURIComponent(id)}`, { skipAuth: true });
394
447
  }
395
448
  };
396
449
  var PayoutResource = class {
@@ -559,5 +612,6 @@ function timingSafeEqualHex(a, b) {
559
612
  FragError,
560
613
  FragValidationError,
561
614
  FragmentPay,
615
+ refundPhase,
562
616
  verifyWebhook
563
617
  });
package/dist/index.mjs CHANGED
@@ -88,6 +88,13 @@ var INTENT_STATUSES = [
88
88
  "refunded"
89
89
  ];
90
90
  var PAYOUT_STATUSES = ["queued", "pending", "paid", "failed", "paused"];
91
+ var REFUND_STATUSES = [
92
+ "pending",
93
+ "processing",
94
+ "retry_scheduled",
95
+ "succeeded",
96
+ "failed"
97
+ ];
91
98
  var WEBHOOK_EVENTS = [
92
99
  "payment_intent.created",
93
100
  "payment_intent.quoted",
@@ -109,6 +116,18 @@ var WEBHOOK_EVENTS = [
109
116
  ];
110
117
 
111
118
  // src/index.ts
119
+ function refundPhase(status) {
120
+ switch (status) {
121
+ case "succeeded":
122
+ return "completed";
123
+ case "processing":
124
+ return "sent";
125
+ case "failed":
126
+ return "failed";
127
+ default:
128
+ return "queued";
129
+ }
130
+ }
112
131
  var FragError = class extends Error {
113
132
  status;
114
133
  code;
@@ -130,6 +149,7 @@ var FragmentPay = class {
130
149
  webhookEndpoints;
131
150
  webhooks;
132
151
  tokens;
152
+ checkout;
133
153
  #opts;
134
154
  constructor(opts) {
135
155
  if (!opts || typeof opts !== "object") {
@@ -148,7 +168,7 @@ var FragmentPay = class {
148
168
  v.num("options.retries", opts.retries, { min: 0, max: 10, int: true });
149
169
  this.#opts = {
150
170
  apiKey: opts.apiKey,
151
- baseUrl: (opts.baseUrl ?? "https://api.frag.dev").replace(/\/$/, ""),
171
+ baseUrl: (opts.baseUrl ?? "https://frag.cash").replace(/\/$/, ""),
152
172
  fetch: opts.fetch ?? globalThis.fetch.bind(globalThis),
153
173
  timeout: opts.timeout ?? 3e4,
154
174
  retries: opts.retries ?? 2,
@@ -160,8 +180,16 @@ var FragmentPay = class {
160
180
  this.payouts = new PayoutResource(req);
161
181
  this.webhookEndpoints = new WebhookEndpointResource(req);
162
182
  this.tokens = new TokenResource(req);
183
+ this.checkout = new PublicCheckoutResource(req);
163
184
  this.webhooks = new WebhookHelpers();
164
185
  }
186
+ /**
187
+ * Unauthenticated health probe against the API host. Safe to call from
188
+ * uptime monitors and CI. Returns `{ status: "ok" | "degraded" | "down", ... }`.
189
+ */
190
+ health() {
191
+ return this.#req(`/api/public/health`, { skipAuth: true });
192
+ }
165
193
  setDebug(on) {
166
194
  this.#opts.debug = on;
167
195
  }
@@ -325,7 +353,7 @@ var RefundResource = class {
325
353
  throw new FragValidationError("refunds.create", "expected object");
326
354
  v.id("refunds.create.paymentIntentId", input.paymentIntentId);
327
355
  v.num("refunds.create.amountUsd", input.amountUsd, { min: 0.01, max: 1e7 });
328
- v.str("refunds.create.destination", input.destination, { min: 26, max: 128 });
356
+ v.optStr("refunds.create.destination", input.destination, { min: 26, max: 128 });
329
357
  v.optStr("refunds.create.reason", input.reason, { max: 500 });
330
358
  v.optStr("refunds.create.idempotencyKey", input.idempotencyKey, { min: 8, max: 128 });
331
359
  return this.req("/api/public/v1/refunds", {
@@ -346,21 +374,45 @@ var RefundResource = class {
346
374
  list(params = {}) {
347
375
  if (params.paymentIntentId !== void 0)
348
376
  v.id("refunds.list.paymentIntentId", params.paymentIntentId);
377
+ v.optEnum("refunds.list.status", params.status, REFUND_STATUSES);
349
378
  v.optNum("refunds.list.limit", params.limit, { min: 1, max: 100, int: true });
350
379
  return this.req(`/api/public/v1/refunds`, {
351
- query: { payment_intent_id: params.paymentIntentId, limit: params.limit }
380
+ query: {
381
+ payment_intent_id: params.paymentIntentId,
382
+ status: params.status,
383
+ limit: params.limit
384
+ }
352
385
  });
353
386
  }
354
387
  /**
355
388
  * Fetch the payer-facing safe status view for a refund. UNAUTHENTICATED —
356
389
  * safe to expose in a customer-facing page or email. Redacts the destination
357
- * address (only the last 6 chars) and omits merchant PII.
390
+ * address (only the last 6 chars) and omits merchant PII. The returned
391
+ * `phase` field is a stable 4-bucket categorization
392
+ * (`queued | sent | completed | failed`) computed on the client for
393
+ * convenient status pills.
358
394
  */
359
- status(id) {
395
+ async status(id) {
360
396
  v.id("refunds.status.id", id);
361
- return this.req(`/api/public/refunds/${encodeURIComponent(id)}/status`, {
362
- skipAuth: true
363
- });
397
+ const raw = await this.req(
398
+ `/api/public/refunds/${encodeURIComponent(id)}/status`,
399
+ { skipAuth: true }
400
+ );
401
+ return { ...raw, phase: refundPhase(raw.status) };
402
+ }
403
+ /** Client-side helper: bucket a raw {@link RefundStatus} to a UI phase. */
404
+ phase(status) {
405
+ return refundPhase(status);
406
+ }
407
+ };
408
+ var PublicCheckoutResource = class {
409
+ constructor(req) {
410
+ this.req = req;
411
+ }
412
+ req;
413
+ retrieve(id) {
414
+ v.id("checkout.retrieve.id", id);
415
+ return this.req(`/api/public/v1/checkout/${encodeURIComponent(id)}`, { skipAuth: true });
364
416
  }
365
417
  };
366
418
  var PayoutResource = class {
@@ -528,5 +580,6 @@ export {
528
580
  FragError,
529
581
  FragValidationError,
530
582
  FragmentPay,
583
+ refundPhase,
531
584
  verifyWebhook
532
585
  };