@spokpay/chat 0.1.0 → 0.2.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/client.d.ts +99 -18
- package/dist/client.js +99 -18
- package/dist/index.d.ts +1 -1
- package/dist/types.d.ts +157 -5
- package/dist/types.js +16 -1
- package/package.json +1 -1
package/dist/client.d.ts
CHANGED
|
@@ -30,22 +30,41 @@ import type { SpokPayChatOptions, CreateConversationOptions, Conversation, GetCo
|
|
|
30
30
|
* });
|
|
31
31
|
* ```
|
|
32
32
|
*
|
|
33
|
-
* @example
|
|
33
|
+
* @example Convex integration — reactive chat with webhooks
|
|
34
34
|
* ```ts
|
|
35
|
-
* //
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
35
|
+
* // convex/http.ts — Receive SpokPay chat webhooks
|
|
36
|
+
* import { SpokPayChat, type ChatWebhookPayload } from "@spokpay/chat";
|
|
37
|
+
*
|
|
38
|
+
* http.route({
|
|
39
|
+
* path: "/webhooks/spokpay-chat",
|
|
40
|
+
* method: "POST",
|
|
41
|
+
* handler: httpAction(async (ctx, req) => {
|
|
42
|
+
* const body = await req.text();
|
|
43
|
+
* const signature = req.headers.get("x-spokpay-signature")!;
|
|
44
|
+
*
|
|
45
|
+
* const isValid = await SpokPayChat.verifyWebhookSignature({
|
|
46
|
+
* payload: body,
|
|
47
|
+
* signature,
|
|
48
|
+
* secret: process.env.SPOKPAY_WEBHOOK_SECRET!,
|
|
49
|
+
* });
|
|
50
|
+
* if (!isValid) return new Response("Invalid signature", { status: 401 });
|
|
51
|
+
*
|
|
52
|
+
* const event: ChatWebhookPayload = JSON.parse(body);
|
|
53
|
+
* if (event.type === "message.created") {
|
|
54
|
+
* await ctx.runMutation(internal.chat.handleStaffReply, {
|
|
55
|
+
* conversationId: event.data.conversationId,
|
|
56
|
+
* content: event.data.content,
|
|
57
|
+
* authorName: event.data.authorDisplayName,
|
|
58
|
+
* });
|
|
59
|
+
* }
|
|
60
|
+
* return new Response("OK");
|
|
61
|
+
* }),
|
|
41
62
|
* });
|
|
42
63
|
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
* displayMessage(event.data.content, event.data.authorDisplayName);
|
|
48
|
-
* }
|
|
64
|
+
* // React component — auto-updates when webhook triggers the mutation
|
|
65
|
+
* function ChatPage({ conversationId }: { conversationId: string }) {
|
|
66
|
+
* const messages = useQuery(api.chat.listMessages, { conversationId });
|
|
67
|
+
* // messages reactively updates when staff replies via the webhook
|
|
49
68
|
* }
|
|
50
69
|
* ```
|
|
51
70
|
*/
|
|
@@ -54,8 +73,45 @@ export declare class SpokPayChat {
|
|
|
54
73
|
private readonly baseUrl;
|
|
55
74
|
/**
|
|
56
75
|
* Client for managing conversations and messages.
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* ```ts
|
|
79
|
+
* // Create a conversation
|
|
80
|
+
* const conv = await chat.conversations.create({
|
|
81
|
+
* type: "order_support",
|
|
82
|
+
* customer: { externalId: "cust_123", name: "João" },
|
|
83
|
+
* subject: "Help with my order",
|
|
84
|
+
* });
|
|
85
|
+
*
|
|
86
|
+
* // Send a message
|
|
87
|
+
* await chat.conversations.sendMessage({
|
|
88
|
+
* conversationId: conv.id,
|
|
89
|
+
* content: "When will my order arrive?",
|
|
90
|
+
* });
|
|
91
|
+
*
|
|
92
|
+
* // List messages
|
|
93
|
+
* const { messages } = await chat.conversations.listMessages({
|
|
94
|
+
* conversationId: conv.id,
|
|
95
|
+
* });
|
|
96
|
+
*
|
|
97
|
+
* // Close when resolved
|
|
98
|
+
* await chat.conversations.close({ id: conv.id });
|
|
99
|
+
* ```
|
|
57
100
|
*/
|
|
58
101
|
readonly conversations: ConversationsClient;
|
|
102
|
+
/**
|
|
103
|
+
* Creates a new SpokPay Chat client.
|
|
104
|
+
*
|
|
105
|
+
* @param options - Client configuration (API key and base URL).
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* ```ts
|
|
109
|
+
* const chat = new SpokPayChat({
|
|
110
|
+
* apiKey: process.env.SPOKPAY_API_KEY!,
|
|
111
|
+
* baseUrl: process.env.SPOKPAY_BASE_URL!,
|
|
112
|
+
* });
|
|
113
|
+
* ```
|
|
114
|
+
*/
|
|
59
115
|
constructor(options: SpokPayChatOptions);
|
|
60
116
|
/**
|
|
61
117
|
* Verify a webhook signature to ensure the request came from SpokPay.
|
|
@@ -64,15 +120,40 @@ export declare class SpokPayChat {
|
|
|
64
120
|
* Works in all JavaScript runtimes: Node.js 18+, Deno, Cloudflare Workers,
|
|
65
121
|
* Vercel Edge, and Convex.
|
|
66
122
|
*
|
|
123
|
+
* **Important:** Always verify signatures before processing webhook payloads.
|
|
124
|
+
* Use the raw request body string — do not parse it before verification.
|
|
125
|
+
*
|
|
67
126
|
* @param options - The raw payload, signature header, and your webhook secret.
|
|
68
127
|
* @returns `true` if the signature is valid, `false` otherwise.
|
|
69
128
|
*
|
|
70
|
-
* @example
|
|
129
|
+
* @example Node.js / Express
|
|
130
|
+
* ```ts
|
|
131
|
+
* app.post("/webhooks/spokpay-chat", express.raw({ type: "*\/*" }), async (req, res) => {
|
|
132
|
+
* const isValid = await SpokPayChat.verifyWebhookSignature({
|
|
133
|
+
* payload: req.body.toString(),
|
|
134
|
+
* signature: req.headers["x-spokpay-signature"] as string,
|
|
135
|
+
* secret: process.env.SPOKPAY_WEBHOOK_SECRET!,
|
|
136
|
+
* });
|
|
137
|
+
*
|
|
138
|
+
* if (!isValid) return res.status(401).send("Invalid signature");
|
|
139
|
+
*
|
|
140
|
+
* const event = JSON.parse(req.body.toString());
|
|
141
|
+
* // Handle event...
|
|
142
|
+
* res.sendStatus(200);
|
|
143
|
+
* });
|
|
144
|
+
* ```
|
|
145
|
+
*
|
|
146
|
+
* @example Convex httpAction
|
|
71
147
|
* ```ts
|
|
72
|
-
* const
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
148
|
+
* const handler = httpAction(async (ctx, req) => {
|
|
149
|
+
* const body = await req.text();
|
|
150
|
+
* const isValid = await SpokPayChat.verifyWebhookSignature({
|
|
151
|
+
* payload: body,
|
|
152
|
+
* signature: req.headers.get("x-spokpay-signature")!,
|
|
153
|
+
* secret: process.env.SPOKPAY_WEBHOOK_SECRET!,
|
|
154
|
+
* });
|
|
155
|
+
* if (!isValid) return new Response("Invalid", { status: 401 });
|
|
156
|
+
* // Process the webhook...
|
|
76
157
|
* });
|
|
77
158
|
* ```
|
|
78
159
|
*/
|
package/dist/client.js
CHANGED
|
@@ -31,22 +31,41 @@ const DEFAULT_BASE_URL = "https://your-convex-deployment.convex.site";
|
|
|
31
31
|
* });
|
|
32
32
|
* ```
|
|
33
33
|
*
|
|
34
|
-
* @example
|
|
34
|
+
* @example Convex integration — reactive chat with webhooks
|
|
35
35
|
* ```ts
|
|
36
|
-
* //
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
36
|
+
* // convex/http.ts — Receive SpokPay chat webhooks
|
|
37
|
+
* import { SpokPayChat, type ChatWebhookPayload } from "@spokpay/chat";
|
|
38
|
+
*
|
|
39
|
+
* http.route({
|
|
40
|
+
* path: "/webhooks/spokpay-chat",
|
|
41
|
+
* method: "POST",
|
|
42
|
+
* handler: httpAction(async (ctx, req) => {
|
|
43
|
+
* const body = await req.text();
|
|
44
|
+
* const signature = req.headers.get("x-spokpay-signature")!;
|
|
45
|
+
*
|
|
46
|
+
* const isValid = await SpokPayChat.verifyWebhookSignature({
|
|
47
|
+
* payload: body,
|
|
48
|
+
* signature,
|
|
49
|
+
* secret: process.env.SPOKPAY_WEBHOOK_SECRET!,
|
|
50
|
+
* });
|
|
51
|
+
* if (!isValid) return new Response("Invalid signature", { status: 401 });
|
|
52
|
+
*
|
|
53
|
+
* const event: ChatWebhookPayload = JSON.parse(body);
|
|
54
|
+
* if (event.type === "message.created") {
|
|
55
|
+
* await ctx.runMutation(internal.chat.handleStaffReply, {
|
|
56
|
+
* conversationId: event.data.conversationId,
|
|
57
|
+
* content: event.data.content,
|
|
58
|
+
* authorName: event.data.authorDisplayName,
|
|
59
|
+
* });
|
|
60
|
+
* }
|
|
61
|
+
* return new Response("OK");
|
|
62
|
+
* }),
|
|
42
63
|
* });
|
|
43
64
|
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
* displayMessage(event.data.content, event.data.authorDisplayName);
|
|
49
|
-
* }
|
|
65
|
+
* // React component — auto-updates when webhook triggers the mutation
|
|
66
|
+
* function ChatPage({ conversationId }: { conversationId: string }) {
|
|
67
|
+
* const messages = useQuery(api.chat.listMessages, { conversationId });
|
|
68
|
+
* // messages reactively updates when staff replies via the webhook
|
|
50
69
|
* }
|
|
51
70
|
* ```
|
|
52
71
|
*/
|
|
@@ -55,8 +74,45 @@ export class SpokPayChat {
|
|
|
55
74
|
baseUrl;
|
|
56
75
|
/**
|
|
57
76
|
* Client for managing conversations and messages.
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```ts
|
|
80
|
+
* // Create a conversation
|
|
81
|
+
* const conv = await chat.conversations.create({
|
|
82
|
+
* type: "order_support",
|
|
83
|
+
* customer: { externalId: "cust_123", name: "João" },
|
|
84
|
+
* subject: "Help with my order",
|
|
85
|
+
* });
|
|
86
|
+
*
|
|
87
|
+
* // Send a message
|
|
88
|
+
* await chat.conversations.sendMessage({
|
|
89
|
+
* conversationId: conv.id,
|
|
90
|
+
* content: "When will my order arrive?",
|
|
91
|
+
* });
|
|
92
|
+
*
|
|
93
|
+
* // List messages
|
|
94
|
+
* const { messages } = await chat.conversations.listMessages({
|
|
95
|
+
* conversationId: conv.id,
|
|
96
|
+
* });
|
|
97
|
+
*
|
|
98
|
+
* // Close when resolved
|
|
99
|
+
* await chat.conversations.close({ id: conv.id });
|
|
100
|
+
* ```
|
|
58
101
|
*/
|
|
59
102
|
conversations;
|
|
103
|
+
/**
|
|
104
|
+
* Creates a new SpokPay Chat client.
|
|
105
|
+
*
|
|
106
|
+
* @param options - Client configuration (API key and base URL).
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```ts
|
|
110
|
+
* const chat = new SpokPayChat({
|
|
111
|
+
* apiKey: process.env.SPOKPAY_API_KEY!,
|
|
112
|
+
* baseUrl: process.env.SPOKPAY_BASE_URL!,
|
|
113
|
+
* });
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
60
116
|
constructor(options) {
|
|
61
117
|
this.apiKey = options.apiKey;
|
|
62
118
|
this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, "");
|
|
@@ -69,15 +125,40 @@ export class SpokPayChat {
|
|
|
69
125
|
* Works in all JavaScript runtimes: Node.js 18+, Deno, Cloudflare Workers,
|
|
70
126
|
* Vercel Edge, and Convex.
|
|
71
127
|
*
|
|
128
|
+
* **Important:** Always verify signatures before processing webhook payloads.
|
|
129
|
+
* Use the raw request body string — do not parse it before verification.
|
|
130
|
+
*
|
|
72
131
|
* @param options - The raw payload, signature header, and your webhook secret.
|
|
73
132
|
* @returns `true` if the signature is valid, `false` otherwise.
|
|
74
133
|
*
|
|
75
|
-
* @example
|
|
134
|
+
* @example Node.js / Express
|
|
135
|
+
* ```ts
|
|
136
|
+
* app.post("/webhooks/spokpay-chat", express.raw({ type: "*\/*" }), async (req, res) => {
|
|
137
|
+
* const isValid = await SpokPayChat.verifyWebhookSignature({
|
|
138
|
+
* payload: req.body.toString(),
|
|
139
|
+
* signature: req.headers["x-spokpay-signature"] as string,
|
|
140
|
+
* secret: process.env.SPOKPAY_WEBHOOK_SECRET!,
|
|
141
|
+
* });
|
|
142
|
+
*
|
|
143
|
+
* if (!isValid) return res.status(401).send("Invalid signature");
|
|
144
|
+
*
|
|
145
|
+
* const event = JSON.parse(req.body.toString());
|
|
146
|
+
* // Handle event...
|
|
147
|
+
* res.sendStatus(200);
|
|
148
|
+
* });
|
|
149
|
+
* ```
|
|
150
|
+
*
|
|
151
|
+
* @example Convex httpAction
|
|
76
152
|
* ```ts
|
|
77
|
-
* const
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
153
|
+
* const handler = httpAction(async (ctx, req) => {
|
|
154
|
+
* const body = await req.text();
|
|
155
|
+
* const isValid = await SpokPayChat.verifyWebhookSignature({
|
|
156
|
+
* payload: body,
|
|
157
|
+
* signature: req.headers.get("x-spokpay-signature")!,
|
|
158
|
+
* secret: process.env.SPOKPAY_WEBHOOK_SECRET!,
|
|
159
|
+
* });
|
|
160
|
+
* if (!isValid) return new Response("Invalid", { status: 401 });
|
|
161
|
+
* // Process the webhook...
|
|
81
162
|
* });
|
|
82
163
|
* ```
|
|
83
164
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { SpokPayChat } from "./client.js";
|
|
2
2
|
export { SpokPayChatApiError } from "./types.js";
|
|
3
|
-
export type { SpokPayChatOptions, Conversation, CreateConversationOptions, GetConversationOptions, Message, SendMessageOptions, MessageAttachment, ListMessagesOptions, CloseConversationOptions, GetUploadUrlOptions, ChatWebhookPayload, WebhookMessageData, WebhookConversationData, VerifyWebhookOptions, } from "./types.js";
|
|
3
|
+
export type { SpokPayChatOptions, Conversation, CreateConversationOptions, GetConversationOptions, Message, SendMessageOptions, MessageAttachment, ListMessagesOptions, CloseConversationOptions, GetUploadUrlOptions, ChatWebhookPayload, WebhookMessageData, WebhookConversationData, WebhookItemDeliveredData, WebhookItemRefundedData, VerifyWebhookOptions, } from "./types.js";
|
package/dist/types.d.ts
CHANGED
|
@@ -1,19 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Configuration options for the {@link SpokPayChat} client.
|
|
3
3
|
*
|
|
4
|
+
* The API key prefix determines the environment:
|
|
5
|
+
* - `spk_live_*` — Production (real conversations routed to staff)
|
|
6
|
+
* - `spk_test_*` — Development/Sandbox (test conversations, no notifications)
|
|
7
|
+
*
|
|
4
8
|
* @example
|
|
5
9
|
* ```ts
|
|
6
10
|
* import { SpokPayChat } from "@spokpay/chat";
|
|
7
11
|
*
|
|
12
|
+
* // Production
|
|
8
13
|
* const chat = new SpokPayChat({
|
|
9
14
|
* apiKey: "spk_live_abc123...",
|
|
10
15
|
* baseUrl: "https://your-deployment.convex.site",
|
|
11
16
|
* });
|
|
17
|
+
*
|
|
18
|
+
* // Sandbox / Testing
|
|
19
|
+
* const chatTest = new SpokPayChat({
|
|
20
|
+
* apiKey: "spk_test_abc123...",
|
|
21
|
+
* baseUrl: "https://your-deployment.convex.site",
|
|
22
|
+
* });
|
|
12
23
|
* ```
|
|
13
24
|
*/
|
|
14
25
|
export interface SpokPayChatOptions {
|
|
15
26
|
/**
|
|
16
27
|
* Your SpokPay API key.
|
|
28
|
+
* - `spk_live_*` keys target **production** (real conversations routed to staff).
|
|
29
|
+
* - `spk_test_*` keys target **SpokPay sandbox** (test conversations, no notifications).
|
|
30
|
+
*
|
|
17
31
|
* Generate keys from the Plugin page in your SpokPay store dashboard.
|
|
18
32
|
*/
|
|
19
33
|
apiKey: string;
|
|
@@ -222,40 +236,163 @@ export interface ChatWebhookPayload {
|
|
|
222
236
|
* - `"message.updated"` — A message was edited.
|
|
223
237
|
* - `"message.deleted"` — A message was deleted.
|
|
224
238
|
* - `"conversation.closed"` — The conversation was closed.
|
|
239
|
+
* - `"item.delivered"` — An order item was delivered by staff.
|
|
240
|
+
* - `"item.refunded"` — An order item was refunded by staff.
|
|
225
241
|
*/
|
|
226
|
-
type: "message.created" | "message.updated" | "message.deleted" | "conversation.closed";
|
|
242
|
+
type: "message.created" | "message.updated" | "message.deleted" | "conversation.closed" | "item.delivered" | "item.refunded";
|
|
227
243
|
/** Event data. Shape depends on the event type. */
|
|
228
|
-
data: WebhookMessageData | WebhookConversationData;
|
|
244
|
+
data: WebhookMessageData | WebhookConversationData | WebhookItemDeliveredData | WebhookItemRefundedData;
|
|
229
245
|
/** Unix timestamp (ms) when the event was created. */
|
|
230
246
|
createdAt: number;
|
|
231
247
|
}
|
|
232
|
-
/**
|
|
248
|
+
/**
|
|
249
|
+
* Data included in message webhook events (`message.created`, `message.updated`, `message.deleted`).
|
|
250
|
+
*
|
|
251
|
+
* @example
|
|
252
|
+
* ```ts
|
|
253
|
+
* const event: ChatWebhookPayload = JSON.parse(body);
|
|
254
|
+
* if (event.type === "message.created") {
|
|
255
|
+
* const msg = event.data as WebhookMessageData;
|
|
256
|
+
* console.log(`${msg.authorDisplayName}: ${msg.content}`);
|
|
257
|
+
* }
|
|
258
|
+
* ```
|
|
259
|
+
*/
|
|
233
260
|
export interface WebhookMessageData {
|
|
261
|
+
/** Unique message ID. */
|
|
234
262
|
id: string;
|
|
263
|
+
/** The conversation this message belongs to. */
|
|
235
264
|
conversationId: string;
|
|
265
|
+
/** Message text content. */
|
|
236
266
|
content: string;
|
|
267
|
+
/** Who sent this message (e.g., `"staff"`, `"ai"`, `"bot"`). */
|
|
237
268
|
authorType: string;
|
|
269
|
+
/** Display name of the author. */
|
|
238
270
|
authorDisplayName?: string;
|
|
271
|
+
/** Your external ID for the author, if provided. */
|
|
239
272
|
authorExternalId?: string;
|
|
273
|
+
/** File attachments included with the message. */
|
|
240
274
|
attachments: Array<{
|
|
275
|
+
/** Filename. */
|
|
241
276
|
filename: string;
|
|
277
|
+
/** MIME content type. */
|
|
242
278
|
contentType?: string;
|
|
279
|
+
/** File size in bytes. */
|
|
243
280
|
size?: number;
|
|
281
|
+
/** Direct URL to the file. */
|
|
244
282
|
url?: string;
|
|
245
283
|
}>;
|
|
284
|
+
/** Unix timestamp (ms) when the message was sent. */
|
|
246
285
|
createdAt: number;
|
|
247
286
|
}
|
|
248
|
-
/**
|
|
287
|
+
/**
|
|
288
|
+
* Data included in conversation webhook events (`conversation.closed`).
|
|
289
|
+
*
|
|
290
|
+
* @example
|
|
291
|
+
* ```ts
|
|
292
|
+
* const event: ChatWebhookPayload = JSON.parse(body);
|
|
293
|
+
* if (event.type === "conversation.closed") {
|
|
294
|
+
* const conv = event.data as WebhookConversationData;
|
|
295
|
+
* console.log(`Conversation ${conv.id} closed at ${new Date(conv.closedAt!)}`);
|
|
296
|
+
* }
|
|
297
|
+
* ```
|
|
298
|
+
*/
|
|
249
299
|
export interface WebhookConversationData {
|
|
300
|
+
/** Unique SpokPay conversation ID. */
|
|
250
301
|
id: string;
|
|
302
|
+
/** The type of conversation (e.g., `"order_support"`, `"general"`). */
|
|
251
303
|
type: string;
|
|
304
|
+
/** Current status of the conversation (e.g., `"closed"`). */
|
|
252
305
|
status: string;
|
|
306
|
+
/** Your external ID, if provided when creating the conversation. */
|
|
253
307
|
externalId?: string;
|
|
308
|
+
/** Conversation subject or title. */
|
|
254
309
|
subject?: string;
|
|
310
|
+
/** Arbitrary metadata as a JSON string, if provided. */
|
|
255
311
|
metadata?: string;
|
|
312
|
+
/** Unix timestamp (ms) when the conversation was created. */
|
|
256
313
|
createdAt: number;
|
|
314
|
+
/** Unix timestamp (ms) when the conversation was closed. */
|
|
257
315
|
closedAt?: number;
|
|
258
316
|
}
|
|
317
|
+
/**
|
|
318
|
+
* Data included in `item.delivered` webhook events.
|
|
319
|
+
*
|
|
320
|
+
* Fired when a staff member marks an order item as delivered from the SpokPay dashboard.
|
|
321
|
+
*
|
|
322
|
+
* @example
|
|
323
|
+
* ```ts
|
|
324
|
+
* const event: ChatWebhookPayload = JSON.parse(body);
|
|
325
|
+
* if (event.type === "item.delivered") {
|
|
326
|
+
* const data = event.data as WebhookItemDeliveredData;
|
|
327
|
+
* console.log(`${data.item.name} delivered by ${data.deliveredBy}`);
|
|
328
|
+
* }
|
|
329
|
+
* ```
|
|
330
|
+
*/
|
|
331
|
+
export interface WebhookItemDeliveredData {
|
|
332
|
+
/** SpokPay conversation ID. */
|
|
333
|
+
conversationId: string;
|
|
334
|
+
/** Your external ID for the conversation. */
|
|
335
|
+
externalId?: string;
|
|
336
|
+
/** The delivered item. */
|
|
337
|
+
item: {
|
|
338
|
+
/** Your external ID for this product (from charge items). */
|
|
339
|
+
externalId?: string;
|
|
340
|
+
/** Product name. */
|
|
341
|
+
name: string;
|
|
342
|
+
/** Quantity delivered. */
|
|
343
|
+
quantity: number;
|
|
344
|
+
/** Delivery proof image, if provided. */
|
|
345
|
+
deliveryProof?: {
|
|
346
|
+
/** Direct URL to the proof image. */
|
|
347
|
+
url: string;
|
|
348
|
+
/** Filename. */
|
|
349
|
+
filename: string;
|
|
350
|
+
/** MIME content type. */
|
|
351
|
+
contentType: string;
|
|
352
|
+
};
|
|
353
|
+
};
|
|
354
|
+
/** Display name of the staff member who delivered. */
|
|
355
|
+
deliveredBy: string;
|
|
356
|
+
/** Unix timestamp (ms) when the item was delivered. */
|
|
357
|
+
deliveredAt: number;
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Data included in `item.refunded` webhook events.
|
|
361
|
+
*
|
|
362
|
+
* Fired when a staff member refunds an order item from the SpokPay dashboard.
|
|
363
|
+
*
|
|
364
|
+
* @example
|
|
365
|
+
* ```ts
|
|
366
|
+
* const event: ChatWebhookPayload = JSON.parse(body);
|
|
367
|
+
* if (event.type === "item.refunded") {
|
|
368
|
+
* const data = event.data as WebhookItemRefundedData;
|
|
369
|
+
* console.log(`${data.item.name} refunded: ${data.item.refundReason}`);
|
|
370
|
+
* }
|
|
371
|
+
* ```
|
|
372
|
+
*/
|
|
373
|
+
export interface WebhookItemRefundedData {
|
|
374
|
+
/** SpokPay conversation ID. */
|
|
375
|
+
conversationId: string;
|
|
376
|
+
/** Your external ID for the conversation. */
|
|
377
|
+
externalId?: string;
|
|
378
|
+
/** The refunded item. */
|
|
379
|
+
item: {
|
|
380
|
+
/** Your external ID for this product (from charge items). */
|
|
381
|
+
externalId?: string;
|
|
382
|
+
/** Product name. */
|
|
383
|
+
name: string;
|
|
384
|
+
/** Quantity refunded. */
|
|
385
|
+
quantity: number;
|
|
386
|
+
/** Refund amount. */
|
|
387
|
+
refundAmount?: number;
|
|
388
|
+
/** Reason for the refund. */
|
|
389
|
+
refundReason?: string;
|
|
390
|
+
};
|
|
391
|
+
/** Display name of the staff member who processed the refund. */
|
|
392
|
+
refundedBy: string;
|
|
393
|
+
/** Unix timestamp (ms) when the item was refunded. */
|
|
394
|
+
refundedAt: number;
|
|
395
|
+
}
|
|
259
396
|
/**
|
|
260
397
|
* Options for verifying a webhook signature.
|
|
261
398
|
*
|
|
@@ -270,7 +407,22 @@ export interface VerifyWebhookOptions {
|
|
|
270
407
|
secret: string;
|
|
271
408
|
}
|
|
272
409
|
/**
|
|
273
|
-
* Error thrown when the SpokPay API returns a non-2xx response.
|
|
410
|
+
* Error thrown when the SpokPay Chat API returns a non-2xx response.
|
|
411
|
+
*
|
|
412
|
+
* @example
|
|
413
|
+
* ```ts
|
|
414
|
+
* import { SpokPayChatApiError } from "@spokpay/chat";
|
|
415
|
+
*
|
|
416
|
+
* try {
|
|
417
|
+
* await chat.conversations.get({ id: "invalid_id" });
|
|
418
|
+
* } catch (error) {
|
|
419
|
+
* if (error instanceof SpokPayChatApiError) {
|
|
420
|
+
* console.error(error.message); // "Conversation not found"
|
|
421
|
+
* console.error(error.statusCode); // 404
|
|
422
|
+
* console.error(error.body); // Raw API response body
|
|
423
|
+
* }
|
|
424
|
+
* }
|
|
425
|
+
* ```
|
|
274
426
|
*/
|
|
275
427
|
export declare class SpokPayChatApiError extends Error {
|
|
276
428
|
/** HTTP status code from the API response. */
|
package/dist/types.js
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Error thrown when the SpokPay API returns a non-2xx response.
|
|
2
|
+
* Error thrown when the SpokPay Chat API returns a non-2xx response.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```ts
|
|
6
|
+
* import { SpokPayChatApiError } from "@spokpay/chat";
|
|
7
|
+
*
|
|
8
|
+
* try {
|
|
9
|
+
* await chat.conversations.get({ id: "invalid_id" });
|
|
10
|
+
* } catch (error) {
|
|
11
|
+
* if (error instanceof SpokPayChatApiError) {
|
|
12
|
+
* console.error(error.message); // "Conversation not found"
|
|
13
|
+
* console.error(error.statusCode); // 404
|
|
14
|
+
* console.error(error.body); // Raw API response body
|
|
15
|
+
* }
|
|
16
|
+
* }
|
|
17
|
+
* ```
|
|
3
18
|
*/
|
|
4
19
|
export class SpokPayChatApiError extends Error {
|
|
5
20
|
/** HTTP status code from the API response. */
|