@primitivedotdev/sdk 0.28.0 → 0.30.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.
@@ -1546,6 +1546,37 @@ const openapiDocument = {
1546
1546
  }
1547
1547
  }
1548
1548
  },
1549
+ "/functions/{id}/test-runs/{run_id}/trace": {
1550
+ "parameters": [{ "$ref": "#/components/parameters/ResourceId" }, {
1551
+ "name": "run_id",
1552
+ "in": "path",
1553
+ "required": true,
1554
+ "description": "Function test run id returned by POST /functions/{id}/test.",
1555
+ "schema": {
1556
+ "type": "string",
1557
+ "format": "uuid"
1558
+ }
1559
+ }],
1560
+ "get": {
1561
+ "operationId": "getFunctionTestRunTrace",
1562
+ "summary": "Get a function test run trace",
1563
+ "description": "Returns the current end-to-end trace for a function test run.\nThe trace is intentionally partial while the test is still in\nflight: callers can poll this endpoint and watch it fill in\nfrom send -> inbound -> webhook deliveries -> outbound\nrequests, logs, and replies.\n",
1564
+ "tags": ["Functions"],
1565
+ "responses": {
1566
+ "200": {
1567
+ "description": "Function test run trace",
1568
+ "content": { "application/json": { "schema": { "allOf": [{ "$ref": "#/components/schemas/SuccessEnvelope" }, {
1569
+ "type": "object",
1570
+ "properties": { "data": { "$ref": "#/components/schemas/FunctionTestRunTrace" } }
1571
+ }] } } }
1572
+ },
1573
+ "400": { "$ref": "#/components/responses/ValidationError" },
1574
+ "401": { "$ref": "#/components/responses/Unauthorized" },
1575
+ "403": { "$ref": "#/components/responses/Forbidden" },
1576
+ "404": { "$ref": "#/components/responses/NotFound" }
1577
+ }
1578
+ }
1579
+ },
1549
1580
  "/functions/{id}/secrets": {
1550
1581
  "parameters": [{ "$ref": "#/components/parameters/ResourceId" }],
1551
1582
  "get": {
@@ -3846,8 +3877,13 @@ const openapiDocument = {
3846
3877
  },
3847
3878
  "TestInvocationResult": {
3848
3879
  "type": "object",
3849
- "description": "Metadata returned by POST /functions/{id}/test. The send is\nqueued; the actual invocation lands on the function's\ninvocations list a few seconds later as the inbound mail\ntraverses the MX path.\n",
3880
+ "description": "Metadata returned by POST /functions/{id}/test. The send is\nqueued; poll `trace_url` to watch the run progress through\nsend -> inbound -> webhook deliveries -> outbound requests,\nlogs, and replies.\n",
3850
3881
  "properties": {
3882
+ "test_run_id": {
3883
+ "type": "string",
3884
+ "format": "uuid",
3885
+ "description": "Durable test run id used to fetch the run trace."
3886
+ },
3851
3887
  "inbound_domain": {
3852
3888
  "type": "string",
3853
3889
  "description": "Verified inbound domain the test email was sent to."
@@ -3877,127 +3913,203 @@ const openapiDocument = {
3877
3913
  "type": "string",
3878
3914
  "format": "uri",
3879
3915
  "description": "Function detail page where invocations show up live."
3916
+ },
3917
+ "trace_url": {
3918
+ "type": "string",
3919
+ "description": "Relative API URL for GET /functions/{id}/test-runs/{test_run_id}/trace."
3880
3920
  }
3881
3921
  },
3882
3922
  "required": [
3923
+ "test_run_id",
3883
3924
  "inbound_domain",
3884
3925
  "to",
3885
3926
  "from",
3886
3927
  "send_id",
3887
3928
  "subject",
3888
3929
  "poll_since",
3889
- "watch_url"
3930
+ "watch_url",
3931
+ "trace_url"
3890
3932
  ]
3891
3933
  },
3892
- "FunctionLogRow": {
3934
+ "FunctionTestRunState": {
3935
+ "type": "string",
3936
+ "description": "High-level state for a function test run trace:\n - `send_failed`: the initial test email send failed.\n - `waiting_for_send`: the test run was created but no send result has been recorded yet.\n - `waiting_for_inbound`: the test send was queued and the matching inbound email has not arrived yet.\n - `waiting_for_function`: the inbound email arrived and webhook/function processing is still in flight.\n - `completed`: the function webhook completed successfully.\n - `failed`: webhook delivery exhausted retries.\n",
3937
+ "enum": [
3938
+ "send_failed",
3939
+ "waiting_for_send",
3940
+ "waiting_for_inbound",
3941
+ "waiting_for_function",
3942
+ "completed",
3943
+ "failed"
3944
+ ]
3945
+ },
3946
+ "FunctionTestRun": {
3893
3947
  "type": "object",
3894
- "description": "One row from GET /functions/{id}/logs. Represents a single\ncaptured log line emitted by the running handler (e.g. via\n`console.log` / `console.error`).\n",
3895
3948
  "properties": {
3896
3949
  "id": {
3897
3950
  "type": "string",
3898
- "format": "uuid",
3899
- "description": "Unique log row id (stable across pages)."
3951
+ "format": "uuid"
3900
3952
  },
3901
3953
  "function_id": {
3902
3954
  "type": "string",
3903
- "format": "uuid",
3904
- "description": "The function this log row belongs to."
3955
+ "format": "uuid"
3905
3956
  },
3906
- "level": {
3957
+ "inbound_domain": { "type": "string" },
3958
+ "to": { "type": "string" },
3959
+ "from": { "type": "string" },
3960
+ "subject": { "type": "string" },
3961
+ "poll_since": {
3907
3962
  "type": "string",
3908
- "enum": [
3909
- "debug",
3910
- "log",
3911
- "info",
3912
- "warn",
3913
- "error"
3914
- ],
3915
- "description": "Severity. `log` is the runtime's default for unannotated\n`console.log` calls; the other levels match standard\n`console.*` methods.\n"
3963
+ "format": "date-time"
3916
3964
  },
3917
- "message": {
3965
+ "created_at": {
3918
3966
  "type": "string",
3919
- "description": "The textual message body. The runtime stringifies non-string\narguments before persisting, so this is always a plain\nstring.\n"
3967
+ "format": "date-time"
3920
3968
  },
3921
- "ts": {
3922
- "type": "string",
3923
- "format": "date-time",
3924
- "description": "When the handler emitted this line. Newest-first ordering\non this column drives pagination; clock is the runtime's,\nnot the gateway's.\n"
3969
+ "sent_at": {
3970
+ "type": ["string", "null"],
3971
+ "format": "date-time"
3925
3972
  },
3926
- "metadata": {
3927
- "type": ["object", "null"],
3928
- "additionalProperties": true,
3929
- "description": "Optional structured payload the runtime attaches alongside\nthe message (e.g. extra args passed to `console.log`).\nShape is opaque; treat keys as untyped.\n"
3930
- }
3973
+ "send_error": { "type": ["string", "null"] }
3931
3974
  },
3932
3975
  "required": [
3933
3976
  "id",
3934
3977
  "function_id",
3935
- "level",
3936
- "message",
3937
- "ts"
3978
+ "inbound_domain",
3979
+ "to",
3980
+ "from",
3981
+ "subject",
3982
+ "poll_since",
3983
+ "created_at",
3984
+ "sent_at",
3985
+ "send_error"
3938
3986
  ]
3939
3987
  },
3940
- "FunctionSecretListItem": {
3941
- "type": "object",
3942
- "description": "One row from GET /functions/{id}/secrets. Discriminate on the\n`managed` field:\n * `managed = true` — system secret provisioned by Primitive.\n `description` is set; `created_at` / `updated_at` are\n null because the row is virtual (resolved at deploy time\n from the managed registry, not stored in the secrets\n table).\n * `managed = false` — secret the user set via the API.\n `created_at` / `updated_at` are set; `description` is\n null.\n",
3988
+ "FunctionTestRunSend": {
3989
+ "type": ["object", "null"],
3943
3990
  "properties": {
3944
- "key": { "type": "string" },
3945
- "managed": {
3946
- "type": "boolean",
3947
- "description": "True for managed system secrets, false for user-set entries."
3948
- },
3949
- "description": {
3950
- "type": ["string", "null"],
3951
- "description": "Set on managed entries only; null on user-set entries."
3991
+ "id": {
3992
+ "type": "string",
3993
+ "format": "uuid"
3952
3994
  },
3995
+ "status": { "$ref": "#/components/schemas/SentEmailStatus" },
3996
+ "queue_id": { "type": ["string", "null"] },
3953
3997
  "created_at": {
3954
- "type": ["string", "null"],
3955
- "format": "date-time",
3956
- "description": "Set on user-set entries only; null on managed entries."
3998
+ "type": "string",
3999
+ "format": "date-time"
3957
4000
  },
3958
4001
  "updated_at": {
3959
- "type": ["string", "null"],
3960
- "format": "date-time",
3961
- "description": "Set on user-set entries only; null on managed entries."
4002
+ "type": "string",
4003
+ "format": "date-time"
3962
4004
  }
3963
4005
  },
3964
- "required": ["key", "managed"]
4006
+ "required": [
4007
+ "id",
4008
+ "status",
4009
+ "queue_id",
4010
+ "created_at",
4011
+ "updated_at"
4012
+ ]
3965
4013
  },
3966
- "CreateFunctionSecretInput": {
3967
- "type": "object",
3968
- "additionalProperties": false,
3969
- "description": "Body for POST /functions/{id}/secrets.",
4014
+ "FunctionTestRunInboundEmail": {
4015
+ "type": ["object", "null"],
3970
4016
  "properties": {
3971
- "key": {
4017
+ "id": {
3972
4018
  "type": "string",
3973
- "pattern": "^[A-Z_][A-Z0-9_]*$",
3974
- "description": "Uppercase letters, digits, and underscores. Must start with\na letter or underscore. System-managed keys (e.g.\nPRIMITIVE_WEBHOOK_SECRET) are reserved.\n"
4019
+ "format": "uuid"
3975
4020
  },
3976
- "value": {
4021
+ "status": { "$ref": "#/components/schemas/EmailStatus" },
4022
+ "received_at": {
3977
4023
  "type": "string",
3978
- "minLength": 1,
3979
- "maxLength": 4096,
3980
- "description": "Secret value, up to 4096 UTF-8 bytes. Encrypted at rest.\nNever returned by any read endpoint.\n"
3981
- }
4024
+ "format": "date-time"
4025
+ },
4026
+ "from": { "type": "string" },
4027
+ "to": { "type": "string" },
4028
+ "subject": { "type": ["string", "null"] },
4029
+ "webhook_status": { "$ref": "#/components/schemas/EmailWebhookStatus" },
4030
+ "webhook_attempt_count": { "type": "integer" },
4031
+ "webhook_last_status_code": { "type": ["integer", "null"] },
4032
+ "webhook_last_error": { "type": ["string", "null"] }
3982
4033
  },
3983
- "required": ["key", "value"]
4034
+ "required": [
4035
+ "id",
4036
+ "status",
4037
+ "received_at",
4038
+ "from",
4039
+ "to",
4040
+ "subject",
4041
+ "webhook_status",
4042
+ "webhook_attempt_count",
4043
+ "webhook_last_status_code",
4044
+ "webhook_last_error"
4045
+ ]
3984
4046
  },
3985
- "SetFunctionSecretInput": {
3986
- "type": "object",
3987
- "additionalProperties": false,
3988
- "description": "Body for PUT /functions/{id}/secrets/{key}. Key comes from the path.",
3989
- "properties": { "value": {
3990
- "type": "string",
3991
- "minLength": 1,
3992
- "maxLength": 4096
3993
- } },
3994
- "required": ["value"]
4047
+ "FunctionTestRunDeliveryEndpoint": {
4048
+ "type": ["object", "null"],
4049
+ "properties": {
4050
+ "id": {
4051
+ "type": "string",
4052
+ "format": "uuid"
4053
+ },
4054
+ "kind": {
4055
+ "type": "string",
4056
+ "description": "Endpoint kind. Current traces may include `http` or `function`; future endpoint kinds may appear."
4057
+ },
4058
+ "function_id": {
4059
+ "type": ["string", "null"],
4060
+ "format": "uuid"
4061
+ },
4062
+ "function_name": { "type": ["string", "null"] },
4063
+ "domain_id": {
4064
+ "type": ["string", "null"],
4065
+ "format": "uuid"
4066
+ },
4067
+ "enabled": { "type": "boolean" },
4068
+ "deactivated_at": {
4069
+ "type": ["string", "null"],
4070
+ "format": "date-time"
4071
+ },
4072
+ "is_current_function": { "type": "boolean" }
4073
+ },
4074
+ "required": [
4075
+ "id",
4076
+ "kind",
4077
+ "function_id",
4078
+ "function_name",
4079
+ "domain_id",
4080
+ "enabled",
4081
+ "deactivated_at",
4082
+ "is_current_function"
4083
+ ]
3995
4084
  },
3996
- "FunctionSecretWriteResult": {
4085
+ "FunctionTestRunDelivery": {
3997
4086
  "type": "object",
3998
- "description": "Returned by POST and PUT secret routes.",
3999
4087
  "properties": {
4000
- "key": { "type": "string" },
4088
+ "id": {
4089
+ "type": "string",
4090
+ "description": "Webhook delivery id."
4091
+ },
4092
+ "endpoint_id": {
4093
+ "type": "string",
4094
+ "format": "uuid"
4095
+ },
4096
+ "endpoint_url": {
4097
+ "type": "string",
4098
+ "format": "uri"
4099
+ },
4100
+ "status": {
4101
+ "type": "string",
4102
+ "enum": [
4103
+ "pending",
4104
+ "delivered",
4105
+ "header_confirmed",
4106
+ "failed"
4107
+ ]
4108
+ },
4109
+ "attempt_count": { "type": "integer" },
4110
+ "duration_ms": { "type": ["integer", "null"] },
4111
+ "last_error": { "type": ["string", "null"] },
4112
+ "last_error_code": { "type": ["string", "null"] },
4001
4113
  "created_at": {
4002
4114
  "type": "string",
4003
4115
  "format": "date-time"
@@ -4006,58 +4118,305 @@ const openapiDocument = {
4006
4118
  "type": "string",
4007
4119
  "format": "date-time"
4008
4120
  },
4009
- "created": {
4010
- "type": "boolean",
4011
- "description": "True if this call inserted a new row, false if it updated an existing one."
4012
- }
4121
+ "endpoint": { "$ref": "#/components/schemas/FunctionTestRunDeliveryEndpoint" }
4013
4122
  },
4014
4123
  "required": [
4015
- "key",
4124
+ "id",
4125
+ "endpoint_id",
4126
+ "endpoint_url",
4127
+ "status",
4128
+ "attempt_count",
4129
+ "duration_ms",
4130
+ "last_error",
4131
+ "last_error_code",
4016
4132
  "created_at",
4017
4133
  "updated_at",
4018
- "created"
4134
+ "endpoint"
4019
4135
  ]
4020
- }
4021
- }
4022
- }
4023
- };
4024
- //#endregion
4025
- //#region ../packages/api-core/src/openapi/operations.generated.ts
4026
- const operationManifest = [
4027
- {
4028
- "binaryResponse": false,
4029
- "bodyRequired": false,
4030
- "command": "get-account",
4031
- "description": null,
4032
- "hasJsonBody": false,
4033
- "method": "GET",
4034
- "operationId": "getAccount",
4035
- "path": "/account",
4036
- "pathParams": [],
4037
- "queryParams": [],
4038
- "requestSchema": null,
4039
- "responseSchema": {
4040
- "type": "object",
4041
- "properties": {
4042
- "id": {
4043
- "type": "string",
4044
- "format": "uuid"
4045
- },
4046
- "email": { "type": "string" },
4047
- "plan": { "type": "string" },
4048
- "created_at": {
4049
- "type": "string",
4050
- "format": "date-time"
4051
- },
4052
- "onboarding_completed": { "type": "boolean" },
4053
- "onboarding_step": { "type": ["string", "null"] },
4054
- "stripe_subscription_status": { "type": ["string", "null"] },
4055
- "subscription_current_period_end": {
4056
- "type": ["string", "null"],
4057
- "format": "date-time"
4058
- },
4059
- "subscription_cancel_at_period_end": { "type": ["boolean", "null"] },
4060
- "spam_threshold": {
4136
+ },
4137
+ "FunctionTestRunOutboundRequest": {
4138
+ "type": "object",
4139
+ "properties": {
4140
+ "id": {
4141
+ "type": "string",
4142
+ "format": "uuid"
4143
+ },
4144
+ "function_id": {
4145
+ "type": "string",
4146
+ "format": "uuid"
4147
+ },
4148
+ "webhook_delivery_id": { "type": ["string", "null"] },
4149
+ "email_id": {
4150
+ "type": ["string", "null"],
4151
+ "format": "uuid"
4152
+ },
4153
+ "endpoint_id": {
4154
+ "type": ["string", "null"],
4155
+ "format": "uuid"
4156
+ },
4157
+ "method": { "type": "string" },
4158
+ "url": {
4159
+ "type": "string",
4160
+ "format": "uri"
4161
+ },
4162
+ "host": { "type": "string" },
4163
+ "path": { "type": "string" },
4164
+ "status_code": { "type": ["integer", "null"] },
4165
+ "ok": { "type": ["boolean", "null"] },
4166
+ "duration_ms": { "type": "integer" },
4167
+ "error": { "type": ["string", "null"] },
4168
+ "ts": {
4169
+ "type": "string",
4170
+ "format": "date-time"
4171
+ }
4172
+ },
4173
+ "required": [
4174
+ "id",
4175
+ "function_id",
4176
+ "webhook_delivery_id",
4177
+ "email_id",
4178
+ "endpoint_id",
4179
+ "method",
4180
+ "url",
4181
+ "host",
4182
+ "path",
4183
+ "status_code",
4184
+ "ok",
4185
+ "duration_ms",
4186
+ "error",
4187
+ "ts"
4188
+ ]
4189
+ },
4190
+ "FunctionTestRunReply": {
4191
+ "type": "object",
4192
+ "properties": {
4193
+ "id": {
4194
+ "type": "string",
4195
+ "format": "uuid"
4196
+ },
4197
+ "status": { "$ref": "#/components/schemas/SentEmailStatus" },
4198
+ "to": { "type": "string" },
4199
+ "subject": { "type": "string" },
4200
+ "queue_id": { "type": ["string", "null"] },
4201
+ "created_at": {
4202
+ "type": "string",
4203
+ "format": "date-time"
4204
+ }
4205
+ },
4206
+ "required": [
4207
+ "id",
4208
+ "status",
4209
+ "to",
4210
+ "subject",
4211
+ "queue_id",
4212
+ "created_at"
4213
+ ]
4214
+ },
4215
+ "FunctionTestRunTrace": {
4216
+ "type": "object",
4217
+ "description": "End-to-end trace for a `POST /functions/{id}/test` run. The\nshape is stable, but many nested sections are null or empty\nuntil the corresponding phase has happened.\n",
4218
+ "properties": {
4219
+ "state": { "$ref": "#/components/schemas/FunctionTestRunState" },
4220
+ "test_run": { "$ref": "#/components/schemas/FunctionTestRun" },
4221
+ "test_send": { "$ref": "#/components/schemas/FunctionTestRunSend" },
4222
+ "inbound_email": { "$ref": "#/components/schemas/FunctionTestRunInboundEmail" },
4223
+ "deliveries": {
4224
+ "type": "array",
4225
+ "items": { "$ref": "#/components/schemas/FunctionTestRunDelivery" }
4226
+ },
4227
+ "outbound_requests": {
4228
+ "type": "array",
4229
+ "items": { "$ref": "#/components/schemas/FunctionTestRunOutboundRequest" }
4230
+ },
4231
+ "logs": {
4232
+ "type": "array",
4233
+ "items": { "$ref": "#/components/schemas/FunctionLogRow" }
4234
+ },
4235
+ "replies": {
4236
+ "type": "array",
4237
+ "items": { "$ref": "#/components/schemas/FunctionTestRunReply" }
4238
+ }
4239
+ },
4240
+ "required": [
4241
+ "state",
4242
+ "test_run",
4243
+ "test_send",
4244
+ "inbound_email",
4245
+ "deliveries",
4246
+ "outbound_requests",
4247
+ "logs",
4248
+ "replies"
4249
+ ]
4250
+ },
4251
+ "FunctionLogRow": {
4252
+ "type": "object",
4253
+ "description": "One row from GET /functions/{id}/logs. Represents a single\ncaptured log line emitted by the running handler (e.g. via\n`console.log` / `console.error`).\n",
4254
+ "properties": {
4255
+ "id": {
4256
+ "type": "string",
4257
+ "format": "uuid",
4258
+ "description": "Unique log row id (stable across pages)."
4259
+ },
4260
+ "function_id": {
4261
+ "type": "string",
4262
+ "format": "uuid",
4263
+ "description": "The function this log row belongs to."
4264
+ },
4265
+ "level": {
4266
+ "type": "string",
4267
+ "enum": [
4268
+ "debug",
4269
+ "log",
4270
+ "info",
4271
+ "warn",
4272
+ "error"
4273
+ ],
4274
+ "description": "Severity. `log` is the runtime's default for unannotated\n`console.log` calls; the other levels match standard\n`console.*` methods.\n"
4275
+ },
4276
+ "message": {
4277
+ "type": "string",
4278
+ "description": "The textual message body. The runtime stringifies non-string\narguments before persisting, so this is always a plain\nstring.\n"
4279
+ },
4280
+ "ts": {
4281
+ "type": "string",
4282
+ "format": "date-time",
4283
+ "description": "When the handler emitted this line. Newest-first ordering\non this column drives pagination; clock is the runtime's,\nnot the gateway's.\n"
4284
+ },
4285
+ "metadata": {
4286
+ "type": ["object", "null"],
4287
+ "additionalProperties": true,
4288
+ "description": "Optional structured payload the runtime attaches alongside\nthe message (e.g. extra args passed to `console.log`).\nShape is opaque; treat keys as untyped.\n"
4289
+ }
4290
+ },
4291
+ "required": [
4292
+ "id",
4293
+ "function_id",
4294
+ "level",
4295
+ "message",
4296
+ "ts"
4297
+ ]
4298
+ },
4299
+ "FunctionSecretListItem": {
4300
+ "type": "object",
4301
+ "description": "One row from GET /functions/{id}/secrets. Discriminate on the\n`managed` field:\n * `managed = true` — system secret provisioned by Primitive.\n `description` is set; `created_at` / `updated_at` are\n null because the row is virtual (resolved at deploy time\n from the managed registry, not stored in the secrets\n table).\n * `managed = false` — secret the user set via the API.\n `created_at` / `updated_at` are set; `description` is\n null.\n",
4302
+ "properties": {
4303
+ "key": { "type": "string" },
4304
+ "managed": {
4305
+ "type": "boolean",
4306
+ "description": "True for managed system secrets, false for user-set entries."
4307
+ },
4308
+ "description": {
4309
+ "type": ["string", "null"],
4310
+ "description": "Set on managed entries only; null on user-set entries."
4311
+ },
4312
+ "created_at": {
4313
+ "type": ["string", "null"],
4314
+ "format": "date-time",
4315
+ "description": "Set on user-set entries only; null on managed entries."
4316
+ },
4317
+ "updated_at": {
4318
+ "type": ["string", "null"],
4319
+ "format": "date-time",
4320
+ "description": "Set on user-set entries only; null on managed entries."
4321
+ }
4322
+ },
4323
+ "required": ["key", "managed"]
4324
+ },
4325
+ "CreateFunctionSecretInput": {
4326
+ "type": "object",
4327
+ "additionalProperties": false,
4328
+ "description": "Body for POST /functions/{id}/secrets.",
4329
+ "properties": {
4330
+ "key": {
4331
+ "type": "string",
4332
+ "pattern": "^[A-Z_][A-Z0-9_]*$",
4333
+ "description": "Uppercase letters, digits, and underscores. Must start with\na letter or underscore. System-managed keys (e.g.\nPRIMITIVE_WEBHOOK_SECRET) are reserved.\n"
4334
+ },
4335
+ "value": {
4336
+ "type": "string",
4337
+ "minLength": 1,
4338
+ "maxLength": 4096,
4339
+ "description": "Secret value, up to 4096 UTF-8 bytes. Encrypted at rest.\nNever returned by any read endpoint.\n"
4340
+ }
4341
+ },
4342
+ "required": ["key", "value"]
4343
+ },
4344
+ "SetFunctionSecretInput": {
4345
+ "type": "object",
4346
+ "additionalProperties": false,
4347
+ "description": "Body for PUT /functions/{id}/secrets/{key}. Key comes from the path.",
4348
+ "properties": { "value": {
4349
+ "type": "string",
4350
+ "minLength": 1,
4351
+ "maxLength": 4096
4352
+ } },
4353
+ "required": ["value"]
4354
+ },
4355
+ "FunctionSecretWriteResult": {
4356
+ "type": "object",
4357
+ "description": "Returned by POST and PUT secret routes.",
4358
+ "properties": {
4359
+ "key": { "type": "string" },
4360
+ "created_at": {
4361
+ "type": "string",
4362
+ "format": "date-time"
4363
+ },
4364
+ "updated_at": {
4365
+ "type": "string",
4366
+ "format": "date-time"
4367
+ },
4368
+ "created": {
4369
+ "type": "boolean",
4370
+ "description": "True if this call inserted a new row, false if it updated an existing one."
4371
+ }
4372
+ },
4373
+ "required": [
4374
+ "key",
4375
+ "created_at",
4376
+ "updated_at",
4377
+ "created"
4378
+ ]
4379
+ }
4380
+ }
4381
+ }
4382
+ };
4383
+ //#endregion
4384
+ //#region ../packages/api-core/src/openapi/operations.generated.ts
4385
+ const operationManifest = [
4386
+ {
4387
+ "binaryResponse": false,
4388
+ "bodyRequired": false,
4389
+ "command": "get-account",
4390
+ "description": null,
4391
+ "hasJsonBody": false,
4392
+ "method": "GET",
4393
+ "operationId": "getAccount",
4394
+ "path": "/account",
4395
+ "pathParams": [],
4396
+ "queryParams": [],
4397
+ "requestSchema": null,
4398
+ "responseSchema": {
4399
+ "type": "object",
4400
+ "properties": {
4401
+ "id": {
4402
+ "type": "string",
4403
+ "format": "uuid"
4404
+ },
4405
+ "email": { "type": "string" },
4406
+ "plan": { "type": "string" },
4407
+ "created_at": {
4408
+ "type": "string",
4409
+ "format": "date-time"
4410
+ },
4411
+ "onboarding_completed": { "type": "boolean" },
4412
+ "onboarding_step": { "type": ["string", "null"] },
4413
+ "stripe_subscription_status": { "type": ["string", "null"] },
4414
+ "subscription_current_period_end": {
4415
+ "type": ["string", "null"],
4416
+ "format": "date-time"
4417
+ },
4418
+ "subscription_cancel_at_period_end": { "type": ["boolean", "null"] },
4419
+ "spam_threshold": {
4061
4420
  "type": ["number", "null"],
4062
4421
  "minimum": 0,
4063
4422
  "maximum": 15
@@ -5249,8 +5608,11 @@ const operationManifest = [
5249
5608
  "type": "string"
5250
5609
  },
5251
5610
  {
5611
+ "default": 50,
5252
5612
  "description": "Number of results per page",
5253
5613
  "enum": null,
5614
+ "maximum": 100,
5615
+ "minimum": 1,
5254
5616
  "name": "limit",
5255
5617
  "required": false,
5256
5618
  "type": "integer"
@@ -5519,13 +5881,17 @@ const operationManifest = [
5519
5881
  "type": "string"
5520
5882
  },
5521
5883
  {
5884
+ "default": 50,
5522
5885
  "description": "Number of results per page",
5523
5886
  "enum": null,
5887
+ "maximum": 100,
5888
+ "minimum": 1,
5524
5889
  "name": "limit",
5525
5890
  "required": false,
5526
5891
  "type": "integer"
5527
5892
  },
5528
5893
  {
5894
+ "default": "true",
5529
5895
  "description": "Include subject/body highlight snippets when text search is active.",
5530
5896
  "enum": ["true", "false"],
5531
5897
  "name": "snippet",
@@ -5533,6 +5899,7 @@ const operationManifest = [
5533
5899
  "type": "string"
5534
5900
  },
5535
5901
  {
5902
+ "default": "true",
5536
5903
  "description": "Include facet counts for sender, domain, status, and attachment presence.",
5537
5904
  "enum": ["true", "false"],
5538
5905
  "name": "include_facets",
@@ -6538,6 +6905,439 @@ const operationManifest = [
6538
6905
  "tag": "Functions",
6539
6906
  "tagCommand": "functions"
6540
6907
  },
6908
+ {
6909
+ "binaryResponse": false,
6910
+ "bodyRequired": false,
6911
+ "command": "get-function-test-run-trace",
6912
+ "description": "Returns the current end-to-end trace for a function test run.\nThe trace is intentionally partial while the test is still in\nflight: callers can poll this endpoint and watch it fill in\nfrom send -> inbound -> webhook deliveries -> outbound\nrequests, logs, and replies.\n",
6913
+ "hasJsonBody": false,
6914
+ "method": "GET",
6915
+ "operationId": "getFunctionTestRunTrace",
6916
+ "path": "/functions/{id}/test-runs/{run_id}/trace",
6917
+ "pathParams": [{
6918
+ "description": "Resource UUID",
6919
+ "enum": null,
6920
+ "name": "id",
6921
+ "required": true,
6922
+ "type": "string"
6923
+ }, {
6924
+ "description": "Function test run id returned by POST /functions/{id}/test.",
6925
+ "enum": null,
6926
+ "name": "run_id",
6927
+ "required": true,
6928
+ "type": "string"
6929
+ }],
6930
+ "queryParams": [],
6931
+ "requestSchema": null,
6932
+ "responseSchema": {
6933
+ "type": "object",
6934
+ "description": "End-to-end trace for a `POST /functions/{id}/test` run. The\nshape is stable, but many nested sections are null or empty\nuntil the corresponding phase has happened.\n",
6935
+ "properties": {
6936
+ "state": {
6937
+ "type": "string",
6938
+ "description": "High-level state for a function test run trace:\n - `send_failed`: the initial test email send failed.\n - `waiting_for_send`: the test run was created but no send result has been recorded yet.\n - `waiting_for_inbound`: the test send was queued and the matching inbound email has not arrived yet.\n - `waiting_for_function`: the inbound email arrived and webhook/function processing is still in flight.\n - `completed`: the function webhook completed successfully.\n - `failed`: webhook delivery exhausted retries.\n",
6939
+ "enum": [
6940
+ "send_failed",
6941
+ "waiting_for_send",
6942
+ "waiting_for_inbound",
6943
+ "waiting_for_function",
6944
+ "completed",
6945
+ "failed"
6946
+ ]
6947
+ },
6948
+ "test_run": {
6949
+ "type": "object",
6950
+ "properties": {
6951
+ "id": {
6952
+ "type": "string",
6953
+ "format": "uuid"
6954
+ },
6955
+ "function_id": {
6956
+ "type": "string",
6957
+ "format": "uuid"
6958
+ },
6959
+ "inbound_domain": { "type": "string" },
6960
+ "to": { "type": "string" },
6961
+ "from": { "type": "string" },
6962
+ "subject": { "type": "string" },
6963
+ "poll_since": {
6964
+ "type": "string",
6965
+ "format": "date-time"
6966
+ },
6967
+ "created_at": {
6968
+ "type": "string",
6969
+ "format": "date-time"
6970
+ },
6971
+ "sent_at": {
6972
+ "type": ["string", "null"],
6973
+ "format": "date-time"
6974
+ },
6975
+ "send_error": { "type": ["string", "null"] }
6976
+ },
6977
+ "required": [
6978
+ "id",
6979
+ "function_id",
6980
+ "inbound_domain",
6981
+ "to",
6982
+ "from",
6983
+ "subject",
6984
+ "poll_since",
6985
+ "created_at",
6986
+ "sent_at",
6987
+ "send_error"
6988
+ ]
6989
+ },
6990
+ "test_send": {
6991
+ "type": ["object", "null"],
6992
+ "properties": {
6993
+ "id": {
6994
+ "type": "string",
6995
+ "format": "uuid"
6996
+ },
6997
+ "status": {
6998
+ "type": "string",
6999
+ "description": "Lifecycle status of a sent_emails row. Possible values:\n\n - `queued`: pre-call INSERT; the outbound agent has not\n yet replied.\n - `submitted_to_agent`: agent accepted; `queue_id` is set.\n - `agent_failed`: agent rejected; `error_code` and\n `error_message` carry the reason.\n - `gate_denied`: a recipient-scope gate denied the send;\n the agent was never called. The `gates` array carries\n the denial detail. /send-mail returns 403 in this case\n so callers see the denial synchronously; /sent-emails\n additionally records the row for historical lookup,\n which is when this status appears in a listing.\n - `unknown`: terminal indeterminate; the on-box log\n poller couldn't classify the receiver's response.\n - `delivered` / `bounced` / `deferred` / `wait_timeout`:\n terminal delivery outcomes (see DeliveryStatus).\n",
7000
+ "enum": [
7001
+ "queued",
7002
+ "submitted_to_agent",
7003
+ "agent_failed",
7004
+ "gate_denied",
7005
+ "unknown",
7006
+ "delivered",
7007
+ "bounced",
7008
+ "deferred",
7009
+ "wait_timeout"
7010
+ ]
7011
+ },
7012
+ "queue_id": { "type": ["string", "null"] },
7013
+ "created_at": {
7014
+ "type": "string",
7015
+ "format": "date-time"
7016
+ },
7017
+ "updated_at": {
7018
+ "type": "string",
7019
+ "format": "date-time"
7020
+ }
7021
+ },
7022
+ "required": [
7023
+ "id",
7024
+ "status",
7025
+ "queue_id",
7026
+ "created_at",
7027
+ "updated_at"
7028
+ ]
7029
+ },
7030
+ "inbound_email": {
7031
+ "type": ["object", "null"],
7032
+ "properties": {
7033
+ "id": {
7034
+ "type": "string",
7035
+ "format": "uuid"
7036
+ },
7037
+ "status": {
7038
+ "type": "string",
7039
+ "description": "Lifecycle status of an INBOUND email (a row in the `emails`\ntable). Distinct from `SentEmailStatus`, which describes\nthe OUTBOUND lifecycle (the `sent_emails` table) and uses\na different vocabulary because the lifecycles differ.\nPossible values:\n\n - `pending`: the row was inserted at ingestion (mx_main)\n and has not yet completed the spam / filter / auth\n pipeline. Body and parsed fields are present; webhook\n delivery is not yet scheduled. Most rows transition out\n of `pending` within seconds.\n - `accepted`: the inbound passed the policy gates and is\n queued for webhook delivery. The `webhook_status` field\n tracks the separate webhook-delivery lifecycle from\n this point.\n - `completed`: terminal success. Webhook delivery\n attempted and acknowledged by every active endpoint, OR\n no endpoints are configured, so the row is durably\n archived.\n - `rejected`: terminal failure at ingestion (spam, blocked\n sender, filter rule, malformed). The body and metadata\n are stored for auditing but no webhook fires and the\n row is not repliable.\n\nSee also `webhook_status` (separate enum tracking the\nwebhook-delivery state machine) and `SentEmailStatus` (the\noutbound vocabulary).\n",
7040
+ "enum": [
7041
+ "pending",
7042
+ "accepted",
7043
+ "completed",
7044
+ "rejected"
7045
+ ]
7046
+ },
7047
+ "received_at": {
7048
+ "type": "string",
7049
+ "format": "date-time"
7050
+ },
7051
+ "from": { "type": "string" },
7052
+ "to": { "type": "string" },
7053
+ "subject": { "type": ["string", "null"] },
7054
+ "webhook_status": {
7055
+ "type": ["string", "null"],
7056
+ "description": "Webhook-delivery state for an inbound email. Tracks a\nSEPARATE lifecycle from the email's `status` field; the\nsame row carries both. Possible values:\n\n - `pending`: ingestion is past `pending` (the email itself\n is `accepted`) but the webhook fan-out has not yet\n started for this row.\n - `in_flight`: at least one delivery attempt is in flight.\n - `fired`: terminal success. Every active endpoint\n acknowledged the delivery (or accepted it after retries).\n - `failed`: terminal partial-failure. At least one endpoint\n exhausted its retry budget; some endpoints may still\n have succeeded.\n - `exhausted`: terminal failure. Every endpoint exhausted\n its retry budget without success.\n - `null`: no endpoints configured, so no webhook lifecycle\n applies.\n\nNote that the value `pending` here does NOT mean the email\nis `pending`; it means the email is past ingestion but\nwebhook delivery has not yet begun. Two overlapping uses\nof the word `pending` for distinct lifecycle phases.\n",
7057
+ "enum": [
7058
+ "pending",
7059
+ "in_flight",
7060
+ "fired",
7061
+ "failed",
7062
+ "exhausted",
7063
+ null
7064
+ ]
7065
+ },
7066
+ "webhook_attempt_count": { "type": "integer" },
7067
+ "webhook_last_status_code": { "type": ["integer", "null"] },
7068
+ "webhook_last_error": { "type": ["string", "null"] }
7069
+ },
7070
+ "required": [
7071
+ "id",
7072
+ "status",
7073
+ "received_at",
7074
+ "from",
7075
+ "to",
7076
+ "subject",
7077
+ "webhook_status",
7078
+ "webhook_attempt_count",
7079
+ "webhook_last_status_code",
7080
+ "webhook_last_error"
7081
+ ]
7082
+ },
7083
+ "deliveries": {
7084
+ "type": "array",
7085
+ "items": {
7086
+ "type": "object",
7087
+ "properties": {
7088
+ "id": {
7089
+ "type": "string",
7090
+ "description": "Webhook delivery id."
7091
+ },
7092
+ "endpoint_id": {
7093
+ "type": "string",
7094
+ "format": "uuid"
7095
+ },
7096
+ "endpoint_url": {
7097
+ "type": "string",
7098
+ "format": "uri"
7099
+ },
7100
+ "status": {
7101
+ "type": "string",
7102
+ "enum": [
7103
+ "pending",
7104
+ "delivered",
7105
+ "header_confirmed",
7106
+ "failed"
7107
+ ]
7108
+ },
7109
+ "attempt_count": { "type": "integer" },
7110
+ "duration_ms": { "type": ["integer", "null"] },
7111
+ "last_error": { "type": ["string", "null"] },
7112
+ "last_error_code": { "type": ["string", "null"] },
7113
+ "created_at": {
7114
+ "type": "string",
7115
+ "format": "date-time"
7116
+ },
7117
+ "updated_at": {
7118
+ "type": "string",
7119
+ "format": "date-time"
7120
+ },
7121
+ "endpoint": {
7122
+ "type": ["object", "null"],
7123
+ "properties": {
7124
+ "id": {
7125
+ "type": "string",
7126
+ "format": "uuid"
7127
+ },
7128
+ "kind": {
7129
+ "type": "string",
7130
+ "description": "Endpoint kind. Current traces may include `http` or `function`; future endpoint kinds may appear."
7131
+ },
7132
+ "function_id": {
7133
+ "type": ["string", "null"],
7134
+ "format": "uuid"
7135
+ },
7136
+ "function_name": { "type": ["string", "null"] },
7137
+ "domain_id": {
7138
+ "type": ["string", "null"],
7139
+ "format": "uuid"
7140
+ },
7141
+ "enabled": { "type": "boolean" },
7142
+ "deactivated_at": {
7143
+ "type": ["string", "null"],
7144
+ "format": "date-time"
7145
+ },
7146
+ "is_current_function": { "type": "boolean" }
7147
+ },
7148
+ "required": [
7149
+ "id",
7150
+ "kind",
7151
+ "function_id",
7152
+ "function_name",
7153
+ "domain_id",
7154
+ "enabled",
7155
+ "deactivated_at",
7156
+ "is_current_function"
7157
+ ]
7158
+ }
7159
+ },
7160
+ "required": [
7161
+ "id",
7162
+ "endpoint_id",
7163
+ "endpoint_url",
7164
+ "status",
7165
+ "attempt_count",
7166
+ "duration_ms",
7167
+ "last_error",
7168
+ "last_error_code",
7169
+ "created_at",
7170
+ "updated_at",
7171
+ "endpoint"
7172
+ ]
7173
+ }
7174
+ },
7175
+ "outbound_requests": {
7176
+ "type": "array",
7177
+ "items": {
7178
+ "type": "object",
7179
+ "properties": {
7180
+ "id": {
7181
+ "type": "string",
7182
+ "format": "uuid"
7183
+ },
7184
+ "function_id": {
7185
+ "type": "string",
7186
+ "format": "uuid"
7187
+ },
7188
+ "webhook_delivery_id": { "type": ["string", "null"] },
7189
+ "email_id": {
7190
+ "type": ["string", "null"],
7191
+ "format": "uuid"
7192
+ },
7193
+ "endpoint_id": {
7194
+ "type": ["string", "null"],
7195
+ "format": "uuid"
7196
+ },
7197
+ "method": { "type": "string" },
7198
+ "url": {
7199
+ "type": "string",
7200
+ "format": "uri"
7201
+ },
7202
+ "host": { "type": "string" },
7203
+ "path": { "type": "string" },
7204
+ "status_code": { "type": ["integer", "null"] },
7205
+ "ok": { "type": ["boolean", "null"] },
7206
+ "duration_ms": { "type": "integer" },
7207
+ "error": { "type": ["string", "null"] },
7208
+ "ts": {
7209
+ "type": "string",
7210
+ "format": "date-time"
7211
+ }
7212
+ },
7213
+ "required": [
7214
+ "id",
7215
+ "function_id",
7216
+ "webhook_delivery_id",
7217
+ "email_id",
7218
+ "endpoint_id",
7219
+ "method",
7220
+ "url",
7221
+ "host",
7222
+ "path",
7223
+ "status_code",
7224
+ "ok",
7225
+ "duration_ms",
7226
+ "error",
7227
+ "ts"
7228
+ ]
7229
+ }
7230
+ },
7231
+ "logs": {
7232
+ "type": "array",
7233
+ "items": {
7234
+ "type": "object",
7235
+ "description": "One row from GET /functions/{id}/logs. Represents a single\ncaptured log line emitted by the running handler (e.g. via\n`console.log` / `console.error`).\n",
7236
+ "properties": {
7237
+ "id": {
7238
+ "type": "string",
7239
+ "format": "uuid",
7240
+ "description": "Unique log row id (stable across pages)."
7241
+ },
7242
+ "function_id": {
7243
+ "type": "string",
7244
+ "format": "uuid",
7245
+ "description": "The function this log row belongs to."
7246
+ },
7247
+ "level": {
7248
+ "type": "string",
7249
+ "enum": [
7250
+ "debug",
7251
+ "log",
7252
+ "info",
7253
+ "warn",
7254
+ "error"
7255
+ ],
7256
+ "description": "Severity. `log` is the runtime's default for unannotated\n`console.log` calls; the other levels match standard\n`console.*` methods.\n"
7257
+ },
7258
+ "message": {
7259
+ "type": "string",
7260
+ "description": "The textual message body. The runtime stringifies non-string\narguments before persisting, so this is always a plain\nstring.\n"
7261
+ },
7262
+ "ts": {
7263
+ "type": "string",
7264
+ "format": "date-time",
7265
+ "description": "When the handler emitted this line. Newest-first ordering\non this column drives pagination; clock is the runtime's,\nnot the gateway's.\n"
7266
+ },
7267
+ "metadata": {
7268
+ "type": ["object", "null"],
7269
+ "additionalProperties": true,
7270
+ "description": "Optional structured payload the runtime attaches alongside\nthe message (e.g. extra args passed to `console.log`).\nShape is opaque; treat keys as untyped.\n"
7271
+ }
7272
+ },
7273
+ "required": [
7274
+ "id",
7275
+ "function_id",
7276
+ "level",
7277
+ "message",
7278
+ "ts"
7279
+ ]
7280
+ }
7281
+ },
7282
+ "replies": {
7283
+ "type": "array",
7284
+ "items": {
7285
+ "type": "object",
7286
+ "properties": {
7287
+ "id": {
7288
+ "type": "string",
7289
+ "format": "uuid"
7290
+ },
7291
+ "status": {
7292
+ "type": "string",
7293
+ "description": "Lifecycle status of a sent_emails row. Possible values:\n\n - `queued`: pre-call INSERT; the outbound agent has not\n yet replied.\n - `submitted_to_agent`: agent accepted; `queue_id` is set.\n - `agent_failed`: agent rejected; `error_code` and\n `error_message` carry the reason.\n - `gate_denied`: a recipient-scope gate denied the send;\n the agent was never called. The `gates` array carries\n the denial detail. /send-mail returns 403 in this case\n so callers see the denial synchronously; /sent-emails\n additionally records the row for historical lookup,\n which is when this status appears in a listing.\n - `unknown`: terminal indeterminate; the on-box log\n poller couldn't classify the receiver's response.\n - `delivered` / `bounced` / `deferred` / `wait_timeout`:\n terminal delivery outcomes (see DeliveryStatus).\n",
7294
+ "enum": [
7295
+ "queued",
7296
+ "submitted_to_agent",
7297
+ "agent_failed",
7298
+ "gate_denied",
7299
+ "unknown",
7300
+ "delivered",
7301
+ "bounced",
7302
+ "deferred",
7303
+ "wait_timeout"
7304
+ ]
7305
+ },
7306
+ "to": { "type": "string" },
7307
+ "subject": { "type": "string" },
7308
+ "queue_id": { "type": ["string", "null"] },
7309
+ "created_at": {
7310
+ "type": "string",
7311
+ "format": "date-time"
7312
+ }
7313
+ },
7314
+ "required": [
7315
+ "id",
7316
+ "status",
7317
+ "to",
7318
+ "subject",
7319
+ "queue_id",
7320
+ "created_at"
7321
+ ]
7322
+ }
7323
+ }
7324
+ },
7325
+ "required": [
7326
+ "state",
7327
+ "test_run",
7328
+ "test_send",
7329
+ "inbound_email",
7330
+ "deliveries",
7331
+ "outbound_requests",
7332
+ "logs",
7333
+ "replies"
7334
+ ]
7335
+ },
7336
+ "sdkName": "getFunctionTestRunTrace",
7337
+ "summary": "Get a function test run trace",
7338
+ "tag": "Functions",
7339
+ "tagCommand": "functions"
7340
+ },
6541
7341
  {
6542
7342
  "binaryResponse": false,
6543
7343
  "bodyRequired": false,
@@ -6555,8 +7355,11 @@ const operationManifest = [
6555
7355
  "type": "string"
6556
7356
  }],
6557
7357
  "queryParams": [{
7358
+ "default": 50,
6558
7359
  "description": "Maximum number of rows to return. Clamped to 1..200; default\n50.\n",
6559
7360
  "enum": null,
7361
+ "maximum": 200,
7362
+ "minimum": 1,
6560
7363
  "name": "limit",
6561
7364
  "required": false,
6562
7365
  "type": "integer"
@@ -6854,8 +7657,13 @@ const operationManifest = [
6854
7657
  },
6855
7658
  "responseSchema": {
6856
7659
  "type": "object",
6857
- "description": "Metadata returned by POST /functions/{id}/test. The send is\nqueued; the actual invocation lands on the function's\ninvocations list a few seconds later as the inbound mail\ntraverses the MX path.\n",
7660
+ "description": "Metadata returned by POST /functions/{id}/test. The send is\nqueued; poll `trace_url` to watch the run progress through\nsend -> inbound -> webhook deliveries -> outbound requests,\nlogs, and replies.\n",
6858
7661
  "properties": {
7662
+ "test_run_id": {
7663
+ "type": "string",
7664
+ "format": "uuid",
7665
+ "description": "Durable test run id used to fetch the run trace."
7666
+ },
6859
7667
  "inbound_domain": {
6860
7668
  "type": "string",
6861
7669
  "description": "Verified inbound domain the test email was sent to."
@@ -6885,16 +7693,22 @@ const operationManifest = [
6885
7693
  "type": "string",
6886
7694
  "format": "uri",
6887
7695
  "description": "Function detail page where invocations show up live."
7696
+ },
7697
+ "trace_url": {
7698
+ "type": "string",
7699
+ "description": "Relative API URL for GET /functions/{id}/test-runs/{test_run_id}/trace."
6888
7700
  }
6889
7701
  },
6890
7702
  "required": [
7703
+ "test_run_id",
6891
7704
  "inbound_domain",
6892
7705
  "to",
6893
7706
  "from",
6894
7707
  "send_id",
6895
7708
  "subject",
6896
7709
  "poll_since",
6897
- "watch_url"
7710
+ "watch_url",
7711
+ "trace_url"
6898
7712
  ]
6899
7713
  },
6900
7714
  "sdkName": "testFunction",
@@ -7380,8 +8194,11 @@ const operationManifest = [
7380
8194
  "type": "string"
7381
8195
  },
7382
8196
  {
8197
+ "default": 50,
7383
8198
  "description": "Number of results per page",
7384
8199
  "enum": null,
8200
+ "maximum": 100,
8201
+ "minimum": 1,
7385
8202
  "name": "limit",
7386
8203
  "required": false,
7387
8204
  "type": "integer"
@@ -7953,8 +8770,11 @@ const operationManifest = [
7953
8770
  "type": "string"
7954
8771
  },
7955
8772
  {
8773
+ "default": 50,
7956
8774
  "description": "Number of results per page",
7957
8775
  "enum": null,
8776
+ "maximum": 100,
8777
+ "minimum": 1,
7958
8778
  "name": "limit",
7959
8779
  "required": false,
7960
8780
  "type": "integer"