@jinshuju/mcp 0.0.0-stage → 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.
@@ -0,0 +1,3996 @@
1
+ {
2
+ "listForms": {
3
+ "operationId": "listForms",
4
+ "summary": "List forms",
5
+ "description": "Returns the forms visible to the current identity (`kind=form`, excluding tables and quick payment forms). A personal token returns the forms the user created and those shared with them; an account token returns every form in the account.\nBy default sorted by id descending (that is, by creation time descending), and `next` is the id of the first row of the next page; when `sort` is passed, rows are sorted by the given field and `next` becomes `row:<offset>`.\n50 per page by default, adjustable with `limit` (max 1000).\n- Each row carries `entries_count` (entry count) and `last_entry_created_at` (when the last entry was received), usable with `filters` / `sort`.\n- With `include_transactions=true`, forms bound to a payment account carry `transactions` payment statistics.",
6
+ "tag": "Forms",
7
+ "method": "get",
8
+ "path": "/forms",
9
+ "params": [
10
+ {
11
+ "name": "q",
12
+ "in": "query",
13
+ "required": false
14
+ },
15
+ {
16
+ "name": "filters",
17
+ "in": "query",
18
+ "required": false
19
+ },
20
+ {
21
+ "name": "sort",
22
+ "in": "query",
23
+ "required": false
24
+ },
25
+ {
26
+ "name": "next",
27
+ "in": "query",
28
+ "required": false
29
+ },
30
+ {
31
+ "name": "skip",
32
+ "in": "query",
33
+ "required": false
34
+ },
35
+ {
36
+ "name": "limit",
37
+ "in": "query",
38
+ "required": false
39
+ },
40
+ {
41
+ "name": "include_transactions",
42
+ "in": "query",
43
+ "required": false
44
+ }
45
+ ],
46
+ "paramNames": [
47
+ "q",
48
+ "filters",
49
+ "sort",
50
+ "next",
51
+ "skip",
52
+ "limit",
53
+ "include_transactions"
54
+ ],
55
+ "successStatus": 200,
56
+ "scopes": [
57
+ "forms"
58
+ ],
59
+ "responseSchema": "FormListResponse"
60
+ },
61
+ "createForm": {
62
+ "operationId": "createForm",
63
+ "summary": "Create a form",
64
+ "description": "Creates a form from a list of field definitions and returns the full form structure. `name` and `fields` are required.\n- `scene` sets the form's scene; exam / evaluation question types (such as `SingleSelect`, `FillInBlank`) can only be used in the scenes that support them.\n- `layout=card` (paged) does not support PageBreak, Matrix*, TableField, GoodsField, ESignatureField, FormAssociation, MultipleBlanksField or any kind of Widget field.\n- The folder named by `folder_token` must be manageable and of kind form; otherwise returns 404 / 400 respectively.\n- `setting` accepts only whitelisted keys (see `FormSettingWriteInput`); `setting.notification_rules` replaces, as a whole, the notification rules created through the API.\n- The returned form structure carries `url` (the public fill URL).",
65
+ "tag": "Forms",
66
+ "method": "post",
67
+ "path": "/forms",
68
+ "params": [],
69
+ "paramNames": [],
70
+ "body": {
71
+ "contentType": "application/json",
72
+ "required": true,
73
+ "flatten": true
74
+ },
75
+ "successStatus": 201,
76
+ "scopes": [
77
+ "forms"
78
+ ],
79
+ "responseSchema": "Form"
80
+ },
81
+ "getForm": {
82
+ "operationId": "getForm",
83
+ "summary": "Show a form's structure",
84
+ "description": "Returns the form's name, public fill URL (`url`), description, field definitions and settings. Each element of `fields` is a single-key object `{ \"<api_code>\": {...} }`, in field order.\nThe following are included when the matching parameter is `true`:\n- `include_analytics`: each analysable field's definition carries `analytics`;\n- `include_theme`: carries `theme` (the form theme);\n- `include_field_rules`: carries `field_rules` (field display rules);\n- `include_extended_attributes`: carries `extended_attributes` (source-tracking links);\n- `include_transactions`: carries `transactions` (payment statistics) when the form is bound to a payment account.",
85
+ "tag": "Forms",
86
+ "method": "get",
87
+ "path": "/forms/{form_token}",
88
+ "params": [
89
+ {
90
+ "name": "form_token",
91
+ "in": "path",
92
+ "required": true
93
+ },
94
+ {
95
+ "name": "include_analytics",
96
+ "in": "query",
97
+ "required": false
98
+ },
99
+ {
100
+ "name": "include_theme",
101
+ "in": "query",
102
+ "required": false
103
+ },
104
+ {
105
+ "name": "include_field_rules",
106
+ "in": "query",
107
+ "required": false
108
+ },
109
+ {
110
+ "name": "include_extended_attributes",
111
+ "in": "query",
112
+ "required": false
113
+ },
114
+ {
115
+ "name": "include_transactions",
116
+ "in": "query",
117
+ "required": false
118
+ }
119
+ ],
120
+ "paramNames": [
121
+ "form_token",
122
+ "include_analytics",
123
+ "include_theme",
124
+ "include_field_rules",
125
+ "include_extended_attributes",
126
+ "include_transactions"
127
+ ],
128
+ "successStatus": 200,
129
+ "scopes": [
130
+ "forms"
131
+ ],
132
+ "responseSchema": "FormDetail"
133
+ },
134
+ "createEntryLegacy": {
135
+ "operationId": "createEntryLegacy",
136
+ "summary": "Create an entry (legacy path)",
137
+ "description": "Legacy alias of `POST /forms/{form_token}/entries`, with identical behavior. New integrations should use the new path.",
138
+ "tag": "Entries",
139
+ "method": "post",
140
+ "path": "/forms/{form_token}",
141
+ "params": [
142
+ {
143
+ "name": "form_token",
144
+ "in": "path",
145
+ "required": true
146
+ }
147
+ ],
148
+ "paramNames": [
149
+ "form_token"
150
+ ],
151
+ "body": {
152
+ "contentType": "application/json",
153
+ "required": true,
154
+ "flatten": false,
155
+ "param": "body"
156
+ },
157
+ "successStatus": 201,
158
+ "scopes": [
159
+ "write_entries"
160
+ ],
161
+ "responseSchema": "Entry"
162
+ },
163
+ "updateForm": {
164
+ "operationId": "updateForm",
165
+ "summary": "Edit a form",
166
+ "description": "Edits a form partially; also accepts `PUT`. The request body must contain at least one of `name` / `description` / `fields` / `setting` / `field_rules`, otherwise returns 400.\n- `fields` is changed incrementally through four kinds of operation, `add` / `remove` / `update` / `update_choices`; fields, choices and api_codes not mentioned are all kept;\n `update[].type` changes a field's type in place, and a change that clears entry data must carry `confirm_data_loss: true`.\n- `field_rules` does `add` / `remove` / `update` on rules located by the `index` that `GET /forms/{form_token}/field_rules` returns.\n- `setting`, as on create, accepts only whitelisted keys.\nReturns the full updated form structure.",
167
+ "tag": "Forms",
168
+ "method": "patch",
169
+ "path": "/forms/{form_token}",
170
+ "params": [
171
+ {
172
+ "name": "form_token",
173
+ "in": "path",
174
+ "required": true
175
+ }
176
+ ],
177
+ "paramNames": [
178
+ "form_token"
179
+ ],
180
+ "body": {
181
+ "contentType": "application/json",
182
+ "required": true,
183
+ "flatten": true
184
+ },
185
+ "successStatus": 200,
186
+ "scopes": [
187
+ "forms"
188
+ ],
189
+ "responseSchema": "Form"
190
+ },
191
+ "checkFormFieldData": {
192
+ "operationId": "checkFormFieldData",
193
+ "summary": "Check whether fields already hold data",
194
+ "description": "Use before deleting a field or choice: checks in batch whether fields (or single choices of a field) already have submitted entries. Deleting a field or choice that still has entries deletes those entries with it, and they cannot be recovered.\nMatches the check the web editor runs before deleting.\n- Put every deletion target of one edit in the `checks` of a single call (at most 100, may span several fields); `results` matches `checks` one to one, in order.\n- When a target cannot be checked (for example, the field does not exist), its row returns `unavailable` with the reason; the other targets return as usual.\n- Returns 400 when `checks` is missing, empty, over 100, not a JSON array, or has an item that is not an object.",
195
+ "tag": "Forms",
196
+ "method": "get",
197
+ "path": "/forms/{form_token}/fields/check",
198
+ "params": [
199
+ {
200
+ "name": "form_token",
201
+ "in": "path",
202
+ "required": true
203
+ },
204
+ {
205
+ "name": "checks",
206
+ "in": "query",
207
+ "required": true
208
+ }
209
+ ],
210
+ "paramNames": [
211
+ "form_token",
212
+ "checks"
213
+ ],
214
+ "successStatus": 200,
215
+ "scopes": [
216
+ "forms"
217
+ ],
218
+ "responseSchema": "FieldDataCheckResponse"
219
+ },
220
+ "previewFormFieldTypeChange": {
221
+ "operationId": "previewFormFieldTypeChange",
222
+ "summary": "Preview a field type change",
223
+ "description": "Use before changing a field's type (the field's `type` in PATCH /forms/{form_token}): changes no data, and counts, from the field's current entries, how many would be kept and how many cleared after the conversion.\nThe conversion happens on the original field (api_code and data column unchanged), so only entry data is affected; matches the preview the web editor shows before converting.\n- Put every conversion of one edit in the `checks` of a single call (at most 20); `results` matches `checks` one to one, in order.\n- `supported=false` means the field cannot be converted to the target type, and the actual edit is refused too.\n- When converting multi-line text to a choice field such as single choice / multiple choice, also returns `choice_count`, the number of choices that would be generated from existing entries, and `choice_limit_exceeded`, whether that exceeds the choice limit (when it does, the conversion is refused rather than truncated).\n- When an item cannot be previewed (the field does not exist, `target_type` is not a type available to this form, etc.), its row returns `unavailable` with the reason; the other items return as usual.\n- Returns 400 when `checks` is missing, empty, over 20, not a JSON array, or has an item that is not an object.",
224
+ "tag": "Forms",
225
+ "method": "get",
226
+ "path": "/forms/{form_token}/fields/preview_convert",
227
+ "params": [
228
+ {
229
+ "name": "form_token",
230
+ "in": "path",
231
+ "required": true
232
+ },
233
+ {
234
+ "name": "checks",
235
+ "in": "query",
236
+ "required": true
237
+ }
238
+ ],
239
+ "paramNames": [
240
+ "form_token",
241
+ "checks"
242
+ ],
243
+ "successStatus": 200,
244
+ "scopes": [
245
+ "forms"
246
+ ],
247
+ "responseSchema": "FieldTypeChangePreviewResponse"
248
+ },
249
+ "listEntries": {
250
+ "operationId": "listEntries",
251
+ "summary": "List entries",
252
+ "description": "Returns form entries page by page, 50 per page by default, set with `limit` (max 1000). Sorted by serial number ascending by default; `next` is the serial number of the first entry of the next page.\n- `filters` / `keyword` trigger a conditional query; `created_at` returns only entries created at or after that time (and sorts by creation time instead);\n in both these cases, and when `sort` is passed, `next` becomes a row offset.\n- `fields` returns only the given fields (the serial number is always returned).\n- Each entry is keyed by field api_code (a field with api_code_alias set is keyed by its alias); for the value shapes see `EntryData`.",
253
+ "tag": "Entries",
254
+ "method": "get",
255
+ "path": "/forms/{form_token}/entries",
256
+ "params": [
257
+ {
258
+ "name": "form_token",
259
+ "in": "path",
260
+ "required": true
261
+ },
262
+ {
263
+ "name": "fields",
264
+ "in": "query",
265
+ "required": false
266
+ },
267
+ {
268
+ "name": "filters",
269
+ "in": "query",
270
+ "required": false
271
+ },
272
+ {
273
+ "name": "keyword",
274
+ "in": "query",
275
+ "required": false
276
+ },
277
+ {
278
+ "name": "sort",
279
+ "in": "query",
280
+ "required": false
281
+ },
282
+ {
283
+ "name": "created_at",
284
+ "in": "query",
285
+ "required": false
286
+ },
287
+ {
288
+ "name": "next",
289
+ "in": "query",
290
+ "required": false
291
+ },
292
+ {
293
+ "name": "skip",
294
+ "in": "query",
295
+ "required": false
296
+ },
297
+ {
298
+ "name": "include_labels",
299
+ "in": "query",
300
+ "required": false
301
+ },
302
+ {
303
+ "name": "limit",
304
+ "in": "query",
305
+ "required": false
306
+ }
307
+ ],
308
+ "paramNames": [
309
+ "form_token",
310
+ "fields",
311
+ "filters",
312
+ "keyword",
313
+ "sort",
314
+ "created_at",
315
+ "next",
316
+ "skip",
317
+ "include_labels",
318
+ "limit"
319
+ ],
320
+ "successStatus": 200,
321
+ "scopes": [
322
+ "read_entries"
323
+ ],
324
+ "responseSchema": "EntryListResponse"
325
+ },
326
+ "createEntry": {
327
+ "operationId": "createEntry",
328
+ "summary": "Create an entry",
329
+ "description": "Submits one entry keyed by field api_code (or api_code_alias). Unknown keys are ignored; when no valid key remains, returns 400, with `error_description` starting with `Entry attributes cannot be empty` and naming each dropped key (not a field of this form, or a signature / calculated field that cannot be written).\n- The form's field display rules and field validation still apply; a validation failure returns 400, and `error_description` is `{ \"<api_code>\": [\"error\"] }` serialized as a JSON string.\n- Mobile fields skip SMS verification; signature fields and calculated fields cannot be written.\n- Returns 403 when the form's entry count has reached the plan limit.\n- Attachment fields accept several forms of input; see `EntryInput`.",
330
+ "tag": "Entries",
331
+ "method": "post",
332
+ "path": "/forms/{form_token}/entries",
333
+ "params": [
334
+ {
335
+ "name": "form_token",
336
+ "in": "path",
337
+ "required": true
338
+ }
339
+ ],
340
+ "paramNames": [
341
+ "form_token"
342
+ ],
343
+ "body": {
344
+ "contentType": "application/json",
345
+ "required": true,
346
+ "flatten": false,
347
+ "param": "body"
348
+ },
349
+ "successStatus": 201,
350
+ "scopes": [
351
+ "write_entries"
352
+ ],
353
+ "responseSchema": "Entry"
354
+ },
355
+ "countEntries": {
356
+ "operationId": "countEntries",
357
+ "summary": "Count entries",
358
+ "description": "Returns the number of entries matching the filters, without the entries themselves. `filters` / `keyword` are the same as for `GET /forms/{form_token}/entries`; with neither, returns the total entry count of the form.\nA cooperator counts only the entries visible to their role.",
359
+ "tag": "Entries",
360
+ "method": "get",
361
+ "path": "/forms/{form_token}/entries/count",
362
+ "params": [
363
+ {
364
+ "name": "form_token",
365
+ "in": "path",
366
+ "required": true
367
+ },
368
+ {
369
+ "name": "filters",
370
+ "in": "query",
371
+ "required": false
372
+ },
373
+ {
374
+ "name": "keyword",
375
+ "in": "query",
376
+ "required": false
377
+ }
378
+ ],
379
+ "paramNames": [
380
+ "form_token",
381
+ "filters",
382
+ "keyword"
383
+ ],
384
+ "successStatus": 200,
385
+ "scopes": [
386
+ "read_entries"
387
+ ],
388
+ "responseSchema": "EntryCountResponse"
389
+ },
390
+ "aggregateEntries": {
391
+ "operationId": "aggregateEntries",
392
+ "summary": "Aggregate entries",
393
+ "description": "Aggregates whole columns on the server over the entries matching the filters (sum, average, count, percentiles, etc.), optionally grouped by 1 to 2 fields. The response size depends only on the number of metrics and groups, not on the amount of data.\n- `metrics` is required, 1 to 20 items; the functions each field takes are in the `analytics.agg_funcs` returned by `GET /forms/{form_token}?include_analytics=true`.\n- `dimensions` is optional, at most 2 items; only fields whose `analytics.groupable` is true (single-value choice fields and date fields) can be grouped by, and a date field must specify `bucket`.\n- Without `dimensions`, `rows` has a single row; when grouped, one row per group, at most `limit` groups; `row_count` is the total number of groups, and `truncated` is true when there are more.\n- `filters` / `keyword` are the same as for the entry list, but `creator_id`, `serial_number` and association field conditions are not supported (returns 400).\n- Returns 400 when a field does not exist or is not readable by the caller, or a function or grouping does not apply to the field, and says which fields / functions / groupings are available.",
394
+ "tag": "Entries",
395
+ "method": "get",
396
+ "path": "/forms/{form_token}/entries/aggregate",
397
+ "params": [
398
+ {
399
+ "name": "form_token",
400
+ "in": "path",
401
+ "required": true
402
+ },
403
+ {
404
+ "name": "metrics",
405
+ "in": "query",
406
+ "required": false
407
+ },
408
+ {
409
+ "name": "dimensions",
410
+ "in": "query",
411
+ "required": false
412
+ },
413
+ {
414
+ "name": "limit",
415
+ "in": "query",
416
+ "required": false
417
+ },
418
+ {
419
+ "name": "filters",
420
+ "in": "query",
421
+ "required": false
422
+ },
423
+ {
424
+ "name": "keyword",
425
+ "in": "query",
426
+ "required": false
427
+ }
428
+ ],
429
+ "paramNames": [
430
+ "form_token",
431
+ "metrics",
432
+ "dimensions",
433
+ "limit",
434
+ "filters",
435
+ "keyword"
436
+ ],
437
+ "successStatus": 200,
438
+ "scopes": [
439
+ "read_entries"
440
+ ],
441
+ "responseSchema": "EntryAggregateResponse"
442
+ },
443
+ "summarizeEntries": {
444
+ "operationId": "summarizeEntries",
445
+ "summary": "Summarize entries",
446
+ "description": "Reads an overall summary of the form's entries in one call: an overview (matching count, added today) plus the distribution or numeric statistics of each analysable field. The response is only a few KB, regardless of the amount of data.\n- Each field returns a uniform structure by `kind`: choice fields give each choice's count and share, matrix fields are grouped by question, numbers give min / max / sum / average, dates give earliest / latest, text gives the distinct count.\n- By default includes every analysable field (fields whose `analytics.summarisable` is true, plus `created_at`), at most 60; fields beyond that are listed in `omitted_fields`, and `truncated` is true.\n- Returns 400 when a field named in `fields` is not analysable or not readable by the caller.\n- `filters` / `keyword` are the same as for the entry list, but `creator_id`, `serial_number` and association field conditions are not supported (returns 400).",
447
+ "tag": "Entries",
448
+ "method": "get",
449
+ "path": "/forms/{form_token}/entries/summary",
450
+ "params": [
451
+ {
452
+ "name": "form_token",
453
+ "in": "path",
454
+ "required": true
455
+ },
456
+ {
457
+ "name": "fields",
458
+ "in": "query",
459
+ "required": false
460
+ },
461
+ {
462
+ "name": "include_overview",
463
+ "in": "query",
464
+ "required": false
465
+ },
466
+ {
467
+ "name": "filters",
468
+ "in": "query",
469
+ "required": false
470
+ },
471
+ {
472
+ "name": "keyword",
473
+ "in": "query",
474
+ "required": false
475
+ }
476
+ ],
477
+ "paramNames": [
478
+ "form_token",
479
+ "fields",
480
+ "include_overview",
481
+ "filters",
482
+ "keyword"
483
+ ],
484
+ "successStatus": 200,
485
+ "scopes": [
486
+ "read_entries"
487
+ ],
488
+ "responseSchema": "EntrySummaryResponse"
489
+ },
490
+ "countFormViewEntries": {
491
+ "operationId": "countFormViewEntries",
492
+ "summary": "Count the entries of a view",
493
+ "description": "Same as `GET /forms/{form_token}/entries/count`, but only over the entries the view's filters select: the view's filters apply first, and `filters` / `keyword` narrow the range further on top of them. The view's columns and sort do not affect the result; a view with no filters is the same as the whole form.\nOnly views visible to the caller are accessible; otherwise 404 (View cannot be found).",
494
+ "tag": "Views",
495
+ "method": "get",
496
+ "path": "/forms/{form_token}/views/{view_token}/entries/count",
497
+ "params": [
498
+ {
499
+ "name": "form_token",
500
+ "in": "path",
501
+ "required": true
502
+ },
503
+ {
504
+ "name": "view_token",
505
+ "in": "path",
506
+ "required": true
507
+ },
508
+ {
509
+ "name": "filters",
510
+ "in": "query",
511
+ "required": false
512
+ },
513
+ {
514
+ "name": "keyword",
515
+ "in": "query",
516
+ "required": false
517
+ }
518
+ ],
519
+ "paramNames": [
520
+ "form_token",
521
+ "view_token",
522
+ "filters",
523
+ "keyword"
524
+ ],
525
+ "successStatus": 200,
526
+ "scopes": [
527
+ "read_entries"
528
+ ],
529
+ "responseSchema": "EntryCountResponse"
530
+ },
531
+ "aggregateFormViewEntries": {
532
+ "operationId": "aggregateFormViewEntries",
533
+ "summary": "Aggregate the entries of a view",
534
+ "description": "Same as `GET /forms/{form_token}/entries/aggregate`, but only over the entries the view's filters select: the view's filters apply first, and `filters` / `keyword` narrow the range further on top of them. The view's columns and sort do not affect the result; a view with no filters is the same as the whole form.\nOnly views visible to the caller are accessible; otherwise 404 (View cannot be found).",
535
+ "tag": "Views",
536
+ "method": "get",
537
+ "path": "/forms/{form_token}/views/{view_token}/entries/aggregate",
538
+ "params": [
539
+ {
540
+ "name": "form_token",
541
+ "in": "path",
542
+ "required": true
543
+ },
544
+ {
545
+ "name": "view_token",
546
+ "in": "path",
547
+ "required": true
548
+ },
549
+ {
550
+ "name": "metrics",
551
+ "in": "query",
552
+ "required": false
553
+ },
554
+ {
555
+ "name": "dimensions",
556
+ "in": "query",
557
+ "required": false
558
+ },
559
+ {
560
+ "name": "limit",
561
+ "in": "query",
562
+ "required": false
563
+ },
564
+ {
565
+ "name": "filters",
566
+ "in": "query",
567
+ "required": false
568
+ },
569
+ {
570
+ "name": "keyword",
571
+ "in": "query",
572
+ "required": false
573
+ }
574
+ ],
575
+ "paramNames": [
576
+ "form_token",
577
+ "view_token",
578
+ "metrics",
579
+ "dimensions",
580
+ "limit",
581
+ "filters",
582
+ "keyword"
583
+ ],
584
+ "successStatus": 200,
585
+ "scopes": [
586
+ "read_entries"
587
+ ],
588
+ "responseSchema": "EntryAggregateResponse"
589
+ },
590
+ "summarizeFormViewEntries": {
591
+ "operationId": "summarizeFormViewEntries",
592
+ "summary": "Summarize the entries of a view",
593
+ "description": "Same as `GET /forms/{form_token}/entries/summary`, but only over the entries the view's filters select: the view's filters apply first, and `filters` / `keyword` narrow the range further on top of them. The view's columns and sort do not affect the result; a view with no filters is the same as the whole form.\nOnly views visible to the caller are accessible; otherwise 404 (View cannot be found).",
594
+ "tag": "Views",
595
+ "method": "get",
596
+ "path": "/forms/{form_token}/views/{view_token}/entries/summary",
597
+ "params": [
598
+ {
599
+ "name": "form_token",
600
+ "in": "path",
601
+ "required": true
602
+ },
603
+ {
604
+ "name": "view_token",
605
+ "in": "path",
606
+ "required": true
607
+ },
608
+ {
609
+ "name": "fields",
610
+ "in": "query",
611
+ "required": false
612
+ },
613
+ {
614
+ "name": "include_overview",
615
+ "in": "query",
616
+ "required": false
617
+ },
618
+ {
619
+ "name": "filters",
620
+ "in": "query",
621
+ "required": false
622
+ },
623
+ {
624
+ "name": "keyword",
625
+ "in": "query",
626
+ "required": false
627
+ }
628
+ ],
629
+ "paramNames": [
630
+ "form_token",
631
+ "view_token",
632
+ "fields",
633
+ "include_overview",
634
+ "filters",
635
+ "keyword"
636
+ ],
637
+ "successStatus": 200,
638
+ "scopes": [
639
+ "read_entries"
640
+ ],
641
+ "responseSchema": "EntrySummaryResponse"
642
+ },
643
+ "createEntriesBatch": {
644
+ "operationId": "createEntriesBatch",
645
+ "summary": "Create entries in batch",
646
+ "description": "Submits up to 200 entries at a time. Each entry is validated on its own; valid ones are written in bulk, invalid ones are recorded in `errors` (`index` is the position in the request array).\nReturns 201 when at least one succeeds and 422 when all fail; returns 400 when `entries` is empty or has over 200 entries.\nBefore writing, the entry count limit is checked against the number of entries submitted; over the limit returns 403. A batch write does not trigger the callbacks of a single create, but creates one \"import\" activity record and backfills calculated fields.",
647
+ "tag": "Entries",
648
+ "method": "post",
649
+ "path": "/forms/{form_token}/entries/batch",
650
+ "params": [
651
+ {
652
+ "name": "form_token",
653
+ "in": "path",
654
+ "required": true
655
+ }
656
+ ],
657
+ "paramNames": [
658
+ "form_token"
659
+ ],
660
+ "body": {
661
+ "contentType": "application/json",
662
+ "required": true,
663
+ "flatten": true
664
+ },
665
+ "successStatus": 201,
666
+ "scopes": [
667
+ "write_entries"
668
+ ],
669
+ "responseSchema": "BatchCreateResult"
670
+ },
671
+ "patchEntriesBatch": {
672
+ "operationId": "patchEntriesBatch",
673
+ "summary": "Update entries in batch",
674
+ "description": "Partially updates entries in batch by serial number, up to 200 rows at a time. Each row requires `serial_number`; `entry` holds the fields to change (fields not mentioned stay unchanged).\nEach row is validated on its own; failed rows are recorded in `failed_rows` (`reason` is `invalid_serial_number` / `invalid_attributes`, etc.).\nReturns 200 when at least one row succeeds and 422 when all fail; returns 400 when `entries` is empty or has over 200 rows.\nBatch update does not handle the attachment lifecycle, so it **cannot write attachment fields** (including attachment columns inside table fields); update those one entry at a time.",
675
+ "tag": "Entries",
676
+ "method": "patch",
677
+ "path": "/forms/{form_token}/entries/batch",
678
+ "params": [
679
+ {
680
+ "name": "form_token",
681
+ "in": "path",
682
+ "required": true
683
+ }
684
+ ],
685
+ "paramNames": [
686
+ "form_token"
687
+ ],
688
+ "body": {
689
+ "contentType": "application/json",
690
+ "required": true,
691
+ "flatten": true
692
+ },
693
+ "successStatus": 200,
694
+ "scopes": [
695
+ "write_entries"
696
+ ],
697
+ "responseSchema": "BatchPatchResult"
698
+ },
699
+ "getEntry": {
700
+ "operationId": "getEntry",
701
+ "summary": "Show an entry",
702
+ "description": "Returns one entry by serial number. `fields` limits the fields returned.",
703
+ "tag": "Entries",
704
+ "method": "get",
705
+ "path": "/forms/{form_token}/entries/{serial_number}",
706
+ "params": [
707
+ {
708
+ "name": "form_token",
709
+ "in": "path",
710
+ "required": true
711
+ },
712
+ {
713
+ "name": "serial_number",
714
+ "in": "path",
715
+ "required": true
716
+ },
717
+ {
718
+ "name": "fields",
719
+ "in": "query",
720
+ "required": false
721
+ },
722
+ {
723
+ "name": "include_labels",
724
+ "in": "query",
725
+ "required": false
726
+ }
727
+ ],
728
+ "paramNames": [
729
+ "form_token",
730
+ "serial_number",
731
+ "fields",
732
+ "include_labels"
733
+ ],
734
+ "successStatus": 200,
735
+ "scopes": [
736
+ "read_entries"
737
+ ],
738
+ "responseSchema": "Entry"
739
+ },
740
+ "updateEntryViaPost": {
741
+ "operationId": "updateEntryViaPost",
742
+ "summary": "Partially update an entry (POST)",
743
+ "description": "A POST alias of `PATCH` on the same path, with the same partial-update semantics, for clients that cannot easily send PATCH.",
744
+ "tag": "Entries",
745
+ "method": "post",
746
+ "path": "/forms/{form_token}/entries/{serial_number}",
747
+ "params": [
748
+ {
749
+ "name": "form_token",
750
+ "in": "path",
751
+ "required": true
752
+ },
753
+ {
754
+ "name": "serial_number",
755
+ "in": "path",
756
+ "required": true
757
+ }
758
+ ],
759
+ "paramNames": [
760
+ "form_token",
761
+ "serial_number"
762
+ ],
763
+ "body": {
764
+ "contentType": "application/json",
765
+ "required": true,
766
+ "flatten": false,
767
+ "param": "body"
768
+ },
769
+ "successStatus": 200,
770
+ "scopes": [
771
+ "write_entries"
772
+ ],
773
+ "responseSchema": "Entry"
774
+ },
775
+ "replaceEntry": {
776
+ "operationId": "replaceEntry",
777
+ "summary": "Replace an entry",
778
+ "description": "**Full replace**: writable fields absent from the request body are cleared, and only the values submitted in this request are kept. For a partial update use `PATCH`.\nReturns 400 when validation fails, with `error_description` being the JSON string of the field errors.",
779
+ "tag": "Entries",
780
+ "method": "put",
781
+ "path": "/forms/{form_token}/entries/{serial_number}",
782
+ "params": [
783
+ {
784
+ "name": "form_token",
785
+ "in": "path",
786
+ "required": true
787
+ },
788
+ {
789
+ "name": "serial_number",
790
+ "in": "path",
791
+ "required": true
792
+ }
793
+ ],
794
+ "paramNames": [
795
+ "form_token",
796
+ "serial_number"
797
+ ],
798
+ "body": {
799
+ "contentType": "application/json",
800
+ "required": true,
801
+ "flatten": false,
802
+ "param": "body"
803
+ },
804
+ "successStatus": 200,
805
+ "scopes": [
806
+ "write_entries"
807
+ ],
808
+ "responseSchema": "Entry"
809
+ },
810
+ "updateEntry": {
811
+ "operationId": "updateEntry",
812
+ "summary": "Partially update an entry",
813
+ "description": "**Partial update**: only the fields present in the request body change; the rest keep their values. An attachment field is replaced as a whole set: to keep existing files, send back the URLs or attachment ids you read along with the new ones.\nReturns 400 when validation fails, with `error_description` being the JSON string of the field errors.",
814
+ "tag": "Entries",
815
+ "method": "patch",
816
+ "path": "/forms/{form_token}/entries/{serial_number}",
817
+ "params": [
818
+ {
819
+ "name": "form_token",
820
+ "in": "path",
821
+ "required": true
822
+ },
823
+ {
824
+ "name": "serial_number",
825
+ "in": "path",
826
+ "required": true
827
+ }
828
+ ],
829
+ "paramNames": [
830
+ "form_token",
831
+ "serial_number"
832
+ ],
833
+ "body": {
834
+ "contentType": "application/json",
835
+ "required": true,
836
+ "flatten": false,
837
+ "param": "body"
838
+ },
839
+ "successStatus": 200,
840
+ "scopes": [
841
+ "write_entries"
842
+ ],
843
+ "responseSchema": "Entry"
844
+ },
845
+ "deleteEntry": {
846
+ "operationId": "deleteEntry",
847
+ "summary": "Delete an entry",
848
+ "description": "Deletes one entry and records a delete activity. On success returns the serial number of the deleted entry; returns 400 when deletion fails (for example, the form's state does not allow it).",
849
+ "tag": "Entries",
850
+ "method": "delete",
851
+ "path": "/forms/{form_token}/entries/{serial_number}",
852
+ "params": [
853
+ {
854
+ "name": "form_token",
855
+ "in": "path",
856
+ "required": true
857
+ },
858
+ {
859
+ "name": "serial_number",
860
+ "in": "path",
861
+ "required": true
862
+ }
863
+ ],
864
+ "paramNames": [
865
+ "form_token",
866
+ "serial_number"
867
+ ],
868
+ "successStatus": 200,
869
+ "scopes": [
870
+ "write_entries"
871
+ ]
872
+ },
873
+ "listEntryComments": {
874
+ "operationId": "listEntryComments",
875
+ "summary": "List an entry's comments",
876
+ "description": "Returns all comments on the entry, oldest first, with their creators, mentioned users and attachments. A caller who is a cooperator needs entry read permission on the form, and the entry must be within their data scope; otherwise returns 400.",
877
+ "tag": "Comments",
878
+ "method": "get",
879
+ "path": "/forms/{form_token}/entries/{serial_number}/comments",
880
+ "params": [
881
+ {
882
+ "name": "form_token",
883
+ "in": "path",
884
+ "required": true
885
+ },
886
+ {
887
+ "name": "serial_number",
888
+ "in": "path",
889
+ "required": true
890
+ }
891
+ ],
892
+ "paramNames": [
893
+ "form_token",
894
+ "serial_number"
895
+ ],
896
+ "successStatus": 200,
897
+ "scopes": [
898
+ "read_entries"
899
+ ]
900
+ },
901
+ "createEntryComment": {
902
+ "operationId": "createEntryComment",
903
+ "summary": "Comment on an entry",
904
+ "description": "Creates a comment on the entry, authored by the caller; content is stripped of leading and trailing whitespace. Returns 400 when content is empty or longer than 2000 characters. Mention a user in content with @[<user_id>] (a 24-character hex user id); the mentioned user must be a cooperator on the form, otherwise returns 400 and no comment is created. parent_id makes the comment a reply; the parent comment must belong to the same entry, otherwise returns 400. This endpoint cannot attach files. A caller who is a cooperator needs entry read permission, and the entry must be within their data scope; otherwise returns 400.",
905
+ "tag": "Comments",
906
+ "method": "post",
907
+ "path": "/forms/{form_token}/entries/{serial_number}/comments",
908
+ "params": [
909
+ {
910
+ "name": "form_token",
911
+ "in": "path",
912
+ "required": true
913
+ },
914
+ {
915
+ "name": "serial_number",
916
+ "in": "path",
917
+ "required": true
918
+ }
919
+ ],
920
+ "paramNames": [
921
+ "form_token",
922
+ "serial_number"
923
+ ],
924
+ "body": {
925
+ "contentType": "application/json",
926
+ "required": true,
927
+ "flatten": true
928
+ },
929
+ "successStatus": 201,
930
+ "scopes": [
931
+ "read_entries"
932
+ ],
933
+ "responseSchema": "EntryComment"
934
+ },
935
+ "updateEntryComment": {
936
+ "operationId": "updateEntryComment",
937
+ "summary": "Update a comment on an entry",
938
+ "description": "Changes a comment's content; PUT is accepted too. Only the comment's author can edit it; not even a form admin can edit someone else's comment; otherwise returns 400. content follows the same rules as on create (leading and trailing whitespace stripped, at most 2000 characters, mentioned users must be cooperators); the comment's existing attachments stay unchanged. Returns 404 (comment cannot be found) when the comment does not belong to the entry.",
939
+ "tag": "Comments",
940
+ "method": "patch",
941
+ "path": "/forms/{form_token}/entries/{serial_number}/comments/{comment_id}",
942
+ "params": [
943
+ {
944
+ "name": "form_token",
945
+ "in": "path",
946
+ "required": true
947
+ },
948
+ {
949
+ "name": "serial_number",
950
+ "in": "path",
951
+ "required": true
952
+ },
953
+ {
954
+ "name": "comment_id",
955
+ "in": "path",
956
+ "required": true
957
+ }
958
+ ],
959
+ "paramNames": [
960
+ "form_token",
961
+ "serial_number",
962
+ "comment_id"
963
+ ],
964
+ "body": {
965
+ "contentType": "application/json",
966
+ "required": true,
967
+ "flatten": true
968
+ },
969
+ "successStatus": 200,
970
+ "scopes": [
971
+ "read_entries"
972
+ ],
973
+ "responseSchema": "EntryComment"
974
+ },
975
+ "deleteEntryComment": {
976
+ "operationId": "deleteEntryComment",
977
+ "summary": "Delete a comment on an entry",
978
+ "description": "Deletes a comment. The comment's author, the form's creator, or a cooperator with the admin role can delete it; any other cooperator gets 400. Returns 404 (comment cannot be found) for a comment that is already deleted or does not belong to the entry.",
979
+ "tag": "Comments",
980
+ "method": "delete",
981
+ "path": "/forms/{form_token}/entries/{serial_number}/comments/{comment_id}",
982
+ "params": [
983
+ {
984
+ "name": "form_token",
985
+ "in": "path",
986
+ "required": true
987
+ },
988
+ {
989
+ "name": "serial_number",
990
+ "in": "path",
991
+ "required": true
992
+ },
993
+ {
994
+ "name": "comment_id",
995
+ "in": "path",
996
+ "required": true
997
+ }
998
+ ],
999
+ "paramNames": [
1000
+ "form_token",
1001
+ "serial_number",
1002
+ "comment_id"
1003
+ ],
1004
+ "successStatus": 200,
1005
+ "scopes": [
1006
+ "read_entries"
1007
+ ]
1008
+ },
1009
+ "getFormSetting": {
1010
+ "operationId": "getFormSetting",
1011
+ "summary": "Show a form's settings",
1012
+ "description": "Returns the form's after-submission settings, collection rules (closing rules, fill frequency), access policy, WeChat restrictions and Webhook settings.\nThe `weixin` key is returned only when the form has a WeChat Official Account selected (selected_weixin_appid is present).",
1013
+ "tag": "Form Settings",
1014
+ "method": "get",
1015
+ "path": "/forms/{form_token}/setting",
1016
+ "params": [
1017
+ {
1018
+ "name": "form_token",
1019
+ "in": "path",
1020
+ "required": true
1021
+ }
1022
+ ],
1023
+ "paramNames": [
1024
+ "form_token"
1025
+ ],
1026
+ "successStatus": 200,
1027
+ "scopes": [
1028
+ "form_setting"
1029
+ ],
1030
+ "responseSchema": "FormSetting"
1031
+ },
1032
+ "updateFormSetting": {
1033
+ "operationId": "updateFormSetting",
1034
+ "summary": "Update a form's settings",
1035
+ "description": "Partially updates the form's settings, writing only the keys present in the request; PUT is accepted too.\n- `submission_region_limited` / `submission_regions` are a paid feature and read-only here; to write them, use `setting` on the \"Edit a form\" endpoint.\n- `manually_close_rule`, `by_time_range_close_rule`, `by_entries_close_rule` and `fill_frequency` are nested objects; the server creates or updates them as nested attributes.\n- Returns `{ \"status\": \"ok\" }` on success; returns 400 when model validation fails, with body `{ \"errors\": \"...\", \"status\": \"failed\" }` (not the common error shape).",
1036
+ "tag": "Form Settings",
1037
+ "method": "patch",
1038
+ "path": "/forms/{form_token}/setting",
1039
+ "params": [
1040
+ {
1041
+ "name": "form_token",
1042
+ "in": "path",
1043
+ "required": true
1044
+ }
1045
+ ],
1046
+ "paramNames": [
1047
+ "form_token"
1048
+ ],
1049
+ "body": {
1050
+ "contentType": "application/json",
1051
+ "required": true,
1052
+ "flatten": false,
1053
+ "param": "body"
1054
+ },
1055
+ "successStatus": 200,
1056
+ "scopes": [
1057
+ "form_setting"
1058
+ ],
1059
+ "responseSchema": "FormSettingSaveOk"
1060
+ },
1061
+ "getManuallyCloseRule": {
1062
+ "operationId": "getManuallyCloseRule",
1063
+ "summary": "Show whether a form is manually closed",
1064
+ "description": "Returns whether the form has been manually closed for collection. Returns `{ \"closed\": false }` when no manual closing rule has ever been created.",
1065
+ "tag": "Form Settings",
1066
+ "method": "get",
1067
+ "path": "/forms/{form_token}/manually_close_rule",
1068
+ "params": [
1069
+ {
1070
+ "name": "form_token",
1071
+ "in": "path",
1072
+ "required": true
1073
+ }
1074
+ ],
1075
+ "paramNames": [
1076
+ "form_token"
1077
+ ],
1078
+ "successStatus": 200,
1079
+ "scopes": [
1080
+ "form_setting"
1081
+ ],
1082
+ "responseSchema": "ManuallyCloseRule"
1083
+ },
1084
+ "updateManuallyCloseRule": {
1085
+ "operationId": "updateManuallyCloseRule",
1086
+ "summary": "Open or close collection manually",
1087
+ "description": "Opens (true) or closes (false) the form for collection manually through `open`; PUT is accepted too.\nCreates the manual closing rule when none exists, updates it otherwise. When the manual closed state changes, the server deletes the form's other closing rules (by time, by entry count, etc.).\nReturns 400 when the `open` parameter is missing (the response body depends on the server implementation); returns 400 when saving fails, with body `{ \"errors\": \"...\", \"status\": \"failed\" }`.",
1088
+ "tag": "Form Settings",
1089
+ "method": "patch",
1090
+ "path": "/forms/{form_token}/manually_close_rule",
1091
+ "params": [
1092
+ {
1093
+ "name": "form_token",
1094
+ "in": "path",
1095
+ "required": true
1096
+ }
1097
+ ],
1098
+ "paramNames": [
1099
+ "form_token"
1100
+ ],
1101
+ "body": {
1102
+ "contentType": "application/json",
1103
+ "required": true,
1104
+ "flatten": true
1105
+ },
1106
+ "successStatus": 200,
1107
+ "scopes": [
1108
+ "form_setting"
1109
+ ],
1110
+ "responseSchema": "ManuallyCloseRule"
1111
+ },
1112
+ "updateAccessPolicy": {
1113
+ "operationId": "updateAccessPolicy",
1114
+ "summary": "Update the fill frequency limit",
1115
+ "description": "Updates the form's fill frequency limit (fill_frequency); PUT is accepted too.\nThis endpoint takes only the `fill_frequency` key; for the other access policy keys, use PATCH /forms/{form_token}/setting.\nReturns `{ \"status\": \"ok\" }` on success; returns 400 when validation fails, with body `{ \"errors\": \"...\", \"status\": \"failed\" }` (not the common error shape).",
1116
+ "tag": "Form Settings",
1117
+ "method": "patch",
1118
+ "path": "/forms/{form_token}/access_policy",
1119
+ "params": [
1120
+ {
1121
+ "name": "form_token",
1122
+ "in": "path",
1123
+ "required": true
1124
+ }
1125
+ ],
1126
+ "paramNames": [
1127
+ "form_token"
1128
+ ],
1129
+ "body": {
1130
+ "contentType": "application/json",
1131
+ "required": true,
1132
+ "flatten": true
1133
+ },
1134
+ "successStatus": 200,
1135
+ "scopes": [
1136
+ "form_setting"
1137
+ ],
1138
+ "responseSchema": "FormSettingSaveOk"
1139
+ },
1140
+ "createFormWebhook": {
1141
+ "operationId": "createFormWebhook",
1142
+ "summary": "Set the Webhook",
1143
+ "description": "Sets the form's entry push URL `entry_post_url` and turns on pushing new entries (post_new_entry = true).\nThe plan must support Webhook; otherwise returns 402 with an empty body.\nThe server does not check the save result and echoes `entry_post_url` from the settings as is (whether an invalid URL was persisted depends on the server implementation).",
1144
+ "tag": "Form Settings",
1145
+ "method": "post",
1146
+ "path": "/forms/{form_token}/webhook",
1147
+ "params": [
1148
+ {
1149
+ "name": "form_token",
1150
+ "in": "path",
1151
+ "required": true
1152
+ }
1153
+ ],
1154
+ "paramNames": [
1155
+ "form_token"
1156
+ ],
1157
+ "body": {
1158
+ "contentType": "application/json",
1159
+ "required": true,
1160
+ "flatten": true
1161
+ },
1162
+ "successStatus": 200,
1163
+ "scopes": [
1164
+ "form_setting"
1165
+ ],
1166
+ "responseSchema": "FormWebhook"
1167
+ },
1168
+ "deleteFormWebhook": {
1169
+ "operationId": "deleteFormWebhook",
1170
+ "summary": "Delete the Webhook",
1171
+ "description": "Removes `entry_post_url` from the form's settings. Returns 200 with an empty body on success.",
1172
+ "tag": "Form Settings",
1173
+ "method": "delete",
1174
+ "path": "/forms/{form_token}/webhook",
1175
+ "params": [
1176
+ {
1177
+ "name": "form_token",
1178
+ "in": "path",
1179
+ "required": true
1180
+ }
1181
+ ],
1182
+ "paramNames": [
1183
+ "form_token"
1184
+ ],
1185
+ "successStatus": 200,
1186
+ "scopes": [
1187
+ "form_setting"
1188
+ ]
1189
+ },
1190
+ "updateFormTheme": {
1191
+ "operationId": "updateFormTheme",
1192
+ "summary": "Update a form's theme",
1193
+ "description": "Partially updates the form's theme (colors, background, header image, typography, form container, submit button); PUT is accepted too.\n- The request body must contain at least one of primary_color / secondary_color / wallpaper / header / typography / form_container / submit_button (`generate_header_image` is turned into header.header_image_url, so it counts too); otherwise 400.\n- Header image source precedence: header_image_upload_token > header_image_base64 > header_image_url > header_image_attachment_id; when a header image is set and header.type is not given, header.type is set to image.\n- Background image source precedence: background_image_upload_token > background_image_url > background_image_attachment_id. Setting or removing the background image also removes the preset background image that comes with the theme template; the background color is kept.\n- `header_image_attachment_id` / `background_image_attachment_id` take the `attachment_id` returned by \"Upload a form image\" (image_type header / wallpaper); pass an empty string `\"\"` to remove the current image.\n- `header.carousel_images` replaces the carousel images as a whole: at most 5, not empty; each item gives one of image_upload_token / image_url / attachment_id, and an attachment_id must be a carousel image the form already has; when it is passed and header.type is not given, header.type is set to carousel.\n- Keys in `text_style` and `typography.*` use underscores (e.g. font_size); the server converts them to hyphenated CSS keys and merges them into the existing styles; the response uses the hyphenated keys.\n- `generate_header_image` has AI generate a header image and consumes AI points; returns 402 when points are insufficient, 400 when generation fails.\n- An image upload_token is the `form_image_token` used by \"Upload a form image\"; the image purpose it records must match (header / wallpaper / carousel), and its upload must be complete.",
1194
+ "tag": "Form Settings",
1195
+ "method": "patch",
1196
+ "path": "/forms/{form_token}/theme",
1197
+ "params": [
1198
+ {
1199
+ "name": "form_token",
1200
+ "in": "path",
1201
+ "required": true
1202
+ }
1203
+ ],
1204
+ "paramNames": [
1205
+ "form_token"
1206
+ ],
1207
+ "body": {
1208
+ "contentType": "application/json",
1209
+ "required": true,
1210
+ "flatten": false,
1211
+ "param": "body"
1212
+ },
1213
+ "successStatus": 200,
1214
+ "scopes": [
1215
+ "form_setting"
1216
+ ],
1217
+ "responseSchema": "FormTheme"
1218
+ },
1219
+ "getExamSetting": {
1220
+ "operationId": "getExamSetting",
1221
+ "summary": "Show a form's exam settings",
1222
+ "description": "Returns an exam form's settings for what is shown after the exam is submitted, the time limit, the pre-exam notice and score range comments.\nOnly for forms in the exam scene (scene = exam); otherwise returns 400. Returns an empty object `{}` when the form has no exam settings record yet.",
1223
+ "tag": "Form Settings",
1224
+ "method": "get",
1225
+ "path": "/forms/{form_token}/exam_setting",
1226
+ "params": [
1227
+ {
1228
+ "name": "form_token",
1229
+ "in": "path",
1230
+ "required": true
1231
+ }
1232
+ ],
1233
+ "paramNames": [
1234
+ "form_token"
1235
+ ],
1236
+ "successStatus": 200,
1237
+ "scopes": [
1238
+ "form_setting"
1239
+ ],
1240
+ "responseSchema": "ExamSetting"
1241
+ },
1242
+ "updateExamSetting": {
1243
+ "operationId": "updateExamSetting",
1244
+ "summary": "Update a form's exam settings",
1245
+ "description": "Partially updates an exam form's settings; PUT is accepted too. Only for exam-scene forms; otherwise returns 400.\n- When the plan does not support \"show the score after submission\", `notice_after_filling_mode` is forced to none and `success_message_rich_text` is ignored.\n- `interval_comments` replaces the existing range comments as a whole; it takes effect only when `notice_after_filling_mode` (passed in this request or already saved) is grade / explaination / answer; passing an empty array does not turn range comments off.\n- Range comments must have end_point ≥ start_point and must not overlap; otherwise 400.\n- Passing `show_timeout: true` returns 400 when the form already has required questions; once the time limit is on, question fields cannot be made required (required candidate info fields are not affected); to turn on the time limit, make the questions optional first.\n- When `notice_after_filling_mode` is not none, the server clears success_redirect_url / success_redirect_fields in the form's settings.\n- A request body with no recognized keys is a no-op and returns the current settings.",
1246
+ "tag": "Form Settings",
1247
+ "method": "patch",
1248
+ "path": "/forms/{form_token}/exam_setting",
1249
+ "params": [
1250
+ {
1251
+ "name": "form_token",
1252
+ "in": "path",
1253
+ "required": true
1254
+ }
1255
+ ],
1256
+ "paramNames": [
1257
+ "form_token"
1258
+ ],
1259
+ "body": {
1260
+ "contentType": "application/json",
1261
+ "required": true,
1262
+ "flatten": true
1263
+ },
1264
+ "successStatus": 200,
1265
+ "scopes": [
1266
+ "form_setting"
1267
+ ],
1268
+ "responseSchema": "ExamSetting"
1269
+ },
1270
+ "getEvaluationSetting": {
1271
+ "operationId": "getEvaluationSetting",
1272
+ "summary": "Show a form's evaluation settings",
1273
+ "description": "Returns an evaluation form's report display, dimension (indicator) settings and total score range comments.\nOnly for forms in the evaluation scene (scene = evaluation); otherwise returns 400. Returns an empty object `{}` when the form has no evaluation settings record yet.",
1274
+ "tag": "Form Settings",
1275
+ "method": "get",
1276
+ "path": "/forms/{form_token}/evaluation_setting",
1277
+ "params": [
1278
+ {
1279
+ "name": "form_token",
1280
+ "in": "path",
1281
+ "required": true
1282
+ }
1283
+ ],
1284
+ "paramNames": [
1285
+ "form_token"
1286
+ ],
1287
+ "successStatus": 200,
1288
+ "scopes": [
1289
+ "form_setting"
1290
+ ],
1291
+ "responseSchema": "EvaluationSetting"
1292
+ },
1293
+ "updateEvaluationSetting": {
1294
+ "operationId": "updateEvaluationSetting",
1295
+ "summary": "Update a form's evaluation settings",
1296
+ "description": "Partially updates an evaluation form's settings; PUT is accepted too. Only for evaluation-scene forms; otherwise returns 400.\n- When the plan does not support \"show the evaluation report after submission\", `notice_after_filling_mode` is forced to none.\n- `evaluation_comments` replaces the total score range comments as a whole, and an empty array turns range comments off; it takes effect only when `notice_after_filling_mode` (passed in this request or already saved) is reports / customize.\n- A comment by score range must give both start_point and end_point; comments written with conditions in the form editor read back as `id` + `conditions` and must be passed back with their original id when updating (only comment / retry may change; the conditions cannot be changed and no range can be added); leaving one out or changing it returns 400.\n- `indicator_setting.indicators` replaces the dimensions as a whole; pass `api_code` back to keep an existing dimension's identity. A dimension can bind only scorable questions visible on the form, referenced by `field_api_codes` or `field_cids`; referencing an unknown field returns 400.\n- When `notice_after_filling_mode` is not none, the server clears success_redirect_url / success_redirect_fields in the form's settings.\n- A request body with no recognized keys is a no-op and returns the current settings.",
1297
+ "tag": "Form Settings",
1298
+ "method": "patch",
1299
+ "path": "/forms/{form_token}/evaluation_setting",
1300
+ "params": [
1301
+ {
1302
+ "name": "form_token",
1303
+ "in": "path",
1304
+ "required": true
1305
+ }
1306
+ ],
1307
+ "paramNames": [
1308
+ "form_token"
1309
+ ],
1310
+ "body": {
1311
+ "contentType": "application/json",
1312
+ "required": true,
1313
+ "flatten": false,
1314
+ "param": "body"
1315
+ },
1316
+ "successStatus": 200,
1317
+ "scopes": [
1318
+ "form_setting"
1319
+ ],
1320
+ "responseSchema": "EvaluationSetting"
1321
+ },
1322
+ "listFieldRules": {
1323
+ "operationId": "listFieldRules",
1324
+ "summary": "Show a form's field display rules",
1325
+ "description": "Returns the form's effective field display rules (logic jumps). `index` is the 0-based position; field_rules updates and removals in PATCH /forms/{form_token} locate rules by this index.",
1326
+ "tag": "Forms",
1327
+ "method": "get",
1328
+ "path": "/forms/{form_token}/field_rules",
1329
+ "params": [
1330
+ {
1331
+ "name": "form_token",
1332
+ "in": "path",
1333
+ "required": true
1334
+ }
1335
+ ],
1336
+ "paramNames": [
1337
+ "form_token"
1338
+ ],
1339
+ "successStatus": 200,
1340
+ "scopes": [
1341
+ "forms"
1342
+ ]
1343
+ },
1344
+ "listExtendedAttributes": {
1345
+ "operationId": "listExtendedAttributes",
1346
+ "summary": "List the source-tracking links",
1347
+ "description": "Returns the \"track entry source\" extended attributes generated for the form (oldest first), each with the fill link that carries its value.",
1348
+ "tag": "Forms",
1349
+ "method": "get",
1350
+ "path": "/forms/{form_token}/extended_attributes",
1351
+ "params": [
1352
+ {
1353
+ "name": "form_token",
1354
+ "in": "path",
1355
+ "required": true
1356
+ }
1357
+ ],
1358
+ "paramNames": [
1359
+ "form_token"
1360
+ ],
1361
+ "successStatus": 200,
1362
+ "scopes": [
1363
+ "forms"
1364
+ ]
1365
+ },
1366
+ "listFormCooperators": {
1367
+ "operationId": "listFormCooperators",
1368
+ "summary": "List a form's cooperators",
1369
+ "description": "Returns the form's cooperators and their role names, including roles inherited from folders; when a user gets roles through several paths, only the nearest one is returned.",
1370
+ "tag": "Forms",
1371
+ "method": "get",
1372
+ "path": "/forms/{form_token}/cooperators",
1373
+ "params": [
1374
+ {
1375
+ "name": "form_token",
1376
+ "in": "path",
1377
+ "required": true
1378
+ }
1379
+ ],
1380
+ "paramNames": [
1381
+ "form_token"
1382
+ ],
1383
+ "successStatus": 200,
1384
+ "scopes": [
1385
+ "forms"
1386
+ ]
1387
+ },
1388
+ "copyForm": {
1389
+ "operationId": "copyForm",
1390
+ "summary": "Copy a form",
1391
+ "description": "Copies the form and returns the new form (same shape as GET /forms/{form_token}). The new form's creator is the calling user (the account owner for an account token).\n- When the source form allows public copying (can_duplicated_in_public), the caller needs no access to the source form; otherwise a caller without access gets 404.\n- Returns 403 when the source form is frozen or its creator's account is disabled, with body `{ \"errors\": ..., \"status_code\": \"form_forbidden\" }` (not the common error shape).\n- `folder_token` takes a folder token or id; returns 404 when the folder does not exist or the caller lacks manage permission on it.\n- Returns 400 when copying fails (model validation does not pass).",
1392
+ "tag": "Forms",
1393
+ "method": "post",
1394
+ "path": "/forms/{form_token}/copy",
1395
+ "params": [
1396
+ {
1397
+ "name": "form_token",
1398
+ "in": "path",
1399
+ "required": true
1400
+ }
1401
+ ],
1402
+ "paramNames": [
1403
+ "form_token"
1404
+ ],
1405
+ "body": {
1406
+ "contentType": "application/json",
1407
+ "required": false,
1408
+ "flatten": true
1409
+ },
1410
+ "successStatus": 200,
1411
+ "scopes": [
1412
+ "forms"
1413
+ ],
1414
+ "responseSchema": "Form"
1415
+ },
1416
+ "moveFormToFolder": {
1417
+ "operationId": "moveFormToFolder",
1418
+ "summary": "Move a form into a folder",
1419
+ "description": "Moves the form into a folder, or out of one (pass null as `folder_token`); PUT is accepted too. The move affects only the calling user's folder placement.\n- The request body must contain the `folder_token` key (its value may be null); otherwise 400.\n- `folder_token` takes only a folder token (not an id); returns 404 when the folder does not exist or the current user lacks manage permission on it.\n- The folder type (form / table) must match the form's type; otherwise 400.\n- To move a table, use `PATCH /tables/{table_token}/folder`.",
1420
+ "tag": "Forms",
1421
+ "method": "patch",
1422
+ "path": "/forms/{form_token}/folder",
1423
+ "params": [
1424
+ {
1425
+ "name": "form_token",
1426
+ "in": "path",
1427
+ "required": true
1428
+ }
1429
+ ],
1430
+ "paramNames": [
1431
+ "form_token"
1432
+ ],
1433
+ "body": {
1434
+ "contentType": "application/json",
1435
+ "required": true,
1436
+ "flatten": true
1437
+ },
1438
+ "successStatus": 200,
1439
+ "scopes": [
1440
+ "forms"
1441
+ ],
1442
+ "responseSchema": "FormFolderMoveResult"
1443
+ },
1444
+ "createWeixinOauthSession": {
1445
+ "operationId": "createWeixinOauthSession",
1446
+ "summary": "Exchange a WeChat authorization code for an openid",
1447
+ "description": "Exchanges the `code` returned by WeChat web authorization for the user's openid, through the WeChat Official Account the form has selected.\nWhen the form's WeChat authorization scope is userinfo, also returns `unionid` (when WeChat returns one) and `profile`.\n- Returns 400 when the form has no WeChat Official Account configured or that account does not exist; returns 400 when `code` is missing.\n- Returns 502 when the exchange fails on the WeChat side (invalid code, etc.) or fetching the user info fails.",
1448
+ "tag": "Forms",
1449
+ "method": "post",
1450
+ "path": "/forms/{form_token}/weixin_oauth_session",
1451
+ "params": [
1452
+ {
1453
+ "name": "form_token",
1454
+ "in": "path",
1455
+ "required": true
1456
+ }
1457
+ ],
1458
+ "paramNames": [
1459
+ "form_token"
1460
+ ],
1461
+ "body": {
1462
+ "contentType": "application/json",
1463
+ "required": true,
1464
+ "flatten": true
1465
+ },
1466
+ "successStatus": 200,
1467
+ "scopes": [
1468
+ "write_entries"
1469
+ ],
1470
+ "responseSchema": "FormWeixinOauthSession"
1471
+ },
1472
+ "listFormViews": {
1473
+ "operationId": "listFormViews",
1474
+ "summary": "List a form's views",
1475
+ "description": "Returns the views the caller can see on the form: views they created, and views whose visibility other cooperators set to cooperators; other users' personal views are not returned. The order follows the caller's own saved view order; views not in it are appended by position, then created_at.",
1476
+ "tag": "Views",
1477
+ "method": "get",
1478
+ "path": "/forms/{form_token}/views",
1479
+ "params": [
1480
+ {
1481
+ "name": "form_token",
1482
+ "in": "path",
1483
+ "required": true
1484
+ }
1485
+ ],
1486
+ "paramNames": [
1487
+ "form_token"
1488
+ ],
1489
+ "successStatus": 200,
1490
+ "scopes": [
1491
+ "forms"
1492
+ ]
1493
+ },
1494
+ "createFormView": {
1495
+ "operationId": "createFormView",
1496
+ "summary": "Create a view on a form",
1497
+ "description": "Creates a new view on the form, created by the caller; visibility defaults to cooperators when not passed, and position is the highest position among the currently visible views plus 1. Each user can have at most 100 views on one form; at the limit, returns 422 (View limit reached). When view_type is kanban and kanban_group_by_api_code is not passed, the server picks the grouping field; when kanban_hidden_groups is not passed, the __unset__ group is hidden by default; when prefer_columns is empty, the form's default columns are used (at most 5 columns for a kanban view, serial_number included). Returns 422 when filter is invalid (not an array, unknown field, unsupported operator, invalid value). Returns 422 when model validation fails (e.g. name is empty or longer than 120 characters, or the grouping field does not support kanban grouping). Form views (view_type form): supported only on tables, otherwise 422; title defaults to the table name; without field_overrides, all fillable columns are selected in the current column order; published defaults to false (the fill link does not work while unpublished). title / description / published / field_overrides apply only to form views; using them on another type returns 422. Creating, updating or deleting a form view (including switching a view to or from a form view) requires the caller to hold a predefined role on the table that can add entries, otherwise 403; an account token is exempt. Returns 422 when a fill item's column does not exist, cannot be a fill item, or sets a validation its column type does not support; the error message names the column's api_code.",
1498
+ "tag": "Views",
1499
+ "method": "post",
1500
+ "path": "/forms/{form_token}/views",
1501
+ "params": [
1502
+ {
1503
+ "name": "form_token",
1504
+ "in": "path",
1505
+ "required": true
1506
+ }
1507
+ ],
1508
+ "paramNames": [
1509
+ "form_token"
1510
+ ],
1511
+ "body": {
1512
+ "contentType": "application/json",
1513
+ "required": true,
1514
+ "flatten": false,
1515
+ "param": "body"
1516
+ },
1517
+ "successStatus": 201,
1518
+ "scopes": [
1519
+ "forms"
1520
+ ],
1521
+ "responseSchema": "FormView"
1522
+ },
1523
+ "getFormView": {
1524
+ "operationId": "getFormView",
1525
+ "summary": "Show a view of a form",
1526
+ "description": "Returns one view. Only views visible to the caller can be read (created by the caller or visible to cooperators); another user's personal view returns 404 (View cannot be found).",
1527
+ "tag": "Views",
1528
+ "method": "get",
1529
+ "path": "/forms/{form_token}/views/{view_token}",
1530
+ "params": [
1531
+ {
1532
+ "name": "form_token",
1533
+ "in": "path",
1534
+ "required": true
1535
+ },
1536
+ {
1537
+ "name": "view_token",
1538
+ "in": "path",
1539
+ "required": true
1540
+ }
1541
+ ],
1542
+ "paramNames": [
1543
+ "form_token",
1544
+ "view_token"
1545
+ ],
1546
+ "successStatus": 200,
1547
+ "scopes": [
1548
+ "forms"
1549
+ ],
1550
+ "responseSchema": "FormView"
1551
+ },
1552
+ "updateFormView": {
1553
+ "operationId": "updateFormView",
1554
+ "summary": "Update a view of a form",
1555
+ "description": "Updates the view's configuration; PUT is accepted too. Only the keys present in the request are updated: an empty array for filter clears the filters, and leaving filter out keeps them unchanged; when kanban_group_by_api_code changes and kanban_group_order / kanban_hidden_groups are not passed with it, those two lists reset to their defaults. Cooperators can change the configuration of a view visible to cooperators, but only the view's creator can switch visibility, otherwise returns 403; a view whose view_scope is form cannot switch visibility. Returns 422 when filter is invalid or model validation fails. field_overrides replaces the fill item settings as a whole; form views have the same permission requirements and parameter limits as on create.",
1556
+ "tag": "Views",
1557
+ "method": "patch",
1558
+ "path": "/forms/{form_token}/views/{view_token}",
1559
+ "params": [
1560
+ {
1561
+ "name": "form_token",
1562
+ "in": "path",
1563
+ "required": true
1564
+ },
1565
+ {
1566
+ "name": "view_token",
1567
+ "in": "path",
1568
+ "required": true
1569
+ }
1570
+ ],
1571
+ "paramNames": [
1572
+ "form_token",
1573
+ "view_token"
1574
+ ],
1575
+ "body": {
1576
+ "contentType": "application/json",
1577
+ "required": true,
1578
+ "flatten": false,
1579
+ "param": "body"
1580
+ },
1581
+ "successStatus": 200,
1582
+ "scopes": [
1583
+ "forms"
1584
+ ],
1585
+ "responseSchema": "FormView"
1586
+ },
1587
+ "deleteFormView": {
1588
+ "operationId": "deleteFormView",
1589
+ "summary": "Delete a view of a form",
1590
+ "description": "Deletes a view. Predefined views (predefined) and views whose view_scope is form cannot be deleted, and the deletion is also refused when it would leave the caller with no visible view; all of these return 422. Deleting a form view needs the same permission as creating one (otherwise 403); once it is deleted, its fill link stops working immediately, and this cannot be undone.",
1591
+ "tag": "Views",
1592
+ "method": "delete",
1593
+ "path": "/forms/{form_token}/views/{view_token}",
1594
+ "params": [
1595
+ {
1596
+ "name": "form_token",
1597
+ "in": "path",
1598
+ "required": true
1599
+ },
1600
+ {
1601
+ "name": "view_token",
1602
+ "in": "path",
1603
+ "required": true
1604
+ }
1605
+ ],
1606
+ "paramNames": [
1607
+ "form_token",
1608
+ "view_token"
1609
+ ],
1610
+ "successStatus": 200,
1611
+ "scopes": [
1612
+ "forms"
1613
+ ]
1614
+ },
1615
+ "listFormViewEntries": {
1616
+ "operationId": "listFormViewEntries",
1617
+ "summary": "List a view's entries",
1618
+ "description": "Returns the form's entries under the view's filters and sort rules, at most 50 per page. The returned fields are limited to those in the view's prefer_columns (serial_number always included); when prefer_columns is empty, all pushable fields are returned. Sorting follows the view's sort rules, with serial_number ascending appended when they do not include serial_number. Paginate with the next parameter (a row offset); next is null on the last page. Returns 400 when the view's filters use an operator the query engine does not support. Only views visible to the caller are accessible, otherwise 404 (View cannot be found).",
1619
+ "tag": "Views",
1620
+ "method": "get",
1621
+ "path": "/forms/{form_token}/views/{view_token}/entries",
1622
+ "params": [
1623
+ {
1624
+ "name": "form_token",
1625
+ "in": "path",
1626
+ "required": true
1627
+ },
1628
+ {
1629
+ "name": "view_token",
1630
+ "in": "path",
1631
+ "required": true
1632
+ },
1633
+ {
1634
+ "name": "next",
1635
+ "in": "query",
1636
+ "required": false
1637
+ },
1638
+ {
1639
+ "name": "include_labels",
1640
+ "in": "query",
1641
+ "required": false
1642
+ }
1643
+ ],
1644
+ "paramNames": [
1645
+ "form_token",
1646
+ "view_token",
1647
+ "next",
1648
+ "include_labels"
1649
+ ],
1650
+ "successStatus": 200,
1651
+ "scopes": [
1652
+ "read_entries"
1653
+ ],
1654
+ "responseSchema": "EntryListResponse"
1655
+ },
1656
+ "uploadEntryAttachment": {
1657
+ "operationId": "uploadEntryAttachment",
1658
+ "summary": "Upload an entry attachment",
1659
+ "description": "Uploads a file ahead of time for a form's attachment field (or an attachment column in a table field) and returns the attachment ID; then, when creating / updating an entry, put that ID (or the upload token) into the matching field to bind it. An uploaded attachment that no entry references stays unused.\nAuthenticate in one of two ways:\n1. Regular API credentials (a Bearer token).\n2. A one-time upload token `attachment_token` (instead of regular credentials): the token starts with `entry_att_tok_`, is valid for 30 minutes, can be used only once, and is bound to the form, field, column and file metadata. When the request carries `attachment_token`, regular credentials are not checked and the request acts as the token's user; returns 400 `attachment_token is invalid or expired; prepare upload again` when the token is invalid, expired, already used, its user has been deleted, or it does not match the requested form / field / column; also returns 400 when the uploaded file's name, Content-Type or byte size does not match the token.\nReturns 401 when there are neither credentials nor `attachment_token`.\nSend the file content in one of two ways: the `file` field of `multipart/form-data`; or a Base64 string in the `base64` (or `data`) field of a JSON / form-encoded body (a `data:<mime>;base64,` prefix is allowed), with `file_name` (or `filename`) and `content_type`. Base64 content cannot exceed 5 MB once decoded; larger returns 400 `attachment exceeds 5MB limit`, and a decoding failure returns 400 `base64 is invalid`; returns 400 `file or base64 is required` when neither is given.\n`field_api_code` must point to an attachment field or a table field; for a table field, `dimension_api_code` must also be passed and point to an attachment column in that table field, otherwise returns 400; returns 404 when the field or column does not exist.\nThe file size is capped by the per-file limit set on the field (or column); a larger file returns 422, with the specific validation message in `error_description` (e.g. `文件超过了10 MB`); returns 422 `上传失败,请重试` when uploading to object storage fails (the server's wording is authoritative).\nReturns 404 `form cannot be found` when the form does not exist or is not accessible to the current identity.",
1660
+ "tag": "Uploads",
1661
+ "method": "post",
1662
+ "path": "/forms/{form_token}/entry_attachments",
1663
+ "params": [
1664
+ {
1665
+ "name": "form_token",
1666
+ "in": "path",
1667
+ "required": true
1668
+ }
1669
+ ],
1670
+ "paramNames": [
1671
+ "form_token"
1672
+ ],
1673
+ "body": {
1674
+ "contentType": "application/json",
1675
+ "required": true,
1676
+ "flatten": true
1677
+ },
1678
+ "successStatus": 201,
1679
+ "scopes": [
1680
+ "write_entries"
1681
+ ],
1682
+ "responseSchema": "UploadedEntryAttachment"
1683
+ },
1684
+ "uploadImportFile": {
1685
+ "operationId": "uploadImportFile",
1686
+ "summary": "Upload an import file",
1687
+ "description": "Uploads a spreadsheet file (`.xlsx` / `.xls` / `.csv`) for bulk-importing entries into the given form, and returns the import attachment ID; then pass it as `attachment_id` to \"Import entries from an uploaded spreadsheet\" (`POST /forms/{form_token}/entry_imports`) to start the import.\nAuthenticate in one of two ways:\n1. Regular API credentials (a Bearer token).\n2. A one-time upload token `import_file_token` (instead of regular credentials): the token starts with `import_file_tok_`, is valid for 30 minutes, can be used only once, and is bound to the form and the file metadata. When the request carries `import_file_token`, regular credentials are not checked, and the request acts as the user the token belongs to; the uploaded file's original file name, Content-Type and byte size must match what the token recorded, otherwise returns 400. Returns 400 `import_file_token is invalid or expired; prepare upload again` when the token does not exist, has expired, has been used, or its user has been deleted; returns 400 `import_file_token was issued for another form; prepare upload again` when the token belongs to another form.\nReturns 401 when there are neither credentials nor an `import_file_token`.\nThe request must be `multipart/form-data`, with the file in the `file` field; a missing file returns 400 `file is required`.\nThe file size is capped by the plan's Excel import limit (in MB), and the extension must be xls / xlsx / csv; otherwise returns 422, with the validation details in `error_description` (with an upload token, the token stays usable, so the file can be uploaded again).\nReturns 404 `form cannot be found` when the form does not exist or is not accessible to the current caller.",
1688
+ "tag": "Uploads",
1689
+ "method": "post",
1690
+ "path": "/forms/{form_token}/import_files",
1691
+ "params": [
1692
+ {
1693
+ "name": "form_token",
1694
+ "in": "path",
1695
+ "required": true
1696
+ }
1697
+ ],
1698
+ "paramNames": [
1699
+ "form_token"
1700
+ ],
1701
+ "body": {
1702
+ "contentType": "multipart/form-data",
1703
+ "required": true,
1704
+ "flatten": true
1705
+ },
1706
+ "successStatus": 201,
1707
+ "scopes": [
1708
+ "write_entries"
1709
+ ],
1710
+ "responseSchema": "UploadedImportFile"
1711
+ },
1712
+ "createEntryImport": {
1713
+ "operationId": "createEntryImport",
1714
+ "summary": "Import entries from an uploaded spreadsheet",
1715
+ "description": "Appends each row of a spreadsheet uploaded with \"Upload an import file\" as an entry of this form. Upload the file first to get the import attachment ID (`attachment_id`), then say here which column goes into which field.\nProblems that can be detected up front, such as the file, the plan's import limit, the header row and the column mapping, are checked before the job is created; a rejected import writes no entries. Error messages include the spreadsheet's actual layout (row and column range, and the header contents), so the request can be fixed and retried.\nOnce validation passes, returns `201` and the entries are written in the background: `201` means the job has started, not finished; poll \"Show an entry import job\" for the result.\n- `attachment_id` must be an import file the current user uploaded for this form, otherwise returns 400 (the file cannot be found; upload it again); returns 400 when the file is not xls / xlsx / csv or cannot be read.\n- `columns` must not be empty; each item names the target field with `field_api_code`, and the source column with `column_label` (the header text, which must exactly match the header cell after trimming leading and trailing spaces) or `sheet_column_index` (the column number); when both are given, `sheet_column_index` wins.\n- The field must be one this form can import into; one field cannot map to several columns; when several header columns share a name, use `sheet_column_index` instead; the column number must be within the spreadsheet's column range.\n- `header_row_index` defaults to the first row of the spreadsheet, and there must be data rows below it.\n- Every required field of the form must have a column, otherwise returns 400 listing the missing fields.\n- `unique_field_code` names a field to deduplicate on: when a row's value for that field already exists in the form's entries, the row is skipped (counted in `skip_count`).\n- Returns 404 `form cannot be found` when the form does not exist or is not accessible to the current caller.",
1716
+ "tag": "Entries",
1717
+ "method": "post",
1718
+ "path": "/forms/{form_token}/entry_imports",
1719
+ "params": [
1720
+ {
1721
+ "name": "form_token",
1722
+ "in": "path",
1723
+ "required": true
1724
+ }
1725
+ ],
1726
+ "paramNames": [
1727
+ "form_token"
1728
+ ],
1729
+ "body": {
1730
+ "contentType": "application/json",
1731
+ "required": true,
1732
+ "flatten": true
1733
+ },
1734
+ "successStatus": 201,
1735
+ "scopes": [
1736
+ "write_entries"
1737
+ ],
1738
+ "responseSchema": "EntryImportCreated"
1739
+ },
1740
+ "getEntryImport": {
1741
+ "operationId": "getEntryImport",
1742
+ "summary": "Show an entry import job",
1743
+ "description": "Returns the progress and result of an entry import job. While `status` is `pending` / `running`, the job is still in progress, and `processed_rows` and `total_rows` can be used to show progress;\n`success` / `failed` / `cancelled` are final states; `imported_count` / `skip_count` / `invalid_count` are the numbers of rows written, skipped and failing validation, `warnings` holds per-row notices, and `error_message` is why the job failed.\nA job can be read only through the form it imports into: when the id does not exist, is not a valid id, or belongs to another form, returns 404 `Import job not found for this form — check the id, and that it belongs to this form.`.\nReturns 404 `form cannot be found` when the form does not exist or is not accessible to the current caller.",
1744
+ "tag": "Entries",
1745
+ "method": "get",
1746
+ "path": "/forms/{form_token}/entry_imports/{id}",
1747
+ "params": [
1748
+ {
1749
+ "name": "form_token",
1750
+ "in": "path",
1751
+ "required": true
1752
+ },
1753
+ {
1754
+ "name": "id",
1755
+ "in": "path",
1756
+ "required": true
1757
+ }
1758
+ ],
1759
+ "paramNames": [
1760
+ "form_token",
1761
+ "id"
1762
+ ],
1763
+ "successStatus": 200,
1764
+ "scopes": [
1765
+ "write_entries"
1766
+ ],
1767
+ "responseSchema": "EntryImportJob"
1768
+ },
1769
+ "uploadFormImage": {
1770
+ "operationId": "uploadFormImage",
1771
+ "summary": "Upload a form image",
1772
+ "description": "Uploads an image that belongs to the form itself (a picture choice image, a header image, a background image, one frame of the header carousel, the header image of the form's public query page, or an inline image in the form description / a field description), and returns the image attachment ID. The image is not bound to any form yet; it takes effect only when a form or theme references it later.\nAuthenticate in one of two ways:\n1. Regular API credentials (a Bearer token). `image_type` must then say what the image is for, and can only be `header` (header image), `wallpaper` (background image), `opensearch_header` (public query page header image) or `description` (inline description image): pass the returned `attachment_id` to `header.header_image_attachment_id` / `wallpaper.background_image_attachment_id` of \"Update a form's theme\", or to `header.background_image.attachment_id` of \"Update a public query\"; `description` also returns the image address `url`, which goes into the `<img src>` of the form `description` or of a field's `notes`. When the form is saved, the image belongs to that form (at most 30 per form); images not used by any form within 7 days are cleaned up. Returns 400 `image_type must be one of: field_choice, header, wallpaper, carousel, opensearch_header, description.` when `image_type` is missing or not one of `field_choice` / `header` / `wallpaper` / `carousel` / `opensearch_header` / `description`; `field_choice` / `carousel` have nowhere that accepts an attachment ID, so they can only be uploaded with an upload token, otherwise returns 400.\n2. A one-time upload token `form_image_token` (instead of regular credentials): the token starts with `form_img_tok_`, is valid for 30 minutes, can be used only once, and has already recorded the image purpose (`field_choice` / `header` / `wallpaper` / `carousel` / `opensearch_header` / `description`; `image_type` is then ignored) and the file metadata; the uploaded file's original file name, Content-Type and byte size must match what the token recorded, otherwise returns 400. After a successful upload, do not use the returned `attachment_id` directly; instead reference the same token in a choice's `image_upload_token` in \"Create a form\" / \"Edit a form\", in `header.header_image_upload_token` / `wallpaper.background_image_upload_token` / `header.carousel_images[].image_upload_token` of \"Update a form's theme\", or in `header.background_image.image_upload_token` of \"Update a public query\"; for the `description` purpose nothing references the token, so use the returned `url` directly. Returns 400 `form_image_token is invalid or expired; prepare upload again` when the token does not exist, has expired, has been used, or its user has been deleted.\nReturns 401 when there are neither credentials nor a `form_image_token`. The request must be `multipart/form-data`, with the image binary in the `file` field; a missing file returns 400 `file is required`.",
1773
+ "tag": "Uploads",
1774
+ "method": "post",
1775
+ "path": "/form_image_attachments",
1776
+ "params": [],
1777
+ "paramNames": [],
1778
+ "body": {
1779
+ "contentType": "multipart/form-data",
1780
+ "required": true,
1781
+ "flatten": true
1782
+ },
1783
+ "successStatus": 201,
1784
+ "scopes": [
1785
+ "forms",
1786
+ "form_setting"
1787
+ ],
1788
+ "responseSchema": "UploadedFormImage"
1789
+ },
1790
+ "listTables": {
1791
+ "operationId": "listTables",
1792
+ "summary": "List tables",
1793
+ "description": "Returns the tables (`kind=table`) visible to the current caller. Pagination, `q`, `filters`, `sort`, `next`, `skip` and `limit` mean the same as in the form list; 50 per page by default, up to 1000.",
1794
+ "tag": "Tables",
1795
+ "method": "get",
1796
+ "path": "/tables",
1797
+ "params": [
1798
+ {
1799
+ "name": "q",
1800
+ "in": "query",
1801
+ "required": false
1802
+ },
1803
+ {
1804
+ "name": "filters",
1805
+ "in": "query",
1806
+ "required": false
1807
+ },
1808
+ {
1809
+ "name": "sort",
1810
+ "in": "query",
1811
+ "required": false
1812
+ },
1813
+ {
1814
+ "name": "next",
1815
+ "in": "query",
1816
+ "required": false
1817
+ },
1818
+ {
1819
+ "name": "skip",
1820
+ "in": "query",
1821
+ "required": false
1822
+ },
1823
+ {
1824
+ "name": "limit",
1825
+ "in": "query",
1826
+ "required": false
1827
+ }
1828
+ ],
1829
+ "paramNames": [
1830
+ "q",
1831
+ "filters",
1832
+ "sort",
1833
+ "next",
1834
+ "skip",
1835
+ "limit"
1836
+ ],
1837
+ "successStatus": 200,
1838
+ "scopes": [
1839
+ "forms"
1840
+ ],
1841
+ "responseSchema": "TableListResponse"
1842
+ },
1843
+ "createTable": {
1844
+ "operationId": "createTable",
1845
+ "summary": "Create a table",
1846
+ "description": "Creates a table. Same as creating a form, except:\n- field types can only be the column types tables support: `TextArea`, `RadioButton`, `CheckBox`, `BooleanField`, `MobileField`, `NumberField`, `DateTimeField`, `EmailField`, `LinkField`, `AttachmentField`, `FormulaField`, `RelationField`;\n- attachment columns do not accept limit properties such as count / size limits, and number / formula columns have limited precision; a violation returns 400 listing the offending columns;\n- choice columns do not get an \"Other\" choice; `folder_token` must be a table folder; `layout` is not supported.\n- with `with_default_entries: true`, 3 blank entries are added after creation (as when creating a table in the product); by default none are added.\nReturns the table structure, including fields and views.",
1847
+ "tag": "Tables",
1848
+ "method": "post",
1849
+ "path": "/tables",
1850
+ "params": [],
1851
+ "paramNames": [],
1852
+ "body": {
1853
+ "contentType": "application/json",
1854
+ "required": true,
1855
+ "flatten": true
1856
+ },
1857
+ "successStatus": 201,
1858
+ "scopes": [
1859
+ "forms"
1860
+ ],
1861
+ "responseSchema": "Table"
1862
+ },
1863
+ "getTable": {
1864
+ "operationId": "getTable",
1865
+ "summary": "Show a table's structure",
1866
+ "description": "Returns the table's basic information, field definitions and the views visible to the current caller. Returns 404 `table cannot be found` when the token is not a table (for example, a regular form).",
1867
+ "tag": "Tables",
1868
+ "method": "get",
1869
+ "path": "/tables/{table_token}",
1870
+ "params": [
1871
+ {
1872
+ "name": "table_token",
1873
+ "in": "path",
1874
+ "required": true
1875
+ },
1876
+ {
1877
+ "name": "include_analytics",
1878
+ "in": "query",
1879
+ "required": false
1880
+ }
1881
+ ],
1882
+ "paramNames": [
1883
+ "table_token",
1884
+ "include_analytics"
1885
+ ],
1886
+ "successStatus": 200,
1887
+ "scopes": [
1888
+ "forms"
1889
+ ],
1890
+ "responseSchema": "Table"
1891
+ },
1892
+ "updateTable": {
1893
+ "operationId": "updateTable",
1894
+ "summary": "Edit a table",
1895
+ "description": "Edits a table incrementally; `PUT` is also accepted. The request body is the same as for editing a form (`kind` is ignored); attachment columns in `fields.add` and `fields.update` do not accept limit properties, and types in `fields.add` must be column types tables support.",
1896
+ "tag": "Tables",
1897
+ "method": "patch",
1898
+ "path": "/tables/{table_token}",
1899
+ "params": [
1900
+ {
1901
+ "name": "table_token",
1902
+ "in": "path",
1903
+ "required": true
1904
+ }
1905
+ ],
1906
+ "paramNames": [
1907
+ "table_token"
1908
+ ],
1909
+ "body": {
1910
+ "contentType": "application/json",
1911
+ "required": true,
1912
+ "flatten": true
1913
+ },
1914
+ "successStatus": 200,
1915
+ "scopes": [
1916
+ "forms"
1917
+ ],
1918
+ "responseSchema": "Table"
1919
+ },
1920
+ "deleteTable": {
1921
+ "operationId": "deleteTable",
1922
+ "summary": "Delete a table",
1923
+ "description": "Deletes a table and its entries; on success, returns the table token.",
1924
+ "tag": "Tables",
1925
+ "method": "delete",
1926
+ "path": "/tables/{table_token}",
1927
+ "params": [
1928
+ {
1929
+ "name": "table_token",
1930
+ "in": "path",
1931
+ "required": true
1932
+ }
1933
+ ],
1934
+ "paramNames": [
1935
+ "table_token"
1936
+ ],
1937
+ "successStatus": 200,
1938
+ "scopes": [
1939
+ "forms"
1940
+ ]
1941
+ },
1942
+ "checkTableFieldData": {
1943
+ "operationId": "checkTableFieldData",
1944
+ "summary": "Check whether table columns already hold data",
1945
+ "description": "Same as GET /forms/{form_token}/fields/check, applied to the columns of a table. Returns 404 (`table cannot be found`) when `table_token` does not point to a table.",
1946
+ "tag": "Tables",
1947
+ "method": "get",
1948
+ "path": "/tables/{table_token}/fields/check",
1949
+ "params": [
1950
+ {
1951
+ "name": "table_token",
1952
+ "in": "path",
1953
+ "required": true
1954
+ },
1955
+ {
1956
+ "name": "checks",
1957
+ "in": "query",
1958
+ "required": true
1959
+ }
1960
+ ],
1961
+ "paramNames": [
1962
+ "table_token",
1963
+ "checks"
1964
+ ],
1965
+ "successStatus": 200,
1966
+ "scopes": [
1967
+ "forms"
1968
+ ],
1969
+ "responseSchema": "FieldDataCheckResponse"
1970
+ },
1971
+ "previewTableFieldTypeChange": {
1972
+ "operationId": "previewTableFieldTypeChange",
1973
+ "summary": "Preview a table column type change",
1974
+ "description": "Same as GET /forms/{form_token}/fields/preview_convert, applied to the columns of a table; `target_type` accepts only column types tables support (see `GET /field_types?kind=table`).\nReturns 404 (`table cannot be found`) when `table_token` does not point to a table.",
1975
+ "tag": "Tables",
1976
+ "method": "get",
1977
+ "path": "/tables/{table_token}/fields/preview_convert",
1978
+ "params": [
1979
+ {
1980
+ "name": "table_token",
1981
+ "in": "path",
1982
+ "required": true
1983
+ },
1984
+ {
1985
+ "name": "checks",
1986
+ "in": "query",
1987
+ "required": true
1988
+ }
1989
+ ],
1990
+ "paramNames": [
1991
+ "table_token",
1992
+ "checks"
1993
+ ],
1994
+ "successStatus": 200,
1995
+ "scopes": [
1996
+ "forms"
1997
+ ],
1998
+ "responseSchema": "FieldTypeChangePreviewResponse"
1999
+ },
2000
+ "listTableEntries": {
2001
+ "operationId": "listTableEntries",
2002
+ "summary": "List table entries",
2003
+ "description": "Exactly the same as `GET /forms/{form_token}/entries`, except that the target must be a table (otherwise 404 `table cannot be found`).",
2004
+ "tag": "Tables",
2005
+ "method": "get",
2006
+ "path": "/tables/{table_token}/entries",
2007
+ "params": [
2008
+ {
2009
+ "name": "table_token",
2010
+ "in": "path",
2011
+ "required": true
2012
+ },
2013
+ {
2014
+ "name": "fields",
2015
+ "in": "query",
2016
+ "required": false
2017
+ },
2018
+ {
2019
+ "name": "filters",
2020
+ "in": "query",
2021
+ "required": false
2022
+ },
2023
+ {
2024
+ "name": "keyword",
2025
+ "in": "query",
2026
+ "required": false
2027
+ },
2028
+ {
2029
+ "name": "sort",
2030
+ "in": "query",
2031
+ "required": false
2032
+ },
2033
+ {
2034
+ "name": "created_at",
2035
+ "in": "query",
2036
+ "required": false
2037
+ },
2038
+ {
2039
+ "name": "next",
2040
+ "in": "query",
2041
+ "required": false
2042
+ },
2043
+ {
2044
+ "name": "skip",
2045
+ "in": "query",
2046
+ "required": false
2047
+ },
2048
+ {
2049
+ "name": "include_labels",
2050
+ "in": "query",
2051
+ "required": false
2052
+ },
2053
+ {
2054
+ "name": "limit",
2055
+ "in": "query",
2056
+ "required": false
2057
+ }
2058
+ ],
2059
+ "paramNames": [
2060
+ "table_token",
2061
+ "fields",
2062
+ "filters",
2063
+ "keyword",
2064
+ "sort",
2065
+ "created_at",
2066
+ "next",
2067
+ "skip",
2068
+ "include_labels",
2069
+ "limit"
2070
+ ],
2071
+ "successStatus": 200,
2072
+ "scopes": [
2073
+ "read_entries"
2074
+ ],
2075
+ "responseSchema": "EntryListResponse"
2076
+ },
2077
+ "createTableEntry": {
2078
+ "operationId": "createTableEntry",
2079
+ "summary": "Create a table entry",
2080
+ "description": "Same as `POST /forms/{form_token}/entries`.",
2081
+ "tag": "Tables",
2082
+ "method": "post",
2083
+ "path": "/tables/{table_token}/entries",
2084
+ "params": [
2085
+ {
2086
+ "name": "table_token",
2087
+ "in": "path",
2088
+ "required": true
2089
+ }
2090
+ ],
2091
+ "paramNames": [
2092
+ "table_token"
2093
+ ],
2094
+ "body": {
2095
+ "contentType": "application/json",
2096
+ "required": true,
2097
+ "flatten": false,
2098
+ "param": "body"
2099
+ },
2100
+ "successStatus": 201,
2101
+ "scopes": [
2102
+ "write_entries"
2103
+ ],
2104
+ "responseSchema": "Entry"
2105
+ },
2106
+ "countTableEntries": {
2107
+ "operationId": "countTableEntries",
2108
+ "summary": "Count table entries",
2109
+ "description": "Exactly the same as `GET /forms/{form_token}/entries/count`, except that the target must be a table (otherwise 404 `table cannot be found`).",
2110
+ "tag": "Tables",
2111
+ "method": "get",
2112
+ "path": "/tables/{table_token}/entries/count",
2113
+ "params": [
2114
+ {
2115
+ "name": "table_token",
2116
+ "in": "path",
2117
+ "required": true
2118
+ },
2119
+ {
2120
+ "name": "filters",
2121
+ "in": "query",
2122
+ "required": false
2123
+ },
2124
+ {
2125
+ "name": "keyword",
2126
+ "in": "query",
2127
+ "required": false
2128
+ }
2129
+ ],
2130
+ "paramNames": [
2131
+ "table_token",
2132
+ "filters",
2133
+ "keyword"
2134
+ ],
2135
+ "successStatus": 200,
2136
+ "scopes": [
2137
+ "read_entries"
2138
+ ],
2139
+ "responseSchema": "EntryCountResponse"
2140
+ },
2141
+ "aggregateTableEntries": {
2142
+ "operationId": "aggregateTableEntries",
2143
+ "summary": "Aggregate table entries",
2144
+ "description": "Exactly the same as `GET /forms/{form_token}/entries/aggregate`, except that the target must be a table (otherwise 404 `table cannot be found`).\nFor the functions and groupings each field supports, see `GET /tables/{table_token}?include_analytics=true`.",
2145
+ "tag": "Tables",
2146
+ "method": "get",
2147
+ "path": "/tables/{table_token}/entries/aggregate",
2148
+ "params": [
2149
+ {
2150
+ "name": "table_token",
2151
+ "in": "path",
2152
+ "required": true
2153
+ },
2154
+ {
2155
+ "name": "metrics",
2156
+ "in": "query",
2157
+ "required": false
2158
+ },
2159
+ {
2160
+ "name": "dimensions",
2161
+ "in": "query",
2162
+ "required": false
2163
+ },
2164
+ {
2165
+ "name": "limit",
2166
+ "in": "query",
2167
+ "required": false
2168
+ },
2169
+ {
2170
+ "name": "filters",
2171
+ "in": "query",
2172
+ "required": false
2173
+ },
2174
+ {
2175
+ "name": "keyword",
2176
+ "in": "query",
2177
+ "required": false
2178
+ }
2179
+ ],
2180
+ "paramNames": [
2181
+ "table_token",
2182
+ "metrics",
2183
+ "dimensions",
2184
+ "limit",
2185
+ "filters",
2186
+ "keyword"
2187
+ ],
2188
+ "successStatus": 200,
2189
+ "scopes": [
2190
+ "read_entries"
2191
+ ],
2192
+ "responseSchema": "EntryAggregateResponse"
2193
+ },
2194
+ "summarizeTableEntries": {
2195
+ "operationId": "summarizeTableEntries",
2196
+ "summary": "Summarize table entries",
2197
+ "description": "Exactly the same as `GET /forms/{form_token}/entries/summary`, except that the target must be a table (otherwise 404 `table cannot be found`).",
2198
+ "tag": "Tables",
2199
+ "method": "get",
2200
+ "path": "/tables/{table_token}/entries/summary",
2201
+ "params": [
2202
+ {
2203
+ "name": "table_token",
2204
+ "in": "path",
2205
+ "required": true
2206
+ },
2207
+ {
2208
+ "name": "fields",
2209
+ "in": "query",
2210
+ "required": false
2211
+ },
2212
+ {
2213
+ "name": "include_overview",
2214
+ "in": "query",
2215
+ "required": false
2216
+ },
2217
+ {
2218
+ "name": "filters",
2219
+ "in": "query",
2220
+ "required": false
2221
+ },
2222
+ {
2223
+ "name": "keyword",
2224
+ "in": "query",
2225
+ "required": false
2226
+ }
2227
+ ],
2228
+ "paramNames": [
2229
+ "table_token",
2230
+ "fields",
2231
+ "include_overview",
2232
+ "filters",
2233
+ "keyword"
2234
+ ],
2235
+ "successStatus": 200,
2236
+ "scopes": [
2237
+ "read_entries"
2238
+ ],
2239
+ "responseSchema": "EntrySummaryResponse"
2240
+ },
2241
+ "countTableViewEntries": {
2242
+ "operationId": "countTableViewEntries",
2243
+ "summary": "Count the entries of a view",
2244
+ "description": "Exactly the same as `GET /forms/{form_token}/views/{view_token}/entries/count`, except that the target must be a table (otherwise 404 `table cannot be found`).",
2245
+ "tag": "Tables",
2246
+ "method": "get",
2247
+ "path": "/tables/{table_token}/views/{view_token}/entries/count",
2248
+ "params": [
2249
+ {
2250
+ "name": "table_token",
2251
+ "in": "path",
2252
+ "required": true
2253
+ },
2254
+ {
2255
+ "name": "view_token",
2256
+ "in": "path",
2257
+ "required": true
2258
+ },
2259
+ {
2260
+ "name": "filters",
2261
+ "in": "query",
2262
+ "required": false
2263
+ },
2264
+ {
2265
+ "name": "keyword",
2266
+ "in": "query",
2267
+ "required": false
2268
+ }
2269
+ ],
2270
+ "paramNames": [
2271
+ "table_token",
2272
+ "view_token",
2273
+ "filters",
2274
+ "keyword"
2275
+ ],
2276
+ "successStatus": 200,
2277
+ "scopes": [
2278
+ "read_entries"
2279
+ ],
2280
+ "responseSchema": "EntryCountResponse"
2281
+ },
2282
+ "aggregateTableViewEntries": {
2283
+ "operationId": "aggregateTableViewEntries",
2284
+ "summary": "Aggregate the entries of a view",
2285
+ "description": "Exactly the same as `GET /forms/{form_token}/views/{view_token}/entries/aggregate`, except that the target must be a table (otherwise 404 `table cannot be found`).",
2286
+ "tag": "Tables",
2287
+ "method": "get",
2288
+ "path": "/tables/{table_token}/views/{view_token}/entries/aggregate",
2289
+ "params": [
2290
+ {
2291
+ "name": "table_token",
2292
+ "in": "path",
2293
+ "required": true
2294
+ },
2295
+ {
2296
+ "name": "view_token",
2297
+ "in": "path",
2298
+ "required": true
2299
+ },
2300
+ {
2301
+ "name": "metrics",
2302
+ "in": "query",
2303
+ "required": false
2304
+ },
2305
+ {
2306
+ "name": "dimensions",
2307
+ "in": "query",
2308
+ "required": false
2309
+ },
2310
+ {
2311
+ "name": "limit",
2312
+ "in": "query",
2313
+ "required": false
2314
+ },
2315
+ {
2316
+ "name": "filters",
2317
+ "in": "query",
2318
+ "required": false
2319
+ },
2320
+ {
2321
+ "name": "keyword",
2322
+ "in": "query",
2323
+ "required": false
2324
+ }
2325
+ ],
2326
+ "paramNames": [
2327
+ "table_token",
2328
+ "view_token",
2329
+ "metrics",
2330
+ "dimensions",
2331
+ "limit",
2332
+ "filters",
2333
+ "keyword"
2334
+ ],
2335
+ "successStatus": 200,
2336
+ "scopes": [
2337
+ "read_entries"
2338
+ ],
2339
+ "responseSchema": "EntryAggregateResponse"
2340
+ },
2341
+ "summarizeTableViewEntries": {
2342
+ "operationId": "summarizeTableViewEntries",
2343
+ "summary": "Summarize the entries of a view",
2344
+ "description": "Exactly the same as `GET /forms/{form_token}/views/{view_token}/entries/summary`, except that the target must be a table (otherwise 404 `table cannot be found`).",
2345
+ "tag": "Tables",
2346
+ "method": "get",
2347
+ "path": "/tables/{table_token}/views/{view_token}/entries/summary",
2348
+ "params": [
2349
+ {
2350
+ "name": "table_token",
2351
+ "in": "path",
2352
+ "required": true
2353
+ },
2354
+ {
2355
+ "name": "view_token",
2356
+ "in": "path",
2357
+ "required": true
2358
+ },
2359
+ {
2360
+ "name": "fields",
2361
+ "in": "query",
2362
+ "required": false
2363
+ },
2364
+ {
2365
+ "name": "include_overview",
2366
+ "in": "query",
2367
+ "required": false
2368
+ },
2369
+ {
2370
+ "name": "filters",
2371
+ "in": "query",
2372
+ "required": false
2373
+ },
2374
+ {
2375
+ "name": "keyword",
2376
+ "in": "query",
2377
+ "required": false
2378
+ }
2379
+ ],
2380
+ "paramNames": [
2381
+ "table_token",
2382
+ "view_token",
2383
+ "fields",
2384
+ "include_overview",
2385
+ "filters",
2386
+ "keyword"
2387
+ ],
2388
+ "successStatus": 200,
2389
+ "scopes": [
2390
+ "read_entries"
2391
+ ],
2392
+ "responseSchema": "EntrySummaryResponse"
2393
+ },
2394
+ "getTableEntry": {
2395
+ "operationId": "getTableEntry",
2396
+ "summary": "Show a table entry",
2397
+ "description": "Same as `GET /forms/{form_token}/entries/{serial_number}`.",
2398
+ "tag": "Tables",
2399
+ "method": "get",
2400
+ "path": "/tables/{table_token}/entries/{serial_number}",
2401
+ "params": [
2402
+ {
2403
+ "name": "table_token",
2404
+ "in": "path",
2405
+ "required": true
2406
+ },
2407
+ {
2408
+ "name": "serial_number",
2409
+ "in": "path",
2410
+ "required": true
2411
+ },
2412
+ {
2413
+ "name": "fields",
2414
+ "in": "query",
2415
+ "required": false
2416
+ },
2417
+ {
2418
+ "name": "include_labels",
2419
+ "in": "query",
2420
+ "required": false
2421
+ }
2422
+ ],
2423
+ "paramNames": [
2424
+ "table_token",
2425
+ "serial_number",
2426
+ "fields",
2427
+ "include_labels"
2428
+ ],
2429
+ "successStatus": 200,
2430
+ "scopes": [
2431
+ "read_entries"
2432
+ ],
2433
+ "responseSchema": "Entry"
2434
+ },
2435
+ "updateTableEntryViaPost": {
2436
+ "operationId": "updateTableEntryViaPost",
2437
+ "summary": "Partially update a table entry (POST)",
2438
+ "description": "A POST alias for `PATCH` on the same path; it performs an incremental update.",
2439
+ "tag": "Tables",
2440
+ "method": "post",
2441
+ "path": "/tables/{table_token}/entries/{serial_number}",
2442
+ "params": [
2443
+ {
2444
+ "name": "table_token",
2445
+ "in": "path",
2446
+ "required": true
2447
+ },
2448
+ {
2449
+ "name": "serial_number",
2450
+ "in": "path",
2451
+ "required": true
2452
+ }
2453
+ ],
2454
+ "paramNames": [
2455
+ "table_token",
2456
+ "serial_number"
2457
+ ],
2458
+ "body": {
2459
+ "contentType": "application/json",
2460
+ "required": true,
2461
+ "flatten": false,
2462
+ "param": "body"
2463
+ },
2464
+ "successStatus": 200,
2465
+ "scopes": [
2466
+ "write_entries"
2467
+ ],
2468
+ "responseSchema": "Entry"
2469
+ },
2470
+ "replaceTableEntry": {
2471
+ "operationId": "replaceTableEntry",
2472
+ "summary": "Replace a table entry",
2473
+ "description": "Same as `PUT /forms/{form_token}/entries/{serial_number}` (full replacement).",
2474
+ "tag": "Tables",
2475
+ "method": "put",
2476
+ "path": "/tables/{table_token}/entries/{serial_number}",
2477
+ "params": [
2478
+ {
2479
+ "name": "table_token",
2480
+ "in": "path",
2481
+ "required": true
2482
+ },
2483
+ {
2484
+ "name": "serial_number",
2485
+ "in": "path",
2486
+ "required": true
2487
+ }
2488
+ ],
2489
+ "paramNames": [
2490
+ "table_token",
2491
+ "serial_number"
2492
+ ],
2493
+ "body": {
2494
+ "contentType": "application/json",
2495
+ "required": true,
2496
+ "flatten": false,
2497
+ "param": "body"
2498
+ },
2499
+ "successStatus": 200,
2500
+ "scopes": [
2501
+ "write_entries"
2502
+ ],
2503
+ "responseSchema": "Entry"
2504
+ },
2505
+ "updateTableEntry": {
2506
+ "operationId": "updateTableEntry",
2507
+ "summary": "Partially update a table entry",
2508
+ "description": "Same as `PATCH /forms/{form_token}/entries/{serial_number}` (incremental update).",
2509
+ "tag": "Tables",
2510
+ "method": "patch",
2511
+ "path": "/tables/{table_token}/entries/{serial_number}",
2512
+ "params": [
2513
+ {
2514
+ "name": "table_token",
2515
+ "in": "path",
2516
+ "required": true
2517
+ },
2518
+ {
2519
+ "name": "serial_number",
2520
+ "in": "path",
2521
+ "required": true
2522
+ }
2523
+ ],
2524
+ "paramNames": [
2525
+ "table_token",
2526
+ "serial_number"
2527
+ ],
2528
+ "body": {
2529
+ "contentType": "application/json",
2530
+ "required": true,
2531
+ "flatten": false,
2532
+ "param": "body"
2533
+ },
2534
+ "successStatus": 200,
2535
+ "scopes": [
2536
+ "write_entries"
2537
+ ],
2538
+ "responseSchema": "Entry"
2539
+ },
2540
+ "deleteTableEntry": {
2541
+ "operationId": "deleteTableEntry",
2542
+ "summary": "Delete a table entry",
2543
+ "description": "Same as `DELETE /forms/{form_token}/entries/{serial_number}`.",
2544
+ "tag": "Tables",
2545
+ "method": "delete",
2546
+ "path": "/tables/{table_token}/entries/{serial_number}",
2547
+ "params": [
2548
+ {
2549
+ "name": "table_token",
2550
+ "in": "path",
2551
+ "required": true
2552
+ },
2553
+ {
2554
+ "name": "serial_number",
2555
+ "in": "path",
2556
+ "required": true
2557
+ }
2558
+ ],
2559
+ "paramNames": [
2560
+ "table_token",
2561
+ "serial_number"
2562
+ ],
2563
+ "successStatus": 200,
2564
+ "scopes": [
2565
+ "write_entries"
2566
+ ]
2567
+ },
2568
+ "listTableEntryComments": {
2569
+ "operationId": "listTableEntryComments",
2570
+ "summary": "List a table entry's comments",
2571
+ "description": "Returns all comments on this table entry in ascending order of creation time, under the same rules as form entry comments. Returns 404 (table cannot be found) when the token is not a table.",
2572
+ "tag": "Comments",
2573
+ "method": "get",
2574
+ "path": "/tables/{table_token}/entries/{serial_number}/comments",
2575
+ "params": [
2576
+ {
2577
+ "name": "table_token",
2578
+ "in": "path",
2579
+ "required": true
2580
+ },
2581
+ {
2582
+ "name": "serial_number",
2583
+ "in": "path",
2584
+ "required": true
2585
+ }
2586
+ ],
2587
+ "paramNames": [
2588
+ "table_token",
2589
+ "serial_number"
2590
+ ],
2591
+ "successStatus": 200,
2592
+ "scopes": [
2593
+ "read_entries"
2594
+ ]
2595
+ },
2596
+ "createTableEntryComment": {
2597
+ "operationId": "createTableEntryComment",
2598
+ "summary": "Comment on a table entry",
2599
+ "description": "Creates a comment on this table entry, with the same parameters and limits as form entry comments (content is required, at most 2000 characters, mentioned users must be cooperators, parent_id must belong to the same entry). Returns 404 (table cannot be found) when the token is not a table.",
2600
+ "tag": "Comments",
2601
+ "method": "post",
2602
+ "path": "/tables/{table_token}/entries/{serial_number}/comments",
2603
+ "params": [
2604
+ {
2605
+ "name": "table_token",
2606
+ "in": "path",
2607
+ "required": true
2608
+ },
2609
+ {
2610
+ "name": "serial_number",
2611
+ "in": "path",
2612
+ "required": true
2613
+ }
2614
+ ],
2615
+ "paramNames": [
2616
+ "table_token",
2617
+ "serial_number"
2618
+ ],
2619
+ "body": {
2620
+ "contentType": "application/json",
2621
+ "required": true,
2622
+ "flatten": true
2623
+ },
2624
+ "successStatus": 201,
2625
+ "scopes": [
2626
+ "read_entries"
2627
+ ],
2628
+ "responseSchema": "EntryComment"
2629
+ },
2630
+ "updateTableEntryComment": {
2631
+ "operationId": "updateTableEntryComment",
2632
+ "summary": "Update a comment on a table entry",
2633
+ "description": "Changes the content of a table entry comment; PUT is also accepted. Only the comment's author can edit it, otherwise returns 400; returns 404 when the comment does not belong to this entry. Returns 404 (table cannot be found) when the token is not a table.",
2634
+ "tag": "Comments",
2635
+ "method": "patch",
2636
+ "path": "/tables/{table_token}/entries/{serial_number}/comments/{comment_id}",
2637
+ "params": [
2638
+ {
2639
+ "name": "table_token",
2640
+ "in": "path",
2641
+ "required": true
2642
+ },
2643
+ {
2644
+ "name": "serial_number",
2645
+ "in": "path",
2646
+ "required": true
2647
+ },
2648
+ {
2649
+ "name": "comment_id",
2650
+ "in": "path",
2651
+ "required": true
2652
+ }
2653
+ ],
2654
+ "paramNames": [
2655
+ "table_token",
2656
+ "serial_number",
2657
+ "comment_id"
2658
+ ],
2659
+ "body": {
2660
+ "contentType": "application/json",
2661
+ "required": true,
2662
+ "flatten": true
2663
+ },
2664
+ "successStatus": 200,
2665
+ "scopes": [
2666
+ "read_entries"
2667
+ ],
2668
+ "responseSchema": "EntryComment"
2669
+ },
2670
+ "deleteTableEntryComment": {
2671
+ "operationId": "deleteTableEntryComment",
2672
+ "summary": "Delete a comment on a table entry",
2673
+ "description": "Deletes a table entry comment. The comment's author, the table's creator, or a cooperator with the admin role can delete it; other cooperators get 400; a comment already deleted returns 404. Returns 404 (table cannot be found) when the token is not a table.",
2674
+ "tag": "Comments",
2675
+ "method": "delete",
2676
+ "path": "/tables/{table_token}/entries/{serial_number}/comments/{comment_id}",
2677
+ "params": [
2678
+ {
2679
+ "name": "table_token",
2680
+ "in": "path",
2681
+ "required": true
2682
+ },
2683
+ {
2684
+ "name": "serial_number",
2685
+ "in": "path",
2686
+ "required": true
2687
+ },
2688
+ {
2689
+ "name": "comment_id",
2690
+ "in": "path",
2691
+ "required": true
2692
+ }
2693
+ ],
2694
+ "paramNames": [
2695
+ "table_token",
2696
+ "serial_number",
2697
+ "comment_id"
2698
+ ],
2699
+ "successStatus": 200,
2700
+ "scopes": [
2701
+ "read_entries"
2702
+ ]
2703
+ },
2704
+ "listTableViews": {
2705
+ "operationId": "listTableViews",
2706
+ "summary": "List a table's views",
2707
+ "description": "Returns the views of this table visible to the current caller, under the same rules as listing form views. Returns 404 (table cannot be found) when the token is not a table (kind is not table).",
2708
+ "tag": "Views",
2709
+ "method": "get",
2710
+ "path": "/tables/{table_token}/views",
2711
+ "params": [
2712
+ {
2713
+ "name": "table_token",
2714
+ "in": "path",
2715
+ "required": true
2716
+ }
2717
+ ],
2718
+ "paramNames": [
2719
+ "table_token"
2720
+ ],
2721
+ "successStatus": 200,
2722
+ "scopes": [
2723
+ "forms"
2724
+ ]
2725
+ },
2726
+ "createTableView": {
2727
+ "operationId": "createTableView",
2728
+ "summary": "Create a view on a table",
2729
+ "description": "Creates a view on a table, with the same parameters and limits as creating a form view (at most 100 views per user per table, name at most 120 characters, an invalid filter returns 422). Returns 404 (table cannot be found) when the token is not a table. view_type can be form (a form view, a public fill page); see creating a form view for the rules.",
2730
+ "tag": "Views",
2731
+ "method": "post",
2732
+ "path": "/tables/{table_token}/views",
2733
+ "params": [
2734
+ {
2735
+ "name": "table_token",
2736
+ "in": "path",
2737
+ "required": true
2738
+ }
2739
+ ],
2740
+ "paramNames": [
2741
+ "table_token"
2742
+ ],
2743
+ "body": {
2744
+ "contentType": "application/json",
2745
+ "required": true,
2746
+ "flatten": false,
2747
+ "param": "body"
2748
+ },
2749
+ "successStatus": 201,
2750
+ "scopes": [
2751
+ "forms"
2752
+ ],
2753
+ "responseSchema": "FormView"
2754
+ },
2755
+ "getTableView": {
2756
+ "operationId": "getTableView",
2757
+ "summary": "Show a view of a table",
2758
+ "description": "Returns one table view; only views visible to the caller can be read. Returns 404 (table cannot be found) when the token is not a table.",
2759
+ "tag": "Views",
2760
+ "method": "get",
2761
+ "path": "/tables/{table_token}/views/{view_token}",
2762
+ "params": [
2763
+ {
2764
+ "name": "table_token",
2765
+ "in": "path",
2766
+ "required": true
2767
+ },
2768
+ {
2769
+ "name": "view_token",
2770
+ "in": "path",
2771
+ "required": true
2772
+ }
2773
+ ],
2774
+ "paramNames": [
2775
+ "table_token",
2776
+ "view_token"
2777
+ ],
2778
+ "successStatus": 200,
2779
+ "scopes": [
2780
+ "forms"
2781
+ ],
2782
+ "responseSchema": "FormView"
2783
+ },
2784
+ "updateTableView": {
2785
+ "operationId": "updateTableView",
2786
+ "summary": "Update a view of a table",
2787
+ "description": "Updates a table view's settings; PUT is also accepted. The rules are the same as for updating a form view: only the creator can change visibility (otherwise 403), and a filter or model validation failure returns 422. Returns 404 (table cannot be found) when the token is not a table.",
2788
+ "tag": "Views",
2789
+ "method": "patch",
2790
+ "path": "/tables/{table_token}/views/{view_token}",
2791
+ "params": [
2792
+ {
2793
+ "name": "table_token",
2794
+ "in": "path",
2795
+ "required": true
2796
+ },
2797
+ {
2798
+ "name": "view_token",
2799
+ "in": "path",
2800
+ "required": true
2801
+ }
2802
+ ],
2803
+ "paramNames": [
2804
+ "table_token",
2805
+ "view_token"
2806
+ ],
2807
+ "body": {
2808
+ "contentType": "application/json",
2809
+ "required": true,
2810
+ "flatten": false,
2811
+ "param": "body"
2812
+ },
2813
+ "successStatus": 200,
2814
+ "scopes": [
2815
+ "forms"
2816
+ ],
2817
+ "responseSchema": "FormView"
2818
+ },
2819
+ "deleteTableView": {
2820
+ "operationId": "deleteTableView",
2821
+ "summary": "Delete a view of a table",
2822
+ "description": "Deletes a table view. Predefined views, views whose view_scope is form, and the caller's last visible view cannot be deleted; these return 422. Returns 404 (table cannot be found) when the token is not a table. Deleting a form view requires a predefined role that can add entries (otherwise 403); once deleted, its fill link stops working immediately, and this cannot be undone.",
2823
+ "tag": "Views",
2824
+ "method": "delete",
2825
+ "path": "/tables/{table_token}/views/{view_token}",
2826
+ "params": [
2827
+ {
2828
+ "name": "table_token",
2829
+ "in": "path",
2830
+ "required": true
2831
+ },
2832
+ {
2833
+ "name": "view_token",
2834
+ "in": "path",
2835
+ "required": true
2836
+ }
2837
+ ],
2838
+ "paramNames": [
2839
+ "table_token",
2840
+ "view_token"
2841
+ ],
2842
+ "successStatus": 200,
2843
+ "scopes": [
2844
+ "forms"
2845
+ ]
2846
+ },
2847
+ "listTableViewEntries": {
2848
+ "operationId": "listTableViewEntries",
2849
+ "summary": "List a table view's entries",
2850
+ "description": "Returns entries using the table view's filters and sort, at most 50 per page; pagination and the rules for which fields are returned are the same as for form view entries. Returns 404 (table cannot be found) when the token is not a table.",
2851
+ "tag": "Views",
2852
+ "method": "get",
2853
+ "path": "/tables/{table_token}/views/{view_token}/entries",
2854
+ "params": [
2855
+ {
2856
+ "name": "table_token",
2857
+ "in": "path",
2858
+ "required": true
2859
+ },
2860
+ {
2861
+ "name": "view_token",
2862
+ "in": "path",
2863
+ "required": true
2864
+ },
2865
+ {
2866
+ "name": "next",
2867
+ "in": "query",
2868
+ "required": false
2869
+ },
2870
+ {
2871
+ "name": "include_labels",
2872
+ "in": "query",
2873
+ "required": false
2874
+ }
2875
+ ],
2876
+ "paramNames": [
2877
+ "table_token",
2878
+ "view_token",
2879
+ "next",
2880
+ "include_labels"
2881
+ ],
2882
+ "successStatus": 200,
2883
+ "scopes": [
2884
+ "read_entries"
2885
+ ],
2886
+ "responseSchema": "EntryListResponse"
2887
+ },
2888
+ "listOpensearchQueries": {
2889
+ "operationId": "listOpensearchQueries",
2890
+ "summary": "List public queries",
2891
+ "description": "Returns the public queries created by the current caller (an account access token counts as the account owner), newest first, with summary fields only. With form_token, returns only the queries under that form; returns 404 when form_token does not exist or the caller cannot access it, instead of ignoring the parameter.",
2892
+ "tag": "OpenSearch",
2893
+ "method": "get",
2894
+ "path": "/opensearch/queries",
2895
+ "params": [
2896
+ {
2897
+ "name": "form_token",
2898
+ "in": "query",
2899
+ "required": false
2900
+ }
2901
+ ],
2902
+ "paramNames": [
2903
+ "form_token"
2904
+ ],
2905
+ "successStatus": 200,
2906
+ "scopes": [
2907
+ "forms"
2908
+ ]
2909
+ },
2910
+ "createOpensearchQuery": {
2911
+ "operationId": "createOpensearchQuery",
2912
+ "summary": "Create a public query",
2913
+ "description": "Creates a public query on the form given by form_token, with the current caller as its creator. The caller must be able to manage the form: no access returns 404, read but not manage returns 403; a plan without the public query feature returns 402. Fields referenced in search_field_rules must be searchable fields of the form, and those in display_field_rules must be displayable fields; otherwise returns 400 listing the available api_code values. search_field_rules / display_field_rules, when passed, cannot be empty arrays; scope_conditions requires a plan that supports limiting the range of searchable entries. A preview image is generated asynchronously after saving.",
2914
+ "tag": "OpenSearch",
2915
+ "method": "post",
2916
+ "path": "/opensearch/queries",
2917
+ "params": [],
2918
+ "paramNames": [],
2919
+ "body": {
2920
+ "contentType": "application/json",
2921
+ "required": true,
2922
+ "flatten": false,
2923
+ "param": "body"
2924
+ },
2925
+ "successStatus": 201,
2926
+ "scopes": [
2927
+ "forms"
2928
+ ],
2929
+ "responseSchema": "OpensearchQuery"
2930
+ },
2931
+ "getOpensearchQuery": {
2932
+ "operationId": "getOpensearchQuery",
2933
+ "summary": "Show a public query",
2934
+ "description": "Returns the public query details, including the search field rules and display field rules. The caller can read only queries it created; another user's query returns 404 (opensearch query cannot be found).",
2935
+ "tag": "OpenSearch",
2936
+ "method": "get",
2937
+ "path": "/opensearch/queries/{query_token}",
2938
+ "params": [
2939
+ {
2940
+ "name": "query_token",
2941
+ "in": "path",
2942
+ "required": true
2943
+ }
2944
+ ],
2945
+ "paramNames": [
2946
+ "query_token"
2947
+ ],
2948
+ "successStatus": 200,
2949
+ "scopes": [
2950
+ "forms"
2951
+ ],
2952
+ "responseSchema": "OpensearchQuery"
2953
+ },
2954
+ "updateOpensearchQuery": {
2955
+ "operationId": "updateOpensearchQuery",
2956
+ "summary": "Update a public query",
2957
+ "description": "Updates a public query the caller created; PUT is also accepted. Only the keys present in the request are updated. Returns 400 when the query's form has been deleted. Field rules are validated as on create: referencing a field that cannot be searched / displayed, an empty rule array, an empty name and the like all return 400. An update does not check form manage permission or whether the plan includes public queries.",
2958
+ "tag": "OpenSearch",
2959
+ "method": "patch",
2960
+ "path": "/opensearch/queries/{query_token}",
2961
+ "params": [
2962
+ {
2963
+ "name": "query_token",
2964
+ "in": "path",
2965
+ "required": true
2966
+ }
2967
+ ],
2968
+ "paramNames": [
2969
+ "query_token"
2970
+ ],
2971
+ "body": {
2972
+ "contentType": "application/json",
2973
+ "required": true,
2974
+ "flatten": false,
2975
+ "param": "body"
2976
+ },
2977
+ "successStatus": 200,
2978
+ "scopes": [
2979
+ "forms"
2980
+ ],
2981
+ "responseSchema": "OpensearchQuery"
2982
+ },
2983
+ "listOpensearchQuerySuggestions": {
2984
+ "operationId": "listOpensearchQuerySuggestions",
2985
+ "summary": "Suggest fields for a public query",
2986
+ "description": "Returns the search fields and display fields a form offers for public queries, plus the recommended field api_code values, for building search_field_rules / display_field_rules. The caller must be able to manage the form: no access returns 404, read but not manage returns 403. Whether the plan includes public queries is not checked.",
2987
+ "tag": "OpenSearch",
2988
+ "method": "get",
2989
+ "path": "/opensearch/query_suggestions",
2990
+ "params": [
2991
+ {
2992
+ "name": "form_token",
2993
+ "in": "query",
2994
+ "required": true
2995
+ }
2996
+ ],
2997
+ "paramNames": [
2998
+ "form_token"
2999
+ ],
3000
+ "successStatus": 200,
3001
+ "scopes": [
3002
+ "forms"
3003
+ ]
3004
+ },
3005
+ "listFolders": {
3006
+ "operationId": "listFolders",
3007
+ "summary": "List folders",
3008
+ "description": "Lists the folders the current user has manage permission on (form folders and table folders alike, told apart by `kind`), newest first. With an account-level credential, returns the account owner's folders.\n`limit` defaults to 50 and is clamped to 1 to 100; there is no paging: `total` is the full count, `count` the number returned this time.",
3009
+ "tag": "Folders",
3010
+ "method": "get",
3011
+ "path": "/folders",
3012
+ "params": [
3013
+ {
3014
+ "name": "limit",
3015
+ "in": "query",
3016
+ "required": false
3017
+ }
3018
+ ],
3019
+ "paramNames": [
3020
+ "limit"
3021
+ ],
3022
+ "successStatus": 200,
3023
+ "scopes": [
3024
+ "forms"
3025
+ ]
3026
+ },
3027
+ "createFolder": {
3028
+ "operationId": "createFolder",
3029
+ "summary": "Create a folder",
3030
+ "description": "Creates a folder as the current user; the creator becomes the folder's manager. `kind` decides whether the folder holds forms (`form`, the default) or tables (`table`).\nReturns 400 `Name cannot be empty` when `name` is empty; returns 400 `Kind must be one of: form, table` when `kind` is not form / table; returns 400 when model validation fails, with the validation message in `error_description`.",
3031
+ "tag": "Folders",
3032
+ "method": "post",
3033
+ "path": "/folders",
3034
+ "params": [],
3035
+ "paramNames": [],
3036
+ "body": {
3037
+ "contentType": "application/json",
3038
+ "required": true,
3039
+ "flatten": true
3040
+ },
3041
+ "successStatus": 201,
3042
+ "scopes": [
3043
+ "forms"
3044
+ ],
3045
+ "responseSchema": "Folder"
3046
+ },
3047
+ "listPredefinedChoicesSets": {
3048
+ "operationId": "listPredefinedChoicesSets",
3049
+ "summary": "List predefined choice sets",
3050
+ "description": "Lists the current account's custom predefined choice sets (type custom), only those matching the locale of the current request (as the server implements it); the built-in global choice sets are not returned.",
3051
+ "tag": "Predefined Choices Sets",
3052
+ "method": "get",
3053
+ "path": "/predefined_choices_sets",
3054
+ "params": [],
3055
+ "paramNames": [],
3056
+ "successStatus": 200,
3057
+ "scopes": [
3058
+ "form_setting"
3059
+ ]
3060
+ },
3061
+ "createPredefinedChoicesSet": {
3062
+ "operationId": "createPredefinedChoicesSet",
3063
+ "summary": "Create a predefined choice set",
3064
+ "description": "Creates a custom predefined choice set in the current account. It looks up by `label`: when the account already has a set with the same label, that set's `choices` are overwritten (in effect an update); otherwise a new set is created.\nThe request body must be wrapped under the `predefined_choices_set` key; returns 400 when the key is missing. Empty strings in `choices` are dropped; neither `label` nor the remaining `choices` may be empty, otherwise returns 400 with the body `{ errors, status: \"failed\" }`.\nReturns 200 on success (not 201).",
3065
+ "tag": "Predefined Choices Sets",
3066
+ "method": "post",
3067
+ "path": "/predefined_choices_sets",
3068
+ "params": [],
3069
+ "paramNames": [],
3070
+ "body": {
3071
+ "contentType": "application/json",
3072
+ "required": true,
3073
+ "flatten": true
3074
+ },
3075
+ "successStatus": 200,
3076
+ "scopes": [
3077
+ "form_setting"
3078
+ ],
3079
+ "responseSchema": "PredefinedChoicesSet"
3080
+ },
3081
+ "updatePredefinedChoicesSet": {
3082
+ "operationId": "updatePredefinedChoicesSet",
3083
+ "summary": "Update a predefined choice set",
3084
+ "description": "Updates the `label` and / or `choices` of one of the current account's custom predefined choice sets. PUT is also accepted and behaves the same.\nOnly a set of type custom that belongs to the current account can be updated: a global set or another account's set returns 403 `{ errors: \"forbidden\", status: \"failed\" }`; an ID that does not exist returns 404 `{ errors: \"not found\", status: \"failed\" }`; a validation failure returns 400 `{ errors, status: \"failed\" }`.",
3085
+ "tag": "Predefined Choices Sets",
3086
+ "method": "patch",
3087
+ "path": "/predefined_choices_sets/{id}",
3088
+ "params": [
3089
+ {
3090
+ "name": "id",
3091
+ "in": "path",
3092
+ "required": true
3093
+ }
3094
+ ],
3095
+ "paramNames": [
3096
+ "id"
3097
+ ],
3098
+ "body": {
3099
+ "contentType": "application/json",
3100
+ "required": true,
3101
+ "flatten": true
3102
+ },
3103
+ "successStatus": 200,
3104
+ "scopes": [
3105
+ "form_setting"
3106
+ ],
3107
+ "responseSchema": "PredefinedChoicesSet"
3108
+ },
3109
+ "deletePredefinedChoicesSet": {
3110
+ "operationId": "deletePredefinedChoicesSet",
3111
+ "summary": "Delete a predefined choice set",
3112
+ "description": "Deletes one of the current account's custom predefined choice sets; returns 200 with no response body on success.\nOnly a set of type custom that belongs to the current account can be deleted: a global set or another account's set returns 403 `{ errors: \"forbidden\", status: \"failed\" }`; an ID that does not exist returns 404 `{ errors: \"not found\", status: \"failed\" }`.",
3113
+ "tag": "Predefined Choices Sets",
3114
+ "method": "delete",
3115
+ "path": "/predefined_choices_sets/{id}",
3116
+ "params": [
3117
+ {
3118
+ "name": "id",
3119
+ "in": "path",
3120
+ "required": true
3121
+ }
3122
+ ],
3123
+ "paramNames": [
3124
+ "id"
3125
+ ],
3126
+ "successStatus": 200,
3127
+ "scopes": [
3128
+ "form_setting"
3129
+ ]
3130
+ },
3131
+ "createTemplateUsage": {
3132
+ "operationId": "createTemplateUsage",
3133
+ "summary": "Create a form from a template",
3134
+ "description": "Uses a template from the template market as the current user, copies it into a new form, and returns the new form's token and edit page URL.\nThe template is given by `id` (or `template_id`), which takes a template token or a 24-character hexadecimal ID. Optional parameters: `tags` (tags, an array or a comma-separated string), `tag_id` / `folder_id` (the tag / folder the new form goes into), `scene` (target scene; falls back to form when the template has fields the scene does not allow), `frm` (source marker; affects the recorded created_from), `create_source`, `group_id`.\nPayment-related branches:\n- Paid template the current user has not bought: returns 200 with the body `{ template_url }` (the template purchase page URL), and no form is created.\n- Template uses paid features the current plan does not offer: returns 403 `{ error: \"CAN_FEATURE_TRIAL\", target_plan, target_trial_type, ... }` when the caller is an admin and a feature trial can be started; otherwise returns 403 `{ error: \"PAID_FEATURE_REQUIRED\", target_plan, template_url }`; an account from a channel partner gets 403 `{ error: \"UNAVAILABLE_TO_TRIAL_OR_UPGRADE\" }`.\n- With `form_app_trial_alert` passed and the template bound to form apps that must be bought / tried: returns 200 `{ error: \"CANNOT_FORM_APP_TRIAL\" | \"FORM_APP_TRIAL_REQUIRED\", ... }`; confirm with `confirm_unbind_form_app` / `confirm_form_app_trial` and retry.\nWhen form creation fails (failing the content risk check included), returns 400 `{ error }`. When the template does not exist, returns 404 with an HTML page, not JSON.\n`mobile_editor_forbidden` appears only on a mobile request when the new form has the card layout and the current plan cannot use the mobile editor.",
3135
+ "tag": "Templates",
3136
+ "method": "post",
3137
+ "path": "/template_usages",
3138
+ "params": [],
3139
+ "paramNames": [],
3140
+ "body": {
3141
+ "contentType": "application/json",
3142
+ "required": true,
3143
+ "flatten": true
3144
+ },
3145
+ "successStatus": 200,
3146
+ "scopes": [
3147
+ "forms"
3148
+ ]
3149
+ },
3150
+ "listContacts": {
3151
+ "operationId": "listContacts",
3152
+ "summary": "List contacts",
3153
+ "description": "Lists the current user's contacts page by page, by ID descending, a fixed 50 per page. With an account-level credential, returns the account owner's contacts.\nCursor paging: `next` in the response is the ID of the first contact on the next page; pass it as the query parameter `next` to get that page. `next` is null when there is no more data.",
3154
+ "tag": "Contacts",
3155
+ "method": "get",
3156
+ "path": "/contacts",
3157
+ "params": [
3158
+ {
3159
+ "name": "next",
3160
+ "in": "query",
3161
+ "required": false
3162
+ }
3163
+ ],
3164
+ "paramNames": [
3165
+ "next"
3166
+ ],
3167
+ "successStatus": 200,
3168
+ "scopes": [
3169
+ "read_contacts"
3170
+ ]
3171
+ },
3172
+ "getCurrentUser": {
3173
+ "operationId": "getCurrentUser",
3174
+ "summary": "Show the current user",
3175
+ "description": "Returns the user behind the current credential. With an account-level credential (no specific user), returns the account owner.",
3176
+ "tag": "Account",
3177
+ "method": "get",
3178
+ "path": "/me",
3179
+ "params": [],
3180
+ "paramNames": [],
3181
+ "successStatus": 200,
3182
+ "scopes": [
3183
+ "users"
3184
+ ],
3185
+ "responseSchema": "CurrentUser"
3186
+ },
3187
+ "getBillingAccount": {
3188
+ "operationId": "getBillingAccount",
3189
+ "summary": "Show the current account",
3190
+ "description": "Returns the account the current credential belongs to: plan, this month's usage and quota, feature trial status, and the bound payment merchant / WeChat Pay / Alipay accounts.\n`usage` is null when the account has no usage record for this month yet; for an add-on service with unlimited quota, only `unit`, `unlimited: true` and `consumed_quota` are returned.",
3191
+ "tag": "Account",
3192
+ "method": "get",
3193
+ "path": "/billing_account",
3194
+ "params": [],
3195
+ "paramNames": [],
3196
+ "successStatus": 200,
3197
+ "scopes": [
3198
+ "users"
3199
+ ],
3200
+ "responseSchema": "BillingAccount"
3201
+ },
3202
+ "listBillingAccountUsers": {
3203
+ "operationId": "listBillingAccountUsers",
3204
+ "summary": "List account members",
3205
+ "description": "Lists the members of the current account (deactivated members included), by status ascending (active first), then by creation time, newest first.\n`limit` defaults to 50 and is clamped to 1 to 100; there is no paging: `total` is the total number of members, `count` the number returned this time.",
3206
+ "tag": "Account",
3207
+ "method": "get",
3208
+ "path": "/billing_account/users",
3209
+ "params": [
3210
+ {
3211
+ "name": "limit",
3212
+ "in": "query",
3213
+ "required": false
3214
+ }
3215
+ ],
3216
+ "paramNames": [
3217
+ "limit"
3218
+ ],
3219
+ "successStatus": 200,
3220
+ "scopes": [
3221
+ "users"
3222
+ ]
3223
+ },
3224
+ "listBillingAccountInvoices": {
3225
+ "operationId": "listBillingAccountInvoices",
3226
+ "summary": "List account e-invoices",
3227
+ "description": "Lists the e-invoices the current account has requested (newest request first, all at once, no paging), and the spending that can be invoiced but has not been yet.\nOnly an account admin can read it: a non-admin member gets 403 (`Only an account admin can read this.`); an account-level credential (no specific user) is treated as the account owner.",
3228
+ "tag": "Account",
3229
+ "method": "get",
3230
+ "path": "/billing_account/invoices",
3231
+ "params": [],
3232
+ "paramNames": [],
3233
+ "successStatus": 200,
3234
+ "scopes": [
3235
+ "users"
3236
+ ],
3237
+ "responseSchema": "BillingAccountInvoicesResponse"
3238
+ },
3239
+ "listBillingAccountPaymentHistories": {
3240
+ "operationId": "listBillingAccountPaymentHistories",
3241
+ "summary": "List account payment history",
3242
+ "description": "Lists the current account's top-ups and spending on Jinshuju (account balance transactions such as buying plans, SMS, AI points and attachment storage), newest first.\nThis is what the account itself spent; money received through payment forms is not included.\nOnly an account admin can read it: a non-admin member gets 403 (`Only an account admin can read this.`); an account-level credential (no specific user) is treated as the account owner.\nThere is no paging: `limit` defaults to 50 and is clamped to 1 to 1000; `total_records` is the number of matching records, `returned_records` the number returned this time.\nWith `include_balance=true`, `current_balance` is included (account balance and the remaining quota of each item); when records are returned, `statistics` is included (counting only the returned records).",
3243
+ "tag": "Account",
3244
+ "method": "get",
3245
+ "path": "/billing_account/payment_histories",
3246
+ "params": [
3247
+ {
3248
+ "name": "start_date",
3249
+ "in": "query",
3250
+ "required": false
3251
+ },
3252
+ {
3253
+ "name": "end_date",
3254
+ "in": "query",
3255
+ "required": false
3256
+ },
3257
+ {
3258
+ "name": "verb",
3259
+ "in": "query",
3260
+ "required": false
3261
+ },
3262
+ {
3263
+ "name": "limit",
3264
+ "in": "query",
3265
+ "required": false
3266
+ },
3267
+ {
3268
+ "name": "include_balance",
3269
+ "in": "query",
3270
+ "required": false
3271
+ }
3272
+ ],
3273
+ "paramNames": [
3274
+ "start_date",
3275
+ "end_date",
3276
+ "verb",
3277
+ "limit",
3278
+ "include_balance"
3279
+ ],
3280
+ "successStatus": 200,
3281
+ "scopes": [
3282
+ "users"
3283
+ ],
3284
+ "responseSchema": "BillingAccountPaymentHistoriesResponse"
3285
+ },
3286
+ "getTradeMerchant": {
3287
+ "operationId": "getTradeMerchant",
3288
+ "summary": "Show the 小金商户",
3289
+ "description": "Returns the current account's 小金商户 (the merchant Jinshuju collects payments for) and its onboarding progress: merchant profile, legal entity and contact details, balance, settlement details, payment channel authorization, freeze status, bound payment forms, and the URL for the next step.\n- When the account has no 小金商户 yet, it still returns 200: `merchant_stage` says how far the onboarding application has got, `merchant` / `subject` / `contact` / `balance` / `settlement` / `freeze` are null, and `channels` is an empty array.\n- An account that collects payments through its own WeChat Pay / Alipay merchant (direct connection) has no rate, settlement account, balance or onboarding status on Jinshuju, and none of these is given here.\n- Sensitive fields such as bank card numbers, mobile numbers, emails and ID numbers are masked by the rules of the product's \"Fund account information\" page: 4 characters are kept at each end (mobile numbers keep the first 3 and last 4), and the middle is replaced with `*`.\n- `payment_form_tokens` holds only the payment forms the current identity can access (quick payment forms included); with an account-level credential, it is computed for the account owner.\n- `balance` is null when the balance lookup fails; that does not mean the balance is 0.",
3290
+ "tag": "Trade",
3291
+ "method": "get",
3292
+ "path": "/trade/merchant",
3293
+ "params": [],
3294
+ "paramNames": [],
3295
+ "successStatus": 200,
3296
+ "scopes": [
3297
+ "users"
3298
+ ],
3299
+ "responseSchema": "TradeMerchant"
3300
+ },
3301
+ "listTradeTransactions": {
3302
+ "operationId": "listTradeTransactions",
3303
+ "summary": "List payment orders",
3304
+ "description": "Lists the payment orders of the 小金商户 (orders customers place by paying on payment forms), newest order first. Only 小金商户 orders are included: orders collected through a direct connection, simulated-payment orders, and unpaid quick payment records are all left out.\n- The date range filters on order time, in Beijing time (UTC+8); `start_date` / `end_date` are both inclusive and must be passed together. Without them, it defaults to the last 90 days; with `order_no` and no dates, there is no time limit. `queried_range` in the response gives the range actually used (both ends null when there is no time limit).\n- Detail limits: the date range spans at most 90 days, and at most 200 orders match. Past either limit, no details are returned: `transactions` is null, `detail_limit` says why, and `stats` gives the transaction amount, paid count and order count for the range; narrow the range and query again.\n- Paging: `limit` is the page size (default and maximum 50), and `next` is a page number. When there is another page, the response carries `next` (the next page number); pass it back as is. `page_info.total` is the total number of matching orders.\n- Returns 404 when the account has no 小金商户.",
3305
+ "tag": "Trade",
3306
+ "method": "get",
3307
+ "path": "/trade/transactions",
3308
+ "params": [
3309
+ {
3310
+ "name": "start_date",
3311
+ "in": "query",
3312
+ "required": false
3313
+ },
3314
+ {
3315
+ "name": "end_date",
3316
+ "in": "query",
3317
+ "required": false
3318
+ },
3319
+ {
3320
+ "name": "paid_status",
3321
+ "in": "query",
3322
+ "required": false,
3323
+ "array": true
3324
+ },
3325
+ {
3326
+ "name": "payment_channel",
3327
+ "in": "query",
3328
+ "required": false
3329
+ },
3330
+ {
3331
+ "name": "form_token",
3332
+ "in": "query",
3333
+ "required": false
3334
+ },
3335
+ {
3336
+ "name": "order_no",
3337
+ "in": "query",
3338
+ "required": false
3339
+ },
3340
+ {
3341
+ "name": "limit",
3342
+ "in": "query",
3343
+ "required": false
3344
+ },
3345
+ {
3346
+ "name": "next",
3347
+ "in": "query",
3348
+ "required": false
3349
+ }
3350
+ ],
3351
+ "paramNames": [
3352
+ "start_date",
3353
+ "end_date",
3354
+ "paid_status",
3355
+ "payment_channel",
3356
+ "form_token",
3357
+ "order_no",
3358
+ "limit",
3359
+ "next"
3360
+ ],
3361
+ "successStatus": 200,
3362
+ "scopes": [
3363
+ "users"
3364
+ ],
3365
+ "responseSchema": "TradeTransactionListResponse"
3366
+ },
3367
+ "aggregateTradeTransactions": {
3368
+ "operationId": "aggregateTradeTransactions",
3369
+ "summary": "Aggregate payment orders",
3370
+ "description": "Totals the transaction amount, paid count and order count of the 小金商户 payment orders over a date range, optionally grouped by one dimension. Orders are counted as in \"List payment orders\" (only 小金商户 orders; no simulated payments and no unpaid quick payment records); the totals cover the whole range and are not bound by the detail limits.\n- The date range filters on order time, in Beijing time (UTC+8); both ends are inclusive and must be passed together. Without them, it defaults to the last 30 days. The range spans at most 366 days; a longer one returns 400.\n- `transactions_amount` (transaction amount): the amount of paid-type orders minus each order's successful refunds, counted on the day the order was placed; refunded and unpaid orders contribute 0. `transactions_count` (paid count): the number of paid, partially refunded and refunding orders. `orders_count` (order count): the number of all matching orders, unpaid included.\n- `group_by=time` groups by time: by day for a range under 90 days, by week from 90 days, by month from 365 days; `granularity` gives the granularity, and periods without orders are filled with zero. `paid_status` / `payment_channel` make one group per value; the group whose `payment_channel` is null holds orders that have not started payment. Under the same filters, the groups add up to the total.\n- Returns 404 when the account has no 小金商户.",
3371
+ "tag": "Trade",
3372
+ "method": "get",
3373
+ "path": "/trade/transactions/aggregate",
3374
+ "params": [
3375
+ {
3376
+ "name": "start_date",
3377
+ "in": "query",
3378
+ "required": false
3379
+ },
3380
+ {
3381
+ "name": "end_date",
3382
+ "in": "query",
3383
+ "required": false
3384
+ },
3385
+ {
3386
+ "name": "group_by",
3387
+ "in": "query",
3388
+ "required": false
3389
+ },
3390
+ {
3391
+ "name": "paid_status",
3392
+ "in": "query",
3393
+ "required": false,
3394
+ "array": true
3395
+ },
3396
+ {
3397
+ "name": "payment_channel",
3398
+ "in": "query",
3399
+ "required": false
3400
+ },
3401
+ {
3402
+ "name": "form_token",
3403
+ "in": "query",
3404
+ "required": false
3405
+ }
3406
+ ],
3407
+ "paramNames": [
3408
+ "start_date",
3409
+ "end_date",
3410
+ "group_by",
3411
+ "paid_status",
3412
+ "payment_channel",
3413
+ "form_token"
3414
+ ],
3415
+ "successStatus": 200,
3416
+ "scopes": [
3417
+ "users"
3418
+ ],
3419
+ "responseSchema": "TradeTransactionAggregateResponse"
3420
+ },
3421
+ "listTradeRefunds": {
3422
+ "operationId": "listTradeRefunds",
3423
+ "summary": "List refunds",
3424
+ "description": "Lists the refunds the 小金商户 issued to customers, with statistics. Refunds are filtered and sorted newest first by the time they were issued, not by the order time or the time the refund arrived. Only a 小金商户 has refund records; an account collecting payments through a direct connection has no data here.\n- The date range is in Beijing time (UTC+8); both ends are inclusive and must be passed together. Without them, it defaults to the last 90 days; with `refund_no` and no dates, there is no time limit. `queried_range` gives the range actually used.\n- `include` decides what is returned: `both` (default) returns `stats` and `refunds` together, `stats` returns the statistics alone, `records` returns the records alone.\n- The detail limits are those of \"List payment orders\" (at most 90 days, 200 records): past them, `refunds` is null, `detail_limit` says why, and `stats` is returned as usual.\n- `stats`: the count and amount of all matching refunds, the count and amount per status, the number of distinct orders with a successful refund, and the trend by refund issue date (only when there is a date range; by day under 90 days, by week from 90 days, by month from 365 days, periods without refunds filled with zero). In the trend, order counts are deduplicated within each period, so the sum over periods can exceed the total order count.\n- Paging works as in \"List payment orders\"; with `include=stats`, `next` is not returned.\n- Returns 404 when the account has no 小金商户.",
3425
+ "tag": "Trade",
3426
+ "method": "get",
3427
+ "path": "/trade/refunds",
3428
+ "params": [
3429
+ {
3430
+ "name": "start_date",
3431
+ "in": "query",
3432
+ "required": false
3433
+ },
3434
+ {
3435
+ "name": "end_date",
3436
+ "in": "query",
3437
+ "required": false
3438
+ },
3439
+ {
3440
+ "name": "status",
3441
+ "in": "query",
3442
+ "required": false
3443
+ },
3444
+ {
3445
+ "name": "refund_no",
3446
+ "in": "query",
3447
+ "required": false
3448
+ },
3449
+ {
3450
+ "name": "include",
3451
+ "in": "query",
3452
+ "required": false
3453
+ },
3454
+ {
3455
+ "name": "limit",
3456
+ "in": "query",
3457
+ "required": false
3458
+ },
3459
+ {
3460
+ "name": "next",
3461
+ "in": "query",
3462
+ "required": false
3463
+ }
3464
+ ],
3465
+ "paramNames": [
3466
+ "start_date",
3467
+ "end_date",
3468
+ "status",
3469
+ "refund_no",
3470
+ "include",
3471
+ "limit",
3472
+ "next"
3473
+ ],
3474
+ "successStatus": 200,
3475
+ "scopes": [
3476
+ "users"
3477
+ ],
3478
+ "responseSchema": "TradeRefundListResponse"
3479
+ },
3480
+ "listTradePayouts": {
3481
+ "operationId": "listTradePayouts",
3482
+ "summary": "List payouts",
3483
+ "description": "Lists the payouts the 小金商户 made from its Jinshuju balance to its own bank account, with statistics. Payouts are filtered and sorted newest first by request time; each record carries the settlement date range the payout covers, but it cannot be filtered on. Only a 小金商户 has payout records; an account collecting payments through a direct connection has no data here.\n- The date range is in Beijing time (UTC+8); both ends are inclusive and must be passed together. Without them, it defaults to the last 90 days. `queried_range` gives the range actually used.\n- `include` decides what is returned: `both` (default) returns `stats` and `payouts` together, `stats` returns the statistics alone, `records` returns the records alone.\n- The detail limits are those of \"List payment orders\" (at most 90 days, 200 records): past them, `payouts` is null, `detail_limit` says why, and `stats` is returned as usual.\n- `stats`: the count and amount of all matching payouts, and the count and amount per status.\n- Paging works as in \"List payment orders\"; with `include=stats`, `next` is not returned.\n- For the balance awaiting payout and the settlement cycle, see \"Show the 小金商户\". Returns 404 when the account has no 小金商户.",
3484
+ "tag": "Trade",
3485
+ "method": "get",
3486
+ "path": "/trade/payouts",
3487
+ "params": [
3488
+ {
3489
+ "name": "start_date",
3490
+ "in": "query",
3491
+ "required": false
3492
+ },
3493
+ {
3494
+ "name": "end_date",
3495
+ "in": "query",
3496
+ "required": false
3497
+ },
3498
+ {
3499
+ "name": "status",
3500
+ "in": "query",
3501
+ "required": false
3502
+ },
3503
+ {
3504
+ "name": "include",
3505
+ "in": "query",
3506
+ "required": false
3507
+ },
3508
+ {
3509
+ "name": "limit",
3510
+ "in": "query",
3511
+ "required": false
3512
+ },
3513
+ {
3514
+ "name": "next",
3515
+ "in": "query",
3516
+ "required": false
3517
+ }
3518
+ ],
3519
+ "paramNames": [
3520
+ "start_date",
3521
+ "end_date",
3522
+ "status",
3523
+ "include",
3524
+ "limit",
3525
+ "next"
3526
+ ],
3527
+ "successStatus": 200,
3528
+ "scopes": [
3529
+ "users"
3530
+ ],
3531
+ "responseSchema": "TradePayoutListResponse"
3532
+ },
3533
+ "listSmsAuditStatuses": {
3534
+ "operationId": "listSmsAuditStatuses",
3535
+ "summary": "Show SMS signature review status",
3536
+ "description": "Lists the SMS signatures the current user applied for and the SMS templates under each signature, with review status and the reason a review failed, newest signature first.\nReturns only the current user's own signatures, not those of other members of the account; with an account-level credential, returns the account owner's signatures. Any member can call it; admin is not required.",
3537
+ "tag": "Account",
3538
+ "method": "get",
3539
+ "path": "/sms/audit_statuses",
3540
+ "params": [],
3541
+ "paramNames": [],
3542
+ "successStatus": 200,
3543
+ "scopes": [
3544
+ "users"
3545
+ ],
3546
+ "responseSchema": "SMSAuditStatusResponse"
3547
+ },
3548
+ "verifyRedirectParams": {
3549
+ "operationId": "verifyRedirectParams",
3550
+ "summary": "Verify redirect parameters",
3551
+ "description": "Lets the receiver of a \"redirect to an external URL after submission\" verify that the redirect parameters have not been tampered with. This endpoint needs no API credentials.\nWhen a form has redirect after submission turned on and \"Fields to carry on redirect\" configured, Jinshuju appends the values of the selected fields to the redirect URL, plus the signature parameter `jamr_h` (signed over the form token, the entry token and a 10-minute validity period). The receiver forwards the received `jamr_h` and all field parameters to this endpoint unchanged: the server verifies the signature, finds the form and entry, and compares the current value of each configured field with the passed parameter value (array values must be equal as a whole; other values are compared as strings).\nReturns 200 `{ status: \"SUCCESS\", message: \"验证成功\" }` when all match; 400 `{ status: \"FAIL\", message: \"无效Token或者过期\" }` when the `jamr_h` signature is invalid or expired; 400 `{ status: \"FAIL\", message: \"验证失败\" }` when the form / entry does not exist, a field value does not match, or a field parameter is missing. The message text follows the request language.",
3552
+ "tag": "Utilities",
3553
+ "method": "get",
3554
+ "path": "/jamr_v",
3555
+ "params": [
3556
+ {
3557
+ "name": "jamr_h",
3558
+ "in": "query",
3559
+ "required": true
3560
+ },
3561
+ {
3562
+ "name": "serial_number",
3563
+ "in": "query",
3564
+ "required": false
3565
+ }
3566
+ ],
3567
+ "paramNames": [
3568
+ "jamr_h",
3569
+ "serial_number"
3570
+ ],
3571
+ "successStatus": 200,
3572
+ "scopes": []
3573
+ },
3574
+ "listFieldTypes": {
3575
+ "operationId": "listFieldTypes",
3576
+ "summary": "List field types",
3577
+ "description": "Returns every field type available when creating / editing a form (or table), with the validation switches and type-specific settings each type accepts, for building `type` and the type-specific parameters in `fields`.\nKept in line with the types and parameters the create endpoints actually accept.",
3578
+ "tag": "Forms",
3579
+ "method": "get",
3580
+ "path": "/field_types",
3581
+ "params": [
3582
+ {
3583
+ "name": "kind",
3584
+ "in": "query",
3585
+ "required": false
3586
+ }
3587
+ ],
3588
+ "paramNames": [
3589
+ "kind"
3590
+ ],
3591
+ "successStatus": 200,
3592
+ "scopes": [
3593
+ "forms"
3594
+ ],
3595
+ "responseSchema": "FieldTypeListResponse"
3596
+ },
3597
+ "getFieldType": {
3598
+ "operationId": "getFieldType",
3599
+ "summary": "Show a field type",
3600
+ "description": "Returns the validation switches and type-specific settings one field type accepts, shaped like one item of the `GET /field_types` list.\nReturns 404, listing the available types in `error_description`, when the type name does not exist or is not among the types available for `kind` (e.g. querying a type tables do not support with `kind=table`).",
3601
+ "tag": "Forms",
3602
+ "method": "get",
3603
+ "path": "/field_types/{type}",
3604
+ "params": [
3605
+ {
3606
+ "name": "type",
3607
+ "in": "path",
3608
+ "required": true
3609
+ },
3610
+ {
3611
+ "name": "kind",
3612
+ "in": "query",
3613
+ "required": false
3614
+ }
3615
+ ],
3616
+ "paramNames": [
3617
+ "type",
3618
+ "kind"
3619
+ ],
3620
+ "successStatus": 200,
3621
+ "scopes": [
3622
+ "forms"
3623
+ ],
3624
+ "responseSchema": "FieldTypeDescription"
3625
+ },
3626
+ "countEntriesAcrossForms": {
3627
+ "operationId": "countEntriesAcrossForms",
3628
+ "summary": "Count entries across several forms",
3629
+ "description": "Counts, in one call, the entries matching the filters in each of up to 10 forms / tables, plus their total.\n- A token that cannot be accessed (does not exist, or does not belong to the caller) does not fail the whole request; its row returns `unavailable` with the reason instead. The total adds up only the rows that could be counted.\n- Field api_codes mean different things in each form, so `filters` can use only the three form-independent conditions `created_at` / `updated_at` / `creator_id`; any other field returns 400.\n- `keyword` is not supported (passing it returns 400); to search several forms by keyword, use `GET /entries/search`.",
3630
+ "tag": "Entries",
3631
+ "method": "get",
3632
+ "path": "/entries/count",
3633
+ "params": [
3634
+ {
3635
+ "name": "form_tokens",
3636
+ "in": "query",
3637
+ "required": false
3638
+ },
3639
+ {
3640
+ "name": "filters",
3641
+ "in": "query",
3642
+ "required": false
3643
+ }
3644
+ ],
3645
+ "paramNames": [
3646
+ "form_tokens",
3647
+ "filters"
3648
+ ],
3649
+ "successStatus": 200,
3650
+ "scopes": [
3651
+ "read_entries"
3652
+ ],
3653
+ "responseSchema": "EntryCountBatchResponse"
3654
+ },
3655
+ "searchEntriesAcrossForms": {
3656
+ "operationId": "searchEntriesAcrossForms",
3657
+ "summary": "Search entries across forms",
3658
+ "description": "Runs one keyword as a full-text search across several forms / tables and returns, per form, the match count and some of the matching serial numbers (at most 50 per form), without entry content.\n- Search scope: the forms in `form_tokens` when given; otherwise every form and table the caller can access (for an account access token, every form and table in the account).\n Either way, `filters` then narrows the scope; unless `filters` specifies `entries_count`, only forms with entries are searched by default (`entries_count > 0`).\n- The scope holds at most 10 forms; beyond that it returns 400: narrow it with `filters`, or pass `form_tokens` directly.\n- Forms with no match are left out of the result; forms that cannot be accessed, where the caller's role does not allow reading entries, whose search timed out or whose search service did not respond are listed with `unavailable` giving the reason (this does not mean there was no match).",
3659
+ "tag": "Entries",
3660
+ "method": "get",
3661
+ "path": "/entries/search",
3662
+ "params": [
3663
+ {
3664
+ "name": "keyword",
3665
+ "in": "query",
3666
+ "required": true
3667
+ },
3668
+ {
3669
+ "name": "form_tokens",
3670
+ "in": "query",
3671
+ "required": false
3672
+ },
3673
+ {
3674
+ "name": "filters",
3675
+ "in": "query",
3676
+ "required": false
3677
+ }
3678
+ ],
3679
+ "paramNames": [
3680
+ "keyword",
3681
+ "form_tokens",
3682
+ "filters"
3683
+ ],
3684
+ "successStatus": 200,
3685
+ "scopes": [
3686
+ "read_entries"
3687
+ ],
3688
+ "responseSchema": "EntrySearchResponse"
3689
+ },
3690
+ "getEntryStats": {
3691
+ "operationId": "getEntryStats",
3692
+ "summary": "Count submissions per form over a date range",
3693
+ "description": "Counts the submissions received within a date range by every form / table the caller can access (for an account access token, every form and table in the account): returns the total, and a list of the forms that received submissions, most submissions first.\n- Dates are in Beijing time (UTC+8); `from` / `to` are both inclusive.\n- It counts submissions as they happened: imported entries count on the day of the import, and deleted entries are not subtracted, so the result may differ from a count by entry `created_at`.\n- The list has at most `limit` rows; when there are more, `truncated` is true, and `total` and `forms_with_data` still cover every form.\n- With `by` (`day` / `week` / `month`), the response also carries `buckets`: one count of the same shape for each period in the range (periods with no submissions included); weeks start on Monday, and the first and last periods are clipped to the range. The range covers at most 92 days / 53 weeks / 24 months; beyond that it returns 400, suggesting a coarser granularity or dropping `by`.",
3694
+ "tag": "Entries",
3695
+ "method": "get",
3696
+ "path": "/entries/stats",
3697
+ "params": [
3698
+ {
3699
+ "name": "from",
3700
+ "in": "query",
3701
+ "required": true
3702
+ },
3703
+ {
3704
+ "name": "to",
3705
+ "in": "query",
3706
+ "required": false
3707
+ },
3708
+ {
3709
+ "name": "kind",
3710
+ "in": "query",
3711
+ "required": false
3712
+ },
3713
+ {
3714
+ "name": "by",
3715
+ "in": "query",
3716
+ "required": false
3717
+ },
3718
+ {
3719
+ "name": "limit",
3720
+ "in": "query",
3721
+ "required": false
3722
+ }
3723
+ ],
3724
+ "paramNames": [
3725
+ "from",
3726
+ "to",
3727
+ "kind",
3728
+ "by",
3729
+ "limit"
3730
+ ],
3731
+ "successStatus": 200,
3732
+ "scopes": [
3733
+ "read_entries"
3734
+ ],
3735
+ "responseSchema": "EntryStatsResponse"
3736
+ },
3737
+ "listMyFilledForms": {
3738
+ "operationId": "listMyFilledForms",
3739
+ "summary": "List the forms I have submitted to",
3740
+ "description": "Returns the forms the current user has submitted entries to as a submitter (quick payment forms excluded), most recent submission first. These forms need not be created by or shared with the current user;\neach row gives the current user's own submission count and latest submission time, not the form's total entry count. Deleted forms do not appear in `data` (`total` still counts them).\n- Pagination: `next` is a row offset, passed back as is for the next page; `skip` and `next` cannot be combined. 50 rows per page by default, adjustable with `limit` (at most 1000).\n- An account access token has no \"current user\"; calling with one returns 400.",
3741
+ "tag": "Forms",
3742
+ "method": "get",
3743
+ "path": "/my/forms",
3744
+ "params": [
3745
+ {
3746
+ "name": "limit",
3747
+ "in": "query",
3748
+ "required": false
3749
+ },
3750
+ {
3751
+ "name": "next",
3752
+ "in": "query",
3753
+ "required": false
3754
+ },
3755
+ {
3756
+ "name": "skip",
3757
+ "in": "query",
3758
+ "required": false
3759
+ }
3760
+ ],
3761
+ "paramNames": [
3762
+ "limit",
3763
+ "next",
3764
+ "skip"
3765
+ ],
3766
+ "successStatus": 200,
3767
+ "scopes": [
3768
+ "forms"
3769
+ ],
3770
+ "responseSchema": "MyFilledFormListResponse"
3771
+ },
3772
+ "listMySubmittedEntries": {
3773
+ "operationId": "listMySubmittedEntries",
3774
+ "summary": "List my entries in a form",
3775
+ "description": "Returns the entries the current user submitted to the given form, newest first. The form need not be created by or shared with the current user: only the user's own entries are returned,\nwith only the fields the form makes public to submitters (hidden fields are neither returned nor usable for filtering or searching). Returns an empty list when the user has not submitted.\n- `fields` keeps only the given public fields; unknown or non-public api_codes are skipped (no error).\n- `filters` works as in the entry list, but cannot filter by `creator_id` (results are already limited to the user's own) or on non-public fields; doing so returns 400.\n- `keyword` searches only the user's own entries and is not subject to the form's entry-count limit.\n- Pagination: `next` is a row offset; `skip` and `next` cannot be combined. 50 rows per page by default, adjustable with `limit` (at most 1000).\n- An account access token has no \"current user\"; calling with one returns 400. Returns 404 when the form does not exist.",
3776
+ "tag": "Entries",
3777
+ "method": "get",
3778
+ "path": "/my/forms/{form_token}/entries",
3779
+ "params": [
3780
+ {
3781
+ "name": "form_token",
3782
+ "in": "path",
3783
+ "required": true
3784
+ },
3785
+ {
3786
+ "name": "fields",
3787
+ "in": "query",
3788
+ "required": false
3789
+ },
3790
+ {
3791
+ "name": "filters",
3792
+ "in": "query",
3793
+ "required": false
3794
+ },
3795
+ {
3796
+ "name": "keyword",
3797
+ "in": "query",
3798
+ "required": false
3799
+ },
3800
+ {
3801
+ "name": "include_labels",
3802
+ "in": "query",
3803
+ "required": false
3804
+ },
3805
+ {
3806
+ "name": "limit",
3807
+ "in": "query",
3808
+ "required": false
3809
+ },
3810
+ {
3811
+ "name": "next",
3812
+ "in": "query",
3813
+ "required": false
3814
+ },
3815
+ {
3816
+ "name": "skip",
3817
+ "in": "query",
3818
+ "required": false
3819
+ }
3820
+ ],
3821
+ "paramNames": [
3822
+ "form_token",
3823
+ "fields",
3824
+ "filters",
3825
+ "keyword",
3826
+ "include_labels",
3827
+ "limit",
3828
+ "next",
3829
+ "skip"
3830
+ ],
3831
+ "successStatus": 200,
3832
+ "scopes": [
3833
+ "read_entries"
3834
+ ],
3835
+ "responseSchema": "MySubmittedEntryListResponse"
3836
+ },
3837
+ "searchMySubmittedEntries": {
3838
+ "operationId": "searchMySubmittedEntries",
3839
+ "summary": "Search my entries",
3840
+ "description": "Searches the current user's own entries across forms with one keyword (only fields the form makes public to submitters are searched), and returns the match count and serial numbers for each matching form.\n- `keyword` is required; returns 400 when empty.\n- By default, searches every form the current user has submitted to (quick payment forms excluded); `form_tokens` limits it to some of them, and tokens not in the user's submission history are ignored.\n Returns 400 when more than 20 forms are in the search; narrow them with `form_tokens`.\n- Forms with no match are left out of the result; when a form cannot be searched (e.g. the keyword is too long), that form returns `unavailable` with an explanation and the other forms return as usual.\n- At most 50 serial numbers are returned per form; `matched` is the form's actual total match count.\n- An account access token has no \"current user\"; calling with one returns 400.",
3841
+ "tag": "Entries",
3842
+ "method": "get",
3843
+ "path": "/my/search",
3844
+ "params": [
3845
+ {
3846
+ "name": "keyword",
3847
+ "in": "query",
3848
+ "required": true
3849
+ },
3850
+ {
3851
+ "name": "form_tokens",
3852
+ "in": "query",
3853
+ "required": false
3854
+ }
3855
+ ],
3856
+ "paramNames": [
3857
+ "keyword",
3858
+ "form_tokens"
3859
+ ],
3860
+ "successStatus": 200,
3861
+ "scopes": [
3862
+ "read_entries"
3863
+ ],
3864
+ "responseSchema": "MySearchResponse"
3865
+ },
3866
+ "getFillFormPage": {
3867
+ "operationId": "getFillFormPage",
3868
+ "summary": "Show a form's fill page",
3869
+ "description": "Reads the fill page behind a fill link (`/f/<token>`): its title, description, the fields to fill in, and whether the current user can submit right now.\nThe caller reads it as a submitter holding the link and needs no permission on the form or table; only what the fill page shows is returned.\n- `fields` lists the public fields in fill-page order, shaped like `fields` when reading a form; for a form view, column names, descriptions and required flags already follow the view's settings.\n- Submission is possible only when `status.key` is `open`; other values (such as `not_opened`, `closed`, `password_required`, `unauthorized`, `submission_prevented`,\n `fill_frequency_limited`: the current user has used up the submissions the fill page allows) are explained in `status.message`; when the page is not yet open or has closed on schedule, `status.open_info` gives the open period.\n- `blockers` lists requirements only the submitter can complete on the page (captcha, SMS verification, WeChat identity, payment, etc.); when it is not empty, submission is refused and the form must be filled in a browser.\n- `manageable` is returned only when the current user can already read the underlying form or table, and gives its token and name.\n- An account access token has no \"current user\"; calling with one returns 400.",
3870
+ "tag": "Fill",
3871
+ "method": "get",
3872
+ "path": "/fill/f/{form_token}",
3873
+ "params": [
3874
+ {
3875
+ "name": "form_token",
3876
+ "in": "path",
3877
+ "required": true
3878
+ }
3879
+ ],
3880
+ "paramNames": [
3881
+ "form_token"
3882
+ ],
3883
+ "successStatus": 200,
3884
+ "scopes": [
3885
+ "submit_entries"
3886
+ ],
3887
+ "responseSchema": "FillPage"
3888
+ },
3889
+ "createFillFormEntry": {
3890
+ "operationId": "createFillFormEntry",
3891
+ "summary": "Submit an entry through a form's fill page",
3892
+ "description": "Submits one entry through the fill page as the current user, the same as clicking \"Submit\" on the page: only fields visible on the fill page are accepted, required fields are checked as the fill page sets them,\nthe submitter is recorded as the current user (the entry shows up in \"My submissions\"), and an entry submitted through a form view records which view it came from.\n- Returns 403 when the fill page is not open, with the reason in `status`; returns 422 listing the reasons when `blockers` is not empty.\n- Returns 422 when a field value is invalid, with `errors` explaining each by field api_code.\n- Each user can submit at most 30 times per hour; beyond that returns 429.\n- An account access token has no \"current user\"; calling with one returns 400.",
3893
+ "tag": "Fill",
3894
+ "method": "post",
3895
+ "path": "/fill/f/{form_token}/entries",
3896
+ "params": [
3897
+ {
3898
+ "name": "form_token",
3899
+ "in": "path",
3900
+ "required": true
3901
+ }
3902
+ ],
3903
+ "paramNames": [
3904
+ "form_token"
3905
+ ],
3906
+ "body": {
3907
+ "contentType": "application/json",
3908
+ "required": true,
3909
+ "flatten": true
3910
+ },
3911
+ "successStatus": 201,
3912
+ "scopes": [
3913
+ "submit_entries"
3914
+ ],
3915
+ "responseSchema": "FillEntryCreated"
3916
+ },
3917
+ "getFillViewPage": {
3918
+ "operationId": "getFillViewPage",
3919
+ "summary": "Show a form view's fill page",
3920
+ "description": "Reads the fill page behind a fill link (`/v/<token>`): its title, description, the fields to fill in, and whether the current user can submit right now.\nThe caller reads it as a submitter holding the link and needs no permission on the form or table; only what the fill page shows is returned.\n- `fields` lists the public fields in fill-page order, shaped like `fields` when reading a form; for a form view, column names, descriptions and required flags already follow the view's settings.\n- Submission is possible only when `status.key` is `open`; other values (such as `not_opened`, `closed`, `password_required`, `unauthorized`, `submission_prevented`,\n `fill_frequency_limited`: the current user has used up the submissions the fill page allows) are explained in `status.message`; when the page is not yet open or has closed on schedule, `status.open_info` gives the open period.\n- `blockers` lists requirements only the submitter can complete on the page (captcha, SMS verification, WeChat identity, payment, etc.); when it is not empty, submission is refused and the form must be filled in a browser.\n- `manageable` is returned only when the current user can already read the underlying form or table, and gives its token and name.\n- An account access token has no \"current user\"; calling with one returns 400.",
3921
+ "tag": "Fill",
3922
+ "method": "get",
3923
+ "path": "/fill/v/{view_token}",
3924
+ "params": [
3925
+ {
3926
+ "name": "view_token",
3927
+ "in": "path",
3928
+ "required": true
3929
+ }
3930
+ ],
3931
+ "paramNames": [
3932
+ "view_token"
3933
+ ],
3934
+ "successStatus": 200,
3935
+ "scopes": [
3936
+ "submit_entries"
3937
+ ],
3938
+ "responseSchema": "FillPage"
3939
+ },
3940
+ "createFillViewEntry": {
3941
+ "operationId": "createFillViewEntry",
3942
+ "summary": "Submit an entry through a form view's fill page",
3943
+ "description": "Submits one entry through the fill page as the current user, the same as clicking \"Submit\" on the page: only fields visible on the fill page are accepted, required fields are checked as the fill page sets them,\nthe submitter is recorded as the current user (the entry shows up in \"My submissions\"), and an entry submitted through a form view records which view it came from.\n- Returns 403 when the fill page is not open, with the reason in `status`; returns 422 listing the reasons when `blockers` is not empty.\n- Returns 422 when a field value is invalid, with `errors` explaining each by field api_code.\n- Each user can submit at most 30 times per hour; beyond that returns 429.\n- An account access token has no \"current user\"; calling with one returns 400.",
3944
+ "tag": "Fill",
3945
+ "method": "post",
3946
+ "path": "/fill/v/{view_token}/entries",
3947
+ "params": [
3948
+ {
3949
+ "name": "view_token",
3950
+ "in": "path",
3951
+ "required": true
3952
+ }
3953
+ ],
3954
+ "paramNames": [
3955
+ "view_token"
3956
+ ],
3957
+ "body": {
3958
+ "contentType": "application/json",
3959
+ "required": true,
3960
+ "flatten": true
3961
+ },
3962
+ "successStatus": 201,
3963
+ "scopes": [
3964
+ "submit_entries"
3965
+ ],
3966
+ "responseSchema": "FillEntryCreated"
3967
+ },
3968
+ "moveTableToFolder": {
3969
+ "operationId": "moveTableToFolder",
3970
+ "summary": "Move a table into a folder",
3971
+ "description": "Moves a table into a folder, or out of its folder (`folder_token` set to null); PUT is also accepted. The move affects only the calling user's folder placement.\n- The request body must include the `folder_token` key (its value may be null); otherwise 400.\n- `folder_token` accepts only a folder token (not an id); returns 404 when the folder does not exist or the current user lacks manage permission on it.\n- The target folder's kind must be table; otherwise 400.\n- Returns 404 `table cannot be found` when the token is not a table's.",
3972
+ "tag": "Tables",
3973
+ "method": "patch",
3974
+ "path": "/tables/{table_token}/folder",
3975
+ "params": [
3976
+ {
3977
+ "name": "table_token",
3978
+ "in": "path",
3979
+ "required": true
3980
+ }
3981
+ ],
3982
+ "paramNames": [
3983
+ "table_token"
3984
+ ],
3985
+ "body": {
3986
+ "contentType": "application/json",
3987
+ "required": true,
3988
+ "flatten": true
3989
+ },
3990
+ "successStatus": 200,
3991
+ "scopes": [
3992
+ "forms"
3993
+ ],
3994
+ "responseSchema": "TableFolderMoveResult"
3995
+ }
3996
+ }