@technomoron/mail-magic 1.0.32 → 1.0.34
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/CHANGES +18 -0
- package/README.md +213 -122
- package/dist/api/assets.js +9 -56
- package/dist/api/auth.js +1 -12
- package/dist/api/form-replyto.js +1 -0
- package/dist/api/form-submission.js +1 -0
- package/dist/api/forms.js +114 -474
- package/dist/api/mailer.js +1 -1
- package/dist/bin/mail-magic.js +2 -2
- package/dist/index.js +30 -18
- package/dist/models/db.js +5 -5
- package/dist/models/domain.js +16 -8
- package/dist/models/form.js +111 -40
- package/dist/models/init.js +44 -74
- package/dist/models/recipient.js +12 -8
- package/dist/models/txmail.js +24 -28
- package/dist/models/user.js +14 -10
- package/dist/server.js +1 -1
- package/dist/store/store.js +53 -22
- package/dist/swagger.js +107 -0
- package/dist/util/captcha.js +24 -0
- package/dist/util/email.js +19 -0
- package/dist/util/form-replyto.js +44 -0
- package/dist/util/form-submission.js +95 -0
- package/dist/util/forms.js +431 -0
- package/dist/util/paths.js +41 -0
- package/dist/util/ratelimit.js +48 -0
- package/dist/util/uploads.js +48 -0
- package/dist/util/utils.js +151 -0
- package/dist/util.js +7 -127
- package/docs/config-example/example.test/assets/files/banner.png +1 -0
- package/docs/config-example/example.test/assets/images/logo.png +1 -0
- package/docs/config-example/example.test/form-template/base.njk +6 -0
- package/docs/config-example/example.test/form-template/contact.njk +9 -0
- package/docs/config-example/example.test/form-template/partials/fields.njk +3 -0
- package/docs/config-example/example.test/tx-template/base.njk +10 -0
- package/docs/config-example/example.test/tx-template/partials/header.njk +1 -0
- package/docs/config-example/example.test/tx-template/welcome.njk +10 -0
- package/docs/config-example/init-data.json +57 -0
- package/docs/form-security.md +194 -0
- package/docs/swagger/openapi.json +1321 -0
- package/{TUTORIAL.MD → docs/tutorial.md} +24 -15
- package/package.json +3 -3
|
@@ -0,0 +1,1321 @@
|
|
|
1
|
+
{
|
|
2
|
+
"openapi": "3.1.0",
|
|
3
|
+
"info": {
|
|
4
|
+
"title": "Mail Magic API",
|
|
5
|
+
"version": "1.0.33",
|
|
6
|
+
"description": "OpenAPI definition for the Mail Magic server. Authenticated endpoints require an API key provided as `Authorization: Bearer apikey-<token>`."
|
|
7
|
+
},
|
|
8
|
+
"servers": [
|
|
9
|
+
{
|
|
10
|
+
"url": "http://localhost:3776",
|
|
11
|
+
"description": "Local development server"
|
|
12
|
+
}
|
|
13
|
+
],
|
|
14
|
+
"tags": [
|
|
15
|
+
{
|
|
16
|
+
"name": "base",
|
|
17
|
+
"description": "Base endpoints provided by the server runtime."
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"name": "transactional",
|
|
21
|
+
"description": "Transactional template endpoints (/v1/tx/*)."
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"name": "forms",
|
|
25
|
+
"description": "Form template and submission endpoints (/v1/form/*)."
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"name": "assets",
|
|
29
|
+
"description": "Asset upload endpoints."
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"name": "public-assets",
|
|
33
|
+
"description": "Publicly served domain assets under ASSET_ROUTE."
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"name": "swagger",
|
|
37
|
+
"description": "Swagger/OpenAPI spec endpoint (enabled via SWAGGER_ENABLED / SWAGGER_PATH)."
|
|
38
|
+
}
|
|
39
|
+
],
|
|
40
|
+
"paths": {
|
|
41
|
+
"/api/v1/ping": {
|
|
42
|
+
"get": {
|
|
43
|
+
"tags": ["base"],
|
|
44
|
+
"summary": "Health check",
|
|
45
|
+
"description": "Auth: none. Returns ApiResponse<PingResponseData> with health and version metadata.",
|
|
46
|
+
"security": [],
|
|
47
|
+
"responses": {
|
|
48
|
+
"200": {
|
|
49
|
+
"description": "Server is reachable.",
|
|
50
|
+
"content": {
|
|
51
|
+
"application/json": {
|
|
52
|
+
"schema": {
|
|
53
|
+
"allOf": [
|
|
54
|
+
{
|
|
55
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"type": "object",
|
|
59
|
+
"properties": {
|
|
60
|
+
"data": {
|
|
61
|
+
"$ref": "#/components/schemas/PingResponseData"
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"required": ["data"]
|
|
65
|
+
}
|
|
66
|
+
]
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
"/api/v1/tx/template": {
|
|
75
|
+
"post": {
|
|
76
|
+
"tags": ["transactional"],
|
|
77
|
+
"summary": "Upsert transactional template",
|
|
78
|
+
"description": "Auth: API key. Stores (upserts) a transactional template for a domain.",
|
|
79
|
+
"security": [
|
|
80
|
+
{
|
|
81
|
+
"apiKeyBearer": []
|
|
82
|
+
}
|
|
83
|
+
],
|
|
84
|
+
"requestBody": {
|
|
85
|
+
"required": true,
|
|
86
|
+
"content": {
|
|
87
|
+
"application/json": {
|
|
88
|
+
"schema": {
|
|
89
|
+
"$ref": "#/components/schemas/TxTemplateUpsertRequest"
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
"responses": {
|
|
95
|
+
"200": {
|
|
96
|
+
"description": "Template stored.",
|
|
97
|
+
"content": {
|
|
98
|
+
"application/json": {
|
|
99
|
+
"schema": {
|
|
100
|
+
"allOf": [
|
|
101
|
+
{
|
|
102
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"type": "object",
|
|
106
|
+
"properties": {
|
|
107
|
+
"data": {
|
|
108
|
+
"$ref": "#/components/schemas/StatusOkData"
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
"required": ["data"]
|
|
112
|
+
}
|
|
113
|
+
]
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
"400": {
|
|
119
|
+
"description": "Bad request.",
|
|
120
|
+
"content": {
|
|
121
|
+
"application/json": {
|
|
122
|
+
"schema": {
|
|
123
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
"401": {
|
|
129
|
+
"description": "Unauthorized.",
|
|
130
|
+
"content": {
|
|
131
|
+
"application/json": {
|
|
132
|
+
"schema": {
|
|
133
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
"403": {
|
|
139
|
+
"description": "Forbidden.",
|
|
140
|
+
"content": {
|
|
141
|
+
"application/json": {
|
|
142
|
+
"schema": {
|
|
143
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
"500": {
|
|
149
|
+
"description": "Server error.",
|
|
150
|
+
"content": {
|
|
151
|
+
"application/json": {
|
|
152
|
+
"schema": {
|
|
153
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
"/api/v1/tx/message": {
|
|
162
|
+
"post": {
|
|
163
|
+
"tags": ["transactional"],
|
|
164
|
+
"summary": "Send transactional message",
|
|
165
|
+
"description": "Auth: API key. Sends one or more emails using a stored template. File uploads are supported via multipart/form-data; uploaded file fields may be named arbitrarily (e.g. `file1`, `attachment`, etc).",
|
|
166
|
+
"security": [
|
|
167
|
+
{
|
|
168
|
+
"apiKeyBearer": []
|
|
169
|
+
}
|
|
170
|
+
],
|
|
171
|
+
"requestBody": {
|
|
172
|
+
"required": true,
|
|
173
|
+
"content": {
|
|
174
|
+
"application/json": {
|
|
175
|
+
"schema": {
|
|
176
|
+
"$ref": "#/components/schemas/TxSendRequest"
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
"multipart/form-data": {
|
|
180
|
+
"schema": {
|
|
181
|
+
"$ref": "#/components/schemas/TxSendMultipartRequest"
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
},
|
|
186
|
+
"responses": {
|
|
187
|
+
"200": {
|
|
188
|
+
"description": "Email(s) sent.",
|
|
189
|
+
"content": {
|
|
190
|
+
"application/json": {
|
|
191
|
+
"schema": {
|
|
192
|
+
"allOf": [
|
|
193
|
+
{
|
|
194
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
"type": "object",
|
|
198
|
+
"properties": {
|
|
199
|
+
"data": {
|
|
200
|
+
"$ref": "#/components/schemas/TxSendResponseData"
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
"required": ["data"]
|
|
204
|
+
}
|
|
205
|
+
]
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
},
|
|
210
|
+
"400": {
|
|
211
|
+
"description": "Bad request.",
|
|
212
|
+
"content": {
|
|
213
|
+
"application/json": {
|
|
214
|
+
"schema": {
|
|
215
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
"401": {
|
|
221
|
+
"description": "Unauthorized.",
|
|
222
|
+
"content": {
|
|
223
|
+
"application/json": {
|
|
224
|
+
"schema": {
|
|
225
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
},
|
|
230
|
+
"403": {
|
|
231
|
+
"description": "Forbidden.",
|
|
232
|
+
"content": {
|
|
233
|
+
"application/json": {
|
|
234
|
+
"schema": {
|
|
235
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
"404": {
|
|
241
|
+
"description": "Template not found.",
|
|
242
|
+
"content": {
|
|
243
|
+
"application/json": {
|
|
244
|
+
"schema": {
|
|
245
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
},
|
|
250
|
+
"413": {
|
|
251
|
+
"description": "Upload too large.",
|
|
252
|
+
"content": {
|
|
253
|
+
"application/json": {
|
|
254
|
+
"schema": {
|
|
255
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
},
|
|
260
|
+
"500": {
|
|
261
|
+
"description": "Server error.",
|
|
262
|
+
"content": {
|
|
263
|
+
"application/json": {
|
|
264
|
+
"schema": {
|
|
265
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
},
|
|
273
|
+
"/api/v1/form/recipient": {
|
|
274
|
+
"post": {
|
|
275
|
+
"tags": ["forms"],
|
|
276
|
+
"summary": "Upsert form recipient mapping",
|
|
277
|
+
"description": "Auth: API key. Creates or updates a named recipient mapping for a domain (optionally scoped to a form_key).",
|
|
278
|
+
"security": [
|
|
279
|
+
{
|
|
280
|
+
"apiKeyBearer": []
|
|
281
|
+
}
|
|
282
|
+
],
|
|
283
|
+
"requestBody": {
|
|
284
|
+
"required": true,
|
|
285
|
+
"content": {
|
|
286
|
+
"application/json": {
|
|
287
|
+
"schema": {
|
|
288
|
+
"$ref": "#/components/schemas/FormRecipientUpsertRequest"
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
},
|
|
293
|
+
"responses": {
|
|
294
|
+
"200": {
|
|
295
|
+
"description": "Recipient mapping stored.",
|
|
296
|
+
"content": {
|
|
297
|
+
"application/json": {
|
|
298
|
+
"schema": {
|
|
299
|
+
"allOf": [
|
|
300
|
+
{
|
|
301
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
"type": "object",
|
|
305
|
+
"properties": {
|
|
306
|
+
"data": {
|
|
307
|
+
"$ref": "#/components/schemas/FormRecipientUpsertResponseData"
|
|
308
|
+
}
|
|
309
|
+
},
|
|
310
|
+
"required": ["data"]
|
|
311
|
+
}
|
|
312
|
+
]
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
},
|
|
317
|
+
"400": {
|
|
318
|
+
"description": "Bad request.",
|
|
319
|
+
"content": {
|
|
320
|
+
"application/json": {
|
|
321
|
+
"schema": {
|
|
322
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
},
|
|
327
|
+
"401": {
|
|
328
|
+
"description": "Unauthorized.",
|
|
329
|
+
"content": {
|
|
330
|
+
"application/json": {
|
|
331
|
+
"schema": {
|
|
332
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
},
|
|
337
|
+
"403": {
|
|
338
|
+
"description": "Forbidden.",
|
|
339
|
+
"content": {
|
|
340
|
+
"application/json": {
|
|
341
|
+
"schema": {
|
|
342
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
},
|
|
347
|
+
"404": {
|
|
348
|
+
"description": "Not found.",
|
|
349
|
+
"content": {
|
|
350
|
+
"application/json": {
|
|
351
|
+
"schema": {
|
|
352
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
},
|
|
357
|
+
"409": {
|
|
358
|
+
"description": "Conflict / ambiguity.",
|
|
359
|
+
"content": {
|
|
360
|
+
"application/json": {
|
|
361
|
+
"schema": {
|
|
362
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
},
|
|
367
|
+
"500": {
|
|
368
|
+
"description": "Server error.",
|
|
369
|
+
"content": {
|
|
370
|
+
"application/json": {
|
|
371
|
+
"schema": {
|
|
372
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
},
|
|
380
|
+
"/api/v1/form/template": {
|
|
381
|
+
"post": {
|
|
382
|
+
"tags": ["forms"],
|
|
383
|
+
"summary": "Upsert form template",
|
|
384
|
+
"description": "Auth: API key. Stores (upserts) a form template for a domain.",
|
|
385
|
+
"security": [
|
|
386
|
+
{
|
|
387
|
+
"apiKeyBearer": []
|
|
388
|
+
}
|
|
389
|
+
],
|
|
390
|
+
"requestBody": {
|
|
391
|
+
"required": true,
|
|
392
|
+
"content": {
|
|
393
|
+
"application/json": {
|
|
394
|
+
"schema": {
|
|
395
|
+
"$ref": "#/components/schemas/FormTemplateUpsertRequest"
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
},
|
|
400
|
+
"responses": {
|
|
401
|
+
"200": {
|
|
402
|
+
"description": "Form template stored.",
|
|
403
|
+
"content": {
|
|
404
|
+
"application/json": {
|
|
405
|
+
"schema": {
|
|
406
|
+
"allOf": [
|
|
407
|
+
{
|
|
408
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
409
|
+
},
|
|
410
|
+
{
|
|
411
|
+
"type": "object",
|
|
412
|
+
"properties": {
|
|
413
|
+
"data": {
|
|
414
|
+
"$ref": "#/components/schemas/FormTemplateUpsertResponseData"
|
|
415
|
+
}
|
|
416
|
+
},
|
|
417
|
+
"required": ["data"]
|
|
418
|
+
}
|
|
419
|
+
]
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
},
|
|
424
|
+
"400": {
|
|
425
|
+
"description": "Bad request.",
|
|
426
|
+
"content": {
|
|
427
|
+
"application/json": {
|
|
428
|
+
"schema": {
|
|
429
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
},
|
|
434
|
+
"401": {
|
|
435
|
+
"description": "Unauthorized.",
|
|
436
|
+
"content": {
|
|
437
|
+
"application/json": {
|
|
438
|
+
"schema": {
|
|
439
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
},
|
|
444
|
+
"403": {
|
|
445
|
+
"description": "Forbidden.",
|
|
446
|
+
"content": {
|
|
447
|
+
"application/json": {
|
|
448
|
+
"schema": {
|
|
449
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
},
|
|
454
|
+
"500": {
|
|
455
|
+
"description": "Server error.",
|
|
456
|
+
"content": {
|
|
457
|
+
"application/json": {
|
|
458
|
+
"schema": {
|
|
459
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
},
|
|
467
|
+
"/api/v1/form/message": {
|
|
468
|
+
"post": {
|
|
469
|
+
"tags": ["forms"],
|
|
470
|
+
"summary": "Submit form message",
|
|
471
|
+
"description": "Auth: none. Submits a form and triggers email delivery. Supports multipart/form-data for attachments.",
|
|
472
|
+
"security": [],
|
|
473
|
+
"requestBody": {
|
|
474
|
+
"required": true,
|
|
475
|
+
"content": {
|
|
476
|
+
"application/json": {
|
|
477
|
+
"schema": {
|
|
478
|
+
"$ref": "#/components/schemas/FormMessageRequest"
|
|
479
|
+
}
|
|
480
|
+
},
|
|
481
|
+
"multipart/form-data": {
|
|
482
|
+
"schema": {
|
|
483
|
+
"$ref": "#/components/schemas/FormMessageMultipartRequest"
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
},
|
|
488
|
+
"responses": {
|
|
489
|
+
"200": {
|
|
490
|
+
"description": "Delivered (or accepted).",
|
|
491
|
+
"content": {
|
|
492
|
+
"application/json": {
|
|
493
|
+
"schema": {
|
|
494
|
+
"allOf": [
|
|
495
|
+
{
|
|
496
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
497
|
+
},
|
|
498
|
+
{
|
|
499
|
+
"type": "object",
|
|
500
|
+
"properties": {
|
|
501
|
+
"data": {
|
|
502
|
+
"$ref": "#/components/schemas/FormMessageResponseData"
|
|
503
|
+
}
|
|
504
|
+
},
|
|
505
|
+
"required": ["data"]
|
|
506
|
+
}
|
|
507
|
+
]
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
},
|
|
512
|
+
"400": {
|
|
513
|
+
"description": "Bad request.",
|
|
514
|
+
"content": {
|
|
515
|
+
"application/json": {
|
|
516
|
+
"schema": {
|
|
517
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
},
|
|
522
|
+
"401": {
|
|
523
|
+
"description": "Unauthorized / bad secret.",
|
|
524
|
+
"content": {
|
|
525
|
+
"application/json": {
|
|
526
|
+
"schema": {
|
|
527
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
},
|
|
532
|
+
"403": {
|
|
533
|
+
"description": "Forbidden / CAPTCHA failed.",
|
|
534
|
+
"content": {
|
|
535
|
+
"application/json": {
|
|
536
|
+
"schema": {
|
|
537
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
},
|
|
542
|
+
"404": {
|
|
543
|
+
"description": "Form not found.",
|
|
544
|
+
"content": {
|
|
545
|
+
"application/json": {
|
|
546
|
+
"schema": {
|
|
547
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
},
|
|
552
|
+
"409": {
|
|
553
|
+
"description": "Ambiguous form id.",
|
|
554
|
+
"content": {
|
|
555
|
+
"application/json": {
|
|
556
|
+
"schema": {
|
|
557
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
},
|
|
562
|
+
"413": {
|
|
563
|
+
"description": "Too many/large attachments.",
|
|
564
|
+
"content": {
|
|
565
|
+
"application/json": {
|
|
566
|
+
"schema": {
|
|
567
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
},
|
|
572
|
+
"429": {
|
|
573
|
+
"description": "Rate limited.",
|
|
574
|
+
"content": {
|
|
575
|
+
"application/json": {
|
|
576
|
+
"schema": {
|
|
577
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
},
|
|
582
|
+
"500": {
|
|
583
|
+
"description": "Server error.",
|
|
584
|
+
"content": {
|
|
585
|
+
"application/json": {
|
|
586
|
+
"schema": {
|
|
587
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
},
|
|
595
|
+
"/api/v1/assets": {
|
|
596
|
+
"post": {
|
|
597
|
+
"tags": ["assets"],
|
|
598
|
+
"summary": "Upload assets",
|
|
599
|
+
"description": "Auth: API key. Upload one or more files to the domain asset directory or to a specific template directory. Requires multipart/form-data.",
|
|
600
|
+
"security": [
|
|
601
|
+
{
|
|
602
|
+
"apiKeyBearer": []
|
|
603
|
+
}
|
|
604
|
+
],
|
|
605
|
+
"requestBody": {
|
|
606
|
+
"required": true,
|
|
607
|
+
"content": {
|
|
608
|
+
"multipart/form-data": {
|
|
609
|
+
"schema": {
|
|
610
|
+
"$ref": "#/components/schemas/AssetsUploadMultipartRequest"
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
},
|
|
615
|
+
"responses": {
|
|
616
|
+
"200": {
|
|
617
|
+
"description": "Assets uploaded.",
|
|
618
|
+
"content": {
|
|
619
|
+
"application/json": {
|
|
620
|
+
"schema": {
|
|
621
|
+
"allOf": [
|
|
622
|
+
{
|
|
623
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
624
|
+
},
|
|
625
|
+
{
|
|
626
|
+
"type": "object",
|
|
627
|
+
"properties": {
|
|
628
|
+
"data": {
|
|
629
|
+
"$ref": "#/components/schemas/StatusOkData"
|
|
630
|
+
}
|
|
631
|
+
},
|
|
632
|
+
"required": ["data"]
|
|
633
|
+
}
|
|
634
|
+
]
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
},
|
|
639
|
+
"400": {
|
|
640
|
+
"description": "Bad request.",
|
|
641
|
+
"content": {
|
|
642
|
+
"application/json": {
|
|
643
|
+
"schema": {
|
|
644
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
},
|
|
649
|
+
"401": {
|
|
650
|
+
"description": "Unauthorized.",
|
|
651
|
+
"content": {
|
|
652
|
+
"application/json": {
|
|
653
|
+
"schema": {
|
|
654
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
},
|
|
659
|
+
"403": {
|
|
660
|
+
"description": "Forbidden.",
|
|
661
|
+
"content": {
|
|
662
|
+
"application/json": {
|
|
663
|
+
"schema": {
|
|
664
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
},
|
|
669
|
+
"404": {
|
|
670
|
+
"description": "Template not found.",
|
|
671
|
+
"content": {
|
|
672
|
+
"application/json": {
|
|
673
|
+
"schema": {
|
|
674
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
},
|
|
679
|
+
"413": {
|
|
680
|
+
"description": "Upload too large.",
|
|
681
|
+
"content": {
|
|
682
|
+
"application/json": {
|
|
683
|
+
"schema": {
|
|
684
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
},
|
|
689
|
+
"500": {
|
|
690
|
+
"description": "Server error.",
|
|
691
|
+
"content": {
|
|
692
|
+
"application/json": {
|
|
693
|
+
"schema": {
|
|
694
|
+
"$ref": "#/components/schemas/ApiResponse"
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
},
|
|
702
|
+
"/asset/{domain}/{path}": {
|
|
703
|
+
"get": {
|
|
704
|
+
"tags": ["public-assets"],
|
|
705
|
+
"summary": "Fetch a public asset",
|
|
706
|
+
"description": "Public route for domain assets. The `{path}` parameter can contain slashes.",
|
|
707
|
+
"security": [],
|
|
708
|
+
"parameters": [
|
|
709
|
+
{
|
|
710
|
+
"name": "domain",
|
|
711
|
+
"in": "path",
|
|
712
|
+
"required": true,
|
|
713
|
+
"schema": {
|
|
714
|
+
"type": "string"
|
|
715
|
+
},
|
|
716
|
+
"description": "Domain name."
|
|
717
|
+
},
|
|
718
|
+
{
|
|
719
|
+
"name": "path",
|
|
720
|
+
"in": "path",
|
|
721
|
+
"required": true,
|
|
722
|
+
"allowReserved": true,
|
|
723
|
+
"schema": {
|
|
724
|
+
"type": "string"
|
|
725
|
+
},
|
|
726
|
+
"description": "Asset path under the domain assets directory (may contain `/`)."
|
|
727
|
+
}
|
|
728
|
+
],
|
|
729
|
+
"responses": {
|
|
730
|
+
"200": {
|
|
731
|
+
"description": "Asset bytes.",
|
|
732
|
+
"content": {
|
|
733
|
+
"application/octet-stream": {
|
|
734
|
+
"schema": {
|
|
735
|
+
"type": "string",
|
|
736
|
+
"format": "binary"
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
},
|
|
741
|
+
"404": {
|
|
742
|
+
"description": "Not found."
|
|
743
|
+
},
|
|
744
|
+
"500": {
|
|
745
|
+
"description": "Server error."
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
},
|
|
750
|
+
"/api/asset/{domain}/{path}": {
|
|
751
|
+
"get": {
|
|
752
|
+
"tags": ["public-assets"],
|
|
753
|
+
"summary": "Fetch a public asset (under API base path)",
|
|
754
|
+
"description": "Compatibility route for assets reachable under API_BASE_PATH + ASSET_ROUTE.",
|
|
755
|
+
"security": [],
|
|
756
|
+
"parameters": [
|
|
757
|
+
{
|
|
758
|
+
"name": "domain",
|
|
759
|
+
"in": "path",
|
|
760
|
+
"required": true,
|
|
761
|
+
"schema": {
|
|
762
|
+
"type": "string"
|
|
763
|
+
}
|
|
764
|
+
},
|
|
765
|
+
{
|
|
766
|
+
"name": "path",
|
|
767
|
+
"in": "path",
|
|
768
|
+
"required": true,
|
|
769
|
+
"allowReserved": true,
|
|
770
|
+
"schema": {
|
|
771
|
+
"type": "string"
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
],
|
|
775
|
+
"responses": {
|
|
776
|
+
"200": {
|
|
777
|
+
"description": "Asset bytes.",
|
|
778
|
+
"content": {
|
|
779
|
+
"application/octet-stream": {
|
|
780
|
+
"schema": {
|
|
781
|
+
"type": "string",
|
|
782
|
+
"format": "binary"
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
},
|
|
787
|
+
"404": {
|
|
788
|
+
"description": "Not found."
|
|
789
|
+
},
|
|
790
|
+
"500": {
|
|
791
|
+
"description": "Server error."
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
},
|
|
796
|
+
"/api/swagger": {
|
|
797
|
+
"get": {
|
|
798
|
+
"tags": ["swagger"],
|
|
799
|
+
"summary": "Get OpenAPI spec",
|
|
800
|
+
"description": "Returns the OpenAPI spec JSON when Swagger is enabled. This endpoint is not wrapped in ApiResponse.",
|
|
801
|
+
"security": [],
|
|
802
|
+
"responses": {
|
|
803
|
+
"200": {
|
|
804
|
+
"description": "OpenAPI JSON.",
|
|
805
|
+
"content": {
|
|
806
|
+
"application/json": {
|
|
807
|
+
"schema": {
|
|
808
|
+
"type": "object"
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
},
|
|
813
|
+
"500": {
|
|
814
|
+
"description": "Spec unavailable."
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
},
|
|
820
|
+
"components": {
|
|
821
|
+
"securitySchemes": {
|
|
822
|
+
"apiKeyBearer": {
|
|
823
|
+
"type": "http",
|
|
824
|
+
"scheme": "bearer",
|
|
825
|
+
"description": "API key via Authorization: Bearer apikey-<secret>."
|
|
826
|
+
}
|
|
827
|
+
},
|
|
828
|
+
"schemas": {
|
|
829
|
+
"ApiResponse": {
|
|
830
|
+
"type": "object",
|
|
831
|
+
"description": "ApiResponse<T> standard envelope used by API endpoints. T is carried in the data field.",
|
|
832
|
+
"properties": {
|
|
833
|
+
"success": {
|
|
834
|
+
"type": "boolean"
|
|
835
|
+
},
|
|
836
|
+
"code": {
|
|
837
|
+
"type": "integer"
|
|
838
|
+
},
|
|
839
|
+
"message": {
|
|
840
|
+
"type": "string"
|
|
841
|
+
},
|
|
842
|
+
"data": {
|
|
843
|
+
"nullable": true
|
|
844
|
+
},
|
|
845
|
+
"errors": {
|
|
846
|
+
"type": "object",
|
|
847
|
+
"additionalProperties": {
|
|
848
|
+
"type": "string"
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
},
|
|
852
|
+
"required": ["success", "code", "message", "data", "errors"]
|
|
853
|
+
},
|
|
854
|
+
"PingResponseData": {
|
|
855
|
+
"type": "object",
|
|
856
|
+
"description": "Data payload returned by GET /api/v1/ping.",
|
|
857
|
+
"properties": {
|
|
858
|
+
"success": {
|
|
859
|
+
"type": "boolean"
|
|
860
|
+
},
|
|
861
|
+
"status": {
|
|
862
|
+
"type": "string"
|
|
863
|
+
},
|
|
864
|
+
"apiVersion": {
|
|
865
|
+
"type": "string"
|
|
866
|
+
},
|
|
867
|
+
"minClientVersion": {
|
|
868
|
+
"type": "string"
|
|
869
|
+
},
|
|
870
|
+
"uptimeSec": {
|
|
871
|
+
"type": "number"
|
|
872
|
+
},
|
|
873
|
+
"startedAt": {
|
|
874
|
+
"type": "integer",
|
|
875
|
+
"format": "int64"
|
|
876
|
+
},
|
|
877
|
+
"timestamp": {
|
|
878
|
+
"type": "string",
|
|
879
|
+
"format": "date-time"
|
|
880
|
+
}
|
|
881
|
+
},
|
|
882
|
+
"required": ["success", "status", "uptimeSec", "startedAt", "timestamp"]
|
|
883
|
+
},
|
|
884
|
+
"StatusOkData": {
|
|
885
|
+
"type": "object",
|
|
886
|
+
"properties": {
|
|
887
|
+
"Status": {
|
|
888
|
+
"type": "string",
|
|
889
|
+
"examples": ["OK"]
|
|
890
|
+
}
|
|
891
|
+
},
|
|
892
|
+
"required": ["Status"]
|
|
893
|
+
},
|
|
894
|
+
"TxTemplateUpsertRequest": {
|
|
895
|
+
"type": "object",
|
|
896
|
+
"additionalProperties": false,
|
|
897
|
+
"properties": {
|
|
898
|
+
"domain": {
|
|
899
|
+
"type": "string",
|
|
900
|
+
"description": "Domain name owned by the API key user."
|
|
901
|
+
},
|
|
902
|
+
"name": {
|
|
903
|
+
"type": "string",
|
|
904
|
+
"description": "Template name/id."
|
|
905
|
+
},
|
|
906
|
+
"template": {
|
|
907
|
+
"type": "string",
|
|
908
|
+
"description": "Nunjucks template content."
|
|
909
|
+
},
|
|
910
|
+
"sender": {
|
|
911
|
+
"type": "string",
|
|
912
|
+
"default": ""
|
|
913
|
+
},
|
|
914
|
+
"subject": {
|
|
915
|
+
"type": "string",
|
|
916
|
+
"default": ""
|
|
917
|
+
},
|
|
918
|
+
"locale": {
|
|
919
|
+
"type": "string",
|
|
920
|
+
"default": ""
|
|
921
|
+
}
|
|
922
|
+
},
|
|
923
|
+
"required": ["domain", "name", "template"]
|
|
924
|
+
},
|
|
925
|
+
"TxSendRequest": {
|
|
926
|
+
"type": "object",
|
|
927
|
+
"properties": {
|
|
928
|
+
"domain": {
|
|
929
|
+
"type": "string"
|
|
930
|
+
},
|
|
931
|
+
"name": {
|
|
932
|
+
"type": "string",
|
|
933
|
+
"description": "Template name."
|
|
934
|
+
},
|
|
935
|
+
"rcpt": {
|
|
936
|
+
"type": "string",
|
|
937
|
+
"description": "Comma-separated recipient emails."
|
|
938
|
+
},
|
|
939
|
+
"locale": {
|
|
940
|
+
"type": "string",
|
|
941
|
+
"default": ""
|
|
942
|
+
},
|
|
943
|
+
"vars": {
|
|
944
|
+
"description": "Vars object or a JSON string.",
|
|
945
|
+
"oneOf": [
|
|
946
|
+
{
|
|
947
|
+
"type": "object"
|
|
948
|
+
},
|
|
949
|
+
{
|
|
950
|
+
"type": "string"
|
|
951
|
+
}
|
|
952
|
+
]
|
|
953
|
+
},
|
|
954
|
+
"subject": {
|
|
955
|
+
"type": "string",
|
|
956
|
+
"description": "Optional override when the stored template has no subject."
|
|
957
|
+
},
|
|
958
|
+
"replyTo": {
|
|
959
|
+
"type": "string"
|
|
960
|
+
},
|
|
961
|
+
"reply_to": {
|
|
962
|
+
"type": "string"
|
|
963
|
+
},
|
|
964
|
+
"headers": {
|
|
965
|
+
"type": "object",
|
|
966
|
+
"additionalProperties": {
|
|
967
|
+
"type": "string"
|
|
968
|
+
},
|
|
969
|
+
"description": "Custom email headers."
|
|
970
|
+
}
|
|
971
|
+
},
|
|
972
|
+
"required": ["domain", "name", "rcpt"]
|
|
973
|
+
},
|
|
974
|
+
"TxSendMultipartRequest": {
|
|
975
|
+
"type": "object",
|
|
976
|
+
"description": "Multipart version of TxSendRequest. Attach files in any multipart field; `files` is a conventional field name.",
|
|
977
|
+
"properties": {
|
|
978
|
+
"domain": {
|
|
979
|
+
"type": "string"
|
|
980
|
+
},
|
|
981
|
+
"name": {
|
|
982
|
+
"type": "string"
|
|
983
|
+
},
|
|
984
|
+
"rcpt": {
|
|
985
|
+
"type": "string"
|
|
986
|
+
},
|
|
987
|
+
"locale": {
|
|
988
|
+
"type": "string"
|
|
989
|
+
},
|
|
990
|
+
"vars": {
|
|
991
|
+
"type": "string",
|
|
992
|
+
"description": "JSON string."
|
|
993
|
+
},
|
|
994
|
+
"subject": {
|
|
995
|
+
"type": "string"
|
|
996
|
+
},
|
|
997
|
+
"replyTo": {
|
|
998
|
+
"type": "string"
|
|
999
|
+
},
|
|
1000
|
+
"reply_to": {
|
|
1001
|
+
"type": "string"
|
|
1002
|
+
},
|
|
1003
|
+
"headers": {
|
|
1004
|
+
"type": "string",
|
|
1005
|
+
"description": "If provided, should be a JSON string object of headers."
|
|
1006
|
+
},
|
|
1007
|
+
"files": {
|
|
1008
|
+
"type": "array",
|
|
1009
|
+
"items": {
|
|
1010
|
+
"type": "string",
|
|
1011
|
+
"format": "binary"
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
},
|
|
1015
|
+
"required": ["domain", "name", "rcpt"]
|
|
1016
|
+
},
|
|
1017
|
+
"TxSendResponseData": {
|
|
1018
|
+
"type": "object",
|
|
1019
|
+
"properties": {
|
|
1020
|
+
"Status": {
|
|
1021
|
+
"type": "string",
|
|
1022
|
+
"examples": ["OK"]
|
|
1023
|
+
},
|
|
1024
|
+
"Message": {
|
|
1025
|
+
"type": "string"
|
|
1026
|
+
}
|
|
1027
|
+
},
|
|
1028
|
+
"required": ["Status"]
|
|
1029
|
+
},
|
|
1030
|
+
"FormRecipientUpsertRequest": {
|
|
1031
|
+
"type": "object",
|
|
1032
|
+
"properties": {
|
|
1033
|
+
"domain": {
|
|
1034
|
+
"type": "string"
|
|
1035
|
+
},
|
|
1036
|
+
"idname": {
|
|
1037
|
+
"type": "string",
|
|
1038
|
+
"description": "Recipient identifier (slug-like)."
|
|
1039
|
+
},
|
|
1040
|
+
"email": {
|
|
1041
|
+
"type": "string"
|
|
1042
|
+
},
|
|
1043
|
+
"name": {
|
|
1044
|
+
"type": "string"
|
|
1045
|
+
},
|
|
1046
|
+
"form_key": {
|
|
1047
|
+
"type": "string"
|
|
1048
|
+
},
|
|
1049
|
+
"formid": {
|
|
1050
|
+
"type": "string"
|
|
1051
|
+
},
|
|
1052
|
+
"locale": {
|
|
1053
|
+
"type": "string"
|
|
1054
|
+
}
|
|
1055
|
+
},
|
|
1056
|
+
"required": ["domain", "idname", "email"]
|
|
1057
|
+
},
|
|
1058
|
+
"FormRecipientUpsertResponseData": {
|
|
1059
|
+
"type": "object",
|
|
1060
|
+
"properties": {
|
|
1061
|
+
"Status": {
|
|
1062
|
+
"type": "string",
|
|
1063
|
+
"examples": ["OK"]
|
|
1064
|
+
},
|
|
1065
|
+
"created": {
|
|
1066
|
+
"type": "boolean"
|
|
1067
|
+
},
|
|
1068
|
+
"form_key": {
|
|
1069
|
+
"type": "string"
|
|
1070
|
+
}
|
|
1071
|
+
},
|
|
1072
|
+
"required": ["Status", "created", "form_key"]
|
|
1073
|
+
},
|
|
1074
|
+
"FormTemplateUpsertRequest": {
|
|
1075
|
+
"type": "object",
|
|
1076
|
+
"properties": {
|
|
1077
|
+
"domain": {
|
|
1078
|
+
"type": "string"
|
|
1079
|
+
},
|
|
1080
|
+
"idname": {
|
|
1081
|
+
"type": "string",
|
|
1082
|
+
"description": "Form identifier."
|
|
1083
|
+
},
|
|
1084
|
+
"template": {
|
|
1085
|
+
"type": "string",
|
|
1086
|
+
"description": "Nunjucks template."
|
|
1087
|
+
},
|
|
1088
|
+
"sender": {
|
|
1089
|
+
"type": "string"
|
|
1090
|
+
},
|
|
1091
|
+
"recipient": {
|
|
1092
|
+
"type": "string"
|
|
1093
|
+
},
|
|
1094
|
+
"subject": {
|
|
1095
|
+
"type": "string",
|
|
1096
|
+
"default": ""
|
|
1097
|
+
},
|
|
1098
|
+
"locale": {
|
|
1099
|
+
"type": "string",
|
|
1100
|
+
"default": ""
|
|
1101
|
+
},
|
|
1102
|
+
"secret": {
|
|
1103
|
+
"type": "string",
|
|
1104
|
+
"default": ""
|
|
1105
|
+
},
|
|
1106
|
+
"replyto_email": {
|
|
1107
|
+
"type": "string",
|
|
1108
|
+
"default": "",
|
|
1109
|
+
"description": "Optional forced Reply-To value (email address or mailbox). Used when replyto_from_fields is false, or as a fallback when replyto_from_fields is true but extraction fails."
|
|
1110
|
+
},
|
|
1111
|
+
"replyto_from_fields": {
|
|
1112
|
+
"type": "boolean",
|
|
1113
|
+
"default": false,
|
|
1114
|
+
"description": "When true, attempt to derive Reply-To from submitted fields (email + name/first_name/last_name). If extraction fails and replyto_email is set, replyto_email is used."
|
|
1115
|
+
},
|
|
1116
|
+
"allowed_fields": {
|
|
1117
|
+
"description": "Optional allowlist of field names that will be exposed to the form template as `_fields_`. When omitted or empty, all non-system fields are exposed.",
|
|
1118
|
+
"oneOf": [
|
|
1119
|
+
{
|
|
1120
|
+
"type": "array",
|
|
1121
|
+
"items": {
|
|
1122
|
+
"type": "string"
|
|
1123
|
+
}
|
|
1124
|
+
},
|
|
1125
|
+
{
|
|
1126
|
+
"type": "string"
|
|
1127
|
+
}
|
|
1128
|
+
]
|
|
1129
|
+
},
|
|
1130
|
+
"captcha_required": {
|
|
1131
|
+
"type": "boolean"
|
|
1132
|
+
}
|
|
1133
|
+
},
|
|
1134
|
+
"required": ["domain", "idname", "template", "sender", "recipient"]
|
|
1135
|
+
},
|
|
1136
|
+
"FormTemplateUpsertResponseData": {
|
|
1137
|
+
"type": "object",
|
|
1138
|
+
"properties": {
|
|
1139
|
+
"Status": {
|
|
1140
|
+
"type": "string",
|
|
1141
|
+
"examples": ["OK"]
|
|
1142
|
+
},
|
|
1143
|
+
"created": {
|
|
1144
|
+
"type": "boolean"
|
|
1145
|
+
},
|
|
1146
|
+
"form_key": {
|
|
1147
|
+
"type": "string"
|
|
1148
|
+
}
|
|
1149
|
+
},
|
|
1150
|
+
"required": ["Status", "created", "form_key"]
|
|
1151
|
+
},
|
|
1152
|
+
"FormMessageRequest": {
|
|
1153
|
+
"type": "object",
|
|
1154
|
+
"description": "Public form submission payload. Requires _mm_form_key. This endpoint accepts arbitrary extra fields which are exposed to templates as `_fields_`.",
|
|
1155
|
+
"properties": {
|
|
1156
|
+
"_mm_form_key": {
|
|
1157
|
+
"type": "string",
|
|
1158
|
+
"description": "Required. Canonical form identifier."
|
|
1159
|
+
},
|
|
1160
|
+
"_mm_locale": {
|
|
1161
|
+
"type": "string"
|
|
1162
|
+
},
|
|
1163
|
+
"_mm_recipients": {
|
|
1164
|
+
"description": "Optional list of recipient idnames to route this message to. If omitted, the stored form default recipient is used.",
|
|
1165
|
+
"oneOf": [
|
|
1166
|
+
{
|
|
1167
|
+
"type": "array",
|
|
1168
|
+
"items": {
|
|
1169
|
+
"type": "string"
|
|
1170
|
+
}
|
|
1171
|
+
},
|
|
1172
|
+
{
|
|
1173
|
+
"type": "string"
|
|
1174
|
+
}
|
|
1175
|
+
]
|
|
1176
|
+
},
|
|
1177
|
+
"email": {
|
|
1178
|
+
"type": "string",
|
|
1179
|
+
"description": "Optional submitter email used to derive the email Reply-To header."
|
|
1180
|
+
},
|
|
1181
|
+
"name": {
|
|
1182
|
+
"type": "string",
|
|
1183
|
+
"description": "Optional submitter name used to derive Reply-To when present alongside email."
|
|
1184
|
+
},
|
|
1185
|
+
"first_name": {
|
|
1186
|
+
"type": "string",
|
|
1187
|
+
"description": "Optional submitter first name used to derive Reply-To when present alongside email."
|
|
1188
|
+
},
|
|
1189
|
+
"last_name": {
|
|
1190
|
+
"type": "string",
|
|
1191
|
+
"description": "Optional submitter last name used to derive Reply-To when present alongside email."
|
|
1192
|
+
},
|
|
1193
|
+
"_mm_file1": {
|
|
1194
|
+
"type": "string",
|
|
1195
|
+
"format": "binary",
|
|
1196
|
+
"description": "Attachment fields must be named _mm_file* when using multipart/form-data."
|
|
1197
|
+
},
|
|
1198
|
+
"cf-turnstile-response": {
|
|
1199
|
+
"type": "string",
|
|
1200
|
+
"description": "Cloudflare Turnstile token (accepted as-is)."
|
|
1201
|
+
},
|
|
1202
|
+
"h-captcha-response": {
|
|
1203
|
+
"type": "string",
|
|
1204
|
+
"description": "hCaptcha token (accepted as-is)."
|
|
1205
|
+
},
|
|
1206
|
+
"g-recaptcha-response": {
|
|
1207
|
+
"type": "string",
|
|
1208
|
+
"description": "Google reCAPTCHA token (accepted as-is)."
|
|
1209
|
+
},
|
|
1210
|
+
"captcha": {
|
|
1211
|
+
"type": "string",
|
|
1212
|
+
"description": "Generic/legacy captcha token (accepted as-is)."
|
|
1213
|
+
}
|
|
1214
|
+
},
|
|
1215
|
+
"required": ["_mm_form_key"],
|
|
1216
|
+
"additionalProperties": true
|
|
1217
|
+
},
|
|
1218
|
+
"FormMessageMultipartRequest": {
|
|
1219
|
+
"type": "object",
|
|
1220
|
+
"description": "Multipart version of FormMessageRequest. Attachment field names must start with `_mm_file` (e.g. `_mm_file1`).",
|
|
1221
|
+
"properties": {
|
|
1222
|
+
"_mm_form_key": {
|
|
1223
|
+
"type": "string"
|
|
1224
|
+
},
|
|
1225
|
+
"_mm_locale": {
|
|
1226
|
+
"type": "string"
|
|
1227
|
+
},
|
|
1228
|
+
"_mm_recipients": {
|
|
1229
|
+
"type": "string"
|
|
1230
|
+
},
|
|
1231
|
+
"email": {
|
|
1232
|
+
"type": "string"
|
|
1233
|
+
},
|
|
1234
|
+
"name": {
|
|
1235
|
+
"type": "string"
|
|
1236
|
+
},
|
|
1237
|
+
"first_name": {
|
|
1238
|
+
"type": "string"
|
|
1239
|
+
},
|
|
1240
|
+
"last_name": {
|
|
1241
|
+
"type": "string"
|
|
1242
|
+
},
|
|
1243
|
+
"_mm_file1": {
|
|
1244
|
+
"type": "string",
|
|
1245
|
+
"format": "binary"
|
|
1246
|
+
},
|
|
1247
|
+
"cf-turnstile-response": {
|
|
1248
|
+
"type": "string"
|
|
1249
|
+
},
|
|
1250
|
+
"h-captcha-response": {
|
|
1251
|
+
"type": "string"
|
|
1252
|
+
},
|
|
1253
|
+
"g-recaptcha-response": {
|
|
1254
|
+
"type": "string"
|
|
1255
|
+
},
|
|
1256
|
+
"captcha": {
|
|
1257
|
+
"type": "string"
|
|
1258
|
+
}
|
|
1259
|
+
},
|
|
1260
|
+
"required": ["_mm_form_key"],
|
|
1261
|
+
"additionalProperties": true
|
|
1262
|
+
},
|
|
1263
|
+
"FormMessageResponseData": {
|
|
1264
|
+
"type": "object",
|
|
1265
|
+
"description": "On success, data is usually an empty object. Some internal failures may return an object with an `error` string.",
|
|
1266
|
+
"additionalProperties": true
|
|
1267
|
+
},
|
|
1268
|
+
"AssetsUploadMultipartRequest": {
|
|
1269
|
+
"type": "object",
|
|
1270
|
+
"properties": {
|
|
1271
|
+
"domain": {
|
|
1272
|
+
"type": "string"
|
|
1273
|
+
},
|
|
1274
|
+
"path": {
|
|
1275
|
+
"type": "string",
|
|
1276
|
+
"description": "Optional subdirectory under assets root."
|
|
1277
|
+
},
|
|
1278
|
+
"dir": {
|
|
1279
|
+
"type": "string",
|
|
1280
|
+
"description": "Alias for path."
|
|
1281
|
+
},
|
|
1282
|
+
"templateType": {
|
|
1283
|
+
"type": "string",
|
|
1284
|
+
"description": "If set, upload to a template directory. Valid values: tx, form."
|
|
1285
|
+
},
|
|
1286
|
+
"template_type": {
|
|
1287
|
+
"type": "string"
|
|
1288
|
+
},
|
|
1289
|
+
"type": {
|
|
1290
|
+
"type": "string"
|
|
1291
|
+
},
|
|
1292
|
+
"template": {
|
|
1293
|
+
"type": "string",
|
|
1294
|
+
"description": "Template name/id (transactional) or form idname (form)."
|
|
1295
|
+
},
|
|
1296
|
+
"name": {
|
|
1297
|
+
"type": "string"
|
|
1298
|
+
},
|
|
1299
|
+
"idname": {
|
|
1300
|
+
"type": "string"
|
|
1301
|
+
},
|
|
1302
|
+
"formid": {
|
|
1303
|
+
"type": "string"
|
|
1304
|
+
},
|
|
1305
|
+
"locale": {
|
|
1306
|
+
"type": "string"
|
|
1307
|
+
},
|
|
1308
|
+
"files": {
|
|
1309
|
+
"type": "array",
|
|
1310
|
+
"items": {
|
|
1311
|
+
"type": "string",
|
|
1312
|
+
"format": "binary"
|
|
1313
|
+
},
|
|
1314
|
+
"minItems": 1
|
|
1315
|
+
}
|
|
1316
|
+
},
|
|
1317
|
+
"required": ["domain", "files"]
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1321
|
+
}
|