{"openapi":"3.0.0","paths":{"/":{"get":{"operationId":"AppController_getHello","parameters":[],"responses":{"200":{"description":""}},"tags":["App"]}},"/api/admin/dashboard":{"get":{"operationId":"AdminController_getDashboard","parameters":[],"responses":{"200":{"description":"Dashboard stats"}},"summary":"Get admin dashboard statistics","tags":["Admin"]}},"/api/admin/users":{"get":{"operationId":"AdminController_listUsers","parameters":[{"name":"search","required":true,"in":"query","schema":{"type":"string"}},{"name":"tier","required":true,"in":"query","schema":{"type":"string"}},{"name":"take","required":true,"in":"query","schema":{"type":"string"}},{"name":"skip","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"List all users (paginated, searchable)","tags":["Admin"]}},"/api/admin/users/{id}":{"get":{"operationId":"AdminController_getUserDetail","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Get detailed user info for admin","tags":["Admin"]},"delete":{"operationId":"AdminController_deleteUser","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Delete a user and all their data","tags":["Admin"]}},"/api/admin/users/{id}/reset-usage":{"post":{"operationId":"AdminController_resetUsage","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":""}},"summary":"Reset a user usage count to zero","tags":["Admin"]}},"/api/admin/users/{id}/tier":{"patch":{"operationId":"AdminController_changeTier","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Change a user tier","tags":["Admin"]}},"/api/admin/users/{id}/tier-expiry":{"patch":{"operationId":"AdminController_setTierExpiry","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Set or clear a user tier expiry","tags":["Admin"]}},"/api/admin/users/{id}/subscription":{"post":{"operationId":"AdminController_grantSubscription","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":""}},"summary":"Manually grant/refresh a paid subscription","tags":["Admin"]}},"/api/admin/subscriptions":{"get":{"operationId":"AdminController_listSubscriptions","parameters":[{"name":"search","required":true,"in":"query","schema":{"type":"string"}},{"name":"status","required":true,"in":"query","schema":{"type":"string"}},{"name":"take","required":true,"in":"query","schema":{"type":"string"}},{"name":"skip","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"List all subscriptions","tags":["Admin"]}},"/api/admin/subscriptions/{id}":{"patch":{"operationId":"AdminController_updateSubscription","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Update a subscription (status/tier/expiry)","tags":["Admin"]}},"/api/admin/devices":{"get":{"operationId":"AdminController_listDevices","parameters":[{"name":"search","required":true,"in":"query","schema":{"type":"string"}},{"name":"platform","required":true,"in":"query","schema":{"type":"string"}},{"name":"active","required":true,"in":"query","schema":{"type":"string"}},{"name":"take","required":true,"in":"query","schema":{"type":"string"}},{"name":"skip","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"List all devices","tags":["Admin"]}},"/api/admin/devices/{id}/deactivate":{"post":{"operationId":"AdminController_deactivateDevice","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":""}},"summary":"Deactivate a device","tags":["Admin"]}},"/api/admin/devices/{id}":{"delete":{"operationId":"AdminController_deleteDevice","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Delete a device","tags":["Admin"]}},"/api/admin/channels":{"get":{"operationId":"AdminController_listChannels","parameters":[{"name":"search","required":true,"in":"query","schema":{"type":"string"}},{"name":"take","required":true,"in":"query","schema":{"type":"string"}},{"name":"skip","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"List all channels","tags":["Admin"]}},"/api/admin/channels/{id}":{"delete":{"operationId":"AdminController_deleteChannel","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Delete a channel and its notifications","tags":["Admin"]}},"/api/admin/organizations":{"get":{"operationId":"AdminController_listOrganizations","parameters":[{"name":"search","required":true,"in":"query","schema":{"type":"string"}},{"name":"take","required":true,"in":"query","schema":{"type":"string"}},{"name":"skip","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"List all organizations","tags":["Admin"]}},"/api/admin/notifications":{"get":{"operationId":"AdminController_listNotifications","parameters":[{"name":"search","required":true,"in":"query","schema":{"type":"string"}},{"name":"priority","required":true,"in":"query","schema":{"type":"string"}},{"name":"take","required":true,"in":"query","schema":{"type":"string"}},{"name":"skip","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"List all notifications","tags":["Admin"]}},"/api/admin/notifications/{id}/interactions":{"get":{"operationId":"AdminController_listNotificationInteractions","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"List interactions for a notification","tags":["Admin"]}},"/api/admin/notifications/{id}":{"delete":{"operationId":"AdminController_deleteNotification","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Delete a notification","tags":["Admin"]}},"/api/admin/api-keys":{"get":{"operationId":"AdminController_listApiKeys","parameters":[{"name":"search","required":true,"in":"query","schema":{"type":"string"}},{"name":"active","required":true,"in":"query","schema":{"type":"string"}},{"name":"take","required":true,"in":"query","schema":{"type":"string"}},{"name":"skip","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"List all API keys","tags":["Admin"]}},"/api/admin/api-keys/{id}/revoke":{"post":{"operationId":"AdminController_revokeApiKey","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":""}},"summary":"Revoke (deactivate) an API key","tags":["Admin"]}},"/api/admin/api-keys/{id}":{"delete":{"operationId":"AdminController_deleteApiKey","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Delete an API key","tags":["Admin"]}},"/api/admin/templates":{"get":{"operationId":"AdminController_listTemplates","parameters":[{"name":"search","required":true,"in":"query","schema":{"type":"string"}},{"name":"category","required":true,"in":"query","schema":{"type":"string"}},{"name":"take","required":true,"in":"query","schema":{"type":"string"}},{"name":"skip","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"List all notification templates","tags":["Admin"]}},"/api/admin/templates/{id}":{"delete":{"operationId":"AdminController_deleteTemplate","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Delete a notification template","tags":["Admin"]}},"/api/admin/audit-logs":{"get":{"operationId":"AdminController_listAuditLogs","parameters":[{"name":"action","required":true,"in":"query","schema":{"type":"string"}},{"name":"resourceType","required":true,"in":"query","schema":{"type":"string"}},{"name":"take","required":true,"in":"query","schema":{"type":"string"}},{"name":"skip","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"List all audit logs","tags":["Admin"]}},"/api/audit/logs":{"get":{"operationId":"AuditController_listAuditLogs","parameters":[{"name":"resourceType","required":false,"in":"query","schema":{"type":"string"}},{"name":"resourceId","required":false,"in":"query","schema":{"type":"string"}},{"name":"action","required":false,"in":"query","schema":{"type":"string"}},{"name":"take","required":false,"in":"query","schema":{"type":"string"}},{"name":"skip","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Audit log entries"}},"summary":"List audit log entries. Non-admin callers see only their own events.","tags":["Audit"]}},"/api/auth/register":{"post":{"operationId":"AuthController_register","parameters":[],"responses":{"201":{"description":"Account created. The API key is only shown once."}},"summary":"Register a new anonymous account and API key","tags":["Authentication"]}},"/api/auth/signin/apple":{"post":{"operationId":"AuthController_signInWithApple","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["identityToken"],"properties":{"identityToken":{"type":"string","description":"Apple Sign In identity token (JWT)"}}}}}},"responses":{"200":{"description":"Signed in with Apple"},"401":{"description":"Invalid identity token"}},"summary":"Sign in with Apple — logs in or creates an account; links/merges when authenticated","tags":["Authentication"]}},"/api/auth/signin/google":{"post":{"operationId":"AuthController_signInWithGoogle","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["idToken"],"properties":{"idToken":{"type":"string","description":"Google Sign In ID token (JWT)"}}}}}},"responses":{"200":{"description":"Signed in with Google"},"401":{"description":"Invalid ID token"}},"summary":"Sign in with Google — logs in or creates an account; links/merges when authenticated","tags":["Authentication"]}},"/api/auth/account":{"delete":{"operationId":"AuthController_deleteAccount","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteAccountDto"}}}},"responses":{"200":{"description":"Account permanently deleted"},"403":{"description":"Social re-authentication required"}},"summary":"Permanently delete the authenticated account","tags":["Authentication"]}},"/api/auth/keys":{"get":{"operationId":"AuthController_listApiKeys","parameters":[],"responses":{"200":{"description":"List of API keys"}},"summary":"List all API keys (keys are masked)","tags":["Authentication"]},"post":{"operationId":"AuthController_createApiKey","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateApiKeyDto"}}}},"responses":{"201":{"description":"API key created"}},"summary":"Create a new API key (raw key returned once)","tags":["Authentication"]}},"/api/auth/keys/{id}/rotate":{"post":{"operationId":"AuthController_rotateApiKey","parameters":[],"responses":{"200":{"description":"API key rotated"},"404":{"description":"API key not found"}},"summary":"Rotate an API key secret (new raw key returned once)","tags":["Authentication"]}},"/api/auth/keys/{id}":{"delete":{"operationId":"AuthController_revokeApiKey","parameters":[],"responses":{"200":{"description":"API key revoked"}},"summary":"Revoke an API key","tags":["Authentication"]}},"/api/auth/keys/{id}/channels":{"post":{"operationId":"AuthController_grantKeyChannel","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["channelId"],"properties":{"channelId":{"type":"string","description":"Channel ID to grant access to"}}}}}},"responses":{"201":{"description":"Access granted"}},"summary":"Grant an API key access to a channel","tags":["Authentication"]},"get":{"operationId":"AuthController_listKeyChannels","parameters":[],"responses":{"200":{"description":"List of channel grants"}},"summary":"List channels an API key has access to","tags":["Authentication"]}},"/api/auth/keys/{id}/channels/{channelId}":{"delete":{"operationId":"AuthController_revokeKeyChannel","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"channelId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Access revoked"}},"summary":"Revoke an API key's access to a channel","tags":["Authentication"]}},"/api/links":{"get":{"operationId":"ChannelLinksController_listAllLinks","parameters":[],"responses":{"200":{"description":"Links with their channel"}},"summary":"List all of the account's active links, across channels","tags":["Channel Links"]}},"/api/channels/{id}/links":{"get":{"operationId":"ChannelLinksController_listLinks","parameters":[],"responses":{"200":{"description":"Channel links"}},"summary":"List active links of a channel (keys masked)","tags":["Channel Links"]},"post":{"operationId":"ChannelLinksController_createLink","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateChannelLinkDto"}}}},"responses":{"201":{"description":"Channel link created"}},"summary":"Create a send-only link for a channel (URL returned once)","tags":["Channel Links"]}},"/api/channels/{id}/links/{linkId}":{"delete":{"operationId":"ChannelLinksController_revokeLink","parameters":[],"responses":{"200":{"description":"Channel link revoked"}},"summary":"Revoke a channel link","tags":["Channel Links"]}},"/auth/users":{"get":{"operationId":"UsersController_listUsers","parameters":[],"responses":{"200":{"description":"List of all users"}},"summary":"List all users","tags":["Users"]}},"/auth/{id}":{"get":{"operationId":"UsersController_getUser","parameters":[],"responses":{"200":{"description":"User details"},"404":{"description":"User not found"}},"summary":"Get user by ID","tags":["Users"]}},"/api/channels":{"post":{"operationId":"ChannelsController_createChannel","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"ownerId":{"type":"string","description":"Optional user ID of channel owner; defaults to the authenticated user"},"name":{"type":"string","description":"Channel name"},"alias":{"type":"string","description":"Human-readable alias (3-64 chars, lowercase alphanumeric + hyphens/underscores)"},"sendAccess":{"type":"string","enum":["open","restricted"],"default":"restricted"},"joinAccess":{"type":"string","enum":["public","invite","personal"],"default":"personal"},"description":{"type":"string"}}}}}},"responses":{"201":{"description":"Channel created successfully"}},"summary":"Create a new channel","tags":["Channels"]},"get":{"operationId":"ChannelsController_getAllChannels","parameters":[],"responses":{"200":{"description":"List of all channels"}},"summary":"List all channels","tags":["Channels"]}},"/api/channels/ensure/{alias}":{"put":{"operationId":"ChannelsController_ensureChannel","parameters":[{"name":"alias","required":true,"in":"path","description":"Stable channel alias","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnsureChannelDto"}}}},"responses":{"200":{"description":"Existing channel returned"},"201":{"description":"Channel created"}},"summary":"Idempotently create or return a channel by alias","tags":["Channels"]}},"/api/channels/{id}":{"get":{"operationId":"ChannelsController_getChannel","parameters":[{"name":"id","required":true,"in":"path","description":"Channel ID","schema":{}}],"responses":{"200":{"description":"Channel details"},"404":{"description":"Channel not found"}},"summary":"Get a channel by ID","tags":["Channels"]},"patch":{"operationId":"ChannelsController_updateChannel","parameters":[{"name":"id","required":true,"in":"path","description":"Channel ID","schema":{}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"alias":{"type":"string"},"description":{"type":"string"},"sendAccess":{"type":"string","enum":["open","restricted"]},"joinAccess":{"type":"string","enum":["public","invite","personal"]},"sender":{"type":"object","nullable":true,"description":"Default sender for notifications that don't set one. Replaces the current default; null removes it.","properties":{"name":{"type":"string","maxLength":100},"avatarUrl":{"type":"string","format":"uri","maxLength":512}}}}}}}},"responses":{"200":{"description":"Channel updated"},"404":{"description":"Channel not found"}},"summary":"Update a channel","tags":["Channels"]},"delete":{"operationId":"ChannelsController_deleteChannel","parameters":[{"name":"id","required":true,"in":"path","description":"Channel ID","schema":{}}],"responses":{"200":{"description":"Channel deleted"},"404":{"description":"Channel not found"}},"summary":"Delete a channel","tags":["Channels"]}},"/api/channels/user/{userId}":{"get":{"operationId":"ChannelsController_getUserChannels","parameters":[{"name":"userId","required":true,"in":"path","description":"User ID","schema":{}}],"responses":{"200":{"description":"List of user channels"}},"summary":"Get all channels a user is subscribed to","tags":["Channels"]}},"/api/channels/{id}/subscribers":{"get":{"operationId":"ChannelsController_getChannelSubscribers","parameters":[{"name":"id","required":true,"in":"path","description":"Channel ID","schema":{}}],"responses":{"200":{"description":"List of subscribers"}},"summary":"Get all subscribers of a channel","tags":["Channels"]}},"/api/channels/{id}/subscribe":{"post":{"operationId":"ChannelsController_subscribe","parameters":[{"name":"id","required":true,"in":"path","description":"Channel ID","schema":{}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["userId"],"properties":{"userId":{"type":"string"},"deviceId":{"type":"string"}}}}}},"responses":{"201":{"description":"Subscribed successfully"}},"summary":"Subscribe to a channel","tags":["Channels"]}},"/api/channels/{id}/unsubscribe":{"post":{"operationId":"ChannelsController_unsubscribe","parameters":[{"name":"id","required":true,"in":"path","description":"Channel ID","schema":{}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["userId"],"properties":{"userId":{"type":"string"}}}}}},"responses":{"200":{"description":"Unsubscribed successfully"}},"summary":"Unsubscribe from a channel","tags":["Channels"]}},"/api/channels/{id}/mute":{"post":{"operationId":"ChannelsController_muteChannel","parameters":[{"name":"id","required":true,"in":"path","description":"Channel ID","schema":{}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["userId","muted"],"properties":{"userId":{"type":"string"},"muted":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Channel mute status updated"}},"summary":"Mute or unmute a channel","tags":["Channels"]}},"/api/channels/{idOrAlias}/live-activity":{"post":{"operationId":"ChannelLiveActivityController_upsertLiveActivity","parameters":[{"name":"idOrAlias","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertLiveActivityDto"}}}},"responses":{"201":{"description":""}},"tags":["ChannelLiveActivity"]},"get":{"operationId":"ChannelLiveActivityController_getLiveActivity","parameters":[{"name":"idOrAlias","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["ChannelLiveActivity"]},"delete":{"operationId":"ChannelLiveActivityController_endLiveActivity","parameters":[{"name":"idOrAlias","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["ChannelLiveActivity"]}},"/api/channels/{idOrAlias}/live-activity/stream":{"get":{"operationId":"ChannelLiveActivityController_streamLiveActivity","parameters":[{"name":"idOrAlias","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["ChannelLiveActivity"]}},"/api/live-activities/register":{"post":{"operationId":"LiveActivitiesController_registerLiveActivity","parameters":[],"responses":{"201":{"description":""}},"tags":["LiveActivities"]}},"/api/live-activities/push-to-start/register":{"post":{"operationId":"LiveActivitiesController_registerPushToStartToken","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterPushToStartTokenDto"}}}},"responses":{"201":{"description":""}},"tags":["LiveActivities"]}},"/api/live-activities/reconcile":{"post":{"operationId":"LiveActivitiesController_reconcile","parameters":[],"responses":{"201":{"description":""}},"tags":["LiveActivities"]}},"/api/live-activities/{activityId}":{"delete":{"operationId":"LiveActivitiesController_unregister","parameters":[{"name":"activityId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["LiveActivities"]}},"/api/devices":{"post":{"operationId":"DevicesController_registerDevice","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["userId","platform"],"properties":{"userId":{"type":"string","description":"User ID"},"fcmToken":{"type":"string","description":"Firebase Cloud Messaging token (Android)"},"apnsToken":{"type":"string","description":"Raw APNs device token (iOS)"},"platform":{"type":"string","enum":["ios","android"],"description":"Device platform"},"deviceName":{"type":"string","description":"Human-readable device name"},"deviceModel":{"type":"string","description":"Device model identifier"},"publicKey":{"type":"string","description":"P-256 public key for E2E encryption (SPKI format, Base64)"}}}}}},"responses":{"201":{"description":"Device registered successfully"}},"summary":"Register a device for push notifications","tags":["Devices"]},"get":{"operationId":"DevicesController_listAllDevices","parameters":[],"responses":{"200":{"description":"List of all devices"}},"summary":"List all devices","tags":["Devices"]}},"/api/devices/user/{userId}":{"get":{"operationId":"DevicesController_getUserDevices","parameters":[{"name":"userId","required":true,"in":"path","description":"User ID","schema":{}}],"responses":{"200":{"description":"List of user devices"}},"summary":"Get all devices for a user","tags":["Devices"]}},"/api/devices/{id}":{"get":{"operationId":"DevicesController_getDevice","parameters":[{"name":"id","required":true,"in":"path","description":"Device ID","schema":{}}],"responses":{"200":{"description":"Device details"},"404":{"description":"Device not found"}},"summary":"Get a device by ID","tags":["Devices"]},"patch":{"description":"Update any of the caller's own devices — usable from a different device, since the API key is per-user.","operationId":"DevicesController_updateDevice","parameters":[{"name":"id","required":true,"in":"path","description":"Device ID","schema":{}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDeviceDto"}}}},"responses":{"200":{"description":"Device updated"},"404":{"description":"Device not found"}},"summary":"Update a device (rename, activate/deactivate)","tags":["Devices"]},"delete":{"operationId":"DevicesController_deleteDevice","parameters":[{"name":"id","required":true,"in":"path","description":"Device ID","schema":{}}],"responses":{"200":{"description":"Device deleted"},"404":{"description":"Device not found"}},"summary":"Delete a device","tags":["Devices"]}},"/api/devices/{id}/public-key":{"get":{"operationId":"DevicesController_getDevicePublicKey","parameters":[{"name":"id","required":true,"in":"path","description":"Device ID","schema":{}}],"responses":{"200":{"description":"Device public key"},"404":{"description":"Device not found"}},"summary":"Get a device public key","tags":["Devices"]}},"/api/devices/channel/{channelId}/public-keys":{"get":{"operationId":"DevicesController_getChannelDevicePublicKeys","parameters":[{"name":"channelId","required":true,"in":"path","description":"Channel ID","schema":{}}],"responses":{"200":{"description":"Channel device public keys"}},"summary":"List public keys for active devices in a channel","tags":["Devices"]}},"/api/devices/{id}/deactivate":{"post":{"operationId":"DevicesController_deactivateDevice","parameters":[{"name":"id","required":true,"in":"path","description":"Device ID","schema":{}}],"responses":{"200":{"description":"Device deactivated"},"404":{"description":"Device not found"}},"summary":"Deactivate a device (stop receiving notifications)","tags":["Devices"]}},"/api/health":{"get":{"operationId":"HealthController_getHealth","parameters":[],"responses":{"200":{"description":"Service health status"}},"summary":"Health check endpoint","tags":["Health & Stats"]}},"/api/health/detailed":{"get":{"operationId":"HealthController_getDetailedHealth","parameters":[],"responses":{"200":{"description":"Detailed health status"}},"summary":"Detailed health check with version and uptime","tags":["Health & Stats"]}},"/api/stats":{"get":{"operationId":"HealthController_getStats","parameters":[],"responses":{"200":{"description":"Dashboard statistics"}},"summary":"Get dashboard statistics","tags":["Health & Stats"]}},"/api/activity":{"get":{"operationId":"HealthController_getActivity","parameters":[{"name":"limit","required":false,"in":"query","schema":{"type":"number"}}],"responses":{"200":{"description":"Recent activity feed"}},"summary":"Get recent activity feed","tags":["Health & Stats"]}},"/api/tokens/register":{"post":{"operationId":"TokensController_registerToken","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterTokenDto"}}}},"responses":{"201":{"description":"Token registered successfully"}},"summary":"Register a push notification token","tags":["Tokens"]}},"/api/tokens/unregister":{"post":{"operationId":"TokensController_unregisterToken","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["token"],"properties":{"token":{"type":"string"}}}}}},"responses":{"200":{"description":"Token unregistered successfully"}},"summary":"Unregister a push notification token","tags":["Tokens"]}},"/api/tokens/user":{"get":{"operationId":"TokensController_getUserTokens","parameters":[{"name":"userId","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"List of user tokens"}},"summary":"Get all tokens for a user","tags":["Tokens"]}},"/api/tokens/send-test":{"post":{"operationId":"TokensController_sendTestNotification","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["token","title","message"],"properties":{"token":{"type":"string"},"title":{"type":"string"},"message":{"type":"string"}}}}}},"responses":{"200":{"description":"Test notification sent"}},"summary":"Send a test notification to a specific token","tags":["Tokens"]}},"/api/tokens/broadcast":{"post":{"operationId":"TokensController_broadcastNotification","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["title","message"],"properties":{"title":{"type":"string"},"message":{"type":"string"},"platform":{"type":"string","enum":["ios","android"]}}}}}},"responses":{"200":{"description":"Broadcast sent"}},"summary":"Broadcast notification to all tokens","tags":["Tokens"]}},"/api/ingresses":{"get":{"operationId":"IngressController_listForOrg","parameters":[],"responses":{"200":{"description":"List of ingresses"}},"summary":"List all ingresses in an org (with usage + channel)","tags":["Ingress"]}},"/api/channels/{channelId}/ingresses":{"get":{"operationId":"IngressController_list","parameters":[{"name":"channelId","required":true,"in":"path","description":"Channel ID","schema":{}}],"responses":{"200":{"description":"List of ingresses"}},"summary":"List a channel’s ingresses","tags":["Ingress"]},"post":{"operationId":"IngressController_create","parameters":[{"name":"channelId","required":true,"in":"path","description":"Channel ID","schema":{}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateIngressDto"}}}},"responses":{"201":{"description":"Ingress created"}},"summary":"Create an ingress on a channel","tags":["Ingress"]}},"/api/ingresses/{id}":{"patch":{"operationId":"IngressController_update","parameters":[{"name":"id","required":true,"in":"path","description":"Ingress ID","schema":{}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateIngressDto"}}}},"responses":{"200":{"description":"Ingress updated"}},"summary":"Update an ingress","tags":["Ingress"]},"delete":{"operationId":"IngressController_remove","parameters":[{"name":"id","required":true,"in":"path","description":"Ingress ID","schema":{}}],"responses":{"200":{"description":"Ingress deleted"}},"summary":"Delete an ingress","tags":["Ingress"]}},"/api/ingresses/{id}/repoint":{"post":{"operationId":"IngressController_repoint","parameters":[{"name":"id","required":true,"in":"path","description":"Ingress ID","schema":{}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RepointIngressDto"}}}},"responses":{"200":{"description":"Ingress re-pointed"}},"summary":"Re-point an ingress at a different channel","tags":["Ingress"]}},"/api/groups":{"get":{"operationId":"GroupsController_list","parameters":[],"responses":{"200":{"description":""}},"summary":"List groups in an org","tags":["Groups"]},"post":{"operationId":"GroupsController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateGroupDto"}}}},"responses":{"201":{"description":""}},"summary":"Create a group","tags":["Groups"]}},"/api/groups/{id}":{"get":{"operationId":"GroupsController_get","parameters":[{"name":"id","required":true,"in":"path","description":"Group ID","schema":{}}],"responses":{"200":{"description":""}},"summary":"Get a group","tags":["Groups"]},"patch":{"operationId":"GroupsController_update","parameters":[{"name":"id","required":true,"in":"path","description":"Group ID","schema":{}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateGroupDto"}}}},"responses":{"200":{"description":""}},"summary":"Update a group","tags":["Groups"]},"delete":{"operationId":"GroupsController_remove","parameters":[{"name":"id","required":true,"in":"path","description":"Group ID","schema":{}}],"responses":{"200":{"description":""}},"summary":"Delete a group","tags":["Groups"]}},"/api/groups/{id}/members":{"get":{"operationId":"GroupsController_listMembers","parameters":[{"name":"id","required":true,"in":"path","description":"Group ID","schema":{}}],"responses":{"200":{"description":""}},"summary":"List group members","tags":["Groups"]},"post":{"operationId":"GroupsController_addMember","parameters":[{"name":"id","required":true,"in":"path","description":"Group ID","schema":{}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddGroupMemberDto"}}}},"responses":{"201":{"description":""}},"summary":"Add a member to a group","tags":["Groups"]}},"/api/groups/{id}/members/{memberId}":{"delete":{"operationId":"GroupsController_removeMember","parameters":[{"name":"memberId","required":true,"in":"path","description":"Group member ID","schema":{}},{"name":"id","required":true,"in":"path","description":"Group ID","schema":{}}],"responses":{"200":{"description":""}},"summary":"Remove a member from a group","tags":["Groups"]}},"/api/channels/{channelId}/targets":{"get":{"operationId":"GroupsController_listTargets","parameters":[{"name":"channelId","required":true,"in":"path","description":"Channel ID","schema":{}}],"responses":{"200":{"description":""}},"summary":"List groups targeting a channel","tags":["Groups"]},"post":{"operationId":"GroupsController_attachTarget","parameters":[{"name":"channelId","required":true,"in":"path","description":"Channel ID","schema":{}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttachTargetDto"}}}},"responses":{"201":{"description":""}},"summary":"Attach a group to a channel","tags":["Groups"]}},"/api/channels/{channelId}/targets/{groupId}":{"delete":{"operationId":"GroupsController_detachTarget","parameters":[{"name":"channelId","required":true,"in":"path","description":"Channel ID","schema":{"type":"string"}},{"name":"groupId","required":true,"in":"path","description":"Group ID","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Detach a group from a channel","tags":["Groups"]}},"/api/notifications/preview":{"post":{"operationId":"NotificationsController_previewNotification","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendNotificationDto"}}}},"responses":{"201":{"description":"Normalized preview and audience"}},"summary":"Validate and preview a notification without sending it","tags":["Notifications"]}},"/api/notifications":{"post":{"operationId":"NotificationsController_sendNotification","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["channel","title","message"],"properties":{"channel":{"type":"string","description":"Channel ID or alias"},"title":{"type":"string"},"message":{"type":"string"},"priority":{"type":"string","enum":["low","normal","high","critical"],"default":"normal"},"data":{"type":"object","description":"Custom data payload"},"private":{"type":"boolean","description":"Encrypt notification content"},"imageUrl":{"type":"string","description":"Rich notification image"},"sender":{"type":"object","description":"Sender shown with the notification (name and circular avatar). Defaults to the channel's sender.","properties":{"name":{"type":"string","maxLength":100},"avatarUrl":{"type":"string","format":"uri","maxLength":512}}},"senderName":{"type":"string","deprecated":true,"description":"Deprecated: use sender.name"},"avatarUrl":{"type":"string","deprecated":true,"description":"Deprecated: use sender.avatarUrl"},"sound":{"type":"string","description":"Custom notification sound"},"badge":{"type":"number","description":"Badge count to set"},"actions":{"type":"object","description":"Notification actions"},"scheduledAt":{"type":"string","description":"ISO date for scheduled delivery"},"preset":{"type":"string","enum":["deploy-started","deploy-success","deploy-failed","incident","warning","approval-needed","reminder","progress"]},"idempotencyKey":{"type":"string","description":"Stable key that makes retries safe"}}}}}},"responses":{"201":{"description":"Notification sent/scheduled"},"429":{"description":"Usage limit exceeded"}},"summary":"Send a notification to a channel","tags":["Notifications"]},"get":{"operationId":"NotificationsController_listAllNotifications","parameters":[],"responses":{"200":{"description":"List of all notifications"}},"summary":"List all notifications","tags":["Notifications"]}},"/api/notifications/send-encrypted":{"post":{"operationId":"NotificationsController_sendEncrypted","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendEncryptedNotificationDto"}}}},"responses":{"201":{"description":"Encrypted notification sent"},"429":{"description":"Usage limit exceeded"}},"summary":"Send a per-device encrypted notification without exposing plaintext to the backend","tags":["Notifications"]}},"/api/notifications/sounds/list":{"get":{"operationId":"NotificationsController_getSystemSounds","parameters":[],"responses":{"200":{"description":"List of system sounds"}},"summary":"Get list of available system sounds","tags":["Notifications"]}},"/api/notifications/channel/{channelId}":{"get":{"operationId":"NotificationsController_getChannelNotifications","parameters":[{"name":"channelId","required":true,"in":"path","description":"Channel ID","schema":{}}],"responses":{"200":{"description":"List of notifications"}},"summary":"Get all notifications for a channel","tags":["Notifications"]}},"/api/notifications/{id}":{"get":{"operationId":"NotificationsController_getNotification","parameters":[{"name":"id","required":true,"in":"path","description":"Notification ID","schema":{}}],"responses":{"200":{"description":"Notification details"},"404":{"description":"Notification not found"}},"summary":"Get a notification by ID","tags":["Notifications"]}},"/api/notifications/{id}/interactions":{"get":{"operationId":"NotificationsController_getNotificationInteractions","parameters":[{"name":"id","required":true,"in":"path","description":"Notification ID","schema":{}}],"responses":{"200":{"description":"List of interactions"},"404":{"description":"Notification not found"}},"summary":"List interactions for a notification","tags":["Notifications"]}},"/api/notifications/interactions":{"post":{"operationId":"NotificationsController_trackInteraction","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["notificationId","userId","channelId","interactionType","platform"],"properties":{"notificationId":{"type":"string"},"userId":{"type":"string"},"channelId":{"type":"string"},"interactionType":{"type":"string","enum":["opened","dismissed","action_clicked","ui_element_interacted"]},"actionId":{"type":"string"},"elementId":{"type":"string"},"value":{},"platform":{"type":"string"},"deviceId":{"type":"string"},"signature":{"type":"object","properties":{"alg":{"type":"string"},"publicKey":{"type":"string"},"signature":{"type":"string"},"signedAt":{"type":"string"}}},"signatureStatus":{"type":"string","enum":["signed","unsigned"]},"signatureReason":{"type":"string"}}}}}},"responses":{"201":{"description":"Interaction tracked"}},"summary":"Track a notification interaction","tags":["Notifications"]}},"/api/channels/{idOrAlias}/notifications":{"post":{"description":"Supports JSON body or plain text. For open channels, no API key is needed.","operationId":"ChannelNotificationsController_sendToChannel","parameters":[{"name":"idOrAlias","required":true,"in":"path","description":"Channel UUID or alias","schema":{}}],"responses":{"201":{"description":"Notification sent"},"404":{"description":"Channel not found"},"429":{"description":"Rate/usage limit exceeded"}},"summary":"Send a notification to a channel by ID or alias","tags":["Channel Notifications"]}},"/send/{idOrAlias}":{"get":{"operationId":"SendController_describeLink","parameters":[{"name":"idOrAlias","required":true,"in":"path","description":"Channel link key (pt_link_…)","schema":{"type":"string"}}],"responses":{"200":{"description":"Usage instructions"},"401":{"description":"Link revoked or expired"},"404":{"description":"Not a channel link"}},"summary":"Describe a channel link (usage instructions for agents)","tags":["Send"]},"post":{"description":"Shorthand endpoint for sending notifications. Supports JSON body or plain text.","operationId":"SendController_sendPost","parameters":[{"name":"idOrAlias","required":true,"in":"path","description":"Channel UUID or alias","schema":{"type":"string"}}],"responses":{"201":{"description":"Notification sent"},"404":{"description":"Channel not found"},"429":{"description":"Rate/usage limit exceeded"}},"summary":"Send a notification to a channel (shorthand)","tags":["Send"]}},"/send/{idOrAlias}/{title}":{"get":{"description":"Simple GET-based endpoint for sending notifications. Title is in the URL path, message and other options via query params.","operationId":"SendController_sendGet","parameters":[{"name":"idOrAlias","required":true,"in":"path","description":"Channel UUID or alias","schema":{"type":"string"}},{"name":"title","required":true,"in":"path","description":"Notification title","schema":{"type":"string"}},{"name":"message","required":false,"in":"query","description":"Notification body text","schema":{"type":"string"}},{"name":"priority","required":false,"in":"query","description":"Notification priority","schema":{"type":"string"}},{"name":"imageUrl","required":false,"in":"query","description":"Image URL","schema":{"type":"string"}},{"name":"senderName","required":false,"in":"query","description":"Sender display name shown next to the avatar. Defaults to the channel's sender.","schema":{"type":"string"}},{"name":"avatarUrl","required":false,"in":"query","description":"Sender avatar URL (http/https), shown as a circle. Defaults to the channel's sender.","schema":{"type":"string"}},{"name":"sound","required":false,"in":"query","description":"Sound name","schema":{"type":"string"}}],"responses":{"200":{"description":"Notification sent"},"404":{"description":"Channel not found"},"429":{"description":"Rate/usage limit exceeded"}},"summary":"Send a notification via GET with title in URL","tags":["Send"]}},"/send/{idOrAlias}/live-activity":{"post":{"operationId":"SendController_upsertLiveActivity","parameters":[{"name":"idOrAlias","required":true,"in":"path","description":"Channel UUID or alias","schema":{"type":"string"}}],"responses":{"201":{"description":"Live Activity started/updated"},"403":{"description":"Live Activities not available on this tier"},"404":{"description":"Channel not found"}},"summary":"Start or update a Live Activity on a channel","tags":["Send"]},"delete":{"operationId":"SendController_endLiveActivity","parameters":[{"name":"idOrAlias","required":true,"in":"path","description":"Channel UUID or alias","schema":{"type":"string"}}],"responses":{"200":{"description":"Live Activity ended"},"403":{"description":"Live Activities not available on this tier"},"404":{"description":"Channel not found"}},"summary":"End a Live Activity on a channel","tags":["Send"]}},"/api/templates":{"get":{"operationId":"TemplatesController_getAllTemplates","parameters":[],"responses":{"200":{"description":""}},"tags":["Templates"]},"post":{"operationId":"TemplatesController_createTemplate","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTemplateDto"}}}},"responses":{"201":{"description":""}},"tags":["Templates"]}},"/api/templates/category/{category}":{"get":{"operationId":"TemplatesController_getTemplatesByCategory","parameters":[],"responses":{"200":{"description":""}},"tags":["Templates"]}},"/api/templates/{id}":{"get":{"operationId":"TemplatesController_getTemplate","parameters":[],"responses":{"200":{"description":""}},"tags":["Templates"]},"put":{"operationId":"TemplatesController_updateTemplate","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTemplateDto"}}}},"responses":{"200":{"description":""}},"tags":["Templates"]},"delete":{"operationId":"TemplatesController_deleteTemplate","parameters":[],"responses":{"200":{"description":""}},"tags":["Templates"]}},"/api/templates/{id}/apply":{"post":{"operationId":"TemplatesController_applyTemplate","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplyTemplateValuesDto"}}}},"responses":{"201":{"description":""}},"tags":["Templates"]}},"/api/billing/iap/apple/validate":{"post":{"operationId":"BillingController_validateAppleTransaction","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["signedTransaction"],"properties":{"signedTransaction":{"type":"string","description":"StoreKit 2 signed transaction (JWS)"}}}}}},"responses":{"200":{"description":"Transaction validated"},"400":{"description":"Invalid transaction"}},"summary":"Validate an Apple IAP transaction","tags":["Billing"]}},"/api/billing/iap/google/validate":{"post":{"operationId":"BillingController_validateGooglePurchase","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["purchaseToken","productId"],"properties":{"purchaseToken":{"type":"string"},"productId":{"type":"string"}}}}}},"responses":{"200":{"description":"Purchase validated"},"400":{"description":"Invalid purchase"}},"summary":"Validate a Google Play purchase","tags":["Billing"]}},"/api/billing/webhooks/apple":{"post":{"operationId":"BillingController_handleAppleWebhook","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppleWebhookDto"}}}},"responses":{"200":{"description":"Webhook processed"}},"summary":"Apple Server-to-Server V2 notification webhook","tags":["Billing"]}},"/api/billing/webhooks/google":{"post":{"operationId":"BillingController_handleGoogleWebhook","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleWebhookDto"}}}},"responses":{"200":{"description":"Webhook processed"}},"summary":"Google Real-Time Developer Notification webhook","tags":["Billing"]}},"/api/billing/subscription":{"get":{"operationId":"BillingController_getSubscription","parameters":[],"responses":{"200":{"description":"Subscription info"}},"summary":"Get current subscription and usage info","tags":["Billing"]}},"/api/billing/usage":{"get":{"operationId":"BillingController_getUsage","parameters":[],"responses":{"200":{"description":"Usage stats"}},"summary":"Get usage statistics","tags":["Billing"]}},"/api/connect/sessions":{"post":{"operationId":"ConnectController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateConnectSessionDto"}}}},"responses":{"201":{"description":"Pairing session created"}},"summary":"Start a pairing request (no auth; show pairingUrl as a QR code)","tags":["Connect"]}},"/api/connect/sessions/{id}/status":{"get":{"operationId":"ConnectController_status","parameters":[],"responses":{"200":{"description":"Session status"}},"summary":"Public progress of a pairing request (no secrets; for widgets)","tags":["Connect"]}},"/api/connect/sessions/{id}/poll":{"post":{"operationId":"ConnectController_poll","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PollConnectSessionDto"}}}},"responses":{"200":{"description":"Session status"}},"summary":"Poll a pairing request; returns the link once after approval","tags":["Connect"]}},"/api/connect/lookup":{"post":{"operationId":"ConnectController_lookup","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectSessionRefDto"}}}},"responses":{"200":{"description":"Request details"},"404":{"description":"Expired or already used"}},"summary":"Show what a pairing request asks for (app)","tags":["Connect"]}},"/api/connect/approve":{"post":{"operationId":"ConnectController_approve","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApproveConnectSessionDto"}}}},"responses":{"200":{"description":"Approved"}},"summary":"Approve a pairing request (app)","tags":["Connect"]}},"/api/connect/deny":{"post":{"operationId":"ConnectController_deny","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectSessionRefDto"}}}},"responses":{"200":{"description":"Denied"}},"summary":"Deny a pairing request (app)","tags":["Connect"]}}},"info":{"title":"PushTower API","description":"\n## Push Notification API\n\nPushTower is a push notification platform with end-to-end encryption support.\n\n### Authentication\nUse an API key in either the `X-API-Key` header or as a bearer token.\n\n```\nX-API-Key: pt_live_your_api_key_here\n```\n      ","version":"1.0","contact":{}},"tags":[{"name":"Notifications","description":"Preview and send push notifications"},{"name":"Channels","description":"Channel management"},{"name":"Live Activities","description":"iOS Live Activities"}],"servers":[],"components":{"securitySchemes":{"api-key":{"type":"apiKey","in":"header","name":"X-API-Key","description":"PushTower API key"},"bearer":{"scheme":"bearer","bearerFormat":"PushTower API key","type":"http"}},"schemas":{"DeleteAccountDto":{"type":"object","properties":{}},"CreateApiKeyDto":{"type":"object","properties":{}},"CreateChannelLinkDto":{"type":"object","properties":{}},"EnsureChannelDto":{"type":"object","properties":{}},"UpsertLiveActivityDto":{"type":"object","properties":{}},"RegisterPushToStartTokenDto":{"type":"object","properties":{}},"UpdateDeviceDto":{"type":"object","properties":{}},"RegisterTokenDto":{"type":"object","properties":{}},"CreateIngressDto":{"type":"object","properties":{}},"UpdateIngressDto":{"type":"object","properties":{}},"RepointIngressDto":{"type":"object","properties":{}},"CreateGroupDto":{"type":"object","properties":{}},"UpdateGroupDto":{"type":"object","properties":{}},"AddGroupMemberDto":{"type":"object","properties":{}},"AttachTargetDto":{"type":"object","properties":{}},"SendNotificationDto":{"type":"object","properties":{}},"SendEncryptedNotificationDto":{"type":"object","properties":{}},"CreateTemplateDto":{"type":"object","properties":{}},"UpdateTemplateDto":{"type":"object","properties":{}},"ApplyTemplateValuesDto":{"type":"object","properties":{}},"AppleWebhookDto":{"type":"object","properties":{}},"GoogleWebhookDto":{"type":"object","properties":{}},"CreateConnectSessionDto":{"type":"object","properties":{}},"PollConnectSessionDto":{"type":"object","properties":{}},"ConnectSessionRefDto":{"type":"object","properties":{}},"ApproveConnectSessionDto":{"type":"object","properties":{}}}}}