@primitivedotdev/sdk 0.18.0 → 0.20.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.
@@ -274,6 +274,183 @@ export const operationManifest = [
274
274
  "tag": "Account",
275
275
  "tagCommand": "account"
276
276
  },
277
+ {
278
+ "binaryResponse": false,
279
+ "bodyRequired": false,
280
+ "command": "cli-logout",
281
+ "description": "Revokes the API key used to authenticate the request. CLI clients use\nthis endpoint during `primitive logout` before removing local credentials.\n",
282
+ "hasJsonBody": true,
283
+ "method": "POST",
284
+ "operationId": "cliLogout",
285
+ "path": "/cli/logout",
286
+ "pathParams": [],
287
+ "queryParams": [],
288
+ "requestSchema": {
289
+ "type": "object",
290
+ "additionalProperties": false,
291
+ "properties": {
292
+ "key_id": {
293
+ "type": "string",
294
+ "format": "uuid",
295
+ "description": "Optional key id guard; when provided it must match the authenticated API key"
296
+ }
297
+ }
298
+ },
299
+ "responseSchema": {
300
+ "type": "object",
301
+ "properties": {
302
+ "revoked": {
303
+ "type": "boolean",
304
+ "const": true
305
+ },
306
+ "key_id": {
307
+ "type": "string",
308
+ "format": "uuid"
309
+ }
310
+ },
311
+ "required": [
312
+ "revoked",
313
+ "key_id"
314
+ ]
315
+ },
316
+ "sdkName": "cliLogout",
317
+ "summary": "Revoke the current CLI API key",
318
+ "tag": "CLI",
319
+ "tagCommand": "cli"
320
+ },
321
+ {
322
+ "binaryResponse": false,
323
+ "bodyRequired": true,
324
+ "command": "poll-cli-login",
325
+ "description": "Polls a CLI login session until the browser approval either succeeds,\nis denied, expires, or is polled too quickly. The API key is generated\nonly after approval and is returned exactly once.\n",
326
+ "hasJsonBody": true,
327
+ "method": "POST",
328
+ "operationId": "pollCliLogin",
329
+ "path": "/cli/login/poll",
330
+ "pathParams": [],
331
+ "queryParams": [],
332
+ "requestSchema": {
333
+ "type": "object",
334
+ "additionalProperties": false,
335
+ "properties": {
336
+ "device_code": {
337
+ "type": "string",
338
+ "minLength": 1
339
+ }
340
+ },
341
+ "required": [
342
+ "device_code"
343
+ ]
344
+ },
345
+ "responseSchema": {
346
+ "type": "object",
347
+ "properties": {
348
+ "api_key": {
349
+ "type": "string",
350
+ "description": "Newly-created API key for CLI authentication"
351
+ },
352
+ "key_id": {
353
+ "type": "string",
354
+ "format": "uuid"
355
+ },
356
+ "key_prefix": {
357
+ "type": "string"
358
+ },
359
+ "org_id": {
360
+ "type": "string",
361
+ "format": "uuid"
362
+ },
363
+ "org_name": {
364
+ "type": [
365
+ "string",
366
+ "null"
367
+ ]
368
+ }
369
+ },
370
+ "required": [
371
+ "api_key",
372
+ "key_id",
373
+ "key_prefix",
374
+ "org_id",
375
+ "org_name"
376
+ ]
377
+ },
378
+ "sdkName": "pollCliLogin",
379
+ "summary": "Poll CLI browser login",
380
+ "tag": "CLI",
381
+ "tagCommand": "cli"
382
+ },
383
+ {
384
+ "binaryResponse": false,
385
+ "bodyRequired": false,
386
+ "command": "start-cli-login",
387
+ "description": "Starts a browser-assisted CLI login session. The response includes a\ndevice code for polling and a user code that the user approves in the\nbrowser. This endpoint does not require an API key.\n",
388
+ "hasJsonBody": true,
389
+ "method": "POST",
390
+ "operationId": "startCliLogin",
391
+ "path": "/cli/login/start",
392
+ "pathParams": [],
393
+ "queryParams": [],
394
+ "requestSchema": {
395
+ "type": "object",
396
+ "additionalProperties": false,
397
+ "properties": {
398
+ "device_name": {
399
+ "type": "string",
400
+ "minLength": 1,
401
+ "maxLength": 80,
402
+ "description": "Human-readable device name shown during browser approval"
403
+ },
404
+ "metadata": {
405
+ "type": "object",
406
+ "additionalProperties": true,
407
+ "description": "Optional client metadata stored with the login session; serialized JSON must be 2048 bytes or fewer"
408
+ }
409
+ }
410
+ },
411
+ "responseSchema": {
412
+ "type": "object",
413
+ "properties": {
414
+ "device_code": {
415
+ "type": "string",
416
+ "description": "Opaque code used by the CLI to poll for approval"
417
+ },
418
+ "user_code": {
419
+ "type": "string",
420
+ "pattern": "^[BCDFGHJKLMNPQRSTVWXZ]{4}-[BCDFGHJKLMNPQRSTVWXZ]{4}$",
421
+ "description": "Short code the user confirms in the browser"
422
+ },
423
+ "verification_uri": {
424
+ "type": "string",
425
+ "description": "Browser URL where the user approves the login"
426
+ },
427
+ "verification_uri_complete": {
428
+ "type": "string",
429
+ "description": "Browser URL with the user code prefilled"
430
+ },
431
+ "expires_in": {
432
+ "type": "integer",
433
+ "description": "Seconds until the login session expires"
434
+ },
435
+ "interval": {
436
+ "type": "integer",
437
+ "description": "Minimum seconds between poll requests"
438
+ }
439
+ },
440
+ "required": [
441
+ "device_code",
442
+ "user_code",
443
+ "verification_uri",
444
+ "verification_uri_complete",
445
+ "expires_in",
446
+ "interval"
447
+ ]
448
+ },
449
+ "sdkName": "startCliLogin",
450
+ "summary": "Start CLI browser login",
451
+ "tag": "CLI",
452
+ "tagCommand": "cli"
453
+ },
277
454
  {
278
455
  "binaryResponse": false,
279
456
  "bodyRequired": true,
@@ -668,7 +845,7 @@ export const operationManifest = [
668
845
  "binaryResponse": false,
669
846
  "bodyRequired": false,
670
847
  "command": "discard-email-content",
671
- "description": "Permanently deletes the email's raw bytes, parsed body (text + HTML),\nand attachments while preserving metadata (sender, recipient,\nsubject, timestamps, hashes, attachment manifest) for audit logs.\nIdempotent: a second call returns success with\n`already_discarded: true` and does no work.\n\n**Gated** on the customer's discard-content opt-in (managed in the\ndashboard at Settings > Webhooks). When the toggle is off, this\nendpoint returns `403` with code `discard_not_enabled` and a\nmessage pointing the human at the dashboard. There is intentionally\nno API to flip this toggle opting in to a destructive,\nnon-reversible operation must be a deliberate human click in the\nUI.\n",
848
+ "description": "Permanently deletes the email's raw bytes, parsed body (text + HTML),\nand attachments while preserving metadata (sender, recipient,\nsubject, timestamps, hashes, attachment manifest) for audit logs.\nIdempotent: a second call returns success with\n`already_discarded: true` and does no work.\n\n**Gated** on the customer's discard-content opt-in (managed in the\ndashboard at Settings > Webhooks). When the toggle is off, this\nendpoint returns `403` with code `discard_not_enabled` and a\nmessage pointing the human at the dashboard. There is intentionally\nno API to flip this toggle. Opting in to a destructive,\nnon-reversible operation must be a deliberate human click in the\nUI.\n",
672
849
  "hasJsonBody": false,
673
850
  "method": "POST",
674
851
  "operationId": "discardEmailContent",
@@ -2034,6 +2211,696 @@ export const operationManifest = [
2034
2211
  "tag": "Filters",
2035
2212
  "tagCommand": "filters"
2036
2213
  },
2214
+ {
2215
+ "binaryResponse": false,
2216
+ "bodyRequired": true,
2217
+ "command": "create-function",
2218
+ "description": "Creates and deploys a new function. The handler must be a single\nESM module that exports a default async function receiving the\n`email.received` event (see the Webhook payload section for the\nfull schema). Code is bundled before being uploaded; ship a\nsingle self-contained file rather than relying on external\nimports.\n\n**Code limits.** `code` is capped at 1 MiB UTF-8. `sourceMap`\n(optional) is capped at 5 MiB UTF-8 and is stored only on the\nedge runtime side; it is not persisted in Primitive's database.\n\n**Auto-wiring.** On successful deploy, Primitive automatically\ncreates a webhook endpoint that delivers inbound mail to the\nfunction. There is nothing to configure on the Endpoints API\nfor this to work; the gateway URL returned here is for\nreference only and is not directly callable from outside.\n\n**Secrets.** New functions ship with the managed secrets\n(`PRIMITIVE_WEBHOOK_SECRET`, `PRIMITIVE_API_KEY`) already\nbound. Add user-set secrets via\n`POST /functions/{id}/secrets`; secret writes only land in the\nrunning handler on the next redeploy.\n",
2219
+ "hasJsonBody": true,
2220
+ "method": "POST",
2221
+ "operationId": "createFunction",
2222
+ "path": "/functions",
2223
+ "pathParams": [],
2224
+ "queryParams": [],
2225
+ "requestSchema": {
2226
+ "type": "object",
2227
+ "additionalProperties": false,
2228
+ "properties": {
2229
+ "name": {
2230
+ "type": "string",
2231
+ "pattern": "^[a-z0-9_-]{1,64}$",
2232
+ "description": "Slug-style name. Lowercase letters, digits, hyphens, and\nunderscores. 1 to 64 characters. Must be unique within the\norg; a 409 is returned on collision.\n"
2233
+ },
2234
+ "code": {
2235
+ "type": "string",
2236
+ "minLength": 1,
2237
+ "maxLength": 1048576,
2238
+ "description": "Bundled handler as a single ESM module. Up to 1 MiB UTF-8.\nMust export a default `{ async fetch(req, env, ctx) { ... } }`\nobject.\n"
2239
+ },
2240
+ "sourceMap": {
2241
+ "type": "string",
2242
+ "minLength": 1,
2243
+ "maxLength": 5242880,
2244
+ "description": "Optional source map for the bundle. Up to 5 MiB UTF-8.\nStored only on the runtime side (not in Primitive's\ndatabase) and used to symbolicate stack traces in the\nfunction's logs.\n"
2245
+ }
2246
+ },
2247
+ "required": [
2248
+ "name",
2249
+ "code"
2250
+ ]
2251
+ },
2252
+ "responseSchema": {
2253
+ "type": "object",
2254
+ "description": "Returned by POST /functions on a successful deploy.",
2255
+ "properties": {
2256
+ "id": {
2257
+ "type": "string",
2258
+ "format": "uuid"
2259
+ },
2260
+ "name": {
2261
+ "type": "string"
2262
+ },
2263
+ "deploy_status": {
2264
+ "type": "string",
2265
+ "enum": [
2266
+ "pending",
2267
+ "deployed",
2268
+ "failed"
2269
+ ],
2270
+ "description": "Lifecycle state of the latest deploy attempt:\n * `pending` — deploy in flight; the runtime has not yet\n confirmed the new bundle is live.\n * `deployed` — the running edge handler is the latest code.\n * `failed` — the most recent deploy attempt failed; the\n previously-live code (if any) is still running. The\n `deploy_error` field carries the error message.\n"
2271
+ },
2272
+ "gateway_url": {
2273
+ "type": "string",
2274
+ "format": "uri"
2275
+ }
2276
+ },
2277
+ "required": [
2278
+ "id",
2279
+ "name",
2280
+ "deploy_status",
2281
+ "gateway_url"
2282
+ ]
2283
+ },
2284
+ "sdkName": "createFunction",
2285
+ "summary": "Deploy a function",
2286
+ "tag": "Functions",
2287
+ "tagCommand": "functions"
2288
+ },
2289
+ {
2290
+ "binaryResponse": false,
2291
+ "bodyRequired": true,
2292
+ "command": "create-function-secret",
2293
+ "description": "Idempotent insert-or-update keyed on `(function_id, key)`.\nReturns 201 the first time the key is set, 200 on subsequent\nupdates. Values are encrypted at rest and only become visible\nto the running handler on the next deploy (`PUT /functions/{id}`\nwith the existing code is sufficient to refresh bindings).\n\nKeys must match `^[A-Z_][A-Z0-9_]*$` (uppercase letters,\ndigits, underscores; first character is a letter or\nunderscore). Values are at most 4096 UTF-8 bytes. System-\nmanaged keys are reserved and rejected.\n",
2294
+ "hasJsonBody": true,
2295
+ "method": "POST",
2296
+ "operationId": "createFunctionSecret",
2297
+ "path": "/functions/{id}/secrets",
2298
+ "pathParams": [
2299
+ {
2300
+ "description": "Resource UUID",
2301
+ "enum": null,
2302
+ "name": "id",
2303
+ "required": true,
2304
+ "type": "string"
2305
+ }
2306
+ ],
2307
+ "queryParams": [],
2308
+ "requestSchema": {
2309
+ "type": "object",
2310
+ "additionalProperties": false,
2311
+ "description": "Body for POST /functions/{id}/secrets.",
2312
+ "properties": {
2313
+ "key": {
2314
+ "type": "string",
2315
+ "pattern": "^[A-Z_][A-Z0-9_]*$",
2316
+ "description": "Uppercase letters, digits, and underscores. Must start with\na letter or underscore. System-managed keys (e.g.\nPRIMITIVE_WEBHOOK_SECRET) are reserved.\n"
2317
+ },
2318
+ "value": {
2319
+ "type": "string",
2320
+ "minLength": 1,
2321
+ "maxLength": 4096,
2322
+ "description": "Secret value, up to 4096 UTF-8 bytes. Encrypted at rest.\nNever returned by any read endpoint.\n"
2323
+ }
2324
+ },
2325
+ "required": [
2326
+ "key",
2327
+ "value"
2328
+ ]
2329
+ },
2330
+ "responseSchema": {
2331
+ "type": "object",
2332
+ "description": "Returned by POST and PUT secret routes.",
2333
+ "properties": {
2334
+ "key": {
2335
+ "type": "string"
2336
+ },
2337
+ "created_at": {
2338
+ "type": "string",
2339
+ "format": "date-time"
2340
+ },
2341
+ "updated_at": {
2342
+ "type": "string",
2343
+ "format": "date-time"
2344
+ },
2345
+ "created": {
2346
+ "type": "boolean",
2347
+ "description": "True if this call inserted a new row, false if it updated an existing one."
2348
+ }
2349
+ },
2350
+ "required": [
2351
+ "key",
2352
+ "created_at",
2353
+ "updated_at",
2354
+ "created"
2355
+ ]
2356
+ },
2357
+ "sdkName": "createFunctionSecret",
2358
+ "summary": "Create or update a secret",
2359
+ "tag": "Functions",
2360
+ "tagCommand": "functions"
2361
+ },
2362
+ {
2363
+ "binaryResponse": false,
2364
+ "bodyRequired": false,
2365
+ "command": "delete-function",
2366
+ "description": "Soft-deletes the function row, removes the script from the edge\nruntime, and deactivates the auto-wired webhook endpoint so no\nfurther inbound mail is delivered. Past deploy history,\ninvocations, and logs are retained.\n\nReturns 502 if the runtime delete fails partway; the function\nrow stays in place and the call is safe to retry until it\nsucceeds.\n",
2367
+ "hasJsonBody": false,
2368
+ "method": "DELETE",
2369
+ "operationId": "deleteFunction",
2370
+ "path": "/functions/{id}",
2371
+ "pathParams": [
2372
+ {
2373
+ "description": "Resource UUID",
2374
+ "enum": null,
2375
+ "name": "id",
2376
+ "required": true,
2377
+ "type": "string"
2378
+ }
2379
+ ],
2380
+ "queryParams": [],
2381
+ "requestSchema": null,
2382
+ "responseSchema": null,
2383
+ "sdkName": "deleteFunction",
2384
+ "summary": "Delete a function",
2385
+ "tag": "Functions",
2386
+ "tagCommand": "functions"
2387
+ },
2388
+ {
2389
+ "binaryResponse": false,
2390
+ "bodyRequired": false,
2391
+ "command": "delete-function-secret",
2392
+ "description": "Removes the secret. The binding stays live in the running\nhandler until the next deploy refreshes the binding set\n(`PUT /functions/{id}` with the existing code is sufficient).\nReturns 404 if the key did not exist. Managed system keys\ncannot be deleted.\n",
2393
+ "hasJsonBody": false,
2394
+ "method": "DELETE",
2395
+ "operationId": "deleteFunctionSecret",
2396
+ "path": "/functions/{id}/secrets/{key}",
2397
+ "pathParams": [
2398
+ {
2399
+ "description": "Resource UUID",
2400
+ "enum": null,
2401
+ "name": "id",
2402
+ "required": true,
2403
+ "type": "string"
2404
+ },
2405
+ {
2406
+ "description": "Secret key. Must match `^[A-Z_][A-Z0-9_]*$`.",
2407
+ "enum": null,
2408
+ "name": "key",
2409
+ "required": true,
2410
+ "type": "string"
2411
+ }
2412
+ ],
2413
+ "queryParams": [],
2414
+ "requestSchema": null,
2415
+ "responseSchema": null,
2416
+ "sdkName": "deleteFunctionSecret",
2417
+ "summary": "Delete a secret",
2418
+ "tag": "Functions",
2419
+ "tagCommand": "functions"
2420
+ },
2421
+ {
2422
+ "binaryResponse": false,
2423
+ "bodyRequired": false,
2424
+ "command": "get-function",
2425
+ "description": "Returns the full record for a function, including its current\nsource code and the deploy status / error from the most recent\ndeploy attempt.\n",
2426
+ "hasJsonBody": false,
2427
+ "method": "GET",
2428
+ "operationId": "getFunction",
2429
+ "path": "/functions/{id}",
2430
+ "pathParams": [
2431
+ {
2432
+ "description": "Resource UUID",
2433
+ "enum": null,
2434
+ "name": "id",
2435
+ "required": true,
2436
+ "type": "string"
2437
+ }
2438
+ ],
2439
+ "queryParams": [],
2440
+ "requestSchema": null,
2441
+ "responseSchema": {
2442
+ "type": "object",
2443
+ "description": "Full function record returned by GET / PUT.",
2444
+ "properties": {
2445
+ "id": {
2446
+ "type": "string",
2447
+ "format": "uuid"
2448
+ },
2449
+ "name": {
2450
+ "type": "string"
2451
+ },
2452
+ "code": {
2453
+ "type": "string",
2454
+ "description": "The bundled handler source. UTF-8 string up to 1 MiB. The\nsame value most recently passed as `code` to POST or PUT.\n"
2455
+ },
2456
+ "deploy_status": {
2457
+ "type": "string",
2458
+ "enum": [
2459
+ "pending",
2460
+ "deployed",
2461
+ "failed"
2462
+ ],
2463
+ "description": "Lifecycle state of the latest deploy attempt:\n * `pending` — deploy in flight; the runtime has not yet\n confirmed the new bundle is live.\n * `deployed` — the running edge handler is the latest code.\n * `failed` — the most recent deploy attempt failed; the\n previously-live code (if any) is still running. The\n `deploy_error` field carries the error message.\n"
2464
+ },
2465
+ "deploy_error": {
2466
+ "type": [
2467
+ "string",
2468
+ "null"
2469
+ ],
2470
+ "description": "Error message from the most recent failed deploy, or null\nafter a successful deploy. Surface this to users to explain\na `failed` status without polling.\n"
2471
+ },
2472
+ "deployed_at": {
2473
+ "type": [
2474
+ "string",
2475
+ "null"
2476
+ ],
2477
+ "format": "date-time"
2478
+ },
2479
+ "gateway_url": {
2480
+ "type": "string",
2481
+ "format": "uri"
2482
+ },
2483
+ "created_at": {
2484
+ "type": "string",
2485
+ "format": "date-time"
2486
+ },
2487
+ "updated_at": {
2488
+ "type": "string",
2489
+ "format": "date-time"
2490
+ }
2491
+ },
2492
+ "required": [
2493
+ "id",
2494
+ "name",
2495
+ "code",
2496
+ "deploy_status",
2497
+ "gateway_url",
2498
+ "created_at",
2499
+ "updated_at"
2500
+ ]
2501
+ },
2502
+ "sdkName": "getFunction",
2503
+ "summary": "Get a function",
2504
+ "tag": "Functions",
2505
+ "tagCommand": "functions"
2506
+ },
2507
+ {
2508
+ "binaryResponse": false,
2509
+ "bodyRequired": false,
2510
+ "command": "list-function-secrets",
2511
+ "description": "Returns metadata for every secret bound to the function, with\nmanaged entries (provisioned by Primitive) listed first and\nuser-set entries listed alphabetically after. **Values are\nnever returned.** Secret writes are write-only.\n\nManaged entries (e.g. `PRIMITIVE_WEBHOOK_SECRET`,\n`PRIMITIVE_API_KEY`) carry a `description` instead of\n`created_at` / `updated_at`. They cannot be created, updated,\nor deleted via this API.\n",
2512
+ "hasJsonBody": false,
2513
+ "method": "GET",
2514
+ "operationId": "listFunctionSecrets",
2515
+ "path": "/functions/{id}/secrets",
2516
+ "pathParams": [
2517
+ {
2518
+ "description": "Resource UUID",
2519
+ "enum": null,
2520
+ "name": "id",
2521
+ "required": true,
2522
+ "type": "string"
2523
+ }
2524
+ ],
2525
+ "queryParams": [],
2526
+ "requestSchema": null,
2527
+ "responseSchema": {
2528
+ "type": "object",
2529
+ "properties": {
2530
+ "items": {
2531
+ "type": "array",
2532
+ "items": {
2533
+ "type": "object",
2534
+ "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",
2535
+ "properties": {
2536
+ "key": {
2537
+ "type": "string"
2538
+ },
2539
+ "managed": {
2540
+ "type": "boolean",
2541
+ "description": "True for managed system secrets, false for user-set entries."
2542
+ },
2543
+ "description": {
2544
+ "type": [
2545
+ "string",
2546
+ "null"
2547
+ ],
2548
+ "description": "Set on managed entries only; null on user-set entries."
2549
+ },
2550
+ "created_at": {
2551
+ "type": [
2552
+ "string",
2553
+ "null"
2554
+ ],
2555
+ "format": "date-time",
2556
+ "description": "Set on user-set entries only; null on managed entries."
2557
+ },
2558
+ "updated_at": {
2559
+ "type": [
2560
+ "string",
2561
+ "null"
2562
+ ],
2563
+ "format": "date-time",
2564
+ "description": "Set on user-set entries only; null on managed entries."
2565
+ }
2566
+ },
2567
+ "required": [
2568
+ "key",
2569
+ "managed"
2570
+ ]
2571
+ }
2572
+ }
2573
+ },
2574
+ "required": [
2575
+ "items"
2576
+ ]
2577
+ },
2578
+ "sdkName": "listFunctionSecrets",
2579
+ "summary": "List a function's secrets",
2580
+ "tag": "Functions",
2581
+ "tagCommand": "functions"
2582
+ },
2583
+ {
2584
+ "binaryResponse": false,
2585
+ "bodyRequired": false,
2586
+ "command": "list-functions",
2587
+ "description": "Returns every active (non-deleted) function in the org, newest\nfirst. Each entry carries the deploy status and the gateway URL\nthat the platform's webhook delivery loop posts to. To inspect\nthe source code or deploy errors, use `GET /functions/{id}`.\n",
2588
+ "hasJsonBody": false,
2589
+ "method": "GET",
2590
+ "operationId": "listFunctions",
2591
+ "path": "/functions",
2592
+ "pathParams": [],
2593
+ "queryParams": [],
2594
+ "requestSchema": null,
2595
+ "responseSchema": {
2596
+ "type": "array",
2597
+ "items": {
2598
+ "type": "object",
2599
+ "description": "One row from the function listing.",
2600
+ "properties": {
2601
+ "id": {
2602
+ "type": "string",
2603
+ "format": "uuid",
2604
+ "description": "Function id, also the script name in the edge runtime."
2605
+ },
2606
+ "name": {
2607
+ "type": "string",
2608
+ "description": "Slug-style name set on creation. Stable; cannot be changed."
2609
+ },
2610
+ "deploy_status": {
2611
+ "type": "string",
2612
+ "enum": [
2613
+ "pending",
2614
+ "deployed",
2615
+ "failed"
2616
+ ],
2617
+ "description": "Lifecycle state of the latest deploy attempt:\n * `pending` — deploy in flight; the runtime has not yet\n confirmed the new bundle is live.\n * `deployed` — the running edge handler is the latest code.\n * `failed` — the most recent deploy attempt failed; the\n previously-live code (if any) is still running. The\n `deploy_error` field carries the error message.\n"
2618
+ },
2619
+ "deployed_at": {
2620
+ "type": [
2621
+ "string",
2622
+ "null"
2623
+ ],
2624
+ "format": "date-time",
2625
+ "description": "Timestamp of the most recent successful deploy. Null until the first deploy succeeds."
2626
+ },
2627
+ "gateway_url": {
2628
+ "type": "string",
2629
+ "format": "uri",
2630
+ "description": "URL the platform's webhook delivery loop posts to in order\nto invoke the function. Reference only; not directly\ncallable from outside.\n"
2631
+ },
2632
+ "created_at": {
2633
+ "type": "string",
2634
+ "format": "date-time"
2635
+ },
2636
+ "updated_at": {
2637
+ "type": "string",
2638
+ "format": "date-time"
2639
+ }
2640
+ },
2641
+ "required": [
2642
+ "id",
2643
+ "name",
2644
+ "deploy_status",
2645
+ "gateway_url",
2646
+ "created_at",
2647
+ "updated_at"
2648
+ ]
2649
+ }
2650
+ },
2651
+ "sdkName": "listFunctions",
2652
+ "summary": "List functions",
2653
+ "tag": "Functions",
2654
+ "tagCommand": "functions"
2655
+ },
2656
+ {
2657
+ "binaryResponse": false,
2658
+ "bodyRequired": true,
2659
+ "command": "set-function-secret",
2660
+ "description": "Path-keyed companion to `POST /functions/{id}/secrets`.\nIdempotent: returns 201 the first time the key is set, 200 on\nsubsequent updates. Same validation rules and same write-only\nguarantees as the POST verb; the new value lands in the running\nhandler on the next deploy.\n",
2661
+ "hasJsonBody": true,
2662
+ "method": "PUT",
2663
+ "operationId": "setFunctionSecret",
2664
+ "path": "/functions/{id}/secrets/{key}",
2665
+ "pathParams": [
2666
+ {
2667
+ "description": "Resource UUID",
2668
+ "enum": null,
2669
+ "name": "id",
2670
+ "required": true,
2671
+ "type": "string"
2672
+ },
2673
+ {
2674
+ "description": "Secret key. Must match `^[A-Z_][A-Z0-9_]*$`.",
2675
+ "enum": null,
2676
+ "name": "key",
2677
+ "required": true,
2678
+ "type": "string"
2679
+ }
2680
+ ],
2681
+ "queryParams": [],
2682
+ "requestSchema": {
2683
+ "type": "object",
2684
+ "additionalProperties": false,
2685
+ "description": "Body for PUT /functions/{id}/secrets/{key}. Key comes from the path.",
2686
+ "properties": {
2687
+ "value": {
2688
+ "type": "string",
2689
+ "minLength": 1,
2690
+ "maxLength": 4096
2691
+ }
2692
+ },
2693
+ "required": [
2694
+ "value"
2695
+ ]
2696
+ },
2697
+ "responseSchema": {
2698
+ "type": "object",
2699
+ "description": "Returned by POST and PUT secret routes.",
2700
+ "properties": {
2701
+ "key": {
2702
+ "type": "string"
2703
+ },
2704
+ "created_at": {
2705
+ "type": "string",
2706
+ "format": "date-time"
2707
+ },
2708
+ "updated_at": {
2709
+ "type": "string",
2710
+ "format": "date-time"
2711
+ },
2712
+ "created": {
2713
+ "type": "boolean",
2714
+ "description": "True if this call inserted a new row, false if it updated an existing one."
2715
+ }
2716
+ },
2717
+ "required": [
2718
+ "key",
2719
+ "created_at",
2720
+ "updated_at",
2721
+ "created"
2722
+ ]
2723
+ },
2724
+ "sdkName": "setFunctionSecret",
2725
+ "summary": "Set a secret by key",
2726
+ "tag": "Functions",
2727
+ "tagCommand": "functions"
2728
+ },
2729
+ {
2730
+ "binaryResponse": false,
2731
+ "bodyRequired": false,
2732
+ "command": "test-function",
2733
+ "description": "Sends a real test email from a Primitive-controlled sender to a\nsynthetic local-part on one of the org's verified inbound\ndomains. The function fires through the normal MX delivery\npath, so reply / send-mail calls from inside the handler\nagainst the inbound's `email.id` work the same as in\nproduction. Returns immediately after the send is queued; the\ninvocation appears on the function's invocations list within a\nfew seconds.\n\nRequires that the function is currently `deployed`. Returns 422\nif the function is in `pending` or `failed` state, or if the\norg has no verified inbound domain to receive the test mail.\n",
2734
+ "hasJsonBody": false,
2735
+ "method": "POST",
2736
+ "operationId": "testFunction",
2737
+ "path": "/functions/{id}/test",
2738
+ "pathParams": [
2739
+ {
2740
+ "description": "Resource UUID",
2741
+ "enum": null,
2742
+ "name": "id",
2743
+ "required": true,
2744
+ "type": "string"
2745
+ }
2746
+ ],
2747
+ "queryParams": [],
2748
+ "requestSchema": null,
2749
+ "responseSchema": {
2750
+ "type": "object",
2751
+ "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",
2752
+ "properties": {
2753
+ "inbound_domain": {
2754
+ "type": "string",
2755
+ "description": "Verified inbound domain the test email was sent to."
2756
+ },
2757
+ "to": {
2758
+ "type": "string",
2759
+ "description": "Synthetic local-part plus inbound_domain. Visible in the org's inbox."
2760
+ },
2761
+ "from": {
2762
+ "type": "string",
2763
+ "description": "Primitive-controlled outbound sender used for the test."
2764
+ },
2765
+ "send_id": {
2766
+ "type": "string",
2767
+ "description": "Outbound message id from the underlying send. NOT the\ninbound email's id; the inbound id is created when the\nemail arrives via MX and lands on the function's\ninvocations list.\n"
2768
+ },
2769
+ "subject": {
2770
+ "type": "string",
2771
+ "description": "Subject placed on the test email so it can be located in the inbox."
2772
+ },
2773
+ "poll_since": {
2774
+ "type": "string",
2775
+ "format": "date-time",
2776
+ "description": "ISO timestamp suitable as a `since` lower bound when\npolling /emails for the inbound's arrival. Captured\nslightly before the send to absorb light clock skew.\n"
2777
+ },
2778
+ "watch_url": {
2779
+ "type": "string",
2780
+ "format": "uri",
2781
+ "description": "Function detail page where invocations show up live."
2782
+ }
2783
+ },
2784
+ "required": [
2785
+ "inbound_domain",
2786
+ "to",
2787
+ "from",
2788
+ "send_id",
2789
+ "subject",
2790
+ "poll_since",
2791
+ "watch_url"
2792
+ ]
2793
+ },
2794
+ "sdkName": "testFunction",
2795
+ "summary": "Send a test invocation",
2796
+ "tag": "Functions",
2797
+ "tagCommand": "functions"
2798
+ },
2799
+ {
2800
+ "binaryResponse": false,
2801
+ "bodyRequired": true,
2802
+ "command": "update-function",
2803
+ "description": "Replaces the function's source code with the body's `code` and\ntriggers a redeploy. Same size limits as `POST /functions`.\nUse this verb to push secret writes into the running handler:\npassing the same `code` re-runs the deploy and refreshes the\nbinding set with the latest values from the secrets table.\n\nOn a 502 deploy failure, the previously-deployed code stays\nlive; the runtime never serves a half-built bundle. The\n`deploy_error` field on the returned record carries the error\nthat came back from the runtime so you can surface it to users\nwithout polling.\n",
2804
+ "hasJsonBody": true,
2805
+ "method": "PUT",
2806
+ "operationId": "updateFunction",
2807
+ "path": "/functions/{id}",
2808
+ "pathParams": [
2809
+ {
2810
+ "description": "Resource UUID",
2811
+ "enum": null,
2812
+ "name": "id",
2813
+ "required": true,
2814
+ "type": "string"
2815
+ }
2816
+ ],
2817
+ "queryParams": [],
2818
+ "requestSchema": {
2819
+ "type": "object",
2820
+ "additionalProperties": false,
2821
+ "properties": {
2822
+ "code": {
2823
+ "type": "string",
2824
+ "minLength": 1,
2825
+ "maxLength": 1048576,
2826
+ "description": "New bundled handler. Same rules as CreateFunctionInput.code."
2827
+ },
2828
+ "sourceMap": {
2829
+ "type": "string",
2830
+ "minLength": 1,
2831
+ "maxLength": 5242880
2832
+ }
2833
+ },
2834
+ "required": [
2835
+ "code"
2836
+ ]
2837
+ },
2838
+ "responseSchema": {
2839
+ "type": "object",
2840
+ "description": "Full function record returned by GET / PUT.",
2841
+ "properties": {
2842
+ "id": {
2843
+ "type": "string",
2844
+ "format": "uuid"
2845
+ },
2846
+ "name": {
2847
+ "type": "string"
2848
+ },
2849
+ "code": {
2850
+ "type": "string",
2851
+ "description": "The bundled handler source. UTF-8 string up to 1 MiB. The\nsame value most recently passed as `code` to POST or PUT.\n"
2852
+ },
2853
+ "deploy_status": {
2854
+ "type": "string",
2855
+ "enum": [
2856
+ "pending",
2857
+ "deployed",
2858
+ "failed"
2859
+ ],
2860
+ "description": "Lifecycle state of the latest deploy attempt:\n * `pending` — deploy in flight; the runtime has not yet\n confirmed the new bundle is live.\n * `deployed` — the running edge handler is the latest code.\n * `failed` — the most recent deploy attempt failed; the\n previously-live code (if any) is still running. The\n `deploy_error` field carries the error message.\n"
2861
+ },
2862
+ "deploy_error": {
2863
+ "type": [
2864
+ "string",
2865
+ "null"
2866
+ ],
2867
+ "description": "Error message from the most recent failed deploy, or null\nafter a successful deploy. Surface this to users to explain\na `failed` status without polling.\n"
2868
+ },
2869
+ "deployed_at": {
2870
+ "type": [
2871
+ "string",
2872
+ "null"
2873
+ ],
2874
+ "format": "date-time"
2875
+ },
2876
+ "gateway_url": {
2877
+ "type": "string",
2878
+ "format": "uri"
2879
+ },
2880
+ "created_at": {
2881
+ "type": "string",
2882
+ "format": "date-time"
2883
+ },
2884
+ "updated_at": {
2885
+ "type": "string",
2886
+ "format": "date-time"
2887
+ }
2888
+ },
2889
+ "required": [
2890
+ "id",
2891
+ "name",
2892
+ "code",
2893
+ "deploy_status",
2894
+ "gateway_url",
2895
+ "created_at",
2896
+ "updated_at"
2897
+ ]
2898
+ },
2899
+ "sdkName": "updateFunction",
2900
+ "summary": "Update and redeploy a function",
2901
+ "tag": "Functions",
2902
+ "tagCommand": "functions"
2903
+ },
2037
2904
  {
2038
2905
  "binaryResponse": false,
2039
2906
  "bodyRequired": false,