diff --git a/AGENTS.md b/AGENTS.md index 7b2116e..8107248 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -28,7 +28,8 @@ browser. swagger consumed here. When an endpoint's behavior is unclear, read the Go handler rather than guessing. - **Generated low-level client:** [`src/generated/api.ts`](./src/generated/api.ts) - — auto-generated from the swagger by `make openapi` (swagger-typescript-api), + — auto-generated from the swagger by `make openapi` (runs `npm run openapi`, + swagger-typescript-api), post-processed with `@ts-nocheck`. Exposed to users as `@webhookrelay/sdk/generated`. Do not hand-edit; it is regenerated. @@ -54,13 +55,14 @@ src/ params.ts camelCase → snake_case param normalization. resources/ One class per resource, hung off the client: buckets.ts inputs.ts outputs.ts serviceConnections.ts functions.ts webhooks.ts + outbound.ts relay.outbound.* — consumers, event types, endpoints, messages streaming/ poller.ts WebhookPoller — async-iterable pull delivery over /v1/events. socket.ts WebhookSubscription — real-time push over /v1/socket. websocket.ts Isomorphic WebSocket resolver + URL helper. generated/api.ts Generated low-level client (do not edit). test/ Vitest suite (mock fetch + fake WebSocket; no network). -examples/ Runnable usage examples. +examples/ Runnable usage examples (outbound.ts is also run by the tests). swagger/swagger.yaml OpenAPI spec (input to `make openapi`). scripts/ Build/codegen helpers (postprocess-generated.mjs). ``` diff --git a/Makefile b/Makefile index 6c61b14..85a69a1 100644 --- a/Makefile +++ b/Makefile @@ -19,13 +19,7 @@ swagger: # SDK in src/ is the ergonomic surface; the generated client is the raw # escape hatch, re-exported from "@webhookrelay/sdk/generated". openapi: swagger - npx swagger-typescript-api generate \ - -p ./swagger/swagger.yaml \ - -o ./src/generated \ - -n api.ts \ - --extract-request-params \ - --extract-response-body - node scripts/postprocess-generated.mjs + npm run openapi @echo "regenerated src/generated/api.ts" build: diff --git a/README.md b/README.md index 4d1fc74..c115b9f 100644 --- a/README.md +++ b/README.md @@ -209,6 +209,37 @@ await relay.serviceConnections.listOutputs(bucket.id); await relay.serviceConnections.list(); ``` +## Outbound webhooks — send webhooks to your customers + +Register each customer as a consumer with the HTTPS endpoint they give you, then +publish events. Webhook Relay signs every delivery +([Standard Webhooks](https://www.standardwebhooks.com/)), retries failures durably +for up to 48 hours and keeps the delivery history. Outbound webhooks are in pilot: +the account needs the `outbound` feature. + +```ts +// Once per customer. +await relay.outbound.eventTypes.upsert("invoice.paid", { description: "An invoice was paid" }); +await relay.outbound.consumers.upsert("customer_42", { name: "Acme" }); +const endpoint = await relay.outbound.endpoints.create("customer_42", { + url: "https://customer.example/webhooks", + eventTypes: ["invoice.paid"], +}); +// endpoint.secret is the signing secret your customer verifies deliveries with. + +// Every time the event happens. +const message = await relay.outbound.messages.publish( + { consumer: "customer_42", eventType: "invoice.paid", payload: { invoice_id: "inv_123", amount: 4900 } }, + { idempotencyKey: "invoice-paid:inv_123" }, // retrying with the same key never publishes twice +); +``` + +Publishing is asynchronous: the result is the durable acceptance receipt. +`outbound.messages.get(id)` shows each endpoint's delivery and attempts; +`outbound.endpoints.retry`, `.recover` and `.replayMissing` re-send in the +background and return a recovery task (`outbound.recoveryTasks.get`). A runnable +version lives in [`examples/outbound.ts`](./examples/outbound.ts). + ## Receiving webhooks Three delivery modes, from most durable to lowest latency: diff --git a/examples/outbound.ts b/examples/outbound.ts new file mode 100644 index 0000000..8eb7e59 --- /dev/null +++ b/examples/outbound.ts @@ -0,0 +1,50 @@ +/** + * Send signed webhooks to your own customers with outbound webhooks. + * + * Run with: + * RELAY_API_KEY=sk-... CUSTOMER_WEBHOOK_URL=https://... npx tsx examples/outbound.ts + * + * test/outbound.test.ts runs these functions, and the Webhook Relay dashboard + * shows the marked region, so keep the two in step. + */ +// dashboard-snippet:start +import { WebhookRelay } from "@webhookrelay/sdk"; + +// Reads RELAY_API_KEY from the environment. Keep it server-side. +export const createClient = () => new WebhookRelay(); + +// Once per customer: register the HTTPS endpoint they give you. +export async function onboardCustomer(relay: WebhookRelay, customerURL: string) { + await relay.outbound.eventTypes.upsert("invoice.paid", { description: "An invoice was paid" }); + await relay.outbound.consumers.upsert("customer_42", { name: "Acme" }); + return relay.outbound.endpoints.create("customer_42", { + url: customerURL, + eventTypes: ["invoice.paid"], + }); +} + +// Every time the event happens. Retry with the same idempotency key. +export function publishInvoicePaid(relay: WebhookRelay) { + return relay.outbound.messages.publish( + { consumer: "customer_42", eventType: "invoice.paid", payload: { invoice_id: "inv_123", amount: 4900 } }, + { idempotencyKey: "invoice-paid:inv_123" }, + ); +} +// dashboard-snippet:end + +async function main() { + const customerURL = process.env.CUSTOMER_WEBHOOK_URL; + if (!customerURL) throw new Error("set CUSTOMER_WEBHOOK_URL"); + const relay = createClient(); + const endpoint = await onboardCustomer(relay, customerURL); + console.log("endpoint:", endpoint.id, "signing secret:", endpoint.secret); + const message = await publishInvoicePaid(relay); + console.log("message:", message.id, "->", message.endpoint_ids.length, "endpoint(s)"); +} + +if (import.meta.filename === process.argv[1]) { + main().catch((err) => { + console.error(err); + process.exit(1); + }); +} diff --git a/src/client.ts b/src/client.ts index 2d19fbe..2979fcc 100644 --- a/src/client.ts +++ b/src/client.ts @@ -6,6 +6,7 @@ import { OutputsResource } from "./resources/outputs.js"; import { ServiceConnectionsResource } from "./resources/serviceConnections.js"; import { FunctionsResource } from "./resources/functions.js"; import { WebhooksResource } from "./resources/webhooks.js"; +import { OutboundResource } from "./resources/outbound.js"; /** * The Webhook Relay API client. @@ -41,6 +42,8 @@ export class WebhookRelay { readonly functions: FunctionsResource; /** Read webhook history, poll, and subscribe over WebSocket. */ readonly webhooks: WebhooksResource; + /** Send signed webhooks to your own customers (pilot). */ + readonly outbound: OutboundResource; constructor(config: WebhookRelayConfig = {}) { const resolved = resolveConfig(config); @@ -51,6 +54,7 @@ export class WebhookRelay { this.serviceConnections = new ServiceConnectionsResource(this.http); this.functions = new FunctionsResource(this.http); this.webhooks = new WebhooksResource(this.http, resolved); + this.outbound = new OutboundResource(this.http); } /** diff --git a/src/generated/api.ts b/src/generated/api.ts index 9434bb0..623aa7f 100644 --- a/src/generated/api.ts +++ b/src/generated/api.ts @@ -36,6 +36,12 @@ export enum StructsTunnelMode { TunnelModeActive = 1, } +export enum StructsSuspiciousEventStatus { + SuspiciousEventStatusOpen = "open", + SuspiciousEventStatusConfirmed = "confirmed", + SuspiciousEventStatusDismissed = "dismissed", +} + export enum StructsSubscriptionTerm { SubscriptionTermMonthly = "monthly", SubscriptionTermYearly = "yearly", @@ -45,6 +51,12 @@ export enum StructsServiceType { ServiceGCP = "gcp", ServiceAWS = "aws", ServiceAzure = "azure", + ServiceSecret = "secret", + ServiceOpenAI = "openai", + ServiceGemini = "gemini", + ServiceAnthropic = "anthropic", + ServiceCustomLLM = "custom_llm", + ServiceWebhookRelayAI = "webhookrelay_ai", } export enum StructsServiceConnectionStatus { @@ -69,6 +81,7 @@ export enum StructsServiceConnectionInputType { ServiceConnectionInputTypeAWSS3 = "aws_s3", ServiceConnectionInputTypeAWSSQS = "aws_sqs", ServiceConnectionInputTypeAWSSNS = "aws_sns", + ServiceConnectionInputTypeEmail = "email", } export enum StructsServiceConnectionInputStatus { @@ -76,13 +89,24 @@ export enum StructsServiceConnectionInputStatus { ServiceConnectionInputStatusError = "error", } -export enum StructsRequestStatus { - RequestStatusPreparing = 0, - RequestStatusSent = 1, - RequestStatusFailed = 2, - RequestStatusStalled = 3, - RequestStatusReceived = 4, - RequestStatusRejected = 5, +export enum StructsRetryTaskType { + RetryTaskRecoverFailed = "recover_failed", + RetryTaskReplayMissing = "replay_missing", +} + +export enum StructsRetryTaskStatus { + RetryTaskStatusPending = "pending", + RetryTaskStatusRunning = "running", + RetryTaskStatusCompleted = "completed", + RetryTaskStatusFailed = "failed", +} + +export enum StructsOrgRole { + OrgRoleOwner = "owner", + OrgRoleAdmin = "admin", + OrgRoleBilling = "billing", + OrgRoleMember = "member", + OrgRoleViewer = "viewer", } export enum StructsObjectStorageFileFormat { @@ -91,9 +115,24 @@ export enum StructsObjectStorageFileFormat { ObjectStorageFileFormatHAR = "har", } +export enum StructsLogAttemptOutcome { + LogAttemptOutcomeUnspecified = "", + LogAttemptOutcomeSuccess = "success", + LogAttemptOutcomeRetryable = "retryable", + LogAttemptOutcomePermanent = "permanent", + LogAttemptOutcomeTimeout = "timeout", +} + export enum StructsIntegrationPlugin { IntegrationPluginWebhook = "webhook", IntegrationPluginSlack = "slack", + IntegrationPluginDiscord = "discord", + IntegrationPluginTelegram = "telegram", + IntegrationPluginEmail = "email", + IntegrationPluginTeams = "teams", + IntegrationPluginPushover = "pushover", + IntegrationPluginGeneric = "generic", + IntegrationPluginDefaultEmail = "default_email", } export enum StructsExecutionStatus { @@ -108,6 +147,18 @@ export enum StructsAuthType { AuthTypeToken = 2, } +export enum StructsAlertType { + AlertTypeDeliveryFailures = "delivery_failures", + AlertTypeTLSExpiration = "tls_expiration", + AlertTypeHostDown = "host_down", + AlertTypeHealthEndpoint = "health_endpoint", +} + +export enum StructsAlertPolicyMode { + AlertPolicyModeAnyFailure = "any_failure", + AlertPolicyModeErrorRate = "error_rate", +} + export enum StructsAccountAuthType { AccountAuthTypeRegular = "regular", AccountAuthTypeGithub = "github", @@ -121,1157 +172,1508 @@ export enum StructsAPIAccess { APIAccessEnabled = 2, } -export interface ApiResponse { +export interface AgentAdminConversation { + account_id?: string; + /** + * Approvals is how many destructive calls asked the user; Denied counts + * those declined, expired or cancelled (anything that did not run). + */ + approvals?: number; + approvals_approved?: number; + approvals_denied?: number; + /** + * ApprovedScopes are the harness scopes the user widened this + * conversation by ("routing:drop"), space separated. Approvals outlive + * a turn: each turn is its own session, so the widening is replayed on + * top of the role's grant when the next turn starts. + */ + approved_scopes?: string; + cache_hit_rate?: number; + cache_miss_cost_usd?: number; + cache_read_tokens?: number; + cache_write_tokens?: number; + context_id?: string; + /** + * ContextKind / ContextID name the page the conversation was opened + * from: "function" + a function ID for the function details page. + */ + context_kind?: string; + created_at?: string; + /** + * CreatedBy is the acting member in an organization context, the + * account itself otherwise. + */ + created_by?: string; + email?: string; + /** Grant is the harness grant label the conversation runs under. */ + grant?: string; + grant_label?: string; id?: string; - status?: string; + input_tokens?: number; + iterations?: number; + last_message_at?: string; + last_stop_cause?: string; + model_calls?: number; + model_failures?: number; + model_latency_ms?: number; + output_tokens?: number; + /** + * Page is a human label for where the chat was opened from ("Buckets", + * "Bucket orders", "Access Tokens"), so the agent knows what the user is + * looking at even when there is no resource to bind to. + */ + page?: string; + provider?: string; + session_turns?: number; + thumbs_down?: number; + thumbs_up?: number; + title?: string; + tool_calls?: number; + turns?: number; + updated_at?: string; + username?: string; } -export interface ApiServerConfig { - turnstile_disabled?: boolean; - version?: string; +export interface AgentAdminDetail { + approvals?: StructsAgentApproval[]; + conversation?: AgentAdminConversation; + feedback?: StructsAgentFeedback[]; + inferences?: SessionstoreInferenceRecord[]; + messages?: AgentMessage[]; + prompts?: SessionstorePromptRecord[]; + tool_calls?: SessionstoreToolCallRecord[]; + truncated?: AgentAdminEvidenceTruncated; } -export interface ApiAccessTokenCreateResponse { - key?: string; - secret?: string; +export interface AgentAdminEvidenceTruncated { + inferences?: boolean; + prompts?: boolean; + tool_calls?: boolean; } -export interface ApiActionLogRequest { - action?: string; - /** output ID, if not specified defaults to original output */ - output?: string; - /** skip/force */ - process_policy?: string; +export interface AgentAdminPage { + items?: AgentAdminConversation[]; + limit?: number; + offset?: number; + total?: number; } -export interface ApiCreateAccessTokenRequest { - api_access?: string; - description?: string; - scopes?: ApiTokenScopes; +export interface AgentAdminStats { + accounts?: number; + approvals_approved?: number; + /** Approvals: destructive calls that paused for the user, by outcome. */ + approvals_asked?: number; + approvals_denied?: number; + approvals_expired?: number; + approvals_pending?: number; + avg_model_latency_ms?: number; + cache_hit_rate?: number; + cache_miss_cost_usd?: number; + cache_read_tokens?: number; + conversations?: number; + daily?: AgentDailyStat[]; + input_tokens?: number; + model_calls?: number; + model_failures?: number; + output_tokens?: number; + pages?: AgentNamedCount[]; + stop_causes?: AgentNamedCount[]; + thumbs_down?: number; + thumbs_up?: number; + tool_calls?: number; + tool_failures?: number; + tool_refusals?: number; + top_tools?: AgentToolStat[]; + turns?: number; } -export interface ApiCreateManagedCertRequest { - domain?: string; +export interface AgentAttachmentView { + bytes?: number; + media_type?: string; name?: string; - options?: Record; - provider?: string; } -export interface ApiEventResponse { - has_more?: boolean; - logs?: StructsLog[]; - next_cursor?: string; +export interface AgentDailyStat { + conversations?: number; + day?: string; + tool_calls?: number; + turns?: number; } -export interface ApiListPlanOptionalItemsResponse { - plans?: ApiPlanOptionalItems[]; +export interface AgentMessage { + attachments?: AgentAttachmentView[]; + role?: string; + text?: string; + tool_calls?: AgentToolCallView[]; + tool_results?: AgentToolResultView[]; } -export interface ApiLoginResponse { - mfa_required?: boolean; - mfa_token?: string; - token?: string; +export interface AgentNamedCount { + count?: number; + name?: string; } -export interface ApiLogsHistogramBucketJSON { - counts?: Record; - latency_ms_avg?: number; - max_retries?: number; - minute?: number; +export interface AgentPage { + focus_id?: string; /** - * Retry-pressure overlay. With durable delivery on, latest-status - * alone drifts to "all sent"; these counters keep outages visible - * in the chart. See design §6.10.9. + * FocusKind/FocusID name the resource the page shows: the output, input + * or webhook log of the bucket the user has open, an incident, an alert + * policy, or an outbound consumer, endpoint or message. */ - retried?: number; - retry_count?: number; - total?: number; + focus_kind?: string; + id?: string; + kind?: string; + label?: string; } -export interface ApiLogsHistogramResponse { - buckets?: ApiLogsHistogramBucketJSON[]; - /** - * Resolution echoes back the bucket size returned by the selected - * histogram tier. - */ - resolution?: string; +export interface AgentQuota { + limit?: number; + /** ResetsAt is when the next month's allowance starts. */ + resets_at?: string; + /** Unlimited plans have no cap; Used still counts. */ + unlimited?: boolean; + /** Used and Limit are model tokens (input + output) this calendar month. */ + used?: number; } -export interface ApiLogsResponse { - data?: StructsLog[]; - limit?: number; - /** - * NextCursor is the opaque token a caller passes back as - * ?cursor=... to get the next page. Emitted only when the - * caller used cursor mode (or asked for it via the flag) AND - * there is at least one more row past the current page. Empty - * otherwise — clients should detect end-of-stream by an empty - * NextCursor or a short final page. - */ - next_cursor?: string; - offset?: number; - total?: number; - /** - * Truncated is true when the storage layer capped the candidate - * segment set (post-manifest-prune) to its scan budget. The - * returned Data still contains the newest matching rows (sort - * order is newest-first), but older entries within the requested - * [from, to] window may have been omitted. The UI should render - * a "showing latest results — narrow the time range to see more" - * banner so users on hot/bloated accounts don't think their - * data is missing entirely. See pkg/turbostore/querylimit and - * design.md §15.17. Omitted from the JSON when false (the - * happy path). - */ - truncated?: boolean; +export interface AgentToolCallView { + id?: string; + input?: object; + name?: string; } -export interface ApiMfaConfirmRequest { - token?: string; +export interface AgentToolInfo { + approvable?: boolean; + description?: string; + name?: string; + needs?: string; + permitted?: boolean; } -export interface ApiMfaSetupResponse { - enabled?: boolean; - otpauth_url?: string; - qr_code_data_url?: string; - secret?: string; +export interface AgentToolResultView { + call_id?: string; + content?: string; + is_error?: boolean; } -export interface ApiMfaStatusResponse { - enabled?: boolean; - token?: string; +export interface AgentToolStat { + avg_ms?: number; + calls?: number; + failed?: number; + refused?: number; + tool?: string; } -export interface ApiMfaVerifyRequest { - mfa_token?: string; - token?: string; +export interface ApiAdminAgentLimitValues { + max_iterations?: number; + max_output_tokens?: number; + max_tokens_per_turn?: number; + plan_tokens?: Record; } -export interface ApiPlanChangeRequest { - optional_items?: ApiPlanChangeRequestOptionalItem[]; - /** Price ID */ - plan_id?: string; +export interface ApiAdminAgentLimits { + defaults?: ApiAdminAgentLimitValues; + effective?: ApiAdminAgentLimitValues; + overrides?: StructsAgentLimitOverrides; + updated_at?: string; + updated_by?: string; } -export interface ApiPlanChangeRequestOptionalItem { - /** For example "Extra 1000 webhooks" (for basic) */ - description?: string; - /** For now contains "webhooks" count, later will add team seats */ - metadata?: Record; - price_id?: string; - quantity?: number; +export interface ApiAdminAgentLimitsUpdateRequest { + overrides?: StructsAgentLimitOverrides; } -export interface ApiPlanChangeResponse { - /** usually true, this is when frontend should call stripe lib */ - checkout_required?: boolean; - publishable_key?: string; - session_id?: string; +export interface ApiAdminTrafficStatsResponse { + collectedAt?: string; + snapshots?: TrafficstatsSnapshot[]; } -export interface ApiPlanOptionalItems { - optional_items?: StructsSubscriptionExtras[]; - plan_id?: string; +export interface ApiAdminUsageAlertsResponse { + alerts?: StructsAdminUsageAlert[]; + limit?: number; + offset?: number; + total?: number; } -export interface ApiSetFunctionConfigRequest { - key?: string; - value?: string; +export interface ApiAdminUsageBucket { + account_id?: string; + created_at?: number; + description?: string; + id?: string; + inputs?: ApiAdminUsageInput[]; + name?: string; + outputs?: ApiAdminUsageOutput[]; + suspended?: boolean; } -export interface ApiTokenScopes { - buckets?: string[]; - tunnels?: string[]; +export interface ApiAdminUsageBucketsResponse { + buckets?: ApiAdminUsageBucket[]; + limit?: number; + offset?: number; + total?: number; } -export interface ApiUpdateAccessTokenRequest { - api_access?: string; +export interface ApiAdminUsageInput { description?: string; - scopes?: ApiTokenScopes; + function_id?: string; + id?: string; + name?: string; } -export interface RulesArgument { - base64decode?: boolean; - envname?: string; +export interface ApiAdminUsageOutput { + account_id?: string; + bucket_id?: string; + /** + * BucketName/AccountID are resolved in the flat outputs listing; the + * buckets listing leaves them empty (the parent row carries them). + */ + bucket_name?: string; + created_at?: number; + destination?: string; + /** + * DestinationProvider is the classified destination service (jenkins, + * slack, localhost, ...) or "unknown". + */ + destination_provider?: string; + disabled?: boolean; + function_id?: string; + id?: string; + internal?: boolean; name?: string; - source?: string; + response_function_id?: string; } -export interface RulesMatchRule { - "ip-range"?: string; - parameter?: RulesArgument; - regex?: string; - secret?: string; - substring?: string; - type?: string; - value?: string; +export interface ApiAdminUsageOutputsResponse { + limit?: number; + offset?: number; + outputs?: ApiAdminUsageOutput[]; + total?: number; } -export interface RulesNotRule { - and?: RulesRules[]; - match?: RulesMatchRule; - or?: RulesRules[]; +export interface ApiAdminUsageSummaryResponse { + collectedAt?: string; + /** DestinationProviders is classified-destination -> output count. */ + destination_providers?: Record; + disabled_outputs?: number; + internal_outputs?: number; + /** + * OutputsWithFunctions counts outputs with a delivery or response + * function attached. + */ + outputs_with_functions?: number; + total_outputs?: number; } -export interface RulesRules { - and?: RulesRules[]; - match?: RulesMatchRule; - not?: RulesNotRule; - or?: RulesRules[]; +export interface ApiAdminUsageWebhookMonth { + /** @example "2026-08" */ + month?: string; + /** @example 125000 */ + webhooks?: number; } -export interface StructsAWSS3Input { - bucket_name?: string; - file_format?: StructsObjectStorageFileFormat; - prefix?: string; - region?: string; +export interface ApiAdminUsageWebhooksResponse { + account_id?: string; + /** @example "2025-09-01" */ + from?: string; + months?: ApiAdminUsageWebhookMonth[]; + /** @example "2026-08-30" */ + to?: string; + total_webhooks?: number; } -export interface StructsAWSS3Output { - bucket_name?: string; - file_format?: StructsObjectStorageFileFormat; - prefix?: string; - region?: string; +export interface ApiAgentApprovalRequest { + /** CallID is the paused tool call, from the approval_requested event. */ + call_id?: string; + /** Remember also allows the scope for the rest of the conversation (approve). */ + remember?: boolean; + /** Scope is the access the call needs, e.g. "routing:drop" (approve). */ + scope?: string; + /** Text is the reason the agent should hear (deny, optional). */ + text?: string; } -export interface StructsAWSSNSInput { - region?: string; - subscription_arn?: string; - topic_arn?: string; +export interface ApiAgentControlRequest { + /** Scope is the harness scope to approve, e.g. "routing:drop" (widen). */ + scope?: string; + /** Text is the steering instruction (steer). */ + text?: string; } -export interface StructsAWSSNSOutput { - region?: string; - topic_arn?: string; +export interface ApiAgentConversationDetail { + active?: boolean; + /** + * Approvals are the destructive calls the agent asked about in this + * conversation and what the user answered, so a reopened chat still + * shows who allowed what. + */ + approvals?: StructsAgentApproval[]; + conversation?: StructsAgentConversation; + feedback?: StructsAgentFeedback[]; + messages?: AgentMessage[]; } -export interface StructsAWSSQSInput { - queue_url?: string; - region?: string; +export interface ApiAgentConversationRequest { + context_id?: string; + context_kind?: string; + /** Page labels where the chat was opened ("Buckets", "Access Tokens"). */ + page?: string; + title?: string; } -export interface StructsAWSSQSOutput { - queue_url?: string; - region?: string; +export interface ApiAgentFeedbackRequest { + comment?: string; + excerpt?: string; + message_index?: number; + /** up | down */ + rating?: string; } -export interface StructsAWSServiceConnection { - access_key_id?: string; - secret_access_key?: string; +export interface ApiAgentMessageRequest { + id?: string; + /** + * Page is where the user is when sending (kind, id, label), so a chat + * that follows them across the dashboard still knows what they see. + */ + page?: AgentPage; + text?: string; } -export interface StructsAccessToken { - active?: boolean; - api_access?: StructsAPIAccess; - created_at?: string; - deleted_at?: string; - description?: string; - id?: string; - last_login?: string; - scopes?: StructsMetadata; - updated_at?: string; +export interface ApiAgentQuotaExceeded { + code?: string; + error?: string; + quota?: AgentQuota; } -export interface StructsAccount { - access_tokens?: StructsAccessToken[]; +export interface ApiAgentStatus { + enabled?: boolean; + grant?: string; + model?: string; + playbooks?: string[]; + /** Quota is the plan's shared account-agent and managed-Function AI token allowance. */ + quota?: AgentQuota; + scopes?: string[]; +} + +export interface ApiAgentToolsResponse { + tools?: AgentToolInfo[]; +} + +export interface ApiEnterprisePlanMetadataField { + aliases?: string[]; + description?: string; + group?: string; + key?: string; + label?: string; + minimum?: number; + type?: "integer" | "number" | "boolean"; + unit?: string; +} + +export interface ApiEnterprisePlanMetadataSchemaResponse { + fields?: ApiEnterprisePlanMetadataField[]; +} + +export interface ApiResponse { + id?: string; + status?: string; +} + +export interface ApiServerConfig { + /** + * EmailInboundAddressTemplate is the canonical inbound-email address format, + * e.g. "{token}@in.webhookrelay-mail.com". The backend is the single source + * of truth for the address shape so the UI and API render addresses + * consistently instead of hardcoding the "{token}@" join — substitute + * an email input's id for "{token}". Empty when inbound email is not + * configured. + */ + email_inbound_address_template?: string; + /** + * EmailInboundDomain is the inbound-email domain ({local-part}@) + * addresses are built on for this environment ("in.webhookrelay-mail.com" in + * production, "dev.webhookrelay-mail.com" in development). Empty when inbound + * email is not configured, which the UI uses to hide the email-input feature. + */ + email_inbound_domain?: string; + /** + * EmailInboundEnabled reports whether the inbound email endpoint is wired up + * (a shared secret is provisioned). + */ + email_inbound_enabled?: boolean; + turnstile_disabled?: boolean; + version?: string; +} + +export interface ApiAccessTokenCreateResponse { + key?: string; + secret?: string; +} + +export interface ApiAccountAuditResponse { + data?: StructsAuditLog[]; + total?: number; +} + +export interface ApiActionLogRequest { + action?: string; + /** output ID, if not specified defaults to original output */ + output?: string; + /** skip/force */ + process_policy?: string; +} + +export interface ApiAdminAccountIdentityUpdateRequest { + auth_type?: StructsAccountAuthType; + email?: string; +} + +export interface ApiAdminAccountSearchResult { active?: boolean; - /** authentication type (regular/github/google) */ auth_type?: StructsAccountAuthType; - avatar_url?: string; - buckets?: StructsBucket[]; company_name?: string; - created_at?: string; - current_period_end?: number; - /** subscription period start and end, updated by stripe */ - current_period_start?: number; - deleted_at?: string; - domains?: StructsDomain[]; + created_at?: number; email?: string; email_verified?: boolean; - failed_login_attempts?: number; first_name?: string; id?: string; - last_failed_login?: string; - last_login_at?: string; + last_login_at?: number; last_name?: string; - mfa_enabled?: boolean; - /** - * desired plan ID, used when registering new account - * to create new subscription in Stripe after - * email is verified - */ + organization?: boolean; plan_id?: string; - plan_meta?: StructsMetadata; - role?: string; - sub_accounts?: StructsSubAccount[]; - /** Unix ts */ + subscription_meta?: StructsMetadata; + username?: string; +} + +export interface ApiAdminAccountStatus { + account_id?: string; + bucket_count?: number; + current_period_end?: number; + current_period_start?: number; + effective_metadata?: StructsPlanMeta; + plan_id?: string; + plan_metadata?: StructsMetadata; subscription_created?: number; subscription_extras?: StructsSubscriptionExtras[]; - subscription_meta?: StructsMetadata; - /** Subscription status and fields */ + subscription_metadata?: StructsMetadata; subscription_status?: string; - /** - * SuspendProtection prevents account's buckets from being suspended for - * overuse - */ suspend_protection?: boolean; - tunnels?: StructsTunnel[]; - updated_at?: string; - usage_alerts?: boolean; - usage_alerts_email?: string; - /** Why have they registered? */ - use_case?: string; - use_case_completed?: boolean; - username?: string; - webhookCounts?: StructsWebhooksCount[]; + suspended_bucket_count?: number; } -export interface StructsAccountAPIKey { - api_key?: string; +export interface ApiAdminBucketSuspensionResponse { + affected?: number; + suspended?: boolean; + total?: number; } -export interface StructsAdminConnectedAccount { - account_id?: string; - email?: string; - plan?: string; - plan_id?: string; - tunnel_clients?: StructsConnectedTunnelClientInfo[]; - username?: string; - webhook_clients?: StructsConnectedWebhookClientInfo[]; +export interface ApiAdminBucketSuspensionUpdateRequest { + suspended?: boolean; } -export interface StructsAdminConnectedClientsResponse { - accounts?: StructsAdminConnectedAccount[]; - total_count?: number; +export interface ApiAdminOrganizationDetails { + members?: StructsOrganizationMemberDetails[]; + organization?: ApiAdminOrganizationSummary; + sub_accounts?: StructsSubAccount[]; } -export interface StructsAzureServiceConnection { - client_id?: string; - client_secret?: string; - tenant_id?: string; +export interface ApiAdminOrganizationMemberCreateRequest { + account_id?: string; + email?: string; + role?: string; + username?: string; } -export interface StructsBillingDetails { - city?: string; - country?: string; - customer_id?: string; - email?: string; - line1?: string; - line2?: string; - /** Customer full name or business name */ - name?: string; - postal_code?: string; - state?: string; - /** Value of the tax ID. */ - tax_id?: string; - /** Type of the tax ID, one of `ae_trn`, `au_abn`, `au_arn`, `bg_uic`, `br_cnpj`, `br_cpf`, `ca_bn`, `ca_gst_hst`, `ca_pst_bc`, `ca_pst_mb`, `ca_pst_sk`, `ca_qst`, `ch_vat`, `cl_tin`, `es_cif`, `eu_oss_vat`, `eu_vat`, `gb_vat`, `ge_vat`, `hk_br`, `hu_tin`, `id_npwp`, `il_vat`, `in_gst`, `is_vat`, `jp_cn`, `jp_rn`, `kr_brn`, `li_uid`, `mx_rfc`, `my_frp`, `my_itn`, `my_sst`, `no_vat`, `nz_gst`, `ru_inn`, `ru_kpp`, `sa_vat`, `sg_gst`, `sg_uen`, `si_tin`, `th_vat`, `tw_vat`, `ua_vat`, `us_ein`, or `za_vat` */ - tax_id_type?: string; +export interface ApiAdminOrganizationMemberUpdateRequest { + role?: string; } -export interface StructsBucket { - account_id?: string; - auth?: StructsBucketAuth; +export interface ApiAdminOrganizationSummary { + active?: boolean; created_at?: number; - cron_id?: string; - description?: string; - /** If true, doesn't save request body, query or headers */ - ephemeral?: boolean; + email?: string; id?: string; - inputs?: StructsInput[]; - integration_configurations?: StructsIntegrationConfiguration[]; - /** - * LargeWebhooks - if set, we allow larger than 3MB webhooks - * to be sent to the bucket. This is useful for large file uploads - */ - large_webhooks?: boolean; - name?: string; - outputs?: StructsOutput[]; - service_connection_inputs?: StructsServiceConnectionInput[]; - service_connection_outputs?: StructsServiceConnectionOutput[]; - /** StaticIP - if set, the bucket will use a static IP (routing through forwarding proxy) */ - static_ip?: boolean; - /** enable/disable websocket streaming for the bucket */ - stream?: boolean; - /** - * Set to TRUE by the curator if accounts goes over the - * webhook limit - */ - suspended?: boolean; - updated_at?: number; + member_count?: number; + organization_description?: string; + organization_name?: string; + plan_id?: string; + sub_account_count?: number; + username?: string; } -export interface StructsBucketAuth { - created_at?: number; +export interface ApiAdminOrganizationUpdateRequest { + organization_description?: string; + organization_name?: string; +} + +export interface ApiAdminRecentAccount { + active?: boolean; + auth_type?: StructsAccountAuthType; + company_name?: string; + created_at?: string; + email?: string; + email_verified?: boolean; + first_name?: string; id?: string; - password?: string; - token?: string; - type?: StructsAuthType; - updated_at?: number; + last_name?: string; + organization?: boolean; + plan_id?: string; + use_case?: string; username?: string; } -export interface StructsCombinedUsage { - plan_meta?: StructsPlanMeta; - usage?: StructsUsage; +export interface ApiAdminRecentAccountsResponse { + accounts?: ApiAdminRecentAccount[]; + created_after?: string; + limit?: number; + offset?: number; + total?: number; } -export interface StructsConnectedClient { - tunnel_clients?: StructsConnectedTunnelClient[]; - webhook_clients?: StructsConnectedWebhookClient[]; +export interface ApiAdminSubAccountCreateRequest { + auth_type?: StructsAccountAuthType; + email?: string; + username?: string; } -export interface StructsConnectedTunnelClient { - access_token_key?: string; - client_ip?: string; - client_version?: string; - subscribed_at?: number; - tunnels?: string[]; +export interface ApiAdminSuspendProtectionUpdateRequest { + enabled?: boolean; } -export interface StructsConnectedTunnelClientInfo { - access_token_key?: string; - client_ip?: string; - client_version?: string; - subscribed_at?: number; - tunnel_names?: string[]; - tunnels?: string[]; +export interface ApiAuditLogsResponse { + data?: StructsAuditLog[]; + limit?: number; + offset?: number; + total?: number; } -export interface StructsConnectedWebhookClient { - access_token_key?: string; - buckets?: string[]; - client_ip?: string; - client_type?: string; - client_version?: string; - destination?: string; - subscribed_at?: number; +export interface ApiBindFunctionConnectionRequest { + service_connection_id?: string; } -export interface StructsConnectedWebhookClientInfo { - access_token_key?: string; - bucket_names?: string[]; - buckets?: string[]; - client_ip?: string; - client_type?: string; - client_version?: string; - destination?: string; - subscribed_at?: number; +export interface ApiCreateAccessTokenRequest { + api_access?: string; + description?: string; + name?: string; + permissions?: StructsTokenPermissions; + scopes?: ApiTokenScopes; } -export interface StructsCreateFunctionRequest { - driver?: string; +export interface ApiCreateManagedCertRequest { + domain?: string; name?: string; - payload?: string; + options?: Record; + provider?: string; } -export interface StructsCreateTunnelRequest { - /** - * Addr specifies TCP address server would listen on, it's required - * for TCP tunnels. - */ - addr?: string; - agent_id?: string; - auth?: StructsTunnelAuth; - crypto?: string; - description?: string; - destination?: string; - features?: StructsFeatures; - group?: string; - host?: string; - ingress_rules?: StructsIngressRules; - name?: string; - protocol?: string; - region?: string; - subdomain?: string; +export interface ApiCreatorIdentity { + avatar_url?: string; + id?: string; + kind?: string; + username?: string; } -export interface StructsCron { - account_id?: string; - bucket?: StructsBucket; +export interface ApiDeletedResponse { + deleted?: boolean; +} + +export interface ApiEndpointWithSecret { + auto_disable?: boolean; + consecutive_failures?: number; + consumer?: string; created_at?: string; - /** URL to send the webhook to */ - destination?: string; - enabled?: boolean; - ends_at?: string; - /** Function ID attached to the output */ + description?: string; + event_types?: string[]; + failing_since?: string; function_id?: string; - headers?: StructsHeaders; + headers?: Record; id?: string; - /** - * Payload and headers injected into the Bucket. Outputs - * are still used to send the webhook - */ - method?: string; - name?: string; - /** Populated by the handler for UI to display */ - next_run?: string; - payload?: string; - recurring?: boolean; - schedule?: string; - /** Dates from which the cron job starts and ends */ - starts_at?: string; - timezone?: string; + previous_secret_expires_at?: string; + rate?: number; + secret?: string; + state?: "active" | "failing" | "paused" | "disabled"; + /** seconds; zero uses OutboundDefaultTimeout */ + timeout?: number; updated_at?: string; + url?: string; } -export type StructsDeleteFunctionResponse = object; +export interface ApiEventResponse { + has_more?: boolean; + logs?: StructsLog[]; +} -export type StructsDeleteVariableResponse = object; +export interface ApiListPlanOptionalItemsResponse { + plans?: ApiPlanOptionalItems[]; +} -export interface StructsDiscordOutput { - webhook_url?: string; +export interface ApiLoginResponse { + mfa_required?: boolean; + mfa_token?: string; + token?: string; } -export interface StructsDomain { - created_at?: number; +export interface ApiLogsHistogramBucketJSON { + counts?: Record; + latency_ms_avg?: number; + max_retries?: number; + minute?: number; /** - * Domain can be any 3rd party domain such as - * user.example.com + * Retry-pressure overlay. With durable delivery on, latest-status + * alone drifts to "all sent"; these counters keep outages visible + * in the chart. See design §6.10.9. */ - domain?: string; - id?: string; - updated_at?: number; + retried?: number; + retry_count?: number; + total?: number; } -export interface StructsDurabilityConfig { - /** CustomDelays is consulted only when Schedule == "custom". */ - custom_delays?: TimeDuration[]; +export interface ApiLogsHistogramResponse { + buckets?: ApiLogsHistogramBucketJSON[]; /** - * Deadline caps total retry duration measured from the webhook's - * received_at timestamp. Zero falls through to a schedule-derived - * default (~30 d for "long", ~16 h for "medium", ~25 min for - * "seconds"). + * Resolution echoes back the bucket size returned by the selected + * histogram tier. */ - deadline?: TimeDuration; - /** Enabled toggles the whole feature for this output. */ - enabled?: boolean; + resolution?: string; +} + +export interface ApiLogsResponse { + data?: StructsLog[]; + limit?: number; /** - * HandoffAfter is the attempt-age threshold past which a failing - * delivery is moved from the in-pubsub retry path to the durable - * pending index. Zero falls through to 15 minutes — short enough - * that long retries don't bloat the pubsub backlog, long enough - * that transient blips don't pay an extra object-store PUT. + * NextCursor is the opaque token a caller passes back as + * ?cursor=... to get the next page. Emitted only when the + * caller used cursor mode (or asked for it via the flag) AND + * there is at least one more row past the current page. Empty + * otherwise — clients should detect end-of-stream by an empty + * NextCursor or a short final page. */ - handoff_after?: TimeDuration; + next_cursor?: string; + offset?: number; + total?: number; /** - * Schedule names a backoff preset ("seconds", "medium", "long", - * "custom"). Empty falls through to "long" when Enabled, "seconds" - * otherwise. Custom backoffs use CustomDelays. + * Truncated is true when the storage layer capped the candidate + * segment set (post-manifest-prune) to its scan budget. The + * returned Data still contains the newest matching rows (sort + * order is newest-first), but older entries within the requested + * [from, to] window may have been omitted. The UI should render + * a "showing latest results — narrow the time range to see more" + * banner so users on hot/bloated accounts don't think their + * data is missing entirely. See pkg/turbostore/querylimit and + * design.md §15.17. Omitted from the JSON when false (the + * happy path). */ - schedule?: string; + truncated?: boolean; } -export interface StructsEndpoint { - address?: string; +export interface ApiMfaConfirmRequest { + token?: string; } -export interface StructsExecuteLog { - account_id?: string; - configuration_id?: string; - created?: number; - duration?: number; - execute_request?: StructsExecuteRequest; - execute_response?: StructsExecuteResponse; - function_id?: string; - id?: string; - status?: StructsExecutionStatus; - updated?: number; +export interface ApiMfaSetupResponse { + enabled?: boolean; + otpauth_url?: string; + qr_code_data_url?: string; + secret?: string; } -export interface StructsExecuteLogResponse { - execute_logs?: StructsExecuteLog[]; - limit?: number; - offset?: number; - total?: number; +export interface ApiMfaStatusResponse { + enabled?: boolean; + token?: string; } -export interface StructsExecuteRequest { - account_id?: string; - configuration_id?: string; - function_id?: string; - request?: StructsRequest; - request_id?: string; - response_body_path?: string; +export interface ApiMfaVerifyRequest { + mfa_token?: string; + token?: string; } -export interface StructsExecuteResponse { - error?: string; - function_id?: string; - request?: StructsRequest; - request_id?: string; - request_modified?: boolean; - response?: StructsResponse; - response_modified?: boolean; - stop_forwarding?: boolean; +export interface ApiOrgInviteCreateRequest { + email?: string; + role?: string; } -export interface StructsFeatures { - rewrite_host_header?: string; - /** validate TLS certificate */ - skip_insecure_verify?: boolean; +export interface ApiOrgMemberUpdateRequest { + role?: string; } -export interface StructsFunction { - account_id?: string; - compression?: string; - created?: number; - driver?: string; - id?: string; - metadata?: Record; +export interface ApiOrgSamlSSORequest { + allow_jit?: boolean; + allowed_domains?: string[]; + email_attribute_name?: string; + entity_id?: string; + force_authn?: boolean; name?: string; - payload?: string; - payload_size?: number; - updated?: number; + name_id_format?: string; + saml_metadata_url?: string; + signature_method?: string; } -export interface StructsGCPGCSInput { - bucket_name?: string; - file_format?: StructsObjectStorageFileFormat; - notification_id?: string; - prefix?: string; +export interface ApiOutboundErrorResponse { + error?: string; } -export interface StructsGCPGCSOutput { - bucket_name?: string; - file_format?: StructsObjectStorageFileFormat; - prefix?: string; +export interface ApiOutboundMessageDetail { + consumer?: string; + created_at?: string; + deliveries?: StructsLog[]; + endpoint_ids?: string[]; + enqueued_at?: string; + event_id?: string; + event_type?: string; + id?: string; + payload?: object; } -export interface StructsGCPPubSubInput { - subscription_name?: string; +export interface ApiOutboundRecoveryBody { + /** MessageID is the message to re-send; required by retry only. */ + message_id?: string; + /** Since starts the recovery window; defaults to 24 hours ago. */ + since?: string; } -export interface StructsGCPPubSubOutput { - topic_name?: string; +export interface ApiPlanChangeRequest { + optional_items?: ApiPlanChangeRequestOptionalItem[]; + /** Price ID */ + plan_id: string; } -export interface StructsGCPServiceConnection { - project_id?: string; - service_account_email?: string; - service_account_key?: string; +export interface ApiPlanChangeRequestOptionalItem { + /** For example "Extra 1000 webhooks" (for basic) */ + description?: string; + /** For now contains "webhooks" count, later will add team seats */ + metadata?: Record; + price_id: string; + /** + * Quantity must be between 1 and 20. The sum across optional_items must not exceed 20. + * @min 1 + * @max 20 + */ + quantity: number; } -export interface StructsGenerateFunctionRequest { - /** Additional information about the function */ - additional_info?: string; - input_payload?: string; - /** Desired output payload */ - output_payload?: string; +export interface ApiPlanChangeResponse { + /** usually true, this is when frontend should call stripe lib */ + checkout_required?: boolean; + publishable_key?: string; + session_id?: string; } -export interface StructsGenerateFunctionResponse { - /** Function code */ - code?: string; - /** Validation error message */ - validation_err?: string; - /** Indicates if the function is valid */ - validation_ok?: boolean; +export interface ApiPlanOptionalItems { + optional_items?: StructsSubscriptionExtras[]; + plan_id?: string; } -export interface StructsHeader { - values?: string[]; +export interface ApiRetryBulkRequest { + bucket?: string; + /** optional: narrow to a single output */ + output?: string; + /** RFC3339; required (bounds the scan) */ + since?: string; + /** RFC3339; optional, defaults to now */ + until?: string; } -export type StructsHeaders = Record; +export interface ApiSecretResponse { + secret?: string; +} -export interface StructsIngressRule { - /** Endpoints */ - endpoints?: StructsEndpoint[]; - /** - * Name is an option identifier for the ingress rule, it usually is a service name - * if used with webrelay-ingress - */ - name?: string; - /** - * Path is an extended POSIX regex as defined by IEEE Std 1003.1, - * (i.e this follows the egrep/unix syntax, not the perl syntax) - * matched against the path of an incoming request. Currently it can - * contain characters disallowed from the conventional "path" - * part of a URL as defined by RFC 3986. Paths must begin with - * a '/'. If unspecified, the path defaults to a catch all sending - * traffic to the backend. - * +optional - */ - path?: string; +export interface ApiSetFunctionConfigRequest { + key?: string; + value?: string; } -export interface StructsIngressRules { - rules?: StructsIngressRule[]; +export interface ApiSuspiciousDetectionSettingsRequest { + config?: StructsSuspiciousDetectionConfig; + expected_version?: string; } -export interface StructsInput { - body?: number[]; - /** BucketID is a foreign key */ - bucket_id?: string; - created_at?: number; - created_by?: string; - /** - * Input's domain name, can be set to work with the CNAMEs - * so WHR will fetch a cert from LE - * (make sure you create a CNAME DNS record for your domain to stats.uptimerobot.com. - * And, it can take up to 30 mins for the custom domain to be activated.) - */ - custom_domain?: string; - description?: string; - function_id?: string; - /** response details */ - headers?: StructsHeaders; - id?: string; - /** - * LegacyTLS widens the accepted handshake to TLS 1.0/1.1 *and* the - * older RSA/CBC cipher set. The two used to be split into separate - * fields but the policy resolver applies them as one logical toggle, - * and the dashboard surfaces them as one switch — keep the on-disk - * shape matching that single concept. - */ - legacy_tls?: boolean; - name?: string; - /** PathPrefix only works when CustomDomain is set */ - path_prefix?: string; - /** - * either output ID or "anyOutput" to indicate that the first response - * from any output is good enough. Empty string - */ - response_from_output?: string; - status_code?: number; - /** - * StripPathPrefix indicates whether full path should be included when - * forwarding the webhook. If the path prefix is /abc and the webhook - * arrives at /abc/foo, then by default the full path will be /abc/foo - */ - strip_path_prefix?: boolean; - /** - * TLSVersion sets the minimum accepted TLS version for this input's HTTPS endpoint. It is a floor, not a pin: handshakes negotiate this version or any higher one the backend allows (for example 1.1 still accepts 1.2 and 1.3). - * Empty value means default hardened policy. - */ - tls_version?: string; - updated_at?: number; +export interface ApiSuspiciousDetectionSettingsResponse { + config?: StructsSuspiciousDetectionConfig; + updated_at?: string; + updated_by?: string; + version?: string; } -export interface StructsIntegrationConfiguration { - buckets?: StructsBucket[]; - /** - * notification plugin configuration, free form JSON. Each plugin parses whatever configuration - * it wants - */ - configuration?: StructsMetadata; - created_at?: string; - description?: string; - /** optionally disable notification (when you want to turn off events) */ - disabled?: boolean; - /** event types, such as schedules.import.error */ - events?: string[]; - id?: string; - /** read-only field populated by the plugin */ - message?: string; - /** plugin to use, such as Slack, Webhook, Email */ - plugin?: StructsIntegrationPlugin; - /** read-only field populated by the plugin */ - status?: string; - updated_at?: string; +export interface ApiSuspiciousEventListResponse { + data?: StructsSuspiciousEvent[]; + limit?: number; + offset?: number; + total?: number; } -export type StructsJSONB = Record; +export interface ApiSuspiciousEventReviewRequest { + log_id?: string; + note?: string; + status?: StructsSuspiciousEventStatus; +} -export interface StructsLog { +export interface ApiSuspiciousEventWebhookResponse { + body_truncated?: boolean; + webhook?: StructsLog; +} + +export interface ApiSuspiciousHuntRequest { account_id?: string; - /** Body is either set or populated from BodyBytes during MarshalJSON() */ - body?: string; bucket_id?: string; + cursor?: string; + from?: string; + limit?: number; + rule_version?: string; + to?: string; +} + +export interface ApiSuspiciousHuntResponse { + findings?: number; + next_cursor?: string; + oversized_bodies?: number; + payload_errors?: number; + rule_version?: string; + scanned?: number; + truncated?: boolean; +} + +export interface ApiTokenScopes { /** - * Compression indicates what compression type - * was used + * Bucket names, IDs, or glob patterns. Empty means unrestricted; !none + * disables bucket subscriptions. */ - compression?: string; - created_at?: number; - deleted_at?: string; - duration_ms?: number; + buckets?: string[]; /** - * If true, doesn't save request body, query or headers, - * inherits from the bucket configuration + * Tunnel names, IDs, groups, hosts, or glob patterns. Empty means + * unrestricted; !none disables tunnel subscriptions. */ - ephemeral?: boolean; - extra_path?: string; - /** request details */ - headers?: StructsHeaders; - id?: string; + tunnels?: string[]; +} + +export interface ApiUpdateAccessTokenRequest { + api_access?: string; + description?: string; + name?: string; + permissions?: StructsTokenPermissions; + scopes?: ApiTokenScopes; +} + +export interface ApiUpdateAccountRequest { + alert_notifications?: boolean; + organization?: boolean; + organization_description?: string; + organization_logo?: string; + organization_name?: string; /** - * InputFunctionExecutionID is the reactor ExecuteLog id for the - * ingress-side function that ran before this webhook hit the - * bucket. Empty when no function ran at the input stage. The UI - * reads /v1/functions//logs/ for this id to render a - * before/after diff. + * every field is a pointer with nil = keep, so partial updates + * (e.g. org-profile-only PUTs) never silently reset the rest */ - input_function_execution_id?: string; - input_id?: string; - internal?: boolean; - ip_address?: string; + usage_alerts?: boolean; + usage_alerts_50?: boolean; + usage_alerts_75?: boolean; + usage_alerts_email?: string; + usage_alerts_emails?: string[]; +} + +export interface FunctiondocsHTTPFixture { + headers?: Record; method?: string; - /** - * OutputFunctionExecutionID is the reactor ExecuteLog id for the - * per-output function that ran before forwarding this delivery - * to the destination. Empty when no function ran on the output. - */ - output_function_execution_id?: string; - output_id?: string; + response_body?: string; + url?: string; +} + +export interface FunctiondocsMethod { + description?: string; + example?: HelpersExample; + name?: string; + notes?: string; + parameters?: HelpersParameter[]; + returns?: string; + signature?: string; +} + +export interface FunctiondocsRecipe { + code?: string; + config?: Record; + delivery_error?: string; + expected_body?: string; + expected_headers?: Record; + http_fixture?: FunctiondocsHTTPFixture; + module?: string; + name?: string; raw_query?: string; - response_body?: number[]; - response_headers?: StructsHeaders; - retries?: number; - /** - * ServiceConnectionInputType is set when the log originates from a service connection input - * (e.g. gcp_pubsub, aws_sqs, aws_sns, aws_s3, gcp_gcs) - */ - service_connection_input_type?: string; - /** - * ServiceConnectionOutputType is set when the log is for a service connection output - * (e.g. gcp_pubsub, aws_sqs, aws_sns, aws_s3, gcp_gcs) - */ - service_connection_output_type?: string; - status?: StructsRequestStatus; - status_code?: number; - updated_at?: number; + request_body?: string; + request_headers?: Record; + response?: FunctiondocsRecipeResponse; + response_body?: string; + response_status?: number; + stop_forwarding?: boolean; } -export interface StructsLogsStats { - day?: string; - failures?: number; - max_retries?: number; - received?: number; - retried?: number; - retry_count?: number; - success?: number; +export interface FunctiondocsRecipeResponse { + body?: string; + headers?: Record; + status?: number; } -export type StructsMetadata = Record; +export interface FunctiondocsReference { + driver?: string; + markdown?: string; + methods?: FunctiondocsMethod[]; + module?: string; + recipes?: FunctiondocsRecipe[]; + version?: string; +} -export interface StructsNewsEntry { - created_at?: string; - id?: string; - message?: string; - message_of_the_day?: boolean; - /** what date to show */ - timestamp?: number; - updated_at?: string; - url?: string; - visible?: boolean; +export interface FunctiondocsRuntime { + driver?: string; + guide?: string; + limits?: string; + modules?: string[]; + version?: string; } -export interface StructsNewsEntryCreateRequest { - /** what date to show */ - date?: string; - message?: string; - message_of_the_day?: boolean; - url?: string; - visible?: boolean; +export interface HelpersExample { + code?: string; + expected_body?: string; + expected_headers?: Record; + expected_method?: string; + expected_path?: string; + expected_raw_query?: string; } -export interface StructsOutput { - /** BucketID is a foreign key */ - bucket_id?: string; - created_at?: number; - created_by?: string; - cron_id?: string; - description?: string; - destination?: string; - /** Enable/disable output destinations */ - disabled?: boolean; - /** - * Durability configures long-period retries via the turbostore - * pending-retry index. See pkg/turbostore/design.md §5.6. - * Stored as JSON so we can extend without a schema migration. - */ - durability?: StructsDurabilityConfig; - /** - * FunctionID is used to indicate whethera code snippet should be used to - * modify this webhook - */ - function_id?: string; - /** - * Headers that will overwrite any existing headers - * from the incoming request - */ - headers?: StructsHeaders; - id?: string; - /** internal outputs will only be relayed by agents */ - internal?: boolean; - /** - * LockPath ensures that the request path cannot be changed from what is - * specified in the destination. For example if request is coming to /v1/webhooks/xxx/github-jenkins, - * with lock path 'false' and destination 'http://localhost:8080' it would go to http://localhost:8080/github-jenkins. - * However, with lock path 'true', it will be sent to 'http://localhost:8080' - */ - lock_path?: boolean; +export interface HelpersParameter { name?: string; + optional?: boolean; + type?: string; + variadic?: boolean; +} + +export interface RulesArgument { + base64decode?: boolean; + envname?: string; + name?: string; + source?: string; +} + +export interface RulesMatchRule { + "ip-range"?: string; + parameter?: RulesArgument; + regex?: string; + secret?: string; + substring?: string; + type?: string; + value?: string; +} + +export interface RulesNotRule { + and?: RulesRules[]; + match?: RulesMatchRule; + or?: RulesRules[]; +} + +export interface RulesRules { + and?: RulesRules[]; + match?: RulesMatchRule; + not?: RulesNotRule; + or?: RulesRules[]; +} + +export interface SessionstoreInferenceRecord { + at?: string; + attempt?: number; + cacheMissCostUSD?: number; + cacheMissReason?: string; + cacheMissTokens?: number; + cacheRead?: number; + cacheWrite?: number; + expectedCacheTokens?: number; + failed?: boolean; + generationMs?: number; + id?: number; + idleSincePreviousMs?: number; + inputTokens?: number; + iteration?: number; + kind?: string; + latencyMs?: number; + outputTokens?: number; + outputTokensPerSecond?: number; + prefixChanged?: boolean; + prefixHash?: string; + provider?: string; + providerChanged?: boolean; + requestID?: string; + sessionID?: string; + stopReason?: string; + ttftms?: number; + turnID?: string; +} + +export interface SessionstorePromptRecord { + acceptedAt?: string; /** - * additional retries (after the first 3 times fail). Setting - * to -1 disables retries - */ - retries?: number; - rules?: RulesRules; - /** - * Throttle configures per-output throughput throttling. When enabled, - * the ingester/server stop delivering this output inline; webhooks are - * persisted (left in RequestStatusReceived) and enqueued into the - * turbostore throttle index, and the dispatcher's throttle controller - * dequeues them at the configured rate/concurrency. Stored as JSON so - * the schema can grow without a migration, same as Durability. - */ - throttle?: StructsThrottleConfig; - /** response timeout */ - timeout?: number; - /** - * Controls TLS verification of the certs for public - * webhooks + * Attachments is the JSON of the prompt's llm.Attachment slice. A recovered + * prompt that never started is re-sent from this row, so dropping them here + * would replay the message without its images. */ - tls_verification?: boolean; - updated_at?: number; + attachments?: number[]; + promptID?: string; + sessionID?: string; + settledAt?: string; + startedAt?: string; + state?: string; + stopCause?: string; + text?: string; } -export interface StructsPlanMeta { - agents?: number; - custom_hostnames?: boolean; - custom_subdomains?: boolean; - custom_tls_version?: boolean; - functions?: number; - https_tunnels?: boolean; - inputs?: number; - integration_configurations?: number; - large_webhooks?: boolean; - legacy_tls?: boolean; - logs_retention?: number; - managed_domains?: number; - outputs?: number; - overage?: number; - /** whether plan should be visible to public */ - public?: boolean; - reserved_domains?: number; - sub_accounts?: number; - tls_tunnels?: boolean; - tokens?: number; - tunnels?: number; - webhooks?: number; +export interface SessionstoreToolCallRecord { + at?: string; + callID?: string; + durationMs?: number; + failed?: boolean; + id?: number; + iteration?: number; + missing?: string; + refused?: boolean; + requestID?: string; + sessionID?: string; + summary?: string; + tool?: string; + turnID?: string; } -export interface StructsRequest { - body?: number[]; - body_modified?: boolean; - body_path?: string; - header?: Record; - header_modified?: boolean; - metadata?: Record; - method?: string; - method_modified?: boolean; - modified_body_path?: string; - path?: string; - path_modified?: boolean; - raw_query?: string; - raw_query_modified?: boolean; +export interface StructsAWSS3Input { + bucket_name?: string; + file_format?: StructsObjectStorageFileFormat; + prefix?: string; + region?: string; } -export interface StructsResponse { - body?: number[]; - body_path?: string; - header?: Record; - status?: number; +export interface StructsAWSS3Output { + bucket_name?: string; + file_format?: StructsObjectStorageFileFormat; + prefix?: string; + region?: string; } -export interface StructsServiceConnection { - account_id?: string; - aws_service_connection?: StructsAWSServiceConnection; - azure_service_connection?: StructsAzureServiceConnection; - created_at?: string; - error?: string; - gcp_service_connection?: StructsGCPServiceConnection; - /** ULID, starts with prefix "scn_" */ - id?: string; - last_checked?: string; - name?: string; - retries?: number; - service_type?: StructsServiceType; - status?: StructsServiceConnectionStatus; - updated_at?: string; +export interface StructsAWSSNSInput { + region?: string; + subscription_arn?: string; + topic_arn?: string; } -export interface StructsServiceConnectionInput { - aws_s3_input?: StructsAWSS3Input; - aws_sns_input?: StructsAWSSNSInput; - aws_sqs_input?: StructsAWSSQSInput; - bucket_id?: string; - created_at?: string; - error?: string; - function_id?: string; - gcp_gcs_input?: StructsGCPGCSInput; - gcp_pubsub_input?: StructsGCPPubSubInput; - id?: string; - name?: string; - service_connection_id?: string; - /** Used to load all inputs for a service connection */ - service_connection_input_type?: StructsServiceConnectionInputType; - status?: StructsServiceConnectionInputStatus; - updated_at?: string; +export interface StructsAWSSNSOutput { + region?: string; + topic_arn?: string; } -export interface StructsServiceConnectionOutput { - aws_s3_output?: StructsAWSS3Output; - aws_sns_output?: StructsAWSSNSOutput; - aws_sqs_output?: StructsAWSSQSOutput; - bucket_id?: string; - created_at?: number; - discord_output?: StructsDiscordOutput; - function_id?: string; - gcp_gcs_output?: StructsGCPGCSOutput; - gcp_pubsub_output?: StructsGCPPubSubOutput; - id?: string; - name?: string; - service_connection_id?: string; - service_connection_output_type?: StructsServiceConnectionOutputType; - slack_output?: StructsSlackOutput; - updated_at?: number; +export interface StructsAWSSQSInput { + queue_url?: string; + region?: string; } -export interface StructsSlackOutput { - webhook_url?: string; +export interface StructsAWSSQSOutput { + queue_url?: string; + region?: string; } -export interface StructsSubAccount { - account?: StructsAccount; - account_id?: string; +export interface StructsAWSServiceConnection { + access_key_id?: string; + secret_access_key?: string; +} + +export interface StructsAccessToken { + active?: boolean; + api_access?: StructsAPIAccess; + created_at?: string; + /** + * CreatedBy attributes the token to whoever minted it (sub-account + * ID or org member account ID; empty = account owner). Used to + * revoke org-bound tokens when their creator leaves the org. + */ + created_by?: string; + created_by_role?: string; + deleted_at?: string; + description?: string; + id?: string; + last_login?: string; + /** + * Name is the API compatibility alias for Description. Description remains + * the persisted column; MarshalJSON derives Name so clients that create a + * token with `name` see it round-trip on list responses. + */ + name?: string; + /** + * Permissions optionally constrains REST and MCP access using the same + * role model as organization members. Nil preserves the historical + * unrestricted access-token behaviour for tokens created before this field + * existed. + */ + permissions?: StructsTokenPermissions; + scopes?: StructsMetadata; + updated_at?: string; +} + +export interface StructsAccount { + access_tokens?: StructsAccessToken[]; + /** normalized: paid/organic/social/email/referral/direct */ + acquisition_channel?: string; + active?: boolean; + alert_notifications?: boolean; /** authentication type (regular/github/google) */ auth_type?: StructsAccountAuthType; avatar_url?: string; + buckets?: StructsBucket[]; + company_name?: string; created_at?: string; + current_period_end?: number; + /** subscription period start and end, updated by stripe */ + current_period_start?: number; deleted_at?: string; + domains?: StructsDomain[]; email?: string; + email_verified?: boolean; failed_login_attempts?: number; + /** Meta click id */ + fbclid?: string; + first_name?: string; + /** first-touch utm_source when it differs from last touch */ + first_touch_source?: string; + /** Google click id (offline conversion import) */ + gclid?: string; id?: string; + landing_page?: string; last_failed_login?: string; last_login_at?: string; + last_name?: string; mfa_enabled?: boolean; - saml_sso_org_id?: string; - /** If set, user will be asked to change the password after login */ - update_password?: boolean; + /** Microsoft click id */ + msclkid?: string; + /** + * Organization marks this account as an organization: other + * accounts can be invited into it as members (see + * OrganizationMember). Org ID == this account's ID. Conversion is + * one-way — the flag is never unset. + */ + organization?: boolean; + organization_description?: string; + /** + * OrganizationLogo holds a small data:image/...;base64 logo (a few + * KB — the dashboard resizes before upload, the API caps the size). + */ + organization_logo?: string; + organization_name?: string; + /** + * desired plan ID, used when registering new account + * to create new subscription in Stripe after + * email is verified + */ + plan_id?: string; + plan_meta?: StructsMetadata; + referrer_url?: string; + role?: string; + sub_accounts?: StructsSubAccount[]; + /** Unix ts */ + subscription_created?: number; + subscription_extras?: StructsSubscriptionExtras[]; + subscription_meta?: StructsMetadata; + /** Subscription status and fields */ + subscription_status?: string; + /** + * SuspendProtection prevents account's buckets from being suspended for + * overuse + */ + suspend_protection?: boolean; + tunnels?: StructsTunnel[]; updated_at?: string; + usage_alerts?: boolean; + usage_alerts_50?: boolean; + usage_alerts_75?: boolean; + usage_alerts_email?: string; + /** + * UsageAlertsEmails are additional recipients for quota notifications. + * The account email remains the primary recipient; this list is additive. + */ + usage_alerts_emails?: string[]; + /** Why have they registered? */ + use_case?: string; + use_case_completed?: boolean; username?: string; + utm_campaign?: string; + utm_content?: string; + utm_medium?: string; + /** + * Acquisition attribution — where this signup came from. Captured at + * registration from the marketing site's wr_attribution cookie / utm_* query + * params (see plugins/attribution.client.ts on webhookrelay.com). Used to + * trace ad -> click -> signup -> paid plan. All best-effort, may be empty. + */ + utm_source?: string; + utm_term?: string; + webhookCounts?: StructsWebhooksCount[]; } -export interface StructsSubAccountCreateRequest { - auth_type?: StructsAccountAuthType; - email?: string; - username?: string; +export interface StructsAccountAPIKey { + api_key?: string; } -export interface StructsSubAccountCreateResponse { - password?: string; - sub_account?: StructsSubAccount; +export interface StructsAdminConnectedAccount { + account_id?: string; + email?: string; + plan?: string; + plan_id?: string; + tunnel_clients?: StructsConnectedTunnelClientInfo[]; username?: string; + webhook_clients?: StructsConnectedWebhookClientInfo[]; } -export interface StructsSubscriptionExtras { - description?: string; - metadata?: Record; - price_id?: string; - quantity?: number; - term?: StructsSubscriptionTerm; - unit_amount?: number; +export interface StructsAdminConnectedClientsResponse { + accounts?: StructsAdminConnectedAccount[]; + total_count?: number; } -export interface StructsSubscriptionResponse { - amount?: number; - cancel_at_period_end?: boolean; - currency?: string; - current_period_end?: number; - current_period_start?: number; - customer_id?: string; - extras?: StructsSubscriptionExtras[]; - meta_data?: StructsPlanMeta; - plan?: string; +export interface StructsAdminUsageAlert { + account_email?: string; + account_id?: string; + account_username?: string; + created_at?: string; + delivery_status?: string; + id?: string; + notice_type?: string; plan_id?: string; - status?: string; - subscription_id?: string; - trial_end?: number; - trial_start?: number; + quota?: number; + recipients_sent?: number; + recipients_total?: number; + subscription_period_end?: number; + subscription_period_start?: number; + suspended?: boolean; + threshold?: number; + used?: number; } -export interface StructsThrottleConfig { +export interface StructsAgentApproval { + account_id?: string; + asked_at?: string; + /** CallID is the provider's tool-call id, matching the tool_call event. */ + call_id?: string; + conversation_id?: string; + decided_at?: string; + decided_by?: string; + decision?: string; + id?: string; /** - * Deadline caps how long a queued webhook may wait for delivery, - * measured from when it was received. Zero falls through to - * DefaultThrottleDeadline. Webhooks older than the deadline are dropped - * (marked failed) instead of delivered. + * Input is the tool's arguments as the model sent them (clipped), so a + * reviewer can see exactly what would have been deleted. */ - deadline?: TimeDuration; - /** Enabled toggles the whole feature for this output. */ - enabled?: boolean; + input?: string; + /** Reason is the user's words on a denial, or the system's on expiry. */ + reason?: string; /** - * Interval is ThrottleIntervalSecond / Minute / Hour. Used only in - * ThrottleModeRate. + * Remember is true when the approval was also recorded on the + * conversation, so later calls needing the same scope do not ask again. */ - interval?: string; + remember?: boolean; + /** Scope is the access that was missing, e.g. "routing:drop". */ + scope?: string; + tool?: string; +} + +export interface StructsAgentConversation { + account_id?: string; /** - * MaxConcurrent is the maximum number of in-flight deliveries. Used - * only in ThrottleModeConcurrency. 1 means serial delivery. + * ApprovedScopes are the harness scopes the user widened this + * conversation by ("routing:drop"), space separated. Approvals outlive + * a turn: each turn is its own session, so the widening is replayed on + * top of the role's grant when the next turn starts. */ - max_concurrent?: number; + approved_scopes?: string; + context_id?: string; /** - * MaxQueueDepth bounds how many webhooks may sit in the queue for this - * output. Zero means unbounded. When exceeded, the ingester rejects - * new webhooks with HTTP 429. + * ContextKind / ContextID name the page the conversation was opened + * from: "function" + a function ID for the function details page. */ - max_queue_depth?: number; - /** Mode is ThrottleModeRate or ThrottleModeConcurrency. */ - mode?: string; + context_kind?: string; + created_at?: string; /** - * Rate is the maximum number of deliveries per Interval. Used only in - * ThrottleModeRate. + * CreatedBy is the acting member in an organization context, the + * account itself otherwise. */ - rate?: number; + created_by?: string; + /** Grant is the harness grant label the conversation runs under. */ + grant?: string; + id?: string; + last_message_at?: string; + /** + * Page is a human label for where the chat was opened from ("Buckets", + * "Bucket orders", "Access Tokens"), so the agent knows what the user is + * looking at even when there is no resource to bind to. + */ + page?: string; + title?: string; + turns?: number; + updated_at?: string; } -export interface StructsTunnel { +export interface StructsAgentFeedback { account_id?: string; + comment?: string; + conversation_id?: string; + created_at?: string; + created_by?: string; /** - * Addr specifies TCP address server would listen on, it's required - * for TCP tunnels. + * Excerpt is the start of the rated message, so a reviewer sees what was + * rated without loading the transcript. */ - addr?: string; + excerpt?: string; + id?: string; /** - * AgentID is used by the ingress controller and is - * randomly generated on startup. Once controller is running - * it will send periodic updates to indicate that it's still running. + * MessageIndex is the position of the assistant message in the stored + * transcript (ProjectHistory order); one rating per message. */ - agent_id?: string; - auth?: StructsTunnelAuth; - created_at?: number; - /** crypto types, used to issue lets encrypt certs */ - crypto?: string; + message_index?: number; + /** up | down */ + rating?: string; + updated_at?: string; +} + +export interface StructsAgentLimitOverrides { + /** MaxIterations overrides model round trips per turn (AGENT_MAX_ITERATIONS). */ + max_iterations?: number; + /** MaxOutputTokens overrides the single-response output cap. */ + max_output_tokens?: number; + /** + * MaxTokensPerTurn overrides the per-turn effective-token budget + * (AGENT_MAX_TOKENS). Cache reads count at one tenth. + */ + max_tokens_per_turn?: number; + /** + * PlanTokens overrides the monthly effective-token allowance per plan + * family (free, basic, business, pro); -1 removes the cap. The override + * replaces the family default only: an account whose plan metadata sets + * agent_tokens explicitly keeps its explicit value. + */ + plan_tokens?: Record; +} + +export interface StructsAlertPolicy { + check_interval_seconds?: number; description?: string; - /** destination host, defaults to 127.0.0.1:8000 */ - destination?: string; - features?: StructsMetadata; + health_endpoint?: StructsHealthEndpointConfig; + minimum_events?: number; + mode?: StructsAlertPolicyMode; + recovery_threshold_percent?: number; + threshold_percent?: number; + tls_expiration_days?: number; + type?: StructsAlertType; + window_seconds?: number; +} + +export interface StructsAuditLog { /** - * optional tunnel group, primarily used by the ingress to subscribe - * to specific group of tunnels + * composite indexes cover the account activity view's query + * patterns: paginated scan by (account_id, created_at) plus + * user/action filters; (account_id, action, resource_id) predates + * this and doubles as the action filter index. */ - group?: string; + account_id?: string; + /** create/delete/update */ + action?: string; /** - * tunnel's subdomain, random for free tier - * or named for paid subs + * Actor fields identify the real logged-in account when the action + * was performed in an organization context (AccountID is then the + * org account). Empty for regular requests. */ - host?: string; + actor_account_id?: string; + actor_email?: string; + /** + * AgentConversationID is the chat the agent acted in when Source is + * "agent", so the activity view can open the conversation. + */ + agent_conversation_id?: string; + created_at?: string; + /** + * Diff is a JSON array of {field, old, new} changes captured on + * update actions (sensitive values redacted). Empty for creates, + * deletes and entries recorded before diffs existed — the UI shows + * those as "unavailable". + */ + diff?: string; + email?: string; id?: string; - ingress_rules?: StructsJSONB; - mode?: StructsTunnelMode; - /** tunnel name */ + /** Caller's IP address */ + ip_address?: string; + message?: string; + resource_id?: string; + /** for inputs it's input ID, for tunnels it's host */ + resource_identifier?: string; + /** bucket/tunnel/input/output/account */ + resource_kind?: string; + /** + * Source names the surface the action came through: "mcp" for an MCP + * client, "agent" for the agent chat. Empty for the REST API and the + * dashboard, which are one surface at this layer. + */ + source?: string; + updated_at?: string; + username?: string; +} + +export interface StructsAzureServiceConnection { + client_id?: string; + client_secret?: string; + tenant_id?: string; +} + +export interface StructsBillingDetails { + city?: string; + country?: string; + customer_id?: string; + email?: string; + line1?: string; + line2?: string; + /** Customer full name or business name */ name?: string; - /** tunnel protocol - http/tcp */ - protocol?: string; - /** optional tunnel region */ - region?: string; + postal_code?: string; + state?: string; + /** Value of the tax ID. */ + tax_id?: string; + /** Type of the tax ID, one of `ae_trn`, `au_abn`, `au_arn`, `bg_uic`, `br_cnpj`, `br_cpf`, `ca_bn`, `ca_gst_hst`, `ca_pst_bc`, `ca_pst_mb`, `ca_pst_sk`, `ca_qst`, `ch_vat`, `cl_tin`, `es_cif`, `eu_oss_vat`, `eu_vat`, `gb_vat`, `ge_vat`, `hk_br`, `hu_tin`, `id_npwp`, `il_vat`, `in_gst`, `is_vat`, `jp_cn`, `jp_rn`, `kr_brn`, `li_uid`, `mx_rfc`, `my_frp`, `my_itn`, `my_sst`, `no_vat`, `nz_gst`, `ru_inn`, `ru_kpp`, `sa_vat`, `sg_gst`, `sg_uen`, `si_tin`, `th_vat`, `tw_vat`, `ua_vat`, `us_ein`, or `za_vat` */ + tax_id_type?: string; +} + +export interface StructsBucket { + account_id?: string; + auth?: StructsBucketAuth; + created_at?: number; + /** + * CreatedBy is the account ID of the user who created the bucket — + * for organization accounts this is the acting member. Empty means + * the account owner. + */ + created_by?: string; + cron_id?: string; + description?: string; + /** If true, doesn't save request body, query or headers */ + ephemeral?: boolean; + id?: string; + inputs?: StructsInput[]; + integration_configurations?: StructsIntegrationConfiguration[]; + /** + * LargeWebhooks - if set, we allow larger than 3MB webhooks + * to be sent to the bucket. This is useful for large file uploads + */ + large_webhooks?: boolean; + name?: string; + outputs?: StructsOutput[]; + service_connection_inputs?: StructsServiceConnectionInput[]; + service_connection_outputs?: StructsServiceConnectionOutput[]; + /** StaticIP - if set, the bucket will use a static IP (routing through forwarding proxy) */ + static_ip?: boolean; + /** enable/disable websocket streaming for the bucket */ + stream?: boolean; + /** + * Set to TRUE by the curator if accounts goes over the + * webhook limit + */ + suspended?: boolean; updated_at?: number; } -export interface StructsTunnelAuth { +export interface StructsBucketAuth { created_at?: number; id?: string; password?: string; @@ -1281,384 +1683,4277 @@ export interface StructsTunnelAuth { username?: string; } -export interface StructsUpdateAPIKeyStatusRequest { - enabled?: boolean; +export interface StructsBucketLogsStats { + bucket_id?: string; + stats?: StructsLogsStats[]; } -export interface StructsUpdateAPIKeyStatusResponse { - enabled?: boolean; +export interface StructsCombinedUsage { + plan_meta?: StructsPlanMeta; + usage?: StructsUsage; } -export interface StructsUpdateFunctionRequest { - account_id?: string; - driver?: string; - id?: string; - name?: string; - payload?: string; +export interface StructsConnectedClient { + tunnel_clients?: StructsConnectedTunnelClient[]; + webhook_clients?: StructsConnectedWebhookClient[]; } -export interface StructsUsage { - account_id?: string; - /** agents currently connected */ - agents?: number; - created_at?: string; - inputs?: number; - outputs?: number; - tokens?: number; - tunnels?: number; - webhooks?: number; +export interface StructsConnectedTunnelClient { + access_token_key?: string; + client_ip?: string; + client_version?: string; + subscribed_at?: number; + tunnels?: string[]; } -export interface StructsVariable { - account_id?: string; - created_at?: string; - function_id?: string; - key?: string; - updated_at?: string; - value?: string; +export interface StructsConnectedTunnelClientInfo { + access_token_key?: string; + client_ip?: string; + client_version?: string; + subscribed_at?: number; + tunnel_names?: string[]; + tunnels?: string[]; } -export interface StructsWebhooksCount { - /** account that it belongs to */ - account_id?: string; - created_at?: string; - /** beginning of the day for which the webhooks are calculated */ - date?: string; - failed?: number; - id?: string; - /** Potential webhook statuses */ - preparing?: number; - received?: number; - rejected?: number; - sent?: number; - stalled?: number; - /** daily/monthly term of the calculation */ - term?: StructsWebhooksCountTerm; - updated_at?: string; +export interface StructsConnectedWebhookClient { + access_token_key?: string; + buckets?: string[]; + client_ip?: string; + client_type?: string; + client_version?: string; + destination?: string; + subscribed_at?: number; } -export type QueryParamsType = Record; -export type ResponseFormat = keyof Omit; - -export interface FullRequestParams extends Omit { - /** set parameter to `true` for call `securityWorker` for this request */ - secure?: boolean; - /** request path */ - path: string; - /** content type of request body */ - type?: ContentType; - /** query params */ - query?: QueryParamsType; - /** format of response (i.e. response.json() -> format: "json") */ - format?: ResponseFormat; - /** request body */ - body?: unknown; - /** base url */ - baseUrl?: string; - /** request cancellation token */ - cancelToken?: CancelToken; +export interface StructsConnectedWebhookClientInfo { + access_token_key?: string; + bucket_names?: string[]; + buckets?: string[]; + client_ip?: string; + client_type?: string; + client_version?: string; + destination?: string; + subscribed_at?: number; } -export type RequestParams = Omit< - FullRequestParams, - "body" | "method" | "query" | "path" ->; - -export interface ApiConfig { - baseUrl?: string; - baseApiParams?: Omit; - securityWorker?: ( - securityData: SecurityDataType | null, - ) => Promise | RequestParams | void; - customFetch?: typeof fetch; +export interface StructsCreateFunctionRequest { + driver?: string; + name?: string; + payload?: string; } -export interface HttpResponse - extends Response { - data: D; - error: E; +export interface StructsCreateTunnelRequest { + /** + * Addr specifies TCP address server would listen on, it's required + * for TCP tunnels. + */ + addr?: string; + agent_id?: string; + auth?: StructsTunnelAuth; + crypto?: string; + description?: string; + destination?: string; + features?: StructsFeatures; + group?: string; + host?: string; + ingress_rules?: StructsIngressRules; + name?: string; + protocol?: string; + region?: string; + subdomain?: string; } -type CancelToken = Symbol | string | number; +export interface StructsCron { + account_id?: string; + bucket?: StructsBucket; + created_at?: string; + /** + * CreatedBy is the account ID of the user who created the cron — + * for organization accounts this is the acting member. Empty means + * the account owner. + */ + created_by?: string; + /** URL to send the webhook to */ + destination?: string; + enabled?: boolean; + ends_at?: string; + /** Function ID attached to the output */ + function_id?: string; + headers?: StructsHeaders; + id?: string; + /** + * Payload and headers injected into the Bucket. Outputs + * are still used to send the webhook + */ + method?: string; + name?: string; + /** Populated by the handler for UI to display */ + next_run?: string; + payload?: string; + recurring?: boolean; + schedule?: string; + /** Dates from which the cron job starts and ends */ + starts_at?: string; + timezone?: string; + updated_at?: string; +} -export enum ContentType { - Json = "application/json", - JsonApi = "application/vnd.api+json", - FormData = "multipart/form-data", - UrlEncoded = "application/x-www-form-urlencoded", - Text = "text/plain", +export interface StructsDBSSODetails { + /** + * AllowJIT is a pointer so old rows with no key retain the historical + * behavior (JIT enabled). New self-service connections write it explicitly. + */ + allow_jit?: boolean; + allowed_domains?: string[]; + /** ForceAuthn asks the IdP to reauthenticate instead of reusing its session. */ + force_authn?: boolean; + /** + * NameIDFormat controls the NameIDPolicy sent in AuthnRequest. Empty keeps + * crewjam's default transient format for backward compatibility. + */ + name_id_format?: string; + /** + * SignatureMethod selects the algorithm used to sign AuthnRequests. Empty + * retains RSA-SHA1 for old rows; new connections explicitly use SHA-256. + */ + signature_method?: string; } -export class HttpClient { - public baseUrl: string = "https://my.webhookrelay.com"; - private securityData: SecurityDataType | null = null; - private securityWorker?: ApiConfig["securityWorker"]; - private abortControllers = new Map(); - private customFetch = (...fetchParams: Parameters) => - fetch(...fetchParams); +export type StructsDeleteFunctionResponse = object; - private baseApiParams: RequestParams = { - credentials: "same-origin", - headers: {}, - redirect: "follow", - referrerPolicy: "no-referrer", - }; +export type StructsDeleteVariableResponse = object; - constructor(apiConfig: ApiConfig = {}) { - Object.assign(this, apiConfig); - } +export interface StructsDiscordOutput { + webhook_url?: string; +} - public setSecurityData = (data: SecurityDataType | null) => { - this.securityData = data; - }; +export interface StructsDomain { + created_at?: number; + /** + * Domain can be any 3rd party domain such as + * user.example.com + */ + domain?: string; + id?: string; + updated_at?: number; +} - protected encodeQueryParam(key: string, value: any) { - const encodedKey = encodeURIComponent(key); - return `${encodedKey}=${encodeURIComponent(typeof value === "number" ? value : `${value}`)}`; - } +export interface StructsDurabilityConfig { + /** CustomDelays is consulted only when Schedule == "custom". */ + custom_delays?: TimeDuration[]; + /** + * Deadline caps total retry duration measured from the webhook's + * received_at timestamp. Zero falls through to a schedule-derived + * default (~30 d for "long", ~16 h for "medium", ~25 min for + * "seconds"). + */ + deadline?: TimeDuration; + /** Enabled toggles the whole feature for this output. */ + enabled?: boolean; + /** + * HandoffAfter is the attempt-age threshold past which a failing + * delivery is moved from the in-pubsub retry path to the durable + * pending index. Zero falls through to 15 minutes — short enough + * that long retries don't bloat the pubsub backlog, long enough + * that transient blips don't pay an extra object-store PUT. + */ + handoff_after?: TimeDuration; + /** + * Schedule names a backoff preset ("seconds", "medium", "long", + * "custom"). Empty falls through to "long" when Enabled, "seconds" + * otherwise. Custom backoffs use CustomDelays. + */ + schedule?: string; +} - protected addQueryParam(query: QueryParamsType, key: string) { - return this.encodeQueryParam(key, query[key]); - } +export interface StructsEmailInput { + /** + * AllowedSenders, when non-empty, restricts inbound mail to these From + * addresses (exact match, lower-cased). Abuse / hardening control. + */ + allowed_senders?: string[]; + /** DropAttachments skips attachment parsing and storage entirely. */ + drop_attachments?: boolean; + /** + * Enabled gates whether inbound mail is accepted. When false the address + * still resolves but mail is dropped at ingest. + */ + enabled?: boolean; + /** + * MaxAttachmentBytes overrides the per-message total attachment storage cap. + * 0 uses the server default. + */ + max_attachment_bytes?: number; +} - protected addArrayQueryParam(query: QueryParamsType, key: string) { - const value = query[key]; - return value.map((v: any) => this.encodeQueryParam(key, v)).join("&"); - } +export interface StructsEndpoint { + address?: string; +} - protected toQueryString(rawQuery?: QueryParamsType): string { - const query = rawQuery || {}; - const keys = Object.keys(query).filter( - (key) => "undefined" !== typeof query[key], - ); - return keys - .map((key) => - Array.isArray(query[key]) - ? this.addArrayQueryParam(query, key) - : this.addQueryParam(query, key), - ) - .join("&"); - } +export interface StructsErrorResponse { + error?: string; +} - protected addQueryParams(rawQuery?: QueryParamsType): string { - const queryString = this.toQueryString(rawQuery); - return queryString ? `?${queryString}` : ""; - } +export interface StructsExecuteLog { + account_id?: string; + configuration_id?: string; + created?: number; + duration?: number; + execute_request?: StructsExecuteRequest; + execute_response?: StructsExecuteResponse; + function_id?: string; + id?: string; + status?: StructsExecutionStatus; + updated?: number; +} - private contentFormatters: Record any> = { - [ContentType.Json]: (input: any) => - input !== null && (typeof input === "object" || typeof input === "string") - ? JSON.stringify(input) - : input, - [ContentType.JsonApi]: (input: any) => - input !== null && (typeof input === "object" || typeof input === "string") - ? JSON.stringify(input) - : input, - [ContentType.Text]: (input: any) => - input !== null && typeof input !== "string" - ? JSON.stringify(input) - : input, - [ContentType.FormData]: (input: any) => { - if (input instanceof FormData) { - return input; - } +export interface StructsExecuteLogResponse { + execute_logs?: StructsExecuteLog[]; + limit?: number; + offset?: number; + total?: number; +} - return Object.keys(input || {}).reduce((formData, key) => { - const property = input[key]; - formData.append( - key, - property instanceof Blob - ? property - : typeof property === "object" && property !== null - ? JSON.stringify(property) - : `${property}`, - ); - return formData; - }, new FormData()); - }, - [ContentType.UrlEncoded]: (input: any) => this.toQueryString(input), +export interface StructsExecuteRequest { + account_id?: string; + configuration_id?: string; + /** + * DeliveryError is the transport-level error string for an + * ExecutionModeResponse run when delivery failed without an HTTP + * response (timeout, connection refused, TLS error). Empty when an HTTP + * response was received, even a 5xx. + */ + delivery_error?: string; + function_id?: string; + request?: StructsRequest; + request_id?: string; + /** + * Response carries the destination's reply for ExecutionModeResponse + * runs. Status is the HTTP status code (0 when there was no response — + * a connection error or timeout), Body is the (inline) response body, + * Header the response headers. Unset for input/output functions. + */ + response?: StructsResponse; + response_body_path?: string; +} + +export interface StructsExecuteResponse { + error?: string; + function_id?: string; + /** + * Logs is the output the function itself emitted through console.log / + * console.warn / console.error (JavaScript) or print (Lua) during this + * execution. Captured per execution and persisted with the ExecuteLog so + * the dashboard, the REST API and the MCP `execute` tool can show users + * what their own code printed — before this existed the output went only + * to the platform's internal logs and was invisible to the account. + * Bounded by pkg/reactor/functionlogs; secrets are redacted at capture. + */ + logs?: StructsFunctionLogEntry[]; + request?: StructsRequest; + request_id?: string; + request_modified?: boolean; + response?: StructsResponse; + response_modified?: boolean; + stop_forwarding?: boolean; +} + +export interface StructsFeatures { + rewrite_host_header?: string; + /** validate TLS certificate */ + skip_insecure_verify?: boolean; +} + +export interface StructsFunction { + account_id?: string; + compression?: string; + created?: number; + /** + * CreatedBy is the account ID of the user who created the function — + * for organization accounts this is the acting member. Empty means + * the account owner. + */ + created_by?: string; + driver?: string; + id?: string; + metadata?: Record; + name?: string; + payload?: string; + payload_size?: number; + requirements?: StructsFunctionConnectionRequirement[]; + updated?: number; +} + +export interface StructsFunctionConnectionRequirement { + alias?: string; + connection_types?: string[]; + module?: string; + required?: boolean; + service_connection_id?: string; + service_connection_name?: string; + status?: string; +} + +export interface StructsFunctionLogEntry { + level?: string; + message?: string; + /** + * Time is the capture time in Unix milliseconds. Useful when a function + * interleaves logging with slow calls (http, bigquery) and the gaps + * matter. + */ + time?: number; +} + +export interface StructsFunctionVersion { + account_id?: string; + created_at?: number; + /** CreatedBy is the acting account when known (org member, token owner). */ + created_by?: string; + driver?: string; + function_id?: string; + name?: string; + payload?: string; + payload_size?: number; + /** RestoredFrom is set when the revision was created by restoring another. */ + restored_from?: number; + /** Source names what saved the revision: api, mcp, agent, restore. */ + source?: string; + version?: number; +} + +export interface StructsGCPGCSInput { + bucket_name?: string; + file_format?: StructsObjectStorageFileFormat; + notification_id?: string; + prefix?: string; +} + +export interface StructsGCPGCSOutput { + bucket_name?: string; + file_format?: StructsObjectStorageFileFormat; + prefix?: string; +} + +export interface StructsGCPPubSubInput { + subscription_name?: string; +} + +export interface StructsGCPPubSubOutput { + topic_name?: string; +} + +export interface StructsGCPServiceConnection { + project_id?: string; + service_account_email?: string; + service_account_key?: string; +} + +export interface StructsGenerateFunctionRequest { + /** Additional information about the function */ + additional_info?: string; + input_payload?: string; + /** Desired output payload */ + output_payload?: string; +} + +export interface StructsGenerateFunctionResponse { + /** Function code */ + code?: string; + /** Validation error message */ + validation_err?: string; + /** Indicates if the function is valid */ + validation_ok?: boolean; +} + +export interface StructsHeader { + values?: string[]; +} + +export type StructsHeaders = Record; + +export interface StructsHealthEndpointConfig { + basic_password?: string; + basic_username?: string; + headers?: Record; + method?: string; + path?: string; +} + +export interface StructsIncidentDayStats { + count?: number; + day?: string; + duration_seconds_count?: number; + duration_seconds_sum?: number; + open_count?: number; + resolved_count?: number; +} + +export interface StructsIngressRule { + /** Endpoints */ + endpoints?: StructsEndpoint[]; + /** + * Name is an option identifier for the ingress rule, it usually is a service name + * if used with webrelay-ingress + */ + name?: string; + /** + * Path is an extended POSIX regex as defined by IEEE Std 1003.1, + * (i.e this follows the egrep/unix syntax, not the perl syntax) + * matched against the path of an incoming request. Currently it can + * contain characters disallowed from the conventional "path" + * part of a URL as defined by RFC 3986. Paths must begin with + * a '/'. If unspecified, the path defaults to a catch all sending + * traffic to the backend. + * +optional + */ + path?: string; +} + +export interface StructsIngressRules { + rules?: StructsIngressRule[]; +} + +export interface StructsInput { + body?: number[]; + /** BucketID is a foreign key */ + bucket_id?: string; + created_at?: number; + created_by?: string; + /** + * Input's domain name, can be set to work with the CNAMEs + * so WHR will fetch a cert from LE + * (make sure you create a CNAME DNS record for your domain to stats.uptimerobot.com. + * And, it can take up to 30 mins for the custom domain to be activated.) + */ + custom_domain?: string; + description?: string; + function_id?: string; + /** response details */ + headers?: StructsHeaders; + id?: string; + /** + * LegacyTLS widens the accepted handshake to TLS 1.0/1.1 *and* the + * older RSA/CBC cipher set. The two used to be split into separate + * fields but the policy resolver applies them as one logical toggle, + * and the dashboard surfaces them as one switch — keep the on-disk + * shape matching that single concept. + */ + legacy_tls?: boolean; + name?: string; + /** PathPrefix only works when CustomDomain is set */ + path_prefix?: string; + /** + * either output ID or "anyOutput" to indicate that the first response + * from any output is good enough. Empty string + */ + response_from_output?: string; + status_code?: number; + /** + * StripPathPrefix indicates whether full path should be included when + * forwarding the webhook. If the path prefix is /abc and the webhook + * arrives at /abc/foo, then by default the full path will be /abc/foo + */ + strip_path_prefix?: boolean; + /** + * TLSVersion sets the MINIMUM accepted TLS version for this input's HTTPS + * endpoint. It is a floor, not a pin: handshakes negotiate this version or + * any higher one the backend allows (e.g. "1.1" still accepts 1.2 and 1.3). + * Empty value means default hardened policy. + */ + tls_version?: string; + updated_at?: number; +} + +export interface StructsIntegrationConfiguration { + /** + * AlertPolicy controls when delivery failures open and resolve incidents. + * It is evaluated from the durable update stream in the worker, not on the + * request path, so high-throughput buckets never query configuration per + * webhook or emit one notification per failure. + */ + alert_policy?: StructsAlertPolicy; + buckets?: StructsBucket[]; + /** + * notification plugin configuration, free form JSON. Each plugin parses whatever configuration + * it wants + */ + configuration?: StructsMetadata; + created_at?: string; + description?: string; + /** optionally disable notification (when you want to turn off events) */ + disabled?: boolean; + /** event types, such as schedules.import.error */ + events?: string[]; + id?: string; + /** read-only field populated by the plugin */ + message?: string; + /** plugin to use, such as Slack, Webhook, Email */ + plugin?: StructsIntegrationPlugin; + /** read-only field populated by the plugin */ + status?: string; + updated_at?: string; +} + +export type StructsJSONB = Record; + +export interface StructsLLMServiceConnection { + api_key?: string; + base_url?: string; +} + +export interface StructsLog { + account_id?: string; + /** + * Attempts is the delivery attempt history (one entry per try, oldest + * first, attempt_no 1-based). Populated by GetLog from turbostore v2's + * WebhookDetail; carried on the update path so the worker's queue + * consumer can emit attempt events. Empty for single first-try + * successes, logs written before attempt capture, and ClickHouse + * reads. Never stored by GORM. + */ + attempts?: StructsLogAttempt[]; + /** Body is either set or populated from BodyBytes during MarshalJSON() */ + body?: string; + bucket_id?: string; + /** + * Compression indicates what compression type + * was used + */ + compression?: string; + consumer_id?: string; + created_at?: number; + deleted_at?: string; + duration_ms?: number; + /** + * If true, doesn't save request body, query or headers, + * inherits from the bucket configuration + */ + ephemeral?: boolean; + event_type?: string; + extra_path?: string; + /** request details */ + headers?: StructsHeaders; + id?: string; + /** + * InputFunctionExecutionID is the reactor ExecuteLog id for the + * ingress-side function that ran before this webhook hit the + * bucket. Empty when no function ran at the input stage. The UI + * reads /v1/functions//logs/ for this id to render a + * before/after diff. + */ + input_function_execution_id?: string; + input_id?: string; + internal?: boolean; + ip_address?: string; + /** Outbound message identity; set only on outbound logs (IsOutbound). */ + message_id?: string; + method?: string; + /** + * OutputFunctionExecutionID is the reactor ExecuteLog id for the + * per-output function that ran before forwarding this delivery + * to the destination. Empty when no function ran on the output. + */ + output_function_execution_id?: string; + output_id?: string; + /** + * OutputResponseFunctionExecutionID is the reactor ExecuteLog id for + * the per-output response (post-delivery) function. Empty when no + * response function ran. + */ + output_response_function_execution_id?: string; + raw_query?: string; + /** + * RequestBytes and ResponseBytes contain recorded body + HTTP header + * bytes for this delivery. They exclude request/status lines, the final + * blank header line, TLS, and transport framing. GORM ignores them so + * ClickHouse remains unchanged; Turbostore persists and aggregates them. + */ + request_bytes?: number; + response_body?: number[]; + response_bytes?: number; + response_headers?: StructsHeaders; + retries?: number; + /** + * ServiceConnectionInputType is set when the log originates from a service connection input + * (e.g. gcp_pubsub, aws_sqs, aws_sns, aws_s3, gcp_gcs) + */ + service_connection_input_type?: string; + /** + * ServiceConnectionOutputType is set when the log is for a service connection output + * (e.g. gcp_pubsub, aws_sqs, aws_sns, aws_s3, gcp_gcs) + */ + service_connection_output_type?: string; + status?: + | "preparing" + | "sent" + | "failed" + | "stalled" + | "received" + | "rejected"; + status_code?: number; + total_bytes?: number; + updated_at?: number; +} + +export interface StructsLogAttempt { + attempt_id?: string; + attempt_no?: number; + duration_ms?: number; + error?: string; + finished_at?: string; + outcome?: StructsLogAttemptOutcome; + request_headers?: StructsHeaders; + response_body?: number[]; + response_headers?: StructsHeaders; + started_at?: string; + status_code?: number; + truncated?: boolean; +} + +export interface StructsLogsStats { + day?: string; + duration_ms_count?: number; + /** + * DurationMsSum / DurationMsCount carry the raw inputs for the mean + * delivery latency on this day (sum of per-row duration_ms over the + * rows that recorded one, and how many did). The mean is sum/count; + * keeping the two parts lets a caller aggregate days correctly + * (sum-of-sums / sum-of-counts) instead of averaging averages. + * Populated only on the turbostore stats path, like the retry fields. + */ + duration_ms_sum?: number; + failures?: number; + max_retries?: number; + received?: number; + /** + * Size fields are Turbostore-only recorded body + HTTP header totals. + * TotalBytes is RequestBytes + ResponseBytes. + */ + request_bytes?: number; + response_bytes?: number; + retried?: number; + retry_count?: number; + success?: number; + total_bytes?: number; +} + +export type StructsMetadata = Record; + +export interface StructsNewsEntry { + created_at?: string; + id?: string; + message?: string; + message_of_the_day?: boolean; + /** what date to show */ + timestamp?: number; + updated_at?: string; + url?: string; + visible?: boolean; +} + +export interface StructsNewsEntryCreateRequest { + /** what date to show */ + date?: string; + message?: string; + message_of_the_day?: boolean; + url?: string; + visible?: boolean; +} + +export interface StructsOrganizationInvite { + created_at?: string; + /** + * Email is stored lowercased and matched against the invitee + * account's email on accept. + */ + email?: string; + expires_at?: string; + id?: string; + /** InvitedBy is the account ID of the inviter (actor). */ + invited_by?: string; + org_account_id?: string; + role?: string; + status?: string; + updated_at?: string; +} + +export interface StructsOrganizationInviteDetails { + created_at?: string; + /** + * Email is stored lowercased and matched against the invitee + * account's email on accept. + */ + email?: string; + expires_at?: string; + id?: string; + /** InvitedBy is the account ID of the inviter (actor). */ + invited_by?: string; + invited_by_email?: string; + org_account_id?: string; + organization_description?: string; + organization_logo?: string; + organization_name?: string; + role?: string; + status?: string; + updated_at?: string; +} + +export interface StructsOrganizationMember { + created_at?: string; + id?: string; + /** InvitedBy is the account ID of the inviter (actor). */ + invited_by?: string; + member_account_id?: string; + org_account_id?: string; + /** admin/billing/member */ + role?: string; + updated_at?: string; +} + +export interface StructsOrganizationMemberDetails { + avatar_url?: string; + created_at?: string; + email?: string; + id?: string; + /** InvitedBy is the account ID of the inviter (actor). */ + invited_by?: string; + member_account_id?: string; + mfa_enabled?: boolean; + org_account_id?: string; + /** admin/billing/member */ + role?: string; + updated_at?: string; + username?: string; +} + +export interface StructsOrganizationMembershipDetails { + created_at?: string; + id?: string; + /** InvitedBy is the account ID of the inviter (actor). */ + invited_by?: string; + member_account_id?: string; + org_account_id?: string; + organization_description?: string; + organization_logo?: string; + organization_name?: string; + /** admin/billing/member */ + role?: string; + updated_at?: string; +} + +export interface StructsOutboundConsumer { + created_at?: string; + id?: string; + name?: string; + rate?: number; + updated_at?: string; +} + +export interface StructsOutboundEndpoint { + auto_disable?: boolean; + consecutive_failures?: number; + consumer?: string; + created_at?: string; + description?: string; + event_types?: string[]; + failing_since?: string; + function_id?: string; + headers?: Record; + id?: string; + previous_secret_expires_at?: string; + rate?: number; + state?: "active" | "failing" | "paused" | "disabled"; + /** seconds; zero uses OutboundDefaultTimeout */ + timeout?: number; + updated_at?: string; + url?: string; +} + +export interface StructsOutboundEventType { + created_at?: string; + deprecated?: boolean; + description?: string; + example?: object; + name?: string; + updated_at?: string; +} + +export interface StructsOutboundMessage { + consumer?: string; + created_at?: string; + endpoint_ids?: string[]; + enqueued_at?: string; + event_id?: string; + event_type?: string; + id?: string; + payload?: object; +} + +export interface StructsOutboundRecoveryTask { + created_at?: string; + endpoint_id?: string; + error?: string; + id?: string; + kind?: "retry" | "recover" | "replay-missing"; + message_id?: string; + processed?: number; + since?: string; + status?: "pending" | "running" | "completed" | "failed"; + until?: string; + updated_at?: string; +} + +export interface StructsOutput { + /** BucketID is a foreign key */ + bucket_id?: string; + created_at?: number; + created_by?: string; + cron_id?: string; + description?: string; + destination?: string; + /** Enable/disable output destinations */ + disabled?: boolean; + /** + * Durability configures long-period retries via the turbostore + * pending-retry index. See pkg/turbostore/design.md §5.6. + * Stored as JSON so we can extend without a schema migration. + */ + durability?: StructsDurabilityConfig; + /** + * FunctionID is used to indicate whethera code snippet should be used to + * modify this webhook + */ + function_id?: string; + /** + * Headers that will overwrite any existing headers + * from the incoming request + */ + headers?: StructsHeaders; + id?: string; + /** internal outputs will only be relayed by agents */ + internal?: boolean; + /** + * LockPath ensures that the request path cannot be changed from what is + * specified in the destination. For example if request is coming to /v1/webhooks/xxx/github-jenkins, + * with lock path 'false' and destination 'http://localhost:8080' it would go to http://localhost:8080/github-jenkins. + * However, with lock path 'true', it will be sent to 'http://localhost:8080' + */ + lock_path?: boolean; + name?: string; + /** + * ReplayMissing configures recovery of internal deliveries that were + * persisted as received but never reached an agent. When an agent connects, + * matching rows from the configured lookback window are sent directly to + * that connection, up to Limit. Stored as JSON so the policy can grow + * without a schema migration. + */ + replay_missing?: StructsReplayMissingConfig; + /** + * ResponseFunctionID names a function that runs AFTER delivery, once the + * destination's response (or the final delivery error) is known. It is + * invoked for every terminal outcome — success, or failure after all + * retries are exhausted — and receives the response status/body/headers + * (and delivery error) so it can implement custom logic such as alerting + * on a 5xx, a timeout, or an empty body. The response function cannot + * modify the response that was already returned to the sender. + */ + response_function_id?: string; + /** + * additional retries (after the first 3 times fail). Setting + * to -1 disables retries + */ + retries?: number; + rules?: RulesRules; + /** + * Throttle configures per-output throughput throttling. When enabled, + * the ingester/server stop delivering this output inline; webhooks are + * persisted (left in RequestStatusReceived) and enqueued into the + * turbostore throttle index, and the dispatcher's throttle controller + * dequeues them at the configured rate/concurrency. Stored as JSON so + * the schema can grow without a migration, same as Durability. + */ + throttle?: StructsThrottleConfig; + /** response timeout */ + timeout?: number; + /** + * Controls TLS verification of the certs for public + * webhooks + */ + tls_verification?: boolean; + updated_at?: number; +} + +export interface StructsPlanMeta { + /** Activity gates the account activity log (audit view) */ + activity?: boolean; + /** + * AgentTokens is the monthly account-agent and managed-Function model-token + * allowance (input + output); UnlimitedAgentTokens (-1) removes the cap. + */ + agent_tokens?: number; + /** + * AgentTokensExplicit records whether any metadata set the agent_tokens + * key itself (rather than the value falling back to a plan-family + * default). Admin runtime overrides only replace defaulted allowances, + * and comparing values cannot tell "explicitly granted 5M" from "basic + * default 5M" — this flag can. + */ + agent_tokens_explicit?: boolean; + agents?: number; + alert_policies?: number; + custom_hostnames?: boolean; + custom_subdomains?: boolean; + custom_tls_version?: boolean; + functions?: number; + https_tunnels?: boolean; + inputs?: number; + integration_configurations?: number; + large_webhooks?: boolean; + legacy_tls?: boolean; + logs_retention?: number; + managed_domains?: number; + outputs?: number; + overage?: number; + /** whether plan should be visible to public */ + public?: boolean; + reserved_domains?: number; + /** SamlSso gates self-service SAML SSO configuration (organization accounts) */ + saml_sso?: boolean; + sub_accounts?: number; + tls_tunnels?: boolean; + tokens?: number; + tunnels?: number; + webhooks?: number; +} + +export interface StructsPublishOutboundMessageRequest { + consumer?: string; + event_id?: string; + event_type?: string; + payload?: object; +} + +export interface StructsReplayMissingConfig { + /** Enabled toggles replay-on-connect for this output. */ + enabled?: boolean; + /** + * Limit bounds the scan itself: the newest Limit received rows in the + * lookback window are considered, and the eligible ones among them are + * replayed oldest-first. Rows skipped by connection filters or status + * re-checks still consume the budget — the bound is deliberately on rows + * scanned, not rows delivered, so a fully-filtered window cannot trigger + * an unbounded walk of the lookback. The server additionally + * clamps/validates this against its environment configured maximum. + */ + limit?: number; + /** + * Lookback selects received logs newer than now-Lookback. It is stored as + * a Go duration (nanoseconds in the REST JSON, consistent with durability + * and throttle duration fields). + */ + lookback?: TimeDuration; +} + +export interface StructsRequest { + body?: number[]; + body_modified?: boolean; + body_path?: string; + header?: Record; + header_modified?: boolean; + metadata?: Record; + method?: string; + method_modified?: boolean; + modified_body_path?: string; + path?: string; + path_modified?: boolean; + raw_query?: string; + raw_query_modified?: boolean; +} + +export interface StructsResponse { + body?: number[]; + body_path?: string; + header?: Record; + status?: number; +} + +export interface StructsRetryTask { + account_id?: string; + bucket_id?: string; + completed_at?: string; + created_at?: string; + /** Error carries a human-readable reason when Status is failed. */ + error?: string; + failed?: number; + id?: string; + /** + * Matched is the number of candidate logs found, Processed the + * number re-dispatched successfully, Failed the number that + * errored while being re-dispatched. + */ + matched?: number; + /** + * OutputID optionally narrows the operation to a single output. + * Empty means every output in the bucket. + */ + output_id?: string; + processed?: number; + /** + * Since/Until bound the candidate window by the log's received + * time. Until is optional (zero means "now" at run time). + */ + since?: string; + started_at?: string; + status?: StructsRetryTaskStatus; + /** + * Truncated is set when the candidate set hit the per-task cap and + * older matching logs in the window were left untouched. + */ + truncated?: boolean; + type?: StructsRetryTaskType; + until?: string; + updated_at?: string; +} + +export interface StructsSamlSsoOrg { + /** Which Webhook Relay account this SSO belongs to */ + account_id?: string; + created_at?: string; + deleted_at?: string; + details?: StructsDBSSODetails; + /** + * EmailAttributeName default is empty, but it could be set to something like + * "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" so we can look for it specifically + */ + email_attribute_name?: string; + entity_id?: string; + id?: string; + name?: string; + /** URL to SAML metadata */ + saml_metadata_url?: string; + updated_at?: string; +} + +export interface StructsSecretServiceConnection { + value?: string; +} + +export interface StructsServiceConnection { + account_id?: string; + aws_service_connection?: StructsAWSServiceConnection; + azure_service_connection?: StructsAzureServiceConnection; + created_at?: string; + error?: string; + gcp_service_connection?: StructsGCPServiceConnection; + /** ULID, starts with prefix "scn_" */ + id?: string; + last_checked?: string; + llm_service_connection?: StructsLLMServiceConnection; + name?: string; + retries?: number; + secret_service_connection?: StructsSecretServiceConnection; + service_type?: StructsServiceType; + status?: StructsServiceConnectionStatus; + updated_at?: string; +} + +export interface StructsServiceConnectionInput { + aws_s3_input?: StructsAWSS3Input; + aws_sns_input?: StructsAWSSNSInput; + aws_sqs_input?: StructsAWSSQSInput; + bucket_id?: string; + created_at?: string; + /** + * EmailAddress is the computed inbound address for email-type inputs + * ({local-part}@). It is populated at the API layer from the + * server's configured inbound domain and is never persisted. + */ + email_address?: string; + email_input?: StructsEmailInput; + error?: string; + function_id?: string; + gcp_gcs_input?: StructsGCPGCSInput; + gcp_pubsub_input?: StructsGCPPubSubInput; + id?: string; + name?: string; + service_connection_id?: string; + /** Used to load all inputs for a service connection */ + service_connection_input_type?: StructsServiceConnectionInputType; + status?: StructsServiceConnectionInputStatus; + updated_at?: string; +} + +export interface StructsServiceConnectionOutput { + aws_s3_output?: StructsAWSS3Output; + aws_sns_output?: StructsAWSSNSOutput; + aws_sqs_output?: StructsAWSSQSOutput; + bucket_id?: string; + created_at?: number; + discord_output?: StructsDiscordOutput; + function_id?: string; + gcp_gcs_output?: StructsGCPGCSOutput; + gcp_pubsub_output?: StructsGCPPubSubOutput; + id?: string; + name?: string; + service_connection_id?: string; + service_connection_output_type?: StructsServiceConnectionOutputType; + slack_output?: StructsSlackOutput; + updated_at?: number; +} + +export interface StructsSlackOutput { + webhook_url?: string; +} + +export interface StructsSubAccount { + account?: StructsAccount; + account_id?: string; + /** authentication type (regular/github/google) */ + auth_type?: StructsAccountAuthType; + avatar_url?: string; + created_at?: string; + /** + * CreatedBy attributes the sub-account to whoever created it (an org + * member's account ID; empty = the account owner). Used to revoke + * sub-accounts an org member created when they leave the org. + */ + created_by?: string; + deleted_at?: string; + email?: string; + failed_login_attempts?: number; + id?: string; + last_failed_login?: string; + last_login_at?: string; + mfa_enabled?: boolean; + saml_sso_org_id?: string; + /** If set, user will be asked to change the password after login */ + update_password?: boolean; + updated_at?: string; + username?: string; +} + +export interface StructsSubAccountCreateRequest { + auth_type?: StructsAccountAuthType; + email?: string; + username?: string; +} + +export interface StructsSubAccountCreateResponse { + password?: string; + sub_account?: StructsSubAccount; + username?: string; +} + +export interface StructsSubscriptionExtras { + description?: string; + metadata?: Record; + price_id?: string; + quantity?: number; + term?: StructsSubscriptionTerm; + unit_amount?: number; +} + +export interface StructsSubscriptionResponse { + amount?: number; + cancel_at_period_end?: boolean; + currency?: string; + current_period_end?: number; + current_period_start?: number; + customer_id?: string; + extras?: StructsSubscriptionExtras[]; + meta_data?: StructsPlanMeta; + plan?: string; + plan_id?: string; + status?: string; + subscription_id?: string; + trial_end?: number; + trial_start?: number; +} + +export interface StructsSuspiciousDetectionConfig { + high_score?: number; + high_signal_sets?: string[][]; + max_body_bytes?: number; + max_walk_depth?: number; + max_walk_nodes?: number; + min_score?: number; + realtime_enabled?: boolean; + rules?: StructsSuspiciousDetectionRule[]; +} + +export interface StructsSuspiciousDetectionRule { + category?: string; + description?: string; + enabled?: boolean; + id?: string; + key_groups?: StructsSuspiciousMatchGroup[]; + match_local_paths?: boolean; + value_groups?: StructsSuspiciousMatchGroup[]; + weight?: number; +} + +export interface StructsSuspiciousEvent { + account_id?: string; + bucket_id?: string; + category?: string; + client?: string; + created_at?: string; + id?: string; + input_id?: string; + log_id?: string; + occurred_at?: string; + occurrences?: number; + output_id?: string; + provider?: string; + review_note?: string; + reviewed_at?: string; + reviewed_by_account_id?: string; + reviewed_by_email?: string; + reviews?: StructsSuspiciousEventReview[]; + rule_version?: string; + score?: number; + severity?: string; + signals?: string[]; + status?: StructsSuspiciousEventStatus; + updated_at?: string; +} + +export interface StructsSuspiciousEventReview { + created_at?: string; + event_id?: string; + id?: string; + log_id?: string; + note?: string; + reviewer_account_id?: string; + reviewer_email?: string; + status?: StructsSuspiciousEventStatus; +} + +export interface StructsSuspiciousMatchGroup { + min_matches?: number; + /** + * Scope is "global" or "object". Object scope is valid for key groups + * and requires the terms to coexist in one JSON object. + */ + scope?: string; + terms?: string[]; +} + +export interface StructsThrottleConfig { + /** + * Deadline caps how long a queued webhook may wait for delivery, + * measured from when it was received. Zero falls through to + * DefaultThrottleDeadline. Webhooks older than the deadline are dropped + * (marked failed) instead of delivered. + */ + deadline?: TimeDuration; + /** Enabled toggles the whole feature for this output. */ + enabled?: boolean; + /** + * Interval is ThrottleIntervalSecond / Minute / Hour. Used only in + * ThrottleModeRate. + */ + interval?: string; + /** + * MaxConcurrent is the maximum number of in-flight deliveries. Used + * only in ThrottleModeConcurrency. 1 means serial delivery. + */ + max_concurrent?: number; + /** + * MaxQueueDepth bounds how many webhooks may sit in the queue for this + * output. Zero means unbounded. When exceeded, the ingester rejects + * new webhooks with HTTP 429. + */ + max_queue_depth?: number; + /** Mode is ThrottleModeRate or ThrottleModeConcurrency. */ + mode?: string; + /** + * Rate is the maximum number of deliveries per Interval. Used only in + * ThrottleModeRate. + */ + rate?: number; +} + +export interface StructsTokenPermissions { + /** + * Outbound restricts this token to outbound API operations only. Empty + * retains general API access. + */ + outbound?: "read" | "publish" | "manage"; + role?: "admin" | "billing" | "member" | "viewer"; +} + +export interface StructsTunnel { + account_id?: string; + /** + * Addr specifies TCP address server would listen on, it's required + * for TCP tunnels. + */ + addr?: string; + /** + * AgentID is used by the ingress controller and is + * randomly generated on startup. Once controller is running + * it will send periodic updates to indicate that it's still running. + */ + agent_id?: string; + auth?: StructsTunnelAuth; + created_at?: number; + /** + * CreatedBy is the account ID of the user who created the tunnel — + * for organization accounts this is the acting member. Empty means + * the account owner (agent auto-created tunnels leave it empty too). + */ + created_by?: string; + /** crypto types, used to issue lets encrypt certs */ + crypto?: string; + description?: string; + /** destination host, defaults to 127.0.0.1:8000 */ + destination?: string; + features?: StructsMetadata; + /** + * optional tunnel group, primarily used by the ingress to subscribe + * to specific group of tunnels + */ + group?: string; + /** + * tunnel's subdomain, random for free tier + * or named for paid subs + */ + host?: string; + id?: string; + ingress_rules?: StructsJSONB; + mode?: StructsTunnelMode; + /** tunnel name */ + name?: string; + /** tunnel protocol - http/tcp */ + protocol?: string; + /** optional tunnel region */ + region?: string; + updated_at?: number; +} + +export interface StructsTunnelAuth { + created_at?: number; + id?: string; + password?: string; + token?: string; + type?: StructsAuthType; + updated_at?: number; + username?: string; +} + +export interface StructsUpdateAPIKeyStatusRequest { + enabled?: boolean; +} + +export interface StructsUpdateAPIKeyStatusResponse { + enabled?: boolean; +} + +export interface StructsUpdateFunctionRequest { + account_id?: string; + driver?: string; + id?: string; + name?: string; + payload?: string; +} + +export interface StructsUsage { + account_id?: string; + /** agents currently connected */ + agents?: number; + created_at?: string; + inputs?: number; + outputs?: number; + /** + * Seats is the shared organization-seat usage: sub-accounts plus + * organization members and active pending invitations. On a personal + * account it is simply the number of sub-accounts. + */ + seats?: number; + tokens?: number; + tunnels?: number; + webhooks?: number; +} + +export interface StructsVariable { + account_id?: string; + created_at?: string; + function_id?: string; + key?: string; + updated_at?: string; + value?: string; +} + +export interface StructsWebhooksCount { + /** account that it belongs to */ + account_id?: string; + created_at?: string; + /** beginning of the day for which the webhooks are calculated */ + date?: string; + failed?: number; + id?: string; + /** Potential webhook statuses */ + preparing?: number; + received?: number; + rejected?: number; + /** + * Turbostore-only recorded body + HTTP header totals. Each delivery + * contributes once, so output fan-out is counted in proportion to the + * application-layer network traffic it creates. + */ + request_bytes?: number; + response_bytes?: number; + sent?: number; + stalled?: number; + /** daily/monthly term of the calculation */ + term?: StructsWebhooksCountTerm; + total_bytes?: number; + updated_at?: string; +} + +export interface TrafficstatsSnapshot { + client?: Record; + clientVersion?: Record; + contentType?: Record; + country?: Record; + flushedAt?: string; + hostname?: string; + ipVersion?: Record; + language?: Record; + method?: Record; + provider?: Record; + /** "|" */ + providerCountry?: Record; + /** "|" */ + providerEvent?: Record; + /** "|" */ + providerLanguage?: Record; + /** "|" */ + providerTls?: Record; + /** payload size bucket (from Content-Length) */ + size?: Record; + startedAt?: string; + tlsCipher?: Record; + tlsVersion?: Record; + total?: number; + version?: number; +} + +export type QueryParamsType = Record; +export type ResponseFormat = keyof Omit; + +export interface FullRequestParams extends Omit { + /** set parameter to `true` for call `securityWorker` for this request */ + secure?: boolean; + /** request path */ + path: string; + /** content type of request body */ + type?: ContentType; + /** query params */ + query?: QueryParamsType; + /** format of response (i.e. response.json() -> format: "json") */ + format?: ResponseFormat; + /** request body */ + body?: unknown; + /** base url */ + baseUrl?: string; + /** request cancellation token */ + cancelToken?: CancelToken; +} + +export type RequestParams = Omit< + FullRequestParams, + "body" | "method" | "query" | "path" +>; + +export interface ApiConfig { + baseUrl?: string; + baseApiParams?: Omit; + securityWorker?: ( + securityData: SecurityDataType | null, + ) => Promise | RequestParams | void; + customFetch?: typeof fetch; +} + +export interface HttpResponse + extends Response { + data: D; + error: E; +} + +type CancelToken = Symbol | string | number; + +export enum ContentType { + Json = "application/json", + JsonApi = "application/vnd.api+json", + FormData = "multipart/form-data", + UrlEncoded = "application/x-www-form-urlencoded", + Text = "text/plain", +} + +export class HttpClient { + public baseUrl: string = "https://my.webhookrelay.com"; + private securityData: SecurityDataType | null = null; + private securityWorker?: ApiConfig["securityWorker"]; + private abortControllers = new Map(); + private customFetch = (...fetchParams: Parameters) => + fetch(...fetchParams); + + private baseApiParams: RequestParams = { + credentials: "same-origin", + headers: {}, + redirect: "follow", + referrerPolicy: "no-referrer", + }; + + constructor(apiConfig: ApiConfig = {}) { + Object.assign(this, apiConfig); + } + + public setSecurityData = (data: SecurityDataType | null) => { + this.securityData = data; + }; + + protected encodeQueryParam(key: string, value: any) { + const encodedKey = encodeURIComponent(key); + return `${encodedKey}=${encodeURIComponent(typeof value === "number" ? value : `${value}`)}`; + } + + protected addQueryParam(query: QueryParamsType, key: string) { + return this.encodeQueryParam(key, query[key]); + } + + protected addArrayQueryParam(query: QueryParamsType, key: string) { + const value = query[key]; + return value.map((v: any) => this.encodeQueryParam(key, v)).join("&"); + } + + protected toQueryString(rawQuery?: QueryParamsType): string { + const query = rawQuery || {}; + const keys = Object.keys(query).filter( + (key) => "undefined" !== typeof query[key], + ); + return keys + .map((key) => + Array.isArray(query[key]) + ? this.addArrayQueryParam(query, key) + : this.addQueryParam(query, key), + ) + .join("&"); + } + + protected addQueryParams(rawQuery?: QueryParamsType): string { + const queryString = this.toQueryString(rawQuery); + return queryString ? `?${queryString}` : ""; + } + + private contentFormatters: Record any> = { + [ContentType.Json]: (input: any) => + input !== null && (typeof input === "object" || typeof input === "string") + ? JSON.stringify(input) + : input, + [ContentType.JsonApi]: (input: any) => + input !== null && (typeof input === "object" || typeof input === "string") + ? JSON.stringify(input) + : input, + [ContentType.Text]: (input: any) => + input !== null && typeof input !== "string" + ? JSON.stringify(input) + : input, + [ContentType.FormData]: (input: any) => { + if (input instanceof FormData) { + return input; + } + + return Object.keys(input || {}).reduce((formData, key) => { + const property = input[key]; + formData.append( + key, + property instanceof Blob + ? property + : typeof property === "object" && property !== null + ? JSON.stringify(property) + : `${property}`, + ); + return formData; + }, new FormData()); + }, + [ContentType.UrlEncoded]: (input: any) => this.toQueryString(input), + }; + + protected mergeRequestParams( + params1: RequestParams, + params2?: RequestParams, + ): RequestParams { + return { + ...this.baseApiParams, + ...params1, + ...(params2 || {}), + headers: { + ...(this.baseApiParams.headers || {}), + ...(params1.headers || {}), + ...((params2 && params2.headers) || {}), + }, + }; + } + + protected createAbortSignal = ( + cancelToken: CancelToken, + ): AbortSignal | undefined => { + if (this.abortControllers.has(cancelToken)) { + const abortController = this.abortControllers.get(cancelToken); + if (abortController) { + return abortController.signal; + } + return void 0; + } + + const abortController = new AbortController(); + this.abortControllers.set(cancelToken, abortController); + return abortController.signal; + }; + + public abortRequest = (cancelToken: CancelToken) => { + const abortController = this.abortControllers.get(cancelToken); + + if (abortController) { + abortController.abort(); + this.abortControllers.delete(cancelToken); + } + }; + + public request = async ({ + body, + secure, + path, + type, + query, + format, + baseUrl, + cancelToken, + ...params + }: FullRequestParams): Promise> => { + const secureParams = + ((typeof secure === "boolean" ? secure : this.baseApiParams.secure) && + this.securityWorker && + (await this.securityWorker(this.securityData))) || + {}; + const requestParams = this.mergeRequestParams(params, secureParams); + const queryString = query && this.toQueryString(query); + const payloadFormatter = this.contentFormatters[type || ContentType.Json]; + const responseFormat = format || requestParams.format; + + return this.customFetch( + `${baseUrl || this.baseUrl || ""}${path}${queryString ? `?${queryString}` : ""}`, + { + ...requestParams, + headers: { + ...(requestParams.headers || {}), + ...(type && type !== ContentType.FormData + ? { "Content-Type": type } + : {}), + }, + signal: + (cancelToken + ? this.createAbortSignal(cancelToken) + : requestParams.signal) || null, + body: + typeof body === "undefined" || body === null + ? null + : payloadFormatter(body), + }, + ).then(async (response) => { + const r = response as HttpResponse; + r.data = null as unknown as T; + r.error = null as unknown as E; + + const responseToParse = responseFormat ? response.clone() : response; + const data = !responseFormat + ? r + : await responseToParse[responseFormat]() + .then((data) => { + if (r.ok) { + r.data = data; + } else { + r.error = data; + } + return r; + }) + .catch((e) => { + r.error = e; + return r; + }); + + if (cancelToken) { + this.abortControllers.delete(cancelToken); + } + + if (!response.ok) throw data; + return data; + }); }; +} + +/** + * @title WebhookRelay API reference + * @version 0.1 + * @baseUrl https://my.webhookrelay.com + * @contact WebhookRelay support (https://my.webhookrelay.com/) + * + * This is the WebhookRelay API. + */ +export class Api< + SecurityDataType extends unknown, +> extends HttpClient { + v1 = { + /** + * @description Get the effective account (the organization account when acting through the X-Org-ID override) + * + * @tags account + * @name AccountList + * @summary Get current account + * @request GET:/v1/account + * @secure + */ + accountList: (params: RequestParams = {}) => + this.request({ + path: `/v1/account`, + method: "GET", + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Update account settings, including quota notification thresholds and up to 10 additional validated email recipients, plus the organization profile. Organization fields are optional. Converting to an organization is one-way (the flag can never be unset) and only the account owner can do it — not org admins acting through the override. The logo must be a small data:image/...;base64 payload. + * + * @tags account + * @name AccountUpdate + * @summary Update account + * @request PUT:/v1/account + * @secure + */ + accountUpdate: ( + account: ApiUpdateAccountRequest, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/account`, + method: "PUT", + body: account, + secure: true, + type: ContentType.Json, + ...params, + }), + + /** + * @description Get the account API key. If no key exists, a new one will be generated. + * + * @tags account + * @name AccountApiKeyList + * @summary Get account API key + * @request GET:/v1/account/api-key + * @secure + */ + accountApiKeyList: (params: RequestParams = {}) => + this.request({ + path: `/v1/account/api-key`, + method: "GET", + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Generate a new API key for the account, replacing the existing one. + * + * @tags account + * @name AccountApiKeyCreate + * @summary Regenerate account API key + * @request POST:/v1/account/api-key + * @secure + */ + accountApiKeyCreate: (params: RequestParams = {}) => + this.request({ + path: `/v1/account/api-key`, + method: "POST", + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Enable or disable the account API key without regenerating it. + * + * @tags account + * @name AccountApiKeyUpdate + * @summary Enable or disable account API key + * @request PUT:/v1/account/api-key + * @secure + */ + accountApiKeyUpdate: ( + request: StructsUpdateAPIKeyStatusRequest, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/account/api-key`, + method: "PUT", + body: request, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Audit entries for the effective account: who did what (owners, org members, sub-accounts). Restricted to the owner and org admins. + * + * @tags account + * @name AccountAuditList + * @summary Account activity log + * @request GET:/v1/account/audit + * @secure + */ + accountAuditList: ( + query?: { + /** Page size (default 50, max 200) */ + limit?: number; + /** Offset */ + offset?: number; + /** Comma-separated resource kinds */ + filter?: string; + /** Filter by acting user's username */ + username?: string; + /** Filter by action (created/updated/deleted/...) */ + action?: string; + /** Filter by surface: mcp (an MCP client) or agent (the agent chat) */ + source?: string; + }, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/account/audit`, + method: "GET", + query: query, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description List everyone who can have created resources on the effective account — the owner, organization members and sub-accounts. Used by the dashboard to resolve created_by attribution. + * + * @tags account + * @name AccountCreatorsList + * @summary List account creator identities + * @request GET:/v1/account/creators + * @secure + */ + accountCreatorsList: (params: RequestParams = {}) => + this.request({ + path: `/v1/account/creators`, + method: "GET", + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Disable MFA after validating a current authenticator token. + * + * @tags account + * @name AccountMfaDelete + * @summary Disable MFA + * @request DELETE:/v1/account/mfa + * @secure + */ + accountMfaDelete: ( + request: ApiMfaConfirmRequest, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/account/mfa`, + method: "DELETE", + body: request, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Enable MFA after validating a token from the pending TOTP secret. + * + * @tags account + * @name AccountMfaConfirmCreate + * @summary Confirm MFA setup + * @request POST:/v1/account/mfa/confirm + * @secure + */ + accountMfaConfirmCreate: ( + request: ApiMfaConfirmRequest, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/account/mfa/confirm`, + method: "POST", + body: request, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Generate a TOTP secret and QR code for the authenticated account or sub-account. + * + * @tags account + * @name AccountMfaSetupCreate + * @summary Start MFA setup + * @request POST:/v1/account/mfa/setup + * @secure + */ + accountMfaSetupCreate: (params: RequestParams = {}) => + this.request({ + path: `/v1/account/mfa/setup`, + method: "POST", + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description List all Webhook Relay accounts for platform administration and account selection. + * + * @tags admin + * @name AccountsList + * @summary List accounts (admin) + * @request GET:/v1/accounts + * @secure + */ + accountsList: (params: RequestParams = {}) => + this.request({ + path: `/v1/accounts`, + method: "GET", + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Manually set the suspended flag on every bucket belonging to any account. Manual suspension is rejected while suspend protection is enabled. + * + * @tags admin, accounts + * @name AdminAccountsBucketsSuspensionUpdate + * @summary Suspend or unsuspend all account buckets (admin) + * @request PUT:/v1/admin/accounts/{id}/buckets/suspension + * @secure + */ + adminAccountsBucketsSuspensionUpdate: ( + id: string, + suspension: ApiAdminBucketSuspensionUpdateRequest, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/admin/accounts/${id}/buckets/suspension`, + method: "PUT", + body: suspension, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Change an account's login email and/or authentication type. Authentication type is limited to regular, github, or google; SAML identities remain managed through SSO configuration. Email verification state is preserved. + * + * @tags admin + * @name AdminAccountsIdentityUpdate + * @summary Update account sign-in identity (admin) + * @request PUT:/v1/admin/accounts/{id}/identity + * @secure + */ + adminAccountsIdentityUpdate: ( + id: string, + identity: ApiAdminAccountIdentityUpdateRequest, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/admin/accounts/${id}/identity`, + method: "PUT", + body: identity, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Get stored subscription status, billing term dates, plan and subscription metadata, effective entitlements, extras and suspension protection for any account. + * + * @tags admin, accounts + * @name AdminAccountsStatusList + * @summary Get account subscription status (admin) + * @request GET:/v1/admin/accounts/{id}/status + * @secure + */ + adminAccountsStatusList: (id: string, params: RequestParams = {}) => + this.request({ + path: `/v1/admin/accounts/${id}/status`, + method: "GET", + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Enable or disable the manual override that prevents automated quota and billing paths from suspending any account's buckets. + * + * @tags admin, accounts + * @name AdminAccountsSuspendProtectionUpdate + * @summary Update account suspend protection (admin) + * @request PUT:/v1/admin/accounts/{id}/suspend-protection + * @secure + */ + adminAccountsSuspendProtectionUpdate: ( + id: string, + protection: ApiAdminSuspendProtectionUpdateRequest, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/admin/accounts/${id}/suspend-protection`, + method: "PUT", + body: protection, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Accounts created at or after `created_after`, oldest first, for reconciling a registration feed. Registration identity only — no billing metadata or account-owned resources. + * + * @tags admin, organizations + * @name AdminAccountsRecentList + * @summary List recent registrations (admin) + * @request GET:/v1/admin/accounts/recent + * @secure + */ + adminAccountsRecentList: ( + query: { + /** RFC 3339 timestamp; accounts created at or after this instant */ + created_after: string; + /** + * Maximum results (default 100, max 500) + * @min 1 + * @max 500 + */ + limit?: number; + /** + * Offset into the result set + * @min 0 + */ + offset?: number; + }, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/admin/accounts/recent`, + method: "GET", + query: query, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Search accounts by email or username prefix, or by exact account ID. Results are bounded for server-backed admin account selectors. + * + * @tags admin, organizations + * @name AdminAccountsSearchList + * @summary Search accounts (admin) + * @request GET:/v1/admin/accounts/search + * @secure + */ + adminAccountsSearchList: ( + query: { + /** + * Email/username prefix or exact account ID + * @minLength 2 + */ + query: string; + /** + * Maximum results (default 20, max 50) + * @min 1 + * @max 50 + */ + limit?: number; + }, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/admin/accounts/search`, + method: "GET", + query: query, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Every conversation across accounts with its session aggregates, newest activity first; filter by account_id, stop_cause, or rated=up|down|any + * + * @tags admin + * @name AdminAgentConversationsList + * @summary List agent conversations (admin) + * @request GET:/v1/admin/agent/conversations + * @secure + */ + adminAgentConversationsList: ( + query?: { + /** Only this account */ + account_id?: string; + /** Only conversations whose last turn ended with this cause */ + stop_cause?: string; + /** up, down or any: only conversations with that feedback */ + rated?: string; + /** any, approved, denied, expired, canceled or pending: only conversations whose destructive calls asked the user */ + approvals?: string; + /** Page size (default 50, max 200) */ + limit?: number; + /** Page offset */ + offset?: number; + }, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/admin/agent/conversations`, + method: "GET", + query: query, + secure: true, + format: "json", + ...params, + }), + + /** + * @description One conversation with its stored transcript, latest 500 tool calls and inferences, latest 200 prompts, feedback and approvals; truncated flags identify omitted earlier evidence + * + * @tags admin + * @name AdminAgentConversationsDetail + * @summary Agent conversation detail (admin) + * @request GET:/v1/admin/agent/conversations/{id} + * @secure + */ + adminAgentConversationsDetail: (id: string, params: RequestParams = {}) => + this.request({ + path: `/v1/admin/agent/conversations/${id}`, + method: "GET", + secure: true, + format: "json", + ...params, + }), + + /** + * @description The runtime-adjustable agent limits: stored overrides, deployed defaults and the effective values. Overrides live in the database so they can be tuned without a deployment. + * + * @tags admin + * @name AdminAgentLimitsList + * @summary Agent limit overrides (admin) + * @request GET:/v1/admin/agent/limits + * @secure + */ + adminAgentLimitsList: (params: RequestParams = {}) => + this.request({ + path: `/v1/admin/agent/limits`, + method: "GET", + secure: true, + format: "json", + ...params, + }), + + /** + * @description Replaces the stored override set. A zero or omitted field clears that override back to the deployed default. Every replica picks the change up within seconds. + * + * @tags admin + * @name AdminAgentLimitsUpdate + * @summary Update agent limit overrides (admin) + * @request PUT:/v1/admin/agent/limits + * @secure + */ + adminAgentLimitsUpdate: ( + body: ApiAdminAgentLimitsUpdateRequest, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/admin/agent/limits`, + method: "PUT", + body: body, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description All-time cross-account totals and latest-session stop causes, plus a UTC daily activity series for the last N days counting conversation creation, prompt settlement, and tool-call timestamps + * + * @tags admin + * @name AdminAgentStatsList + * @summary Agent usage totals (admin) + * @request GET:/v1/admin/agent/stats + * @secure + */ + adminAgentStatsList: ( + query?: { + /** Length of the daily series (default 30) */ + days?: number; + }, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/admin/agent/stats`, + method: "GET", + query: query, + secure: true, + format: "json", + ...params, + }), + + /** + * @description Get list of all connected clients across all accounts from the state tracker service. + * + * @tags admin + * @name AdminConnectedClientsList + * @summary Get all connected clients (admin) + * @request GET:/v1/admin/connected-clients + * @secure + */ + adminConnectedClientsList: (params: RequestParams = {}) => + this.request({ + path: `/v1/admin/connected-clients`, + method: "GET", + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Canonical schema for Stripe plan/subscription metadata used by enterprise deals. Numeric limits and boolean capabilities include labels, descriptions, groups, units, aliases, and validation bounds. + * + * @tags admin, enterprise-crm + * @name AdminEnterpriseDealsMetadataSchemaList + * @summary List supported enterprise entitlement metadata fields (admin) + * @request GET:/v1/admin/enterprise-deals/metadata-schema + * @secure + */ + adminEnterpriseDealsMetadataSchemaList: (params: RequestParams = {}) => + this.request({ + path: `/v1/admin/enterprise-deals/metadata-schema`, + method: "GET", + secure: true, + format: "json", + ...params, + }), + + /** + * @description List every active or inactive organization account with owner identity and member/sub-account counts. + * + * @tags admin, organizations + * @name AdminOrgsList + * @summary List organizations (admin) + * @request GET:/v1/admin/orgs + * @secure + */ + adminOrgsList: (params: RequestParams = {}) => + this.request({ + path: `/v1/admin/orgs`, + method: "GET", + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Get an organization account together with its member roster and active sub-accounts. + * + * @tags admin, organizations + * @name AdminOrgsDetail + * @summary Get organization details (admin) + * @request GET:/v1/admin/orgs/{id} + * @secure + */ + adminOrgsDetail: (id: string, params: RequestParams = {}) => + this.request({ + path: `/v1/admin/orgs/${id}`, + method: "GET", + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Convert an individual account to an organization, or update an existing organization's name and description. Conversion is one-way. Admin operations bypass self-service seat limits. + * + * @tags admin, organizations + * @name AdminOrgsUpdate + * @summary Convert or update organization (admin) + * @request PUT:/v1/admin/orgs/{id} + * @secure + */ + adminOrgsUpdate: ( + id: string, + organization: ApiAdminOrganizationUpdateRequest, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/admin/orgs/${id}`, + method: "PUT", + body: organization, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Manually set the suspended flag on every organization bucket. Manual suspension is rejected while suspend protection is enabled. + * + * @tags admin, organizations + * @name AdminOrgsBucketsSuspensionUpdate + * @summary Suspend or unsuspend all organization buckets (admin) + * @request PUT:/v1/admin/orgs/{id}/buckets/suspension + * @secure + */ + adminOrgsBucketsSuspensionUpdate: ( + id: string, + suspension: ApiAdminBucketSuspensionUpdateRequest, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/admin/orgs/${id}/buckets/suspension`, + method: "PUT", + body: suspension, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Directly link an existing active account to an organization with an assignable role. No invitation acceptance is required and admin operations bypass self-service seat limits. + * + * @tags admin, organizations + * @name AdminOrgsMembersCreate + * @summary Add organization member (admin) + * @request POST:/v1/admin/orgs/{id}/members + * @secure + */ + adminOrgsMembersCreate: ( + id: string, + member: ApiAdminOrganizationMemberCreateRequest, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/admin/orgs/${id}/members`, + method: "POST", + body: member, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Remove a member and revoke organization-bound access tokens and sub-accounts created by that member. + * + * @tags admin, organizations + * @name AdminOrgsMembersDelete + * @summary Remove organization member (admin) + * @request DELETE:/v1/admin/orgs/{id}/members/{memberID} + * @secure + */ + adminOrgsMembersDelete: ( + id: string, + memberId: string, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/admin/orgs/${id}/members/${memberId}`, + method: "DELETE", + secure: true, + type: ContentType.Json, + ...params, + }), + + /** + * @description Change an existing organization member's role and update the role captured on organization-bound access tokens. + * + * @tags admin, organizations + * @name AdminOrgsMembersUpdate + * @summary Update organization member role (admin) + * @request PUT:/v1/admin/orgs/{id}/members/{memberID} + * @secure + */ + adminOrgsMembersUpdate: ( + id: string, + memberId: string, + member: ApiAdminOrganizationMemberUpdateRequest, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/admin/orgs/${id}/members/${memberId}`, + method: "PUT", + body: member, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Get stored subscription status, billing term dates, plan and subscription metadata, effective entitlements, extras and suspension protection for an organization account. + * + * @tags admin, organizations + * @name AdminOrgsStatusList + * @summary Get organization subscription status (admin) + * @request GET:/v1/admin/orgs/{id}/status + * @secure + */ + adminOrgsStatusList: (id: string, params: RequestParams = {}) => + this.request({ + path: `/v1/admin/orgs/${id}/status`, + method: "GET", + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Create a regular, GitHub, or Google sub-account directly under an organization. Regular accounts return a one-time password. Admin operations bypass self-service seat limits. + * + * @tags admin, organizations + * @name AdminOrgsSubAccountsCreate + * @summary Create organization sub-account (admin) + * @request POST:/v1/admin/orgs/{id}/sub-accounts + * @secure + */ + adminOrgsSubAccountsCreate: ( + id: string, + subAccount: ApiAdminSubAccountCreateRequest, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/admin/orgs/${id}/sub-accounts`, + method: "POST", + body: subAccount, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Delete a sub-account from the specified organization and immediately revoke its access. + * + * @tags admin, organizations + * @name AdminOrgsSubAccountsDelete + * @summary Delete organization sub-account (admin) + * @request DELETE:/v1/admin/orgs/{id}/sub-accounts/{subID} + * @secure + */ + adminOrgsSubAccountsDelete: ( + id: string, + subId: string, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/admin/orgs/${id}/sub-accounts/${subId}`, + method: "DELETE", + secure: true, + type: ContentType.Json, + ...params, + }), + + /** + * @description Generate and return a new one-time password for a regular organization sub-account. + * + * @tags admin, organizations + * @name AdminOrgsSubAccountsResetPasswordCreate + * @summary Reset organization sub-account password (admin) + * @request POST:/v1/admin/orgs/{id}/sub-accounts/{subID}/reset-password + * @secure + */ + adminOrgsSubAccountsResetPasswordCreate: ( + id: string, + subId: string, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/admin/orgs/${id}/sub-accounts/${subId}/reset-password`, + method: "POST", + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Enable or disable the manual override that prevents automated quota and billing paths from suspending the organization's buckets. + * + * @tags admin, organizations + * @name AdminOrgsSuspendProtectionUpdate + * @summary Update organization suspend protection (admin) + * @request PUT:/v1/admin/orgs/{id}/suspend-protection + * @secure + */ + adminOrgsSuspendProtectionUpdate: ( + id: string, + protection: ApiAdminSuspendProtectionUpdateRequest, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/admin/orgs/${id}/suspend-protection`, + method: "PUT", + body: protection, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Get current billing-term usage and effective plan limits for an organization account. Live agents are reported as zero when State Tracker is unavailable; persisted usage remains available. + * + * @tags admin, organizations + * @name AdminOrgsUsageList + * @summary Get organization usage (admin) + * @request GET:/v1/admin/orgs/{id}/usage + * @secure + */ + adminOrgsUsageList: (id: string, params: RequestParams = {}) => + this.request({ + path: `/v1/admin/orgs/${id}/usage`, + method: "GET", + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Lists real-time detector findings. Findings contain sanitized signal names and a reference to the canonical Turbostore webhook; no payload is copied into the review table. + * + * @tags admin, security + * @name AdminSuspiciousEventsList + * @summary List suspicious webhook findings + * @request GET:/v1/admin/suspicious-events + * @secure + */ + adminSuspiciousEventsList: ( + query?: { + /** Exact account ID */ + account_id?: string; + /** Review status: open, confirmed, dismissed */ + status?: string; + /** Severity: medium or high */ + severity?: string; + /** Finding category */ + category?: string; + /** Page size */ + limit?: number; + /** Offset */ + offset?: number; + }, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/admin/suspicious-events`, + method: "GET", + query: query, + secure: true, + format: "json", + ...params, + }), + + /** + * No description + * + * @tags admin, security + * @name AdminSuspiciousEventsDetail + * @summary Get a suspicious webhook finding + * @request GET:/v1/admin/suspicious-events/{id} + * @secure + */ + adminSuspiciousEventsDetail: (id: string, params: RequestParams = {}) => + this.request({ + path: `/v1/admin/suspicious-events/${id}`, + method: "GET", + secure: true, + format: "json", + ...params, + }), + + /** + * @description Marks a finding confirmed, dismissed, or reopens it. This does not suspend the account. + * + * @tags admin, security + * @name AdminSuspiciousEventsReviewUpdate + * @summary Review a suspicious webhook finding + * @request PUT:/v1/admin/suspicious-events/{id}/review + * @secure + */ + adminSuspiciousEventsReviewUpdate: ( + id: string, + review: ApiSuspiciousEventReviewRequest, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/admin/suspicious-events/${id}/review`, + method: "PUT", + body: review, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Loads the canonical webhook directly from Turbostore for admin review. There is no ClickHouse fallback. + * + * @tags admin, security + * @name AdminSuspiciousEventsWebhookList + * @summary Get the Turbostore webhook for a suspicious finding + * @request GET:/v1/admin/suspicious-events/{id}/webhook + * @secure + */ + adminSuspiciousEventsWebhookList: ( + id: string, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/admin/suspicious-events/${id}/webhook`, + method: "GET", + secure: true, + format: "json", + ...params, + }), + + /** + * @description Runs only when called by an admin. The hunt is account-, bucket-, time-, and page-bounded and never reads ClickHouse. Continue with next_cursor until it is empty. + * + * @tags admin, security + * @name AdminSuspiciousEventsHuntCreate + * @summary Scan one bounded Turbostore history page for suspicious webhooks + * @request POST:/v1/admin/suspicious-events/hunt + * @secure + */ + adminSuspiciousEventsHuntCreate: ( + hunt: ApiSuspiciousHuntRequest, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/admin/suspicious-events/hunt`, + method: "POST", + body: hunt, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Returns the effective database-backed rule set used for real-time detection and explicit historical hunts. + * + * @tags admin, security + * @name AdminSuspiciousEventsRulesList + * @summary Get suspicious webhook detection rules + * @request GET:/v1/admin/suspicious-events/rules + * @secure + */ + adminSuspiciousEventsRulesList: (params: RequestParams = {}) => + this.request({ + path: `/v1/admin/suspicious-events/rules`, + method: "GET", + secure: true, + format: "json", + ...params, + }), + + /** + * @description Validates and atomically replaces the detector rule set. Real-time processes refresh it within 15 seconds; no historical scan is started. + * + * @tags admin, security + * @name AdminSuspiciousEventsRulesUpdate + * @summary Replace suspicious webhook detection rules + * @request PUT:/v1/admin/suspicious-events/rules + * @secure + */ + adminSuspiciousEventsRulesUpdate: ( + settings: ApiSuspiciousDetectionSettingsRequest, + params: RequestParams = {}, + ) => + this.request< + ApiSuspiciousDetectionSettingsResponse, + StructsErrorResponse + >({ + path: `/v1/admin/suspicious-events/rules`, + method: "PUT", + body: settings, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Per-ingester-replica cumulative counters of incoming webhook traffic: provider fingerprint, client family/language, negotiated TLS version/cipher, sender country. No payloads or identifiers are collected. + * + * @tags admin + * @name AdminTrafficStatsList + * @summary Get aggregate incoming webhook traffic statistics (admin) + * @request GET:/v1/admin/traffic-stats + * @secure + */ + adminTrafficStatsList: (params: RequestParams = {}) => + this.request({ + path: `/v1/admin/traffic-stats`, + method: "GET", + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Returns successfully sent quota notifications newest first, including account identity, threshold, usage/quota at send time, plan, and billing period. Filter by account_id for the account-details Usage alerts tab. + * + * @tags admin + * @name AdminUsageAlertsList + * @summary List sent quota usage alerts (admin) + * @request GET:/v1/admin/usage-alerts + * @secure + */ + adminUsageAlertsList: ( + query?: { + /** Filter to one account ID */ + account_id?: string; + /** + * Page size (default 50, max 200) + * @min 1 + * @max 200 + */ + limit?: number; + /** + * Page offset + * @min 0 + */ + offset?: number; + }, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/admin/usage-alerts`, + method: "GET", + query: query, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Paginated cross-account bucket inventory with each bucket's inputs (incl. transformation functions) and outputs (destination URL, classified destination provider, type, functions). Answers "what are customers wiring the service up to". + * + * @tags admin + * @name AdminUsageBucketsList + * @summary List buckets across all accounts (admin) + * @request GET:/v1/admin/usage/buckets + * @secure + */ + adminUsageBucketsList: ( + query?: { + /** Filter to one account */ + account_id?: string; + /** + * Page size (default 100, max 500) + * @min 1 + * @max 500 + */ + limit?: number; + /** + * Page offset + * @min 0 + */ + offset?: number; + }, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/admin/usage/buckets`, + method: "GET", + query: query, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Paginated cross-account output inventory: destination URL (basic-auth passwords masked), classified destination provider, internal/public type and attached functions, with bucket and account attribution. Use destination=substr to answer e.g. "who forwards to jenkins". Note destination_provider classifies the destination ADDRESS (jenkins, slack, localhost, private-network, ...) and is independent of the internal flag, which is the delivery mode: a private-IP destination delivered server-side shows internal=false with destination_provider=private-network. + * + * @tags admin + * @name AdminUsageOutputsList + * @summary List outputs across all accounts (admin) + * @request GET:/v1/admin/usage/outputs + * @secure + */ + adminUsageOutputsList: ( + query?: { + /** Filter to one account */ + account_id?: string; + /** Case-insensitive destination URL substring filter */ + destination?: string; + /** + * Page size (default 100, max 500) + * @min 1 + * @max 500 + */ + limit?: number; + /** + * Page offset + * @min 0 + */ + offset?: number; + }, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/admin/usage/outputs`, + method: "GET", + query: query, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Fleet-level classification of every output's destination (jenkins, slack, ms-teams, localhost, unknown, ...) plus internal/disabled/function counts. The inbound-side counterpart (which providers send us traffic, incl. fingerprinted event types) is /v1/admin/traffic-stats. + * + * @tags admin + * @name AdminUsageSummaryList + * @summary Aggregate destination usage across all outputs (admin) + * @request GET:/v1/admin/usage/summary + * @secure + */ + adminUsageSummaryList: (params: RequestParams = {}) => + this.request({ + path: `/v1/admin/usage/summary`, + method: "GET", + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Returns a dense month-by-month series of inbound webhook requests. A webhook is counted once when received, independently of how many outputs it is delivered to. Defaults to the current month and previous 11 calendar months. + * + * @tags admin + * @name AdminUsageWebhooksList + * @summary Get monthly webhook volume for an account (admin) + * @request GET:/v1/admin/usage/webhooks + * @secure + */ + adminUsageWebhooksList: ( + query: { + /** Account ID */ + account_id: string; + /** From date (YYYY-MM-DD); defaults to 11 months before the current month */ + from?: string; + /** To date (YYYY-MM-DD); defaults to today */ + to?: string; + }, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/admin/usage/webhooks`, + method: "GET", + query: query, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Whether the account agent is enabled on this server, which model answers, and what the caller's grant permits + * + * @tags agent + * @name AgentList + * @summary Agent status + * @request GET:/v1/agent + * @secure + */ + agentList: (params: RequestParams = {}) => + this.request({ + path: `/v1/agent`, + method: "GET", + secure: true, + format: "json", + ...params, + }), + + /** + * @description Conversations of the authenticated account, newest activity first; filter by the page they were opened from + * + * @tags agent + * @name AgentConversationsList + * @summary List agent conversations + * @request GET:/v1/agent/conversations + * @secure + */ + agentConversationsList: ( + query?: { + /** Page kind the conversation was opened from (function, bucket, account) */ + context_kind?: string; + /** ID of that page's resource */ + context_id?: string; + }, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/agent/conversations`, + method: "GET", + query: query, + secure: true, + format: "json", + ...params, + }), + + /** + * @description Open a conversation, optionally bound to the page it was started from (a function context must be the caller's own function) + * + * @tags agent + * @name AgentConversationsCreate + * @summary Create agent conversation + * @request POST:/v1/agent/conversations + * @secure + */ + agentConversationsCreate: ( + conversation: ApiAgentConversationRequest, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/agent/conversations`, + method: "POST", + body: conversation, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Deletes the conversation and its stored transcript + * + * @tags agent + * @name AgentConversationsDelete + * @summary Delete agent conversation + * @request DELETE:/v1/agent/conversations/{id} + * @secure + */ + agentConversationsDelete: (id: string, params: RequestParams = {}) => + this.request({ + path: `/v1/agent/conversations/${id}`, + method: "DELETE", + secure: true, + format: "json", + ...params, + }), + + /** + * @description The conversation, its stored transcript, and whether a turn is running on any replica + * + * @tags agent + * @name AgentConversationsDetail + * @summary Get agent conversation + * @request GET:/v1/agent/conversations/{id} + * @secure + */ + agentConversationsDetail: (id: string, params: RequestParams = {}) => + this.request({ + path: `/v1/agent/conversations/${id}`, + method: "GET", + secure: true, + format: "json", + ...params, + }), + + /** + * No description + * + * @tags agent + * @name AgentConversationsUpdate + * @summary Rename agent conversation + * @request PUT:/v1/agent/conversations/{id} + * @secure + */ + agentConversationsUpdate: ( + id: string, + conversation: ApiAgentConversationRequest, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/agent/conversations/${id}`, + method: "PUT", + body: conversation, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Answers an approval_requested event: the paused call runs with the scope it lacked. With remember the scope is also recorded on the conversation, so later calls needing it do not ask. Limited by the caller's role. 202 when the answer was broadcast to the replica running the turn. + * + * @tags agent + * @name AgentConversationsApproveCreate + * @summary Allow a paused destructive tool call + * @request POST:/v1/agent/conversations/{id}/approve + * @secure + */ + agentConversationsApproveCreate: ( + id: string, + decision: ApiAgentApprovalRequest, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/agent/conversations/${id}/approve`, + method: "POST", + body: decision, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Stops the current turn; completed tool results are kept. 202 when the request was broadcast to the replica running the turn. + * + * @tags agent + * @name AgentConversationsCancelCreate + * @summary Cancel the running agent turn + * @request POST:/v1/agent/conversations/{id}/cancel + * @secure + */ + agentConversationsCancelCreate: (id: string, params: RequestParams = {}) => + this.request({ + path: `/v1/agent/conversations/${id}/cancel`, + method: "POST", + secure: true, + format: "json", + ...params, + }), + + /** + * @description Answers an approval_requested event: the call does not run and the agent is told, with the optional text as the reason. 202 when the answer was broadcast to the replica running the turn. + * + * @tags agent + * @name AgentConversationsDenyCreate + * @summary Decline a paused destructive tool call + * @request POST:/v1/agent/conversations/{id}/deny + * @secure + */ + agentConversationsDenyCreate: ( + id: string, + decision: ApiAgentApprovalRequest, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/agent/conversations/${id}/deny`, + method: "POST", + body: decision, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description The thumbs up/down ratings the account gave messages in a conversation + * + * @tags agent + * @name AgentConversationsFeedbackList + * @summary List message feedback + * @request GET:/v1/agent/conversations/{id}/feedback + * @secure + */ + agentConversationsFeedbackList: (id: string, params: RequestParams = {}) => + this.request({ + path: `/v1/agent/conversations/${id}/feedback`, + method: "GET", + secure: true, + format: "json", + ...params, + }), + + /** + * @description Records a thumbs up or down on one assistant message (by its index in the stored transcript); rating the same message again replaces the earlier rating + * + * @tags agent + * @name AgentConversationsFeedbackCreate + * @summary Rate an assistant message + * @request POST:/v1/agent/conversations/{id}/feedback + * @secure + */ + agentConversationsFeedbackCreate: ( + id: string, + feedback: ApiAgentFeedbackRequest, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/agent/conversations/${id}/feedback`, + method: "POST", + body: feedback, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * No description + * + * @tags agent + * @name AgentConversationsFeedbackDelete + * @summary Remove a message rating + * @request DELETE:/v1/agent/conversations/{id}/feedback/{index} + * @secure + */ + agentConversationsFeedbackDelete: ( + id: string, + index: number, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/agent/conversations/${id}/feedback/${index}`, + method: "DELETE", + secure: true, + format: "json", + ...params, + }), + + /** + * @description Starts one turn and streams its events as server-sent events (text/event-stream): meta, text_delta, text, tool_call, tool_result, refused, usage, done. The turn keeps running if the client disconnects; re-attach with GET /v1/agent/conversations/{id}/stream. The prompt id is an idempotency key. + * + * @tags agent + * @name AgentConversationsMessagesCreate + * @summary Send a message to the agent + * @request POST:/v1/agent/conversations/{id}/messages + * @secure + */ + agentConversationsMessagesCreate: ( + id: string, + message: ApiAgentMessageRequest, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/agent/conversations/${id}/messages`, + method: "POST", + body: message, + secure: true, + type: ContentType.Json, + ...params, + }), + + /** + * @description Cancels the current work and queues a replacement instruction on the same conversation + * + * @tags agent + * @name AgentConversationsSteerCreate + * @summary Steer the running agent turn + * @request POST:/v1/agent/conversations/{id}/steer + * @secure + */ + agentConversationsSteerCreate: ( + id: string, + control: ApiAgentControlRequest, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/agent/conversations/${id}/steer`, + method: "POST", + body: control, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Re-joins a turn already running on any replica as server-sent events: the events so far are replayed, then followed live. 404 when nothing is running (read the stored transcript instead). + * + * @tags agent + * @name AgentConversationsStreamList + * @summary Attach to a running agent turn + * @request GET:/v1/agent/conversations/{id}/stream + * @secure + */ + agentConversationsStreamList: (id: string, params: RequestParams = {}) => + this.request({ + path: `/v1/agent/conversations/${id}/stream`, + method: "GET", + secure: true, + ...params, + }), + + /** + * @description Widens the conversation's grant by one harness scope (e.g. routing:drop after a refused delete). The approval is recorded on the conversation and applies to the running turn and every later one. Limited by the caller's role. + * + * @tags agent + * @name AgentConversationsWidenCreate + * @summary Approve a scope for the conversation + * @request POST:/v1/agent/conversations/{id}/widen + * @secure + */ + agentConversationsWidenCreate: ( + id: string, + control: ApiAgentControlRequest, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/agent/conversations/${id}/widen`, + method: "POST", + body: control, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Every account tool the agent can reach, the harness scope it needs, and whether the caller's grant permits it or could approve it + * + * @tags agent + * @name AgentToolsList + * @summary List agent tools + * @request GET:/v1/agent/tools + * @secure + */ + agentToolsList: (params: RequestParams = {}) => + this.request({ + path: `/v1/agent/tools`, + method: "GET", + secure: true, + format: "json", + ...params, + }), + + /** + * @description List audit entries across the platform or scope them to one exact account. Platform admins bypass account-plan activity restrictions. + * + * @tags admin, audit + * @name AuditList + * @summary List audit entries (admin) + * @request GET:/v1/audit + * @secure + */ + auditList: ( + query?: { + /** Page size */ + limit?: number; + /** Offset */ + offset?: number; + /** Comma-separated resource kinds */ + filter?: string; + /** Exact account ID */ + account_id?: string; + /** Account email or ID (legacy filter) */ + email?: string; + /** Filter by acting user's username */ + username?: string; + /** Filter by action */ + action?: string; + /** Filter by surface: mcp or agent */ + source?: string; + }, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/audit`, + method: "GET", + query: query, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Exchange an MFA challenge token and authenticator code for a session token. + * + * @tags auth + * @name AuthMfaVerifyCreate + * @summary Verify MFA login + * @request POST:/v1/auth/mfa/verify + */ + authMfaVerifyCreate: ( + request: ApiMfaVerifyRequest, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/auth/mfa/verify`, + method: "POST", + body: request, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Get the billing details for the authenticated account + * + * @tags billing + * @name BillingDetailsList + * @summary Get billing details + * @request GET:/v1/billing-details + * @secure + */ + billingDetailsList: (params: RequestParams = {}) => + this.request({ + path: `/v1/billing-details`, + method: "GET", + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Update the billing details for the authenticated account + * + * @tags billing + * @name BillingDetailsUpdate + * @summary Update billing details + * @request PUT:/v1/billing-details + * @secure + */ + billingDetailsUpdate: ( + billingDetails: StructsBillingDetails, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/billing-details`, + method: "PUT", + body: billingDetails, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Get list of all buckets for the authenticated account + * + * @tags buckets + * @name BucketsList + * @summary List account buckets + * @request GET:/v1/buckets + * @secure + */ + bucketsList: (params: RequestParams = {}) => + this.request({ + path: `/v1/buckets`, + method: "GET", + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Create a new webhook bucket for the authenticated account + * + * @tags buckets + * @name BucketsCreate + * @summary Create a new bucket + * @request POST:/v1/buckets + * @secure + */ + bucketsCreate: (bucket: StructsBucket, params: RequestParams = {}) => + this.request({ + path: `/v1/buckets`, + method: "POST", + body: bucket, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Delete a bucket by ID. Bucket must not have any inputs or outputs unless force parameter is used + * + * @tags buckets + * @name BucketsDelete + * @summary Delete bucket + * @request DELETE:/v1/buckets/{id} + * @secure + */ + bucketsDelete: ( + id: string, + query?: { + /** Force delete even if bucket has inputs or outputs */ + force?: boolean; + }, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/buckets/${id}`, + method: "DELETE", + query: query, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Get details of a specific bucket by ID + * + * @tags buckets + * @name BucketsDetail + * @summary Get bucket details + * @request GET:/v1/buckets/{id} + * @secure + */ + bucketsDetail: (id: string, params: RequestParams = {}) => + this.request({ + path: `/v1/buckets/${id}`, + method: "GET", + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Update an existing bucket configuration + * + * @tags buckets + * @name BucketsUpdate + * @summary Update bucket + * @request PUT:/v1/buckets/{id} + * @secure + */ + bucketsUpdate: ( + id: string, + bucket: StructsBucket, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/buckets/${id}`, + method: "PUT", + body: bucket, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Create a new input endpoint for a bucket + * + * @tags inputs + * @name BucketsInputsCreate + * @summary Create input + * @request POST:/v1/buckets/{id}/inputs + * @secure + */ + bucketsInputsCreate: ( + id: string, + input: StructsInput, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/buckets/${id}/inputs`, + method: "POST", + body: input, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Delete an input endpoint by ID + * + * @tags inputs + * @name BucketsInputsDelete + * @summary Delete input + * @request DELETE:/v1/buckets/{id}/inputs/{detailed} + * @secure + */ + bucketsInputsDelete: ( + id: string, + detailed: string, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/buckets/${id}/inputs/${detailed}`, + method: "DELETE", + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Update an existing input endpoint configuration + * + * @tags inputs + * @name BucketsInputsUpdate + * @summary Update input + * @request PUT:/v1/buckets/{id}/inputs/{detailed} + * @secure + */ + bucketsInputsUpdate: ( + id: string, + detailed: string, + input: StructsInput, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/buckets/${id}/inputs/${detailed}`, + method: "PUT", + body: input, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Get detailed information about a specific webhook log from one bucket + * + * @tags logs + * @name BucketsLogsDetail + * @summary Get bucket-scoped log details from warehouse + * @request GET:/v1/buckets/{id}/logs/{logId} + * @secure + */ + bucketsLogsDetail: ( + id: string, + logId: string, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/buckets/${id}/logs/${logId}`, + method: "GET", + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Create a new output destination for a bucket + * + * @tags outputs + * @name BucketsOutputsCreate + * @summary Create output + * @request POST:/v1/buckets/{id}/outputs + * @secure + */ + bucketsOutputsCreate: ( + id: string, + output: StructsOutput, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/buckets/${id}/outputs`, + method: "POST", + body: output, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Delete an output destination by ID + * + * @tags outputs + * @name BucketsOutputsDelete + * @summary Delete output + * @request DELETE:/v1/buckets/{id}/outputs/{detailed} + * @secure + */ + bucketsOutputsDelete: ( + id: string, + detailed: string, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/buckets/${id}/outputs/${detailed}`, + method: "DELETE", + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Update an existing output destination configuration + * + * @tags outputs + * @name BucketsOutputsUpdate + * @summary Update output + * @request PUT:/v1/buckets/{id}/outputs/{detailed} + * @secure + */ + bucketsOutputsUpdate: ( + id: string, + detailed: string, + output: StructsOutput, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/buckets/${id}/outputs/${detailed}`, + method: "PUT", + body: output, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Delete filtering rules from an output destination + * + * @tags outputs + * @name BucketsOutputsRulesDelete + * @summary Delete output rules + * @request DELETE:/v1/buckets/{id}/outputs/{detailed}/rules + * @secure + */ + bucketsOutputsRulesDelete: ( + id: string, + detailed: string, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/buckets/${id}/outputs/${detailed}/rules`, + method: "DELETE", + secure: true, + ...params, + }), + + /** + * @description Update filtering rules for an output destination + * + * @tags outputs + * @name BucketsOutputsRulesUpdate + * @summary Update output rules + * @request PUT:/v1/buckets/{id}/outputs/{detailed}/rules + * @secure + */ + bucketsOutputsRulesUpdate: ( + id: string, + detailed: string, + rules: StructsDeleteFunctionResponse, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/buckets/${id}/outputs/${detailed}/rules`, + method: "PUT", + body: rules, + secure: true, + type: ContentType.Json, + ...params, + }), + + /** + * @description Get all service connection inputs for a specific bucket + * + * @tags service-connection-inputs + * @name BucketsServiceConnectionInputsList + * @summary List service connection inputs for a bucket + * @request GET:/v1/buckets/{id}/service-connection-inputs + * @secure + */ + bucketsServiceConnectionInputsList: ( + id: string, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/buckets/${id}/service-connection-inputs`, + method: "GET", + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Create a new service connection input for a bucket + * + * @tags service-connection-inputs + * @name BucketsServiceConnectionInputsCreate + * @summary Create service connection input + * @request POST:/v1/buckets/{id}/service-connection-inputs + * @secure + */ + bucketsServiceConnectionInputsCreate: ( + id: string, + input: StructsServiceConnectionInput, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/buckets/${id}/service-connection-inputs`, + method: "POST", + body: input, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Delete a service connection input by ID + * + * @tags service-connection-inputs + * @name BucketsServiceConnectionInputsDelete + * @summary Delete service connection input + * @request DELETE:/v1/buckets/{id}/service-connection-inputs/{detailed} + * @secure + */ + bucketsServiceConnectionInputsDelete: ( + id: string, + detailed: string, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/buckets/${id}/service-connection-inputs/${detailed}`, + method: "DELETE", + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Update a service connection input by ID + * + * @tags service-connection-inputs + * @name BucketsServiceConnectionInputsUpdate + * @summary Update service connection input + * @request PUT:/v1/buckets/{id}/service-connection-inputs/{detailed} + * @secure + */ + bucketsServiceConnectionInputsUpdate: ( + id: string, + detailed: string, + input: StructsServiceConnectionInput, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/buckets/${id}/service-connection-inputs/${detailed}`, + method: "PUT", + body: input, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), - protected mergeRequestParams( - params1: RequestParams, - params2?: RequestParams, - ): RequestParams { - return { - ...this.baseApiParams, - ...params1, - ...(params2 || {}), - headers: { - ...(this.baseApiParams.headers || {}), - ...(params1.headers || {}), - ...((params2 && params2.headers) || {}), - }, - }; - } + /** + * @description Get all service connection outputs for a specific bucket + * + * @tags service-connection-outputs + * @name BucketsServiceConnectionOutputsList + * @summary List service connection outputs for a bucket + * @request GET:/v1/buckets/{id}/service-connection-outputs + * @secure + */ + bucketsServiceConnectionOutputsList: ( + id: string, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/buckets/${id}/service-connection-outputs`, + method: "GET", + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), - protected createAbortSignal = ( - cancelToken: CancelToken, - ): AbortSignal | undefined => { - if (this.abortControllers.has(cancelToken)) { - const abortController = this.abortControllers.get(cancelToken); - if (abortController) { - return abortController.signal; - } - return void 0; - } + /** + * @description Create a new service connection output for a bucket + * + * @tags service-connection-outputs + * @name BucketsServiceConnectionOutputsCreate + * @summary Create service connection output + * @request POST:/v1/buckets/{id}/service-connection-outputs + * @secure + */ + bucketsServiceConnectionOutputsCreate: ( + id: string, + output: StructsServiceConnectionOutput, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/buckets/${id}/service-connection-outputs`, + method: "POST", + body: output, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Delete a service connection output by ID + * + * @tags service-connection-outputs + * @name BucketsServiceConnectionOutputsDelete + * @summary Delete service connection output + * @request DELETE:/v1/buckets/{id}/service-connection-outputs/{detailed} + * @secure + */ + bucketsServiceConnectionOutputsDelete: ( + id: string, + detailed: string, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/buckets/${id}/service-connection-outputs/${detailed}`, + method: "DELETE", + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Update a service connection output by ID + * + * @tags service-connection-outputs + * @name BucketsServiceConnectionOutputsUpdate + * @summary Update service connection output + * @request PUT:/v1/buckets/{id}/service-connection-outputs/{detailed} + * @secure + */ + bucketsServiceConnectionOutputsUpdate: ( + id: string, + detailed: string, + output: StructsServiceConnectionOutput, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/buckets/${id}/service-connection-outputs/${detailed}`, + method: "PUT", + body: output, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Initiates stripe checkout session, new subscription will be created + * + * @tags billing + * @name CheckoutCreate + * @summary Initiates stripe checkout session, new subscription will be created + * @request POST:/v1/checkout + * @secure + */ + checkoutCreate: ( + planReq: ApiPlanChangeRequest, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/checkout`, + method: "POST", + body: planReq, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Start a checkout session setup for the authenticated account + * + * @tags billing + * @name CheckoutSetupCreate + * @summary Start checkout session setup + * @request POST:/v1/checkout-setup + * @secure + */ + checkoutSetupCreate: (params: RequestParams = {}) => + this.request({ + path: `/v1/checkout-setup`, + method: "POST", + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Get the server config + * + * @tags config + * @name ConfigList + * @summary Get server config + * @request GET:/v1/config + * @secure + */ + configList: (params: RequestParams = {}) => + this.request({ + path: `/v1/config`, + method: "GET", + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Get list of all connected clients for the authenticated account + * + * @tags connected-clients + * @name ConnectedClientsList + * @summary Get connected clients + * @request GET:/v1/connected-clients + * @secure + */ + connectedClientsList: (params: RequestParams = {}) => + this.request({ + path: `/v1/connected-clients`, + method: "GET", + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Get list of all cron jobs for the authenticated account + * + * @tags crons + * @name CronsList + * @summary List cron jobs + * @request GET:/v1/crons + * @secure + */ + cronsList: (params: RequestParams = {}) => + this.request({ + path: `/v1/crons`, + method: "GET", + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Create a new scheduled cron job + * + * @tags crons + * @name CronsCreate + * @summary Create cron job + * @request POST:/v1/crons + * @secure + */ + cronsCreate: (cron: StructsCron, params: RequestParams = {}) => + this.request({ + path: `/v1/crons`, + method: "POST", + body: cron, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Delete a cron job by ID + * + * @tags crons + * @name CronsDelete + * @summary Delete cron job + * @request DELETE:/v1/crons/{id} + * @secure + */ + cronsDelete: (id: string, params: RequestParams = {}) => + this.request({ + path: `/v1/crons/${id}`, + method: "DELETE", + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), - const abortController = new AbortController(); - this.abortControllers.set(cancelToken, abortController); - return abortController.signal; - }; + /** + * @description Get details of a specific cron job by ID + * + * @tags crons + * @name CronsDetail + * @summary Get cron job + * @request GET:/v1/crons/{id} + * @secure + */ + cronsDetail: (id: string, params: RequestParams = {}) => + this.request({ + path: `/v1/crons/${id}`, + method: "GET", + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), - public abortRequest = (cancelToken: CancelToken) => { - const abortController = this.abortControllers.get(cancelToken); + /** + * @description Update an existing cron job configuration + * + * @tags crons + * @name CronsUpdate + * @summary Update cron job + * @request PUT:/v1/crons/{id} + * @secure + */ + cronsUpdate: (id: string, cron: StructsCron, params: RequestParams = {}) => + this.request({ + path: `/v1/crons/${id}`, + method: "PUT", + body: cron, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), - if (abortController) { - abortController.abort(); - this.abortControllers.delete(cancelToken); - } - }; + /** + * @description Get list of all domains for the authenticated account + * + * @tags domains + * @name DomainsList + * @summary List account domains + * @request GET:/v1/domains + * @secure + */ + domainsList: (params: RequestParams = {}) => + this.request({ + path: `/v1/domains`, + method: "GET", + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), - public request = async ({ - body, - secure, - path, - type, - query, - format, - baseUrl, - cancelToken, - ...params - }: FullRequestParams): Promise> => { - const secureParams = - ((typeof secure === "boolean" ? secure : this.baseApiParams.secure) && - this.securityWorker && - (await this.securityWorker(this.securityData))) || - {}; - const requestParams = this.mergeRequestParams(params, secureParams); - const queryString = query && this.toQueryString(query); - const payloadFormatter = this.contentFormatters[type || ContentType.Json]; - const responseFormat = format || requestParams.format; + /** + * @description Reserve a domain for the authenticated account. Domain must be valid and not already taken. + * + * @tags domains + * @name DomainsCreate + * @summary Create domain reservation + * @request POST:/v1/domains + * @secure + */ + domainsCreate: (domain: StructsDomain, params: RequestParams = {}) => + this.request({ + path: `/v1/domains`, + method: "POST", + body: domain, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), - return this.customFetch( - `${baseUrl || this.baseUrl || ""}${path}${queryString ? `?${queryString}` : ""}`, - { - ...requestParams, - headers: { - ...(requestParams.headers || {}), - ...(type && type !== ContentType.FormData - ? { "Content-Type": type } - : {}), - }, - signal: - (cancelToken - ? this.createAbortSignal(cancelToken) - : requestParams.signal) || null, - body: - typeof body === "undefined" || body === null - ? null - : payloadFormatter(body), - }, - ).then(async (response) => { - const r = response as HttpResponse; - r.data = null as unknown as T; - r.error = null as unknown as E; + /** + * @description Delete a reserved domain by ID. Domain must not be in use by any inputs or tunnels. + * + * @tags domains + * @name DomainsDelete + * @summary Delete domain reservation + * @request DELETE:/v1/domains/{id} + * @secure + */ + domainsDelete: (id: string, params: RequestParams = {}) => + this.request({ + path: `/v1/domains/${id}`, + method: "DELETE", + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), - const responseToParse = responseFormat ? response.clone() : response; - const data = !responseFormat - ? r - : await responseToParse[responseFormat]() - .then((data) => { - if (r.ok) { - r.data = data; - } else { - r.error = data; - } - return r; - }) - .catch((e) => { - r.error = e; - return r; - }); + /** + * @description Server-to-server endpoint the Cloudflare Email Worker posts raw RFC822 to. This handler resolves the recipient to an email-type service connection input, parses the message (pkg/email), enforces per-input policy (sender allowlist, attachment drop/cap), and pushes the resulting email.Message through the normal relay pipeline. Authenticated with the X-WHR-Secret shared secret, not a user token. + * + * @tags email + * @name EmailInboundCreate + * @summary Inbound email ingest (internal) + * @request POST:/v1/email-inbound + */ + emailInboundCreate: (params: RequestParams = {}) => + this.request({ + path: `/v1/email-inbound`, + method: "POST", + format: "json", + ...params, + }), - if (cancelToken) { - this.abortControllers.delete(cancelToken); - } + /** + * @description Pull-based delivery: returns the oldest unsent webhooks for the bucket and marks them delivered (RECEIVED → SENT), so each poll returns the next batch and drains to an empty page. Report a different outcome with PUT /v1/logs/{id}. + * + * @tags logs + * @name EventsList + * @summary Consume webhook events (pull-delivery queue) + * @request GET:/v1/events + * @secure + */ + eventsList: ( + query: { + /** Bucket ID or account-unique name */ + bucket: string; + /** Output ID filter */ + output?: string; + /** Page size (default 1, max 100) */ + limit?: number; + /** How far back to look for unsent webhooks (default 24h, Go duration syntax) */ + max_age?: string; + }, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/events`, + method: "GET", + query: query, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), - if (!response.ok) throw data; - return data; - }); - }; -} + /** + * @description Look up a function execution log by its id without requiring the function id in the URL. Useful for the webhook-log-detail UI, where the log only knows the ExecuteLog id (not which function emitted it). The executing function id is embedded on the row. + * + * @tags functions + * @name ExecLogsDetail + * @summary Get a function execution log by id (account-scoped) + * @request GET:/v1/exec-logs/{id} + * @secure + */ + execLogsDetail: ( + id: string, + query?: { + /** Execution creation time (unix seconds/ms/us). Optional day hint that turns the lookup into a single index read; omit it and the log still resolves, just less cheaply. */ + created_at?: number; + }, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/exec-logs/${id}`, + method: "GET", + query: query, + secure: true, + format: "json", + ...params, + }), -/** - * @title WebhookRelay API reference - * @version 0.1 - * @baseUrl https://my.webhookrelay.com - * @contact WebhookRelay support (https://my.webhookrelay.com/) - * - * This is the WebhookRelay API. - */ -export class Api< - SecurityDataType extends unknown, -> extends HttpClient { - v1 = { /** - * @description Get the account API key. If no key exists, a new one will be generated. + * No description * - * @tags account - * @name AccountApiKeyList - * @summary Get account API key - * @request GET:/v1/account/api-key + * @tags functions + * @name FunctionReferenceList + * @summary Read the deployed Function API reference and executable examples + * @request GET:/v1/function-reference * @secure */ - accountApiKeyList: (params: RequestParams = {}) => - this.request({ - path: `/v1/account/api-key`, + functionReferenceList: ( + query: { + /** Runtime */ + driver: "js" | "lua"; + /** Module from the runtime catalog, or core */ + module: string; + /** Curated helper method */ + method?: string; + }, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/function-reference`, method: "GET", + query: query, secure: true, - type: ContentType.Json, format: "json", ...params, }), /** - * @description Generate a new API key for the account, replacing the existing one. + * No description * - * @tags account - * @name AccountApiKeyCreate - * @summary Regenerate account API key - * @request POST:/v1/account/api-key + * @tags functions + * @name FunctionRuntimeList + * @summary Read the deployed Function runtime capabilities + * @request GET:/v1/function-runtime * @secure */ - accountApiKeyCreate: (params: RequestParams = {}) => - this.request({ - path: `/v1/account/api-key`, - method: "POST", + functionRuntimeList: ( + query: { + /** Runtime */ + driver: "js" | "lua"; + }, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/function-runtime`, + method: "GET", + query: query, secure: true, - type: ContentType.Json, format: "json", ...params, }), /** - * @description Enable or disable the account API key without regenerating it. + * @description List the functions for the authenticated account * - * @tags account - * @name AccountApiKeyUpdate - * @summary Enable or disable account API key - * @request PUT:/v1/account/api-key + * @tags functions + * @name FunctionsList + * @summary List functions + * @request GET:/v1/functions * @secure */ - accountApiKeyUpdate: ( - request: StructsUpdateAPIKeyStatusRequest, - params: RequestParams = {}, - ) => - this.request({ - path: `/v1/account/api-key`, - method: "PUT", - body: request, + functionsList: (params: RequestParams = {}) => + this.request({ + path: `/v1/functions`, + method: "GET", secure: true, type: ContentType.Json, format: "json", @@ -1666,22 +5961,22 @@ export class Api< }), /** - * @description Disable MFA after validating a current authenticator token. + * @description Create a new function * - * @tags account - * @name AccountMfaDelete - * @summary Disable MFA - * @request DELETE:/v1/account/mfa + * @tags functions + * @name FunctionsCreate + * @summary Create function + * @request POST:/v1/functions * @secure */ - accountMfaDelete: ( - request: ApiMfaConfirmRequest, + functionsCreate: ( + functionPayload: StructsCreateFunctionRequest, params: RequestParams = {}, ) => - this.request({ - path: `/v1/account/mfa`, - method: "DELETE", - body: request, + this.request({ + path: `/v1/functions`, + method: "POST", + body: functionPayload, secure: true, type: ContentType.Json, format: "json", @@ -1689,22 +5984,22 @@ export class Api< }), /** - * @description Enable MFA after validating a token from the pending TOTP secret. + * @description Generate a new function based on the provided input and output payloads * - * @tags account - * @name AccountMfaConfirmCreate - * @summary Confirm MFA setup - * @request POST:/v1/account/mfa/confirm + * @tags functions + * @name FunctionsGenerateCreate + * @summary Generate function + * @request POST:/v1/functions-generate * @secure */ - accountMfaConfirmCreate: ( - request: ApiMfaConfirmRequest, + functionsGenerateCreate: ( + generateRequest: StructsGenerateFunctionRequest, params: RequestParams = {}, ) => - this.request({ - path: `/v1/account/mfa/confirm`, + this.request({ + path: `/v1/functions-generate`, method: "POST", - body: request, + body: generateRequest, secure: true, type: ContentType.Json, format: "json", @@ -1712,18 +6007,18 @@ export class Api< }), /** - * @description Generate a TOTP secret and QR code for the authenticated account or sub-account. + * @description Delete a function by its ID * - * @tags account - * @name AccountMfaSetupCreate - * @summary Start MFA setup - * @request POST:/v1/account/mfa/setup + * @tags functions + * @name FunctionsDelete + * @summary Delete function + * @request DELETE:/v1/functions/{id} * @secure */ - accountMfaSetupCreate: (params: RequestParams = {}) => - this.request({ - path: `/v1/account/mfa/setup`, - method: "POST", + functionsDelete: (id: string, params: RequestParams = {}) => + this.request({ + path: `/v1/functions/${id}`, + method: "DELETE", secure: true, type: ContentType.Json, format: "json", @@ -1731,17 +6026,17 @@ export class Api< }), /** - * @description Get list of all connected clients across all accounts from the state tracker service. + * @description Get a function by its ID * - * @tags admin - * @name AdminConnectedClientsList - * @summary Get all connected clients (admin) - * @request GET:/v1/admin/connected-clients + * @tags functions + * @name FunctionsDetail + * @summary Get function + * @request GET:/v1/functions/{id} * @secure */ - adminConnectedClientsList: (params: RequestParams = {}) => - this.request({ - path: `/v1/admin/connected-clients`, + functionsDetail: (id: string, params: RequestParams = {}) => + this.request({ + path: `/v1/functions/${id}`, method: "GET", secure: true, type: ContentType.Json, @@ -1750,38 +6045,41 @@ export class Api< }), /** - * @description Exchange an MFA challenge token and authenticator code for a session token. + * @description Update an existing function * - * @tags auth - * @name AuthMfaVerifyCreate - * @summary Verify MFA login - * @request POST:/v1/auth/mfa/verify + * @tags functions + * @name FunctionsUpdate + * @summary Update function + * @request PUT:/v1/functions/{id} + * @secure */ - authMfaVerifyCreate: ( - request: ApiMfaVerifyRequest, + functionsUpdate: ( + id: string, + functionPayload: StructsUpdateFunctionRequest, params: RequestParams = {}, ) => - this.request({ - path: `/v1/auth/mfa/verify`, - method: "POST", - body: request, + this.request({ + path: `/v1/functions/${id}`, + method: "PUT", + body: functionPayload, + secure: true, type: ContentType.Json, format: "json", ...params, }), /** - * @description Get the billing details for the authenticated account + * @description List the configuration values for a given function * - * @tags billing - * @name BillingDetailsList - * @summary Get billing details - * @request GET:/v1/billing-details + * @tags functions + * @name FunctionsConfigList + * @summary List function config + * @request GET:/v1/functions/{id}/config * @secure */ - billingDetailsList: (params: RequestParams = {}) => - this.request({ - path: `/v1/billing-details`, + functionsConfigList: (id: string, params: RequestParams = {}) => + this.request({ + path: `/v1/functions/${id}/config`, method: "GET", secure: true, type: ContentType.Json, @@ -1790,22 +6088,23 @@ export class Api< }), /** - * @description Update the billing details for the authenticated account + * @description Set the configuration value for a given function * - * @tags billing - * @name BillingDetailsUpdate - * @summary Update billing details - * @request PUT:/v1/billing-details + * @tags functions + * @name FunctionsConfigUpdate + * @summary Set function config + * @request PUT:/v1/functions/{id}/config * @secure */ - billingDetailsUpdate: ( - billingDetails: StructsBillingDetails, + functionsConfigUpdate: ( + id: string, + config: ApiSetFunctionConfigRequest, params: RequestParams = {}, ) => - this.request({ - path: `/v1/billing-details`, + this.request({ + path: `/v1/functions/${id}/config`, method: "PUT", - body: billingDetails, + body: config, secure: true, type: ContentType.Json, format: "json", @@ -1813,18 +6112,22 @@ export class Api< }), /** - * @description Get list of all buckets for the authenticated account + * @description Delete the configuration value for a given function * - * @tags buckets - * @name BucketsList - * @summary List account buckets - * @request GET:/v1/buckets + * @tags functions + * @name FunctionsConfigDelete + * @summary Delete function config value + * @request DELETE:/v1/functions/{id}/config/{key} * @secure */ - bucketsList: (params: RequestParams = {}) => - this.request({ - path: `/v1/buckets`, - method: "GET", + functionsConfigDelete: ( + id: string, + key: string, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/functions/${id}/config/${key}`, + method: "DELETE", secure: true, type: ContentType.Json, format: "json", @@ -1832,89 +6135,63 @@ export class Api< }), /** - * @description Create a new webhook bucket for the authenticated account + * No description * - * @tags buckets - * @name BucketsCreate - * @summary Create a new bucket - * @request POST:/v1/buckets + * @tags functions + * @name FunctionsConnectionsList + * @summary List Function connection requirements + * @request GET:/v1/functions/{id}/connections * @secure */ - bucketsCreate: (bucket: StructsBucket, params: RequestParams = {}) => - this.request({ - path: `/v1/buckets`, - method: "POST", - body: bucket, + functionsConnectionsList: (id: string, params: RequestParams = {}) => + this.request({ + path: `/v1/functions/${id}/connections`, + method: "GET", secure: true, - type: ContentType.Json, format: "json", ...params, }), /** - * @description Delete a bucket by ID. Bucket must not have any inputs or outputs unless force parameter is used + * No description * - * @tags buckets - * @name BucketsDelete - * @summary Delete bucket - * @request DELETE:/v1/buckets/{id} + * @tags functions + * @name FunctionsConnectionsDelete + * @summary Unbind a Function service connection import + * @request DELETE:/v1/functions/{id}/connections/{alias} * @secure */ - bucketsDelete: ( + functionsConnectionsDelete: ( id: string, - query?: { - /** Force delete even if bucket has inputs or outputs */ - force?: boolean; - }, + alias: string, params: RequestParams = {}, ) => - this.request({ - path: `/v1/buckets/${id}`, + this.request({ + path: `/v1/functions/${id}/connections/${alias}`, method: "DELETE", - query: query, - secure: true, - type: ContentType.Json, - format: "json", - ...params, - }), - - /** - * @description Get details of a specific bucket by ID - * - * @tags buckets - * @name BucketsDetail - * @summary Get bucket details - * @request GET:/v1/buckets/{id} - * @secure - */ - bucketsDetail: (id: string, params: RequestParams = {}) => - this.request({ - path: `/v1/buckets/${id}`, - method: "GET", secure: true, - type: ContentType.Json, - format: "json", ...params, }), /** - * @description Update an existing bucket configuration + * No description * - * @tags buckets - * @name BucketsUpdate - * @summary Update bucket - * @request PUT:/v1/buckets/{id} + * @tags functions + * @name FunctionsConnectionsUpdate + * @summary Bind a Function service connection import + * @request PUT:/v1/functions/{id}/connections/{alias} * @secure */ - bucketsUpdate: ( + functionsConnectionsUpdate: ( id: string, - bucket: StructsBucket, + alias: string, + binding: ApiBindFunctionConnectionRequest, params: RequestParams = {}, ) => - this.request({ - path: `/v1/buckets/${id}`, + this.request({ + path: `/v1/functions/${id}/connections/${alias}`, method: "PUT", - body: bucket, + body: binding, secure: true, type: ContentType.Json, format: "json", @@ -1922,23 +6199,18 @@ export class Api< }), /** - * @description Create a new input endpoint for a bucket + * @description Invoke a function by its ID * - * @tags inputs - * @name BucketsInputsCreate - * @summary Create input - * @request POST:/v1/buckets/{id}/inputs + * @tags functions + * @name FunctionsInvokeCreate + * @summary Invoke function + * @request POST:/v1/functions/{id}/invoke * @secure */ - bucketsInputsCreate: ( - id: string, - input: StructsInput, - params: RequestParams = {}, - ) => - this.request({ - path: `/v1/buckets/${id}/inputs`, + functionsInvokeCreate: (id: string, params: RequestParams = {}) => + this.request({ + path: `/v1/functions/${id}/invoke`, method: "POST", - body: input, secure: true, type: ContentType.Json, format: "json", @@ -1946,22 +6218,18 @@ export class Api< }), /** - * @description Delete an input endpoint by ID + * @description Get the logs for a function * - * @tags inputs - * @name BucketsInputsDelete - * @summary Delete input - * @request DELETE:/v1/buckets/{id}/inputs/{detailed} + * @tags functions + * @name FunctionsLogsList + * @summary Get function logs + * @request GET:/v1/functions/{id}/logs * @secure */ - bucketsInputsDelete: ( - id: string, - detailed: string, - params: RequestParams = {}, - ) => - this.request({ - path: `/v1/buckets/${id}/inputs/${detailed}`, - method: "DELETE", + functionsLogsList: (id: string, params: RequestParams = {}) => + this.request({ + path: `/v1/functions/${id}/logs`, + method: "GET", secure: true, type: ContentType.Json, format: "json", @@ -1969,24 +6237,22 @@ export class Api< }), /** - * @description Update an existing input endpoint configuration + * @description Get the logs for a function * - * @tags inputs - * @name BucketsInputsUpdate - * @summary Update input - * @request PUT:/v1/buckets/{id}/inputs/{detailed} + * @tags functions + * @name FunctionsLogsDetail + * @summary Get function logs + * @request GET:/v1/functions/{id}/logs/{logId} * @secure */ - bucketsInputsUpdate: ( + functionsLogsDetail: ( id: string, - detailed: string, - input: StructsInput, + logId: string, params: RequestParams = {}, ) => - this.request({ - path: `/v1/buckets/${id}/inputs/${detailed}`, - method: "PUT", - body: input, + this.request({ + path: `/v1/functions/${id}/logs/${logId}`, + method: "GET", secure: true, type: ContentType.Json, format: "json", @@ -1994,69 +6260,97 @@ export class Api< }), /** - * @description Get detailed information about a specific webhook log from one bucket + * @description Revision history of a function, newest first, without code. A revision is recorded on create, on every code change, and on restore. * - * @tags logs - * @name BucketsLogsDetail - * @summary Get bucket-scoped log details from warehouse - * @request GET:/v1/buckets/{id}/logs/{logId} + * @tags functions + * @name FunctionsVersionsList + * @summary List function versions + * @request GET:/v1/functions/{id}/versions * @secure */ - bucketsLogsDetail: ( + functionsVersionsList: (id: string, params: RequestParams = {}) => + this.request({ + path: `/v1/functions/${id}/versions`, + method: "GET", + secure: true, + format: "json", + ...params, + }), + + /** + * @description One revision of a function including its code + * + * @tags functions + * @name FunctionsVersionsDetail + * @summary Get function version + * @request GET:/v1/functions/{id}/versions/{version} + * @secure + */ + functionsVersionsDetail: ( id: string, - logId: string, + version: number, params: RequestParams = {}, ) => - this.request({ - path: `/v1/buckets/${id}/logs/${logId}`, + this.request({ + path: `/v1/functions/${id}/versions/${version}`, method: "GET", secure: true, - type: ContentType.Json, format: "json", ...params, }), /** - * @description Create a new output destination for a bucket + * @description Makes an earlier revision the current code. The restore is itself recorded as the newest revision, so history is never lost. * - * @tags outputs - * @name BucketsOutputsCreate - * @summary Create output - * @request POST:/v1/buckets/{id}/outputs + * @tags functions + * @name FunctionsVersionsRestoreCreate + * @summary Restore function version + * @request POST:/v1/functions/{id}/versions/{version}/restore * @secure */ - bucketsOutputsCreate: ( + functionsVersionsRestoreCreate: ( id: string, - output: StructsOutput, + version: number, params: RequestParams = {}, ) => - this.request({ - path: `/v1/buckets/${id}/outputs`, + this.request({ + path: `/v1/functions/${id}/versions/${version}/restore`, method: "POST", - body: output, secure: true, - type: ContentType.Json, format: "json", ...params, }), /** - * @description Delete an output destination by ID + * @description Returns a dense per-UTC-day series of incidents that started in the inclusive [from, to] window, including count and resolved-incident duration totals for charting. * - * @tags outputs - * @name BucketsOutputsDelete - * @summary Delete output - * @request DELETE:/v1/buckets/{id}/outputs/{detailed} + * @tags incidents + * @name IncidentsStatsList + * @summary Get incident statistics by day + * @request GET:/v1/incidents/stats * @secure */ - bucketsOutputsDelete: ( - id: string, - detailed: string, + incidentsStatsList: ( + query?: { + /** From date (YYYY-MM-DD), defaults to 30 days ago */ + from?: string; + /** To date (YYYY-MM-DD), defaults to today */ + to?: string; + /** Filter by status (open|resolved) */ + status?: string; + /** Filter by bucket ID */ + bucket_id?: string; + /** Filter by output ID */ + output_id?: string; + /** Filter by integration configuration ID */ + integration_id?: string; + }, params: RequestParams = {}, ) => - this.request({ - path: `/v1/buckets/${id}/outputs/${detailed}`, - method: "DELETE", + this.request({ + path: `/v1/incidents/stats`, + method: "GET", + query: query, secure: true, type: ContentType.Json, format: "json", @@ -2064,24 +6358,37 @@ export class Api< }), /** - * @description Update an existing output destination configuration + * @description Get paginated list of webhook logs from warehouse for the authenticated account * - * @tags outputs - * @name BucketsOutputsUpdate - * @summary Update output - * @request PUT:/v1/buckets/{id}/outputs/{detailed} + * @tags logs + * @name LogsList + * @summary List webhook logs from warehouse (paginated) + * @request GET:/v1/logs * @secure */ - bucketsOutputsUpdate: ( - id: string, - detailed: string, - output: StructsOutput, + logsList: ( + query: { + /** Filter by bucket ID */ + bucket: string; + /** Number of results per page */ + limit?: number; + /** Offset for pagination */ + offset?: number; + /** From date (YYYY-MM-DD or RFC3339) */ + from?: string; + /** To date (YYYY-MM-DD or RFC3339) */ + to?: string; + /** Filter by status (sent, failed, stalled, received, rejected) */ + status?: string; + /** Opaque pagination cursor (turbostore accounts; takes precedence over offset) */ + cursor?: string; + }, params: RequestParams = {}, ) => - this.request({ - path: `/v1/buckets/${id}/outputs/${detailed}`, - method: "PUT", - body: output, + this.request({ + path: `/v1/logs`, + method: "GET", + query: query, secure: true, type: ContentType.Json, format: "json", @@ -2089,65 +6396,75 @@ export class Api< }), /** - * @description Delete filtering rules from an output destination + * @description Get daily account log counts, retry/latency aggregates, and Turbostore request/response byte totals (recorded bodies plus HTTP headers) * - * @tags outputs - * @name BucketsOutputsRulesDelete - * @summary Delete output rules - * @request DELETE:/v1/buckets/{id}/outputs/{detailed}/rules + * @tags logs + * @name LogsStatsList + * @summary Get account log statistics + * @request GET:/v1/logs-stats * @secure */ - bucketsOutputsRulesDelete: ( - id: string, - detailed: string, + logsStatsList: ( + query?: { + /** From date (YYYY-MM-DD) */ + from?: string; + /** To date (YYYY-MM-DD) */ + to?: string; + /** Filter by bucket ID */ + bucketId?: string; + }, params: RequestParams = {}, ) => - this.request({ - path: `/v1/buckets/${id}/outputs/${detailed}/rules`, - method: "DELETE", + this.request({ + path: `/v1/logs-stats`, + method: "GET", + query: query, secure: true, + type: ContentType.Json, + format: "json", ...params, }), /** - * @description Update filtering rules for an output destination + * @description Per-bucket daily log statistics for the whole account. Returns success/failure/retry/latency series plus Turbostore request/response byte totals (recorded bodies plus HTTP headers) without fanning out one request per bucket. * - * @tags outputs - * @name BucketsOutputsRulesUpdate - * @summary Update output rules - * @request PUT:/v1/buckets/{id}/outputs/{detailed}/rules + * @tags logs + * @name LogsStatsByBucketList + * @summary Get per-bucket log statistics + * @request GET:/v1/logs-stats/by-bucket * @secure */ - bucketsOutputsRulesUpdate: ( - id: string, - detailed: string, - rules: StructsDeleteFunctionResponse, + logsStatsByBucketList: ( + query?: { + /** From date (YYYY-MM-DD) */ + from?: string; + /** To date (YYYY-MM-DD) */ + to?: string; + }, params: RequestParams = {}, ) => - this.request({ - path: `/v1/buckets/${id}/outputs/${detailed}/rules`, - method: "PUT", - body: rules, + this.request({ + path: `/v1/logs-stats/by-bucket`, + method: "GET", + query: query, secure: true, type: ContentType.Json, + format: "json", ...params, }), /** - * @description Get all service connection inputs for a specific bucket + * @description Get detailed information about a specific webhook log from warehouse * - * @tags service-connection-inputs - * @name BucketsServiceConnectionInputsList - * @summary List service connection inputs for a bucket - * @request GET:/v1/buckets/{id}/service-connection-inputs + * @tags logs + * @name LogsDetail + * @summary Get log details from warehouse + * @request GET:/v1/logs/{id} * @secure */ - bucketsServiceConnectionInputsList: ( - id: string, - params: RequestParams = {}, - ) => - this.request({ - path: `/v1/buckets/${id}/service-connection-inputs`, + logsDetail: (id: string, params: RequestParams = {}) => + this.request({ + path: `/v1/logs/${id}`, method: "GET", secure: true, type: ContentType.Json, @@ -2156,46 +6473,42 @@ export class Api< }), /** - * @description Create a new service connection input for a bucket + * @description Update a webhook log. Can be used to update status, response body, headers and status code. Only modifiable within 2 minutes of receipt. * - * @tags service-connection-inputs - * @name BucketsServiceConnectionInputsCreate - * @summary Create service connection input - * @request POST:/v1/buckets/{id}/service-connection-inputs + * @tags logs + * @name LogsUpdate + * @summary Update log + * @request PUT:/v1/logs/{id} * @secure - */ - bucketsServiceConnectionInputsCreate: ( - id: string, - input: StructsServiceConnectionInput, - params: RequestParams = {}, - ) => - this.request({ - path: `/v1/buckets/${id}/service-connection-inputs`, - method: "POST", - body: input, + */ + logsUpdate: (id: string, log: StructsLog, params: RequestParams = {}) => + this.request({ + path: `/v1/logs/${id}`, + method: "PUT", + body: log, secure: true, type: ContentType.Json, - format: "json", ...params, }), /** - * @description Delete a service connection input by ID + * @description Perform an action on a webhook log from warehouse (e.g., resend) * - * @tags service-connection-inputs - * @name BucketsServiceConnectionInputsDelete - * @summary Delete service connection input - * @request DELETE:/v1/buckets/{id}/service-connection-inputs/{detailed} + * @tags logs + * @name LogsActionCreate + * @summary Perform action on log from warehouse + * @request POST:/v1/logs/{id}/action * @secure */ - bucketsServiceConnectionInputsDelete: ( + logsActionCreate: ( id: string, - detailed: string, + action: ApiActionLogRequest, params: RequestParams = {}, ) => this.request({ - path: `/v1/buckets/${id}/service-connection-inputs/${detailed}`, - method: "DELETE", + path: `/v1/logs/${id}/action`, + method: "POST", + body: action, secure: true, type: ContentType.Json, format: "json", @@ -2203,45 +6516,52 @@ export class Api< }), /** - * @description Update a service connection input by ID + * @description Returns 1-minute resolution counts split by status plus * - * @tags service-connection-inputs - * @name BucketsServiceConnectionInputsUpdate - * @summary Update service connection input - * @request PUT:/v1/buckets/{id}/service-connection-inputs/{detailed} + * @tags logs + * @name LogsHistogramList + * @summary Per-minute log histogram for the explorer timeline + * @request GET:/v1/logs/histogram * @secure */ - bucketsServiceConnectionInputsUpdate: ( - id: string, - detailed: string, - input: StructsServiceConnectionInput, + logsHistogramList: ( + query?: { + /** From timestamp (RFC3339 or YYYY-MM-DD); default: 1h ago */ + from?: string; + /** To timestamp (RFC3339 or YYYY-MM-DD); default: now */ + to?: string; + /** Filter to a single bucket */ + bucket_id?: string; + /** Filter to a single output */ + output_id?: string; + /** Filter to a single status (sent, failed, stalled, received, rejected, preparing) */ + status?: string; + /** Filter to a single HTTP status code */ + status_code?: number; + }, params: RequestParams = {}, ) => - this.request({ - path: `/v1/buckets/${id}/service-connection-inputs/${detailed}`, - method: "PUT", - body: input, + this.request({ + path: `/v1/logs/histogram`, + method: "GET", + query: query, secure: true, - type: ContentType.Json, format: "json", ...params, }), /** - * @description Get all service connection outputs for a specific bucket + * @description Get list of all managed certificates for the authenticated account * - * @tags service-connection-outputs - * @name BucketsServiceConnectionOutputsList - * @summary List service connection outputs for a bucket - * @request GET:/v1/buckets/{id}/service-connection-outputs + * @tags managed-certs + * @name ManagedCertsList + * @summary List managed certificates + * @request GET:/v1/managed-certs * @secure */ - bucketsServiceConnectionOutputsList: ( - id: string, - params: RequestParams = {}, - ) => - this.request({ - path: `/v1/buckets/${id}/service-connection-outputs`, + managedCertsList: (params: RequestParams = {}) => + this.request({ + path: `/v1/managed-certs`, method: "GET", secure: true, type: ContentType.Json, @@ -2250,23 +6570,22 @@ export class Api< }), /** - * @description Create a new service connection output for a bucket + * @description Create a new managed SSL certificate for a domain * - * @tags service-connection-outputs - * @name BucketsServiceConnectionOutputsCreate - * @summary Create service connection output - * @request POST:/v1/buckets/{id}/service-connection-outputs + * @tags managed-certs + * @name ManagedCertsCreate + * @summary Create managed certificate + * @request POST:/v1/managed-certs * @secure */ - bucketsServiceConnectionOutputsCreate: ( - id: string, - output: StructsServiceConnectionOutput, + managedCertsCreate: ( + cert: ApiCreateManagedCertRequest, params: RequestParams = {}, ) => - this.request({ - path: `/v1/buckets/${id}/service-connection-outputs`, + this.request({ + path: `/v1/managed-certs`, method: "POST", - body: output, + body: cert, secure: true, type: ContentType.Json, format: "json", @@ -2274,47 +6593,35 @@ export class Api< }), /** - * @description Delete a service connection output by ID + * @description Delete a managed certificate by ID * - * @tags service-connection-outputs - * @name BucketsServiceConnectionOutputsDelete - * @summary Delete service connection output - * @request DELETE:/v1/buckets/{id}/service-connection-outputs/{detailed} + * @tags managed-certs + * @name ManagedCertsDelete + * @summary Delete managed certificate + * @request DELETE:/v1/managed-certs/{id} * @secure */ - bucketsServiceConnectionOutputsDelete: ( - id: string, - detailed: string, - params: RequestParams = {}, - ) => - this.request({ - path: `/v1/buckets/${id}/service-connection-outputs/${detailed}`, + managedCertsDelete: (id: string, params: RequestParams = {}) => + this.request({ + path: `/v1/managed-certs/${id}`, method: "DELETE", secure: true, - type: ContentType.Json, - format: "json", ...params, }), /** - * @description Update a service connection output by ID + * @description Get all news entries * - * @tags service-connection-outputs - * @name BucketsServiceConnectionOutputsUpdate - * @summary Update service connection output - * @request PUT:/v1/buckets/{id}/service-connection-outputs/{detailed} + * @tags news + * @name NewsList + * @summary Get news entries + * @request GET:/v1/news * @secure */ - bucketsServiceConnectionOutputsUpdate: ( - id: string, - detailed: string, - output: StructsServiceConnectionOutput, - params: RequestParams = {}, - ) => - this.request({ - path: `/v1/buckets/${id}/service-connection-outputs/${detailed}`, - method: "PUT", - body: output, + newsList: (params: RequestParams = {}) => + this.request({ + path: `/v1/news`, + method: "GET", secure: true, type: ContentType.Json, format: "json", @@ -2322,22 +6629,22 @@ export class Api< }), /** - * @description Initiates stripe checkout session, new subscription will be created + * @description Create a new news entry * - * @tags billing - * @name CheckoutCreate - * @summary Initiates stripe checkout session, new subscription will be created - * @request POST:/v1/checkout + * @tags news + * @name NewsCreate + * @summary Create news entry + * @request POST:/v1/news * @secure */ - checkoutCreate: ( - planReq: ApiPlanChangeRequest, + newsCreate: ( + newsEntry: StructsNewsEntryCreateRequest, params: RequestParams = {}, ) => - this.request({ - path: `/v1/checkout`, + this.request({ + path: `/v1/news`, method: "POST", - body: planReq, + body: newsEntry, secure: true, type: ContentType.Json, format: "json", @@ -2345,18 +6652,18 @@ export class Api< }), /** - * @description Start a checkout session setup for the authenticated account + * @description Delete a news entry by ID * - * @tags billing - * @name CheckoutSetupCreate - * @summary Start checkout session setup - * @request POST:/v1/checkout-setup + * @tags news + * @name NewsDelete + * @summary Delete news entry + * @request DELETE:/v1/news/{id} * @secure */ - checkoutSetupCreate: (params: RequestParams = {}) => - this.request({ - path: `/v1/checkout-setup`, - method: "POST", + newsDelete: (id: string, params: RequestParams = {}) => + this.request({ + path: `/v1/news/${id}`, + method: "DELETE", secure: true, type: ContentType.Json, format: "json", @@ -2364,18 +6671,25 @@ export class Api< }), /** - * @description Get the server config + * @description List invitations for the effective organization account, pending by default (?status=) * - * @tags config - * @name ConfigList - * @summary Get server config - * @request GET:/v1/config + * @tags organizations + * @name OrgInvitesList + * @summary List organization invitations + * @request GET:/v1/org/invites * @secure */ - configList: (params: RequestParams = {}) => - this.request({ - path: `/v1/config`, + orgInvitesList: ( + query?: { + /** Invite status filter (pending/accepted/declined/revoked) */ + status?: string; + }, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/org/invites`, method: "GET", + query: query, secure: true, type: ContentType.Json, format: "json", @@ -2383,18 +6697,22 @@ export class Api< }), /** - * @description Get list of all connected clients for the authenticated account + * @description Create a pending invitation for an email address. Invited members and sub-accounts share the plan's sub-account quota. * - * @tags connected-clients - * @name ConnectedClientsList - * @summary Get connected clients - * @request GET:/v1/connected-clients + * @tags organizations + * @name OrgInvitesCreate + * @summary Invite an account into the organization + * @request POST:/v1/org/invites * @secure */ - connectedClientsList: (params: RequestParams = {}) => - this.request({ - path: `/v1/connected-clients`, - method: "GET", + orgInvitesCreate: ( + invite: ApiOrgInviteCreateRequest, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/org/invites`, + method: "POST", + body: invite, secure: true, type: ContentType.Json, format: "json", @@ -2402,38 +6720,36 @@ export class Api< }), /** - * @description Get list of all cron jobs for the authenticated account + * @description Revoke a pending invitation * - * @tags crons - * @name CronsList - * @summary List cron jobs - * @request GET:/v1/crons + * @tags organizations + * @name OrgInvitesDelete + * @summary Revoke organization invitation + * @request DELETE:/v1/org/invites/{id} * @secure */ - cronsList: (params: RequestParams = {}) => - this.request({ - path: `/v1/crons`, - method: "GET", + orgInvitesDelete: (id: string, params: RequestParams = {}) => + this.request({ + path: `/v1/org/invites/${id}`, + method: "DELETE", secure: true, type: ContentType.Json, - format: "json", ...params, }), /** - * @description Create a new scheduled cron job + * @description List members of the effective organization account, joined with member identity * - * @tags crons - * @name CronsCreate - * @summary Create cron job - * @request POST:/v1/crons + * @tags organizations + * @name OrgMembersList + * @summary List organization members + * @request GET:/v1/org/members * @secure */ - cronsCreate: (cron: StructsCron, params: RequestParams = {}) => - this.request({ - path: `/v1/crons`, - method: "POST", - body: cron, + orgMembersList: (params: RequestParams = {}) => + this.request({ + path: `/v1/org/members`, + method: "GET", secure: true, type: ContentType.Json, format: "json", @@ -2441,37 +6757,41 @@ export class Api< }), /** - * @description Delete a cron job by ID + * @description Remove a member from the effective organization account * - * @tags crons - * @name CronsDelete - * @summary Delete cron job - * @request DELETE:/v1/crons/{id} + * @tags organizations + * @name OrgMembersDelete + * @summary Remove organization member + * @request DELETE:/v1/org/members/{id} * @secure */ - cronsDelete: (id: string, params: RequestParams = {}) => - this.request({ - path: `/v1/crons/${id}`, + orgMembersDelete: (id: string, params: RequestParams = {}) => + this.request({ + path: `/v1/org/members/${id}`, method: "DELETE", secure: true, type: ContentType.Json, - format: "json", ...params, }), /** - * @description Get details of a specific cron job by ID + * @description Change a member's role (admin/billing/member) * - * @tags crons - * @name CronsDetail - * @summary Get cron job - * @request GET:/v1/crons/{id} + * @tags organizations + * @name OrgMembersUpdate + * @summary Update organization member role + * @request PUT:/v1/org/members/{id} * @secure */ - cronsDetail: (id: string, params: RequestParams = {}) => - this.request({ - path: `/v1/crons/${id}`, - method: "GET", + orgMembersUpdate: ( + id: string, + member: ApiOrgMemberUpdateRequest, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/org/members/${id}`, + method: "PUT", + body: member, secure: true, type: ContentType.Json, format: "json", @@ -2479,58 +6799,54 @@ export class Api< }), /** - * @description Update an existing cron job configuration + * @description Removes the SAML SSO connection for the effective organization. * - * @tags crons - * @name CronsUpdate - * @summary Update cron job - * @request PUT:/v1/crons/{id} + * @tags organizations + * @name OrgSsoDelete + * @summary Delete organization SAML SSO configuration + * @request DELETE:/v1/org/sso * @secure */ - cronsUpdate: (id: string, cron: StructsCron, params: RequestParams = {}) => - this.request({ - path: `/v1/crons/${id}`, - method: "PUT", - body: cron, + orgSsoDelete: (params: RequestParams = {}) => + this.request({ + path: `/v1/org/sso`, + method: "DELETE", secure: true, - type: ContentType.Json, - format: "json", ...params, }), /** - * @description Get list of all domains for the authenticated account + * @description Returns the SAML SSO connection for the effective organization account, or null when none is configured. * - * @tags domains - * @name DomainsList - * @summary List account domains - * @request GET:/v1/domains + * @tags organizations + * @name OrgSsoList + * @summary Get organization SAML SSO configuration + * @request GET:/v1/org/sso * @secure */ - domainsList: (params: RequestParams = {}) => - this.request({ - path: `/v1/domains`, + orgSsoList: (params: RequestParams = {}) => + this.request({ + path: `/v1/org/sso`, method: "GET", secure: true, - type: ContentType.Json, format: "json", ...params, }), /** - * @description Reserve a domain for the authenticated account. Domain must be valid and not already taken. + * @description Creates a SAML SSO connection for the effective organization. Requires plan metadata saml_sso=true. Supports Okta and Microsoft Entra ID (Azure AD) style federation metadata URLs. * - * @tags domains - * @name DomainsCreate - * @summary Create domain reservation - * @request POST:/v1/domains + * @tags organizations + * @name OrgSsoCreate + * @summary Create organization SAML SSO configuration + * @request POST:/v1/org/sso * @secure */ - domainsCreate: (domain: StructsDomain, params: RequestParams = {}) => - this.request({ - path: `/v1/domains`, + orgSsoCreate: (body: ApiOrgSamlSSORequest, params: RequestParams = {}) => + this.request({ + path: `/v1/org/sso`, method: "POST", - body: domain, + body: body, secure: true, type: ContentType.Json, format: "json", @@ -2538,18 +6854,19 @@ export class Api< }), /** - * @description Delete a reserved domain by ID. Domain must not be in use by any inputs or tunnels. + * @description Updates the SAML SSO connection for the effective organization. * - * @tags domains - * @name DomainsDelete - * @summary Delete domain reservation - * @request DELETE:/v1/domains/{id} + * @tags organizations + * @name OrgSsoUpdate + * @summary Update organization SAML SSO configuration + * @request PUT:/v1/org/sso * @secure */ - domainsDelete: (id: string, params: RequestParams = {}) => - this.request({ - path: `/v1/domains/${id}`, - method: "DELETE", + orgSsoUpdate: (body: ApiOrgSamlSSORequest, params: RequestParams = {}) => + this.request({ + path: `/v1/org/sso`, + method: "PUT", + body: body, secure: true, type: ContentType.Json, format: "json", @@ -2557,51 +6874,38 @@ export class Api< }), /** - * @description Stream new webhook deliveries since the last poll. Cursor-bound to the (account, bucket, output) tuple the first call established. + * @description Lists the producer's customers that receive outbound webhooks. Pilot: requires the outbound feature flag. * - * @tags logs - * @name EventsList - * @summary Poll webhook events (cursor-mode) - * @request GET:/v1/events + * @tags outbound + * @name OutboundConsumersList + * @summary List outbound consumers + * @request GET:/v1/outbound/consumers * @secure */ - eventsList: ( - query?: { - /** Bucket ID (required on first call; cursor carries it on subsequent calls) */ - bucket?: string; - /** Output ID filter */ - output?: string; - /** Opaque resume cursor from a previous call */ - cursor?: string; - /** Page size (default 100) */ - limit?: number; - /** Lookback window on the first call (default 24h, Go duration syntax) */ - max_age?: string; - }, - params: RequestParams = {}, - ) => - this.request({ - path: `/v1/events`, + outboundConsumersList: (params: RequestParams = {}) => + this.request({ + path: `/v1/outbound/consumers`, method: "GET", - query: query, secure: true, - type: ContentType.Json, format: "json", ...params, }), /** - * @description Look up a function execution log by its id without requiring the function id in the URL. Useful for the webhook-log-detail UI, where the log only knows the ExecuteLog id (not which function emitted it). The executing function id is embedded on the row. + * @description Newest first. Signing secrets are not included. * - * @tags functions - * @name ExecLogsDetail - * @summary Get a function execution log by id (account-scoped) - * @request GET:/v1/exec-logs/{id} + * @tags outbound + * @name OutboundConsumersEndpointsList + * @summary List a consumer's outbound endpoints + * @request GET:/v1/outbound/consumers/{consumer}/endpoints * @secure */ - execLogsDetail: (id: string, params: RequestParams = {}) => - this.request({ - path: `/v1/exec-logs/${id}`, + outboundConsumersEndpointsList: ( + consumer: string, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/outbound/consumers/${consumer}/endpoints`, method: "GET", secure: true, format: "json", @@ -2609,18 +6913,23 @@ export class Api< }), /** - * @description List the functions for the authenticated account + * @description Adds a destination to a consumer. The response includes the endpoint's signing secret. * - * @tags functions - * @name FunctionsList - * @summary List functions - * @request GET:/v1/functions + * @tags outbound + * @name OutboundConsumersEndpointsCreate + * @summary Create an outbound endpoint + * @request POST:/v1/outbound/consumers/{consumer}/endpoints * @secure */ - functionsList: (params: RequestParams = {}) => - this.request({ - path: `/v1/functions`, - method: "GET", + outboundConsumersEndpointsCreate: ( + consumer: string, + endpoint: StructsOutboundEndpoint, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/outbound/consumers/${consumer}/endpoints`, + method: "POST", + body: endpoint, secure: true, type: ContentType.Json, format: "json", @@ -2628,45 +6937,59 @@ export class Api< }), /** - * @description Create a new function + * @description Deletes the consumer and its endpoints. Delivery history is kept. * - * @tags functions - * @name FunctionsCreate - * @summary Create function - * @request POST:/v1/functions + * @tags outbound + * @name OutboundConsumersDelete + * @summary Delete an outbound consumer + * @request DELETE:/v1/outbound/consumers/{id} * @secure */ - functionsCreate: ( - functionPayload: StructsCreateFunctionRequest, - params: RequestParams = {}, - ) => - this.request({ - path: `/v1/functions`, - method: "POST", - body: functionPayload, + outboundConsumersDelete: (id: string, params: RequestParams = {}) => + this.request({ + path: `/v1/outbound/consumers/${id}`, + method: "DELETE", secure: true, - type: ContentType.Json, format: "json", ...params, }), /** - * @description Generate a new function based on the provided input and output payloads + * No description * - * @tags functions - * @name FunctionsGenerateCreate - * @summary Generate function - * @request POST:/v1/functions-generate + * @tags outbound + * @name OutboundConsumersDetail + * @summary Get an outbound consumer + * @request GET:/v1/outbound/consumers/{id} * @secure */ - functionsGenerateCreate: ( - generateRequest: StructsGenerateFunctionRequest, + outboundConsumersDetail: (id: string, params: RequestParams = {}) => + this.request({ + path: `/v1/outbound/consumers/${id}`, + method: "GET", + secure: true, + format: "json", + ...params, + }), + + /** + * @description Consumer IDs are chosen by the producer. Only name and rate are updated; a deleted consumer's ID cannot be reused. + * + * @tags outbound + * @name OutboundConsumersUpdate + * @summary Create or update an outbound consumer + * @request PUT:/v1/outbound/consumers/{id} + * @secure + */ + outboundConsumersUpdate: ( + id: string, + consumer: StructsOutboundConsumer, params: RequestParams = {}, ) => - this.request({ - path: `/v1/functions-generate`, - method: "POST", - body: generateRequest, + this.request({ + path: `/v1/outbound/consumers/${id}`, + method: "PUT", + body: consumer, secure: true, type: ContentType.Json, format: "json", @@ -2674,61 +6997,59 @@ export class Api< }), /** - * @description Delete a function by its ID + * @description Delivery history is kept. * - * @tags functions - * @name FunctionsDelete - * @summary Delete function - * @request DELETE:/v1/functions/{id} + * @tags outbound + * @name OutboundEndpointsDelete + * @summary Delete an outbound endpoint + * @request DELETE:/v1/outbound/endpoints/{id} * @secure */ - functionsDelete: (id: string, params: RequestParams = {}) => - this.request({ - path: `/v1/functions/${id}`, + outboundEndpointsDelete: (id: string, params: RequestParams = {}) => + this.request({ + path: `/v1/outbound/endpoints/${id}`, method: "DELETE", secure: true, - type: ContentType.Json, format: "json", ...params, }), /** - * @description Get a function by its ID + * No description * - * @tags functions - * @name FunctionsDetail - * @summary Get function - * @request GET:/v1/functions/{id} + * @tags outbound + * @name OutboundEndpointsDetail + * @summary Get an outbound endpoint + * @request GET:/v1/outbound/endpoints/{id} * @secure */ - functionsDetail: (id: string, params: RequestParams = {}) => - this.request({ - path: `/v1/functions/${id}`, + outboundEndpointsDetail: (id: string, params: RequestParams = {}) => + this.request({ + path: `/v1/outbound/endpoints/${id}`, method: "GET", secure: true, - type: ContentType.Json, format: "json", ...params, }), /** - * @description Update an existing function + * @description Replaces the endpoint's configuration. Its state, health and signing secrets are kept. * - * @tags functions - * @name FunctionsUpdate - * @summary Update function - * @request PUT:/v1/functions/{id} + * @tags outbound + * @name OutboundEndpointsUpdate + * @summary Update an outbound endpoint + * @request PUT:/v1/outbound/endpoints/{id} * @secure */ - functionsUpdate: ( + outboundEndpointsUpdate: ( id: string, - functionPayload: StructsUpdateFunctionRequest, + endpoint: StructsOutboundEndpoint, params: RequestParams = {}, ) => - this.request({ - path: `/v1/functions/${id}`, + this.request({ + path: `/v1/outbound/endpoints/${id}`, method: "PUT", - body: functionPayload, + body: endpoint, secure: true, type: ContentType.Json, format: "json", @@ -2736,65 +7057,69 @@ export class Api< }), /** - * @description List the configuration values for a given function + * @description Newest first, with their delivery attempts, within the 35-day history. * - * @tags functions - * @name FunctionsConfigList - * @summary List function config - * @request GET:/v1/functions/{id}/config + * @tags outbound + * @name OutboundEndpointsDeliveriesList + * @summary List an outbound endpoint's deliveries + * @request GET:/v1/outbound/endpoints/{id}/deliveries * @secure */ - functionsConfigList: (id: string, params: RequestParams = {}) => - this.request({ - path: `/v1/functions/${id}/config`, + outboundEndpointsDeliveriesList: ( + id: string, + query?: { + /** Page size, at most 100 */ + limit?: number; + /** Page offset */ + offset?: number; + }, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/outbound/endpoints/${id}/deliveries`, method: "GET", + query: query, secure: true, - type: ContentType.Json, format: "json", ...params, }), /** - * @description Set the configuration value for a given function + * @description Messages published while paused are recorded as skipped; replay them with replay-missing after resuming. * - * @tags functions - * @name FunctionsConfigUpdate - * @summary Set function config - * @request PUT:/v1/functions/{id}/config + * @tags outbound + * @name OutboundEndpointsPauseCreate + * @summary Pause an outbound endpoint + * @request POST:/v1/outbound/endpoints/{id}/pause * @secure */ - functionsConfigUpdate: ( - id: string, - config: ApiSetFunctionConfigRequest, - params: RequestParams = {}, - ) => - this.request({ - path: `/v1/functions/${id}/config`, - method: "PUT", - body: config, + outboundEndpointsPauseCreate: (id: string, params: RequestParams = {}) => + this.request({ + path: `/v1/outbound/endpoints/${id}/pause`, + method: "POST", secure: true, - type: ContentType.Json, format: "json", ...params, }), /** - * @description Delete the configuration value for a given function + * @description Re-sends the endpoint's deliveries that exhausted their retries since the given time, in the background. * - * @tags functions - * @name FunctionsConfigDelete - * @summary Delete function config value - * @request DELETE:/v1/functions/{id}/config/{key} + * @tags outbound + * @name OutboundEndpointsRecoverCreate + * @summary Recover failed outbound deliveries + * @request POST:/v1/outbound/endpoints/{id}/recover * @secure */ - functionsConfigDelete: ( + outboundEndpointsRecoverCreate: ( id: string, - key: string, + recovery: ApiOutboundRecoveryBody, params: RequestParams = {}, ) => - this.request({ - path: `/v1/functions/${id}/config/${key}`, - method: "DELETE", + this.request({ + path: `/v1/outbound/endpoints/${id}/recover`, + method: "POST", + body: recovery, secure: true, type: ContentType.Json, format: "json", @@ -2802,18 +7127,23 @@ export class Api< }), /** - * @description Invoke a function by its ID + * @description Sends the deliveries skipped while the endpoint was paused or disabled, in the background. Resume the endpoint first. * - * @tags functions - * @name FunctionsInvokeCreate - * @summary Invoke function - * @request POST:/v1/functions/{id}/invoke + * @tags outbound + * @name OutboundEndpointsReplayMissingCreate + * @summary Replay skipped outbound deliveries + * @request POST:/v1/outbound/endpoints/{id}/replay-missing * @secure */ - functionsInvokeCreate: (id: string, params: RequestParams = {}) => - this.request({ - path: `/v1/functions/${id}/invoke`, + outboundEndpointsReplayMissingCreate: ( + id: string, + recovery: ApiOutboundRecoveryBody, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/outbound/endpoints/${id}/replay-missing`, method: "POST", + body: recovery, secure: true, type: ContentType.Json, format: "json", @@ -2821,41 +7151,41 @@ export class Api< }), /** - * @description Get the logs for a function + * @description Restarts deliveries and resets the endpoint's failure count. * - * @tags functions - * @name FunctionsLogsList - * @summary Get function logs - * @request GET:/v1/functions/{id}/logs + * @tags outbound + * @name OutboundEndpointsResumeCreate + * @summary Resume an outbound endpoint + * @request POST:/v1/outbound/endpoints/{id}/resume * @secure */ - functionsLogsList: (id: string, params: RequestParams = {}) => - this.request({ - path: `/v1/functions/${id}/logs`, - method: "GET", + outboundEndpointsResumeCreate: (id: string, params: RequestParams = {}) => + this.request({ + path: `/v1/outbound/endpoints/${id}/resume`, + method: "POST", secure: true, - type: ContentType.Json, format: "json", ...params, }), /** - * @description Get the logs for a function + * @description Re-sends message_id to the endpoint in the background and returns the recovery task. * - * @tags functions - * @name FunctionsLogsDetail - * @summary Get function logs - * @request GET:/v1/functions/{id}/logs/{logId} + * @tags outbound + * @name OutboundEndpointsRetryCreate + * @summary Retry one outbound delivery + * @request POST:/v1/outbound/endpoints/{id}/retry * @secure */ - functionsLogsDetail: ( + outboundEndpointsRetryCreate: ( id: string, - logId: string, + recovery: ApiOutboundRecoveryBody, params: RequestParams = {}, ) => - this.request({ - path: `/v1/functions/${id}/logs/${logId}`, - method: "GET", + this.request({ + path: `/v1/outbound/endpoints/${id}/retry`, + method: "POST", + body: recovery, secure: true, type: ContentType.Json, format: "json", @@ -2863,129 +7193,124 @@ export class Api< }), /** - * @description Get paginated list of webhook logs from warehouse for the authenticated account + * No description * - * @tags logs - * @name LogsList - * @summary List webhook logs from warehouse (paginated) - * @request GET:/v1/logs + * @tags outbound + * @name OutboundEndpointsSecretRevealCreate + * @summary Reveal an outbound endpoint's signing secret + * @request POST:/v1/outbound/endpoints/{id}/secret/reveal * @secure */ - logsList: ( - query: { - /** Filter by bucket ID */ - bucket: string; - /** Number of results per page */ - limit?: number; - /** Offset for pagination */ - offset?: number; - /** From date (YYYY-MM-DD or RFC3339) */ - from?: string; - /** To date (YYYY-MM-DD or RFC3339) */ - to?: string; - /** Filter by status (sent, failed, stalled, received, rejected) */ - status?: string; - /** Opaque pagination cursor (turbostore accounts; takes precedence over offset) */ - cursor?: string; - }, + outboundEndpointsSecretRevealCreate: ( + id: string, params: RequestParams = {}, ) => - this.request({ - path: `/v1/logs`, - method: "GET", - query: query, + this.request({ + path: `/v1/outbound/endpoints/${id}/secret/reveal`, + method: "POST", secure: true, - type: ContentType.Json, format: "json", ...params, }), /** - * @description Get account log statistics + * @description Returns the new secret. The previous secret keeps signing for 24 hours; another rotation is refused until then. * - * @tags logs - * @name LogsStatsList - * @summary Get account log statistics - * @request GET:/v1/logs-stats + * @tags outbound + * @name OutboundEndpointsSecretRotateCreate + * @summary Rotate an outbound endpoint's signing secret + * @request POST:/v1/outbound/endpoints/{id}/secret/rotate * @secure */ - logsStatsList: ( - query?: { - /** From date (YYYY-MM-DD) */ - from?: string; - /** To date (YYYY-MM-DD) */ - to?: string; - /** Filter by bucket ID */ - bucketId?: string; - }, + outboundEndpointsSecretRotateCreate: ( + id: string, params: RequestParams = {}, ) => - this.request({ - path: `/v1/logs-stats`, - method: "GET", - query: query, + this.request({ + path: `/v1/outbound/endpoints/${id}/secret/rotate`, + method: "POST", secure: true, - type: ContentType.Json, format: "json", ...params, }), /** - * @description Get detailed information about a specific webhook log from warehouse + * @description Lists the producer's event catalog. * - * @tags logs - * @name LogsDetail - * @summary Get log details from warehouse - * @request GET:/v1/logs/{id} + * @tags outbound + * @name OutboundEventTypesList + * @summary List outbound event types + * @request GET:/v1/outbound/event-types * @secure */ - logsDetail: (id: string, params: RequestParams = {}) => - this.request({ - path: `/v1/logs/${id}`, + outboundEventTypesList: (params: RequestParams = {}) => + this.request({ + path: `/v1/outbound/event-types`, method: "GET", secure: true, - type: ContentType.Json, format: "json", ...params, }), /** - * @description Update a webhook log. Can be used to update status, response body, headers and status code. Only modifiable within first 10 seconds. + * No description * - * @tags logs - * @name LogsUpdate - * @summary Update log - * @request PUT:/v1/logs/{id} + * @tags outbound + * @name OutboundEventTypesCreate + * @summary Create or update an outbound event type + * @request POST:/v1/outbound/event-types * @secure */ - logsUpdate: (id: string, log: StructsLog, params: RequestParams = {}) => - this.request({ - path: `/v1/logs/${id}`, - method: "PUT", - body: log, + outboundEventTypesCreate: ( + eventType: StructsOutboundEventType, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/outbound/event-types`, + method: "POST", + body: eventType, secure: true, type: ContentType.Json, + format: "json", ...params, }), /** - * @description Perform an action on a webhook log from warehouse (e.g., resend) + * @description Refused while an endpoint subscribes to the event type by name. * - * @tags logs - * @name LogsActionCreate - * @summary Perform action on log from warehouse - * @request POST:/v1/logs/{id}/action + * @tags outbound + * @name OutboundEventTypesDelete + * @summary Delete an outbound event type + * @request DELETE:/v1/outbound/event-types/{name} * @secure */ - logsActionCreate: ( - id: string, - action: ApiActionLogRequest, + outboundEventTypesDelete: (name: string, params: RequestParams = {}) => + this.request({ + path: `/v1/outbound/event-types/${name}`, + method: "DELETE", + secure: true, + format: "json", + ...params, + }), + + /** + * @description The name in the path wins over a name in the body. + * + * @tags outbound + * @name OutboundEventTypesUpdate + * @summary Create or update an outbound event type + * @request PUT:/v1/outbound/event-types/{name} + * @secure + */ + outboundEventTypesUpdate: ( + name: string, + eventType: StructsOutboundEventType, params: RequestParams = {}, ) => - this.request({ - path: `/v1/logs/${id}/action`, - method: "POST", - body: action, + this.request({ + path: `/v1/outbound/event-types/${name}`, + method: "PUT", + body: eventType, secure: true, type: ContentType.Json, format: "json", @@ -2993,33 +7318,29 @@ export class Api< }), /** - * @description Returns 1-minute resolution counts split by status plus + * @description Newest first, without payloads. * - * @tags logs - * @name LogsHistogramList - * @summary Per-minute log histogram for the explorer timeline - * @request GET:/v1/logs/histogram + * @tags outbound + * @name OutboundMessagesList + * @summary List outbound messages + * @request GET:/v1/outbound/messages * @secure */ - logsHistogramList: ( + outboundMessagesList: ( query?: { - /** From timestamp (RFC3339 or YYYY-MM-DD); default: 1h ago */ - from?: string; - /** To timestamp (RFC3339 or YYYY-MM-DD); default: now */ - to?: string; - /** Filter to a single bucket */ - bucket_id?: string; - /** Filter to a single output */ - output_id?: string; - /** Filter to a single status (sent, failed, stalled, received, rejected, preparing) */ - status?: string; - /** Filter to a single HTTP status code */ - status_code?: number; + /** Consumer ID */ + consumer?: string; + /** Event type */ + event_type?: string; + /** Page size, at most 100 */ + limit?: number; + /** Page offset */ + offset?: number; }, params: RequestParams = {}, ) => - this.request({ - path: `/v1/logs/histogram`, + this.request({ + path: `/v1/outbound/messages`, method: "GET", query: query, secure: true, @@ -3028,18 +7349,22 @@ export class Api< }), /** - * @description Get list of all managed certificates for the authenticated account + * @description Accepts a message for signed, asynchronous delivery to every endpoint of the consumer subscribed to its event type. Reusing an Idempotency-Key with the same message returns the original receipt. * - * @tags managed-certs - * @name ManagedCertsList - * @summary List managed certificates - * @request GET:/v1/managed-certs + * @tags outbound + * @name OutboundMessagesCreate + * @summary Publish an outbound message + * @request POST:/v1/outbound/messages * @secure */ - managedCertsList: (params: RequestParams = {}) => - this.request({ - path: `/v1/managed-certs`, - method: "GET", + outboundMessagesCreate: ( + message: StructsPublishOutboundMessageRequest, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/outbound/messages`, + method: "POST", + body: message, secure: true, type: ContentType.Json, format: "json", @@ -3047,57 +7372,53 @@ export class Api< }), /** - * @description Create a new managed SSL certificate for a domain + * @description Returns the payload and each endpoint's delivery with its attempts. Recently accepted messages may still be preparing. * - * @tags managed-certs - * @name ManagedCertsCreate - * @summary Create managed certificate - * @request POST:/v1/managed-certs + * @tags outbound + * @name OutboundMessagesDetail + * @summary Get an outbound message + * @request GET:/v1/outbound/messages/{id} * @secure */ - managedCertsCreate: ( - cert: ApiCreateManagedCertRequest, - params: RequestParams = {}, - ) => - this.request({ - path: `/v1/managed-certs`, - method: "POST", - body: cert, + outboundMessagesDetail: (id: string, params: RequestParams = {}) => + this.request({ + path: `/v1/outbound/messages/${id}`, + method: "GET", secure: true, - type: ContentType.Json, format: "json", ...params, }), /** - * @description Delete a managed certificate by ID + * No description * - * @tags managed-certs - * @name ManagedCertsDelete - * @summary Delete managed certificate - * @request DELETE:/v1/managed-certs/{id} + * @tags outbound + * @name OutboundRecoveryTasksDetail + * @summary Get an outbound recovery task + * @request GET:/v1/outbound/recovery-tasks/{id} * @secure */ - managedCertsDelete: (id: string, params: RequestParams = {}) => - this.request({ - path: `/v1/managed-certs/${id}`, - method: "DELETE", + outboundRecoveryTasksDetail: (id: string, params: RequestParams = {}) => + this.request({ + path: `/v1/outbound/recovery-tasks/${id}`, + method: "GET", secure: true, + format: "json", ...params, }), /** - * @description Get all news entries + * @description Returns optional add-on items (like extra webhooks) available for each plan * - * @tags news - * @name NewsList - * @summary Get news entries - * @request GET:/v1/news + * @tags billing + * @name PlansOptionalItemsList + * @summary List optional items for plans + * @request GET:/v1/plans/optional-items * @secure */ - newsList: (params: RequestParams = {}) => - this.request({ - path: `/v1/news`, + plansOptionalItemsList: (params: RequestParams = {}) => + this.request({ + path: `/v1/plans/optional-items`, method: "GET", secure: true, type: ContentType.Json, @@ -3106,22 +7427,40 @@ export class Api< }), /** - * @description Create a new news entry + * @description Re-delivers a stored webhook log to its endpoint and updates that log in place. Relies on turbostore v2. * - * @tags news - * @name NewsCreate - * @summary Create news entry - * @request POST:/v1/news + * @tags retry + * @name RetryMessagesCreate + * @summary Retry a single webhook message + * @request POST:/v1/retry/messages/{id} * @secure */ - newsCreate: ( - newsEntry: StructsNewsEntryCreateRequest, + retryMessagesCreate: (id: string, params: RequestParams = {}) => + this.request({ + path: `/v1/retry/messages/${id}`, + method: "POST", + secure: true, + format: "json", + ...params, + }), + + /** + * @description Re-delivers every failed webhook log in a bucket within the given window. Returns a task that can be polled for progress. + * + * @tags retry + * @name RetryRecoverCreate + * @summary Recover failed webhook messages + * @request POST:/v1/retry/recover + * @secure + */ + retryRecoverCreate: ( + body: ApiRetryBulkRequest, params: RequestParams = {}, ) => - this.request({ - path: `/v1/news`, + this.request({ + path: `/v1/retry/recover`, method: "POST", - body: newsEntry, + body: body, secure: true, type: ContentType.Json, format: "json", @@ -3129,18 +7468,22 @@ export class Api< }), /** - * @description Delete a news entry by ID + * @description Re-delivers webhook logs that were persisted but never attempted against their output within the given window. Returns a task that can be polled for progress. * - * @tags news - * @name NewsDelete - * @summary Delete news entry - * @request DELETE:/v1/news/{id} + * @tags retry + * @name RetryReplayMissingCreate + * @summary Replay never-attempted webhook messages + * @request POST:/v1/retry/replay-missing * @secure */ - newsDelete: (id: string, params: RequestParams = {}) => - this.request({ - path: `/v1/news/${id}`, - method: "DELETE", + retryReplayMissingCreate: ( + body: ApiRetryBulkRequest, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/retry/replay-missing`, + method: "POST", + body: body, secure: true, type: ContentType.Json, format: "json", @@ -3148,20 +7491,44 @@ export class Api< }), /** - * @description Returns optional add-on items (like extra webhooks) available for each plan + * No description * - * @tags billing - * @name PlansOptionalItemsList - * @summary List optional items for plans - * @request GET:/v1/plans/optional-items + * @tags retry + * @name RetryTasksList + * @summary List retry tasks + * @request GET:/v1/retry/tasks * @secure */ - plansOptionalItemsList: (params: RequestParams = {}) => - this.request({ - path: `/v1/plans/optional-items`, + retryTasksList: ( + query?: { + /** Filter by bucket ID */ + bucket?: string; + }, + params: RequestParams = {}, + ) => + this.request({ + path: `/v1/retry/tasks`, + method: "GET", + query: query, + secure: true, + format: "json", + ...params, + }), + + /** + * No description + * + * @tags retry + * @name RetryTasksDetail + * @summary Get a retry task + * @request GET:/v1/retry/tasks/{id} + * @secure + */ + retryTasksDetail: (id: string, params: RequestParams = {}) => + this.request({ + path: `/v1/retry/tasks/${id}`, method: "GET", secure: true, - type: ContentType.Json, format: "json", ...params, }), @@ -3186,7 +7553,7 @@ export class Api< }), /** - * @description Create a new service connection + * @description Create a credentialed service connection. Webhook Relay AI is built in and is imported by Functions with require("ai") without a service connection. * * @tags service-connections * @name ServiceConnectionsCreate @@ -3635,5 +8002,98 @@ export class Api< format: "json", ...params, }), + + /** + * @description List pending, unexpired invitations addressed to the authenticated account's email + * + * @tags organizations + * @name UserInvitationsList + * @summary List my pending invitations + * @request GET:/v1/user/invitations + * @secure + */ + userInvitationsList: (params: RequestParams = {}) => + this.request({ + path: `/v1/user/invitations`, + method: "GET", + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Accept a pending invitation addressed to the authenticated account's email. Requires a verified email. + * + * @tags organizations + * @name UserInvitationsAcceptCreate + * @summary Accept an invitation + * @request POST:/v1/user/invitations/{id}/accept + * @secure + */ + userInvitationsAcceptCreate: (id: string, params: RequestParams = {}) => + this.request({ + path: `/v1/user/invitations/${id}/accept`, + method: "POST", + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Decline a pending invitation addressed to the authenticated account's email + * + * @tags organizations + * @name UserInvitationsDeclineCreate + * @summary Decline an invitation + * @request POST:/v1/user/invitations/{id}/decline + * @secure + */ + userInvitationsDeclineCreate: (id: string, params: RequestParams = {}) => + this.request({ + path: `/v1/user/invitations/${id}/decline`, + method: "POST", + secure: true, + type: ContentType.Json, + ...params, + }), + + /** + * @description List organizations the authenticated account belongs to. Always actor-scoped: the org override never applies to /v1/user/ routes. + * + * @tags organizations + * @name UserMembershipsList + * @summary List my organization memberships + * @request GET:/v1/user/memberships + * @secure + */ + userMembershipsList: (params: RequestParams = {}) => + this.request({ + path: `/v1/user/memberships`, + method: "GET", + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Remove the authenticated account's own membership. The path ID is the organization account ID. + * + * @tags organizations + * @name UserMembershipsDelete + * @summary Leave an organization + * @request DELETE:/v1/user/memberships/{id} + * @secure + */ + userMembershipsDelete: (id: string, params: RequestParams = {}) => + this.request({ + path: `/v1/user/memberships/${id}`, + method: "DELETE", + secure: true, + type: ContentType.Json, + ...params, + }), }; } diff --git a/src/index.ts b/src/index.ts index 8807a13..f2b61c6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -47,6 +47,14 @@ export { OutputsResource } from "./resources/outputs.js"; export { ServiceConnectionsResource } from "./resources/serviceConnections.js"; export { FunctionsResource } from "./resources/functions.js"; export { WebhooksResource } from "./resources/webhooks.js"; +export { + OutboundResource, + OutboundConsumersResource, + OutboundEventTypesResource, + OutboundEndpointsResource, + OutboundMessagesResource, + OutboundRecoveryTasksResource, +} from "./resources/outbound.js"; // Streaming export { WebhookPoller, type PollOptions } from "./streaming/poller.js"; diff --git a/src/params.ts b/src/params.ts index 882229c..90e965e 100644 --- a/src/params.ts +++ b/src/params.ts @@ -46,6 +46,17 @@ const functionAliases: Record = { outputPayload: "output_payload", }; +const outboundEndpointAliases: Record = { + eventTypes: "event_types", + autoDisable: "auto_disable", + functionId: "function_id", +}; + +const outboundMessageAliases: Record = { + eventType: "event_type", + eventId: "event_id", +}; + export function inputParams(params: T): T { return applyAliases(params, inputAliases) as T; } @@ -66,6 +77,14 @@ export function functionParams(params: T): T { return applyAliases(params, functionAliases) as T; } +export function outboundEndpointParams(params: T): T { + return applyAliases(params, outboundEndpointAliases) as T; +} + +export function outboundMessageParams(params: T): T { + return applyAliases(params, outboundMessageAliases) as T; +} + function applyAliases(params: object, aliases: Record): Params { const out: Params = {}; for (const [key, value] of Object.entries(params)) { diff --git a/src/resources/outbound.ts b/src/resources/outbound.ts new file mode 100644 index 0000000..dfe8ca6 --- /dev/null +++ b/src/resources/outbound.ts @@ -0,0 +1,327 @@ +import type { HttpClient } from "../http.js"; +import { outboundEndpointParams, outboundMessageParams } from "../params.js"; +import type { + ListOutboundDeliveriesParams, + ListOutboundMessagesParams, + OutboundConsumer, + OutboundDelivery, + OutboundEndpoint, + OutboundEndpointParams, + OutboundEndpointWithSecret, + OutboundEventType, + OutboundMessage, + OutboundRecoveryParams, + OutboundRecoveryTask, + PublishOutboundMessageOptions, + PublishOutboundMessageParams, + UpsertOutboundConsumerParams, + UpsertOutboundEventTypeParams, +} from "../types.js"; + +const segment = encodeURIComponent; + +/** Your customers (consumers) that receive outbound webhooks. */ +export class OutboundConsumersResource { + constructor(private readonly http: HttpClient) {} + + /** List your consumers. */ + list(): Promise { + return this.http.unwrap( + this.http.api.v1.outboundConsumersList(), + "GET", + "/v1/outbound/consumers", + ); + } + + /** Get a consumer by ID. */ + get(id: string): Promise { + return this.http.unwrap( + this.http.api.v1.outboundConsumersDetail(segment(id)), + "GET", + "/v1/outbound/consumers/{id}", + ); + } + + /** + * Create the consumer or update its name and rate. A deleted consumer's ID + * cannot be reused. + */ + upsert(id: string, params: UpsertOutboundConsumerParams = {}): Promise { + return this.http.unwrap( + this.http.api.v1.outboundConsumersUpdate(segment(id), params), + "PUT", + "/v1/outbound/consumers/{id}", + ); + } + + /** Delete the consumer and its endpoints. Delivery history is kept. */ + delete(id: string): Promise { + return this.http.unwrap( + this.http.api.v1.outboundConsumersDelete(segment(id)), + "DELETE", + "/v1/outbound/consumers/{id}", + ); + } +} + +/** Your event catalog, such as `invoice.paid`. */ +export class OutboundEventTypesResource { + constructor(private readonly http: HttpClient) {} + + /** List your event types. */ + list(): Promise { + return this.http.unwrap( + this.http.api.v1.outboundEventTypesList(), + "GET", + "/v1/outbound/event-types", + ); + } + + /** Create the event type or update its description, example and deprecation. */ + upsert(name: string, params: UpsertOutboundEventTypeParams = {}): Promise { + return this.http.unwrap( + // The generated type narrows `example` to an object; any JSON value is valid. + this.http.api.v1.outboundEventTypesUpdate(segment(name), { ...params, name } as never), + "PUT", + "/v1/outbound/event-types/{name}", + ); + } + + /** Delete an event type no endpoint subscribes to. */ + delete(name: string): Promise { + return this.http.unwrap( + this.http.api.v1.outboundEventTypesDelete(segment(name)), + "DELETE", + "/v1/outbound/event-types/{name}", + ); + } +} + +/** Consumers' HTTPS destinations, their delivery history and recovery. */ +export class OutboundEndpointsResource { + constructor(private readonly http: HttpClient) {} + + /** List a consumer's endpoints, newest first. */ + list(consumerId: string): Promise { + return this.http.unwrap( + this.http.api.v1.outboundConsumersEndpointsList(segment(consumerId)), + "GET", + "/v1/outbound/consumers/{consumer}/endpoints", + ); + } + + /** Get an endpoint by ID. */ + get(id: string): Promise { + return this.http.unwrap( + this.http.api.v1.outboundEndpointsDetail(segment(id)), + "GET", + "/v1/outbound/endpoints/{id}", + ); + } + + /** + * Register an HTTPS endpoint for a consumer. The result carries the signing + * secret your customer verifies deliveries with. + * + * ```ts + * const endpoint = await relay.outbound.endpoints.create("customer_42", { + * url: "https://customer.example/webhooks", + * eventTypes: ["invoice.paid"], + * }); + * ``` + */ + create(consumerId: string, params: OutboundEndpointParams): Promise { + return this.http.unwrap( + this.http.api.v1.outboundConsumersEndpointsCreate( + segment(consumerId), + outboundEndpointParams(params), + ), + "POST", + "/v1/outbound/consumers/{consumer}/endpoints", + ); + } + + /** Replace an endpoint's configuration. Its state and signing secrets are kept. */ + update(id: string, params: OutboundEndpointParams): Promise { + return this.http.unwrap( + this.http.api.v1.outboundEndpointsUpdate(segment(id), outboundEndpointParams(params)), + "PUT", + "/v1/outbound/endpoints/{id}", + ); + } + + /** Delete an endpoint. Delivery history is kept. */ + delete(id: string): Promise { + return this.http.unwrap( + this.http.api.v1.outboundEndpointsDelete(segment(id)), + "DELETE", + "/v1/outbound/endpoints/{id}", + ); + } + + /** + * Stop deliveries. Messages published while paused are recorded as skipped; + * send them later with {@link replayMissing}. + */ + pause(id: string): Promise { + return this.http.unwrap( + this.http.api.v1.outboundEndpointsPauseCreate(segment(id)), + "POST", + "/v1/outbound/endpoints/{id}/pause", + ); + } + + /** Restart deliveries and reset the failure count. */ + resume(id: string): Promise { + return this.http.unwrap( + this.http.api.v1.outboundEndpointsResumeCreate(segment(id)), + "POST", + "/v1/outbound/endpoints/{id}/resume", + ); + } + + /** Replace the signing secret. The previous one keeps signing for 24 hours. */ + async rotateSecret(id: string): Promise { + const { secret } = await this.http.unwrap<{ secret: string }>( + this.http.api.v1.outboundEndpointsSecretRotateCreate(segment(id)), + "POST", + "/v1/outbound/endpoints/{id}/secret/rotate", + ); + return secret; + } + + /** Return the current signing secret. */ + async revealSecret(id: string): Promise { + const { secret } = await this.http.unwrap<{ secret: string }>( + this.http.api.v1.outboundEndpointsSecretRevealCreate(segment(id)), + "POST", + "/v1/outbound/endpoints/{id}/secret/reveal", + ); + return secret; + } + + /** List the endpoint's deliveries, newest first. */ + deliveries(id: string, params: ListOutboundDeliveriesParams = {}): Promise { + return this.http.unwrap( + this.http.api.v1.outboundEndpointsDeliveriesList(segment(id), params), + "GET", + "/v1/outbound/endpoints/{id}/deliveries", + ); + } + + /** Re-send one message to the endpoint in the background. */ + retry(id: string, messageId: string): Promise { + return this.http.unwrap( + this.http.api.v1.outboundEndpointsRetryCreate(segment(id), { message_id: messageId }), + "POST", + "/v1/outbound/endpoints/{id}/retry", + ); + } + + /** Re-send deliveries whose retries were exhausted since `since` (default: last 24 hours). */ + recover(id: string, params: OutboundRecoveryParams = {}): Promise { + return this.http.unwrap( + this.http.api.v1.outboundEndpointsRecoverCreate(segment(id), params), + "POST", + "/v1/outbound/endpoints/{id}/recover", + ); + } + + /** + * Send deliveries skipped while the endpoint was paused or disabled, since + * `since` (default: last 24 hours). Resume the endpoint first. + */ + replayMissing(id: string, params: OutboundRecoveryParams = {}): Promise { + return this.http.unwrap( + this.http.api.v1.outboundEndpointsReplayMissingCreate(segment(id), params), + "POST", + "/v1/outbound/endpoints/{id}/replay-missing", + ); + } +} + +/** Publish messages and inspect them. */ +export class OutboundMessagesResource { + constructor(private readonly http: HttpClient) {} + + /** + * Accept a message for signed delivery to every endpoint of the consumer + * subscribed to its event type. Delivery is asynchronous: the result is the + * durable acceptance receipt. + * + * ```ts + * await relay.outbound.messages.publish( + * { consumer: "customer_42", eventType: "invoice.paid", payload: { invoice_id: "inv_123" } }, + * { idempotencyKey: "invoice-paid:inv_123" }, + * ); + * ``` + */ + publish( + params: PublishOutboundMessageParams, + options: PublishOutboundMessageOptions = {}, + ): Promise { + const headers = options.idempotencyKey + ? { "Idempotency-Key": options.idempotencyKey } + : undefined; + return this.http.unwrap( + // The generated type narrows `payload` to an object; any JSON value is valid. + this.http.api.v1.outboundMessagesCreate(outboundMessageParams(params) as never, { headers }), + "POST", + "/v1/outbound/messages", + ); + } + + /** Get a message with its payload and one delivery per addressed endpoint. */ + get(id: string): Promise { + return this.http.unwrap( + this.http.api.v1.outboundMessagesDetail(segment(id)), + "GET", + "/v1/outbound/messages/{id}", + ); + } + + /** List accepted messages, newest first, without payloads. */ + list(params: ListOutboundMessagesParams = {}): Promise { + return this.http.unwrap( + this.http.api.v1.outboundMessagesList(outboundMessageParams(params)), + "GET", + "/v1/outbound/messages", + ); + } +} + +/** Progress of background re-sends started by endpoint recovery. */ +export class OutboundRecoveryTasksResource { + constructor(private readonly http: HttpClient) {} + + /** Get a recovery task by ID. */ + get(id: string): Promise { + return this.http.unwrap( + this.http.api.v1.outboundRecoveryTasksDetail(segment(id)), + "GET", + "/v1/outbound/recovery-tasks/{id}", + ); + } +} + +/** + * Outbound webhooks (pilot): send signed webhooks to your own customers. + * Register each customer as a consumer with the HTTPS endpoints they give + * you, then publish messages. Webhook Relay signs every delivery (Standard + * Webhooks), retries failures durably and keeps the delivery history. + */ +export class OutboundResource { + readonly consumers: OutboundConsumersResource; + readonly eventTypes: OutboundEventTypesResource; + readonly endpoints: OutboundEndpointsResource; + readonly messages: OutboundMessagesResource; + readonly recoveryTasks: OutboundRecoveryTasksResource; + + constructor(http: HttpClient) { + this.consumers = new OutboundConsumersResource(http); + this.eventTypes = new OutboundEventTypesResource(http); + this.endpoints = new OutboundEndpointsResource(http); + this.messages = new OutboundMessagesResource(http); + this.recoveryTasks = new OutboundRecoveryTasksResource(http); + } +} diff --git a/src/types.ts b/src/types.ts index 9e4e6df..0a2c042 100644 --- a/src/types.ts +++ b/src/types.ts @@ -444,3 +444,176 @@ export interface WebhookLogsPage { next_cursor?: string; truncated?: boolean; } + +// --------------------------------------------------------------------------- +// Outbound webhooks (pilot): send signed webhooks to your own customers +// --------------------------------------------------------------------------- + +/** One of your customers. You choose its ID, for example your own customer ID. */ +export interface OutboundConsumer { + id: string; + name: string; + /** Default deliveries per second for the consumer's endpoints; 0 means 50. */ + rate: number; + /** RFC3339 timestamp. */ + created_at?: string; + updated_at?: string; +} + +export interface UpsertOutboundConsumerParams { + name?: string; + rate?: number; +} + +/** An entry in your event catalog, such as `invoice.paid`. */ +export interface OutboundEventType { + name: string; + description?: string; + example?: unknown; + /** Deprecated event types cannot be published. */ + deprecated?: boolean; + created_at?: string; + updated_at?: string; +} + +export interface UpsertOutboundEventTypeParams { + description?: string; + example?: unknown; + deprecated?: boolean; +} + +export type OutboundEndpointState = "active" | "failing" | "paused" | "disabled"; + +/** A consumer's HTTPS destination. */ +export interface OutboundEndpoint { + id: string; + consumer: string; + url: string; + description?: string; + event_types: string[]; + headers?: Record; + rate: number; + /** Seconds per delivery attempt; 0 means 15. */ + timeout: number; + function_id?: string; + auto_disable: boolean; + state: OutboundEndpointState; + consecutive_failures?: number; + failing_since?: string; + /** When the secret replaced by the last rotation stops signing deliveries. */ + previous_secret_expires_at?: string; + created_at?: string; + updated_at?: string; +} + +/** A new endpoint with its signing secret, returned only on creation. */ +export interface OutboundEndpointWithSecret extends OutboundEndpoint { + secret: string; +} + +export interface OutboundEndpointParams { + /** Public HTTPS URL. */ + url: string; + /** Event types to deliver, or `["*"]` for all. */ + event_types?: string[]; + eventTypes?: string[]; + description?: string; + headers?: Record; + /** Deliveries per second; 0 uses the consumer's rate. */ + rate?: number; + /** Seconds per attempt, up to 60; 0 means 15. */ + timeout?: number; + /** Disable after 100 consecutive failed deliveries over at least 12 hours. */ + auto_disable?: boolean; + autoDisable?: boolean; + /** Function that may rewrite the JSON body or drop the message. */ + function_id?: string; + functionId?: string; +} + +export interface PublishOutboundMessageParams { + consumer: string; + event_type?: string; + eventType?: string; + /** Your own event ID, delivered with the message. */ + event_id?: string; + eventId?: string; + /** Any JSON value, up to 256 KiB. */ + payload: unknown; +} + +export interface PublishOutboundMessageOptions { + /** + * Makes publishing safe to retry: repeating a publish with the same key and + * message returns the original message instead of publishing again. + */ + idempotencyKey?: string; +} + +/** An outbound delivery attempt. */ +export interface OutboundDeliveryAttempt { + attempt_no: number; + started_at?: string; + finished_at?: string; + duration_ms?: number; + status_code?: number; + outcome?: string; + error?: string; + response_body?: string; +} + +/** A message's delivery to one endpoint. `output_id` is the endpoint ID. */ +export interface OutboundDelivery extends WebhookLog { + message_id?: string; + consumer_id?: string; + event_type?: string; + attempts?: OutboundDeliveryAttempt[]; +} + +/** An accepted message. */ +export interface OutboundMessage { + id: string; + consumer: string; + event_type: string; + event_id?: string; + payload?: unknown; + endpoint_ids: string[]; + created_at?: string; + /** When deliveries were queued; absent while the message is still preparing. */ + enqueued_at?: string; + /** Set by `messages.get`: one delivery per addressed endpoint. */ + deliveries?: OutboundDelivery[]; +} + +export interface ListOutboundMessagesParams { + consumer?: string; + event_type?: string; + eventType?: string; + limit?: number; + offset?: number; +} + +export interface ListOutboundDeliveriesParams { + limit?: number; + offset?: number; +} + +export interface OutboundRecoveryParams { + /** RFC3339 start of the window; defaults to 24 hours ago. */ + since?: string; +} + +/** Progress of a background re-send. */ +export interface OutboundRecoveryTask { + id: string; + endpoint_id: string; + message_id?: string; + kind: "retry" | "recover" | "replay-missing"; + status: "pending" | "running" | "completed" | "failed"; + since?: string; + until?: string; + processed: number; + error?: string; + created_at?: string; + updated_at?: string; +} diff --git a/swagger/swagger.yaml b/swagger/swagger.yaml index b442469..230da97 100644 --- a/swagger/swagger.yaml +++ b/swagger/swagger.yaml @@ -1,2111 +1,4928 @@ definitions: - api.Response: + agent.AdminConversation: properties: - id: + account_id: type: string - status: + approvals: + description: |- + Approvals is how many destructive calls asked the user; Denied counts + those declined, expired or cancelled (anything that did not run). + type: integer + approvals_approved: + type: integer + approvals_denied: + type: integer + approved_scopes: + description: |- + ApprovedScopes are the harness scopes the user widened this + conversation by ("routing:drop"), space separated. Approvals outlive + a turn: each turn is its own session, so the widening is replayed on + top of the role's grant when the next turn starts. type: string - type: object - api.ServerConfig: - properties: - turnstile_disabled: - type: boolean - version: + cache_hit_rate: + type: number + cache_miss_cost_usd: + type: number + cache_read_tokens: + type: integer + cache_write_tokens: + type: integer + context_id: type: string - type: object - api.accessTokenCreateResponse: - properties: - key: + context_kind: + description: |- + ContextKind / ContextID name the page the conversation was opened + from: "function" + a function ID for the function details page. type: string - secret: + created_at: type: string - type: object - api.actionLogRequest: - properties: - action: + created_by: + description: |- + CreatedBy is the acting member in an organization context, the + account itself otherwise. type: string - output: - description: output ID, if not specified defaults to original output + email: type: string - process_policy: - description: skip/force + grant: + description: Grant is the harness grant label the conversation runs under. type: string - type: object - api.createAccessTokenRequest: - properties: - api_access: + grant_label: type: string - description: + id: type: string - scopes: - $ref: '#/definitions/api.tokenScopes' - type: object - api.createManagedCertRequest: - properties: - domain: + input_tokens: + type: integer + iterations: + type: integer + last_message_at: type: string - name: + last_stop_cause: + type: string + model_calls: + type: integer + model_failures: + type: integer + model_latency_ms: + type: integer + output_tokens: + type: integer + page: + description: |- + Page is a human label for where the chat was opened from ("Buckets", + "Bucket orders", "Access Tokens"), so the agent knows what the user is + looking at even when there is no resource to bind to. type: string - options: - additionalProperties: - type: string - type: object provider: type: string + session_turns: + type: integer + thumbs_down: + type: integer + thumbs_up: + type: integer + title: + type: string + tool_calls: + type: integer + turns: + type: integer + updated_at: + type: string + username: + type: string type: object - api.eventResponse: + agent.AdminDetail: properties: - has_more: - type: boolean - logs: + approvals: items: - $ref: '#/definitions/structs.Log' + $ref: '#/definitions/structs.AgentApproval' type: array - next_cursor: - type: string - type: object - api.listPlanOptionalItemsResponse: - properties: - plans: + conversation: + $ref: '#/definitions/agent.AdminConversation' + feedback: items: - $ref: '#/definitions/api.planOptionalItems' + $ref: '#/definitions/structs.AgentFeedback' + type: array + inferences: + items: + $ref: '#/definitions/sessionstore.InferenceRecord' + type: array + messages: + items: + $ref: '#/definitions/agent.Message' type: array + prompts: + items: + $ref: '#/definitions/sessionstore.PromptRecord' + type: array + tool_calls: + items: + $ref: '#/definitions/sessionstore.ToolCallRecord' + type: array + truncated: + $ref: '#/definitions/agent.AdminEvidenceTruncated' type: object - api.loginResponse: + agent.AdminEvidenceTruncated: properties: - mfa_required: + inferences: + type: boolean + prompts: + type: boolean + tool_calls: type: boolean - mfa_token: - type: string - token: - type: string type: object - api.logsHistogramBucketJSON: + agent.AdminPage: properties: - counts: - additionalProperties: - type: integer - type: object - latency_ms_avg: - type: number - max_retries: - type: integer - minute: - type: integer - retried: - description: |- - Retry-pressure overlay. With durable delivery on, latest-status - alone drifts to "all sent"; these counters keep outages visible - in the chart. See design §6.10.9. + items: + items: + $ref: '#/definitions/agent.AdminConversation' + type: array + limit: type: integer - retry_count: + offset: type: integer total: type: integer type: object - api.logsHistogramResponse: + agent.AdminStats: properties: - buckets: + accounts: + type: integer + approvals_approved: + type: integer + approvals_asked: + description: 'Approvals: destructive calls that paused for the user, by outcome.' + type: integer + approvals_denied: + type: integer + approvals_expired: + type: integer + approvals_pending: + type: integer + avg_model_latency_ms: + type: number + cache_hit_rate: + type: number + cache_miss_cost_usd: + type: number + cache_read_tokens: + type: integer + conversations: + type: integer + daily: items: - $ref: '#/definitions/api.logsHistogramBucketJSON' + $ref: '#/definitions/agent.DailyStat' type: array - resolution: - description: |- - Resolution echoes back the bucket size returned by the selected - histogram tier. - type: string - type: object - api.logsResponse: - properties: - data: + input_tokens: + type: integer + model_calls: + type: integer + model_failures: + type: integer + output_tokens: + type: integer + pages: items: - $ref: '#/definitions/structs.Log' + $ref: '#/definitions/agent.NamedCount' type: array - limit: + stop_causes: + items: + $ref: '#/definitions/agent.NamedCount' + type: array + thumbs_down: type: integer - next_cursor: - description: |- - NextCursor is the opaque token a caller passes back as - ?cursor=... to get the next page. Emitted only when the - caller used cursor mode (or asked for it via the flag) AND - there is at least one more row past the current page. Empty - otherwise — clients should detect end-of-stream by an empty - NextCursor or a short final page. - type: string - offset: + thumbs_up: type: integer - total: + tool_calls: + type: integer + tool_failures: + type: integer + tool_refusals: + type: integer + top_tools: + items: + $ref: '#/definitions/agent.ToolStat' + type: array + turns: type: integer - truncated: - description: |- - Truncated is true when the storage layer capped the candidate - segment set (post-manifest-prune) to its scan budget. The - returned Data still contains the newest matching rows (sort - order is newest-first), but older entries within the requested - [from, to] window may have been omitted. The UI should render - a "showing latest results — narrow the time range to see more" - banner so users on hot/bloated accounts don't think their - data is missing entirely. See pkg/turbostore/querylimit and - design.md §15.17. Omitted from the JSON when false (the - happy path). - type: boolean type: object - api.mfaConfirmRequest: + agent.AttachmentView: properties: - token: + bytes: + type: integer + media_type: + type: string + name: type: string type: object - api.mfaSetupResponse: + agent.DailyStat: properties: - enabled: - type: boolean - otpauth_url: + conversations: + type: integer + day: type: string - qr_code_data_url: + tool_calls: + type: integer + turns: + type: integer + type: object + agent.Message: + properties: + attachments: + items: + $ref: '#/definitions/agent.AttachmentView' + type: array + role: type: string - secret: + text: type: string + tool_calls: + items: + $ref: '#/definitions/agent.ToolCallView' + type: array + tool_results: + items: + $ref: '#/definitions/agent.ToolResultView' + type: array type: object - api.mfaStatusResponse: + agent.NamedCount: properties: - enabled: - type: boolean - token: + count: + type: integer + name: type: string type: object - api.mfaVerifyRequest: + agent.Page: properties: - mfa_token: + focus_id: type: string - token: + focus_kind: + description: |- + FocusKind/FocusID name the resource the page shows: the output, input + or webhook log of the bucket the user has open, an incident, an alert + policy, or an outbound consumer, endpoint or message. + type: string + id: + type: string + kind: + type: string + label: type: string type: object - api.planChangeRequest: + agent.Quota: properties: - optional_items: - items: - $ref: '#/definitions/api.planChangeRequestOptionalItem' - type: array - plan_id: - description: Price ID + limit: + type: integer + resets_at: + description: ResetsAt is when the next month's allowance starts. type: string + unlimited: + description: Unlimited plans have no cap; Used still counts. + type: boolean + used: + description: Used and Limit are model tokens (input + output) this calendar + month. + type: integer type: object - api.planChangeRequestOptionalItem: + agent.ToolCallView: properties: - description: - description: For example "Extra 1000 webhooks" (for basic) + id: type: string - metadata: - additionalProperties: - type: string - description: For now contains "webhooks" count, later will add team seats + input: type: object - price_id: + name: type: string - quantity: - type: integer type: object - api.planChangeResponse: + agent.ToolInfo: properties: - checkout_required: - description: usually true, this is when frontend should call stripe lib + approvable: type: boolean - publishable_key: + description: type: string - session_id: + name: + type: string + needs: type: string + permitted: + type: boolean type: object - api.planOptionalItems: + agent.ToolResultView: properties: - optional_items: - items: - $ref: '#/definitions/structs.SubscriptionExtras' - type: array - plan_id: + call_id: + type: string + content: type: string + is_error: + type: boolean type: object - api.setFunctionConfigRequest: + agent.ToolStat: properties: - key: + avg_ms: + type: number + calls: + type: integer + failed: + type: integer + refused: + type: integer + tool: type: string - value: + type: object + api.AdminAgentLimitValues: + properties: + max_iterations: + type: integer + max_output_tokens: + type: integer + max_tokens_per_turn: + type: integer + plan_tokens: + additionalProperties: + type: integer + type: object + type: object + api.AdminAgentLimits: + properties: + defaults: + $ref: '#/definitions/api.AdminAgentLimitValues' + effective: + $ref: '#/definitions/api.AdminAgentLimitValues' + overrides: + $ref: '#/definitions/structs.AgentLimitOverrides' + updated_at: + type: string + updated_by: type: string type: object - api.tokenScopes: + api.AdminAgentLimitsUpdateRequest: properties: - buckets: + overrides: + $ref: '#/definitions/structs.AgentLimitOverrides' + type: object + api.AdminTrafficStatsResponse: + properties: + collectedAt: + type: string + snapshots: items: - type: string + $ref: '#/definitions/trafficstats.Snapshot' type: array - tunnels: + type: object + api.AdminUsageAlertsResponse: + properties: + alerts: items: - type: string + $ref: '#/definitions/structs.AdminUsageAlert' type: array + limit: + type: integer + offset: + type: integer + total: + type: integer type: object - api.updateAccessTokenRequest: + api.AdminUsageBucket: properties: - api_access: + account_id: type: string + created_at: + type: integer description: type: string - scopes: - $ref: '#/definitions/api.tokenScopes' + id: + type: string + inputs: + items: + $ref: '#/definitions/api.AdminUsageInput' + type: array + name: + type: string + outputs: + items: + $ref: '#/definitions/api.AdminUsageOutput' + type: array + suspended: + type: boolean type: object - rules.Argument: + api.AdminUsageBucketsResponse: properties: - base64decode: - type: boolean - envname: + buckets: + items: + $ref: '#/definitions/api.AdminUsageBucket' + type: array + limit: + type: integer + offset: + type: integer + total: + type: integer + type: object + api.AdminUsageInput: + properties: + description: type: string - name: + function_id: type: string - source: + id: + type: string + name: type: string type: object - rules.MatchRule: + api.AdminUsageOutput: properties: - ip-range: + account_id: type: string - parameter: - $ref: '#/definitions/rules.Argument' - regex: + bucket_id: type: string - secret: + bucket_name: + description: |- + BucketName/AccountID are resolved in the flat outputs listing; the + buckets listing leaves them empty (the parent row carries them). type: string - substring: + created_at: + type: integer + destination: type: string - type: + destination_provider: + description: |- + DestinationProvider is the classified destination service (jenkins, + slack, localhost, ...) or "unknown". type: string - value: + disabled: + type: boolean + function_id: + type: string + id: + type: string + internal: + type: boolean + name: + type: string + response_function_id: type: string type: object - rules.NotRule: + api.AdminUsageOutputsResponse: properties: - and: - items: - $ref: '#/definitions/rules.Rules' - type: array - match: - $ref: '#/definitions/rules.MatchRule' - or: + limit: + type: integer + offset: + type: integer + outputs: items: - $ref: '#/definitions/rules.Rules' + $ref: '#/definitions/api.AdminUsageOutput' type: array + total: + type: integer type: object - rules.Rules: + api.AdminUsageSummaryResponse: properties: - and: - items: - $ref: '#/definitions/rules.Rules' - type: array - match: - $ref: '#/definitions/rules.MatchRule' - not: - $ref: '#/definitions/rules.NotRule' - or: - items: - $ref: '#/definitions/rules.Rules' - type: array + collectedAt: + type: string + destination_providers: + additionalProperties: + type: integer + description: DestinationProviders is classified-destination -> output count. + type: object + disabled_outputs: + type: integer + internal_outputs: + type: integer + outputs_with_functions: + description: |- + OutputsWithFunctions counts outputs with a delivery or response + function attached. + type: integer + total_outputs: + type: integer type: object - structs.APIAccess: - enum: - - 0 - - 1 - - 2 - type: integer - x-enum-varnames: - - APIAccessNone - - APIAccessDisabled - - APIAccessEnabled - structs.AWSS3Input: + api.AdminUsageWebhookMonth: properties: - bucket_name: + month: + example: 2026-08 type: string - file_format: - $ref: '#/definitions/structs.ObjectStorageFileFormat' - prefix: + webhooks: + example: 125000 + type: integer + type: object + api.AdminUsageWebhooksResponse: + properties: + account_id: type: string - region: + from: + example: "2025-09-01" type: string + months: + items: + $ref: '#/definitions/api.AdminUsageWebhookMonth' + type: array + to: + example: "2026-08-30" + type: string + total_webhooks: + type: integer type: object - structs.AWSS3Output: + api.AgentApprovalRequest: properties: - bucket_name: + call_id: + description: CallID is the paused tool call, from the approval_requested event. type: string - file_format: - $ref: '#/definitions/structs.ObjectStorageFileFormat' - prefix: + remember: + description: Remember also allows the scope for the rest of the conversation + (approve). + type: boolean + scope: + description: Scope is the access the call needs, e.g. "routing:drop" (approve). type: string - region: + text: + description: Text is the reason the agent should hear (deny, optional). type: string type: object - structs.AWSSNSInput: + api.AgentControlRequest: properties: - region: - type: string - subscription_arn: + scope: + description: Scope is the harness scope to approve, e.g. "routing:drop" (widen). type: string - topic_arn: + text: + description: Text is the steering instruction (steer). type: string type: object - structs.AWSSNSOutput: + api.AgentConversationDetail: properties: - region: + active: + type: boolean + approvals: + description: |- + Approvals are the destructive calls the agent asked about in this + conversation and what the user answered, so a reopened chat still + shows who allowed what. + items: + $ref: '#/definitions/structs.AgentApproval' + type: array + conversation: + $ref: '#/definitions/structs.AgentConversation' + feedback: + items: + $ref: '#/definitions/structs.AgentFeedback' + type: array + messages: + items: + $ref: '#/definitions/agent.Message' + type: array + type: object + api.AgentConversationRequest: + properties: + context_id: type: string - topic_arn: + context_kind: + type: string + page: + description: Page labels where the chat was opened ("Buckets", "Access Tokens"). + type: string + title: type: string type: object - structs.AWSSQSInput: + api.AgentFeedbackRequest: properties: - queue_url: + comment: type: string - region: + excerpt: + type: string + message_index: + type: integer + rating: + description: up | down type: string type: object - structs.AWSSQSOutput: + api.AgentMessageRequest: properties: - queue_url: + id: type: string - region: + page: + allOf: + - $ref: '#/definitions/agent.Page' + description: |- + Page is where the user is when sending (kind, id, label), so a chat + that follows them across the dashboard still knows what they see. + text: type: string type: object - structs.AWSServiceConnection: + api.AgentQuotaExceeded: properties: - access_key_id: + code: type: string - secret_access_key: + error: type: string + quota: + $ref: '#/definitions/agent.Quota' type: object - structs.AccessToken: + api.AgentStatus: properties: - active: + enabled: type: boolean - api_access: - $ref: '#/definitions/structs.APIAccess' - created_at: + grant: type: string - deleted_at: + model: type: string + playbooks: + items: + type: string + type: array + quota: + allOf: + - $ref: '#/definitions/agent.Quota' + description: Quota is the plan's shared account-agent and managed-Function + AI token allowance. + scopes: + items: + type: string + type: array + type: object + api.AgentToolsResponse: + properties: + tools: + items: + $ref: '#/definitions/agent.ToolInfo' + type: array + type: object + api.EnterprisePlanMetadataField: + properties: + aliases: + items: + type: string + type: array description: type: string - id: + group: type: string - last_login: + key: type: string - scopes: - $ref: '#/definitions/structs.Metadata' - updated_at: + label: + type: string + minimum: + type: number + type: + enum: + - integer + - number + - boolean + type: string + unit: type: string type: object - structs.Account: + api.EnterprisePlanMetadataSchemaResponse: properties: - access_tokens: + fields: items: - $ref: '#/definitions/structs.AccessToken' + $ref: '#/definitions/api.EnterprisePlanMetadataField' type: array - active: - type: boolean - auth_type: - allOf: - - $ref: '#/definitions/structs.AccountAuthType' - description: authentication type (regular/github/google) - avatar_url: + type: object + api.Response: + properties: + id: type: string - buckets: + status: + type: string + type: object + api.ServerConfig: + properties: + email_inbound_address_template: + description: |- + EmailInboundAddressTemplate is the canonical inbound-email address format, + e.g. "{token}@in.webhookrelay-mail.com". The backend is the single source + of truth for the address shape so the UI and API render addresses + consistently instead of hardcoding the "{token}@" join — substitute + an email input's id for "{token}". Empty when inbound email is not + configured. + type: string + email_inbound_domain: + description: |- + EmailInboundDomain is the inbound-email domain ({local-part}@) + addresses are built on for this environment ("in.webhookrelay-mail.com" in + production, "dev.webhookrelay-mail.com" in development). Empty when inbound + email is not configured, which the UI uses to hide the email-input feature. + type: string + email_inbound_enabled: + description: |- + EmailInboundEnabled reports whether the inbound email endpoint is wired up + (a shared secret is provisioned). + type: boolean + turnstile_disabled: + type: boolean + version: + type: string + type: object + api.accessTokenCreateResponse: + properties: + key: + type: string + secret: + type: string + type: object + api.accountAuditResponse: + properties: + data: items: - $ref: '#/definitions/structs.Bucket' + $ref: '#/definitions/structs.AuditLog' type: array + total: + type: integer + type: object + api.actionLogRequest: + properties: + action: + type: string + output: + description: output ID, if not specified defaults to original output + type: string + process_policy: + description: skip/force + type: string + type: object + api.adminAccountIdentityUpdateRequest: + properties: + auth_type: + $ref: '#/definitions/structs.AccountAuthType' + email: + type: string + type: object + api.adminAccountSearchResult: + properties: + active: + type: boolean + auth_type: + $ref: '#/definitions/structs.AccountAuthType' company_name: type: string created_at: - type: string - current_period_end: - type: integer - current_period_start: - description: subscription period start and end, updated by stripe type: integer - deleted_at: - type: string - domains: - items: - $ref: '#/definitions/structs.Domain' - type: array email: type: string email_verified: type: boolean - failed_login_attempts: - type: integer first_name: type: string id: type: string - last_failed_login: - type: string last_login_at: - type: string + type: integer last_name: type: string - mfa_enabled: + organization: type: boolean plan_id: - description: |- - desired plan ID, used when registering new account - to create new subscription in Stripe after - email is verified type: string - plan_meta: + subscription_meta: $ref: '#/definitions/structs.Metadata' - role: + username: type: string - sub_accounts: - items: - $ref: '#/definitions/structs.SubAccount' - type: array + type: object + api.adminAccountStatus: + properties: + account_id: + type: string + bucket_count: + type: integer + current_period_end: + type: integer + current_period_start: + type: integer + effective_metadata: + $ref: '#/definitions/structs.PlanMeta' + plan_id: + type: string + plan_metadata: + $ref: '#/definitions/structs.Metadata' subscription_created: - description: Unix ts type: integer subscription_extras: items: $ref: '#/definitions/structs.SubscriptionExtras' type: array - subscription_meta: + subscription_metadata: $ref: '#/definitions/structs.Metadata' subscription_status: - description: Subscription status and fields type: string suspend_protection: - description: |- - SuspendProtection prevents account's buckets from being suspended for - overuse type: boolean - tunnels: + suspended_bucket_count: + type: integer + type: object + api.adminBucketSuspensionResponse: + properties: + affected: + type: integer + suspended: + type: boolean + total: + type: integer + type: object + api.adminBucketSuspensionUpdateRequest: + properties: + suspended: + type: boolean + type: object + api.adminOrganizationDetails: + properties: + members: items: - $ref: '#/definitions/structs.Tunnel' + $ref: '#/definitions/structs.OrganizationMemberDetails' type: array - updated_at: + organization: + $ref: '#/definitions/api.adminOrganizationSummary' + sub_accounts: + items: + $ref: '#/definitions/structs.SubAccount' + type: array + type: object + api.adminOrganizationMemberCreateRequest: + properties: + account_id: type: string - usage_alerts: - type: boolean - usage_alerts_email: + email: type: string - use_case: - description: Why have they registered? + role: type: string - use_case_completed: - type: boolean username: type: string - webhookCounts: - items: - $ref: '#/definitions/structs.WebhooksCount' - type: array type: object - structs.AccountAPIKey: + api.adminOrganizationMemberUpdateRequest: properties: - api_key: + role: type: string type: object - structs.AccountAuthType: - enum: - - regular - - github - - google - - saml - type: string - x-enum-varnames: - - AccountAuthTypeRegular - - AccountAuthTypeGithub - - AccountAuthTypeGoogle - - AccountAuthTypeSAML - structs.AdminConnectedAccount: + api.adminOrganizationSummary: properties: - account_id: - type: string + active: + type: boolean + created_at: + type: integer email: type: string - plan: + id: + type: string + member_count: + type: integer + organization_description: + type: string + organization_name: type: string plan_id: type: string - tunnel_clients: - items: - $ref: '#/definitions/structs.ConnectedTunnelClientInfo' - type: array + sub_account_count: + type: integer username: type: string - webhook_clients: - items: - $ref: '#/definitions/structs.ConnectedWebhookClientInfo' - type: array - type: object - structs.AdminConnectedClientsResponse: - properties: - accounts: - items: - $ref: '#/definitions/structs.AdminConnectedAccount' - type: array - total_count: - type: integer type: object - structs.AuthType: - enum: - - 0 - - 1 - - 2 - type: integer - x-enum-varnames: - - AuthTypeNone - - AuthTypeBasic - - AuthTypeToken - structs.AzureServiceConnection: + api.adminOrganizationUpdateRequest: properties: - client_id: - type: string - client_secret: + organization_description: type: string - tenant_id: + organization_name: type: string type: object - structs.BillingDetails: + api.adminRecentAccount: properties: - city: - type: string - country: + active: + type: boolean + auth_type: + $ref: '#/definitions/structs.AccountAuthType' + company_name: type: string - customer_id: + created_at: type: string email: type: string - line1: - type: string - line2: + email_verified: + type: boolean + first_name: type: string - name: - description: Customer full name or business name + id: type: string - postal_code: + last_name: type: string - state: + organization: + type: boolean + plan_id: type: string - tax_id: - description: Value of the tax ID. + use_case: type: string - tax_id_type: - description: Type of the tax ID, one of `ae_trn`, `au_abn`, `au_arn`, `bg_uic`, - `br_cnpj`, `br_cpf`, `ca_bn`, `ca_gst_hst`, `ca_pst_bc`, `ca_pst_mb`, `ca_pst_sk`, - `ca_qst`, `ch_vat`, `cl_tin`, `es_cif`, `eu_oss_vat`, `eu_vat`, `gb_vat`, - `ge_vat`, `hk_br`, `hu_tin`, `id_npwp`, `il_vat`, `in_gst`, `is_vat`, `jp_cn`, - `jp_rn`, `kr_brn`, `li_uid`, `mx_rfc`, `my_frp`, `my_itn`, `my_sst`, `no_vat`, - `nz_gst`, `ru_inn`, `ru_kpp`, `sa_vat`, `sg_gst`, `sg_uen`, `si_tin`, `th_vat`, - `tw_vat`, `ua_vat`, `us_ein`, or `za_vat` + username: type: string type: object - structs.Bucket: + api.adminRecentAccountsResponse: properties: - account_id: + accounts: + items: + $ref: '#/definitions/api.adminRecentAccount' + type: array + created_after: type: string - auth: - $ref: '#/definitions/structs.BucketAuth' - created_at: + limit: type: integer - cron_id: - type: string - description: - type: string - ephemeral: - description: If true, doesn't save request body, query or headers - type: boolean - id: - type: string - inputs: - items: - $ref: '#/definitions/structs.Input' - type: array - integration_configurations: - items: - $ref: '#/definitions/structs.IntegrationConfiguration' - type: array - large_webhooks: - description: |- - LargeWebhooks - if set, we allow larger than 3MB webhooks - to be sent to the bucket. This is useful for large file uploads - type: boolean - name: - type: string - outputs: - items: - $ref: '#/definitions/structs.Output' - type: array - service_connection_inputs: - items: - $ref: '#/definitions/structs.ServiceConnectionInput' - type: array - service_connection_outputs: - items: - $ref: '#/definitions/structs.ServiceConnectionOutput' - type: array - static_ip: - description: StaticIP - if set, the bucket will use a static IP (routing through - forwarding proxy) - type: boolean - stream: - description: enable/disable websocket streaming for the bucket - type: boolean - suspended: - description: |- - Set to TRUE by the curator if accounts goes over the - webhook limit - type: boolean - updated_at: + offset: + type: integer + total: type: integer type: object - structs.BucketAuth: + api.adminSubAccountCreateRequest: properties: - created_at: - type: integer - id: - type: string - password: - type: string - token: + auth_type: + $ref: '#/definitions/structs.AccountAuthType' + email: type: string - type: - $ref: '#/definitions/structs.AuthType' - updated_at: - type: integer username: type: string type: object - structs.CombinedUsage: + api.adminSuspendProtectionUpdateRequest: properties: - plan_meta: - $ref: '#/definitions/structs.PlanMeta' - usage: - $ref: '#/definitions/structs.Usage' + enabled: + type: boolean type: object - structs.ConnectedClient: + api.auditLogsResponse: properties: - tunnel_clients: - items: - $ref: '#/definitions/structs.ConnectedTunnelClient' - type: array - webhook_clients: + data: items: - $ref: '#/definitions/structs.ConnectedWebhookClient' + $ref: '#/definitions/structs.AuditLog' type: array - type: object - structs.ConnectedTunnelClient: - properties: - access_token_key: - type: string - client_ip: - type: string - client_version: - type: string - subscribed_at: + limit: type: integer - tunnels: - items: - type: string - type: array - type: object - structs.ConnectedTunnelClientInfo: - properties: - access_token_key: - type: string - client_ip: - type: string - client_version: - type: string - subscribed_at: + offset: + type: integer + total: type: integer - tunnel_names: - items: - type: string - type: array - tunnels: - items: - type: string - type: array type: object - structs.ConnectedWebhookClient: + api.bindFunctionConnectionRequest: properties: - access_token_key: - type: string - buckets: - items: - type: string - type: array - client_ip: - type: string - client_type: - type: string - client_version: - type: string - destination: + service_connection_id: type: string - subscribed_at: - type: integer type: object - structs.ConnectedWebhookClientInfo: + api.createAccessTokenRequest: properties: - access_token_key: - type: string - bucket_names: - items: - type: string - type: array - buckets: - items: - type: string - type: array - client_ip: - type: string - client_type: + api_access: type: string - client_version: + description: type: string - destination: + name: type: string - subscribed_at: - type: integer + permissions: + $ref: '#/definitions/structs.TokenPermissions' + scopes: + $ref: '#/definitions/api.tokenScopes' type: object - structs.CreateFunctionRequest: + api.createManagedCertRequest: properties: - driver: + domain: type: string name: type: string - payload: + options: + additionalProperties: + type: string + type: object + provider: type: string type: object - structs.CreateTunnelRequest: + api.creatorIdentity: properties: - addr: - description: |- - Addr specifies TCP address server would listen on, it's required - for TCP tunnels. - type: string - agent_id: - type: string - auth: - $ref: '#/definitions/structs.TunnelAuth' - crypto: - type: string - description: - type: string - destination: - type: string - features: - $ref: '#/definitions/structs.Features' - group: - type: string - host: - type: string - ingress_rules: - $ref: '#/definitions/structs.IngressRules' - name: + avatar_url: type: string - protocol: + id: type: string - region: + kind: type: string - subdomain: + username: type: string type: object - structs.Cron: + api.deletedResponse: properties: - account_id: + deleted: + type: boolean + type: object + api.endpointWithSecret: + properties: + auto_disable: + type: boolean + consecutive_failures: + type: integer + consumer: type: string - bucket: - $ref: '#/definitions/structs.Bucket' created_at: type: string - destination: - description: URL to send the webhook to + description: type: string - enabled: - type: boolean - ends_at: + event_types: + items: + type: string + type: array + failing_since: type: string function_id: - description: Function ID attached to the output type: string headers: - $ref: '#/definitions/structs.Headers' + additionalProperties: + type: string + type: object id: type: string - method: - description: |- - Payload and headers injected into the Bucket. Outputs - are still used to send the webhook - type: string - name: - type: string - next_run: - description: Populated by the handler for UI to display - type: string - payload: - type: string - recurring: - type: boolean - schedule: + previous_secret_expires_at: type: string - starts_at: - description: Dates from which the cron job starts and ends + rate: + type: integer + secret: type: string - timezone: + state: + enum: + - active + - failing + - paused + - disabled type: string + timeout: + description: seconds; zero uses OutboundDefaultTimeout + type: integer updated_at: type: string - type: object - structs.DeleteFunctionResponse: - type: object - structs.DeleteVariableResponse: - type: object - structs.DiscordOutput: - properties: - webhook_url: + url: type: string type: object - structs.Domain: + api.eventResponse: properties: - created_at: - type: integer - domain: - description: |- - Domain can be any 3rd party domain such as - user.example.com - type: string - id: - type: string - updated_at: - type: integer + has_more: + type: boolean + logs: + items: + $ref: '#/definitions/structs.Log' + type: array type: object - structs.DurabilityConfig: + api.listPlanOptionalItemsResponse: properties: - custom_delays: - description: CustomDelays is consulted only when Schedule == "custom". + plans: items: - $ref: '#/definitions/time.Duration' + $ref: '#/definitions/api.planOptionalItems' type: array - deadline: - allOf: - - $ref: '#/definitions/time.Duration' - description: |- - Deadline caps total retry duration measured from the webhook's - received_at timestamp. Zero falls through to a schedule-derived - default (~30 d for "long", ~16 h for "medium", ~25 min for - "seconds"). - enabled: - description: Enabled toggles the whole feature for this output. - type: boolean - handoff_after: - allOf: - - $ref: '#/definitions/time.Duration' - description: |- - HandoffAfter is the attempt-age threshold past which a failing - delivery is moved from the in-pubsub retry path to the durable - pending index. Zero falls through to 15 minutes — short enough - that long retries don't bloat the pubsub backlog, long enough - that transient blips don't pay an extra object-store PUT. - schedule: - description: |- - Schedule names a backoff preset ("seconds", "medium", "long", - "custom"). Empty falls through to "long" when Enabled, "seconds" - otherwise. Custom backoffs use CustomDelays. - type: string type: object - structs.Endpoint: + api.loginResponse: properties: - address: + mfa_required: + type: boolean + mfa_token: + type: string + token: type: string type: object - structs.ExecuteLog: + api.logsHistogramBucketJSON: properties: - account_id: - type: string - configuration_id: - type: string - created: + counts: + additionalProperties: + type: integer + type: object + latency_ms_avg: + type: number + max_retries: type: integer - duration: + minute: type: integer - execute_request: - $ref: '#/definitions/structs.ExecuteRequest' - execute_response: - $ref: '#/definitions/structs.ExecuteResponse' - function_id: - type: string - id: - type: string - status: - $ref: '#/definitions/structs.ExecutionStatus' - updated: + retried: + description: |- + Retry-pressure overlay. With durable delivery on, latest-status + alone drifts to "all sent"; these counters keep outages visible + in the chart. See design §6.10.9. + type: integer + retry_count: + type: integer + total: type: integer type: object - structs.ExecuteLogResponse: + api.logsHistogramResponse: properties: - execute_logs: + buckets: items: - $ref: '#/definitions/structs.ExecuteLog' + $ref: '#/definitions/api.logsHistogramBucketJSON' + type: array + resolution: + description: |- + Resolution echoes back the bucket size returned by the selected + histogram tier. + type: string + type: object + api.logsResponse: + properties: + data: + items: + $ref: '#/definitions/structs.Log' type: array limit: type: integer + next_cursor: + description: |- + NextCursor is the opaque token a caller passes back as + ?cursor=... to get the next page. Emitted only when the + caller used cursor mode (or asked for it via the flag) AND + there is at least one more row past the current page. Empty + otherwise — clients should detect end-of-stream by an empty + NextCursor or a short final page. + type: string offset: type: integer total: type: integer + truncated: + description: |- + Truncated is true when the storage layer capped the candidate + segment set (post-manifest-prune) to its scan budget. The + returned Data still contains the newest matching rows (sort + order is newest-first), but older entries within the requested + [from, to] window may have been omitted. The UI should render + a "showing latest results — narrow the time range to see more" + banner so users on hot/bloated accounts don't think their + data is missing entirely. See pkg/turbostore/querylimit and + design.md §15.17. Omitted from the JSON when false (the + happy path). + type: boolean type: object - structs.ExecuteRequest: + api.mfaConfirmRequest: properties: - account_id: + token: type: string - configuration_id: + type: object + api.mfaSetupResponse: + properties: + enabled: + type: boolean + otpauth_url: type: string - function_id: + qr_code_data_url: type: string - request: - $ref: '#/definitions/structs.Request' - request_id: + secret: type: string - response_body_path: + type: object + api.mfaStatusResponse: + properties: + enabled: + type: boolean + token: type: string type: object - structs.ExecuteResponse: + api.mfaVerifyRequest: properties: - error: + mfa_token: type: string - function_id: + token: type: string - request: - $ref: '#/definitions/structs.Request' - request_id: + type: object + api.orgInviteCreateRequest: + properties: + email: + type: string + role: type: string - request_modified: - type: boolean - response: - $ref: '#/definitions/structs.Response' - response_modified: - type: boolean - stop_forwarding: - type: boolean type: object - structs.ExecutionStatus: - enum: - - none - - success - - error - type: string - x-enum-comments: - ExecutionStatusError: "2" - ExecutionStatusNone: "0" - ExecutionStatusSuccess: "1" - x-enum-varnames: - - ExecutionStatusNone - - ExecutionStatusSuccess - - ExecutionStatusError - structs.Features: + api.orgMemberUpdateRequest: properties: - rewrite_host_header: + role: type: string - skip_insecure_verify: - description: validate TLS certificate - type: boolean type: object - structs.Function: + api.orgSamlSSORequest: properties: - account_id: + allow_jit: + type: boolean + allowed_domains: + items: + type: string + type: array + email_attribute_name: type: string - compression: + entity_id: type: string - created: - type: integer - driver: + force_authn: + type: boolean + name: type: string - id: + name_id_format: type: string - metadata: - additionalProperties: - type: string - type: object - name: + saml_metadata_url: type: string - payload: + signature_method: type: string - payload_size: - type: integer - updated: - type: integer type: object - structs.GCPGCSInput: + api.outboundErrorResponse: properties: - bucket_name: - type: string - file_format: - $ref: '#/definitions/structs.ObjectStorageFileFormat' - notification_id: - type: string - prefix: + error: type: string type: object - structs.GCPGCSOutput: + api.outboundMessageDetail: properties: - bucket_name: + consumer: type: string - file_format: - $ref: '#/definitions/structs.ObjectStorageFileFormat' - prefix: + created_at: type: string - type: object - structs.GCPPubSubInput: - properties: - subscription_name: + deliveries: + items: + $ref: '#/definitions/structs.Log' + type: array + endpoint_ids: + items: + type: string + type: array + enqueued_at: + type: string + event_id: + type: string + event_type: type: string + id: + type: string + payload: + type: object type: object - structs.GCPPubSubOutput: + api.outboundRecoveryBody: properties: - topic_name: + message_id: + description: MessageID is the message to re-send; required by retry only. + type: string + since: + description: Since starts the recovery window; defaults to 24 hours ago. type: string type: object - structs.GCPServiceConnection: + api.planChangeRequest: properties: - project_id: + optional_items: + items: + $ref: '#/definitions/api.planChangeRequestOptionalItem' + type: array + plan_id: + description: Price ID type: string - service_account_email: + required: + - plan_id + type: object + api.planChangeRequestOptionalItem: + properties: + description: + description: For example "Extra 1000 webhooks" (for basic) type: string - service_account_key: + metadata: + additionalProperties: + type: string + description: For now contains "webhooks" count, later will add team seats + type: object + price_id: type: string + quantity: + description: Quantity must be between 1 and 20. The sum across optional_items + must not exceed 20. + maximum: 20 + minimum: 1 + type: integer + required: + - price_id + - quantity type: object - structs.GenerateFunctionRequest: + api.planChangeResponse: properties: - additional_info: - description: Additional information about the function + checkout_required: + description: usually true, this is when frontend should call stripe lib + type: boolean + publishable_key: type: string - input_payload: + session_id: type: string - output_payload: - description: Desired output payload + type: object + api.planOptionalItems: + properties: + optional_items: + items: + $ref: '#/definitions/structs.SubscriptionExtras' + type: array + plan_id: type: string type: object - structs.GenerateFunctionResponse: + api.retryBulkRequest: properties: - code: - description: Function code + bucket: type: string - validation_err: - description: Validation error message + output: + description: 'optional: narrow to a single output' + type: string + since: + description: RFC3339; required (bounds the scan) + type: string + until: + description: RFC3339; optional, defaults to now type: string - validation_ok: - description: Indicates if the function is valid - type: boolean type: object - structs.Header: + api.secretResponse: properties: - values: - items: - type: string - type: array + secret: + type: string type: object - structs.Headers: - additionalProperties: true + api.setFunctionConfigRequest: + properties: + key: + type: string + value: + type: string type: object - structs.IngressRule: + api.suspiciousDetectionSettingsRequest: properties: - endpoints: - description: Endpoints - items: - $ref: '#/definitions/structs.Endpoint' - type: array - name: - description: |- - Name is an option identifier for the ingress rule, it usually is a service name - if used with webrelay-ingress + config: + $ref: '#/definitions/structs.SuspiciousDetectionConfig' + expected_version: type: string - path: - description: |- - Path is an extended POSIX regex as defined by IEEE Std 1003.1, - (i.e this follows the egrep/unix syntax, not the perl syntax) - matched against the path of an incoming request. Currently it can - contain characters disallowed from the conventional "path" - part of a URL as defined by RFC 3986. Paths must begin with - a '/'. If unspecified, the path defaults to a catch all sending - traffic to the backend. - +optional + type: object + api.suspiciousDetectionSettingsResponse: + properties: + config: + $ref: '#/definitions/structs.SuspiciousDetectionConfig' + updated_at: + type: string + updated_by: + type: string + version: type: string type: object - structs.IngressRules: + api.suspiciousEventListResponse: properties: - rules: + data: items: - $ref: '#/definitions/structs.IngressRule' + $ref: '#/definitions/structs.SuspiciousEvent' type: array + limit: + type: integer + offset: + type: integer + total: + type: integer type: object - structs.Input: + api.suspiciousEventReviewRequest: properties: - body: - items: - type: integer - type: array - bucket_id: - description: BucketID is a foreign key + log_id: type: string - created_at: - type: integer - created_by: + note: type: string - custom_domain: - description: |- - Input's domain name, can be set to work with the CNAMEs - so WHR will fetch a cert from LE - (make sure you create a CNAME DNS record for your domain to stats.uptimerobot.com. - And, it can take up to 30 mins for the custom domain to be activated.) + status: + $ref: '#/definitions/structs.SuspiciousEventStatus' + type: object + api.suspiciousEventWebhookResponse: + properties: + body_truncated: + type: boolean + webhook: + $ref: '#/definitions/structs.Log' + type: object + api.suspiciousHuntRequest: + properties: + account_id: type: string - description: + bucket_id: type: string - function_id: + cursor: type: string - headers: - allOf: - - $ref: '#/definitions/structs.Headers' - description: response details - id: + from: type: string - legacy_tls: - description: |- - LegacyTLS widens the accepted handshake to TLS 1.0/1.1 *and* the - older RSA/CBC cipher set. The two used to be split into separate - fields but the policy resolver applies them as one logical toggle, - and the dashboard surfaces them as one switch — keep the on-disk - shape matching that single concept. - type: boolean - name: + limit: + type: integer + rule_version: type: string - path_prefix: - description: PathPrefix only works when CustomDomain is set + to: type: string - response_from_output: - description: |- - either output ID or "anyOutput" to indicate that the first response - from any output is good enough. Empty string + type: object + api.suspiciousHuntResponse: + properties: + findings: + type: integer + next_cursor: type: string - status_code: + oversized_bodies: type: integer - strip_path_prefix: - description: |- - StripPathPrefix indicates whether full path should be included when - forwarding the webhook. If the path prefix is /abc and the webhook - arrives at /abc/foo, then by default the full path will be /abc/foo - type: boolean - tls_version: - description: |- - TLSVersion sets the minimum accepted TLS version for this input's HTTPS endpoint. It is a floor, not a pin: handshakes negotiate this version or any higher one the backend allows (for example 1.1 still accepts 1.2 and 1.3). - Empty value means default hardened policy. + payload_errors: + type: integer + rule_version: type: string - updated_at: + scanned: type: integer + truncated: + type: boolean type: object - structs.IntegrationConfiguration: + api.tokenScopes: properties: buckets: + description: |- + Bucket names, IDs, or glob patterns. Empty means unrestricted; !none + disables bucket subscriptions. items: - $ref: '#/definitions/structs.Bucket' + type: string type: array - configuration: - allOf: - - $ref: '#/definitions/structs.Metadata' + tunnels: description: |- - notification plugin configuration, free form JSON. Each plugin parses whatever configuration - it wants - created_at: - type: string - description: - type: string - disabled: - description: optionally disable notification (when you want to turn off events) - type: boolean - events: - description: event types, such as schedules.import.error + Tunnel names, IDs, groups, hosts, or glob patterns. Empty means + unrestricted; !none disables tunnel subscriptions. items: type: string type: array - id: - type: string - message: - description: read-only field populated by the plugin + type: object + api.updateAccessTokenRequest: + properties: + api_access: type: string - plugin: - allOf: - - $ref: '#/definitions/structs.IntegrationPlugin' - description: plugin to use, such as Slack, Webhook, Email - status: - description: read-only field populated by the plugin + description: type: string - updated_at: + name: type: string + permissions: + $ref: '#/definitions/structs.TokenPermissions' + scopes: + $ref: '#/definitions/api.tokenScopes' type: object - structs.IntegrationPlugin: - enum: - - webhook - - slack - type: string - x-enum-varnames: - - IntegrationPluginWebhook - - IntegrationPluginSlack - structs.JSONB: - additionalProperties: true - type: object - structs.Log: + api.updateAccountRequest: properties: - account_id: - type: string - body: - description: Body is either set or populated from BodyBytes during MarshalJSON() - type: string - bucket_id: + alert_notifications: + type: boolean + organization: + type: boolean + organization_description: type: string - compression: - description: |- - Compression indicates what compression type - was used + organization_logo: type: string - created_at: - type: integer - deleted_at: + organization_name: type: string - duration_ms: - type: integer - ephemeral: + usage_alerts: description: |- - If true, doesn't save request body, query or headers, - inherits from the bucket configuration + every field is a pointer with nil = keep, so partial updates + (e.g. org-profile-only PUTs) never silently reset the rest type: boolean - extra_path: + usage_alerts_50: + type: boolean + usage_alerts_75: + type: boolean + usage_alerts_email: type: string + usage_alerts_emails: + items: + type: string + type: array + type: object + functiondocs.HTTPFixture: + properties: headers: - allOf: - - $ref: '#/definitions/structs.Headers' - description: request details - id: + additionalProperties: + type: string + type: object + method: type: string - input_function_execution_id: - description: |- - InputFunctionExecutionID is the reactor ExecuteLog id for the - ingress-side function that ran before this webhook hit the - bucket. Empty when no function ran at the input stage. The UI - reads /v1/functions//logs/ for this id to render a - before/after diff. + response_body: type: string - input_id: + url: type: string - internal: - type: boolean - ip_address: + type: object + functiondocs.Method: + properties: + description: type: string - method: + example: + $ref: '#/definitions/helpers.Example' + name: type: string - output_function_execution_id: - description: |- - OutputFunctionExecutionID is the reactor ExecuteLog id for the - per-output function that ran before forwarding this delivery - to the destination. Empty when no function ran on the output. + notes: type: string - output_id: + parameters: + items: + $ref: '#/definitions/helpers.Parameter' + type: array + returns: + type: string + signature: + type: string + type: object + functiondocs.Recipe: + properties: + code: + type: string + config: + additionalProperties: + type: string + type: object + delivery_error: + type: string + expected_body: + type: string + expected_headers: + additionalProperties: + type: string + type: object + http_fixture: + $ref: '#/definitions/functiondocs.HTTPFixture' + module: + type: string + name: type: string raw_query: type: string + request_body: + type: string + request_headers: + additionalProperties: + type: string + type: object + response: + $ref: '#/definitions/functiondocs.RecipeResponse' response_body: - items: - type: integer - type: array - response_headers: - $ref: '#/definitions/structs.Headers' - retries: - type: integer - service_connection_input_type: - description: |- - ServiceConnectionInputType is set when the log originates from a service connection input - (e.g. gcp_pubsub, aws_sqs, aws_sns, aws_s3, gcp_gcs) type: string - service_connection_output_type: - description: |- - ServiceConnectionOutputType is set when the log is for a service connection output - (e.g. gcp_pubsub, aws_sqs, aws_sns, aws_s3, gcp_gcs) + response_status: + type: integer + stop_forwarding: + type: boolean + type: object + functiondocs.RecipeResponse: + properties: + body: type: string + headers: + additionalProperties: + type: string + type: object status: - $ref: '#/definitions/structs.RequestStatus' - status_code: - type: integer - updated_at: type: integer type: object - structs.LogsStats: + functiondocs.Reference: properties: - day: + driver: + type: string + markdown: + type: string + methods: + items: + $ref: '#/definitions/functiondocs.Method' + type: array + module: + type: string + recipes: + items: + $ref: '#/definitions/functiondocs.Recipe' + type: array + version: type: string - failures: - type: integer - max_retries: - type: integer - received: - type: integer - retried: - type: integer - retry_count: - type: integer - success: - type: integer type: object - structs.Metadata: - additionalProperties: true + functiondocs.Runtime: + properties: + driver: + type: string + guide: + type: string + limits: + type: string + modules: + items: + type: string + type: array + version: + type: string type: object - structs.NewsEntry: + helpers.Example: properties: - created_at: + code: type: string - id: + expected_body: type: string - message: + expected_headers: + additionalProperties: + type: string + type: object + expected_method: type: string - message_of_the_day: - type: boolean - timestamp: - description: what date to show - type: integer - updated_at: + expected_path: type: string - url: + expected_raw_query: type: string - visible: - type: boolean type: object - structs.NewsEntryCreateRequest: + helpers.Parameter: properties: - date: - description: what date to show - type: string - message: + name: type: string - message_of_the_day: + optional: type: boolean - url: + type: type: string - visible: + variadic: type: boolean type: object - structs.ObjectStorageFileFormat: - enum: - - json - - body_only - - har - type: string - x-enum-comments: - ObjectStorageFileFormatJSON: JSON format with headers, body, etc. - x-enum-varnames: - - ObjectStorageFileFormatJSON - - ObjectStorageFileFormatBody - - ObjectStorageFileFormatHAR - structs.Output: + rules.Argument: properties: - bucket_id: - description: BucketID is a foreign key + base64decode: + type: boolean + envname: type: string - created_at: - type: integer - created_by: + name: type: string - cron_id: + source: type: string - description: + type: object + rules.MatchRule: + properties: + ip-range: type: string - destination: + parameter: + $ref: '#/definitions/rules.Argument' + regex: type: string - disabled: - description: Enable/disable output destinations - type: boolean - durability: - allOf: - - $ref: '#/definitions/structs.DurabilityConfig' - description: |- - Durability configures long-period retries via the turbostore - pending-retry index. See pkg/turbostore/design.md §5.6. - Stored as JSON so we can extend without a schema migration. - function_id: - description: |- - FunctionID is used to indicate whethera code snippet should be used to - modify this webhook + secret: type: string - headers: - allOf: - - $ref: '#/definitions/structs.Headers' - description: |- - Headers that will overwrite any existing headers - from the incoming request - id: + substring: type: string - internal: - description: internal outputs will only be relayed by agents - type: boolean - lock_path: - description: |- - LockPath ensures that the request path cannot be changed from what is - specified in the destination. For example if request is coming to /v1/webhooks/xxx/github-jenkins, - with lock path 'false' and destination 'http://localhost:8080' it would go to http://localhost:8080/github-jenkins. - However, with lock path 'true', it will be sent to 'http://localhost:8080' - type: boolean - name: + type: + type: string + value: type: string - retries: - description: |- - additional retries (after the first 3 times fail). Setting - to -1 disables retries - type: integer - rules: - $ref: '#/definitions/rules.Rules' - throttle: - allOf: - - $ref: '#/definitions/structs.ThrottleConfig' - description: |- - Throttle configures per-output throughput throttling. When enabled, - the ingester/server stop delivering this output inline; webhooks are - persisted (left in RequestStatusReceived) and enqueued into the - turbostore throttle index, and the dispatcher's throttle controller - dequeues them at the configured rate/concurrency. Stored as JSON so - the schema can grow without a migration, same as Durability. - timeout: - description: response timeout - type: integer - tls_verification: - description: |- - Controls TLS verification of the certs for public - webhooks - type: boolean - updated_at: - type: integer type: object - structs.PlanMeta: + rules.NotRule: properties: - agents: - type: integer - custom_hostnames: - type: boolean - custom_subdomains: - type: boolean - custom_tls_version: - type: boolean - functions: - type: integer - https_tunnels: - type: boolean - inputs: + and: + items: + $ref: '#/definitions/rules.Rules' + type: array + match: + $ref: '#/definitions/rules.MatchRule' + or: + items: + $ref: '#/definitions/rules.Rules' + type: array + type: object + rules.Rules: + properties: + and: + items: + $ref: '#/definitions/rules.Rules' + type: array + match: + $ref: '#/definitions/rules.MatchRule' + not: + $ref: '#/definitions/rules.NotRule' + or: + items: + $ref: '#/definitions/rules.Rules' + type: array + type: object + sessionstore.InferenceRecord: + properties: + at: + type: string + attempt: type: integer - integration_configurations: + cacheMissCostUSD: + type: number + cacheMissReason: + type: string + cacheMissTokens: type: integer - large_webhooks: - type: boolean - legacy_tls: - type: boolean - logs_retention: + cacheRead: type: integer - managed_domains: + cacheWrite: type: integer - outputs: + expectedCacheTokens: type: integer - overage: - type: number - public: - description: whether plan should be visible to public + failed: type: boolean - reserved_domains: + generationMs: type: integer - sub_accounts: + id: type: integer - tls_tunnels: - type: boolean - tokens: + idleSincePreviousMs: type: integer - tunnels: + inputTokens: type: integer - webhooks: + iteration: + type: integer + kind: + type: string + latencyMs: + type: integer + outputTokens: + type: integer + outputTokensPerSecond: + type: number + prefixChanged: + type: boolean + prefixHash: + type: string + provider: + type: string + providerChanged: + type: boolean + requestID: + type: string + sessionID: + type: string + stopReason: + type: string + ttftms: type: integer + turnID: + type: string type: object - structs.Request: + sessionstore.PromptRecord: properties: - body: + acceptedAt: + type: string + attachments: + description: |- + Attachments is the JSON of the prompt's llm.Attachment slice. A recovered + prompt that never started is re-sent from this row, so dropping them here + would replay the message without its images. items: type: integer type: array - body_modified: - type: boolean - body_path: + promptID: type: string - header: - additionalProperties: - $ref: '#/definitions/structs.Header' - type: object - header_modified: - type: boolean - metadata: - additionalProperties: - type: string - type: object - method: + sessionID: type: string - method_modified: - type: boolean - modified_body_path: + settledAt: type: string - path: + startedAt: type: string - path_modified: + state: + type: string + stopCause: + type: string + text: + type: string + type: object + sessionstore.ToolCallRecord: + properties: + at: + type: string + callID: + type: string + durationMs: + type: integer + failed: type: boolean - raw_query: + id: + type: integer + iteration: + type: integer + missing: type: string - raw_query_modified: + refused: type: boolean + requestID: + type: string + sessionID: + type: string + summary: + type: string + tool: + type: string + turnID: + type: string type: object - structs.RequestStatus: + structs.APIAccess: enum: - 0 - 1 - 2 - - 3 - - 4 - - 5 type: integer - x-enum-comments: - RequestStatusFailed: "2" - RequestStatusPreparing: "0" - RequestStatusReceived: "4" - RequestStatusRejected: "5" - RequestStatusSent: "1" - RequestStatusStalled: 3 - if request destination wasn't listening - incoming - requests will be stalled x-enum-varnames: - - RequestStatusPreparing - - RequestStatusSent - - RequestStatusFailed - - RequestStatusStalled - - RequestStatusReceived - - RequestStatusRejected - structs.Response: + - APIAccessNone + - APIAccessDisabled + - APIAccessEnabled + structs.AWSS3Input: properties: - body: - items: - type: integer - type: array - body_path: + bucket_name: + type: string + file_format: + $ref: '#/definitions/structs.ObjectStorageFileFormat' + prefix: + type: string + region: type: string - header: - additionalProperties: - $ref: '#/definitions/structs.Header' - type: object - status: - type: integer type: object - structs.ServiceConnection: + structs.AWSS3Output: properties: - account_id: + bucket_name: type: string - aws_service_connection: - $ref: '#/definitions/structs.AWSServiceConnection' - azure_service_connection: - $ref: '#/definitions/structs.AzureServiceConnection' - created_at: + file_format: + $ref: '#/definitions/structs.ObjectStorageFileFormat' + prefix: type: string - error: + region: type: string - gcp_service_connection: - $ref: '#/definitions/structs.GCPServiceConnection' - id: - description: ULID, starts with prefix "scn_" + type: object + structs.AWSSNSInput: + properties: + region: type: string - last_checked: + subscription_arn: type: string - name: + topic_arn: type: string - retries: - type: integer - service_type: - $ref: '#/definitions/structs.ServiceType' - status: - $ref: '#/definitions/structs.ServiceConnectionStatus' - updated_at: + type: object + structs.AWSSNSOutput: + properties: + region: + type: string + topic_arn: type: string type: object - structs.ServiceConnectionInput: + structs.AWSSQSInput: properties: - aws_s3_input: - $ref: '#/definitions/structs.AWSS3Input' - aws_sns_input: - $ref: '#/definitions/structs.AWSSNSInput' - aws_sqs_input: - $ref: '#/definitions/structs.AWSSQSInput' - bucket_id: + queue_url: + type: string + region: + type: string + type: object + structs.AWSSQSOutput: + properties: + queue_url: + type: string + region: + type: string + type: object + structs.AWSServiceConnection: + properties: + access_key_id: type: string + secret_access_key: + type: string + type: object + structs.AccessToken: + properties: + active: + type: boolean + api_access: + $ref: '#/definitions/structs.APIAccess' created_at: type: string - error: + created_by: + description: |- + CreatedBy attributes the token to whoever minted it (sub-account + ID or org member account ID; empty = account owner). Used to + revoke org-bound tokens when their creator leaves the org. type: string - function_id: + created_by_role: + type: string + deleted_at: + type: string + description: type: string - gcp_gcs_input: - $ref: '#/definitions/structs.GCPGCSInput' - gcp_pubsub_input: - $ref: '#/definitions/structs.GCPPubSubInput' id: type: string - name: + last_login: type: string - service_connection_id: + name: + description: |- + Name is the API compatibility alias for Description. Description remains + the persisted column; MarshalJSON derives Name so clients that create a + token with `name` see it round-trip on list responses. type: string - service_connection_input_type: + permissions: allOf: - - $ref: '#/definitions/structs.ServiceConnectionInputType' - description: Used to load all inputs for a service connection - status: - $ref: '#/definitions/structs.ServiceConnectionInputStatus' + - $ref: '#/definitions/structs.TokenPermissions' + description: |- + Permissions optionally constrains REST and MCP access using the same + role model as organization members. Nil preserves the historical + unrestricted access-token behaviour for tokens created before this field + existed. + scopes: + $ref: '#/definitions/structs.Metadata' updated_at: type: string type: object - structs.ServiceConnectionInputStatus: - enum: - - ok - - error - type: string - x-enum-varnames: - - ServiceConnectionInputStatusOK - - ServiceConnectionInputStatusError - structs.ServiceConnectionInputType: - enum: - - gcp_pubsub - - gcp_gcs - - aws_s3 - - aws_sqs - - aws_sns - type: string - x-enum-varnames: - - ServiceConnectionInputTypeGCPPubSub - - ServiceConnectionInputTypeGCPGCS - - ServiceConnectionInputTypeAWSS3 - - ServiceConnectionInputTypeAWSSQS - - ServiceConnectionInputTypeAWSSNS - structs.ServiceConnectionOutput: + structs.Account: properties: - aws_s3_output: - $ref: '#/definitions/structs.AWSS3Output' - aws_sns_output: - $ref: '#/definitions/structs.AWSSNSOutput' - aws_sqs_output: - $ref: '#/definitions/structs.AWSSQSOutput' - bucket_id: - type: string - created_at: - type: integer - discord_output: - $ref: '#/definitions/structs.DiscordOutput' - function_id: - type: string - gcp_gcs_output: - $ref: '#/definitions/structs.GCPGCSOutput' - gcp_pubsub_output: - $ref: '#/definitions/structs.GCPPubSubOutput' - id: - type: string - name: - type: string - service_connection_id: - type: string - service_connection_output_type: - $ref: '#/definitions/structs.ServiceConnectionOutputType' - slack_output: - $ref: '#/definitions/structs.SlackOutput' - updated_at: - type: integer - type: object - structs.ServiceConnectionOutputType: - enum: - - gcp_pubsub - - gcp_gcs - - aws_s3 - - aws_sqs - - aws_sns - - discord - - slack - type: string - x-enum-varnames: - - ServiceConnectionOutputTypeGCPPubSub - - ServiceConnectionOutputTypeGCPGCS - - ServiceConnectionOutputTypeAWSS3 - - ServiceConnectionOutputTypeAWSSQS - - ServiceConnectionOutputTypeAWSSNS - - ServiceConnectionOutputTypeDiscord - - ServiceConnectionOutputTypeSlack - structs.ServiceConnectionStatus: - enum: - - pending - - connected - - error - type: string - x-enum-varnames: - - ServiceConnectionStatusPending - - ServiceConnectionStatusConnected - - ServiceConnectionStatusError - structs.ServiceType: - enum: - - gcp - - aws - - azure - type: string - x-enum-varnames: - - ServiceGCP - - ServiceAWS - - ServiceAzure - structs.SlackOutput: - properties: - webhook_url: - type: string - type: object - structs.SubAccount: - properties: - account: - $ref: '#/definitions/structs.Account' - account_id: + access_tokens: + items: + $ref: '#/definitions/structs.AccessToken' + type: array + acquisition_channel: + description: 'normalized: paid/organic/social/email/referral/direct' type: string + active: + type: boolean + alert_notifications: + type: boolean auth_type: allOf: - $ref: '#/definitions/structs.AccountAuthType' description: authentication type (regular/github/google) avatar_url: type: string + buckets: + items: + $ref: '#/definitions/structs.Bucket' + type: array + company_name: + type: string created_at: type: string + current_period_end: + type: integer + current_period_start: + description: subscription period start and end, updated by stripe + type: integer deleted_at: type: string + domains: + items: + $ref: '#/definitions/structs.Domain' + type: array email: type: string + email_verified: + type: boolean failed_login_attempts: type: integer + fbclid: + description: Meta click id + type: string + first_name: + type: string + first_touch_source: + description: first-touch utm_source when it differs from last touch + type: string + gclid: + description: Google click id (offline conversion import) + type: string id: type: string + landing_page: + type: string last_failed_login: type: string last_login_at: type: string + last_name: + type: string mfa_enabled: type: boolean - saml_sso_org_id: + msclkid: + description: Microsoft click id type: string - update_password: - description: If set, user will be asked to change the password after login + organization: + description: |- + Organization marks this account as an organization: other + accounts can be invited into it as members (see + OrganizationMember). Org ID == this account's ID. Conversion is + one-way — the flag is never unset. type: boolean - updated_at: - type: string - username: - type: string - type: object - structs.SubAccountCreateRequest: - properties: - auth_type: - $ref: '#/definitions/structs.AccountAuthType' - email: + organization_description: type: string - username: + organization_logo: + description: |- + OrganizationLogo holds a small data:image/...;base64 logo (a few + KB — the dashboard resizes before upload, the API caps the size). type: string - type: object - structs.SubAccountCreateResponse: - properties: - password: + organization_name: type: string - sub_account: - $ref: '#/definitions/structs.SubAccount' - username: + plan_id: + description: |- + desired plan ID, used when registering new account + to create new subscription in Stripe after + email is verified type: string - type: object - structs.SubscriptionExtras: - properties: - description: + plan_meta: + $ref: '#/definitions/structs.Metadata' + referrer_url: type: string - metadata: - additionalProperties: - type: string - type: object - price_id: + role: type: string - quantity: - type: integer - term: - $ref: '#/definitions/structs.SubscriptionTerm' - unit_amount: - type: integer - type: object - structs.SubscriptionResponse: - properties: - amount: + sub_accounts: + items: + $ref: '#/definitions/structs.SubAccount' + type: array + subscription_created: + description: Unix ts type: integer - cancel_at_period_end: + subscription_extras: + items: + $ref: '#/definitions/structs.SubscriptionExtras' + type: array + subscription_meta: + $ref: '#/definitions/structs.Metadata' + subscription_status: + description: Subscription status and fields + type: string + suspend_protection: + description: |- + SuspendProtection prevents account's buckets from being suspended for + overuse type: boolean - currency: + tunnels: + items: + $ref: '#/definitions/structs.Tunnel' + type: array + updated_at: type: string - current_period_end: - type: integer - current_period_start: - type: integer - customer_id: + usage_alerts: + type: boolean + usage_alerts_50: + type: boolean + usage_alerts_75: + type: boolean + usage_alerts_email: type: string - extras: + usage_alerts_emails: + description: |- + UsageAlertsEmails are additional recipients for quota notifications. + The account email remains the primary recipient; this list is additive. items: - $ref: '#/definitions/structs.SubscriptionExtras' + type: string type: array - meta_data: - $ref: '#/definitions/structs.PlanMeta' - plan: + use_case: + description: Why have they registered? type: string - plan_id: + use_case_completed: + type: boolean + username: type: string - status: + utm_campaign: type: string - subscription_id: + utm_content: type: string - trial_end: - type: integer - trial_start: - type: integer + utm_medium: + type: string + utm_source: + description: |- + Acquisition attribution — where this signup came from. Captured at + registration from the marketing site's wr_attribution cookie / utm_* query + params (see plugins/attribution.client.ts on webhookrelay.com). Used to + trace ad -> click -> signup -> paid plan. All best-effort, may be empty. + type: string + utm_term: + type: string + webhookCounts: + items: + $ref: '#/definitions/structs.WebhooksCount' + type: array type: object - structs.SubscriptionTerm: + structs.AccountAPIKey: + properties: + api_key: + type: string + type: object + structs.AccountAuthType: enum: - - monthly - - yearly + - regular + - github + - google + - saml type: string x-enum-varnames: - - SubscriptionTermMonthly - - SubscriptionTermYearly - structs.ThrottleConfig: + - AccountAuthTypeRegular + - AccountAuthTypeGithub + - AccountAuthTypeGoogle + - AccountAuthTypeSAML + structs.AdminConnectedAccount: properties: - deadline: - allOf: - - $ref: '#/definitions/time.Duration' - description: |- - Deadline caps how long a queued webhook may wait for delivery, - measured from when it was received. Zero falls through to - DefaultThrottleDeadline. Webhooks older than the deadline are dropped - (marked failed) instead of delivered. - enabled: - description: Enabled toggles the whole feature for this output. - type: boolean - interval: - description: |- - Interval is ThrottleIntervalSecond / Minute / Hour. Used only in - ThrottleModeRate. + account_id: type: string - max_concurrent: - description: |- - MaxConcurrent is the maximum number of in-flight deliveries. Used - only in ThrottleModeConcurrency. 1 means serial delivery. - type: integer - max_queue_depth: - description: |- - MaxQueueDepth bounds how many webhooks may sit in the queue for this - output. Zero means unbounded. When exceeded, the ingester rejects - new webhooks with HTTP 429. - type: integer - mode: - description: Mode is ThrottleModeRate or ThrottleModeConcurrency. + email: type: string - rate: - description: |- - Rate is the maximum number of deliveries per Interval. Used only in - ThrottleModeRate. + plan: + type: string + plan_id: + type: string + tunnel_clients: + items: + $ref: '#/definitions/structs.ConnectedTunnelClientInfo' + type: array + username: + type: string + webhook_clients: + items: + $ref: '#/definitions/structs.ConnectedWebhookClientInfo' + type: array + type: object + structs.AdminConnectedClientsResponse: + properties: + accounts: + items: + $ref: '#/definitions/structs.AdminConnectedAccount' + type: array + total_count: type: integer type: object - structs.Tunnel: + structs.AdminUsageAlert: properties: - account_id: + account_email: type: string - addr: - description: |- - Addr specifies TCP address server would listen on, it's required - for TCP tunnels. + account_id: type: string - agent_id: - description: |- - AgentID is used by the ingress controller and is - randomly generated on startup. Once controller is running - it will send periodic updates to indicate that it's still running. + account_username: type: string - auth: - $ref: '#/definitions/structs.TunnelAuth' created_at: + type: string + delivery_status: + type: string + id: + type: string + notice_type: + type: string + plan_id: + type: string + quota: type: integer - crypto: - description: crypto types, used to issue lets encrypt certs + recipients_sent: + type: integer + recipients_total: + type: integer + subscription_period_end: + type: integer + subscription_period_start: + type: integer + suspended: + type: boolean + threshold: + type: integer + used: + type: integer + type: object + structs.AgentApproval: + properties: + account_id: type: string - description: + asked_at: type: string - destination: - description: destination host, defaults to 127.0.0.1:8000 + call_id: + description: CallID is the provider's tool-call id, matching the tool_call + event. type: string - features: - $ref: '#/definitions/structs.Metadata' - group: - description: |- - optional tunnel group, primarily used by the ingress to subscribe - to specific group of tunnels + conversation_id: type: string - host: - description: |- - tunnel's subdomain, random for free tier - or named for paid subs + decided_at: + type: string + decided_by: + type: string + decision: type: string id: type: string - ingress_rules: - $ref: '#/definitions/structs.JSONB' - mode: - $ref: '#/definitions/structs.TunnelMode' - name: - description: tunnel name + input: + description: |- + Input is the tool's arguments as the model sent them (clipped), so a + reviewer can see exactly what would have been deleted. type: string - protocol: - description: tunnel protocol - http/tcp + reason: + description: Reason is the user's words on a denial, or the system's on expiry. type: string - region: - description: optional tunnel region + remember: + description: |- + Remember is true when the approval was also recorded on the + conversation, so later calls needing the same scope do not ask again. + type: boolean + scope: + description: Scope is the access that was missing, e.g. "routing:drop". + type: string + tool: type: string - updated_at: - type: integer type: object - structs.TunnelAuth: + structs.AgentConversation: properties: + account_id: + type: string + approved_scopes: + description: |- + ApprovedScopes are the harness scopes the user widened this + conversation by ("routing:drop"), space separated. Approvals outlive + a turn: each turn is its own session, so the widening is replayed on + top of the role's grant when the next turn starts. + type: string + context_id: + type: string + context_kind: + description: |- + ContextKind / ContextID name the page the conversation was opened + from: "function" + a function ID for the function details page. + type: string created_at: - type: integer + type: string + created_by: + description: |- + CreatedBy is the acting member in an organization context, the + account itself otherwise. + type: string + grant: + description: Grant is the harness grant label the conversation runs under. + type: string id: type: string - password: + last_message_at: type: string - token: + page: + description: |- + Page is a human label for where the chat was opened from ("Buckets", + "Bucket orders", "Access Tokens"), so the agent knows what the user is + looking at even when there is no resource to bind to. type: string - type: - $ref: '#/definitions/structs.AuthType' - updated_at: + title: + type: string + turns: type: integer - username: + updated_at: type: string type: object - structs.TunnelMode: - enum: - - 0 - - 1 - type: integer - x-enum-varnames: - - TunnelModeInactive - - TunnelModeActive - structs.UpdateAPIKeyStatusRequest: - properties: - enabled: - type: boolean - type: object - structs.UpdateAPIKeyStatusResponse: - properties: - enabled: - type: boolean - type: object - structs.UpdateFunctionRequest: + structs.AgentFeedback: properties: account_id: type: string - driver: + comment: + type: string + conversation_id: + type: string + created_at: + type: string + created_by: + type: string + excerpt: + description: |- + Excerpt is the start of the rated message, so a reviewer sees what was + rated without loading the transcript. type: string id: type: string - name: + message_index: + description: |- + MessageIndex is the position of the assistant message in the stored + transcript (ProjectHistory order); one rating per message. + type: integer + rating: + description: up | down type: string - payload: + updated_at: type: string type: object - structs.Usage: + structs.AgentLimitOverrides: properties: - account_id: - type: string - agents: - description: agents currently connected + max_iterations: + description: MaxIterations overrides model round trips per turn (AGENT_MAX_ITERATIONS). type: integer - created_at: - type: string - inputs: + max_output_tokens: + description: MaxOutputTokens overrides the single-response output cap. type: integer - outputs: + max_tokens_per_turn: + description: |- + MaxTokensPerTurn overrides the per-turn effective-token budget + (AGENT_MAX_TOKENS). Cache reads count at one tenth. type: integer - tokens: + plan_tokens: + additionalProperties: + type: integer + description: |- + PlanTokens overrides the monthly effective-token allowance per plan + family (free, basic, business, pro); -1 removes the cap. The override + replaces the family default only: an account whose plan metadata sets + agent_tokens explicitly keeps its explicit value. + type: object + type: object + structs.AlertPolicy: + properties: + check_interval_seconds: type: integer - tunnels: + description: + type: string + health_endpoint: + $ref: '#/definitions/structs.HealthEndpointConfig' + minimum_events: type: integer - webhooks: + mode: + $ref: '#/definitions/structs.AlertPolicyMode' + recovery_threshold_percent: + type: number + threshold_percent: + type: number + tls_expiration_days: + type: integer + type: + $ref: '#/definitions/structs.AlertType' + window_seconds: type: integer type: object - structs.Variable: + structs.AlertPolicyMode: + enum: + - any_failure + - error_rate + type: string + x-enum-varnames: + - AlertPolicyModeAnyFailure + - AlertPolicyModeErrorRate + structs.AlertType: + enum: + - delivery_failures + - tls_expiration + - host_down + - health_endpoint + type: string + x-enum-varnames: + - AlertTypeDeliveryFailures + - AlertTypeTLSExpiration + - AlertTypeHostDown + - AlertTypeHealthEndpoint + structs.AuditLog: properties: account_id: + description: |- + composite indexes cover the account activity view's query + patterns: paginated scan by (account_id, created_at) plus + user/action filters; (account_id, action, resource_id) predates + this and doubles as the action filter index. + type: string + action: + description: create/delete/update + type: string + actor_account_id: + description: |- + Actor fields identify the real logged-in account when the action + was performed in an organization context (AccountID is then the + org account). Empty for regular requests. + type: string + actor_email: + type: string + agent_conversation_id: + description: |- + AgentConversationID is the chat the agent acted in when Source is + "agent", so the activity view can open the conversation. type: string created_at: type: string - function_id: + diff: + description: |- + Diff is a JSON array of {field, old, new} changes captured on + update actions (sensitive values redacted). Empty for creates, + deletes and entries recorded before diffs existed — the UI shows + those as "unavailable". type: string - key: + email: type: string - updated_at: + id: type: string - value: + ip_address: + description: Caller's IP address type: string - type: object - structs.WebhooksCount: - properties: - account_id: - description: account that it belongs to + message: type: string - created_at: + resource_id: type: string - date: - description: beginning of the day for which the webhooks are calculated + resource_identifier: + description: for inputs it's input ID, for tunnels it's host type: string - failed: - type: integer - id: + resource_kind: + description: bucket/tunnel/input/output/account + type: string + source: + description: |- + Source names the surface the action came through: "mcp" for an MCP + client, "agent" for the agent chat. Empty for the REST API and the + dashboard, which are one surface at this layer. type: string - preparing: - description: Potential webhook statuses - type: integer - received: - type: integer - rejected: - type: integer - sent: - type: integer - stalled: - type: integer - term: - allOf: - - $ref: '#/definitions/structs.WebhooksCountTerm' - description: daily/monthly term of the calculation updated_at: type: string + username: + type: string type: object - structs.WebhooksCountTerm: + structs.AuthType: enum: - 0 - 1 + - 2 type: integer x-enum-varnames: - - WebhooksCountTermDaily - - WebhooksCountTermMonthly - time.Duration: - enum: - - -9223372036854775808 - - 9223372036854775807 - - 1 - - 1000 - - 1000000 + - AuthTypeNone + - AuthTypeBasic + - AuthTypeToken + structs.AzureServiceConnection: + properties: + client_id: + type: string + client_secret: + type: string + tenant_id: + type: string + type: object + structs.BillingDetails: + properties: + city: + type: string + country: + type: string + customer_id: + type: string + email: + type: string + line1: + type: string + line2: + type: string + name: + description: Customer full name or business name + type: string + postal_code: + type: string + state: + type: string + tax_id: + description: Value of the tax ID. + type: string + tax_id_type: + description: Type of the tax ID, one of `ae_trn`, `au_abn`, `au_arn`, `bg_uic`, + `br_cnpj`, `br_cpf`, `ca_bn`, `ca_gst_hst`, `ca_pst_bc`, `ca_pst_mb`, `ca_pst_sk`, + `ca_qst`, `ch_vat`, `cl_tin`, `es_cif`, `eu_oss_vat`, `eu_vat`, `gb_vat`, + `ge_vat`, `hk_br`, `hu_tin`, `id_npwp`, `il_vat`, `in_gst`, `is_vat`, `jp_cn`, + `jp_rn`, `kr_brn`, `li_uid`, `mx_rfc`, `my_frp`, `my_itn`, `my_sst`, `no_vat`, + `nz_gst`, `ru_inn`, `ru_kpp`, `sa_vat`, `sg_gst`, `sg_uen`, `si_tin`, `th_vat`, + `tw_vat`, `ua_vat`, `us_ein`, or `za_vat` + type: string + type: object + structs.Bucket: + properties: + account_id: + type: string + auth: + $ref: '#/definitions/structs.BucketAuth' + created_at: + type: integer + created_by: + description: |- + CreatedBy is the account ID of the user who created the bucket — + for organization accounts this is the acting member. Empty means + the account owner. + type: string + cron_id: + type: string + description: + type: string + ephemeral: + description: If true, doesn't save request body, query or headers + type: boolean + id: + type: string + inputs: + items: + $ref: '#/definitions/structs.Input' + type: array + integration_configurations: + items: + $ref: '#/definitions/structs.IntegrationConfiguration' + type: array + large_webhooks: + description: |- + LargeWebhooks - if set, we allow larger than 3MB webhooks + to be sent to the bucket. This is useful for large file uploads + type: boolean + name: + type: string + outputs: + items: + $ref: '#/definitions/structs.Output' + type: array + service_connection_inputs: + items: + $ref: '#/definitions/structs.ServiceConnectionInput' + type: array + service_connection_outputs: + items: + $ref: '#/definitions/structs.ServiceConnectionOutput' + type: array + static_ip: + description: StaticIP - if set, the bucket will use a static IP (routing through + forwarding proxy) + type: boolean + stream: + description: enable/disable websocket streaming for the bucket + type: boolean + suspended: + description: |- + Set to TRUE by the curator if accounts goes over the + webhook limit + type: boolean + updated_at: + type: integer + type: object + structs.BucketAuth: + properties: + created_at: + type: integer + id: + type: string + password: + type: string + token: + type: string + type: + $ref: '#/definitions/structs.AuthType' + updated_at: + type: integer + username: + type: string + type: object + structs.BucketLogsStats: + properties: + bucket_id: + type: string + stats: + items: + $ref: '#/definitions/structs.LogsStats' + type: array + type: object + structs.CombinedUsage: + properties: + plan_meta: + $ref: '#/definitions/structs.PlanMeta' + usage: + $ref: '#/definitions/structs.Usage' + type: object + structs.ConnectedClient: + properties: + tunnel_clients: + items: + $ref: '#/definitions/structs.ConnectedTunnelClient' + type: array + webhook_clients: + items: + $ref: '#/definitions/structs.ConnectedWebhookClient' + type: array + type: object + structs.ConnectedTunnelClient: + properties: + access_token_key: + type: string + client_ip: + type: string + client_version: + type: string + subscribed_at: + type: integer + tunnels: + items: + type: string + type: array + type: object + structs.ConnectedTunnelClientInfo: + properties: + access_token_key: + type: string + client_ip: + type: string + client_version: + type: string + subscribed_at: + type: integer + tunnel_names: + items: + type: string + type: array + tunnels: + items: + type: string + type: array + type: object + structs.ConnectedWebhookClient: + properties: + access_token_key: + type: string + buckets: + items: + type: string + type: array + client_ip: + type: string + client_type: + type: string + client_version: + type: string + destination: + type: string + subscribed_at: + type: integer + type: object + structs.ConnectedWebhookClientInfo: + properties: + access_token_key: + type: string + bucket_names: + items: + type: string + type: array + buckets: + items: + type: string + type: array + client_ip: + type: string + client_type: + type: string + client_version: + type: string + destination: + type: string + subscribed_at: + type: integer + type: object + structs.CreateFunctionRequest: + properties: + driver: + type: string + name: + type: string + payload: + type: string + type: object + structs.CreateTunnelRequest: + properties: + addr: + description: |- + Addr specifies TCP address server would listen on, it's required + for TCP tunnels. + type: string + agent_id: + type: string + auth: + $ref: '#/definitions/structs.TunnelAuth' + crypto: + type: string + description: + type: string + destination: + type: string + features: + $ref: '#/definitions/structs.Features' + group: + type: string + host: + type: string + ingress_rules: + $ref: '#/definitions/structs.IngressRules' + name: + type: string + protocol: + type: string + region: + type: string + subdomain: + type: string + type: object + structs.Cron: + properties: + account_id: + type: string + bucket: + $ref: '#/definitions/structs.Bucket' + created_at: + type: string + created_by: + description: |- + CreatedBy is the account ID of the user who created the cron — + for organization accounts this is the acting member. Empty means + the account owner. + type: string + destination: + description: URL to send the webhook to + type: string + enabled: + type: boolean + ends_at: + type: string + function_id: + description: Function ID attached to the output + type: string + headers: + $ref: '#/definitions/structs.Headers' + id: + type: string + method: + description: |- + Payload and headers injected into the Bucket. Outputs + are still used to send the webhook + type: string + name: + type: string + next_run: + description: Populated by the handler for UI to display + type: string + payload: + type: string + recurring: + type: boolean + schedule: + type: string + starts_at: + description: Dates from which the cron job starts and ends + type: string + timezone: + type: string + updated_at: + type: string + type: object + structs.DBSSODetails: + properties: + allow_jit: + description: |- + AllowJIT is a pointer so old rows with no key retain the historical + behavior (JIT enabled). New self-service connections write it explicitly. + type: boolean + allowed_domains: + items: + type: string + type: array + force_authn: + description: ForceAuthn asks the IdP to reauthenticate instead of reusing + its session. + type: boolean + name_id_format: + description: |- + NameIDFormat controls the NameIDPolicy sent in AuthnRequest. Empty keeps + crewjam's default transient format for backward compatibility. + type: string + signature_method: + description: |- + SignatureMethod selects the algorithm used to sign AuthnRequests. Empty + retains RSA-SHA1 for old rows; new connections explicitly use SHA-256. + type: string + type: object + structs.DeleteFunctionResponse: + type: object + structs.DeleteVariableResponse: + type: object + structs.DiscordOutput: + properties: + webhook_url: + type: string + type: object + structs.Domain: + properties: + created_at: + type: integer + domain: + description: |- + Domain can be any 3rd party domain such as + user.example.com + type: string + id: + type: string + updated_at: + type: integer + type: object + structs.DurabilityConfig: + properties: + custom_delays: + description: CustomDelays is consulted only when Schedule == "custom". + items: + $ref: '#/definitions/time.Duration' + type: array + deadline: + allOf: + - $ref: '#/definitions/time.Duration' + description: |- + Deadline caps total retry duration measured from the webhook's + received_at timestamp. Zero falls through to a schedule-derived + default (~30 d for "long", ~16 h for "medium", ~25 min for + "seconds"). + enabled: + description: Enabled toggles the whole feature for this output. + type: boolean + handoff_after: + allOf: + - $ref: '#/definitions/time.Duration' + description: |- + HandoffAfter is the attempt-age threshold past which a failing + delivery is moved from the in-pubsub retry path to the durable + pending index. Zero falls through to 15 minutes — short enough + that long retries don't bloat the pubsub backlog, long enough + that transient blips don't pay an extra object-store PUT. + schedule: + description: |- + Schedule names a backoff preset ("seconds", "medium", "long", + "custom"). Empty falls through to "long" when Enabled, "seconds" + otherwise. Custom backoffs use CustomDelays. + type: string + type: object + structs.EmailInput: + properties: + allowed_senders: + description: |- + AllowedSenders, when non-empty, restricts inbound mail to these From + addresses (exact match, lower-cased). Abuse / hardening control. + items: + type: string + type: array + drop_attachments: + description: DropAttachments skips attachment parsing and storage entirely. + type: boolean + enabled: + description: |- + Enabled gates whether inbound mail is accepted. When false the address + still resolves but mail is dropped at ingest. + type: boolean + max_attachment_bytes: + description: |- + MaxAttachmentBytes overrides the per-message total attachment storage cap. + 0 uses the server default. + type: integer + type: object + structs.Endpoint: + properties: + address: + type: string + type: object + structs.ErrorResponse: + properties: + error: + type: string + type: object + structs.ExecuteLog: + properties: + account_id: + type: string + configuration_id: + type: string + created: + type: integer + duration: + type: integer + execute_request: + $ref: '#/definitions/structs.ExecuteRequest' + execute_response: + $ref: '#/definitions/structs.ExecuteResponse' + function_id: + type: string + id: + type: string + status: + $ref: '#/definitions/structs.ExecutionStatus' + updated: + type: integer + type: object + structs.ExecuteLogResponse: + properties: + execute_logs: + items: + $ref: '#/definitions/structs.ExecuteLog' + type: array + limit: + type: integer + offset: + type: integer + total: + type: integer + type: object + structs.ExecuteRequest: + properties: + account_id: + type: string + configuration_id: + type: string + delivery_error: + description: |- + DeliveryError is the transport-level error string for an + ExecutionModeResponse run when delivery failed without an HTTP + response (timeout, connection refused, TLS error). Empty when an HTTP + response was received, even a 5xx. + type: string + function_id: + type: string + request: + $ref: '#/definitions/structs.Request' + request_id: + type: string + response: + allOf: + - $ref: '#/definitions/structs.Response' + description: |- + Response carries the destination's reply for ExecutionModeResponse + runs. Status is the HTTP status code (0 when there was no response — + a connection error or timeout), Body is the (inline) response body, + Header the response headers. Unset for input/output functions. + response_body_path: + type: string + type: object + structs.ExecuteResponse: + properties: + error: + type: string + function_id: + type: string + logs: + description: |- + Logs is the output the function itself emitted through console.log / + console.warn / console.error (JavaScript) or print (Lua) during this + execution. Captured per execution and persisted with the ExecuteLog so + the dashboard, the REST API and the MCP `execute` tool can show users + what their own code printed — before this existed the output went only + to the platform's internal logs and was invisible to the account. + Bounded by pkg/reactor/functionlogs; secrets are redacted at capture. + items: + $ref: '#/definitions/structs.FunctionLogEntry' + type: array + request: + $ref: '#/definitions/structs.Request' + request_id: + type: string + request_modified: + type: boolean + response: + $ref: '#/definitions/structs.Response' + response_modified: + type: boolean + stop_forwarding: + type: boolean + type: object + structs.ExecutionStatus: + enum: + - none + - success + - error + type: string + x-enum-comments: + ExecutionStatusError: "2" + ExecutionStatusNone: "0" + ExecutionStatusSuccess: "1" + x-enum-varnames: + - ExecutionStatusNone + - ExecutionStatusSuccess + - ExecutionStatusError + structs.Features: + properties: + rewrite_host_header: + type: string + skip_insecure_verify: + description: validate TLS certificate + type: boolean + type: object + structs.Function: + properties: + account_id: + type: string + compression: + type: string + created: + type: integer + created_by: + description: |- + CreatedBy is the account ID of the user who created the function — + for organization accounts this is the acting member. Empty means + the account owner. + type: string + driver: + type: string + id: + type: string + metadata: + additionalProperties: + type: string + type: object + name: + type: string + payload: + type: string + payload_size: + type: integer + requirements: + items: + $ref: '#/definitions/structs.FunctionConnectionRequirement' + type: array + updated: + type: integer + type: object + structs.FunctionConnectionRequirement: + properties: + alias: + type: string + connection_types: + items: + type: string + type: array + module: + type: string + required: + type: boolean + service_connection_id: + type: string + service_connection_name: + type: string + status: + type: string + type: object + structs.FunctionLogEntry: + properties: + level: + type: string + message: + type: string + time: + description: |- + Time is the capture time in Unix milliseconds. Useful when a function + interleaves logging with slow calls (http, bigquery) and the gaps + matter. + type: integer + type: object + structs.FunctionVersion: + properties: + account_id: + type: string + created_at: + type: integer + created_by: + description: CreatedBy is the acting account when known (org member, token + owner). + type: string + driver: + type: string + function_id: + type: string + name: + type: string + payload: + type: string + payload_size: + type: integer + restored_from: + description: RestoredFrom is set when the revision was created by restoring + another. + type: integer + source: + description: 'Source names what saved the revision: api, mcp, agent, restore.' + type: string + version: + type: integer + type: object + structs.GCPGCSInput: + properties: + bucket_name: + type: string + file_format: + $ref: '#/definitions/structs.ObjectStorageFileFormat' + notification_id: + type: string + prefix: + type: string + type: object + structs.GCPGCSOutput: + properties: + bucket_name: + type: string + file_format: + $ref: '#/definitions/structs.ObjectStorageFileFormat' + prefix: + type: string + type: object + structs.GCPPubSubInput: + properties: + subscription_name: + type: string + type: object + structs.GCPPubSubOutput: + properties: + topic_name: + type: string + type: object + structs.GCPServiceConnection: + properties: + project_id: + type: string + service_account_email: + type: string + service_account_key: + type: string + type: object + structs.GenerateFunctionRequest: + properties: + additional_info: + description: Additional information about the function + type: string + input_payload: + type: string + output_payload: + description: Desired output payload + type: string + type: object + structs.GenerateFunctionResponse: + properties: + code: + description: Function code + type: string + validation_err: + description: Validation error message + type: string + validation_ok: + description: Indicates if the function is valid + type: boolean + type: object + structs.Header: + properties: + values: + items: + type: string + type: array + type: object + structs.Headers: + additionalProperties: true + type: object + structs.HealthEndpointConfig: + properties: + basic_password: + type: string + basic_username: + type: string + headers: + additionalProperties: + type: string + type: object + method: + type: string + path: + type: string + type: object + structs.IncidentDayStats: + properties: + count: + type: integer + day: + type: string + duration_seconds_count: + type: integer + duration_seconds_sum: + type: integer + open_count: + type: integer + resolved_count: + type: integer + type: object + structs.IngressRule: + properties: + endpoints: + description: Endpoints + items: + $ref: '#/definitions/structs.Endpoint' + type: array + name: + description: |- + Name is an option identifier for the ingress rule, it usually is a service name + if used with webrelay-ingress + type: string + path: + description: |- + Path is an extended POSIX regex as defined by IEEE Std 1003.1, + (i.e this follows the egrep/unix syntax, not the perl syntax) + matched against the path of an incoming request. Currently it can + contain characters disallowed from the conventional "path" + part of a URL as defined by RFC 3986. Paths must begin with + a '/'. If unspecified, the path defaults to a catch all sending + traffic to the backend. + +optional + type: string + type: object + structs.IngressRules: + properties: + rules: + items: + $ref: '#/definitions/structs.IngressRule' + type: array + type: object + structs.Input: + properties: + body: + items: + type: integer + type: array + bucket_id: + description: BucketID is a foreign key + type: string + created_at: + type: integer + created_by: + type: string + custom_domain: + description: |- + Input's domain name, can be set to work with the CNAMEs + so WHR will fetch a cert from LE + (make sure you create a CNAME DNS record for your domain to stats.uptimerobot.com. + And, it can take up to 30 mins for the custom domain to be activated.) + type: string + description: + type: string + function_id: + type: string + headers: + allOf: + - $ref: '#/definitions/structs.Headers' + description: response details + id: + type: string + legacy_tls: + description: |- + LegacyTLS widens the accepted handshake to TLS 1.0/1.1 *and* the + older RSA/CBC cipher set. The two used to be split into separate + fields but the policy resolver applies them as one logical toggle, + and the dashboard surfaces them as one switch — keep the on-disk + shape matching that single concept. + type: boolean + name: + type: string + path_prefix: + description: PathPrefix only works when CustomDomain is set + type: string + response_from_output: + description: |- + either output ID or "anyOutput" to indicate that the first response + from any output is good enough. Empty string + type: string + status_code: + type: integer + strip_path_prefix: + description: |- + StripPathPrefix indicates whether full path should be included when + forwarding the webhook. If the path prefix is /abc and the webhook + arrives at /abc/foo, then by default the full path will be /abc/foo + type: boolean + tls_version: + description: |- + TLSVersion sets the MINIMUM accepted TLS version for this input's HTTPS + endpoint. It is a floor, not a pin: handshakes negotiate this version or + any higher one the backend allows (e.g. "1.1" still accepts 1.2 and 1.3). + Empty value means default hardened policy. + type: string + updated_at: + type: integer + type: object + structs.IntegrationConfiguration: + properties: + alert_policy: + allOf: + - $ref: '#/definitions/structs.AlertPolicy' + description: |- + AlertPolicy controls when delivery failures open and resolve incidents. + It is evaluated from the durable update stream in the worker, not on the + request path, so high-throughput buckets never query configuration per + webhook or emit one notification per failure. + buckets: + items: + $ref: '#/definitions/structs.Bucket' + type: array + configuration: + allOf: + - $ref: '#/definitions/structs.Metadata' + description: |- + notification plugin configuration, free form JSON. Each plugin parses whatever configuration + it wants + created_at: + type: string + description: + type: string + disabled: + description: optionally disable notification (when you want to turn off events) + type: boolean + events: + description: event types, such as schedules.import.error + items: + type: string + type: array + id: + type: string + message: + description: read-only field populated by the plugin + type: string + plugin: + allOf: + - $ref: '#/definitions/structs.IntegrationPlugin' + description: plugin to use, such as Slack, Webhook, Email + status: + description: read-only field populated by the plugin + type: string + updated_at: + type: string + type: object + structs.IntegrationPlugin: + enum: + - webhook + - slack + - discord + - telegram + - email + - teams + - pushover + - generic + - default_email + type: string + x-enum-comments: + IntegrationPluginDefaultEmail: built-in email via Mailjet + IntegrationPluginGeneric: generic shoutrrr URL + x-enum-varnames: + - IntegrationPluginWebhook + - IntegrationPluginSlack + - IntegrationPluginDiscord + - IntegrationPluginTelegram + - IntegrationPluginEmail + - IntegrationPluginTeams + - IntegrationPluginPushover + - IntegrationPluginGeneric + - IntegrationPluginDefaultEmail + structs.JSONB: + additionalProperties: true + type: object + structs.LLMServiceConnection: + properties: + api_key: + type: string + base_url: + type: string + type: object + structs.Log: + properties: + account_id: + type: string + attempts: + description: |- + Attempts is the delivery attempt history (one entry per try, oldest + first, attempt_no 1-based). Populated by GetLog from turbostore v2's + WebhookDetail; carried on the update path so the worker's queue + consumer can emit attempt events. Empty for single first-try + successes, logs written before attempt capture, and ClickHouse + reads. Never stored by GORM. + items: + $ref: '#/definitions/structs.LogAttempt' + type: array + body: + description: Body is either set or populated from BodyBytes during MarshalJSON() + type: string + bucket_id: + type: string + compression: + description: |- + Compression indicates what compression type + was used + type: string + consumer_id: + type: string + created_at: + type: integer + deleted_at: + type: string + duration_ms: + type: integer + ephemeral: + description: |- + If true, doesn't save request body, query or headers, + inherits from the bucket configuration + type: boolean + event_type: + type: string + extra_path: + type: string + headers: + allOf: + - $ref: '#/definitions/structs.Headers' + description: request details + id: + type: string + input_function_execution_id: + description: |- + InputFunctionExecutionID is the reactor ExecuteLog id for the + ingress-side function that ran before this webhook hit the + bucket. Empty when no function ran at the input stage. The UI + reads /v1/functions//logs/ for this id to render a + before/after diff. + type: string + input_id: + type: string + internal: + type: boolean + ip_address: + type: string + message_id: + description: Outbound message identity; set only on outbound logs (IsOutbound). + type: string + method: + type: string + output_function_execution_id: + description: |- + OutputFunctionExecutionID is the reactor ExecuteLog id for the + per-output function that ran before forwarding this delivery + to the destination. Empty when no function ran on the output. + type: string + output_id: + type: string + output_response_function_execution_id: + description: |- + OutputResponseFunctionExecutionID is the reactor ExecuteLog id for + the per-output response (post-delivery) function. Empty when no + response function ran. + type: string + raw_query: + type: string + request_bytes: + description: |- + RequestBytes and ResponseBytes contain recorded body + HTTP header + bytes for this delivery. They exclude request/status lines, the final + blank header line, TLS, and transport framing. GORM ignores them so + ClickHouse remains unchanged; Turbostore persists and aggregates them. + type: integer + response_body: + items: + type: integer + type: array + response_bytes: + type: integer + response_headers: + $ref: '#/definitions/structs.Headers' + retries: + type: integer + service_connection_input_type: + description: |- + ServiceConnectionInputType is set when the log originates from a service connection input + (e.g. gcp_pubsub, aws_sqs, aws_sns, aws_s3, gcp_gcs) + type: string + service_connection_output_type: + description: |- + ServiceConnectionOutputType is set when the log is for a service connection output + (e.g. gcp_pubsub, aws_sqs, aws_sns, aws_s3, gcp_gcs) + type: string + status: + enum: + - preparing + - sent + - failed + - stalled + - received + - rejected + type: string + status_code: + type: integer + total_bytes: + type: integer + updated_at: + type: integer + type: object + structs.LogAttempt: + properties: + attempt_id: + type: string + attempt_no: + type: integer + duration_ms: + type: integer + error: + type: string + finished_at: + type: string + outcome: + $ref: '#/definitions/structs.LogAttemptOutcome' + request_headers: + $ref: '#/definitions/structs.Headers' + response_body: + items: + type: integer + type: array + response_headers: + $ref: '#/definitions/structs.Headers' + started_at: + type: string + status_code: + type: integer + truncated: + type: boolean + type: object + structs.LogAttemptOutcome: + enum: + - "" + - success + - retryable + - permanent + - timeout + type: string + x-enum-varnames: + - LogAttemptOutcomeUnspecified + - LogAttemptOutcomeSuccess + - LogAttemptOutcomeRetryable + - LogAttemptOutcomePermanent + - LogAttemptOutcomeTimeout + structs.LogsStats: + properties: + day: + type: string + duration_ms_count: + type: integer + duration_ms_sum: + description: |- + DurationMsSum / DurationMsCount carry the raw inputs for the mean + delivery latency on this day (sum of per-row duration_ms over the + rows that recorded one, and how many did). The mean is sum/count; + keeping the two parts lets a caller aggregate days correctly + (sum-of-sums / sum-of-counts) instead of averaging averages. + Populated only on the turbostore stats path, like the retry fields. + type: integer + failures: + type: integer + max_retries: + type: integer + received: + type: integer + request_bytes: + description: |- + Size fields are Turbostore-only recorded body + HTTP header totals. + TotalBytes is RequestBytes + ResponseBytes. + type: integer + response_bytes: + type: integer + retried: + type: integer + retry_count: + type: integer + success: + type: integer + total_bytes: + type: integer + type: object + structs.Metadata: + additionalProperties: true + type: object + structs.NewsEntry: + properties: + created_at: + type: string + id: + type: string + message: + type: string + message_of_the_day: + type: boolean + timestamp: + description: what date to show + type: integer + updated_at: + type: string + url: + type: string + visible: + type: boolean + type: object + structs.NewsEntryCreateRequest: + properties: + date: + description: what date to show + type: string + message: + type: string + message_of_the_day: + type: boolean + url: + type: string + visible: + type: boolean + type: object + structs.ObjectStorageFileFormat: + enum: + - json + - body_only + - har + type: string + x-enum-comments: + ObjectStorageFileFormatJSON: JSON format with headers, body, etc. + x-enum-varnames: + - ObjectStorageFileFormatJSON + - ObjectStorageFileFormatBody + - ObjectStorageFileFormatHAR + structs.OrgRole: + enum: + - owner + - admin + - billing + - member + - viewer + type: string + x-enum-varnames: + - OrgRoleOwner + - OrgRoleAdmin + - OrgRoleBilling + - OrgRoleMember + - OrgRoleViewer + structs.OrganizationInvite: + properties: + created_at: + type: string + email: + description: |- + Email is stored lowercased and matched against the invitee + account's email on accept. + type: string + expires_at: + type: string + id: + type: string + invited_by: + description: InvitedBy is the account ID of the inviter (actor). + type: string + org_account_id: + type: string + role: + type: string + status: + type: string + updated_at: + type: string + type: object + structs.OrganizationInviteDetails: + properties: + created_at: + type: string + email: + description: |- + Email is stored lowercased and matched against the invitee + account's email on accept. + type: string + expires_at: + type: string + id: + type: string + invited_by: + description: InvitedBy is the account ID of the inviter (actor). + type: string + invited_by_email: + type: string + org_account_id: + type: string + organization_description: + type: string + organization_logo: + type: string + organization_name: + type: string + role: + type: string + status: + type: string + updated_at: + type: string + type: object + structs.OrganizationMember: + properties: + created_at: + type: string + id: + type: string + invited_by: + description: InvitedBy is the account ID of the inviter (actor). + type: string + member_account_id: + type: string + org_account_id: + type: string + role: + description: admin/billing/member + type: string + updated_at: + type: string + type: object + structs.OrganizationMemberDetails: + properties: + avatar_url: + type: string + created_at: + type: string + email: + type: string + id: + type: string + invited_by: + description: InvitedBy is the account ID of the inviter (actor). + type: string + member_account_id: + type: string + mfa_enabled: + type: boolean + org_account_id: + type: string + role: + description: admin/billing/member + type: string + updated_at: + type: string + username: + type: string + type: object + structs.OrganizationMembershipDetails: + properties: + created_at: + type: string + id: + type: string + invited_by: + description: InvitedBy is the account ID of the inviter (actor). + type: string + member_account_id: + type: string + org_account_id: + type: string + organization_description: + type: string + organization_logo: + type: string + organization_name: + type: string + role: + description: admin/billing/member + type: string + updated_at: + type: string + type: object + structs.OutboundConsumer: + properties: + created_at: + type: string + id: + type: string + name: + type: string + rate: + type: integer + updated_at: + type: string + type: object + structs.OutboundEndpoint: + properties: + auto_disable: + type: boolean + consecutive_failures: + type: integer + consumer: + type: string + created_at: + type: string + description: + type: string + event_types: + items: + type: string + type: array + failing_since: + type: string + function_id: + type: string + headers: + additionalProperties: + type: string + type: object + id: + type: string + previous_secret_expires_at: + type: string + rate: + type: integer + state: + enum: + - active + - failing + - paused + - disabled + type: string + timeout: + description: seconds; zero uses OutboundDefaultTimeout + type: integer + updated_at: + type: string + url: + type: string + type: object + structs.OutboundEventType: + properties: + created_at: + type: string + deprecated: + type: boolean + description: + type: string + example: + type: object + name: + type: string + updated_at: + type: string + type: object + structs.OutboundMessage: + properties: + consumer: + type: string + created_at: + type: string + endpoint_ids: + items: + type: string + type: array + enqueued_at: + type: string + event_id: + type: string + event_type: + type: string + id: + type: string + payload: + type: object + type: object + structs.OutboundRecoveryTask: + properties: + created_at: + type: string + endpoint_id: + type: string + error: + type: string + id: + type: string + kind: + enum: + - retry + - recover + - replay-missing + type: string + message_id: + type: string + processed: + type: integer + since: + type: string + status: + enum: + - pending + - running + - completed + - failed + type: string + until: + type: string + updated_at: + type: string + type: object + structs.Output: + properties: + bucket_id: + description: BucketID is a foreign key + type: string + created_at: + type: integer + created_by: + type: string + cron_id: + type: string + description: + type: string + destination: + type: string + disabled: + description: Enable/disable output destinations + type: boolean + durability: + allOf: + - $ref: '#/definitions/structs.DurabilityConfig' + description: |- + Durability configures long-period retries via the turbostore + pending-retry index. See pkg/turbostore/design.md §5.6. + Stored as JSON so we can extend without a schema migration. + function_id: + description: |- + FunctionID is used to indicate whethera code snippet should be used to + modify this webhook + type: string + headers: + allOf: + - $ref: '#/definitions/structs.Headers' + description: |- + Headers that will overwrite any existing headers + from the incoming request + id: + type: string + internal: + description: internal outputs will only be relayed by agents + type: boolean + lock_path: + description: |- + LockPath ensures that the request path cannot be changed from what is + specified in the destination. For example if request is coming to /v1/webhooks/xxx/github-jenkins, + with lock path 'false' and destination 'http://localhost:8080' it would go to http://localhost:8080/github-jenkins. + However, with lock path 'true', it will be sent to 'http://localhost:8080' + type: boolean + name: + type: string + replay_missing: + allOf: + - $ref: '#/definitions/structs.ReplayMissingConfig' + description: |- + ReplayMissing configures recovery of internal deliveries that were + persisted as received but never reached an agent. When an agent connects, + matching rows from the configured lookback window are sent directly to + that connection, up to Limit. Stored as JSON so the policy can grow + without a schema migration. + response_function_id: + description: |- + ResponseFunctionID names a function that runs AFTER delivery, once the + destination's response (or the final delivery error) is known. It is + invoked for every terminal outcome — success, or failure after all + retries are exhausted — and receives the response status/body/headers + (and delivery error) so it can implement custom logic such as alerting + on a 5xx, a timeout, or an empty body. The response function cannot + modify the response that was already returned to the sender. + type: string + retries: + description: |- + additional retries (after the first 3 times fail). Setting + to -1 disables retries + type: integer + rules: + $ref: '#/definitions/rules.Rules' + throttle: + allOf: + - $ref: '#/definitions/structs.ThrottleConfig' + description: |- + Throttle configures per-output throughput throttling. When enabled, + the ingester/server stop delivering this output inline; webhooks are + persisted (left in RequestStatusReceived) and enqueued into the + turbostore throttle index, and the dispatcher's throttle controller + dequeues them at the configured rate/concurrency. Stored as JSON so + the schema can grow without a migration, same as Durability. + timeout: + description: response timeout + type: integer + tls_verification: + description: |- + Controls TLS verification of the certs for public + webhooks + type: boolean + updated_at: + type: integer + type: object + structs.PlanMeta: + properties: + activity: + description: Activity gates the account activity log (audit view) + type: boolean + agent_tokens: + description: |- + AgentTokens is the monthly account-agent and managed-Function model-token + allowance (input + output); UnlimitedAgentTokens (-1) removes the cap. + type: integer + agent_tokens_explicit: + description: |- + AgentTokensExplicit records whether any metadata set the agent_tokens + key itself (rather than the value falling back to a plan-family + default). Admin runtime overrides only replace defaulted allowances, + and comparing values cannot tell "explicitly granted 5M" from "basic + default 5M" — this flag can. + type: boolean + agents: + type: integer + alert_policies: + type: integer + custom_hostnames: + type: boolean + custom_subdomains: + type: boolean + custom_tls_version: + type: boolean + functions: + type: integer + https_tunnels: + type: boolean + inputs: + type: integer + integration_configurations: + type: integer + large_webhooks: + type: boolean + legacy_tls: + type: boolean + logs_retention: + type: integer + managed_domains: + type: integer + outputs: + type: integer + overage: + type: number + public: + description: whether plan should be visible to public + type: boolean + reserved_domains: + type: integer + saml_sso: + description: SamlSso gates self-service SAML SSO configuration (organization + accounts) + type: boolean + sub_accounts: + type: integer + tls_tunnels: + type: boolean + tokens: + type: integer + tunnels: + type: integer + webhooks: + type: integer + type: object + structs.PublishOutboundMessageRequest: + properties: + consumer: + type: string + event_id: + type: string + event_type: + type: string + payload: + type: object + type: object + structs.ReplayMissingConfig: + properties: + enabled: + description: Enabled toggles replay-on-connect for this output. + type: boolean + limit: + description: |- + Limit bounds the scan itself: the newest Limit received rows in the + lookback window are considered, and the eligible ones among them are + replayed oldest-first. Rows skipped by connection filters or status + re-checks still consume the budget — the bound is deliberately on rows + scanned, not rows delivered, so a fully-filtered window cannot trigger + an unbounded walk of the lookback. The server additionally + clamps/validates this against its environment configured maximum. + type: integer + lookback: + allOf: + - $ref: '#/definitions/time.Duration' + description: |- + Lookback selects received logs newer than now-Lookback. It is stored as + a Go duration (nanoseconds in the REST JSON, consistent with durability + and throttle duration fields). + type: object + structs.Request: + properties: + body: + items: + type: integer + type: array + body_modified: + type: boolean + body_path: + type: string + header: + additionalProperties: + $ref: '#/definitions/structs.Header' + type: object + header_modified: + type: boolean + metadata: + additionalProperties: + type: string + type: object + method: + type: string + method_modified: + type: boolean + modified_body_path: + type: string + path: + type: string + path_modified: + type: boolean + raw_query: + type: string + raw_query_modified: + type: boolean + type: object + structs.Response: + properties: + body: + items: + type: integer + type: array + body_path: + type: string + header: + additionalProperties: + $ref: '#/definitions/structs.Header' + type: object + status: + type: integer + type: object + structs.RetryTask: + properties: + account_id: + type: string + bucket_id: + type: string + completed_at: + type: string + created_at: + type: string + error: + description: Error carries a human-readable reason when Status is failed. + type: string + failed: + type: integer + id: + type: string + matched: + description: |- + Matched is the number of candidate logs found, Processed the + number re-dispatched successfully, Failed the number that + errored while being re-dispatched. + type: integer + output_id: + description: |- + OutputID optionally narrows the operation to a single output. + Empty means every output in the bucket. + type: string + processed: + type: integer + since: + description: |- + Since/Until bound the candidate window by the log's received + time. Until is optional (zero means "now" at run time). + type: string + started_at: + type: string + status: + $ref: '#/definitions/structs.RetryTaskStatus' + truncated: + description: |- + Truncated is set when the candidate set hit the per-task cap and + older matching logs in the window were left untouched. + type: boolean + type: + $ref: '#/definitions/structs.RetryTaskType' + until: + type: string + updated_at: + type: string + type: object + structs.RetryTaskStatus: + enum: + - pending + - running + - completed + - failed + type: string + x-enum-varnames: + - RetryTaskStatusPending + - RetryTaskStatusRunning + - RetryTaskStatusCompleted + - RetryTaskStatusFailed + structs.RetryTaskType: + enum: + - recover_failed + - replay_missing + type: string + x-enum-varnames: + - RetryTaskRecoverFailed + - RetryTaskReplayMissing + structs.SamlSsoOrg: + properties: + account_id: + description: Which Webhook Relay account this SSO belongs to + type: string + created_at: + type: string + deleted_at: + type: string + details: + $ref: '#/definitions/structs.DBSSODetails' + email_attribute_name: + description: |- + EmailAttributeName default is empty, but it could be set to something like + "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" so we can look for it specifically + type: string + entity_id: + type: string + id: + type: string + name: + type: string + saml_metadata_url: + description: URL to SAML metadata + type: string + updated_at: + type: string + type: object + structs.SecretServiceConnection: + properties: + value: + type: string + type: object + structs.ServiceConnection: + properties: + account_id: + type: string + aws_service_connection: + $ref: '#/definitions/structs.AWSServiceConnection' + azure_service_connection: + $ref: '#/definitions/structs.AzureServiceConnection' + created_at: + type: string + error: + type: string + gcp_service_connection: + $ref: '#/definitions/structs.GCPServiceConnection' + id: + description: ULID, starts with prefix "scn_" + type: string + last_checked: + type: string + llm_service_connection: + $ref: '#/definitions/structs.LLMServiceConnection' + name: + type: string + retries: + type: integer + secret_service_connection: + $ref: '#/definitions/structs.SecretServiceConnection' + service_type: + $ref: '#/definitions/structs.ServiceType' + status: + $ref: '#/definitions/structs.ServiceConnectionStatus' + updated_at: + type: string + type: object + structs.ServiceConnectionInput: + properties: + aws_s3_input: + $ref: '#/definitions/structs.AWSS3Input' + aws_sns_input: + $ref: '#/definitions/structs.AWSSNSInput' + aws_sqs_input: + $ref: '#/definitions/structs.AWSSQSInput' + bucket_id: + type: string + created_at: + type: string + email_address: + description: |- + EmailAddress is the computed inbound address for email-type inputs + ({local-part}@). It is populated at the API layer from the + server's configured inbound domain and is never persisted. + type: string + email_input: + $ref: '#/definitions/structs.EmailInput' + error: + type: string + function_id: + type: string + gcp_gcs_input: + $ref: '#/definitions/structs.GCPGCSInput' + gcp_pubsub_input: + $ref: '#/definitions/structs.GCPPubSubInput' + id: + type: string + name: + type: string + service_connection_id: + type: string + service_connection_input_type: + allOf: + - $ref: '#/definitions/structs.ServiceConnectionInputType' + description: Used to load all inputs for a service connection + status: + $ref: '#/definitions/structs.ServiceConnectionInputStatus' + updated_at: + type: string + type: object + structs.ServiceConnectionInputStatus: + enum: + - ok + - error + type: string + x-enum-varnames: + - ServiceConnectionInputStatusOK + - ServiceConnectionInputStatusError + structs.ServiceConnectionInputType: + enum: + - gcp_pubsub + - gcp_gcs + - aws_s3 + - aws_sqs + - aws_sns + - email + type: string + x-enum-varnames: + - ServiceConnectionInputTypeGCPPubSub + - ServiceConnectionInputTypeGCPGCS + - ServiceConnectionInputTypeAWSS3 + - ServiceConnectionInputTypeAWSSQS + - ServiceConnectionInputTypeAWSSNS + - ServiceConnectionInputTypeEmail + structs.ServiceConnectionOutput: + properties: + aws_s3_output: + $ref: '#/definitions/structs.AWSS3Output' + aws_sns_output: + $ref: '#/definitions/structs.AWSSNSOutput' + aws_sqs_output: + $ref: '#/definitions/structs.AWSSQSOutput' + bucket_id: + type: string + created_at: + type: integer + discord_output: + $ref: '#/definitions/structs.DiscordOutput' + function_id: + type: string + gcp_gcs_output: + $ref: '#/definitions/structs.GCPGCSOutput' + gcp_pubsub_output: + $ref: '#/definitions/structs.GCPPubSubOutput' + id: + type: string + name: + type: string + service_connection_id: + type: string + service_connection_output_type: + $ref: '#/definitions/structs.ServiceConnectionOutputType' + slack_output: + $ref: '#/definitions/structs.SlackOutput' + updated_at: + type: integer + type: object + structs.ServiceConnectionOutputType: + enum: + - gcp_pubsub + - gcp_gcs + - aws_s3 + - aws_sqs + - aws_sns + - discord + - slack + type: string + x-enum-varnames: + - ServiceConnectionOutputTypeGCPPubSub + - ServiceConnectionOutputTypeGCPGCS + - ServiceConnectionOutputTypeAWSS3 + - ServiceConnectionOutputTypeAWSSQS + - ServiceConnectionOutputTypeAWSSNS + - ServiceConnectionOutputTypeDiscord + - ServiceConnectionOutputTypeSlack + structs.ServiceConnectionStatus: + enum: + - pending + - connected + - error + type: string + x-enum-varnames: + - ServiceConnectionStatusPending + - ServiceConnectionStatusConnected + - ServiceConnectionStatusError + structs.ServiceType: + enum: + - gcp + - aws + - azure + - secret + - openai + - gemini + - anthropic + - custom_llm + - webhookrelay_ai + type: string + x-enum-varnames: + - ServiceGCP + - ServiceAWS + - ServiceAzure + - ServiceSecret + - ServiceOpenAI + - ServiceGemini + - ServiceAnthropic + - ServiceCustomLLM + - ServiceWebhookRelayAI + structs.SlackOutput: + properties: + webhook_url: + type: string + type: object + structs.SubAccount: + properties: + account: + $ref: '#/definitions/structs.Account' + account_id: + type: string + auth_type: + allOf: + - $ref: '#/definitions/structs.AccountAuthType' + description: authentication type (regular/github/google) + avatar_url: + type: string + created_at: + type: string + created_by: + description: |- + CreatedBy attributes the sub-account to whoever created it (an org + member's account ID; empty = the account owner). Used to revoke + sub-accounts an org member created when they leave the org. + type: string + deleted_at: + type: string + email: + type: string + failed_login_attempts: + type: integer + id: + type: string + last_failed_login: + type: string + last_login_at: + type: string + mfa_enabled: + type: boolean + saml_sso_org_id: + type: string + update_password: + description: If set, user will be asked to change the password after login + type: boolean + updated_at: + type: string + username: + type: string + type: object + structs.SubAccountCreateRequest: + properties: + auth_type: + $ref: '#/definitions/structs.AccountAuthType' + email: + type: string + username: + type: string + type: object + structs.SubAccountCreateResponse: + properties: + password: + type: string + sub_account: + $ref: '#/definitions/structs.SubAccount' + username: + type: string + type: object + structs.SubscriptionExtras: + properties: + description: + type: string + metadata: + additionalProperties: + type: string + type: object + price_id: + type: string + quantity: + type: integer + term: + $ref: '#/definitions/structs.SubscriptionTerm' + unit_amount: + type: integer + type: object + structs.SubscriptionResponse: + properties: + amount: + type: integer + cancel_at_period_end: + type: boolean + currency: + type: string + current_period_end: + type: integer + current_period_start: + type: integer + customer_id: + type: string + extras: + items: + $ref: '#/definitions/structs.SubscriptionExtras' + type: array + meta_data: + $ref: '#/definitions/structs.PlanMeta' + plan: + type: string + plan_id: + type: string + status: + type: string + subscription_id: + type: string + trial_end: + type: integer + trial_start: + type: integer + type: object + structs.SubscriptionTerm: + enum: + - monthly + - yearly + type: string + x-enum-varnames: + - SubscriptionTermMonthly + - SubscriptionTermYearly + structs.SuspiciousDetectionConfig: + properties: + high_score: + type: integer + high_signal_sets: + items: + items: + type: string + type: array + type: array + max_body_bytes: + type: integer + max_walk_depth: + type: integer + max_walk_nodes: + type: integer + min_score: + type: integer + realtime_enabled: + type: boolean + rules: + items: + $ref: '#/definitions/structs.SuspiciousDetectionRule' + type: array + type: object + structs.SuspiciousDetectionRule: + properties: + category: + type: string + description: + type: string + enabled: + type: boolean + id: + type: string + key_groups: + items: + $ref: '#/definitions/structs.SuspiciousMatchGroup' + type: array + match_local_paths: + type: boolean + value_groups: + items: + $ref: '#/definitions/structs.SuspiciousMatchGroup' + type: array + weight: + type: integer + type: object + structs.SuspiciousEvent: + properties: + account_id: + type: string + bucket_id: + type: string + category: + type: string + client: + type: string + created_at: + type: string + id: + type: string + input_id: + type: string + log_id: + type: string + occurred_at: + type: string + occurrences: + type: integer + output_id: + type: string + provider: + type: string + review_note: + type: string + reviewed_at: + type: string + reviewed_by_account_id: + type: string + reviewed_by_email: + type: string + reviews: + items: + $ref: '#/definitions/structs.SuspiciousEventReview' + type: array + rule_version: + type: string + score: + type: integer + severity: + type: string + signals: + items: + type: string + type: array + status: + $ref: '#/definitions/structs.SuspiciousEventStatus' + updated_at: + type: string + type: object + structs.SuspiciousEventReview: + properties: + created_at: + type: string + event_id: + type: string + id: + type: string + log_id: + type: string + note: + type: string + reviewer_account_id: + type: string + reviewer_email: + type: string + status: + $ref: '#/definitions/structs.SuspiciousEventStatus' + type: object + structs.SuspiciousEventStatus: + enum: + - open + - confirmed + - dismissed + type: string + x-enum-varnames: + - SuspiciousEventStatusOpen + - SuspiciousEventStatusConfirmed + - SuspiciousEventStatusDismissed + structs.SuspiciousMatchGroup: + properties: + min_matches: + type: integer + scope: + description: |- + Scope is "global" or "object". Object scope is valid for key groups + and requires the terms to coexist in one JSON object. + type: string + terms: + items: + type: string + type: array + type: object + structs.ThrottleConfig: + properties: + deadline: + allOf: + - $ref: '#/definitions/time.Duration' + description: |- + Deadline caps how long a queued webhook may wait for delivery, + measured from when it was received. Zero falls through to + DefaultThrottleDeadline. Webhooks older than the deadline are dropped + (marked failed) instead of delivered. + enabled: + description: Enabled toggles the whole feature for this output. + type: boolean + interval: + description: |- + Interval is ThrottleIntervalSecond / Minute / Hour. Used only in + ThrottleModeRate. + type: string + max_concurrent: + description: |- + MaxConcurrent is the maximum number of in-flight deliveries. Used + only in ThrottleModeConcurrency. 1 means serial delivery. + type: integer + max_queue_depth: + description: |- + MaxQueueDepth bounds how many webhooks may sit in the queue for this + output. Zero means unbounded. When exceeded, the ingester rejects + new webhooks with HTTP 429. + type: integer + mode: + description: Mode is ThrottleModeRate or ThrottleModeConcurrency. + type: string + rate: + description: |- + Rate is the maximum number of deliveries per Interval. Used only in + ThrottleModeRate. + type: integer + type: object + structs.TokenPermissions: + properties: + outbound: + description: |- + Outbound restricts this token to outbound API operations only. Empty + retains general API access. + enum: + - read + - publish + - manage + type: string + role: + allOf: + - $ref: '#/definitions/structs.OrgRole' + enum: + - admin + - billing + - member + - viewer + type: object + structs.Tunnel: + properties: + account_id: + type: string + addr: + description: |- + Addr specifies TCP address server would listen on, it's required + for TCP tunnels. + type: string + agent_id: + description: |- + AgentID is used by the ingress controller and is + randomly generated on startup. Once controller is running + it will send periodic updates to indicate that it's still running. + type: string + auth: + $ref: '#/definitions/structs.TunnelAuth' + created_at: + type: integer + created_by: + description: |- + CreatedBy is the account ID of the user who created the tunnel — + for organization accounts this is the acting member. Empty means + the account owner (agent auto-created tunnels leave it empty too). + type: string + crypto: + description: crypto types, used to issue lets encrypt certs + type: string + description: + type: string + destination: + description: destination host, defaults to 127.0.0.1:8000 + type: string + features: + $ref: '#/definitions/structs.Metadata' + group: + description: |- + optional tunnel group, primarily used by the ingress to subscribe + to specific group of tunnels + type: string + host: + description: |- + tunnel's subdomain, random for free tier + or named for paid subs + type: string + id: + type: string + ingress_rules: + $ref: '#/definitions/structs.JSONB' + mode: + $ref: '#/definitions/structs.TunnelMode' + name: + description: tunnel name + type: string + protocol: + description: tunnel protocol - http/tcp + type: string + region: + description: optional tunnel region + type: string + updated_at: + type: integer + type: object + structs.TunnelAuth: + properties: + created_at: + type: integer + id: + type: string + password: + type: string + token: + type: string + type: + $ref: '#/definitions/structs.AuthType' + updated_at: + type: integer + username: + type: string + type: object + structs.TunnelMode: + enum: + - 0 + - 1 + type: integer + x-enum-varnames: + - TunnelModeInactive + - TunnelModeActive + structs.UpdateAPIKeyStatusRequest: + properties: + enabled: + type: boolean + type: object + structs.UpdateAPIKeyStatusResponse: + properties: + enabled: + type: boolean + type: object + structs.UpdateFunctionRequest: + properties: + account_id: + type: string + driver: + type: string + id: + type: string + name: + type: string + payload: + type: string + type: object + structs.Usage: + properties: + account_id: + type: string + agents: + description: agents currently connected + type: integer + created_at: + type: string + inputs: + type: integer + outputs: + type: integer + seats: + description: |- + Seats is the shared organization-seat usage: sub-accounts plus + organization members and active pending invitations. On a personal + account it is simply the number of sub-accounts. + type: integer + tokens: + type: integer + tunnels: + type: integer + webhooks: + type: integer + type: object + structs.Variable: + properties: + account_id: + type: string + created_at: + type: string + function_id: + type: string + key: + type: string + updated_at: + type: string + value: + type: string + type: object + structs.WebhooksCount: + properties: + account_id: + description: account that it belongs to + type: string + created_at: + type: string + date: + description: beginning of the day for which the webhooks are calculated + type: string + failed: + type: integer + id: + type: string + preparing: + description: Potential webhook statuses + type: integer + received: + type: integer + rejected: + type: integer + request_bytes: + description: |- + Turbostore-only recorded body + HTTP header totals. Each delivery + contributes once, so output fan-out is counted in proportion to the + application-layer network traffic it creates. + type: integer + response_bytes: + type: integer + sent: + type: integer + stalled: + type: integer + term: + allOf: + - $ref: '#/definitions/structs.WebhooksCountTerm' + description: daily/monthly term of the calculation + total_bytes: + type: integer + updated_at: + type: string + type: object + structs.WebhooksCountTerm: + enum: + - 0 + - 1 + type: integer + x-enum-varnames: + - WebhooksCountTermDaily + - WebhooksCountTermMonthly + time.Duration: + enum: + - -9223372036854775808 + - 9223372036854775807 + - 1 + - 1000 + - 1000000 - 1000000000 - 60000000000 - 3600000000000 @@ -2119,6 +4936,84 @@ definitions: - Second - Minute - Hour + trafficstats.Snapshot: + properties: + client: + additionalProperties: + type: integer + type: object + clientVersion: + additionalProperties: + type: integer + type: object + contentType: + additionalProperties: + type: integer + type: object + country: + additionalProperties: + type: integer + type: object + flushedAt: + type: string + hostname: + type: string + ipVersion: + additionalProperties: + type: integer + type: object + language: + additionalProperties: + type: integer + type: object + method: + additionalProperties: + type: integer + type: object + provider: + additionalProperties: + type: integer + type: object + providerCountry: + additionalProperties: + type: integer + description: '"|"' + type: object + providerEvent: + additionalProperties: + type: integer + description: '"|"' + type: object + providerLanguage: + additionalProperties: + type: integer + description: '"|"' + type: object + providerTls: + additionalProperties: + type: integer + description: '"|"' + type: object + size: + additionalProperties: + type: integer + description: payload size bucket (from Content-Length) + type: object + startedAt: + type: string + tlsCipher: + additionalProperties: + type: integer + type: object + tlsVersion: + additionalProperties: + type: integer + type: object + total: + type: integer + version: + type: integer + type: object host: my.webhookrelay.com info: contact: @@ -2129,220 +5024,3809 @@ info: title: WebhookRelay API reference version: "0.1" paths: + /v1/account: + get: + consumes: + - application/json + description: Get the effective account (the organization account when acting + through the X-Org-ID override) + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/structs.Account' + security: + - BearerAuth: [] + summary: Get current account + tags: + - account + put: + consumes: + - application/json + description: Update account settings, including quota notification thresholds + and up to 10 additional validated email recipients, plus the organization + profile. Organization fields are optional. Converting to an organization is + one-way (the flag can never be unset) and only the account owner can do it + — not org admins acting through the override. The logo must be a small data:image/...;base64 + payload. + parameters: + - description: Account changes + in: body + name: account + required: true + schema: + $ref: '#/definitions/api.updateAccountRequest' + produces: + - application/json + responses: + "200": + description: OK + security: + - BearerAuth: [] + summary: Update account + tags: + - account /v1/account/api-key: get: consumes: - application/json - description: Get the account API key. If no key exists, a new one will be generated. + description: Get the account API key. If no key exists, a new one will be generated. + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/structs.AccountAPIKey' + "401": + description: Unauthorized + schema: + type: string + "500": + description: Internal server error + schema: + type: string + security: + - BearerAuth: [] + summary: Get account API key + tags: + - account + post: + consumes: + - application/json + description: Generate a new API key for the account, replacing the existing + one. + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/structs.AccountAPIKey' + "401": + description: Unauthorized + schema: + type: string + "500": + description: Internal server error + schema: + type: string + security: + - BearerAuth: [] + summary: Regenerate account API key + tags: + - account + put: + consumes: + - application/json + description: Enable or disable the account API key without regenerating it. + parameters: + - description: API key status + in: body + name: request + required: true + schema: + $ref: '#/definitions/structs.UpdateAPIKeyStatusRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/structs.UpdateAPIKeyStatusResponse' + "400": + description: Bad request + schema: + type: string + "401": + description: Unauthorized + schema: + type: string + "500": + description: Internal server error + schema: + type: string + security: + - BearerAuth: [] + summary: Enable or disable account API key + tags: + - account + /v1/account/audit: + get: + consumes: + - application/json + description: 'Audit entries for the effective account: who did what (owners, + org members, sub-accounts). Restricted to the owner and org admins.' + parameters: + - description: Page size (default 50, max 200) + in: query + name: limit + type: integer + - description: Offset + in: query + name: offset + type: integer + - description: Comma-separated resource kinds + in: query + name: filter + type: string + - description: Filter by acting user's username + in: query + name: username + type: string + - description: Filter by action (created/updated/deleted/...) + in: query + name: action + type: string + - description: 'Filter by surface: mcp (an MCP client) or agent (the agent chat)' + in: query + name: source + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.accountAuditResponse' + security: + - BearerAuth: [] + summary: Account activity log + tags: + - account + /v1/account/creators: + get: + consumes: + - application/json + description: List everyone who can have created resources on the effective account + — the owner, organization members and sub-accounts. Used by the dashboard + to resolve created_by attribution. + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/api.creatorIdentity' + type: array + security: + - BearerAuth: [] + summary: List account creator identities + tags: + - account + /v1/account/mfa: + delete: + consumes: + - application/json + description: Disable MFA after validating a current authenticator token. + parameters: + - description: Authenticator token + in: body + name: request + required: true + schema: + $ref: '#/definitions/api.mfaConfirmRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.mfaStatusResponse' + security: + - BearerAuth: [] + summary: Disable MFA + tags: + - account + /v1/account/mfa/confirm: + post: + consumes: + - application/json + description: Enable MFA after validating a token from the pending TOTP secret. + parameters: + - description: Authenticator token + in: body + name: request + required: true + schema: + $ref: '#/definitions/api.mfaConfirmRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.mfaStatusResponse' + security: + - BearerAuth: [] + summary: Confirm MFA setup + tags: + - account + /v1/account/mfa/setup: + post: + consumes: + - application/json + description: Generate a TOTP secret and QR code for the authenticated account + or sub-account. + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.mfaSetupResponse' + security: + - BearerAuth: [] + summary: Start MFA setup + tags: + - account + /v1/accounts: + get: + consumes: + - application/json + description: List all Webhook Relay accounts for platform administration and + account selection. + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/structs.Account' + type: array + "500": + description: Internal Server Error + schema: + type: string + security: + - BearerAuth: [] + summary: List accounts (admin) + tags: + - admin + /v1/admin/accounts/{id}/buckets/suspension: + put: + consumes: + - application/json + description: Manually set the suspended flag on every bucket belonging to any + account. Manual suspension is rejected while suspend protection is enabled. + parameters: + - description: Account ID + in: path + name: id + required: true + type: string + - description: Desired bucket suspension state + in: body + name: suspension + required: true + schema: + $ref: '#/definitions/api.adminBucketSuspensionUpdateRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.adminBucketSuspensionResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/structs.ErrorResponse' + "404": + description: Not Found + schema: + $ref: '#/definitions/structs.ErrorResponse' + "412": + description: Precondition Failed + schema: + $ref: '#/definitions/structs.ErrorResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/structs.ErrorResponse' + security: + - BearerAuth: [] + summary: Suspend or unsuspend all account buckets (admin) + tags: + - admin + - accounts + /v1/admin/accounts/{id}/identity: + put: + consumes: + - application/json + description: Change an account's login email and/or authentication type. Authentication + type is limited to regular, github, or google; SAML identities remain managed + through SSO configuration. Email verification state is preserved. + parameters: + - description: Account ID + in: path + name: id + required: true + type: string + - description: Sign-in identity changes + in: body + name: identity + required: true + schema: + $ref: '#/definitions/api.adminAccountIdentityUpdateRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.adminAccountSearchResult' + "400": + description: Bad Request + schema: + $ref: '#/definitions/structs.ErrorResponse' + "404": + description: Not Found + schema: + $ref: '#/definitions/structs.ErrorResponse' + "409": + description: Conflict + schema: + $ref: '#/definitions/structs.ErrorResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/structs.ErrorResponse' + security: + - BearerAuth: [] + summary: Update account sign-in identity (admin) + tags: + - admin + /v1/admin/accounts/{id}/status: + get: + consumes: + - application/json + description: Get stored subscription status, billing term dates, plan and subscription + metadata, effective entitlements, extras and suspension protection for any + account. + parameters: + - description: Account ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.adminAccountStatus' + "404": + description: Not Found + schema: + $ref: '#/definitions/structs.ErrorResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/structs.ErrorResponse' + security: + - BearerAuth: [] + summary: Get account subscription status (admin) + tags: + - admin + - accounts + /v1/admin/accounts/{id}/suspend-protection: + put: + consumes: + - application/json + description: Enable or disable the manual override that prevents automated quota + and billing paths from suspending any account's buckets. + parameters: + - description: Account ID + in: path + name: id + required: true + type: string + - description: Suspend protection state + in: body + name: protection + required: true + schema: + $ref: '#/definitions/api.adminSuspendProtectionUpdateRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.adminAccountStatus' + "400": + description: Bad Request + schema: + $ref: '#/definitions/structs.ErrorResponse' + "404": + description: Not Found + schema: + $ref: '#/definitions/structs.ErrorResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/structs.ErrorResponse' + security: + - BearerAuth: [] + summary: Update account suspend protection (admin) + tags: + - admin + - accounts + /v1/admin/accounts/recent: + get: + consumes: + - application/json + description: Accounts created at or after `created_after`, oldest first, for + reconciling a registration feed. Registration identity only — no billing metadata + or account-owned resources. + parameters: + - description: RFC 3339 timestamp; accounts created at or after this instant + in: query + name: created_after + required: true + type: string + - description: Maximum results (default 100, max 500) + in: query + maximum: 500 + minimum: 1 + name: limit + type: integer + - description: Offset into the result set + in: query + minimum: 0 + name: offset + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.adminRecentAccountsResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/structs.ErrorResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/structs.ErrorResponse' + security: + - BearerAuth: [] + summary: List recent registrations (admin) + tags: + - admin + - organizations + /v1/admin/accounts/search: + get: + consumes: + - application/json + description: Search accounts by email or username prefix, or by exact account + ID. Results are bounded for server-backed admin account selectors. + parameters: + - description: Email/username prefix or exact account ID + in: query + minLength: 2 + name: query + required: true + type: string + - description: Maximum results (default 20, max 50) + in: query + maximum: 50 + minimum: 1 + name: limit + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/api.adminAccountSearchResult' + type: array + "400": + description: Bad Request + schema: + $ref: '#/definitions/structs.ErrorResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/structs.ErrorResponse' + security: + - BearerAuth: [] + summary: Search accounts (admin) + tags: + - admin + - organizations + /v1/admin/agent/conversations: + get: + description: Every conversation across accounts with its session aggregates, + newest activity first; filter by account_id, stop_cause, or rated=up|down|any + parameters: + - description: Only this account + in: query + name: account_id + type: string + - description: Only conversations whose last turn ended with this cause + in: query + name: stop_cause + type: string + - description: 'up, down or any: only conversations with that feedback' + in: query + name: rated + type: string + - description: 'any, approved, denied, expired, canceled or pending: only conversations + whose destructive calls asked the user' + in: query + name: approvals + type: string + - description: Page size (default 50, max 200) + in: query + name: limit + type: integer + - description: Page offset + in: query + name: offset + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/agent.AdminPage' + "503": + description: Agent not enabled + schema: + type: string + security: + - BearerAuth: [] + summary: List agent conversations (admin) + tags: + - admin + /v1/admin/agent/conversations/{id}: + get: + description: One conversation with its stored transcript, latest 500 tool calls + and inferences, latest 200 prompts, feedback and approvals; truncated flags + identify omitted earlier evidence + parameters: + - description: Conversation ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/agent.AdminDetail' + "404": + description: Not Found + schema: + type: string + security: + - BearerAuth: [] + summary: Agent conversation detail (admin) + tags: + - admin + /v1/admin/agent/limits: + get: + description: 'The runtime-adjustable agent limits: stored overrides, deployed + defaults and the effective values. Overrides live in the database so they + can be tuned without a deployment.' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.AdminAgentLimits' + "503": + description: Agent not enabled + schema: + type: string + security: + - BearerAuth: [] + summary: Agent limit overrides (admin) + tags: + - admin + put: + consumes: + - application/json + description: Replaces the stored override set. A zero or omitted field clears + that override back to the deployed default. Every replica picks the change + up within seconds. + parameters: + - description: Override set + in: body + name: body + required: true + schema: + $ref: '#/definitions/api.AdminAgentLimitsUpdateRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.AdminAgentLimits' + "400": + description: Invalid overrides + schema: + type: string + "503": + description: Agent not enabled + schema: + type: string + security: + - BearerAuth: [] + summary: Update agent limit overrides (admin) + tags: + - admin + /v1/admin/agent/stats: + get: + description: All-time cross-account totals and latest-session stop causes, plus + a UTC daily activity series for the last N days counting conversation creation, + prompt settlement, and tool-call timestamps + parameters: + - description: Length of the daily series (default 30) + in: query + name: days + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/agent.AdminStats' + "503": + description: Agent not enabled + schema: + type: string + security: + - BearerAuth: [] + summary: Agent usage totals (admin) + tags: + - admin + /v1/admin/connected-clients: + get: + consumes: + - application/json + description: Get list of all connected clients across all accounts from the + state tracker service. + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/structs.AdminConnectedClientsResponse' + "500": + description: Internal Server Error + schema: + type: string + "503": + description: Service Unavailable + schema: + type: string + security: + - BearerAuth: [] + summary: Get all connected clients (admin) + tags: + - admin + /v1/admin/enterprise-deals/metadata-schema: + get: + description: Canonical schema for Stripe plan/subscription metadata used by + enterprise deals. Numeric limits and boolean capabilities include labels, + descriptions, groups, units, aliases, and validation bounds. + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.EnterprisePlanMetadataSchemaResponse' + security: + - BearerAuth: [] + summary: List supported enterprise entitlement metadata fields (admin) + tags: + - admin + - enterprise-crm + /v1/admin/orgs: + get: + consumes: + - application/json + description: List every active or inactive organization account with owner identity + and member/sub-account counts. + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/api.adminOrganizationSummary' + type: array + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/structs.ErrorResponse' + security: + - BearerAuth: [] + summary: List organizations (admin) + tags: + - admin + - organizations + /v1/admin/orgs/{id}: + get: + consumes: + - application/json + description: Get an organization account together with its member roster and + active sub-accounts. + parameters: + - description: Organization account ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.adminOrganizationDetails' + "404": + description: Not Found + schema: + $ref: '#/definitions/structs.ErrorResponse' + "412": + description: Precondition Failed + schema: + $ref: '#/definitions/structs.ErrorResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/structs.ErrorResponse' + security: + - BearerAuth: [] + summary: Get organization details (admin) + tags: + - admin + - organizations + put: + consumes: + - application/json + description: Convert an individual account to an organization, or update an + existing organization's name and description. Conversion is one-way. Admin + operations bypass self-service seat limits. + parameters: + - description: Account ID + in: path + name: id + required: true + type: string + - description: Organization profile + in: body + name: organization + required: true + schema: + $ref: '#/definitions/api.adminOrganizationUpdateRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.adminOrganizationSummary' + "400": + description: Bad Request + schema: + $ref: '#/definitions/structs.ErrorResponse' + "404": + description: Not Found + schema: + $ref: '#/definitions/structs.ErrorResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/structs.ErrorResponse' + security: + - BearerAuth: [] + summary: Convert or update organization (admin) + tags: + - admin + - organizations + /v1/admin/orgs/{id}/buckets/suspension: + put: + consumes: + - application/json + description: Manually set the suspended flag on every organization bucket. Manual + suspension is rejected while suspend protection is enabled. + parameters: + - description: Organization account ID + in: path + name: id + required: true + type: string + - description: Desired bucket suspension state + in: body + name: suspension + required: true + schema: + $ref: '#/definitions/api.adminBucketSuspensionUpdateRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.adminBucketSuspensionResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/structs.ErrorResponse' + "404": + description: Not Found + schema: + $ref: '#/definitions/structs.ErrorResponse' + "412": + description: Precondition Failed + schema: + $ref: '#/definitions/structs.ErrorResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/structs.ErrorResponse' + security: + - BearerAuth: [] + summary: Suspend or unsuspend all organization buckets (admin) + tags: + - admin + - organizations + /v1/admin/orgs/{id}/members: + post: + consumes: + - application/json + description: Directly link an existing active account to an organization with + an assignable role. No invitation acceptance is required and admin operations + bypass self-service seat limits. + parameters: + - description: Organization account ID + in: path + name: id + required: true + type: string + - description: Member account and role + in: body + name: member + required: true + schema: + $ref: '#/definitions/api.adminOrganizationMemberCreateRequest' + produces: + - application/json + responses: + "201": + description: Created + schema: + $ref: '#/definitions/structs.OrganizationMemberDetails' + "400": + description: Bad Request + schema: + $ref: '#/definitions/structs.ErrorResponse' + "404": + description: Not Found + schema: + $ref: '#/definitions/structs.ErrorResponse' + "409": + description: Conflict + schema: + $ref: '#/definitions/structs.ErrorResponse' + "412": + description: Precondition Failed + schema: + $ref: '#/definitions/structs.ErrorResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/structs.ErrorResponse' + security: + - BearerAuth: [] + summary: Add organization member (admin) + tags: + - admin + - organizations + /v1/admin/orgs/{id}/members/{memberID}: + delete: + consumes: + - application/json + description: Remove a member and revoke organization-bound access tokens and + sub-accounts created by that member. + parameters: + - description: Organization account ID + in: path + name: id + required: true + type: string + - description: Organization membership ID + in: path + name: memberID + required: true + type: string + produces: + - application/json + responses: + "204": + description: No Content + "404": + description: Not Found + schema: + $ref: '#/definitions/structs.ErrorResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/structs.ErrorResponse' + security: + - BearerAuth: [] + summary: Remove organization member (admin) + tags: + - admin + - organizations + put: + consumes: + - application/json + description: Change an existing organization member's role and update the role + captured on organization-bound access tokens. + parameters: + - description: Organization account ID + in: path + name: id + required: true + type: string + - description: Organization membership ID + in: path + name: memberID + required: true + type: string + - description: Role change + in: body + name: member + required: true + schema: + $ref: '#/definitions/api.adminOrganizationMemberUpdateRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/structs.OrganizationMember' + "400": + description: Bad Request + schema: + $ref: '#/definitions/structs.ErrorResponse' + "404": + description: Not Found + schema: + $ref: '#/definitions/structs.ErrorResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/structs.ErrorResponse' + security: + - BearerAuth: [] + summary: Update organization member role (admin) + tags: + - admin + - organizations + /v1/admin/orgs/{id}/status: + get: + consumes: + - application/json + description: Get stored subscription status, billing term dates, plan and subscription + metadata, effective entitlements, extras and suspension protection for an + organization account. + parameters: + - description: Organization account ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.adminAccountStatus' + "404": + description: Not Found + schema: + $ref: '#/definitions/structs.ErrorResponse' + "412": + description: Precondition Failed + schema: + $ref: '#/definitions/structs.ErrorResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/structs.ErrorResponse' + security: + - BearerAuth: [] + summary: Get organization subscription status (admin) + tags: + - admin + - organizations + /v1/admin/orgs/{id}/sub-accounts: + post: + consumes: + - application/json + description: Create a regular, GitHub, or Google sub-account directly under + an organization. Regular accounts return a one-time password. Admin operations + bypass self-service seat limits. + parameters: + - description: Organization account ID + in: path + name: id + required: true + type: string + - description: Sub-account configuration + in: body + name: subAccount + required: true + schema: + $ref: '#/definitions/api.adminSubAccountCreateRequest' + produces: + - application/json + responses: + "201": + description: Created + schema: + $ref: '#/definitions/structs.SubAccountCreateResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/structs.ErrorResponse' + "404": + description: Not Found + schema: + $ref: '#/definitions/structs.ErrorResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/structs.ErrorResponse' + security: + - BearerAuth: [] + summary: Create organization sub-account (admin) + tags: + - admin + - organizations + /v1/admin/orgs/{id}/sub-accounts/{subID}: + delete: + consumes: + - application/json + description: Delete a sub-account from the specified organization and immediately + revoke its access. + parameters: + - description: Organization account ID + in: path + name: id + required: true + type: string + - description: Sub-account ID + in: path + name: subID + required: true + type: string + produces: + - application/json + responses: + "204": + description: No Content + "404": + description: Not Found + schema: + $ref: '#/definitions/structs.ErrorResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/structs.ErrorResponse' + security: + - BearerAuth: [] + summary: Delete organization sub-account (admin) + tags: + - admin + - organizations + /v1/admin/orgs/{id}/sub-accounts/{subID}/reset-password: + post: + consumes: + - application/json + description: Generate and return a new one-time password for a regular organization + sub-account. + parameters: + - description: Organization account ID + in: path + name: id + required: true + type: string + - description: Sub-account ID + in: path + name: subID + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/structs.SubAccountCreateResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/structs.ErrorResponse' + "404": + description: Not Found + schema: + $ref: '#/definitions/structs.ErrorResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/structs.ErrorResponse' + security: + - BearerAuth: [] + summary: Reset organization sub-account password (admin) + tags: + - admin + - organizations + /v1/admin/orgs/{id}/suspend-protection: + put: + consumes: + - application/json + description: Enable or disable the manual override that prevents automated quota + and billing paths from suspending the organization's buckets. + parameters: + - description: Organization account ID + in: path + name: id + required: true + type: string + - description: Suspend protection state + in: body + name: protection + required: true + schema: + $ref: '#/definitions/api.adminSuspendProtectionUpdateRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.adminAccountStatus' + "400": + description: Bad Request + schema: + $ref: '#/definitions/structs.ErrorResponse' + "404": + description: Not Found + schema: + $ref: '#/definitions/structs.ErrorResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/structs.ErrorResponse' + security: + - BearerAuth: [] + summary: Update organization suspend protection (admin) + tags: + - admin + - organizations + /v1/admin/orgs/{id}/usage: + get: + consumes: + - application/json + description: Get current billing-term usage and effective plan limits for an + organization account. Live agents are reported as zero when State Tracker + is unavailable; persisted usage remains available. + parameters: + - description: Organization account ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/structs.CombinedUsage' + "400": + description: Bad Request + schema: + $ref: '#/definitions/structs.ErrorResponse' + "404": + description: Not Found + schema: + $ref: '#/definitions/structs.ErrorResponse' + "412": + description: Precondition Failed + schema: + $ref: '#/definitions/structs.ErrorResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/structs.ErrorResponse' + "504": + description: Gateway Timeout + schema: + $ref: '#/definitions/structs.ErrorResponse' + security: + - BearerAuth: [] + summary: Get organization usage (admin) + tags: + - admin + - organizations + /v1/admin/suspicious-events: + get: + description: Lists real-time detector findings. Findings contain sanitized signal + names and a reference to the canonical Turbostore webhook; no payload is copied + into the review table. + parameters: + - description: Exact account ID + in: query + name: account_id + type: string + - description: 'Review status: open, confirmed, dismissed' + in: query + name: status + type: string + - description: 'Severity: medium or high' + in: query + name: severity + type: string + - description: Finding category + in: query + name: category + type: string + - description: Page size + in: query + name: limit + type: integer + - description: Offset + in: query + name: offset + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.suspiciousEventListResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/structs.ErrorResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/structs.ErrorResponse' + security: + - BearerAuth: [] + summary: List suspicious webhook findings + tags: + - admin + - security + /v1/admin/suspicious-events/{id}: + get: + parameters: + - description: Finding ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/structs.SuspiciousEvent' + "404": + description: Not Found + schema: + $ref: '#/definitions/structs.ErrorResponse' + security: + - BearerAuth: [] + summary: Get a suspicious webhook finding + tags: + - admin + - security + /v1/admin/suspicious-events/{id}/review: + put: + consumes: + - application/json + description: Marks a finding confirmed, dismissed, or reopens it. This does + not suspend the account. + parameters: + - description: Finding ID + in: path + name: id + required: true + type: string + - description: Review decision + in: body + name: review + required: true + schema: + $ref: '#/definitions/api.suspiciousEventReviewRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/structs.SuspiciousEvent' + "400": + description: Bad Request + schema: + $ref: '#/definitions/structs.ErrorResponse' + "404": + description: Not Found + schema: + $ref: '#/definitions/structs.ErrorResponse' + security: + - BearerAuth: [] + summary: Review a suspicious webhook finding + tags: + - admin + - security + /v1/admin/suspicious-events/{id}/webhook: + get: + description: Loads the canonical webhook directly from Turbostore for admin + review. There is no ClickHouse fallback. + parameters: + - description: Finding ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.suspiciousEventWebhookResponse' + "404": + description: Not Found + schema: + $ref: '#/definitions/structs.ErrorResponse' + "503": + description: Service Unavailable + schema: + $ref: '#/definitions/structs.ErrorResponse' + security: + - BearerAuth: [] + summary: Get the Turbostore webhook for a suspicious finding + tags: + - admin + - security + /v1/admin/suspicious-events/hunt: + post: + consumes: + - application/json + description: Runs only when called by an admin. The hunt is account-, bucket-, + time-, and page-bounded and never reads ClickHouse. Continue with next_cursor + until it is empty. + parameters: + - description: Bounded hunt target + in: body + name: hunt + required: true + schema: + $ref: '#/definitions/api.suspiciousHuntRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.suspiciousHuntResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/structs.ErrorResponse' + "409": + description: Conflict + schema: + $ref: '#/definitions/structs.ErrorResponse' + "503": + description: Service Unavailable + schema: + $ref: '#/definitions/structs.ErrorResponse' + security: + - BearerAuth: [] + summary: Scan one bounded Turbostore history page for suspicious webhooks + tags: + - admin + - security + /v1/admin/suspicious-events/rules: + get: + description: Returns the effective database-backed rule set used for real-time + detection and explicit historical hunts. + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.suspiciousDetectionSettingsResponse' + security: + - BearerAuth: [] + summary: Get suspicious webhook detection rules + tags: + - admin + - security + put: + consumes: + - application/json + description: Validates and atomically replaces the detector rule set. Real-time + processes refresh it within 15 seconds; no historical scan is started. + parameters: + - description: Rule set and current version + in: body + name: settings + required: true + schema: + $ref: '#/definitions/api.suspiciousDetectionSettingsRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.suspiciousDetectionSettingsResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/structs.ErrorResponse' + "409": + description: Conflict + schema: + $ref: '#/definitions/structs.ErrorResponse' + security: + - BearerAuth: [] + summary: Replace suspicious webhook detection rules + tags: + - admin + - security + /v1/admin/traffic-stats: + get: + consumes: + - application/json + description: 'Per-ingester-replica cumulative counters of incoming webhook traffic: + provider fingerprint, client family/language, negotiated TLS version/cipher, + sender country. No payloads or identifiers are collected.' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.AdminTrafficStatsResponse' + "503": + description: Service Unavailable + schema: + type: string + security: + - BearerAuth: [] + summary: Get aggregate incoming webhook traffic statistics (admin) + tags: + - admin + /v1/admin/usage-alerts: + get: + consumes: + - application/json + description: Returns successfully sent quota notifications newest first, including + account identity, threshold, usage/quota at send time, plan, and billing period. + Filter by account_id for the account-details Usage alerts tab. + parameters: + - description: Filter to one account ID + in: query + name: account_id + type: string + - description: Page size (default 50, max 200) + in: query + maximum: 200 + minimum: 1 + name: limit + type: integer + - description: Page offset + in: query + minimum: 0 + name: offset + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.AdminUsageAlertsResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/structs.ErrorResponse' + security: + - BearerAuth: [] + summary: List sent quota usage alerts (admin) + tags: + - admin + /v1/admin/usage/buckets: + get: + consumes: + - application/json + description: Paginated cross-account bucket inventory with each bucket's inputs + (incl. transformation functions) and outputs (destination URL, classified + destination provider, type, functions). Answers "what are customers wiring + the service up to". + parameters: + - description: Filter to one account + in: query + name: account_id + type: string + - description: Page size (default 100, max 500) + in: query + maximum: 500 + minimum: 1 + name: limit + type: integer + - description: Page offset + in: query + minimum: 0 + name: offset + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.AdminUsageBucketsResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/structs.ErrorResponse' + security: + - BearerAuth: [] + summary: List buckets across all accounts (admin) + tags: + - admin + /v1/admin/usage/outputs: + get: + consumes: + - application/json + description: 'Paginated cross-account output inventory: destination URL (basic-auth + passwords masked), classified destination provider, internal/public type and + attached functions, with bucket and account attribution. Use destination=substr + to answer e.g. "who forwards to jenkins". Note destination_provider classifies + the destination ADDRESS (jenkins, slack, localhost, private-network, ...) + and is independent of the internal flag, which is the delivery mode: a private-IP + destination delivered server-side shows internal=false with destination_provider=private-network.' + parameters: + - description: Filter to one account + in: query + name: account_id + type: string + - description: Case-insensitive destination URL substring filter + in: query + name: destination + type: string + - description: Page size (default 100, max 500) + in: query + maximum: 500 + minimum: 1 + name: limit + type: integer + - description: Page offset + in: query + minimum: 0 + name: offset + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.AdminUsageOutputsResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/structs.ErrorResponse' + security: + - BearerAuth: [] + summary: List outputs across all accounts (admin) + tags: + - admin + /v1/admin/usage/summary: + get: + consumes: + - application/json + description: Fleet-level classification of every output's destination (jenkins, + slack, ms-teams, localhost, unknown, ...) plus internal/disabled/function + counts. The inbound-side counterpart (which providers send us traffic, incl. + fingerprinted event types) is /v1/admin/traffic-stats. + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.AdminUsageSummaryResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/structs.ErrorResponse' + security: + - BearerAuth: [] + summary: Aggregate destination usage across all outputs (admin) + tags: + - admin + /v1/admin/usage/webhooks: + get: + consumes: + - application/json + description: Returns a dense month-by-month series of inbound webhook requests. + A webhook is counted once when received, independently of how many outputs + it is delivered to. Defaults to the current month and previous 11 calendar + months. + parameters: + - description: Account ID + in: query + name: account_id + required: true + type: string + - description: From date (YYYY-MM-DD); defaults to 11 months before the current + month + in: query + name: from + type: string + - description: To date (YYYY-MM-DD); defaults to today + in: query + name: to + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.AdminUsageWebhooksResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/structs.ErrorResponse' + "404": + description: Not Found + schema: + $ref: '#/definitions/structs.ErrorResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/structs.ErrorResponse' + security: + - BearerAuth: [] + summary: Get monthly webhook volume for an account (admin) + tags: + - admin + /v1/agent: + get: + description: Whether the account agent is enabled on this server, which model + answers, and what the caller's grant permits + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.AgentStatus' + "401": + description: Unauthorized + schema: + type: string + security: + - BearerAuth: [] + summary: Agent status + tags: + - agent + /v1/agent/conversations: + get: + description: Conversations of the authenticated account, newest activity first; + filter by the page they were opened from + parameters: + - description: Page kind the conversation was opened from (function, bucket, + account) + in: query + name: context_kind + type: string + - description: ID of that page's resource + in: query + name: context_id + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/structs.AgentConversation' + type: array + "401": + description: Unauthorized + schema: + type: string + "503": + description: Agent not enabled + schema: + type: string + security: + - BearerAuth: [] + summary: List agent conversations + tags: + - agent + post: + consumes: + - application/json + description: Open a conversation, optionally bound to the page it was started + from (a function context must be the caller's own function) + parameters: + - description: Conversation context + in: body + name: conversation + required: true + schema: + $ref: '#/definitions/api.AgentConversationRequest' + produces: + - application/json + responses: + "201": + description: Created + schema: + $ref: '#/definitions/structs.AgentConversation' + "400": + description: Bad Request + schema: + type: string + "404": + description: Context resource not found + schema: + type: string + "503": + description: Agent not enabled + schema: + type: string + security: + - BearerAuth: [] + summary: Create agent conversation + tags: + - agent + /v1/agent/conversations/{id}: + delete: + description: Deletes the conversation and its stored transcript + parameters: + - description: Conversation ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.Response' + "404": + description: Not Found + schema: + type: string + security: + - BearerAuth: [] + summary: Delete agent conversation + tags: + - agent + get: + description: The conversation, its stored transcript, and whether a turn is + running on any replica + parameters: + - description: Conversation ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.AgentConversationDetail' + "404": + description: Not Found + schema: + type: string + "503": + description: Agent not enabled + schema: + type: string + security: + - BearerAuth: [] + summary: Get agent conversation + tags: + - agent + put: + consumes: + - application/json + parameters: + - description: Conversation ID + in: path + name: id + required: true + type: string + - description: New title + in: body + name: conversation + required: true + schema: + $ref: '#/definitions/api.AgentConversationRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.Response' + "400": + description: Bad Request + schema: + type: string + "404": + description: Not Found + schema: + type: string + security: + - BearerAuth: [] + summary: Rename agent conversation + tags: + - agent + /v1/agent/conversations/{id}/approve: + post: + consumes: + - application/json + description: 'Answers an approval_requested event: the paused call runs with + the scope it lacked. With remember the scope is also recorded on the conversation, + so later calls needing it do not ask. Limited by the caller''s role. 202 when + the answer was broadcast to the replica running the turn.' + parameters: + - description: Conversation ID + in: path + name: id + required: true + type: string + - description: Call to allow (call_id, scope, remember) + in: body + name: decision + required: true + schema: + $ref: '#/definitions/api.AgentApprovalRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.Response' + "202": + description: Accepted + schema: + $ref: '#/definitions/api.Response' + "400": + description: Invalid body + schema: + type: string + "403": + description: Role cannot approve this scope + schema: + type: string + "404": + description: No turn running or no approval pending for the call + schema: + type: string + "503": + description: Agent not configured + schema: + type: string + security: + - ApiKeyAuth: [] + summary: Allow a paused destructive tool call + tags: + - agent + /v1/agent/conversations/{id}/cancel: + post: + description: Stops the current turn; completed tool results are kept. 202 when + the request was broadcast to the replica running the turn. + parameters: + - description: Conversation ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.Response' + "202": + description: Accepted + schema: + $ref: '#/definitions/api.Response' + "404": + description: No running turn + schema: + type: string + security: + - BearerAuth: [] + summary: Cancel the running agent turn + tags: + - agent + /v1/agent/conversations/{id}/deny: + post: + consumes: + - application/json + description: 'Answers an approval_requested event: the call does not run and + the agent is told, with the optional text as the reason. 202 when the answer + was broadcast to the replica running the turn.' + parameters: + - description: Conversation ID + in: path + name: id + required: true + type: string + - description: Call to decline (call_id, text) + in: body + name: decision + required: true + schema: + $ref: '#/definitions/api.AgentApprovalRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.Response' + "202": + description: Accepted + schema: + $ref: '#/definitions/api.Response' + "400": + description: Invalid body + schema: + type: string + "404": + description: No turn running or no approval pending for the call + schema: + type: string + "503": + description: Agent not configured + schema: + type: string + security: + - ApiKeyAuth: [] + summary: Decline a paused destructive tool call + tags: + - agent + /v1/agent/conversations/{id}/feedback: + get: + description: The thumbs up/down ratings the account gave messages in a conversation + parameters: + - description: Conversation ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/structs.AgentFeedback' + type: array + "404": + description: Not Found + schema: + type: string + security: + - BearerAuth: [] + summary: List message feedback + tags: + - agent + post: + consumes: + - application/json + description: Records a thumbs up or down on one assistant message (by its index + in the stored transcript); rating the same message again replaces the earlier + rating + parameters: + - description: Conversation ID + in: path + name: id + required: true + type: string + - description: Rating + in: body + name: feedback + required: true + schema: + $ref: '#/definitions/api.AgentFeedbackRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/structs.AgentFeedback' + "400": + description: Bad Request + schema: + type: string + "404": + description: Not Found + schema: + type: string + security: + - BearerAuth: [] + summary: Rate an assistant message + tags: + - agent + /v1/agent/conversations/{id}/feedback/{index}: + delete: + parameters: + - description: Conversation ID + in: path + name: id + required: true + type: string + - description: Message index + in: path + name: index + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.Response' + "404": + description: Not Found + schema: + type: string + security: + - BearerAuth: [] + summary: Remove a message rating + tags: + - agent + /v1/agent/conversations/{id}/messages: + post: + consumes: + - application/json + description: 'Starts one turn and streams its events as server-sent events (text/event-stream): + meta, text_delta, text, tool_call, tool_result, refused, usage, done. The + turn keeps running if the client disconnects; re-attach with GET /v1/agent/conversations/{id}/stream. + The prompt id is an idempotency key.' + parameters: + - description: Conversation ID + in: path + name: id + required: true + type: string + - description: User message + in: body + name: message + required: true + schema: + $ref: '#/definitions/api.AgentMessageRequest' + produces: + - text/event-stream + responses: + "200": + description: event stream + schema: + type: string + "400": + description: Bad Request + schema: + type: string + "404": + description: Not Found + schema: + type: string + "409": + description: A turn is already running + schema: + type: string + "429": + description: Monthly token allowance used up + schema: + $ref: '#/definitions/api.AgentQuotaExceeded' + security: + - BearerAuth: [] + summary: Send a message to the agent + tags: + - agent + /v1/agent/conversations/{id}/steer: + post: + consumes: + - application/json + description: Cancels the current work and queues a replacement instruction on + the same conversation + parameters: + - description: Conversation ID + in: path + name: id + required: true + type: string + - description: Steering instruction (text) + in: body + name: control + required: true + schema: + $ref: '#/definitions/api.AgentControlRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.Response' + "202": + description: Accepted + schema: + $ref: '#/definitions/api.Response' + "400": + description: Bad Request + schema: + type: string + "404": + description: No running turn + schema: + type: string + security: + - BearerAuth: [] + summary: Steer the running agent turn + tags: + - agent + /v1/agent/conversations/{id}/stream: + get: + description: 'Re-joins a turn already running on any replica as server-sent + events: the events so far are replayed, then followed live. 404 when nothing + is running (read the stored transcript instead).' + parameters: + - description: Conversation ID + in: path + name: id + required: true + type: string + produces: + - text/event-stream + responses: + "200": + description: event stream + schema: + type: string + "404": + description: No running turn + schema: + type: string + security: + - BearerAuth: [] + summary: Attach to a running agent turn + tags: + - agent + /v1/agent/conversations/{id}/widen: + post: + consumes: + - application/json + description: Widens the conversation's grant by one harness scope (e.g. routing:drop + after a refused delete). The approval is recorded on the conversation and + applies to the running turn and every later one. Limited by the caller's role. + parameters: + - description: Conversation ID + in: path + name: id + required: true + type: string + - description: Scope to approve (scope) + in: body + name: control + required: true + schema: + $ref: '#/definitions/api.AgentControlRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.Response' + "202": + description: Accepted + schema: + $ref: '#/definitions/api.Response' + "400": + description: Invalid scope + schema: + type: string + "403": + description: Role cannot approve this scope + schema: + type: string + "404": + description: Not Found + schema: + type: string + security: + - BearerAuth: [] + summary: Approve a scope for the conversation + tags: + - agent + /v1/agent/tools: + get: + description: Every account tool the agent can reach, the harness scope it needs, + and whether the caller's grant permits it or could approve it + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.AgentToolsResponse' + "401": + description: Unauthorized + schema: + type: string + "503": + description: Agent not enabled + schema: + type: string + security: + - BearerAuth: [] + summary: List agent tools + tags: + - agent + /v1/audit: + get: + consumes: + - application/json + description: List audit entries across the platform or scope them to one exact + account. Platform admins bypass account-plan activity restrictions. + parameters: + - description: Page size + in: query + name: limit + type: integer + - description: Offset + in: query + name: offset + type: integer + - description: Comma-separated resource kinds + in: query + name: filter + type: string + - description: Exact account ID + in: query + name: account_id + type: string + - description: Account email or ID (legacy filter) + in: query + name: email + type: string + - description: Filter by acting user's username + in: query + name: username + type: string + - description: Filter by action + in: query + name: action + type: string + - description: 'Filter by surface: mcp or agent' + in: query + name: source + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.auditLogsResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/structs.ErrorResponse' + security: + - BearerAuth: [] + summary: List audit entries (admin) + tags: + - admin + - audit + /v1/auth/mfa/verify: + post: + consumes: + - application/json + description: Exchange an MFA challenge token and authenticator code for a session + token. + parameters: + - description: MFA challenge and authenticator token + in: body + name: request + required: true + schema: + $ref: '#/definitions/api.mfaVerifyRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.loginResponse' + summary: Verify MFA login + tags: + - auth + /v1/billing-details: + get: + consumes: + - application/json + description: Get the billing details for the authenticated account + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/structs.BillingDetails' + "404": + description: Not Found + schema: + type: string + "500": + description: Internal Server Error + schema: + type: string + security: + - BearerAuth: [] + summary: Get billing details + tags: + - billing + put: + consumes: + - application/json + description: Update the billing details for the authenticated account + parameters: + - description: Billing details + in: body + name: billingDetails + required: true + schema: + $ref: '#/definitions/structs.BillingDetails' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/structs.BillingDetails' + "400": + description: Bad Request + schema: + type: string + "404": + description: Not Found + schema: + type: string + "412": + description: Precondition Failed + schema: + type: string + "500": + description: Internal Server Error + schema: + type: string + security: + - BearerAuth: [] + summary: Update billing details + tags: + - billing + /v1/buckets: + get: + consumes: + - application/json + description: Get list of all buckets for the authenticated account + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/structs.Bucket' + type: array + security: + - BearerAuth: [] + summary: List account buckets + tags: + - buckets + post: + consumes: + - application/json + description: Create a new webhook bucket for the authenticated account + parameters: + - description: Bucket configuration + in: body + name: bucket + required: true + schema: + $ref: '#/definitions/structs.Bucket' + produces: + - application/json + responses: + "201": + description: Created + schema: + $ref: '#/definitions/structs.Bucket' + "400": + description: Bad Request + schema: + type: string + "412": + description: Precondition Failed + schema: + type: string + security: + - BearerAuth: [] + summary: Create a new bucket + tags: + - buckets + /v1/buckets/{id}: + delete: + consumes: + - application/json + description: Delete a bucket by ID. Bucket must not have any inputs or outputs + unless force parameter is used + parameters: + - description: Bucket ID + in: path + name: id + required: true + type: string + - description: Force delete even if bucket has inputs or outputs + in: query + name: force + type: boolean + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.Response' + "403": + description: Forbidden + schema: + type: string + "404": + description: Not Found + schema: + type: string + "412": + description: Precondition Failed + schema: + type: string + security: + - BearerAuth: [] + summary: Delete bucket + tags: + - buckets + get: + consumes: + - application/json + description: Get details of a specific bucket by ID + parameters: + - description: Bucket ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/structs.Bucket' + "403": + description: Forbidden + schema: + type: string + "404": + description: Not Found + schema: + type: string + security: + - BearerAuth: [] + summary: Get bucket details + tags: + - buckets + put: + consumes: + - application/json + description: Update an existing bucket configuration + parameters: + - description: Bucket ID + in: path + name: id + required: true + type: string + - description: Updated bucket configuration + in: body + name: bucket + required: true + schema: + $ref: '#/definitions/structs.Bucket' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/structs.Bucket' + "400": + description: Bad Request + schema: + type: string + "404": + description: Not Found + schema: + type: string + "412": + description: Precondition Failed + schema: + type: string + security: + - BearerAuth: [] + summary: Update bucket + tags: + - buckets + /v1/buckets/{id}/inputs: + post: + consumes: + - application/json + description: Create a new input endpoint for a bucket + parameters: + - description: Bucket ID + in: path + name: id + required: true + type: string + - description: Input configuration + in: body + name: input + required: true + schema: + $ref: '#/definitions/structs.Input' + produces: + - application/json + responses: + "201": + description: Created + schema: + $ref: '#/definitions/structs.Input' + "400": + description: Bad Request + schema: + type: string + "412": + description: Precondition Failed + schema: + type: string + security: + - BearerAuth: [] + summary: Create input + tags: + - inputs + /v1/buckets/{id}/inputs/{detailed}: + delete: + consumes: + - application/json + description: Delete an input endpoint by ID + parameters: + - description: Bucket ID + in: path + name: id + required: true + type: string + - description: Input ID + in: path + name: detailed + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.Response' + "400": + description: Bad Request + schema: + type: string + "404": + description: Not Found + schema: + type: string + security: + - BearerAuth: [] + summary: Delete input + tags: + - inputs + put: + consumes: + - application/json + description: Update an existing input endpoint configuration + parameters: + - description: Bucket ID + in: path + name: id + required: true + type: string + - description: Input ID + in: path + name: detailed + required: true + type: string + - description: Updated input configuration + in: body + name: input + required: true + schema: + $ref: '#/definitions/structs.Input' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/structs.Input' + "400": + description: Bad Request + schema: + type: string + "404": + description: Not Found + schema: + type: string + "412": + description: Precondition Failed + schema: + type: string + security: + - BearerAuth: [] + summary: Update input + tags: + - inputs + /v1/buckets/{id}/logs/{logId}: + get: + consumes: + - application/json + description: Get detailed information about a specific webhook log from one + bucket + parameters: + - description: Bucket ID + in: path + name: id + required: true + type: string + - description: Log ID + in: path + name: logId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/structs.Log' + "404": + description: Not Found + schema: + type: string + security: + - BearerAuth: [] + summary: Get bucket-scoped log details from warehouse + tags: + - logs + /v1/buckets/{id}/outputs: + post: + consumes: + - application/json + description: Create a new output destination for a bucket + parameters: + - description: Bucket ID + in: path + name: id + required: true + type: string + - description: Output configuration + in: body + name: output + required: true + schema: + $ref: '#/definitions/structs.Output' + produces: + - application/json + responses: + "201": + description: Created + schema: + $ref: '#/definitions/structs.Output' + "400": + description: Bad Request + schema: + type: string + "402": + description: Payment Required + schema: + type: string + "404": + description: Not Found + schema: + type: string + "412": + description: Precondition Failed + schema: + type: string + security: + - BearerAuth: [] + summary: Create output + tags: + - outputs + /v1/buckets/{id}/outputs/{detailed}: + delete: + consumes: + - application/json + description: Delete an output destination by ID + parameters: + - description: Bucket ID + in: path + name: id + required: true + type: string + - description: Output ID + in: path + name: detailed + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.Response' + "400": + description: Bad Request + schema: + type: string + "404": + description: Not Found + schema: + type: string + security: + - BearerAuth: [] + summary: Delete output + tags: + - outputs + put: + consumes: + - application/json + description: Update an existing output destination configuration + parameters: + - description: Bucket ID + in: path + name: id + required: true + type: string + - description: Output ID + in: path + name: detailed + required: true + type: string + - description: Updated output configuration + in: body + name: output + required: true + schema: + $ref: '#/definitions/structs.Output' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/structs.Output' + "400": + description: Bad Request + schema: + type: string + "404": + description: Not Found + schema: + type: string + "412": + description: Precondition Failed + schema: + type: string + security: + - BearerAuth: [] + summary: Update output + tags: + - outputs + /v1/buckets/{id}/outputs/{detailed}/rules: + delete: + description: Delete filtering rules from an output destination + parameters: + - description: Bucket ID + in: path + name: id + required: true + type: string + - description: Output ID + in: path + name: detailed + required: true + type: string + responses: + "200": + description: OK + schema: + $ref: '#/definitions/structs.Output' + "400": + description: Bad Request + schema: + type: string + "404": + description: Not Found + schema: + type: string + security: + - BearerAuth: [] + summary: Delete output rules + tags: + - outputs + put: + description: Update filtering rules for an output destination + parameters: + - description: Bucket ID + in: path + name: id + required: true + type: string + - description: Output ID + in: path + name: detailed + required: true + type: string + - description: Output rules configuration + in: body + name: rules + required: true + schema: + type: object + responses: + "200": + description: OK + schema: + $ref: '#/definitions/structs.Output' + "400": + description: Bad Request + schema: + type: string + "404": + description: Not Found + schema: + type: string + security: + - BearerAuth: [] + summary: Update output rules + tags: + - outputs + /v1/buckets/{id}/service-connection-inputs: + get: + consumes: + - application/json + description: Get all service connection inputs for a specific bucket + parameters: + - description: Bucket ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/structs.ServiceConnectionInput' + type: array + "404": + description: Not Found + schema: + type: string + security: + - BearerAuth: [] + summary: List service connection inputs for a bucket + tags: + - service-connection-inputs + post: + consumes: + - application/json + description: Create a new service connection input for a bucket + parameters: + - description: Bucket ID + in: path + name: id + required: true + type: string + - description: Service connection input configuration + in: body + name: input + required: true + schema: + $ref: '#/definitions/structs.ServiceConnectionInput' + produces: + - application/json + responses: + "201": + description: Created + schema: + $ref: '#/definitions/structs.ServiceConnectionInput' + "400": + description: Bad Request + schema: + type: string + "404": + description: Not Found + schema: + type: string + security: + - BearerAuth: [] + summary: Create service connection input + tags: + - service-connection-inputs + /v1/buckets/{id}/service-connection-inputs/{detailed}: + delete: + consumes: + - application/json + description: Delete a service connection input by ID + parameters: + - description: Bucket ID + in: path + name: id + required: true + type: string + - description: Service Connection Input ID + in: path + name: detailed + required: true + type: string + produces: + - application/json + responses: + "204": + description: No Content + schema: + type: string + "404": + description: Not Found + schema: + type: string + security: + - BearerAuth: [] + summary: Delete service connection input + tags: + - service-connection-inputs + put: + consumes: + - application/json + description: Update a service connection input by ID + parameters: + - description: Bucket ID + in: path + name: id + required: true + type: string + - description: Service Connection Input ID + in: path + name: detailed + required: true + type: string + - description: Service connection input configuration + in: body + name: input + required: true + schema: + $ref: '#/definitions/structs.ServiceConnectionInput' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/structs.ServiceConnectionInput' + "400": + description: Bad Request + schema: + type: string + "404": + description: Not Found + schema: + type: string + security: + - BearerAuth: [] + summary: Update service connection input + tags: + - service-connection-inputs + /v1/buckets/{id}/service-connection-outputs: + get: + consumes: + - application/json + description: Get all service connection outputs for a specific bucket + parameters: + - description: Bucket ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/structs.ServiceConnectionOutput' + type: array + "404": + description: Not Found + schema: + type: string + security: + - BearerAuth: [] + summary: List service connection outputs for a bucket + tags: + - service-connection-outputs + post: + consumes: + - application/json + description: Create a new service connection output for a bucket + parameters: + - description: Bucket ID + in: path + name: id + required: true + type: string + - description: Service connection output configuration + in: body + name: output + required: true + schema: + $ref: '#/definitions/structs.ServiceConnectionOutput' + produces: + - application/json + responses: + "201": + description: Created + schema: + $ref: '#/definitions/structs.ServiceConnectionOutput' + "400": + description: Bad Request + schema: + type: string + "404": + description: Not Found + schema: + type: string + security: + - BearerAuth: [] + summary: Create service connection output + tags: + - service-connection-outputs + /v1/buckets/{id}/service-connection-outputs/{detailed}: + delete: + consumes: + - application/json + description: Delete a service connection output by ID + parameters: + - description: Bucket ID + in: path + name: id + required: true + type: string + - description: Service Connection Output ID + in: path + name: detailed + required: true + type: string + produces: + - application/json + responses: + "204": + description: No Content + schema: + type: string + "404": + description: Not Found + schema: + type: string + security: + - BearerAuth: [] + summary: Delete service connection output + tags: + - service-connection-outputs + put: + consumes: + - application/json + description: Update a service connection output by ID + parameters: + - description: Bucket ID + in: path + name: id + required: true + type: string + - description: Service Connection Output ID + in: path + name: detailed + required: true + type: string + - description: Service connection output configuration + in: body + name: output + required: true + schema: + $ref: '#/definitions/structs.ServiceConnectionOutput' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/structs.ServiceConnectionOutput' + "400": + description: Bad Request + schema: + type: string + "404": + description: Not Found + schema: + type: string + security: + - BearerAuth: [] + summary: Update service connection output + tags: + - service-connection-outputs + /v1/checkout: + post: + consumes: + - application/json + description: Initiates stripe checkout session, new subscription will be created + parameters: + - description: Plan request + in: body + name: planReq + required: true + schema: + $ref: '#/definitions/api.planChangeRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.planChangeResponse' + "400": + description: Bad Request + schema: + type: string + "404": + description: Not Found + schema: + type: string + "412": + description: Precondition Failed + schema: + type: string + "500": + description: Internal Server Error + schema: + type: string + security: + - BearerAuth: [] + summary: Initiates stripe checkout session, new subscription will be created + tags: + - billing + /v1/checkout-setup: + post: + consumes: + - application/json + description: Start a checkout session setup for the authenticated account + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.planChangeResponse' + "500": + description: Internal Server Error + schema: + type: string + security: + - BearerAuth: [] + summary: Start checkout session setup + tags: + - billing + /v1/config: + get: + consumes: + - application/json + description: Get the server config + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.ServerConfig' + security: + - BearerAuth: [] + summary: Get server config + tags: + - config + /v1/connected-clients: + get: + consumes: + - application/json + description: Get list of all connected clients for the authenticated account + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/structs.ConnectedClient' + "400": + description: Bad Request + schema: + type: string + security: + - BearerAuth: [] + summary: Get connected clients + tags: + - connected-clients + /v1/crons: + get: + consumes: + - application/json + description: Get list of all cron jobs for the authenticated account + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/structs.Cron' + type: array + security: + - BearerAuth: [] + summary: List cron jobs + tags: + - crons + post: + consumes: + - application/json + description: Create a new scheduled cron job + parameters: + - description: Cron job configuration + in: body + name: cron + required: true + schema: + $ref: '#/definitions/structs.Cron' + produces: + - application/json + responses: + "201": + description: Created + schema: + $ref: '#/definitions/structs.Cron' + "400": + description: Bad Request + schema: + type: string + security: + - BearerAuth: [] + summary: Create cron job + tags: + - crons + /v1/crons/{id}: + delete: + consumes: + - application/json + description: Delete a cron job by ID + parameters: + - description: Cron ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "204": + description: No Content + schema: + type: string + "404": + description: Not Found + schema: + type: string + security: + - BearerAuth: [] + summary: Delete cron job + tags: + - crons + get: + consumes: + - application/json + description: Get details of a specific cron job by ID + parameters: + - description: Cron ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/structs.Cron' + "404": + description: Not Found + schema: + type: string + security: + - BearerAuth: [] + summary: Get cron job + tags: + - crons + put: + consumes: + - application/json + description: Update an existing cron job configuration + parameters: + - description: Cron ID + in: path + name: id + required: true + type: string + - description: Updated cron job configuration + in: body + name: cron + required: true + schema: + $ref: '#/definitions/structs.Cron' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/structs.Cron' + "400": + description: Bad Request + schema: + type: string + "404": + description: Not Found + schema: + type: string + security: + - BearerAuth: [] + summary: Update cron job + tags: + - crons + /v1/domains: + get: + consumes: + - application/json + description: Get list of all domains for the authenticated account + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/structs.Domain' + type: array + security: + - BearerAuth: [] + summary: List account domains + tags: + - domains + post: + consumes: + - application/json + description: Reserve a domain for the authenticated account. Domain must be + valid and not already taken. + parameters: + - description: Domain configuration + in: body + name: domain + required: true + schema: + $ref: '#/definitions/structs.Domain' + produces: + - application/json + responses: + "201": + description: Created + schema: + $ref: '#/definitions/structs.Domain' + "400": + description: Bad Request + schema: + type: string + "412": + description: Precondition Failed + schema: + type: string + "451": + description: Unavailable For Legal Reasons + schema: + type: string + security: + - BearerAuth: [] + summary: Create domain reservation + tags: + - domains + /v1/domains/{id}: + delete: + consumes: + - application/json + description: Delete a reserved domain by ID. Domain must not be in use by any + inputs or tunnels. + parameters: + - description: Domain ID + in: path + name: id + required: true + type: string produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/structs.AccountAPIKey' - "401": - description: Unauthorized + $ref: '#/definitions/api.Response' + "404": + description: Not Found schema: type: string - "500": - description: Internal server error + "412": + description: Precondition Failed schema: type: string security: - BearerAuth: [] - summary: Get account API key + summary: Delete domain reservation tags: - - account + - domains + /v1/email-inbound: post: consumes: - - application/json - description: Generate a new API key for the account, replacing the existing - one. + - message/rfc822 + description: Server-to-server endpoint the Cloudflare Email Worker posts raw + RFC822 to. This handler resolves the recipient to an email-type service connection + input, parses the message (pkg/email), enforces per-input policy (sender allowlist, + attachment drop/cap), and pushes the resulting email.Message through the normal + relay pipeline. Authenticated with the X-WHR-Secret shared secret, not a user + token. + parameters: + - description: Shared secret + in: header + name: X-WHR-Secret + required: true + type: string + - description: Full recipient address ({local-part}@) + in: header + name: X-WHR-Recipient + required: true + type: string produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/structs.AccountAPIKey' + type: string "401": description: Unauthorized schema: type: string - "500": - description: Internal server error + "404": + description: Unknown recipient schema: type: string - security: - - BearerAuth: [] - summary: Regenerate account API key + summary: Inbound email ingest (internal) tags: - - account - put: + - email + /v1/events: + get: consumes: - application/json - description: Enable or disable the account API key without regenerating it. + description: 'Pull-based delivery: returns the oldest unsent webhooks for the + bucket and marks them delivered (RECEIVED → SENT), so each poll returns the + next batch and drains to an empty page. Report a different outcome with PUT + /v1/logs/{id}.' parameters: - - description: API key status - in: body - name: request + - description: Bucket ID or account-unique name + in: query + name: bucket required: true - schema: - $ref: '#/definitions/structs.UpdateAPIKeyStatusRequest' + type: string + - description: Output ID filter + in: query + name: output + type: string + - description: Page size (default 1, max 100) + in: query + name: limit + type: integer + - description: How far back to look for unsent webhooks (default 24h, Go duration + syntax) + in: query + name: max_age + type: string produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/structs.UpdateAPIKeyStatusResponse' + $ref: '#/definitions/api.eventResponse' "400": - description: Bad request + description: Bad Request schema: type: string - "401": - description: Unauthorized + "404": + description: bucket not found schema: type: string - "500": - description: Internal server error + "503": + description: turbostore v2 is not enabled schema: type: string security: - BearerAuth: [] - summary: Enable or disable account API key + summary: Consume webhook events (pull-delivery queue) tags: - - account - /v1/account/mfa: - delete: - consumes: - - application/json - description: Disable MFA after validating a current authenticator token. + - logs + /v1/exec-logs/{id}: + get: + description: |- + Look up a function execution log by its id without + requiring the function id in the URL. Useful for the + webhook-log-detail UI, where the log only knows the + ExecuteLog id (not which function emitted it). The + executing function id is embedded on the row. parameters: - - description: Authenticator token - in: body - name: request + - description: Execution Log ID + in: path + name: id required: true - schema: - $ref: '#/definitions/api.mfaConfirmRequest' + type: string + - description: Execution creation time (unix seconds/ms/us). Optional day hint + that turns the lookup into a single index read; omit it and the log still + resolves, just less cheaply. + in: query + name: created_at + type: integer produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/api.mfaStatusResponse' + $ref: '#/definitions/structs.ExecuteLog' + "404": + description: Not Found + schema: + type: string security: - BearerAuth: [] - summary: Disable MFA + summary: Get a function execution log by id (account-scoped) tags: - - account - /v1/account/mfa/confirm: - post: - consumes: - - application/json - description: Enable MFA after validating a token from the pending TOTP secret. + - functions + /v1/function-reference: + get: parameters: - - description: Authenticator token - in: body - name: request + - description: Runtime + enum: + - js + - lua + in: query + name: driver required: true - schema: - $ref: '#/definitions/api.mfaConfirmRequest' + type: string + - description: Module from the runtime catalog, or core + in: query + name: module + required: true + type: string + - description: Curated helper method + in: query + name: method + type: string produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/api.mfaStatusResponse' + $ref: '#/definitions/functiondocs.Reference' + "400": + description: Unknown runtime, module or method + schema: + type: string security: - BearerAuth: [] - summary: Confirm MFA setup + summary: Read the deployed Function API reference and executable examples tags: - - account - /v1/account/mfa/setup: - post: - consumes: - - application/json - description: Generate a TOTP secret and QR code for the authenticated account - or sub-account. + - functions + /v1/function-runtime: + get: + parameters: + - description: Runtime + enum: + - js + - lua + in: query + name: driver + required: true + type: string produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/api.mfaSetupResponse' + $ref: '#/definitions/functiondocs.Runtime' + "400": + description: Unknown runtime + schema: + type: string security: - BearerAuth: [] - summary: Start MFA setup + summary: Read the deployed Function runtime capabilities tags: - - account - /v1/admin/connected-clients: + - functions + /v1/functions: get: consumes: - application/json - description: Get list of all connected clients across all accounts from the - state tracker service. + description: List the functions for the authenticated account produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/structs.AdminConnectedClientsResponse' - "500": - description: Internal Server Error + items: + $ref: '#/definitions/structs.Function' + type: array + "400": + description: Bad Request schema: type: string - "503": - description: Service Unavailable + "500": + description: Internal Server Error schema: type: string security: - BearerAuth: [] - summary: Get all connected clients (admin) + summary: List functions tags: - - admin - /v1/auth/mfa/verify: + - functions post: consumes: - application/json - description: Exchange an MFA challenge token and authenticator code for a session - token. + description: Create a new function parameters: - - description: MFA challenge and authenticator token + - description: Function configuration in: body - name: request + name: functionPayload required: true schema: - $ref: '#/definitions/api.mfaVerifyRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/api.loginResponse' - summary: Verify MFA login - tags: - - auth - /v1/billing-details: - get: - consumes: - - application/json - description: Get the billing details for the authenticated account + $ref: '#/definitions/structs.CreateFunctionRequest' produces: - application/json responses: - "200": - description: OK + "201": + description: Created schema: - $ref: '#/definitions/structs.BillingDetails' - "404": - description: Not Found + $ref: '#/definitions/structs.Function' + "400": + description: Bad Request schema: type: string "500": @@ -2351,144 +8835,146 @@ paths: type: string security: - BearerAuth: [] - summary: Get billing details + summary: Create function tags: - - billing - put: + - functions + /v1/functions-generate: + post: consumes: - application/json - description: Update the billing details for the authenticated account + description: Generate a new function based on the provided input and output + payloads parameters: - - description: Billing details + - description: Function generation request in: body - name: billingDetails + name: generateRequest required: true schema: - $ref: '#/definitions/structs.BillingDetails' + $ref: '#/definitions/structs.GenerateFunctionRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/structs.BillingDetails' + $ref: '#/definitions/structs.GenerateFunctionResponse' "400": description: Bad Request schema: type: string - "404": - description: Not Found - schema: - type: string - "412": - description: Precondition Failed - schema: - type: string "500": description: Internal Server Error schema: type: string security: - BearerAuth: [] - summary: Update billing details + summary: Generate function tags: - - billing - /v1/buckets: - get: + - functions + /v1/functions/{id}: + delete: consumes: - application/json - description: Get list of all buckets for the authenticated account + description: Delete a function by its ID + parameters: + - description: Function ID + in: path + name: id + required: true + type: string produces: - application/json responses: "200": description: OK schema: - items: - $ref: '#/definitions/structs.Bucket' - type: array + $ref: '#/definitions/structs.DeleteFunctionResponse' + "400": + description: Bad Request + schema: + type: string + "500": + description: Internal Server Error + schema: + type: string security: - BearerAuth: [] - summary: List account buckets + summary: Delete function tags: - - buckets - post: + - functions + get: consumes: - application/json - description: Create a new webhook bucket for the authenticated account + description: Get a function by its ID parameters: - - description: Bucket configuration - in: body - name: bucket + - description: Function ID + in: path + name: id required: true - schema: - $ref: '#/definitions/structs.Bucket' + type: string produces: - application/json responses: - "201": - description: Created + "200": + description: OK schema: - $ref: '#/definitions/structs.Bucket' + $ref: '#/definitions/structs.Function' "400": description: Bad Request schema: type: string - "412": - description: Precondition Failed + "500": + description: Internal Server Error schema: type: string security: - BearerAuth: [] - summary: Create a new bucket + summary: Get function tags: - - buckets - /v1/buckets/{id}: - delete: + - functions + put: consumes: - application/json - description: Delete a bucket by ID. Bucket must not have any inputs or outputs - unless force parameter is used + description: Update an existing function parameters: - - description: Bucket ID + - description: Function ID in: path name: id required: true type: string - - description: Force delete even if bucket has inputs or outputs - in: query - name: force - type: boolean + - description: Function configuration + in: body + name: functionPayload + required: true + schema: + $ref: '#/definitions/structs.UpdateFunctionRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/api.Response' - "403": - description: Forbidden - schema: - type: string - "404": - description: Not Found + $ref: '#/definitions/structs.Function' + "400": + description: Bad Request schema: type: string - "412": - description: Precondition Failed + "500": + description: Internal Server Error schema: type: string security: - BearerAuth: [] - summary: Delete bucket + summary: Update function tags: - - buckets + - functions + /v1/functions/{id}/config: get: consumes: - application/json - description: Get details of a specific bucket by ID + description: List the configuration values for a given function parameters: - - description: Bucket ID + - description: Function ID in: path name: id required: true @@ -2499,417 +8985,465 @@ paths: "200": description: OK schema: - $ref: '#/definitions/structs.Bucket' - "403": - description: Forbidden + items: + $ref: '#/definitions/structs.Variable' + type: array + "400": + description: Bad Request schema: type: string - "404": - description: Not Found + "500": + description: Internal Server Error schema: type: string security: - BearerAuth: [] - summary: Get bucket details + summary: List function config tags: - - buckets + - functions put: consumes: - application/json - description: Update an existing bucket configuration + description: Set the configuration value for a given function parameters: - - description: Bucket ID + - description: Function ID in: path name: id required: true type: string - - description: Updated bucket configuration + - description: Configuration value in: body - name: bucket + name: config required: true schema: - $ref: '#/definitions/structs.Bucket' + $ref: '#/definitions/api.setFunctionConfigRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/structs.Bucket' + $ref: '#/definitions/structs.Variable' "400": description: Bad Request schema: type: string - "404": - description: Not Found - schema: - type: string - "412": - description: Precondition Failed + "500": + description: Internal Server Error schema: type: string security: - BearerAuth: [] - summary: Update bucket + summary: Set function config tags: - - buckets - /v1/buckets/{id}/inputs: - post: + - functions + /v1/functions/{id}/config/{key}: + delete: consumes: - application/json - description: Create a new input endpoint for a bucket + description: Delete the configuration value for a given function parameters: - - description: Bucket ID + - description: Function ID in: path name: id required: true type: string - - description: Input configuration - in: body - name: input + - description: Configuration key + in: path + name: key required: true - schema: - $ref: '#/definitions/structs.Input' + type: string produces: - application/json responses: - "201": - description: Created + "200": + description: OK schema: - $ref: '#/definitions/structs.Input' + $ref: '#/definitions/structs.DeleteVariableResponse' "400": description: Bad Request schema: type: string - "412": - description: Precondition Failed + "500": + description: Internal Server Error schema: type: string security: - BearerAuth: [] - summary: Create input + summary: Delete function config value tags: - - inputs - /v1/buckets/{id}/inputs/{detailed}: - delete: - consumes: - - application/json - description: Delete an input endpoint by ID + - functions + /v1/functions/{id}/connections: + get: parameters: - - description: Bucket ID + - description: Function ID in: path name: id required: true type: string - - description: Input ID - in: path - name: detailed - required: true - type: string produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/api.Response' - "400": - description: Bad Request - schema: - type: string - "404": - description: Not Found - schema: - type: string + items: + $ref: '#/definitions/structs.FunctionConnectionRequirement' + type: array security: - BearerAuth: [] - summary: Delete input + summary: List Function connection requirements tags: - - inputs + - functions + /v1/functions/{id}/connections/{alias}: + delete: + parameters: + - description: Function ID + in: path + name: id + required: true + type: string + - description: Connection import alias + in: path + name: alias + required: true + type: string + responses: + "204": + description: No Content + security: + - BearerAuth: [] + summary: Unbind a Function service connection import + tags: + - functions put: consumes: - application/json - description: Update an existing input endpoint configuration parameters: - - description: Bucket ID + - description: Function ID in: path name: id required: true type: string - - description: Input ID + - description: Connection import alias in: path - name: detailed + name: alias required: true type: string - - description: Updated input configuration + - description: Connection binding in: body - name: input + name: binding required: true schema: - $ref: '#/definitions/structs.Input' + $ref: '#/definitions/api.bindFunctionConnectionRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/structs.FunctionConnectionRequirement' + security: + - BearerAuth: [] + summary: Bind a Function service connection import + tags: + - functions + /v1/functions/{id}/invoke: + post: + consumes: + - application/json + description: Invoke a function by its ID + parameters: + - description: Function ID + in: path + name: id + required: true + type: string produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/structs.Input' + $ref: '#/definitions/structs.ExecuteResponse' "400": description: Bad Request schema: type: string - "404": - description: Not Found - schema: - type: string - "412": - description: Precondition Failed + "500": + description: Internal Server Error schema: type: string security: - BearerAuth: [] - summary: Update input + summary: Invoke function tags: - - inputs - /v1/buckets/{id}/logs/{logId}: + - functions + /v1/functions/{id}/logs: get: consumes: - application/json - description: Get detailed information about a specific webhook log from one - bucket + description: Get the logs for a function parameters: - - description: Bucket ID + - description: Function ID in: path name: id required: true type: string - - description: Log ID - in: path - name: logId - required: true - type: string produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/structs.Log' - "404": - description: Not Found + $ref: '#/definitions/structs.ExecuteLogResponse' + "400": + description: Bad Request + schema: + type: string + "500": + description: Internal Server Error schema: type: string security: - BearerAuth: [] - summary: Get bucket-scoped log details from warehouse + summary: Get function logs tags: - - logs - /v1/buckets/{id}/outputs: - post: + - functions + /v1/functions/{id}/logs/{logId}: + get: consumes: - application/json - description: Create a new output destination for a bucket + description: Get the logs for a function parameters: - - description: Bucket ID + - description: Function ID in: path name: id required: true type: string - - description: Output configuration - in: body - name: output - required: true - schema: - $ref: '#/definitions/structs.Output' produces: - application/json responses: - "201": - description: Created + "200": + description: OK schema: - $ref: '#/definitions/structs.Output' + $ref: '#/definitions/structs.ExecuteLogResponse' "400": description: Bad Request schema: type: string - "402": - description: Payment Required - schema: - type: string - "404": - description: Not Found - schema: - type: string - "412": - description: Precondition Failed + "500": + description: Internal Server Error schema: type: string security: - BearerAuth: [] - summary: Create output + summary: Get function logs tags: - - outputs - /v1/buckets/{id}/outputs/{detailed}: - delete: - consumes: - - application/json - description: Delete an output destination by ID + - functions + /v1/functions/{id}/versions: + get: + description: Revision history of a function, newest first, without code. A revision + is recorded on create, on every code change, and on restore. parameters: - - description: Bucket ID + - description: Function ID in: path name: id required: true type: string - - description: Output ID - in: path - name: detailed - required: true - type: string produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/api.Response' - "400": - description: Bad Request - schema: - type: string + items: + $ref: '#/definitions/structs.FunctionVersion' + type: array "404": description: Not Found schema: type: string security: - BearerAuth: [] - summary: Delete output + summary: List function versions tags: - - outputs - put: - consumes: - - application/json - description: Update an existing output destination configuration + - functions + /v1/functions/{id}/versions/{version}: + get: + description: One revision of a function including its code parameters: - - description: Bucket ID + - description: Function ID in: path name: id required: true type: string - - description: Output ID + - description: Version number in: path - name: detailed - required: true - type: string - - description: Updated output configuration - in: body - name: output + name: version required: true - schema: - $ref: '#/definitions/structs.Output' + type: integer produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/structs.Output' - "400": - description: Bad Request - schema: - type: string + $ref: '#/definitions/structs.FunctionVersion' "404": description: Not Found schema: type: string - "412": - description: Precondition Failed - schema: - type: string security: - BearerAuth: [] - summary: Update output + summary: Get function version tags: - - outputs - /v1/buckets/{id}/outputs/{detailed}/rules: - delete: - description: Delete filtering rules from an output destination + - functions + /v1/functions/{id}/versions/{version}/restore: + post: + description: Makes an earlier revision the current code. The restore is itself + recorded as the newest revision, so history is never lost. parameters: - - description: Bucket ID + - description: Function ID in: path name: id required: true type: string - - description: Output ID + - description: Version number to restore in: path - name: detailed + name: version required: true - type: string + type: integer + produces: + - application/json responses: "200": description: OK schema: - $ref: '#/definitions/structs.Output' - "400": - description: Bad Request - schema: - type: string + $ref: '#/definitions/structs.Function' "404": description: Not Found schema: type: string security: - BearerAuth: [] - summary: Delete output rules + summary: Restore function version tags: - - outputs - put: - description: Update filtering rules for an output destination + - functions + /v1/incidents/stats: + get: + consumes: + - application/json + description: Returns a dense per-UTC-day series of incidents that started in + the inclusive [from, to] window, including count and resolved-incident duration + totals for charting. parameters: - - description: Bucket ID - in: path - name: id - required: true + - description: From date (YYYY-MM-DD), defaults to 30 days ago + in: query + name: from type: string - - description: Output ID - in: path - name: detailed - required: true + - description: To date (YYYY-MM-DD), defaults to today + in: query + name: to type: string - - description: Output rules configuration - in: body - name: rules - required: true - schema: - type: object + - description: Filter by status (open|resolved) + in: query + name: status + type: string + - description: Filter by bucket ID + in: query + name: bucket_id + type: string + - description: Filter by output ID + in: query + name: output_id + type: string + - description: Filter by integration configuration ID + in: query + name: integration_id + type: string + produces: + - application/json responses: "200": description: OK schema: - $ref: '#/definitions/structs.Output' - "400": - description: Bad Request - schema: - type: string - "404": - description: Not Found - schema: - type: string + items: + $ref: '#/definitions/structs.IncidentDayStats' + type: array security: - BearerAuth: [] - summary: Update output rules + summary: Get incident statistics by day tags: - - outputs - /v1/buckets/{id}/service-connection-inputs: + - incidents + /v1/logs: get: consumes: - application/json - description: Get all service connection inputs for a specific bucket + description: Get paginated list of webhook logs from warehouse for the authenticated + account parameters: - - description: Bucket ID - in: path - name: id + - description: Filter by bucket ID + in: query + name: bucket required: true type: string + - description: Number of results per page + in: query + name: limit + type: integer + - description: Offset for pagination + in: query + name: offset + type: integer + - description: From date (YYYY-MM-DD or RFC3339) + in: query + name: from + type: string + - description: To date (YYYY-MM-DD or RFC3339) + in: query + name: to + type: string + - description: Filter by status (sent, failed, stalled, received, rejected) + in: query + name: status + type: string + - description: Opaque pagination cursor (turbostore accounts; takes precedence + over offset) + in: query + name: cursor + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.logsResponse' + security: + - BearerAuth: [] + summary: List webhook logs from warehouse (paginated) + tags: + - logs + /v1/logs-stats: + get: + consumes: + - application/json + description: Get daily account log counts, retry/latency aggregates, and Turbostore + request/response byte totals (recorded bodies plus HTTP headers) + parameters: + - description: From date (YYYY-MM-DD) + in: query + name: from + type: string + - description: To date (YYYY-MM-DD) + in: query + name: to + type: string + - description: Filter by bucket ID + in: query + name: bucketId + type: string produces: - application/json responses: @@ -2917,113 +9451,91 @@ paths: description: OK schema: items: - $ref: '#/definitions/structs.ServiceConnectionInput' + $ref: '#/definitions/structs.LogsStats' type: array - "404": - description: Not Found - schema: - type: string security: - BearerAuth: [] - summary: List service connection inputs for a bucket + summary: Get account log statistics tags: - - service-connection-inputs - post: + - logs + /v1/logs-stats/by-bucket: + get: consumes: - application/json - description: Create a new service connection input for a bucket + description: Per-bucket daily log statistics for the whole account. Returns + success/failure/retry/latency series plus Turbostore request/response byte + totals (recorded bodies plus HTTP headers) without fanning out one request + per bucket. parameters: - - description: Bucket ID - in: path - name: id - required: true + - description: From date (YYYY-MM-DD) + in: query + name: from + type: string + - description: To date (YYYY-MM-DD) + in: query + name: to type: string - - description: Service connection input configuration - in: body - name: input - required: true - schema: - $ref: '#/definitions/structs.ServiceConnectionInput' produces: - application/json responses: - "201": - description: Created - schema: - $ref: '#/definitions/structs.ServiceConnectionInput' - "400": - description: Bad Request - schema: - type: string - "404": - description: Not Found + "200": + description: OK schema: - type: string + items: + $ref: '#/definitions/structs.BucketLogsStats' + type: array security: - BearerAuth: [] - summary: Create service connection input + summary: Get per-bucket log statistics tags: - - service-connection-inputs - /v1/buckets/{id}/service-connection-inputs/{detailed}: - delete: + - logs + /v1/logs/{id}: + get: consumes: - application/json - description: Delete a service connection input by ID + description: Get detailed information about a specific webhook log from warehouse parameters: - - description: Bucket ID + - description: Log ID in: path name: id required: true type: string - - description: Service Connection Input ID - in: path - name: detailed - required: true - type: string produces: - application/json responses: - "204": - description: No Content + "200": + description: OK schema: - type: string + $ref: '#/definitions/structs.Log' "404": description: Not Found schema: type: string security: - BearerAuth: [] - summary: Delete service connection input + summary: Get log details from warehouse tags: - - service-connection-inputs + - logs put: - consumes: - - application/json - description: Update a service connection input by ID + description: Update a webhook log. Can be used to update status, response body, + headers and status code. Only modifiable within 2 minutes of receipt. parameters: - - description: Bucket ID + - description: Log ID in: path name: id required: true type: string - - description: Service Connection Input ID - in: path - name: detailed - required: true - type: string - - description: Service connection input configuration + - description: Updated log data in: body - name: input + name: log required: true schema: - $ref: '#/definitions/structs.ServiceConnectionInput' - produces: - - application/json + $ref: '#/definitions/structs.Log' responses: "200": description: OK schema: - $ref: '#/definitions/structs.ServiceConnectionInput' + type: string "400": description: Bad Request schema: @@ -3034,61 +9546,33 @@ paths: type: string security: - BearerAuth: [] - summary: Update service connection input - tags: - - service-connection-inputs - /v1/buckets/{id}/service-connection-outputs: - get: - consumes: - - application/json - description: Get all service connection outputs for a specific bucket - parameters: - - description: Bucket ID - in: path - name: id - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/structs.ServiceConnectionOutput' - type: array - "404": - description: Not Found - schema: - type: string - security: - - BearerAuth: [] - summary: List service connection outputs for a bucket + summary: Update log tags: - - service-connection-outputs + - logs + /v1/logs/{id}/action: post: consumes: - application/json - description: Create a new service connection output for a bucket + description: Perform an action on a webhook log from warehouse (e.g., resend) parameters: - - description: Bucket ID + - description: Log ID in: path name: id required: true type: string - - description: Service connection output configuration + - description: Action request in: body - name: output + name: action required: true schema: - $ref: '#/definitions/structs.ServiceConnectionOutput' + $ref: '#/definitions/api.actionLogRequest' produces: - application/json responses: - "201": - description: Created + "200": + description: OK schema: - $ref: '#/definitions/structs.ServiceConnectionOutput' + type: string "400": description: Bad Request schema: @@ -3099,186 +9583,215 @@ paths: type: string security: - BearerAuth: [] - summary: Create service connection output + summary: Perform action on log from warehouse tags: - - service-connection-outputs - /v1/buckets/{id}/service-connection-outputs/{detailed}: - delete: - consumes: - - application/json - description: Delete a service connection output by ID + - logs + /v1/logs/histogram: + get: + description: Returns 1-minute resolution counts split by status plus parameters: - - description: Bucket ID - in: path - name: id - required: true + - description: 'From timestamp (RFC3339 or YYYY-MM-DD); default: 1h ago' + in: query + name: from type: string - - description: Service Connection Output ID - in: path - name: detailed - required: true + - description: 'To timestamp (RFC3339 or YYYY-MM-DD); default: now' + in: query + name: to type: string + - description: Filter to a single bucket + in: query + name: bucket_id + type: string + - description: Filter to a single output + in: query + name: output_id + type: string + - description: Filter to a single status (sent, failed, stalled, received, rejected, + preparing) + in: query + name: status + type: string + - description: Filter to a single HTTP status code + in: query + name: status_code + type: integer produces: - application/json responses: - "204": - description: No Content - schema: - type: string - "404": - description: Not Found + "200": + description: OK schema: - type: string + $ref: '#/definitions/api.logsHistogramResponse' security: - BearerAuth: [] - summary: Delete service connection output + summary: Per-minute log histogram for the explorer timeline tags: - - service-connection-outputs - put: + - logs + /v1/managed-certs: + get: consumes: - application/json - description: Update a service connection output by ID - parameters: - - description: Bucket ID - in: path - name: id - required: true - type: string - - description: Service Connection Output ID - in: path - name: detailed - required: true - type: string - - description: Service connection output configuration - in: body - name: output - required: true - schema: - $ref: '#/definitions/structs.ServiceConnectionOutput' + description: Get list of all managed certificates for the authenticated account produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/structs.ServiceConnectionOutput' - "400": - description: Bad Request - schema: - type: string - "404": - description: Not Found - schema: - type: string + items: + type: object + type: array security: - BearerAuth: [] - summary: Update service connection output + summary: List managed certificates tags: - - service-connection-outputs - /v1/checkout: + - managed-certs post: consumes: - application/json - description: Initiates stripe checkout session, new subscription will be created + description: Create a new managed SSL certificate for a domain parameters: - - description: Plan request + - description: Managed certificate configuration in: body - name: planReq + name: cert required: true schema: - $ref: '#/definitions/api.planChangeRequest' + $ref: '#/definitions/api.createManagedCertRequest' produces: - application/json responses: - "200": - description: OK + "201": + description: Created schema: - $ref: '#/definitions/api.planChangeResponse' + $ref: '#/definitions/api.Response' "400": description: Bad Request schema: type: string - "404": - description: Not Found - schema: - type: string - "412": - description: Precondition Failed + "451": + description: Unavailable For Legal Reasons schema: type: string - "500": - description: Internal Server Error + security: + - BearerAuth: [] + summary: Create managed certificate + tags: + - managed-certs + /v1/managed-certs/{id}: + delete: + description: Delete a managed certificate by ID + parameters: + - description: Managed certificate ID + in: path + name: id + required: true + type: string + responses: + "200": + description: OK schema: - type: string + $ref: '#/definitions/api.Response' security: - BearerAuth: [] - summary: Initiates stripe checkout session, new subscription will be created + summary: Delete managed certificate tags: - - billing - /v1/checkout-setup: - post: + - managed-certs + /v1/news: + get: consumes: - application/json - description: Start a checkout session setup for the authenticated account + description: Get all news entries produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/api.planChangeResponse' + items: + $ref: '#/definitions/structs.NewsEntry' + type: array "500": description: Internal Server Error schema: type: string security: - BearerAuth: [] - summary: Start checkout session setup + summary: Get news entries tags: - - billing - /v1/config: - get: + - news + post: consumes: - application/json - description: Get the server config + description: Create a new news entry + parameters: + - description: News entry + in: body + name: newsEntry + required: true + schema: + $ref: '#/definitions/structs.NewsEntryCreateRequest' produces: - application/json responses: - "200": - description: OK + "201": + description: Created schema: - $ref: '#/definitions/api.ServerConfig' + $ref: '#/definitions/api.Response' + "400": + description: Bad Request + schema: + type: string + "500": + description: Internal Server Error + schema: + type: string security: - BearerAuth: [] - summary: Get server config + summary: Create news entry tags: - - config - /v1/connected-clients: - get: + - news + /v1/news/{id}: + delete: consumes: - application/json - description: Get list of all connected clients for the authenticated account + description: Delete a news entry by ID + parameters: + - description: News entry ID + in: path + name: id + required: true + type: string produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/structs.ConnectedClient' + $ref: '#/definitions/api.Response' "400": description: Bad Request schema: type: string + "500": + description: Internal Server Error + schema: + type: string security: - BearerAuth: [] - summary: Get connected clients + summary: Delete news entry tags: - - connected-clients - /v1/crons: + - news + /v1/org/invites: get: consumes: - application/json - description: Get list of all cron jobs for the authenticated account + description: List invitations for the effective organization account, pending + by default (?status=) + parameters: + - description: Invite status filter (pending/accepted/declined/revoked) + in: query + name: status + type: string produces: - application/json responses: @@ -3286,47 +9799,44 @@ paths: description: OK schema: items: - $ref: '#/definitions/structs.Cron' + $ref: '#/definitions/structs.OrganizationInvite' type: array security: - BearerAuth: [] - summary: List cron jobs + summary: List organization invitations tags: - - crons + - organizations post: consumes: - application/json - description: Create a new scheduled cron job + description: Create a pending invitation for an email address. Invited members + and sub-accounts share the plan's sub-account quota. parameters: - - description: Cron job configuration + - description: Invitation in: body - name: cron + name: invite required: true schema: - $ref: '#/definitions/structs.Cron' + $ref: '#/definitions/api.orgInviteCreateRequest' produces: - application/json responses: "201": description: Created schema: - $ref: '#/definitions/structs.Cron' - "400": - description: Bad Request - schema: - type: string + $ref: '#/definitions/structs.OrganizationInvite' security: - BearerAuth: [] - summary: Create cron job + summary: Invite an account into the organization tags: - - crons - /v1/crons/{id}: + - organizations + /v1/org/invites/{id}: delete: consumes: - application/json - description: Delete a cron job by ID + description: Revoke a pending invitation parameters: - - description: Cron ID + - description: Invitation ID in: path name: id required: true @@ -3334,25 +9844,40 @@ paths: produces: - application/json responses: - "204": - description: No Content - schema: - type: string - "404": - description: Not Found - schema: - type: string + "200": + description: OK security: - BearerAuth: [] - summary: Delete cron job + summary: Revoke organization invitation tags: - - crons + - organizations + /v1/org/members: get: consumes: - application/json - description: Get details of a specific cron job by ID + description: List members of the effective organization account, joined with + member identity + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/structs.OrganizationMemberDetails' + type: array + security: + - BearerAuth: [] + summary: List organization members + tags: + - organizations + /v1/org/members/{id}: + delete: + consumes: + - application/json + description: Remove a member from the effective organization account parameters: - - description: Cron ID + - description: Membership ID in: path name: id required: true @@ -3362,196 +9887,142 @@ paths: responses: "200": description: OK - schema: - $ref: '#/definitions/structs.Cron' - "404": - description: Not Found - schema: - type: string security: - BearerAuth: [] - summary: Get cron job + summary: Remove organization member tags: - - crons + - organizations put: consumes: - application/json - description: Update an existing cron job configuration + description: Change a member's role (admin/billing/member) parameters: - - description: Cron ID + - description: Membership ID in: path name: id required: true type: string - - description: Updated cron job configuration + - description: Role change in: body - name: cron + name: member required: true schema: - $ref: '#/definitions/structs.Cron' + $ref: '#/definitions/api.orgMemberUpdateRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/structs.Cron' - "400": - description: Bad Request - schema: - type: string - "404": - description: Not Found - schema: - type: string + $ref: '#/definitions/structs.OrganizationMember' security: - BearerAuth: [] - summary: Update cron job + summary: Update organization member role tags: - - crons - /v1/domains: + - organizations + /v1/org/sso: + delete: + description: Removes the SAML SSO connection for the effective organization. + responses: + "204": + description: No Content + security: + - BearerAuth: [] + summary: Delete organization SAML SSO configuration + tags: + - organizations get: - consumes: - - application/json - description: Get list of all domains for the authenticated account + description: Returns the SAML SSO connection for the effective organization + account, or null when none is configured. produces: - application/json responses: "200": description: OK schema: - items: - $ref: '#/definitions/structs.Domain' - type: array + $ref: '#/definitions/structs.SamlSsoOrg' security: - BearerAuth: [] - summary: List account domains + summary: Get organization SAML SSO configuration tags: - - domains + - organizations post: consumes: - application/json - description: Reserve a domain for the authenticated account. Domain must be - valid and not already taken. + description: Creates a SAML SSO connection for the effective organization. Requires + plan metadata saml_sso=true. Supports Okta and Microsoft Entra ID (Azure AD) + style federation metadata URLs. parameters: - - description: Domain configuration + - description: SAML SSO configuration in: body - name: domain + name: body required: true schema: - $ref: '#/definitions/structs.Domain' + $ref: '#/definitions/api.orgSamlSSORequest' produces: - application/json responses: "201": description: Created schema: - $ref: '#/definitions/structs.Domain' - "400": - description: Bad Request - schema: - type: string - "412": - description: Precondition Failed - schema: - type: string - "451": - description: Unavailable For Legal Reasons - schema: - type: string + $ref: '#/definitions/structs.SamlSsoOrg' security: - BearerAuth: [] - summary: Create domain reservation + summary: Create organization SAML SSO configuration tags: - - domains - /v1/domains/{id}: - delete: + - organizations + put: consumes: - application/json - description: Delete a reserved domain by ID. Domain must not be in use by any - inputs or tunnels. + description: Updates the SAML SSO connection for the effective organization. parameters: - - description: Domain ID - in: path - name: id + - description: SAML SSO configuration + in: body + name: body required: true - type: string + schema: + $ref: '#/definitions/api.orgSamlSSORequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/api.Response' - "404": - description: Not Found - schema: - type: string - "412": - description: Precondition Failed - schema: - type: string + $ref: '#/definitions/structs.SamlSsoOrg' security: - BearerAuth: [] - summary: Delete domain reservation + summary: Update organization SAML SSO configuration tags: - - domains - /v1/events: + - organizations + /v1/outbound/consumers: get: - consumes: - - application/json - description: Stream new webhook deliveries since the last poll. Cursor-bound - to the (account, bucket, output) tuple the first call established. - parameters: - - description: Bucket ID (required on first call; cursor carries it on subsequent - calls) - in: query - name: bucket - type: string - - description: Output ID filter - in: query - name: output - type: string - - description: Opaque resume cursor from a previous call - in: query - name: cursor - type: string - - description: Page size (default 100) - in: query - name: limit - type: integer - - description: Lookback window on the first call (default 24h, Go duration syntax) - in: query - name: max_age - type: string + description: 'Lists the producer''s customers that receive outbound webhooks. + Pilot: requires the outbound feature flag.' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/api.eventResponse' - "503": - description: turbostore v2 polling is not enabled + items: + $ref: '#/definitions/structs.OutboundConsumer' + type: array + "403": + description: Outbound webhooks are not enabled, or the caller lacks permission schema: - type: string + $ref: '#/definitions/api.outboundErrorResponse' security: - BearerAuth: [] - summary: Poll webhook events (cursor-mode) + summary: List outbound consumers tags: - - logs - /v1/exec-logs/{id}: + - outbound + /v1/outbound/consumers/{consumer}/endpoints: get: - description: |- - Look up a function execution log by its id without - requiring the function id in the URL. Useful for the - webhook-log-detail UI, where the log only knows the - ExecuteLog id (not which function emitted it). The - executing function id is embedded on the row. + description: Newest first. Signing secrets are not included. parameters: - - description: Execution Log ID + - description: Consumer ID in: path - name: id + name: consumer required: true type: string produces: @@ -3560,114 +10031,165 @@ paths: "200": description: OK schema: - $ref: '#/definitions/structs.ExecuteLog' + items: + $ref: '#/definitions/structs.OutboundEndpoint' + type: array + "403": + description: Forbidden + schema: + $ref: '#/definitions/api.outboundErrorResponse' "404": - description: Not Found + description: Consumer not found schema: - type: string + $ref: '#/definitions/api.outboundErrorResponse' security: - BearerAuth: [] - summary: Get a function execution log by id (account-scoped) + summary: List a consumer's outbound endpoints tags: - - functions - /v1/functions: - get: + - outbound + post: consumes: - application/json - description: List the functions for the authenticated account + description: Adds a destination to a consumer. The response includes the endpoint's + signing secret. + parameters: + - description: Consumer ID + in: path + name: consumer + required: true + type: string + - description: Endpoint configuration + in: body + name: endpoint + required: true + schema: + $ref: '#/definitions/structs.OutboundEndpoint' produces: - application/json responses: - "200": - description: OK + "201": + description: Created schema: - items: - $ref: '#/definitions/structs.Function' - type: array + $ref: '#/definitions/api.endpointWithSecret' "400": description: Bad Request schema: - type: string - "500": - description: Internal Server Error + $ref: '#/definitions/api.outboundErrorResponse' + "403": + description: Not permitted, or the endpoint limit is reached schema: - type: string + $ref: '#/definitions/api.outboundErrorResponse' + "404": + description: Consumer not found + schema: + $ref: '#/definitions/api.outboundErrorResponse' security: - BearerAuth: [] - summary: List functions + summary: Create an outbound endpoint tags: - - functions - post: - consumes: + - outbound + /v1/outbound/consumers/{id}: + delete: + description: Deletes the consumer and its endpoints. Delivery history is kept. + parameters: + - description: Consumer ID + in: path + name: id + required: true + type: string + produces: - application/json - description: Create a new function + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.deletedResponse' + "403": + description: Forbidden + schema: + $ref: '#/definitions/api.outboundErrorResponse' + "404": + description: Not Found + schema: + $ref: '#/definitions/api.outboundErrorResponse' + security: + - BearerAuth: [] + summary: Delete an outbound consumer + tags: + - outbound + get: parameters: - - description: Function configuration - in: body - name: functionPayload + - description: Consumer ID + in: path + name: id required: true - schema: - $ref: '#/definitions/structs.CreateFunctionRequest' + type: string produces: - application/json responses: - "201": - description: Created + "200": + description: OK schema: - $ref: '#/definitions/structs.Function' - "400": - description: Bad Request + $ref: '#/definitions/structs.OutboundConsumer' + "403": + description: Forbidden schema: - type: string - "500": - description: Internal Server Error + $ref: '#/definitions/api.outboundErrorResponse' + "404": + description: Not Found schema: - type: string + $ref: '#/definitions/api.outboundErrorResponse' security: - BearerAuth: [] - summary: Create function + summary: Get an outbound consumer tags: - - functions - /v1/functions-generate: - post: + - outbound + put: consumes: - application/json - description: Generate a new function based on the provided input and output - payloads + description: Consumer IDs are chosen by the producer. Only name and rate are + updated; a deleted consumer's ID cannot be reused. parameters: - - description: Function generation request + - description: Consumer ID + in: path + name: id + required: true + type: string + - description: Consumer in: body - name: generateRequest + name: consumer required: true schema: - $ref: '#/definitions/structs.GenerateFunctionRequest' + $ref: '#/definitions/structs.OutboundConsumer' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/structs.GenerateFunctionResponse' + $ref: '#/definitions/structs.OutboundConsumer' "400": description: Bad Request schema: - type: string - "500": - description: Internal Server Error + $ref: '#/definitions/api.outboundErrorResponse' + "403": + description: Not permitted, or the consumer limit is reached schema: - type: string + $ref: '#/definitions/api.outboundErrorResponse' + "409": + description: The consumer ID was deleted + schema: + $ref: '#/definitions/api.outboundErrorResponse' security: - BearerAuth: [] - summary: Generate function + summary: Create or update an outbound consumer tags: - - functions - /v1/functions/{id}: + - outbound + /v1/outbound/endpoints/{id}: delete: - consumes: - - application/json - description: Delete a function by its ID + description: Delivery history is kept. parameters: - - description: Function ID + - description: Endpoint ID in: path name: id required: true @@ -3678,26 +10200,23 @@ paths: "200": description: OK schema: - $ref: '#/definitions/structs.DeleteFunctionResponse' - "400": - description: Bad Request + $ref: '#/definitions/api.deletedResponse' + "403": + description: Forbidden schema: - type: string - "500": - description: Internal Server Error + $ref: '#/definitions/api.outboundErrorResponse' + "404": + description: Not Found schema: - type: string + $ref: '#/definitions/api.outboundErrorResponse' security: - BearerAuth: [] - summary: Delete function + summary: Delete an outbound endpoint tags: - - functions + - outbound get: - consumes: - - application/json - description: Get a function by its ID parameters: - - description: Function ID + - description: Endpoint ID in: path name: id required: true @@ -3708,67 +10227,78 @@ paths: "200": description: OK schema: - $ref: '#/definitions/structs.Function' - "400": - description: Bad Request + $ref: '#/definitions/structs.OutboundEndpoint' + "403": + description: Forbidden schema: - type: string - "500": - description: Internal Server Error + $ref: '#/definitions/api.outboundErrorResponse' + "404": + description: Not Found schema: - type: string + $ref: '#/definitions/api.outboundErrorResponse' security: - BearerAuth: [] - summary: Get function + summary: Get an outbound endpoint tags: - - functions + - outbound put: consumes: - application/json - description: Update an existing function + description: Replaces the endpoint's configuration. Its state, health and signing + secrets are kept. parameters: - - description: Function ID + - description: Endpoint ID in: path name: id required: true type: string - - description: Function configuration + - description: Endpoint configuration in: body - name: functionPayload + name: endpoint required: true schema: - $ref: '#/definitions/structs.UpdateFunctionRequest' + $ref: '#/definitions/structs.OutboundEndpoint' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/structs.Function' + $ref: '#/definitions/structs.OutboundEndpoint' "400": description: Bad Request schema: - type: string - "500": - description: Internal Server Error + $ref: '#/definitions/api.outboundErrorResponse' + "403": + description: Forbidden schema: - type: string + $ref: '#/definitions/api.outboundErrorResponse' + "404": + description: Not Found + schema: + $ref: '#/definitions/api.outboundErrorResponse' security: - BearerAuth: [] - summary: Update function + summary: Update an outbound endpoint tags: - - functions - /v1/functions/{id}/config: + - outbound + /v1/outbound/endpoints/{id}/deliveries: get: - consumes: - - application/json - description: List the configuration values for a given function + description: Newest first, with their delivery attempts, within the 35-day history. parameters: - - description: Function ID + - description: Endpoint ID in: path name: id required: true type: string + - description: Page size, at most 100 + in: query + name: limit + type: integer + - description: Page offset + in: query + name: offset + type: integer produces: - application/json responses: @@ -3776,100 +10306,150 @@ paths: description: OK schema: items: - $ref: '#/definitions/structs.Variable' + $ref: '#/definitions/structs.Log' type: array - "400": - description: Bad Request + "403": + description: Forbidden schema: - type: string - "500": - description: Internal Server Error + $ref: '#/definitions/api.outboundErrorResponse' + "404": + description: Not Found schema: - type: string + $ref: '#/definitions/api.outboundErrorResponse' + "503": + description: Outbound storage is not enabled + schema: + $ref: '#/definitions/api.outboundErrorResponse' security: - BearerAuth: [] - summary: List function config + summary: List an outbound endpoint's deliveries tags: - - functions - put: - consumes: - - application/json - description: Set the configuration value for a given function + - outbound + /v1/outbound/endpoints/{id}/pause: + post: + description: Messages published while paused are recorded as skipped; replay + them with replay-missing after resuming. parameters: - - description: Function ID + - description: Endpoint ID in: path name: id required: true type: string - - description: Configuration value - in: body - name: config - required: true - schema: - $ref: '#/definitions/api.setFunctionConfigRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/structs.Variable' - "400": - description: Bad Request + $ref: '#/definitions/structs.OutboundEndpoint' + "403": + description: Forbidden schema: - type: string - "500": - description: Internal Server Error + $ref: '#/definitions/api.outboundErrorResponse' + "404": + description: Not Found schema: - type: string + $ref: '#/definitions/api.outboundErrorResponse' security: - BearerAuth: [] - summary: Set function config + summary: Pause an outbound endpoint tags: - - functions - /v1/functions/{id}/config/{key}: - delete: + - outbound + /v1/outbound/endpoints/{id}/recover: + post: consumes: - application/json - description: Delete the configuration value for a given function + description: Re-sends the endpoint's deliveries that exhausted their retries + since the given time, in the background. parameters: - - description: Function ID + - description: Endpoint ID in: path name: id required: true type: string - - description: Configuration key + - description: Recovery window + in: body + name: recovery + schema: + $ref: '#/definitions/api.outboundRecoveryBody' + produces: + - application/json + responses: + "202": + description: Accepted + schema: + $ref: '#/definitions/structs.OutboundRecoveryTask' + "400": + description: Bad Request + schema: + $ref: '#/definitions/api.outboundErrorResponse' + "403": + description: Forbidden + schema: + $ref: '#/definitions/api.outboundErrorResponse' + "404": + description: Not Found + schema: + $ref: '#/definitions/api.outboundErrorResponse' + "429": + description: Too many recovery tasks are still running + schema: + $ref: '#/definitions/api.outboundErrorResponse' + security: + - BearerAuth: [] + summary: Recover failed outbound deliveries + tags: + - outbound + /v1/outbound/endpoints/{id}/replay-missing: + post: + consumes: + - application/json + description: Sends the deliveries skipped while the endpoint was paused or disabled, + in the background. Resume the endpoint first. + parameters: + - description: Endpoint ID in: path - name: key + name: id required: true type: string + - description: Recovery window + in: body + name: recovery + schema: + $ref: '#/definitions/api.outboundRecoveryBody' produces: - application/json responses: - "200": - description: OK + "202": + description: Accepted schema: - $ref: '#/definitions/structs.DeleteVariableResponse' + $ref: '#/definitions/structs.OutboundRecoveryTask' "400": description: Bad Request schema: - type: string - "500": - description: Internal Server Error + $ref: '#/definitions/api.outboundErrorResponse' + "403": + description: Forbidden schema: - type: string + $ref: '#/definitions/api.outboundErrorResponse' + "404": + description: Not Found + schema: + $ref: '#/definitions/api.outboundErrorResponse' + "429": + description: Too many recovery tasks are still running + schema: + $ref: '#/definitions/api.outboundErrorResponse' security: - BearerAuth: [] - summary: Delete function config value + summary: Replay skipped outbound deliveries tags: - - functions - /v1/functions/{id}/invoke: + - outbound + /v1/outbound/endpoints/{id}/resume: post: - consumes: - - application/json - description: Invoke a function by its ID + description: Restarts deliveries and resets the endpoint's failure count. parameters: - - description: Function ID + - description: Endpoint ID in: path name: id required: true @@ -3880,58 +10460,70 @@ paths: "200": description: OK schema: - $ref: '#/definitions/structs.ExecuteResponse' - "400": - description: Bad Request + $ref: '#/definitions/structs.OutboundEndpoint' + "403": + description: Forbidden schema: - type: string - "500": - description: Internal Server Error + $ref: '#/definitions/api.outboundErrorResponse' + "404": + description: Not Found schema: - type: string + $ref: '#/definitions/api.outboundErrorResponse' security: - BearerAuth: [] - summary: Invoke function + summary: Resume an outbound endpoint tags: - - functions - /v1/functions/{id}/logs: - get: + - outbound + /v1/outbound/endpoints/{id}/retry: + post: consumes: - application/json - description: Get the logs for a function + description: Re-sends message_id to the endpoint in the background and returns + the recovery task. parameters: - - description: Function ID + - description: Endpoint ID in: path name: id required: true type: string + - description: message_id is required + in: body + name: recovery + required: true + schema: + $ref: '#/definitions/api.outboundRecoveryBody' produces: - application/json responses: - "200": - description: OK + "202": + description: Accepted schema: - $ref: '#/definitions/structs.ExecuteLogResponse' + $ref: '#/definitions/structs.OutboundRecoveryTask' "400": description: Bad Request schema: - type: string - "500": - description: Internal Server Error + $ref: '#/definitions/api.outboundErrorResponse' + "403": + description: Forbidden schema: - type: string + $ref: '#/definitions/api.outboundErrorResponse' + "404": + description: Not Found + schema: + $ref: '#/definitions/api.outboundErrorResponse' + "429": + description: Too many recovery tasks are still running + schema: + $ref: '#/definitions/api.outboundErrorResponse' security: - BearerAuth: [] - summary: Get function logs + summary: Retry one outbound delivery tags: - - functions - /v1/functions/{id}/logs/{logId}: - get: - consumes: - - application/json - description: Get the logs for a function + - outbound + /v1/outbound/endpoints/{id}/secret/reveal: + post: parameters: - - description: Function ID + - description: Endpoint ID in: path name: id required: true @@ -3942,87 +10534,57 @@ paths: "200": description: OK schema: - $ref: '#/definitions/structs.ExecuteLogResponse' - "400": - description: Bad Request + $ref: '#/definitions/api.secretResponse' + "403": + description: Forbidden schema: - type: string - "500": - description: Internal Server Error + $ref: '#/definitions/api.outboundErrorResponse' + "404": + description: Not Found schema: - type: string + $ref: '#/definitions/api.outboundErrorResponse' security: - BearerAuth: [] - summary: Get function logs + summary: Reveal an outbound endpoint's signing secret tags: - - functions - /v1/logs: - get: - consumes: - - application/json - description: Get paginated list of webhook logs from warehouse for the authenticated - account + - outbound + /v1/outbound/endpoints/{id}/secret/rotate: + post: + description: Returns the new secret. The previous secret keeps signing for 24 + hours; another rotation is refused until then. parameters: - - description: Filter by bucket ID - in: query - name: bucket + - description: Endpoint ID + in: path + name: id required: true type: string - - description: Number of results per page - in: query - name: limit - type: integer - - description: Offset for pagination - in: query - name: offset - type: integer - - description: From date (YYYY-MM-DD or RFC3339) - in: query - name: from - type: string - - description: To date (YYYY-MM-DD or RFC3339) - in: query - name: to - type: string - - description: Filter by status (sent, failed, stalled, received, rejected) - in: query - name: status - type: string - - description: Opaque pagination cursor (turbostore accounts; takes precedence - over offset) - in: query - name: cursor - type: string produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/api.logsResponse' + $ref: '#/definitions/api.secretResponse' + "400": + description: The previous rotation's overlap has not ended + schema: + $ref: '#/definitions/api.outboundErrorResponse' + "403": + description: Forbidden + schema: + $ref: '#/definitions/api.outboundErrorResponse' + "404": + description: Not Found + schema: + $ref: '#/definitions/api.outboundErrorResponse' security: - BearerAuth: [] - summary: List webhook logs from warehouse (paginated) + summary: Rotate an outbound endpoint's signing secret tags: - - logs - /v1/logs-stats: + - outbound + /v1/outbound/event-types: get: - consumes: - - application/json - description: Get account log statistics - parameters: - - description: From date (YYYY-MM-DD) - in: query - name: from - type: string - - description: To date (YYYY-MM-DD) - in: query - name: to - type: string - - description: Filter by bucket ID - in: query - name: bucketId - type: string + description: Lists the producer's event catalog. produces: - application/json responses: @@ -4030,156 +10592,136 @@ paths: description: OK schema: items: - $ref: '#/definitions/structs.LogsStats' + $ref: '#/definitions/structs.OutboundEventType' type: array + "403": + description: Forbidden + schema: + $ref: '#/definitions/api.outboundErrorResponse' security: - BearerAuth: [] - summary: Get account log statistics + summary: List outbound event types tags: - - logs - /v1/logs/{id}: - get: + - outbound + post: consumes: - application/json - description: Get detailed information about a specific webhook log from warehouse parameters: - - description: Log ID - in: path - name: id + - description: Event type + in: body + name: eventType required: true - type: string + schema: + $ref: '#/definitions/structs.OutboundEventType' produces: - application/json responses: - "200": - description: OK + "201": + description: Created schema: - $ref: '#/definitions/structs.Log' - "404": - description: Not Found + $ref: '#/definitions/structs.OutboundEventType' + "400": + description: Bad Request schema: - type: string + $ref: '#/definitions/api.outboundErrorResponse' + "403": + description: Not permitted, or the event type limit is reached + schema: + $ref: '#/definitions/api.outboundErrorResponse' security: - BearerAuth: [] - summary: Get log details from warehouse + summary: Create or update an outbound event type tags: - - logs - put: - description: Update a webhook log. Can be used to update status, response body, - headers and status code. Only modifiable within first 10 seconds. + - outbound + /v1/outbound/event-types/{name}: + delete: + description: Refused while an endpoint subscribes to the event type by name. parameters: - - description: Log ID + - description: Event type name in: path - name: id + name: name required: true type: string - - description: Updated log data - in: body - name: log - required: true - schema: - $ref: '#/definitions/structs.Log' + produces: + - application/json responses: "200": description: OK schema: - type: string + $ref: '#/definitions/api.deletedResponse' "400": - description: Bad Request + description: An endpoint subscribes to the event type schema: - type: string + $ref: '#/definitions/api.outboundErrorResponse' + "403": + description: Forbidden + schema: + $ref: '#/definitions/api.outboundErrorResponse' "404": description: Not Found schema: - type: string + $ref: '#/definitions/api.outboundErrorResponse' security: - BearerAuth: [] - summary: Update log + summary: Delete an outbound event type tags: - - logs - /v1/logs/{id}/action: - post: + - outbound + put: consumes: - application/json - description: Perform an action on a webhook log from warehouse (e.g., resend) + description: The name in the path wins over a name in the body. parameters: - - description: Log ID + - description: Event type name in: path - name: id + name: name required: true type: string - - description: Action request + - description: Event type in: body - name: action + name: eventType required: true schema: - $ref: '#/definitions/api.actionLogRequest' + $ref: '#/definitions/structs.OutboundEventType' produces: - application/json responses: "200": description: OK schema: - type: string + $ref: '#/definitions/structs.OutboundEventType' "400": description: Bad Request schema: - type: string - "404": - description: Not Found - schema: - type: string - security: - - BearerAuth: [] - summary: Perform action on log from warehouse - tags: - - logs - /v1/logs/histogram: - get: - description: Returns 1-minute resolution counts split by status plus - parameters: - - description: 'From timestamp (RFC3339 or YYYY-MM-DD); default: 1h ago' - in: query - name: from - type: string - - description: 'To timestamp (RFC3339 or YYYY-MM-DD); default: now' - in: query - name: to - type: string - - description: Filter to a single bucket - in: query - name: bucket_id - type: string - - description: Filter to a single output - in: query - name: output_id - type: string - - description: Filter to a single status (sent, failed, stalled, received, rejected, - preparing) - in: query - name: status - type: string - - description: Filter to a single HTTP status code - in: query - name: status_code - type: integer - produces: - - application/json - responses: - "200": - description: OK + $ref: '#/definitions/api.outboundErrorResponse' + "403": + description: Not permitted, or the event type limit is reached schema: - $ref: '#/definitions/api.logsHistogramResponse' + $ref: '#/definitions/api.outboundErrorResponse' security: - BearerAuth: [] - summary: Per-minute log histogram for the explorer timeline + summary: Create or update an outbound event type tags: - - logs - /v1/managed-certs: + - outbound + /v1/outbound/messages: get: - consumes: - - application/json - description: Get list of all managed certificates for the authenticated account + description: Newest first, without payloads. + parameters: + - description: Consumer ID + in: query + name: consumer + type: string + - description: Event type + in: query + name: event_type + type: string + - description: Page size, at most 100 + in: query + name: limit + type: integer + - description: Page offset + in: query + name: offset + type: integer produces: - application/json responses: @@ -4187,170 +10729,285 @@ paths: description: OK schema: items: - type: object + $ref: '#/definitions/structs.OutboundMessage' type: array + "403": + description: Forbidden + schema: + $ref: '#/definitions/api.outboundErrorResponse' security: - BearerAuth: [] - summary: List managed certificates + summary: List outbound messages tags: - - managed-certs + - outbound post: consumes: - application/json - description: Create a new managed SSL certificate for a domain + description: Accepts a message for signed, asynchronous delivery to every endpoint + of the consumer subscribed to its event type. Reusing an Idempotency-Key with + the same message returns the original receipt. parameters: - - description: Managed certificate configuration + - description: Message in: body - name: cert + name: message required: true schema: - $ref: '#/definitions/api.createManagedCertRequest' + $ref: '#/definitions/structs.PublishOutboundMessageRequest' + - description: Retry key; reuse it only for the same consumer, event type and + payload + in: header + name: Idempotency-Key + type: string produces: - application/json responses: - "201": - description: Created + "202": + description: Accepted schema: - $ref: '#/definitions/api.Response' + $ref: '#/definitions/structs.OutboundMessage' "400": description: Bad Request schema: - type: string - "451": - description: Unavailable For Legal Reasons + $ref: '#/definitions/api.outboundErrorResponse' + "403": + description: Forbidden schema: - type: string + $ref: '#/definitions/api.outboundErrorResponse' + "404": + description: Consumer not found + schema: + $ref: '#/definitions/api.outboundErrorResponse' + "409": + description: The idempotency key was used for a different message + schema: + $ref: '#/definitions/api.outboundErrorResponse' + "429": + description: Too many messages are still waiting to be enqueued + schema: + $ref: '#/definitions/api.outboundErrorResponse' + "503": + description: Outbound storage is not enabled + schema: + $ref: '#/definitions/api.outboundErrorResponse' security: - BearerAuth: [] - summary: Create managed certificate + summary: Publish an outbound message tags: - - managed-certs - /v1/managed-certs/{id}: - delete: - description: Delete a managed certificate by ID + - outbound + /v1/outbound/messages/{id}: + get: + description: Returns the payload and each endpoint's delivery with its attempts. + Recently accepted messages may still be preparing. parameters: - - description: Managed certificate ID + - description: Message ID in: path name: id required: true type: string + produces: + - application/json responses: "200": description: OK schema: - $ref: '#/definitions/api.Response' + $ref: '#/definitions/api.outboundMessageDetail' + "403": + description: Forbidden + schema: + $ref: '#/definitions/api.outboundErrorResponse' + "404": + description: Not Found + schema: + $ref: '#/definitions/api.outboundErrorResponse' security: - BearerAuth: [] - summary: Delete managed certificate + summary: Get an outbound message tags: - - managed-certs - /v1/news: + - outbound + /v1/outbound/recovery-tasks/{id}: + get: + parameters: + - description: Recovery task ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/structs.OutboundRecoveryTask' + "403": + description: Forbidden + schema: + $ref: '#/definitions/api.outboundErrorResponse' + "404": + description: Not Found + schema: + $ref: '#/definitions/api.outboundErrorResponse' + security: + - BearerAuth: [] + summary: Get an outbound recovery task + tags: + - outbound + /v1/plans/optional-items: get: consumes: - application/json - description: Get all news entries + description: Returns optional add-on items (like extra webhooks) available for + each plan produces: - application/json responses: "200": description: OK schema: - items: - $ref: '#/definitions/structs.NewsEntry' - type: array + $ref: '#/definitions/api.listPlanOptionalItemsResponse' "500": description: Internal Server Error schema: type: string security: - BearerAuth: [] - summary: Get news entries + summary: List optional items for plans tags: - - news + - billing + /v1/retry/messages/{id}: post: - consumes: - - application/json - description: Create a new news entry + description: Re-delivers a stored webhook log to its endpoint and updates that + log in place. Relies on turbostore v2. parameters: - - description: News entry - in: body - name: newsEntry + - description: Log ID + in: path + name: id required: true - schema: - $ref: '#/definitions/structs.NewsEntryCreateRequest' + type: string produces: - application/json responses: - "201": - description: Created + "200": + description: OK schema: $ref: '#/definitions/api.Response' "400": description: Bad Request schema: type: string - "500": - description: Internal Server Error + "404": + description: Not Found schema: type: string security: - BearerAuth: [] - summary: Create news entry + summary: Retry a single webhook message tags: - - news - /v1/news/{id}: - delete: + - retry + /v1/retry/recover: + post: consumes: - application/json - description: Delete a news entry by ID + description: Re-delivers every failed webhook log in a bucket within the given + window. Returns a task that can be polled for progress. parameters: - - description: News entry ID - in: path - name: id + - description: Recovery window + in: body + name: body required: true - type: string + schema: + $ref: '#/definitions/api.retryBulkRequest' produces: - application/json responses: - "200": - description: OK + "202": + description: Accepted schema: - $ref: '#/definitions/api.Response' + $ref: '#/definitions/structs.RetryTask' "400": description: Bad Request schema: type: string - "500": - description: Internal Server Error + security: + - BearerAuth: [] + summary: Recover failed webhook messages + tags: + - retry + /v1/retry/replay-missing: + post: + consumes: + - application/json + description: Re-delivers webhook logs that were persisted but never attempted + against their output within the given window. Returns a task that can be polled + for progress. + parameters: + - description: Replay window + in: body + name: body + required: true + schema: + $ref: '#/definitions/api.retryBulkRequest' + produces: + - application/json + responses: + "202": + description: Accepted + schema: + $ref: '#/definitions/structs.RetryTask' + "400": + description: Bad Request schema: type: string security: - BearerAuth: [] - summary: Delete news entry + summary: Replay never-attempted webhook messages tags: - - news - /v1/plans/optional-items: + - retry + /v1/retry/tasks: get: - consumes: + parameters: + - description: Filter by bucket ID + in: query + name: bucket + type: string + produces: - application/json - description: Returns optional add-on items (like extra webhooks) available for - each plan + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/structs.RetryTask' + type: array + security: + - BearerAuth: [] + summary: List retry tasks + tags: + - retry + /v1/retry/tasks/{id}: + get: + parameters: + - description: Task ID + in: path + name: id + required: true + type: string produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/api.listPlanOptionalItemsResponse' - "500": - description: Internal Server Error + $ref: '#/definitions/structs.RetryTask' + "404": + description: Not Found schema: type: string security: - BearerAuth: [] - summary: List optional items for plans + summary: Get a retry task tags: - - billing + - retry /v1/service-connections: get: consumes: @@ -4373,7 +11030,8 @@ paths: post: consumes: - application/json - description: Create a new service connection + description: Create a credentialed service connection. Webhook Relay AI is built + in and is imported by Functions with require("ai") without a service connection. parameters: - description: Service connection configuration in: body @@ -4909,6 +11567,114 @@ paths: summary: Get account usage tags: - usage + /v1/user/invitations: + get: + consumes: + - application/json + description: List pending, unexpired invitations addressed to the authenticated + account's email + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/structs.OrganizationInviteDetails' + type: array + security: + - BearerAuth: [] + summary: List my pending invitations + tags: + - organizations + /v1/user/invitations/{id}/accept: + post: + consumes: + - application/json + description: Accept a pending invitation addressed to the authenticated account's + email. Requires a verified email. + parameters: + - description: Invitation ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/structs.OrganizationMember' + security: + - BearerAuth: [] + summary: Accept an invitation + tags: + - organizations + /v1/user/invitations/{id}/decline: + post: + consumes: + - application/json + description: Decline a pending invitation addressed to the authenticated account's + email + parameters: + - description: Invitation ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + security: + - BearerAuth: [] + summary: Decline an invitation + tags: + - organizations + /v1/user/memberships: + get: + consumes: + - application/json + description: 'List organizations the authenticated account belongs to. Always + actor-scoped: the org override never applies to /v1/user/ routes.' + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/structs.OrganizationMembershipDetails' + type: array + security: + - BearerAuth: [] + summary: List my organization memberships + tags: + - organizations + /v1/user/memberships/{id}: + delete: + consumes: + - application/json + description: Remove the authenticated account's own membership. The path ID + is the organization account ID. + parameters: + - description: Organization account ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + security: + - BearerAuth: [] + summary: Leave an organization + tags: + - organizations schemes: - https swagger: "2.0" diff --git a/test/outbound.test.ts b/test/outbound.test.ts new file mode 100644 index 0000000..bce63db --- /dev/null +++ b/test/outbound.test.ts @@ -0,0 +1,141 @@ +import { describe, expect, it } from "vitest"; +import { createClient } from "./helpers.js"; +import { onboardCustomer, publishInvoicePaid } from "../examples/outbound.js"; + +const base = "https://my.webhookrelay.com"; +const requests = (calls: { method: string; url: string }[]) => + calls.map((c) => `${c.method} ${c.url.replace(base, "")}`); + +describe("outbound", () => { + it("manages consumers and event types", async () => { + const { relay, calls } = createClient((url, method) => + method === "GET" ? { json: [] } : { json: { id: "customer:42", name: "Acme", rate: 0 } }, + ); + + await relay.outbound.consumers.list(); + await relay.outbound.consumers.upsert("customer:42", { name: "Acme" }); + await relay.outbound.consumers.delete("customer:42"); + await relay.outbound.eventTypes.upsert("invoice/paid", { description: "Paid", example: [1, 2] }); + await relay.outbound.eventTypes.delete("invoice/paid"); + + expect(requests(calls)).toEqual([ + "GET /v1/outbound/consumers", + "PUT /v1/outbound/consumers/customer%3A42", + "DELETE /v1/outbound/consumers/customer%3A42", + "PUT /v1/outbound/event-types/invoice%2Fpaid", + "DELETE /v1/outbound/event-types/invoice%2Fpaid", + ]); + expect(calls[1]?.body).toEqual({ name: "Acme" }); + expect(calls[3]?.body).toEqual({ name: "invoice/paid", description: "Paid", example: [1, 2] }); + }); + + it("creates endpoints with camelCase or snake_case params", async () => { + const { relay, calls } = createClient(() => ({ json: { id: "endpoint-1", secret: "whsec_abc" } })); + + const endpoint = await relay.outbound.endpoints.create("customer_42", { + url: "https://example.com/hook", + eventTypes: ["*"], + autoDisable: true, + functionId: "fn-1", + }); + await relay.outbound.endpoints.update("endpoint-1", { url: "https://example.com/v2", event_types: ["a"] }); + + expect(endpoint.secret).toBe("whsec_abc"); + expect(calls[0]?.body).toEqual({ + url: "https://example.com/hook", + event_types: ["*"], + auto_disable: true, + function_id: "fn-1", + }); + expect(calls[1]?.body).toEqual({ url: "https://example.com/v2", event_types: ["a"] }); + }); + + it("pauses, resumes and handles signing secrets", async () => { + const { relay, calls } = createClient((url) => + url.includes("/secret/") ? { json: { secret: "whsec_new" } } : { json: { id: "endpoint-1", state: "paused" } }, + ); + + expect((await relay.outbound.endpoints.pause("endpoint-1")).state).toBe("paused"); + await relay.outbound.endpoints.resume("endpoint-1"); + expect(await relay.outbound.endpoints.rotateSecret("endpoint-1")).toBe("whsec_new"); + expect(await relay.outbound.endpoints.revealSecret("endpoint-1")).toBe("whsec_new"); + + expect(requests(calls)).toEqual([ + "POST /v1/outbound/endpoints/endpoint-1/pause", + "POST /v1/outbound/endpoints/endpoint-1/resume", + "POST /v1/outbound/endpoints/endpoint-1/secret/rotate", + "POST /v1/outbound/endpoints/endpoint-1/secret/reveal", + ]); + }); + + it("publishes with an idempotency key and lists messages", async () => { + const { relay, calls } = createClient((url, method) => + method === "GET" ? { json: [] } : { status: 202, json: { id: "message-1", endpoint_ids: ["endpoint-1"] } }, + ); + + const message = await relay.outbound.messages.publish( + { consumer: "customer_42", eventType: "invoice.paid", eventId: "evt_1", payload: "plain string" }, + { idempotencyKey: "invoice-paid:inv_123" }, + ); + await relay.outbound.messages.publish({ consumer: "customer_42", event_type: "invoice.paid", payload: {} }); + await relay.outbound.messages.list({ consumer: "customer_42", eventType: "invoice.paid", limit: 10 }); + + expect(message.id).toBe("message-1"); + expect(calls[0]?.headers["Idempotency-Key"]).toBe("invoice-paid:inv_123"); + expect(calls[0]?.body).toEqual({ + consumer: "customer_42", + event_type: "invoice.paid", + event_id: "evt_1", + payload: "plain string", + }); + expect(calls[1]?.headers["Idempotency-Key"]).toBeUndefined(); + expect(calls[2]?.url).toBe(`${base}/v1/outbound/messages?consumer=customer_42&event_type=invoice.paid&limit=10`); + }); + + it("reads deliveries and starts recoveries", async () => { + const { relay, calls } = createClient((url, method) => + method === "GET" && url.includes("/deliveries") + ? { json: [{ id: "delivery-1", message_id: "message-1", status: "sent" }] } + : { status: 202, json: { id: "task-1", status: "pending" } }, + ); + + const deliveries = await relay.outbound.endpoints.deliveries("endpoint-1", { limit: 5 }); + await relay.outbound.endpoints.retry("endpoint-1", "message-1"); + await relay.outbound.endpoints.recover("endpoint-1", { since: "2026-09-01T00:00:00Z" }); + await relay.outbound.endpoints.replayMissing("endpoint-1"); + await relay.outbound.recoveryTasks.get("task-1"); + + expect(deliveries[0]?.message_id).toBe("message-1"); + expect(requests(calls)).toEqual([ + "GET /v1/outbound/endpoints/endpoint-1/deliveries?limit=5", + "POST /v1/outbound/endpoints/endpoint-1/retry", + "POST /v1/outbound/endpoints/endpoint-1/recover", + "POST /v1/outbound/endpoints/endpoint-1/replay-missing", + "GET /v1/outbound/recovery-tasks/task-1", + ]); + expect(calls[1]?.body).toEqual({ message_id: "message-1" }); + expect(calls[2]?.body).toEqual({ since: "2026-09-01T00:00:00Z" }); + }); + + it("runs the example that the dashboard shows", async () => { + const { relay, calls } = createClient((url) => + url.endsWith("/endpoints") + ? { status: 201, json: { id: "endpoint-1", secret: "whsec_abc" } } + : { json: { id: "resource-1", endpoint_ids: ["endpoint-1"] } }, + ); + + const endpoint = await onboardCustomer(relay, "https://customer.example/webhooks"); + const message = await publishInvoicePaid(relay); + + expect(endpoint.secret).toBe("whsec_abc"); + expect(message.endpoint_ids).toEqual(["endpoint-1"]); + expect(requests(calls)).toEqual([ + "PUT /v1/outbound/event-types/invoice.paid", + "PUT /v1/outbound/consumers/customer_42", + "POST /v1/outbound/consumers/customer_42/endpoints", + "POST /v1/outbound/messages", + ]); + expect(calls[2]?.body).toEqual({ url: "https://customer.example/webhooks", event_types: ["invoice.paid"] }); + expect(calls[3]?.headers["Idempotency-Key"]).toBe("invoice-paid:inv_123"); + }); +}); diff --git a/vitest.config.ts b/vitest.config.ts index 3c38114..43af930 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -1,6 +1,10 @@ import { defineConfig } from "vitest/config"; export default defineConfig({ + resolve: { + // Examples import the package by name; resolve it to the source under test. + alias: { "@webhookrelay/sdk": new URL("./src/index.ts", import.meta.url).pathname }, + }, test: { environment: "node", include: ["test/**/*.test.ts"],