{"openapi":"3.1.0","info":{"title":"Zygnal API","version":"0.1.0","description":"Internal API for the Zygnal signal-to-action platform"},"servers":[{"url":"https://api.signalraven.ai","description":"Production"},{"url":"http://localhost:3000","description":"Local dev"}],"tags":[{"name":"public","description":"No auth required"},{"name":"me","description":"Authenticated as customer"},{"name":"admin","description":"Authenticated as admin"},{"name":"v1","description":"Customer API v1 — OAuth-gated, workspace-scoped (api.signalraven.ai/api/v1)"}],"paths":{"/api/v1/register":{"post":{"operationId":"registerClient","tags":["v1"],"summary":"Register an OAuth/MCP client (identity-gated)","description":"Public + rate-limited. Requires a contact email + LinkedIn. Returns client credentials once; the client is pending platform approval (data endpoints return sample data until approved).","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1RegisterBody"}}}},"responses":{"201":{"description":"Client registered (pending approval)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1RegisterResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/signals":{"get":{"operationId":"v1ListSignals","tags":["v1"],"summary":"List signals","security":[{"bearerAuth":[]}],"parameters":[{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":100}},{"in":"query","name":"offset","schema":{"type":"integer","minimum":0,"maximum":9007199254740991}},{"in":"query","name":"type","schema":{"type":"string"}},{"in":"query","name":"minStrength","schema":{"type":"integer","minimum":0,"maximum":10}}],"responses":{"200":{"description":"Signals (live or sample per client approval)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1SignalsResponse"}}}},"401":{"description":"Missing/invalid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope or no workspace","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/signals/{id}":{"get":{"operationId":"v1GetSignal","tags":["v1"],"summary":"Get a signal by id","security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string"},"required":true}],"responses":{"200":{"description":"Signal","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1SignalResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/sources":{"get":{"operationId":"v1ListSources","tags":["v1"],"summary":"List sources with metrics","security":[{"bearerAuth":[]}],"parameters":[{"in":"query","name":"period","schema":{"type":"string","enum":["7","30","all"]}}],"responses":{"200":{"description":"Sources","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1SourcesResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/watchlist":{"get":{"operationId":"v1GetWatchlist","tags":["v1"],"summary":"List watchlist posts","security":[{"bearerAuth":[]}],"parameters":[{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":100}},{"in":"query","name":"offset","schema":{"type":"integer","minimum":0,"maximum":9007199254740991}}],"responses":{"200":{"description":"Watchlist posts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1WatchlistResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/icp":{"get":{"operationId":"v1GetIcp","tags":["v1"],"summary":"Get the workspace ICP profile","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"ICP profile","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1IcpResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No ICP profile","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/health":{"get":{"operationId":"healthCheck","tags":["public"],"summary":"Health check","responses":{"200":{"description":"Service is healthy","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}}}}},"/api/me":{"get":{"operationId":"getMe","tags":["me"],"summary":"Get current authenticated user and signup state","responses":{"200":{"description":"Current user info","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeResponse"}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/provisioning-status":{"get":{"operationId":"getProvisioningStatus","tags":["me"],"summary":"Coarse 5-step progress view for the customer setup pipeline","description":"Polled by the portal during onboarding_running and awaiting_admin_icp_review phases. Auth: requireUser (works pre-active). Returns a ProvisioningStatus describing which step the customer is on and which are complete.","responses":{"200":{"description":"Current provisioning status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProvisioningStatus"}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No customer linked yet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/icp":{"get":{"operationId":"getMeIcp","tags":["me"],"summary":"Get the customer's default ICP profile","responses":{"200":{"description":"Default ICP profile","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeIcpResponse"}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Customer not active or not provisioned","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No default ICP profile","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"updateMeIcp","tags":["me"],"summary":"Update the customer's default ICP profile","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMeIcpBody"}}}},"responses":{"200":{"description":"Updated ICP","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeIcpResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No default ICP profile","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/icp/reset":{"post":{"operationId":"resetMeIcp","tags":["me"],"summary":"Restore ICP fields to AI-generated draft","description":"Copies the onboarding-time draft_snapshot back over the live ICP row, preserving id/customer_id/name/is_default/created_at. Writes an icp.reset audit event with before/after diffs. Returns 404 NoIcp when no default ICP exists, or 409 NoDraft when the profile has no snapshot on file (pre-existing customers or manual admin creates). Use the resettable flag on GET /api/me/icp to gate the UI button.","responses":{"200":{"description":"ICP restored from draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeIcpResponse"}}}},"404":{"description":"No default ICP profile","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"No AI draft on file for this ICP","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/sources":{"get":{"operationId":"listMeSources","tags":["me"],"summary":"List all sources for the customer (active + paused) with aggregate stats","parameters":[{"name":"period","in":"query","required":false,"description":"Window for stats aggregations: '7' / '30' / 'all' (default '30')","schema":{"type":"string","enum":["7","30","all"]}}],"responses":{"200":{"description":"Source list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeSourceListResponse"}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Customer not active or not provisioned","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createMeSource","tags":["me"],"summary":"Add a source — fires immediate one-shot DISCOVERY","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSourceBody"}}}},"responses":{"201":{"description":"Created source","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Source"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Source with this LinkedIn URL already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/sources/bulk":{"post":{"operationId":"createMeSourcesBulk","tags":["me"],"summary":"Bulk-create target_person sources (best-effort per-row)","description":"Per-row best-effort batch create. 100-input cap. Each input is normalized via the LinkedIn profile URL helper before in-batch dedup and existing-URL check. Returns 200 with both created[] and skipped[] populated — caller checks `created.length` to know what happened. Skipped reasons: invalid_format | duplicate | already_active | cap_exceeded.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sourceType":{"type":"string","const":"target_person"},"inputs":{"minItems":1,"maxItems":100,"type":"array","items":{"type":"string"}},"displayName":{"type":"string","maxLength":255}},"required":["sourceType","inputs"]}}}},"responses":{"200":{"description":"Per-row results","content":{"application/json":{"schema":{"type":"object","properties":{"created":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"linkedinUrl":{"type":"string"},"displayName":{"type":"string"}},"required":["id","linkedinUrl","displayName"],"additionalProperties":false}},"skipped":{"type":"array","items":{"type":"object","properties":{"input":{"type":"string"},"normalized":{"type":"string"},"reason":{"type":"string","enum":["duplicate","cap_exceeded","invalid_format","already_active"]}},"required":["input","reason"],"additionalProperties":false}}},"required":["created","skipped"],"additionalProperties":false}}}},"400":{"description":"Validation error or too_many_inputs (>100)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient role (requires admin or manager)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/sources/{id}":{"get":{"operationId":"getMeSource","tags":["me"],"summary":"Get a single source (404 if not yours)","parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Source detail with score distribution","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceWithStats"}}}},"404":{"description":"Source not found or not owned by customer","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"updateMeSource","tags":["me"],"summary":"Update a source (display name, pause, resume, etc.)","parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSourceBody"}}}},"responses":{"200":{"description":"Updated source","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Source"}}}},"404":{"description":"Source not found or not owned by customer","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deleteMeSource","tags":["me"],"summary":"Soft-delete a source (sets isActive=false)","parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"204":{"description":"Deactivated"},"404":{"description":"Source not found or not owned by customer","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/destinations":{"get":{"operationId":"listMeDestinations","tags":["me"],"summary":"List delivery destinations for the customer","responses":{"200":{"description":"Destination list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeDestinationListResponse"}}}}}},"post":{"operationId":"createMeDestination","tags":["me"],"summary":"Create a destination","description":"Customer-side modal supports slack, google_sheet, webhook, notion, n8n, clay_webhook. See CreateMeDestinationSchema for the allow-list.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateMeDestinationBody"}}}},"responses":{"201":{"description":"Created destination","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Destination"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/destinations/{id}":{"patch":{"operationId":"updateMeDestination","tags":["me"],"summary":"Update a destination","parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDestinationBody"}}}},"responses":{"200":{"description":"Updated destination","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Destination"}}}},"404":{"description":"Destination not found or not owned by customer","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deleteMeDestination","tags":["me"],"summary":"Soft-delete a destination","parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"204":{"description":"Deactivated"},"404":{"description":"Destination not found or not owned by customer","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/destinations/{id}/test":{"post":{"operationId":"testMeDestination","tags":["me"],"summary":"Send a sample signal through a destination (no activation record)","parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Test result (success or error)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestDestinationResponse"}}}},"404":{"description":"Destination not found or not owned by customer","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/destinations/google-sheet/service-account":{"get":{"operationId":"getMeGoogleSheetServiceAccount","tags":["me"],"summary":"Service-account email customers share their sheet with","description":"Per-env (dev / staging / prod each have their own service account). The portal's Sheets add flow fetches this to render a copyable \"share your sheet with this email as Editor\" callout, since the email differs between environments and shouldn't be hardcoded in the portal build.","responses":{"200":{"description":"Service account email","content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string"}},"required":["email"],"additionalProperties":false}}}},"503":{"description":"Sheets delivery not configured on this environment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/destinations/slack/oauth/start":{"post":{"operationId":"startMeSlackOauth","tags":["me"],"summary":"Begin the Slack Connect flow","description":"Mints a 10-min state JWT scoped to the calling customer and returns Slack's authorize URL with the state embedded. The portal redirects the browser to authorizeUrl. After the customer approves, Slack hits GET /api/destinations/slack/oauth/callback which verifies the state, exchanges the code, and creates the destination.","responses":{"200":{"description":"Authorize URL ready","content":{"application/json":{"schema":{"type":"object","properties":{"authorizeUrl":{"type":"string","format":"uri"}},"required":["authorizeUrl"],"additionalProperties":false}}}},"503":{"description":"Slack OAuth not configured on this environment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/destinations/{id}/rotate-secret":{"post":{"operationId":"rotateMeDestinationSecret","tags":["me"],"summary":"Generate a new HMAC signature secret for a destination","description":"One-time-reveal rotation. The old secret stops working immediately; customers must re-paste the returned value into their webhook verifier.","parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"New secret generated","content":{"application/json":{"schema":{"type":"object","properties":{"signatureSecret":{"type":"string"}},"required":["signatureSecret"],"additionalProperties":false}}}},"404":{"description":"Destination not found or not owned by customer","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/destinations/notion/probe":{"post":{"operationId":"probeMeNotionDatabase","tags":["me"],"summary":"Enumerate a Notion database's properties for the create-flow mapping UI","description":"Customer pastes their Notion integration token + database ID into the destination-create modal; the portal calls this endpoint to fetch the database's property names + types. Does not create a destination — the customer reviews the auto-detected mapping, edits it, then submits the full create body via POST /api/me/destinations.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"integrationToken":{"type":"string","minLength":1},"databaseId":{"type":"string","minLength":1}},"required":["integrationToken","databaseId"]}}}},"responses":{"200":{"description":"Properties enumerated successfully","content":{"application/json":{"schema":{"type":"object","properties":{"properties":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string","description":"Notion property type: title | rich_text | number | url | select | multi_select | date | …"}},"required":["name","type"],"additionalProperties":false}}},"required":["properties"],"additionalProperties":false}}}},"401":{"description":"Notion token invalid or integration not shared with the database","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Notion database ID not found or not shared with the integration","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Notion API call failed for any other reason","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/sources/{id}/posts":{"get":{"operationId":"listMeSourcePosts","tags":["me"],"summary":"Active watched posts attributed to a source (closed posts excluded per spec §9.5)","parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true},{"in":"query","name":"limit","schema":{"type":"string","pattern":"^\\d+$"}},{"in":"query","name":"offset","schema":{"type":"string","pattern":"^\\d+$"}},{"in":"query","name":"lifecycleStatus","schema":{"description":"qualified | harvesting","type":"string"},"description":"qualified | harvesting"}],"responses":{"200":{"description":"Active watched posts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeWatchedPostListResponse"}}}},"404":{"description":"Source not found or not owned by customer","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/sources/{id}/signals":{"get":{"operationId":"listMeSourceSignals","tags":["me"],"summary":"Signals attributed to a source (joined via watched_posts.source_id)","parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true},{"in":"query","name":"limit","schema":{"type":"string","pattern":"^\\d+$"}},{"in":"query","name":"offset","schema":{"type":"string","pattern":"^\\d+$"}}],"responses":{"200":{"description":"Signals from this source","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeSourceSignalsResponse"}}}},"404":{"description":"Source not found or not owned by customer","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/destinations/{id}/deliveries":{"get":{"operationId":"listMeDestinationDeliveries","tags":["me"],"summary":"Recent activation records for a destination, joined with the originating signal","parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true},{"in":"query","name":"limit","schema":{"type":"string","pattern":"^\\d+$"}},{"in":"query","name":"offset","schema":{"type":"string","pattern":"^\\d+$"}}],"responses":{"200":{"description":"Delivery list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeDeliveryListResponse"}}}},"404":{"description":"Destination not found or not owned by customer","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/watchlist":{"get":{"operationId":"listMeWatchlist","tags":["me"],"summary":"Active watched posts (closed posts NEVER returned per spec §9.5)","description":"is_active=true is hard-coded. Optional `status` query narrows on lifecycle_status (qualified | harvesting | max_harvests).","parameters":[{"in":"query","name":"status","schema":{"type":"string"}},{"in":"query","name":"source","schema":{"description":"Source ID filter (single source UUID)","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"Source ID filter (single source UUID)"},{"in":"query","name":"sourceType","schema":{"description":"Filter to all sources of this type (e.g. \"keyword_search\"). Mutually exclusive with `source` in practice.","type":"string"},"description":"Filter to all sources of this type (e.g. \"keyword_search\"). Mutually exclusive with `source` in practice."},{"in":"query","name":"days","schema":{"type":"string","pattern":"^\\d+$"}},{"in":"query","name":"limit","schema":{"type":"string","pattern":"^\\d+$"}},{"in":"query","name":"offset","schema":{"type":"string","pattern":"^\\d+$"}},{"in":"query","name":"sortBy","schema":{"description":"Server-side sort column. Default createdAt.","type":"string","enum":["likes","comments","postedAt","createdAt","expiresAt"]},"description":"Server-side sort column. Default createdAt."},{"in":"query","name":"sortDir","schema":{"description":"Sort direction. Default desc.","type":"string","enum":["asc","desc"]},"description":"Sort direction. Default desc."}],"responses":{"200":{"description":"Watchlist","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeWatchedPostListResponse"}}}}}}},"/api/me/activity":{"get":{"operationId":"listMeActivity","tags":["me"],"summary":"Sanitized pipeline activity feed for the customer","description":"Translates internal pipeline_logs into customer-facing strings. Filters out errors, budget warnings, internal pre-screen / ICP-gate-rejection details, raw job IDs, Apify run IDs.","parameters":[{"in":"query","name":"category","schema":{"type":"string","enum":["discovery","harvest","enrichment","icp","delivery"]}},{"in":"query","name":"source","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"in":"query","name":"days","schema":{"description":"Look back 1-30 days (default 1)","type":"string","pattern":"^\\d+$"},"description":"Look back 1-30 days (default 1)"},{"in":"query","name":"limit","schema":{"type":"string","pattern":"^\\d+$"}}],"responses":{"200":{"description":"Activity events","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeActivityResponse"}}}}}}},"/api/me/usage":{"get":{"operationId":"getMeUsage","tags":["me"],"summary":"Activity counts only — NO dollar figures (pricing TBD)","description":"Per spec §6.11 + §9.11. Returns banner=beta so portal shows the placeholder banner. signalsThisMonth/signalsLastMonth use calendar month boundaries (UTC).","responses":{"200":{"description":"Usage","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Usage"}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Customer not active or not provisioned","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/credits/summary":{"get":{"operationId":"getMeCreditsSummary","tags":["me"],"summary":"Credit balance, per-Bundle burn, add-on packs, projected exhaustion","description":"Customer-facing credit dashboard data. 5-min Redis cache + 5-min Cache-Control (private). Bundle breakdown sums credits charged per Bundle 1-4 for the current period (or last 30d for Trial without a period). Projected-exhaustion is null when no burn yet OR forecast date is past period_end.","responses":{"200":{"description":"Credit summary","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditSummary"}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Customer not active","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/billing/invoices":{"get":{"operationId":"listMeBillingInvoices","tags":["me"],"summary":"Last N paid Stripe invoices for the customer","description":"Admin-only. Proxies stripe.invoices.list (status=paid). Each row carries the Stripe-hosted view URL + direct PDF URL — both gated by the URL token itself, no portal auth needed for click-through.","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"string"},"description":"Default 12, max 50."}],"responses":{"200":{"description":"Invoice list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingInvoicesResponse"}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/billing/payg-purchases":{"get":{"operationId":"listMeBillingPaygPurchases","tags":["me"],"summary":"PAYG add-on credit-pack purchase history","description":"Admin-only. Sibling to /api/me/billing/invoices for the one-off add-on credit-pack flow. Admin-granted packs excluded. Includes refund status derived from credit_transactions.","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"string"},"description":"Default 12, max 50."}],"responses":{"200":{"description":"PAYG purchase list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaygPurchasesResponse"}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/plan":{"get":{"operationId":"getMePlan","tags":["me"],"summary":"Current plan with all gate flags consumed by useMePlan hook","description":"Returns the customer's plan slug, economics, caps, and feature flags (signalStacking, icpEditing, paygEnabled, etc.). Includes derived isInternal flag + stripeCustomerId for portal Stripe-management UX gating. 5-min Cache-Control private.","responses":{"200":{"description":"Current plan","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MePlan"}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Customer not active","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Customer missing plan_id (migration anomaly)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/plan/cancel-to-trial":{"post":{"operationId":"postMePlanCancelToTrial","tags":["me"],"summary":"Schedule a downgrade to Trial at the end of the current billing period (admin only)","description":"Admin-only Zygnal-side cancel path since Stripe Customer Portal does not list Trial in the plan picker. Schedules the Stripe subscription for cancel-at-period-end and tags subscription.metadata.downgrade_target='trial' so the eventual subscription.deleted webhook flips planId to Trial. Existing credit balance is preserved until period_end (then wiped by the local-expiry cron). No future Trial allotments are granted. PAYG packs survive untouched at their original rate. Idempotent — repeat calls return 409 already_scheduled.","responses":{"200":{"description":"Cancel-to-Trial scheduled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelToTrialResponse"}}}},"403":{"description":"Caller role is not admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Customer not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"No active subscription, OR already scheduled to downgrade","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Stripe API call failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/public/plans":{"get":{"operationId":"getPublicPlans","tags":["public"],"summary":"Public plan catalog for marketing site (Solo/Pro/Scale only)","description":"No auth required. Returns is_customer_selectable=true plans only — excludes Trial (signup-only) and Internal (admin-only) per design §3.1. 5-min CDN-friendly Cache-Control (public + s-maxage).","responses":{"200":{"description":"Public plans","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicPlansResponse"}}}}}}},"/api/me/account/sessions":{"get":{"operationId":"listMeAccountSessions","tags":["me"],"summary":"List the last 5 sessions for the authenticated user","description":"Auth: requireUser only (works for non-active customers too — needed on the account/security page regardless of state). isCurrent flag is set from the JWT jti.","responses":{"200":{"description":"Session list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionListResponse"}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/account/sessions/revoke-all":{"post":{"operationId":"revokeAllMeSessions","tags":["me"],"summary":"Sign out of every device — revokes all of this user's sessions including the current one","description":"The calling session is also revoked, so the next request will fail auth. Portal should treat 200 as \"redirect to /signin\". Audit: session.revoked_all.","responses":{"200":{"description":"Revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevokeAllResponse"}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/dashboard/overview":{"get":{"operationId":"getMeDashboardOverview","tags":["me"],"summary":"Customer-scoped dashboard KPIs over a rolling N-day window (default 7)","parameters":[{"in":"query","name":"days","schema":{"description":"Window size 1-90 (default 7)","type":"string","pattern":"^\\d+$"},"description":"Window size 1-90 (default 7)"}],"responses":{"200":{"description":"Dashboard overview","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DashboardOverview"}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Customer not active or not provisioned","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/signals":{"get":{"operationId":"listMeSignals","tags":["me"],"summary":"List signals for the customer with filters + pagination","description":"customerId in query is IGNORED — server uses req.customer.id. Filters are AND-combined.","parameters":[{"in":"query","name":"type","schema":{"type":"string"}},{"in":"query","name":"kind","schema":{"description":"Coarse engagement-kind filter (reaction | comment).","type":"string","enum":["reaction","comment"]},"description":"Coarse engagement-kind filter (reaction | comment)."},{"in":"query","name":"minScore","schema":{"description":"Minimum strength 1-10","type":"string","pattern":"^\\d+$"},"description":"Minimum strength 1-10"},{"in":"query","name":"minIcp","schema":{"description":"Minimum composite ICP percentage 0-100, inclusive. Excludes signals without a composite score.","type":"string","pattern":"^\\d+$"},"description":"Minimum composite ICP percentage 0-100, inclusive. Excludes signals without a composite score."},{"in":"query","name":"classification","schema":{"description":"Buyer-classification filter (plan 2026-08-28). Reads COALESCE(metadata, icp_analysis)->>'buyerClassification'; 'buyer' also matches unclassified rows (server treats NULL as buyer).","type":"string","enum":["buyer","influencer"]},"description":"Buyer-classification filter (plan 2026-08-28). Reads COALESCE(metadata, icp_analysis)->>'buyerClassification'; 'buyer' also matches unclassified rows (server treats NULL as buyer)."},{"in":"query","name":"days","schema":{"description":"Look back N days","type":"string","pattern":"^\\d+$"},"description":"Look back N days"},{"in":"query","name":"source","schema":{"description":"Source ID filter (single source UUID)","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"Source ID filter (single source UUID)"},{"in":"query","name":"sourceType","schema":{"description":"Filter to all sources of this type (own_company, competitor_company, …).","type":"string"},"description":"Filter to all sources of this type (own_company, competitor_company, …)."},{"in":"query","name":"persona","schema":{"description":"Substring of icp_analysis.persona","type":"string"},"description":"Substring of icp_analysis.persona"},{"in":"query","name":"industry","schema":{"description":"Substring of company industry","type":"string"},"description":"Substring of company industry"},{"in":"query","name":"search","schema":{"description":"Free-text search across name/company/context/post","type":"string"},"description":"Free-text search across name/company/context/post"},{"in":"query","name":"company","schema":{"description":"Company key (LinkedIn URL or lowercased name) to filter signals to a single company.","type":"string"},"description":"Company key (LinkedIn URL or lowercased name) to filter signals to a single company."},{"in":"query","name":"view","schema":{"description":"Per-user archive filter. active (default) hides signals this user has archived; archived shows only those; all shows both.","type":"string","enum":["active","archived","all"]},"description":"Per-user archive filter. active (default) hides signals this user has archived; archived shows only those; all shows both."},{"in":"query","name":"tags","schema":{"description":"Packed tag filter: `<catId>:<tok>|<tok>,<catId2>:<tok>` where tok = value UUID | `!`UUID (exclude) | `none` (untagged in category) | `any` (tagged in category). OR within a group, AND across groups.","type":"string"},"description":"Packed tag filter: `<catId>:<tok>|<tok>,<catId2>:<tok>` where tok = value UUID | `!`UUID (exclude) | `none` (untagged in category) | `any` (tagged in category). OR within a group, AND across groups."},{"in":"query","name":"limit","schema":{"type":"string","pattern":"^\\d+$"}},{"in":"query","name":"offset","schema":{"type":"string","pattern":"^\\d+$"}}],"responses":{"200":{"description":"Paginated signals","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeSignalListResponse"}}}}}}},"/api/me/signals/tag-facets":{"get":{"operationId":"getMeSignalTagFacets","tags":["me"],"summary":"Per-category tag facet counts under the current filters","description":"Same filter params as the signals list. Per category, counts are computed with that category's own tag group EXCLUDED (classic faceting), plus a noneCount of untagged signals.","parameters":[{"in":"query","name":"type","schema":{"type":"string"}},{"in":"query","name":"kind","schema":{"type":"string","enum":["reaction","comment"]}},{"in":"query","name":"minScore","schema":{"type":"string","pattern":"^\\d+$"}},{"in":"query","name":"minIcp","schema":{"type":"string","pattern":"^\\d+$"}},{"in":"query","name":"classification","schema":{"type":"string","enum":["buyer","influencer"]}},{"in":"query","name":"days","schema":{"type":"string","pattern":"^\\d+$"}},{"in":"query","name":"source","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"in":"query","name":"sourceType","schema":{"type":"string"}},{"in":"query","name":"persona","schema":{"type":"string"}},{"in":"query","name":"industry","schema":{"type":"string"}},{"in":"query","name":"search","schema":{"type":"string"}},{"in":"query","name":"company","schema":{"type":"string"}},{"in":"query","name":"view","schema":{"type":"string","enum":["active","archived","all"]}},{"in":"query","name":"tags","schema":{"description":"Packed tag filter: `<catId>:<tok>|<tok>,<catId2>:<tok>` where tok = value UUID | `!`UUID (exclude) | `none` (untagged in category) | `any` (tagged in category). OR within a group, AND across groups.","type":"string"},"description":"Packed tag filter: `<catId>:<tok>|<tok>,<catId2>:<tok>` where tok = value UUID | `!`UUID (exclude) | `none` (untagged in category) | `any` (tagged in category). OR within a group, AND across groups."}],"responses":{"200":{"description":"Facet counts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagFacetsResponse"}}}}}}},"/api/me/tag-categories":{"get":{"operationId":"listMeTagCategories","tags":["me"],"summary":"List tag categories with values + usage counts","responses":{"200":{"description":"Categories","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeTagCategoryListResponse"}}}}}},"post":{"operationId":"createMeTagCategory","tags":["me"],"summary":"Create a tag category (admin/manager)","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":50},"selectionMode":{"default":"single","$ref":"#/components/schemas/TagSelectionMode"}},"required":["name"]}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagCategory"}}}},"409":{"description":"Duplicate name or category cap reached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/tag-categories/{id}":{"patch":{"operationId":"updateMeTagCategory","tags":["me"],"summary":"Rename a category or relax single→multi (admin/manager)","parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":50},"selectionMode":{"description":"single→multi is allowed; multi→single is rejected 409 in v1 (delete and recreate instead).","$ref":"#/components/schemas/TagSelectionMode"}}}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagCategoryCore"}}}},"409":{"description":"Duplicate name or multi→single rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deleteMeTagCategory","tags":["me"],"summary":"Delete a category (cascades values + applications; admin/manager)","parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"204":{"description":"Deleted"},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/tag-categories/{id}/values":{"post":{"operationId":"createMeTagValue","tags":["me"],"summary":"Add a value to a category (admin/manager)","parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":50}},"required":["name"]}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagValue"}}}},"409":{"description":"Duplicate name or value cap reached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/tag-categories/{id}/values/{valueId}":{"patch":{"operationId":"updateMeTagValue","tags":["me"],"summary":"Rename a value (admin/manager)","parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true},{"in":"path","name":"valueId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":50}},"required":["name"]}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagValueCore"}}}},"409":{"description":"Duplicate name","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deleteMeTagValue","tags":["me"],"summary":"Delete a value (removes it from all signals; admin/manager)","parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true},{"in":"path","name":"valueId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"204":{"description":"Deleted"},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/signals/{id}/tags":{"post":{"operationId":"applyMeSignalTag","tags":["me"],"summary":"Apply a tag value to a signal (any member role)","description":"Single-mode categories REPLACE any existing value atomically. Returns the full post-apply tag list.","parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"valueId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["valueId"]}}}},"responses":{"200":{"description":"Applied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignalTagsResponse"}}}},"404":{"description":"Signal or value not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/signals/{id}/tags/{valueId}":{"delete":{"operationId":"removeMeSignalTag","tags":["me"],"summary":"Remove a tag value from a signal (any member role; idempotent)","parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true},{"in":"path","name":"valueId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Removed (or was absent)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignalTagsResponse"}}}},"404":{"description":"Signal not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/signals/companies":{"get":{"operationId":"listMeSignalsByCompany","tags":["me"],"summary":"List signals grouped by company with aggregates","description":"Same filters as /api/me/signals but returns one row per company with signal count, person count, avg ICP, top persona, and latest signal date. Available to all plans.","parameters":[{"in":"query","name":"type","schema":{"type":"string"}},{"in":"query","name":"kind","schema":{"type":"string","enum":["reaction","comment"]}},{"in":"query","name":"minScore","schema":{"type":"string","pattern":"^\\d+$"}},{"in":"query","name":"minIcp","schema":{"type":"string","pattern":"^\\d+$"}},{"in":"query","name":"classification","schema":{"type":"string","enum":["buyer","influencer"]}},{"in":"query","name":"days","schema":{"type":"string","pattern":"^\\d+$"}},{"in":"query","name":"source","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"in":"query","name":"sourceType","schema":{"type":"string"}},{"in":"query","name":"persona","schema":{"type":"string"}},{"in":"query","name":"industry","schema":{"type":"string"}},{"in":"query","name":"search","schema":{"type":"string"}},{"in":"query","name":"company","schema":{"description":"Filter to a single company key (enriched LinkedIn URL or lowered name). Matches either form. Used by /signals/company/:companyKey to fetch the aggregate enrichment row.","type":"string"},"description":"Filter to a single company key (enriched LinkedIn URL or lowered name). Matches either form. Used by /signals/company/:companyKey to fetch the aggregate enrichment row."},{"in":"query","name":"limit","schema":{"type":"string","pattern":"^\\d+$"}},{"in":"query","name":"offset","schema":{"type":"string","pattern":"^\\d+$"}},{"in":"query","name":"tags","schema":{"description":"Packed tag filter: `<catId>:<tok>|<tok>,<catId2>:<tok>` where tok = value UUID | `!`UUID (exclude) | `none` (untagged in category) | `any` (tagged in category). OR within a group, AND across groups.","type":"string"},"description":"Packed tag filter: `<catId>:<tok>|<tok>,<catId2>:<tok>` where tok = value UUID | `!`UUID (exclude) | `none` (untagged in category) | `any` (tagged in category). OR within a group, AND across groups."},{"in":"query","name":"sortBy","schema":{"description":"Sort key for the company list. Default: signalCount.","type":"string","enum":["signalCount","latestSignalAt","employeeCount","companyName"]},"description":"Sort key for the company list. Default: signalCount."},{"in":"query","name":"sortDir","schema":{"description":"Sort direction. Default: desc.","type":"string","enum":["asc","desc"]},"description":"Sort direction. Default: desc."}],"responses":{"200":{"description":"Paginated company-grouped signals","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeCompaniesListResponse"}}}}}}},"/api/me/signals/{id}":{"get":{"operationId":"getMeSignal","tags":["me"],"summary":"Signal detail with pipeline result, source post, and delivery info","parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Signal detail","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeSignalDetail"}}}},"404":{"description":"Signal not found or not owned by customer","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/signals/{id}/related":{"get":{"operationId":"getMeSignalRelated","tags":["me"],"summary":"Other signals from the same company in the last 30 days","parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Related signals","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RelatedSignalsResponse"}}}},"404":{"description":"Signal not found or not owned by customer","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/signals/{id}/deliver":{"post":{"operationId":"deliverMeSignal","tags":["me"],"summary":"Manually send a signal to a destination","description":"Powers the portal's \"Send to {destination}\" button on the signal detail page. Bypasses the destination's routing mode (manual destinations are only reachable this way) but respects isActive — paused destinations return 422. Idempotent on (signal_id, destination_id): repeat calls return the existing activation rather than enqueueing a duplicate.","parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"destinationId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["destinationId"]}}}},"responses":{"200":{"description":"Activation created or already existed","content":{"application/json":{"schema":{"type":"object","properties":{"activationId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"queued":{"type":"boolean","description":"true when a new delivery job was enqueued; false when an activation already existed (idempotent no-op)."},"destinationName":{"type":"string"}},"required":["activationId","queued","destinationName"],"additionalProperties":false}}}},"404":{"description":"Signal or destination not found / not owned by customer","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Destination is paused (isActive=false)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/signals/{id}/archive":{"post":{"operationId":"archiveMeSignal","tags":["me"],"summary":"Archive a signal (per-user, non-destructive)","description":"Per-user archive — hides the signal from the current user's Active view without affecting other team members. Idempotent — re-archiving is a no-op. Backlog #51 Archive MVP.","parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Archived (or already archived)","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":true}},"required":["ok"],"additionalProperties":false}}}},"404":{"description":"Signal not found or not owned by customer","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"unarchiveMeSignal","tags":["me"],"summary":"Restore a previously archived signal","description":"Reverse of POST — removes the per-user archive row. Idempotent — deleting a non-existent row is a no-op.","parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Restored (or already active)","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":true}},"required":["ok"],"additionalProperties":false}}}},"404":{"description":"Signal not found or not owned by customer","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/setup/activate":{"post":{"operationId":"activateMe","tags":["me"],"summary":"Final step of setup wizard — flips lifecycle to active and kicks discovery","description":"Validates ≥1 active source + ICP profile exists. Destinations are NOT a prerequisite — customers configure them post-activation from /destinations; signals accumulate undelivered until then. Sets self-serve defaults (autoHarvest=true, dailyBudgetCapCents=$50). Enqueues immediate DISCOVERY for each active source. Audit: lifecycle.activated.","responses":{"200":{"description":"Activated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivateResponse"}}}},"400":{"description":"Missing prerequisite (NoActiveSources/NoIcp)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Already activated (wrong lifecyclePhase)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/team":{"get":{"operationId":"listMeTeam","tags":["me"],"summary":"List team members + pending invites for the current customer","description":"All roles can read. Returns current customer_users rows alongside pending (non-accepted, non-expired) invites.","responses":{"200":{"description":"Team listing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamListResponse"}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/team/invite":{"post":{"operationId":"inviteTeamMember","tags":["me"],"summary":"Send an invitation email to a new teammate (admin + manager)","description":"Force-reinvites by canceling any prior pending invite for the same (customer, email). Manager cannot grant admin role; CHECK constraint at the DB + Zod enum here enforce role ∈ {user, manager}.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InviteBody"}}}},"responses":{"201":{"description":"Invite created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InviteResponse"}}}},"400":{"description":"Validation error / invalid email","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient role (user-role denied)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/team/invites/{inviteId}":{"delete":{"operationId":"cancelTeamInvite","tags":["me"],"summary":"Cancel a pending invitation (admin + manager)","parameters":[{"name":"inviteId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Invite canceled"},"404":{"description":"Invite not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Invite already accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/team/invites/{inviteId}/resend":{"post":{"operationId":"resendTeamInvite","tags":["me"],"summary":"Re-send invitation email (admin + manager, throttled 1/hour)","parameters":[{"name":"inviteId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Invite re-sent","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InviteResponse"}}}},"404":{"description":"Invite not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Throttled — resend allowed once per hour","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/team/members/{userId}/role":{"patch":{"operationId":"changeMemberRole","tags":["me"],"summary":"Change a member's role (admin only, last-admin protection)","parameters":[{"name":"userId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeRoleBody"}}}},"responses":{"200":{"description":"Role changed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeRoleResponse"}}}},"404":{"description":"User not on this team","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Would orphan customer (last-admin protection)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/team/members/{userId}":{"delete":{"operationId":"removeMember","tags":["me"],"summary":"Remove a teammate (admin only, last-admin protection, session revoked)","parameters":[{"name":"userId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Member removed"},"404":{"description":"User not on this team","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Would orphan customer","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/team/members/{userId}/reactivate":{"post":{"operationId":"reactivateTeamMember","tags":["me"],"summary":"Reactivate a paused teammate (admin only, gated by seat cap)","description":"Flips customer_users.is_paused from true to false. Refuses with 409 if the resulting active member count would exceed plans.max_users. Audit event team.seat.reactivated is written. (Trial-to-Solo-seat-pause)","parameters":[{"name":"userId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Member reactivated"},"404":{"description":"User not on this team","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Not paused, or would exceed seat cap","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/signals/{id}/share":{"post":{"operationId":"shareSignal","tags":["me"],"summary":"Share a signal with one or more teammates","description":"All roles can share. Server validates each recipient is a current customer_users member of the same customer, drops self + already-shared recipients, and fires a shared_with_me notification (in-app + email per recipient prefs).","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShareSignalBody"}}}},"responses":{"201":{"description":"Shares created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShareSignalResponse"}}}},"400":{"description":"Validation error / self-share / invalid recipients","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Signal not found in this customer","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"All recipients were already shared with — nothing to do","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/signals/{id}/comments":{"get":{"operationId":"listSignalComments","tags":["me"],"summary":"List the comment thread on a signal","description":"Returns comments oldest-first with author + mention emails hydrated. Soft-deleted comments have body=\"\" and deleted=true so the FE can render \"(comment removed)\".","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Thread","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommentListResponse"}}}},"404":{"description":"Signal not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createSignalComment","tags":["me"],"summary":"Post a new comment on a signal (with optional @-mentions)","description":"All roles allowed. Self-mentions and non-member mentions are silently dropped. Server fires \"mentioned\" notifications to each valid mention and \"commented_on_my_share\" to the original sharer (suppressed if the sharer was already mentioned or is the commenter themselves).","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommentBody"}}}},"responses":{"201":{"description":"Comment created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCommentResponse"}}}},"400":{"description":"Validation error (empty body, too many mentions, etc.)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Signal not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/signals/{id}/activity":{"get":{"operationId":"getSignalActivity","tags":["me"],"summary":"Chronological activity feed for a single signal","description":"Unions shares + comments, newest-first. Each event carries a `kind` discriminator. Future kinds (ratings, delivery events) will be added in lockstep with backlog #51.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Activity events","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignalActivityResponse"}}}},"404":{"description":"Signal not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/signals/{id}/comments/{commentId}":{"delete":{"operationId":"deleteSignalComment","tags":["me"],"summary":"Soft-delete a comment (author or admin)","description":"Author can always delete their own comment. Admin can delete any comment in their customer (moderation). Idempotent — re-deleting a deleted comment returns 204.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"commentId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Comment soft-deleted"},"403":{"description":"Not the author and not an admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Comment not found in this customer/signal","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/notifications":{"get":{"operationId":"listMeNotifications","tags":["me"],"summary":"List recent notifications + unread count for the bell icon","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50}}],"responses":{"200":{"description":"Notification list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationListResponse"}}}}}}},"/api/me/notifications/mark-read":{"post":{"operationId":"markNotificationsRead","tags":["me"],"summary":"Mark notifications as read","description":"Two modes: {ids: [...]} marks specific notifications, {all: true} (or empty body) marks every unread for the current user/customer. Returns the count updated + the new unreadCount.","requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarkReadBody"}}}},"responses":{"200":{"description":"Marked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarkReadResponse"}}}}}}},"/api/me/notification-prefs":{"get":{"operationId":"getMeNotificationPrefs","tags":["me"],"summary":"Get the current email-notification preferences for the calling user + customer","description":"Always returns a shape — falls back to defaults (emailSharedWithMe=true, emailMentioned=true, emailCommentedOnMyShare=false, emailRoleChanged=true) when no row has been saved yet.","responses":{"200":{"description":"Prefs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationPrefs"}}}}}},"patch":{"operationId":"patchMeNotificationPrefs","tags":["me"],"summary":"Update one or more email-notification toggles","description":"Partial update. Omitted fields stay at their current value. Empty body → 400.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationPrefsPatch"}}}},"responses":{"200":{"description":"Updated prefs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationPrefs"}}}},"400":{"description":"Empty body or invalid field","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/admin/customers/{customerId}/audit-events":{"get":{"operationId":"adminListCustomerAuditEvents","tags":["admin"],"summary":"List a customer's audit events (admin SPA drilldown)","description":"Admin-side view of the same audit_events feed /api/me/audit-events exposes to customer admins+managers. Customer is scoped via the URL param (not session — admin tooling spans customers). Cursor + response shape match the /me variant so the dashboard SPA can reuse the portal's row-rendering logic.","parameters":[{"name":"customerId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque cursor returned as nextCursor from the previous page. Round-trip verbatim; do not parse."}],"responses":{"200":{"description":"Audit-event page","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuditEventListResponse"}}}},"404":{"description":"Unknown customerId","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/audit-events":{"get":{"operationId":"listMeAuditEvents","tags":["me"],"summary":"List the customer's audit events (admin + manager only)","description":"Newest-first, cursor-paginated. Powers the portal /portal/settings/audit page. Includes team-management events (invites, role changes, member removal), trial lifecycle, credit grants/reconciles, and other customer-scoped audit rows. Admin and manager only — regular users 403.","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque cursor returned as nextCursor from the previous page. Round-trip verbatim; do not parse."}],"responses":{"200":{"description":"Audit-event page","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuditEventListResponse"}}}},"403":{"description":"Caller role is \"user\" — admin or manager required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/public/burst/{token}":{"get":{"operationId":"resolveBurstPage","tags":["public"],"summary":"Instant Signals prospect page payload (no auth — the token is the auth)","description":"Resolves an 18-hex page token to the prospect page payload. 404 for a malformed or unknown token. 200 with state=expired (past the 25-day clock, no signal data touched), state=not_available (zero visible cards — takedown, zero-card run, or workspace-less lead), or state=ok with hero + up to 2 secondary cards + lockedCount. TD7 by position: locked write-up fields are never present in the payload. ?preview=1 (admin View-page link) skips view recording.","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","pattern":"^[0-9a-f]{18}$"}},{"name":"preview","in":"query","required":false,"schema":{"type":"string","enum":["1"]}}],"responses":{"200":{"description":"Page payload (state discriminated: ok / expired / not_available)"},"404":{"description":"Malformed or unknown token"}}}},"/api/public/invite/{token}/status":{"get":{"operationId":"getInviteStatus","tags":["public"],"summary":"Read-only invite status (no auth, no token consumption)","description":"Returns one of: valid (with invitee details) / expired / already_accepted / not_found / email_already_user (existing user, not on this workspace) / already_member (existing user already on this workspace, with customerName). Used by the portal /signup/accept-invite landing page to branch the UI before driving the user into the auth flow.","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Status (discriminated union)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InviteStatus"}}}}}}},"/api/me/intelligence/account":{"post":{"operationId":"createAccountIntelligence","tags":["me","intelligence"],"summary":"Kick off (or return cached) Account Intelligence run","description":"Idempotent by (customer, canonical company slug) within the 30-day cache. Non-cached path deducts the account_intelligence bundle up-front + enqueues the pipeline BullMQ job.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostAccountIntelligenceBody"}}}},"responses":{"201":{"description":"Report queued or returned from cache","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostAccountIntelligenceResponse"}}}},"400":{"description":"Validation error / bad URL","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient role","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/intelligence/account/{reportId}":{"get":{"operationId":"getAccountIntelligence","tags":["me","intelligence"],"summary":"Fetch a specific Account Intelligence report by id","description":"Cross-tenant reads return 404 (§10.3.4). Poll while status ∈ {queued, running}; terminal at status ∈ {ready, failed}.","parameters":[{"name":"reportId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Report row","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountIntelligenceRow"}}}},"404":{"description":"Not found or cross-tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/intelligence/account/latest":{"get":{"operationId":"getLatestAccountIntelligenceBySlug","tags":["me","intelligence"],"summary":"Resolve the latest ready Account IX for a company slug","description":"Returns the most recent ready row for the caller-owned company slug, or 404 when none exist. Used by the Portal committee \"Learn more\" back-navigation and by useLatestAccountBySlug.","parameters":[{"name":"slug","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Report row","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountIntelligenceRow"}}}},"404":{"description":"No report for this customer + slug","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/intelligence/account/latest-any":{"get":{"operationId":"getLatestAccountIntelligenceAnyStatusBySlug","tags":["me","intelligence"],"summary":"Resolve the latest Account IX for a company slug (any status)","description":"Status-agnostic + window-agnostic sibling of /latest. Returns queued/running/ready/failed rows so Portal committee-card polling and post-submit workspace polling can render intermediate states without flashing a 404.","parameters":[{"name":"slug","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Report row","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountIntelligenceRow"}}}},"404":{"description":"No report for this customer + slug","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/intelligence/person":{"post":{"operationId":"createPersonIntelligence","tags":["me","intelligence"],"summary":"Kick off (or return cached) Person Intelligence snapshot","description":"Idempotent by (customer, person slug) within the 30-day cache. Optional sourceCompanyReportId anchors the run to a Buying Committee entry (§4.3 dual-FK guard verifies ownership; cross-tenant → 404).","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostPersonIntelligenceBody"}}}},"responses":{"201":{"description":"Snapshot queued or returned from cache","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostPersonIntelligenceResponse"}}}},"400":{"description":"Validation error / bad URL","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credits","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient role","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"sourceCompanyReportId not owned by caller","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/intelligence/person/{snapshotId}":{"get":{"operationId":"getPersonIntelligence","tags":["me","intelligence"],"summary":"Fetch a specific Person Intelligence snapshot by id","description":"Cross-tenant reads return 404 (§10.3.4). Poll while status ∈ {queued, running}.","parameters":[{"name":"snapshotId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Snapshot row","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonIntelligenceRow"}}}},"404":{"description":"Not found or cross-tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/intelligence/person/latest":{"get":{"operationId":"getLatestPersonIntelligenceBySlug","tags":["me","intelligence"],"summary":"Resolve the latest ready Person IX snapshot for a person slug","description":"Returns the most recent ready snapshot for the caller-owned person slug, or 404. Used by useLatestPersonBySlug from the composite person-in-account route.","parameters":[{"name":"slug","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Snapshot row","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonIntelligenceRow"}}}},"404":{"description":"No snapshot for this customer + slug","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/intelligence/person/latest-any":{"get":{"operationId":"getLatestPersonIntelligenceAnyStatusBySlug","tags":["me","intelligence"],"summary":"Resolve the latest Person IX snapshot for a person slug (any status)","description":"Status-agnostic + window-agnostic sibling of /latest. Committee-card polling + composite-page polling both consume this so the row shows queued/running/failed states instead of a 404 flash.","parameters":[{"name":"slug","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Snapshot row","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonIntelligenceRow"}}}},"404":{"description":"No snapshot for this customer + slug","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/intelligence/history":{"get":{"operationId":"listIntelligenceHistory","tags":["me","intelligence"],"summary":"List recent Account IX + Person IX runs for the current customer","description":"Sorted by createdAt DESC, interleaved account + person entries, server-side deduped by (type, slug). Powers the /intelligence landing page Recent Activity block with inline filter tabs, free-text search, and offset pagination.","parameters":[{"name":"type","in":"query","required":false,"schema":{"type":"string","enum":["all","account","person"],"default":"all"}},{"name":"q","in":"query","required":false,"schema":{"type":"string","maxLength":200},"description":"Case-insensitive substring match against canonicalName / companySlug / firmographics.industry (accounts) and personSlug / profile.fullName / profile.currentTitle / profile.currentCompany (persons)."},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":20}}],"responses":{"200":{"description":"History list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntelligenceHistoryResponse"}}}}}}},"/api/me/intelligence/person/{snapshotId}/signals/{signalId}/score":{"post":{"operationId":"scoreIntelligenceSignal","tags":["me","intelligence"],"summary":"Score one Person-IX evaluated signal (\"View Signal\") — idempotent, 0 credits","description":"Stage 3 of Person IX. First call runs the shared signal_score prompt (1-10 urgency, harvest-comparable) and caches onto scored_signals; later calls return the cache instantly. No re-score path — the report is a snapshot in time. Returns the score plus company firmographics from the enrichment caches for the inline card. 503 scoring_unavailable when the scorer degrades (deliberately not cached).","parameters":[{"name":"snapshotId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"signalId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Score (fresh or cached) + card firmographics","content":{"application/json":{"schema":{"type":"object","properties":{"scored":{"type":"object","properties":{"strength":{"type":"number","minimum":1,"maximum":10},"signalContext":{"type":"string"},"relevanceReasoning":{"type":"string"},"topicTags":{"type":"array","items":{"type":"string"}},"scoredAt":{"type":"string"}},"required":["strength","signalContext","relevanceReasoning","topicTags","scoredAt"],"additionalProperties":false},"fromCache":{"type":"boolean"},"company":{"type":"object","properties":{"industry":{"anyOf":[{"type":"string"},{"type":"null"}]},"employeeCount":{"anyOf":[{"type":"number"},{"type":"null"}]},"description":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["industry","employeeCount","description"],"additionalProperties":false}},"required":["scored","fromCache","company"],"additionalProperties":false}}}},"404":{"description":"Snapshot or signal not found"},"503":{"description":"Scoring temporarily unavailable — retry"}}}},"/api/me/intelligence/account/{reportId}/committee/{personSlug}/context":{"post":{"operationId":"getMeMemberContext","tags":["me"],"summary":"Role rationale + opener for one committee member (idempotent, cached)","description":"First call generates (a few seconds); later calls return the cache. 0 credits. 503 context_unavailable when generation is degraded (retryable).","parameters":[{"in":"path","name":"reportId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true},{"in":"path","name":"personSlug","schema":{"type":"string"},"required":true}],"responses":{"200":{"description":"Member context","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemberContextResponse"}}}},"404":{"description":"Report or member not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Report not ready","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Generation degraded — retry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/intelligence/person/{snapshotId}/signals/{signalId}/push":{"post":{"operationId":"pushIntelligenceSignalToInbox","tags":["me","intelligence"],"summary":"Push a surfaced Person-IX evaluated signal into the Signal Inbox","description":"§4.3 revised — 0 credits. Creates one signal_events row (source_event_type=intelligence_push_person) + enqueues destination fan-out. ON CONFLICT dedup returns the existing signal_events.id with deduped=true.","parameters":[{"name":"snapshotId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"signalId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"201":{"description":"Signal pushed (or existing row returned)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PushToInboxResponse"}}}},"404":{"description":"Snapshot / signal not found or cross-tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/public/signup":{"post":{"operationId":"publicOneStepSignup","tags":["public"],"summary":"One-step magic-link signup: application fields + email in a single request","description":"Replaces the retired two-step flow (auth, then POST /api/me/signup/linkedin). Creates the user and the signup_requests row together, dispatches a sign-in link, and puts the application in the admin review queue immediately. Email verification is enforced at APPROVAL, not here. The OAuth variant does not use this endpoint — those users authenticate first and submit fields via the authenticated POST /api/me/signup. Turnstile-gated + per-IP rate limited.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicSignupBody"}}}},"responses":{"200":{"description":"Sign-in link dispatched (uniform response — reveals nothing about account state)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicSignupResponse"}}}},"400":{"description":"Validation or Turnstile failure","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per-IP, per-email, or per-LinkedIn-URL)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/me/signup":{"post":{"operationId":"submitSignupApplication","tags":["me"],"summary":"Authenticated \"last step\" of the two-step signup — submit application fields","description":"The OAuth path of the auth-first two-step signup: the provider proved the email at step 1; this submits the four application fields from /signup/apply. Same validation/rate-limit/dedup core as POST /api/public/signup (the email path). Guarded to incomplete users and expired-application re-signups.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeSignupBody"}}}},"responses":{"201":{"description":"Application created and queued for review","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeSignupResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Already submitted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/public/auth/magic-link/request":{"post":{"operationId":"requestMagicLink","tags":["public"],"summary":"Request a magic link email","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MagicLinkRequestBody"}}}},"responses":{"200":{"description":"Magic link sent (always returns success)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MagicLinkResponse"}}}},"400":{"description":"Invalid email","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/public/auth/logout":{"post":{"operationId":"logout","tags":["public"],"summary":"Log out and clear session cookie","responses":{"200":{"description":"Logged out","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LogoutResponse"}}}}}}}},"components":{"schemas":{"V1RegisterBody":{"type":"object","properties":{"client_name":{"type":"string"},"redirect_uris":{"type":"array","items":{"type":"string","format":"uri"}},"registrant_email":{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"registrant_linkedin":{"type":"string","format":"uri"},"scope":{"type":"array","items":{"type":"string","enum":["read:signals","read:sources","read:watchlist","read:icp","read:intelligence","read:usage","read:destinations","write:intelligence","write:destinations","ext:lookups"]}}},"required":["client_name","redirect_uris","registrant_email","registrant_linkedin"]},"PostAccountIntelligenceBody":{"type":"object","properties":{"companyUrl":{"type":"string","description":"LinkedIn company URL. Accepts variants (case, scheme, regional subdomain, trailing slash) — canonicalized via normalizeLinkedinUrl."}},"required":["companyUrl"]},"PostPersonIntelligenceBody":{"type":"object","properties":{"personUrl":{"type":"string","description":"LinkedIn person URL — /in/<slug>. Canonicalized via normalizeLinkedinUrl."},"sourceCompanyReportId":{"description":"Optional — set when running Person IX from an Account IX Buying Committee row. Verified against caller customer_id before accepting (dual-FK guard §10.3.1 #4). 404 on cross-tenant.","anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"initialProfile":{"description":"Optional seed for the profile jsonb so Recent Activity + workspace render the natural name before worker enrichment completes. Worker markPersonReady overwrites with authoritative actor data.","anyOf":[{"type":"object","properties":{"fullName":{"anyOf":[{"type":"string"},{"type":"null"}]},"currentTitle":{"anyOf":[{"type":"string"},{"type":"null"}]},"currentCompany":{"anyOf":[{"type":"string"},{"type":"null"}]}}},{"type":"null"}]}},"required":["personUrl"]},"PublicSignupBody":{"type":"object","properties":{"email":{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"contactName":{"type":"string","maxLength":200},"contactTitle":{"type":"string","maxLength":200},"websiteUrl":{"type":"string","example":"yourcompany.com"},"linkedinUrl":{"type":"string","example":"linkedin.com/company/acme"},"referralCode":{"type":"string","maxLength":64},"turnstileToken":{"type":"string"}},"required":["email","contactName","contactTitle","websiteUrl","linkedinUrl"]},"MeSignupBody":{"type":"object","properties":{"contactName":{"type":"string","maxLength":200},"contactTitle":{"type":"string","maxLength":200},"websiteUrl":{"type":"string","example":"yourcompany.com"},"linkedinUrl":{"type":"string","example":"linkedin.com/company/acme"},"referralCode":{"type":"string","maxLength":64}},"required":["contactName","contactTitle","websiteUrl","linkedinUrl"]},"MagicLinkRequestBody":{"type":"object","properties":{"email":{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$","example":"jane@acme.com"}},"required":["email"]},"User":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"User ID"},"email":{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$","example":"jane@acme.com"},"signupStatus":{"type":"string","enum":["incomplete","pending_review","active","denied","tool"],"description":"Current signup lifecycle status"},"customerId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"Associated customer ID, if any"},"role":{"anyOf":[{"type":"string","enum":["admin","manager","user"]},{"type":"null"}],"description":"Role on the active customer; null if no customer link"},"authMethod":{"type":"string","enum":["magic_link","google","microsoft"],"description":"How the current session was established"}},"required":["id","email","signupStatus","customerId","role","authMethod"]},"SignupRequest":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"linkedinCompanyUrl":{"type":"string","example":"https://www.linkedin.com/company/acme/"},"status":{"type":"string","description":"Review status"},"submittedAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]}},"required":["id","linkedinCompanyUrl","status","submittedAt"]},"MeCustomer":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string","example":"Acme Corp"},"slug":{"type":"string","example":"acme-corp"},"lifecyclePhase":{"type":"string","enum":["onboarding_running","awaiting_admin_icp_review","awaiting_customer_setup","active","paused","suspended","deactivated"],"description":"Drives portal AuthGate routing","example":"active"},"isActive":{"type":"boolean"},"productDescription":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["id","name","slug","lifecyclePhase","isActive","productDescription"]},"ProvisioningStep":{"type":"object","properties":{"id":{"anyOf":[{"type":"number","const":1},{"type":"number","const":2},{"type":"number","const":3},{"type":"number","const":4},{"type":"number","const":5}]},"label":{"type":"string","example":"Analyzing your company"},"status":{"type":"string","enum":["completed","in_progress","pending"]}},"required":["id","label","status"]},"SourceWithStats":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"Source ID"},"customerId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"sourceType":{"type":"string","enum":["own_company","competitor_company","competitor_company_broad","competitor_employee","keyword_search","industry_search","mention_tracking","hashtag_search","target_person","event_search"],"description":"Source type classification"},"linkedinUrl":{"type":"string","example":"https://www.linkedin.com/company/acme/"},"displayName":{"anyOf":[{"type":"string"},{"type":"null"}],"example":"Acme Corp"},"priority":{"type":"integer","minimum":1,"maximum":5,"example":3},"isActive":{"type":"boolean"},"metadata":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]},"topicFilter":{"anyOf":[{"type":"string"},{"type":"null"}]},"searchQuery":{"anyOf":[{"type":"string"},{"type":"null"}]},"industryCodes":{"anyOf":[{"type":"string"},{"type":"null"}]},"lastSeenPostId":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Most recent post ID seen during discovery"},"lastDiscoveryAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"event":{"anyOf":[{"type":"object","properties":{"name":{"type":"string"},"startDate":{"type":"string"},"endDate":{"type":"string"},"phase":{"type":"string","enum":["dormant","pre","live","wrap","ended"]},"completedAt":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["name","startDate","endDate","phase","completedAt"]},{"type":"null"}]},"status":{"description":"Computed source health badge — derived portal-side","type":"string","enum":["producing","watching","slow","paused","error"]},"strengthScore":{"description":"Source quality strength 0-1 (qualRate per MEMORY.md formula)","type":"number"},"sparkline":{"description":"30 daily counts of signals attributed to this source (oldest → newest)","minItems":30,"maxItems":30,"type":"array","items":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"totalPosts":{"description":"Watched posts in window","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"qualifiedPosts":{"description":"Posts in qualified or harvesting lifecycle","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"avgRelevanceScore":{"description":"Avg watched_posts.relevance_score (1-5; lower = more relevant)","anyOf":[{"type":"number"},{"type":"null"}]},"totalLikes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"totalComments":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"signalCount":{"description":"Signals attributed to this source within the window","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"scoreDistribution":{"description":"Counts of watched_posts grouped by relevance_score (1=Strong … 5=Irrelevant) within the window","type":"object","properties":{"1":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"2":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"3":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"4":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"5":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["1","2","3","4","5"]}},"required":["id","customerId","sourceType","linkedinUrl","displayName","priority","isActive","metadata","topicFilter","searchQuery","industryCodes","lastSeenPostId","lastDiscoveryAt","createdAt"]},"DestinationWithStats":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"Destination ID"},"customerId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"destinationType":{"type":"string","enum":["google_sheet","clay_webhook","slack","webhook","n8n","notion"],"description":"Delivery channel type"},"name":{"type":"string","example":"Sales Team Slack"},"config":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{},"description":"Destination-specific configuration"},"routing":{"oneOf":[{"type":"object","properties":{"mode":{"type":"string","const":"all"}},"required":["mode"]},{"type":"object","properties":{"mode":{"type":"string","const":"manual"}},"required":["mode"]},{"type":"object","properties":{"mode":{"type":"string","const":"min_strength"},"minStrength":{"type":"integer","minimum":1,"maximum":10}},"required":["mode","minStrength"]}],"description":"When to auto-route signals to this destination. Defaults to {mode:\"all\"}.","type":"object"},"isActive":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"signatureSecret":{"description":"HMAC secret used to sign outbound webhook deliveries (X-SignalRaven-Signature). Revealed once on create; rotate via POST :id/rotate-secret.","type":"string"},"status":{"type":"string","enum":["connected","error","paused"]},"lastDeliveryAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"recentDeliveryCount":{"description":"Count of activations in the last 7 days","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"health":{"type":"string","enum":["healthy","circuit_open","never_delivered"]},"consecutiveFailures":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"lastFailureAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"lastFailureReason":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["id","customerId","destinationType","name","config","routing","isActive","createdAt"]},"UpdateMeIcpBody":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"minEmployees":{"type":"integer","minimum":1,"maximum":9007199254740991},"maxEmployees":{"type":"integer","minimum":1,"maximum":9007199254740991},"targetIndustries":{"type":"array","items":{"type":"string"}},"targetTitles":{"type":"array","items":{"type":"string"}},"excludeTitles":{"type":"array","items":{"type":"string"}},"targetPersonas":{"type":"array","items":{"type":"string"}},"additionalContext":{"anyOf":[{"type":"string"},{"type":"null"}]},"targetLocations":{"type":"array","items":{"type":"string"}},"targetBuyerIndustries":{"type":"array","items":{"type":"string"}},"buyerContext":{"anyOf":[{"type":"string"},{"type":"null"}]},"productCategory":{"anyOf":[{"type":"string"},{"type":"null"}]},"classificationExamples":{"anyOf":[{"type":"string"},{"type":"null"}]},"excludeInfluencers":{"type":"boolean"},"matchWeights":{"type":"object","properties":{"title":{"type":"number","minimum":0,"maximum":100},"marketAffinity":{"type":"number","minimum":0,"maximum":100},"industry":{"type":"number","minimum":0,"maximum":100},"companySize":{"type":"number","minimum":0,"maximum":100},"location":{"type":"number","minimum":0,"maximum":100}},"required":["title","marketAffinity","industry","companySize","location"]}}},"CreateMeDestinationBody":{"type":"object","properties":{"destinationType":{"type":"string","enum":["slack","google_sheet","webhook","notion","n8n","clay_webhook"]},"name":{"type":"string","minLength":1,"maxLength":255},"config":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"routing":{"oneOf":[{"type":"object","properties":{"mode":{"type":"string","const":"all"}},"required":["mode"]},{"type":"object","properties":{"mode":{"type":"string","const":"manual"}},"required":["mode"]},{"type":"object","properties":{"mode":{"type":"string","const":"min_strength"},"minStrength":{"type":"integer","minimum":1,"maximum":10}},"required":["mode","minStrength"]}],"type":"object"}},"required":["destinationType","name","config"]},"WatchedPost":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"customerId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"sourceId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"postUrl":{"type":"string","example":"https://www.linkedin.com/posts/example"},"postUrn":{"type":"string"},"postAuthorName":{"anyOf":[{"type":"string"},{"type":"null"}]},"postTextPreview":{"anyOf":[{"type":"string"},{"type":"null"}]},"postedAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"tier":{"type":"string","description":"Harvest tier (A/B/C)"},"initialLikes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"initialComments":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"latestLikes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"latestComments":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"isActive":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"expiresAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"harvestCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"lifecycleStatus":{"type":"string","description":"discovered | qualified | harvesting | closed"},"closedReason":{"anyOf":[{"type":"string"},{"type":"null"}]},"relevanceScore":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"1=strong, 5=irrelevant"},"relevanceReason":{"anyOf":[{"type":"string"},{"type":"null"}]},"aiPostSummary":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["id","customerId","sourceId","postUrl","postUrn","postAuthorName","postTextPreview","postedAt","tier","initialLikes","initialComments","latestLikes","latestComments","isActive","createdAt","expiresAt","harvestCount","lifecycleStatus","closedReason","relevanceScore","relevanceReason","aiPostSummary"]},"DeliveryRecord":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"signalEventId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"destinationId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"status":{"type":"string","enum":["pending","delivered","failed","skipped"]},"errorMessage":{"anyOf":[{"type":"string"},{"type":"null"}]},"retryCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"deliveredAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"signalPersonName":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Person whose engagement triggered the signal"},"signalPersonCompany":{"anyOf":[{"type":"string"},{"type":"null"}]},"signalType":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["id","signalEventId","destinationId","status","errorMessage","retryCount","deliveredAt","createdAt","signalPersonName","signalPersonCompany","signalType"]},"ActivityEvent":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"category":{"type":"string","enum":["discovery","harvest","enrichment","icp","delivery"]},"message":{"type":"string","example":"Discovered 12 new posts from competitor company"},"detail":{"type":"string"},"occurredAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"link":{"type":"object","properties":{"type":{"type":"string","enum":["signal","source","watchedPost"]},"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["type","id"]}},"required":["id","category","message","occurredAt"]},"SessionRecord":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"issuedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"lastUsedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"expiresAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"userAgent":{"anyOf":[{"type":"string"},{"type":"null"}]},"ipAddress":{"anyOf":[{"type":"string"},{"type":"null"}]},"isCurrent":{"type":"boolean","description":"true if this is the session making the request"},"revokedAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]}},"required":["id","issuedAt","lastUsedAt","expiresAt","userAgent","ipAddress","isCurrent","revokedAt"]},"PaygPurchase":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"credits":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991,"description":"Credits granted at purchase (whole units)."},"creditsRemaining":{"type":"number","minimum":0,"description":"Credits still available from this pack (scale-4 since migration 0038). Zero when refunded or fully consumed."},"amountCents":{"type":"integer","minimum":0,"maximum":9007199254740991,"description":"What the customer paid, in the smallest currency unit."},"currency":{"type":"string","const":"usd"},"purchasedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"expiresAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"planSlugAtPurchase":{"type":"string","description":"Customer's plan slug at purchase time — determined the $/credit rate charged."},"receiptUrl":{"anyOf":[{"type":"string","format":"uri"},{"type":"null"}],"description":"Stripe-hosted receipt URL. NULL for the one pre-migration test purchase; portal renders \"—\" in that case."},"isExpired":{"type":"boolean","description":"true when expires_at has passed. Server-derived so portal state stays consistent across timezones."},"isRefunded":{"type":"boolean","description":"true when a credit_transactions row with type=refund references this pack. Row still shown in history with a \"(refunded)\" tag."}},"required":["id","credits","creditsRemaining","amountCents","currency","purchasedAt","expiresAt","planSlugAtPurchase","receiptUrl","isExpired","isRefunded"]},"BillingInvoice":{"type":"object","properties":{"id":{"type":"string","description":"Stripe invoice id, e.g. \"in_1Q...\"."},"number":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Stripe-issued invoice number, e.g. \"AB1234-001\". May be null on draft."},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"amountPaid":{"type":"integer","minimum":0,"maximum":9007199254740991,"description":"Cents actually charged."},"currency":{"type":"string","description":"ISO 4217 code, e.g. \"usd\"."},"periodStart":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"periodEnd":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"hostedInvoiceUrl":{"anyOf":[{"type":"string","format":"uri"},{"type":"null"}],"description":"Stripe-hosted invoice page. Read-only view + download button. URL gates access by its own token — no portal auth needed on click-through."},"pdfUrl":{"anyOf":[{"type":"string","format":"uri"},{"type":"null"}],"description":"Direct PDF download URL (Stripe-hosted)."},"billingReason":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Stripe billing reason — useful for distinguishing subscription_cycle vs subscription_create vs manual."}},"required":["id","number","createdAt","amountPaid","currency","periodStart","periodEnd","hostedInvoiceUrl","pdfUrl","billingReason"]},"Signal":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"Signal event ID"},"customerId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"signalType":{"type":"string","enum":["COMPETITOR_POST_COMMENT","COMPETITOR_POST_REACTION","CUSTOMER_POST_COMMENT","CUSTOMER_POST_REACTION","COMPETITOR_EMPLOYEE_POST_COMMENT","COMPETITOR_EMPLOYEE_POST_REACTION","KEYWORD_SEARCH_COMMENT","KEYWORD_SEARCH_REACTION","INDUSTRY_SEARCH_COMMENT","INDUSTRY_SEARCH_REACTION","MENTION_TRACKING_COMMENT","MENTION_TRACKING_REACTION","HASHTAG_SEARCH_COMMENT","HASHTAG_SEARCH_REACTION","EVENT_SEARCH_COMMENT","EVENT_SEARCH_REACTION","EVENT_SEARCH_POST","TARGET_PERSON_POST","TARGET_PERSON_REPOST","TARGET_PERSON_COMMENT","TARGET_PERSON_REACTION","INTELLIGENCE_PUSH_ACTIVITY"],"description":"Signal classification"},"strength":{"type":"integer","minimum":1,"maximum":10,"example":7},"personName":{"type":"string","example":"Jane Doe"},"personTitle":{"anyOf":[{"type":"string"},{"type":"null"}],"example":"VP Marketing"},"personCompany":{"anyOf":[{"type":"string"},{"type":"null"}],"example":"Acme Corp"},"personLinkedinUrl":{"anyOf":[{"type":"string"},{"type":"null"}]},"companyEmployeeCount":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"companyIndustry":{"anyOf":[{"type":"string"},{"type":"null"}]},"companyDescription":{"anyOf":[{"type":"string"},{"type":"null"}]},"personLocation":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Person's LinkedIn-displayed location (e.g. 'Belfast Metropolitan Area'). Joined from person_profile_cache."},"personHeadline":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Person's LinkedIn headline (e.g. 'VP Marketing | Sales engagement evangelist'). Joined from person_profile_cache."},"personAbout":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Person's LinkedIn About text (long-form bio). Joined from person_profile_cache."},"personExperience":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"title":{"anyOf":[{"type":"string"},{"type":"null"}]},"company":{"anyOf":[{"type":"string"},{"type":"null"}]},"companyUrl":{"anyOf":[{"type":"string"},{"type":"null"}]},"startDate":{"anyOf":[{"type":"string"},{"type":"null"}]},"endDate":{"anyOf":[{"type":"string"},{"type":"null"}]},"description":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["title","company","companyUrl","startDate","endDate","description"]}},{"type":"null"}],"description":"Person's LinkedIn work history (most-recent first). Joined from person_profile_cache.experience. Each entry has title, company, companyUrl, startDate, endDate, description — endDate is null/empty when the role is current. Portal uses this to render concurrent + past roles at the current company on the signal detail page."},"companyHeadquarters":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Company HQ location (e.g. 'San Francisco, CA, US'). Flattened from person_profile_cache.companyHeadquarters → company_profile_cache.headquarters."},"stackCount":{"description":"Count of other signals from the same person OR same company within the last 90 days. Mirrors the Signal Stack panel on the detail page (person match via person_profile_cache.linkedin_urn, company match via case-insensitive personCompany). Used to render the Signal Stack indicator on /signals. 0 when no siblings.","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"icpAnalysis":{"anyOf":[{"$ref":"#/components/schemas/IcpAnalysis"},{"type":"null"}]},"buyerClassification":{"description":"Normalized buyer/seller/influencer classification: COALESCE(metadata, icp_analysis)->>'buyerClassification'. Coverage is mixed by era (backfill wrote metadata only; older reaction rows wrote icp_analysis only; current rows write both) — this field is the single normalized read. null = pre-classification row (treat as buyer). Drives the Influencer chip + classification filter (plan 2026-08-28).","anyOf":[{"type":"string"},{"type":"null"}]},"signalContext":{"anyOf":[{"type":"string"},{"type":"null"}]},"event":{"anyOf":[{"type":"object","properties":{"name":{"type":"string"},"startDate":{"type":"string"},"endDate":{"type":"string"},"role":{"type":"string","enum":["author","engager"]},"evidence":{"type":"string","enum":["author_attendance","author_recap","engager_comment","engager_reaction"]},"phaseAtCapture":{"anyOf":[{"type":"string","enum":["pre","live","wrap"]},{"type":"null"}]}},"required":["name","startDate","endDate","role","evidence"]},{"type":"null"}]},"talkingPoints":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"postTextPreview":{"anyOf":[{"type":"string"},{"type":"null"}]},"aiPostSummary":{"anyOf":[{"type":"string"},{"type":"null"}]},"whyItMatters":{"anyOf":[{"type":"string"},{"type":"null"}]},"engagementDetail":{"anyOf":[{"type":"string"},{"type":"null"}]},"sourceEventType":{"anyOf":[{"type":"string"},{"type":"null"}]},"sourcePostUrl":{"anyOf":[{"type":"string"},{"type":"null"}]},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"archivedAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"tags":{"description":"Workspace tag values applied to this signal. Present on /me list + detail responses; ordered by category then value name.","type":"array","items":{"$ref":"#/components/schemas/SignalTag"}}},"required":["id","customerId","signalType","strength","personName","personTitle","personCompany","personLinkedinUrl","companyEmployeeCount","companyIndustry","companyDescription","personLocation","personHeadline","personAbout","personExperience","companyHeadquarters","icpAnalysis","signalContext","talkingPoints","postTextPreview","aiPostSummary","whyItMatters","engagementDetail","sourceEventType","sourcePostUrl","createdAt"]},"IcpAnalysis":{"type":"object","properties":{"fit":{"type":"boolean"},"confidence":{"type":"number"},"persona":{"type":"string"},"reasoning":{"type":"string"},"seniority":{"type":"string"},"compositeScore":{"anyOf":[{"type":"number"},{"type":"null"}]},"titleScore":{"anyOf":[{"type":"number"},{"type":"null"}]},"marketAffinityScore":{"anyOf":[{"type":"number"},{"type":"null"}]},"industryScore":{"anyOf":[{"type":"number"},{"type":"null"}]},"companySizeScore":{"anyOf":[{"type":"number"},{"type":"null"}]},"locationScore":{"anyOf":[{"type":"number"},{"type":"null"}]},"dimensionNotes":{"anyOf":[{"type":"object","properties":{"title":{"anyOf":[{"type":"string"},{"type":"null"}]},"marketAffinity":{"anyOf":[{"type":"string"},{"type":"null"}]},"industry":{"anyOf":[{"type":"string"},{"type":"null"}]},"companySize":{"anyOf":[{"type":"string"},{"type":"null"}]},"location":{"anyOf":[{"type":"string"},{"type":"null"}]}}},{"type":"null"}]},"failedDimensions":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"buyerClassification":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["fit","confidence","persona","reasoning","seniority"]},"IcpProfile":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"ICP Profile ID"},"customerId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string","example":"Primary ICP"},"minEmployees":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"maxEmployees":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"targetIndustries":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"targetTitles":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"excludeTitles":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"targetPersonas":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"additionalContext":{"anyOf":[{"type":"string"},{"type":"null"}]},"targetLocations":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"targetBuyerIndustries":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"buyerContext":{"anyOf":[{"type":"string"},{"type":"null"}]},"targetSeniority":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"matchWeights":{"anyOf":[{"type":"object","properties":{"title":{"type":"number","minimum":0,"maximum":100},"marketAffinity":{"type":"number","minimum":0,"maximum":100},"industry":{"type":"number","minimum":0,"maximum":100},"companySize":{"type":"number","minimum":0,"maximum":100},"location":{"type":"number","minimum":0,"maximum":100}},"required":["title","marketAffinity","industry","companySize","location"]},{"type":"null"}]},"productCategory":{"anyOf":[{"type":"string"},{"type":"null"}]},"classificationExamples":{"anyOf":[{"type":"string"},{"type":"null"}]},"excludeInfluencers":{"type":"boolean"},"isDefault":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","customerId","name","minEmployees","maxEmployees","targetIndustries","targetTitles","excludeTitles","targetPersonas","additionalContext","targetLocations","targetBuyerIndustries","buyerContext","targetSeniority","matchWeights","productCategory","classificationExamples","excludeInfluencers","isDefault","createdAt"]},"CreateSourceBody":{"type":"object","properties":{"sourceType":{"type":"string","enum":["own_company","competitor_company","competitor_company_broad","competitor_employee","keyword_search","industry_search","mention_tracking","hashtag_search","target_person","event_search"]},"linkedinUrl":{"type":"string"},"displayName":{"type":"string","maxLength":255},"priority":{"type":"integer","minimum":1,"maximum":5},"metadata":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"topicFilter":{"type":"string","maxLength":2000},"searchQuery":{"type":"string","maxLength":2000},"industryCodes":{"type":"string","maxLength":2000}},"required":["sourceType"]},"UpdateSourceBody":{"type":"object","properties":{"sourceType":{"type":"string","enum":["own_company","competitor_company","competitor_company_broad","competitor_employee","keyword_search","industry_search","mention_tracking","hashtag_search","target_person","event_search"]},"linkedinUrl":{"type":"string"},"displayName":{"type":"string","maxLength":255},"priority":{"type":"integer","minimum":1,"maximum":5},"isActive":{"type":"boolean"},"metadata":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"topicFilter":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]},"searchQuery":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]},"industryCodes":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]}}},"UpdateDestinationBody":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"config":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"routing":{"oneOf":[{"type":"object","properties":{"mode":{"type":"string","const":"all"}},"required":["mode"]},{"type":"object","properties":{"mode":{"type":"string","const":"manual"}},"required":["mode"]},{"type":"object","properties":{"mode":{"type":"string","const":"min_strength"},"minStrength":{"type":"integer","minimum":1,"maximum":10}},"required":["mode","minStrength"]}],"type":"object"},"isActive":{"type":"boolean"}}},"InviteBody":{"type":"object","properties":{"email":{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"role":{"type":"string","enum":["user","manager","prospector"]}},"required":["email","role"]},"ChangeRoleBody":{"type":"object","properties":{"role":{"type":"string","enum":["admin","manager","prospector","user"]}},"required":["role"]},"ShareSignalBody":{"type":"object","properties":{"recipientUserIds":{"minItems":1,"maxItems":20,"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"Teammates to share with. Must be current customer_users members."},"message":{"description":"Optional note from the sharer. Empty/omitted → \"shared without comment\".","type":"string","maxLength":2000}},"required":["recipientUserIds"]},"CommentBody":{"type":"object","properties":{"body":{"type":"string","minLength":1,"maxLength":4000},"mentionedUserIds":{"description":"User IDs to @-mention. Server validates each is a current customer_users member and silently drops self-mentions.","maxItems":20,"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}},"required":["body"]},"CreateCommentResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"authorUserId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"authorEmail":{"anyOf":[{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},{"type":"null"}]},"authorRemoved":{"type":"boolean","description":"True when the author is no longer a member of this customer (their customer_users link was deleted). The FE renders \"(removed)\" alongside the email."},"body":{"type":"string","description":"Empty string when deleted is true (the original text is redacted server-side to preserve privacy)."},"mentionedUserIds":{"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"mentionedEmails":{"type":"array","items":{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"}},"deleted":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","authorUserId","authorEmail","authorRemoved","body","mentionedUserIds","deleted","createdAt"]},"NotificationType":{"type":"string","enum":["shared_with_me","mentioned","commented_on_my_share","role_changed","credit_usage_80pct","credit_usage_100pct","credit_usage_projected_exhaustion","credit_payment_failed","credit_refund_processed","weekly_credit_digest","trial_inactive_deactivated","plan_downgrade_to_trial_scheduled","subscription_downgrade_scheduled","subscription_resumed","destination_action_required","pending_teammate_review","add_your_teammates_reminder","trial_to_paid_welcome","credit_pack_purchase","first_signal_delivered","card_expiring_soon","upgrade_prompt","setup_incomplete_nudge","no_recent_signals","trial_credit_usage_80pct","trial_credit_usage_100pct","signals_taking_longer","login_nudge_1","login_nudge_2"]},"NotificationItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"type":{"$ref":"#/components/schemas/NotificationType"},"payload":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{},"description":"Type-specific payload. Collaboration: shared_with_me {signalId, fromUserId, fromUserEmail, message}; mentioned/commented_on_my_share {signalId, commentId, actorUserId, actorUserEmail, excerpt}; role_changed {fromRole, toRole, changedByUserId, changedByUserEmail}. Billing (credit_*, weekly_credit_digest, trial_inactive_deactivated): generic shape {title, body?, actionUrl?} — title + body render directly in the bell-icon, actionUrl is the portal route the click should navigate to. The email + id values on collaboration payloads are immutable history; if the actor was later removed from the team, see actorRemoved below."},"actorRemoved":{"type":"boolean","description":"True when the actor recorded in payload is no longer a member of this customer. Lets the FE render \"Alice (removed)\" without the FE having to re-look-up membership for every row."},"readAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","type","payload","actorRemoved","readAt","createdAt"]},"MarkReadBody":{"type":"object","properties":{"ids":{"maxItems":500,"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"all":{"type":"boolean"}},"description":"Pass {ids: [...]} to mark specific notifications read, or {all: true} (or empty body) to mark every unread item read."},"NotificationPrefsPatch":{"type":"object","properties":{"emailSharedWithMe":{"type":"boolean"},"emailMentioned":{"type":"boolean"},"emailCommentedOnMyShare":{"type":"boolean"},"emailRoleChanged":{"type":"boolean"}},"description":"Partial update. Pass only the toggles you want to change. Empty body returns 400."},"SignalActivityEvent":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"share"},"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"actorUserId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"actorEmail":{"anyOf":[{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},{"type":"null"}]},"actorRemoved":{"type":"boolean"},"toUserId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"toEmail":{"anyOf":[{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},{"type":"null"}]},"toRemoved":{"type":"boolean"},"message":{"anyOf":[{"type":"string"},{"type":"null"}]},"occurredAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["kind","id","actorUserId","actorEmail","actorRemoved","toUserId","toEmail","toRemoved","message","occurredAt"]},{"type":"object","properties":{"kind":{"type":"string","const":"comment"},"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"actorUserId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"actorEmail":{"anyOf":[{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},{"type":"null"}]},"actorRemoved":{"type":"boolean"},"body":{"type":"string","description":"Empty string when deleted=true (server-side redaction)."},"deleted":{"type":"boolean"},"mentionedUserIds":{"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"occurredAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["kind","id","actorUserId","actorEmail","actorRemoved","body","deleted","mentionedUserIds","occurredAt"]}],"type":"object"},"TagSelectionMode":{"type":"string","enum":["single","multi"],"description":"How many values from this category one signal can carry. 'single' replaces on apply."},"TagValue":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"usageCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Signals currently carrying this value (drives delete confirms)."}},"required":["id","name","usageCount"]},"TagCategory":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"selectionMode":{"$ref":"#/components/schemas/TagSelectionMode"},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"values":{"type":"array","items":{"$ref":"#/components/schemas/TagValue"},"description":"Ordered by name (case-insensitive)."}},"required":["id","name","selectionMode","createdAt","values"]},"SignalTag":{"type":"object","properties":{"valueId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"valueName":{"type":"string"},"categoryId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"categoryName":{"type":"string"}},"required":["valueId","valueName","categoryId","categoryName"]},"AuditEvent":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"eventType":{"type":"string","description":"Machine-readable event identifier (e.g. team.member_invited, team.role_changed, team.member_removed, trial.inactivity_deactivated, credit.grant.reconciled). Stable enough for the FE to switch on; the canonical list lives in src/services/*/audit emitters."},"actorUserId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"actorEmail":{"anyOf":[{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},{"type":"null"}],"description":"Email of the customer-side actor at the time of the event. Hydrated server-side from users.email; nullable when the row was actorless (system/admin) or the actor row has been hard-deleted."},"actorAdminId":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Set when a Zygnal-internal admin tool wrote the event. Mutually exclusive with actorUserId/actorEmail."},"actorRemoved":{"type":"boolean","description":"True when the actorUserId no longer has a customer_users link to THIS customer. Same semantics as the notifications endpoint — FE renders \"Alice (removed)\" so the reader knows the actor is no longer on the team."},"resourceId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"metadata":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}],"description":"Free-form per-event metadata. Shape varies by eventType; the FE pretty-prints it inside an expandable details disclosure."},"occurredAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","eventType","actorUserId","actorEmail","actorAdminId","actorRemoved","resourceId","metadata","occurredAt"]},"V1RegisterResponse":{"type":"object","properties":{"client_id":{"type":"string"},"client_secret":{"type":"string"},"approval_status":{"type":"string"},"token_endpoint":{"type":"string"},"authorization_endpoint":{"type":"string"},"granted_scopes":{"type":"string"},"notice":{"type":"string"}},"required":["client_id","client_secret","approval_status","token_endpoint","authorization_endpoint","granted_scopes","notice"],"additionalProperties":false},"V1SignalsResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/V1Signal"}},"total":{"type":"number"},"limit":{"type":"number"},"offset":{"type":"number"},"_meta":{"$ref":"#/components/schemas/V1Meta"}},"required":["data","total","limit","offset","_meta"],"additionalProperties":false},"V1Signal":{"type":"object","properties":{"id":{"type":"string"},"type":{"anyOf":[{"type":"string"},{"type":"null"}]},"strength":{"anyOf":[{"type":"number"},{"type":"null"}]},"person":{"type":"object","properties":{"company":{"anyOf":[{"type":"string"},{"type":"null"}]},"linkedinUrl":{"anyOf":[{"type":"string"},{"type":"null"}]},"location":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["company","linkedinUrl","location"],"additionalProperties":false},"icp":{"anyOf":[{"type":"string"},{"type":"null"}]},"whyItMatters":{"anyOf":[{"type":"string"},{"type":"null"}]},"suggestedOpener":{"anyOf":[{"type":"string"},{"type":"null"}]},"talkingPoints":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"postPreview":{"anyOf":[{"type":"string"},{"type":"null"}]},"createdAt":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["id","type","strength","person","icp","whyItMatters","suggestedOpener","talkingPoints","postPreview","createdAt"],"additionalProperties":false},"V1Meta":{"type":"object","properties":{"mode":{"type":"string","enum":["live","sample"]},"notice":{"type":"string"},"cta":{"type":"object","properties":{"text":{"type":"string"},"url":{"type":"string"}},"required":["text","url"],"additionalProperties":false}},"required":["mode"],"additionalProperties":false},"V1SignalResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/V1Signal"},"_meta":{"$ref":"#/components/schemas/V1Meta"}},"required":["data","_meta"],"additionalProperties":false},"V1SourcesResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/V1Source"}},"total":{"type":"number"},"_meta":{"$ref":"#/components/schemas/V1Meta"}},"required":["data","total","_meta"],"additionalProperties":false},"V1Source":{"type":"object","properties":{"id":{"type":"string"},"type":{"anyOf":[{"type":"string"},{"type":"null"}]},"linkedinUrl":{"anyOf":[{"type":"string"},{"type":"null"}]},"displayName":{"anyOf":[{"type":"string"},{"type":"null"}]},"isActive":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"strengthScore":{"anyOf":[{"type":"number"},{"type":"null"}]},"signalCount":{"anyOf":[{"type":"number"},{"type":"null"}]},"totalPosts":{"anyOf":[{"type":"number"},{"type":"null"}]},"qualifiedPosts":{"anyOf":[{"type":"number"},{"type":"null"}]},"createdAt":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["id","type","linkedinUrl","displayName","isActive","strengthScore","signalCount","totalPosts","qualifiedPosts","createdAt"],"additionalProperties":false},"V1WatchlistResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/V1Post"}},"total":{"type":"number"},"limit":{"type":"number"},"offset":{"type":"number"},"_meta":{"$ref":"#/components/schemas/V1Meta"}},"required":["data","total","limit","offset","_meta"],"additionalProperties":false},"V1Post":{"type":"object","properties":{"id":{"type":"string"},"sourceId":{"anyOf":[{"type":"string"},{"type":"null"}]},"url":{"anyOf":[{"type":"string"},{"type":"null"}]},"author":{"anyOf":[{"type":"string"},{"type":"null"}]},"preview":{"anyOf":[{"type":"string"},{"type":"null"}]},"relevanceScore":{"anyOf":[{"type":"number"},{"type":"null"}]},"lifecycleStatus":{"anyOf":[{"type":"string"},{"type":"null"}]},"createdAt":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["id","sourceId","url","author","preview","relevanceScore","lifecycleStatus","createdAt"],"additionalProperties":false},"V1IcpResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/V1Icp"},"_meta":{"$ref":"#/components/schemas/V1Meta"}},"required":["data","_meta"],"additionalProperties":false},"V1Icp":{"type":"object","properties":{"id":{"type":"string"},"minEmployees":{"anyOf":[{"type":"number"},{"type":"null"}]},"maxEmployees":{"anyOf":[{"type":"number"},{"type":"null"}]},"targetIndustries":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"targetTitles":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"targetPersonas":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"targetSeniority":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"additionalContext":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["id","minEmployees","maxEmployees","targetIndustries","targetTitles","targetPersonas","targetSeniority","additionalContext"],"additionalProperties":false},"HealthResponse":{"type":"object","properties":{"status":{"type":"string","enum":["healthy","degraded"],"example":"healthy"},"timestamp":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"checks":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"object","properties":{"status":{"type":"string","example":"ok"},"latencyMs":{"type":"number"}},"required":["status"],"additionalProperties":false}}},"required":["status","timestamp","checks"],"additionalProperties":false},"PostAccountIntelligenceResponse":{"type":"object","properties":{"reportId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"slug":{"type":"string"},"status":{"$ref":"#/components/schemas/ToolStatus"},"cached":{"type":"boolean","description":"true when returned from the 30-day cache; false when a fresh pipeline was enqueued."}},"required":["reportId","slug","status","cached"],"additionalProperties":false},"ToolStatus":{"type":"string","enum":["queued","running","ready","failed"]},"AccountIntelligenceRow":{"type":"object","properties":{"reportId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"slug":{"type":"string"},"companyUrl":{"type":"string"},"status":{"$ref":"#/components/schemas/ToolStatus"},"disposition":{"anyOf":[{"$ref":"#/components/schemas/AccountDisposition"},{"type":"null"}]},"dispositionReason":{"anyOf":[{"type":"string"},{"type":"null"}]},"canonicalName":{"anyOf":[{"type":"string"},{"type":"null"}]},"firmographics":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"buyingCommittee":{"type":"array","items":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"companyInsights":{"description":"Normalized company-insights actor output (headcount growth, hires-by-month, openings). Null when the actor was unavailable or the company id was unknown.","anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]},"dispositionChecks":{"description":"Structured disposition gate readout — the values each gate compared (size band, industry strings, committee match split, momentum). Null on reports predating the release.","anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]},"companyPosts":{"anyOf":[{"type":"array","items":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},{"type":"null"}]},"memberContext":{"description":"Lazy role-rationale + opener cache keyed by personSlug.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"committeeSignals":{"description":"Inbox-signal stats per committee member (90-day window), computed at read time. Keyed by personSlug.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"object","properties":{"signalCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"maxStrength":{"anyOf":[{"type":"number"},{"type":"null"}]},"lastSignalAt":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["signalCount","maxStrength","lastSignalAt"],"additionalProperties":false}},"q1RowCount":{"type":"integer","minimum":0,"maximum":9007199254740991},"q2RowCount":{"type":"integer","minimum":0,"maximum":9007199254740991},"q3RowCount":{"type":"integer","minimum":0,"maximum":9007199254740991},"ghostFilterDropped":{"type":"integer","minimum":0,"maximum":9007199254740991},"aiPostFilterDropped":{"type":"integer","minimum":0,"maximum":9007199254740991},"dedupDropped":{"type":"integer","minimum":0,"maximum":9007199254740991},"canonicalUrl":{"description":"The URL the ghost filter actually used (enrichCompany-canonical, or falls back to input companyUrl).","anyOf":[{"type":"string"},{"type":"null"}]},"canonicalUrlMatchedInput":{"description":"true = actor canonical URL equals customer input. false = parent-brand aliasing detected on this run. null = actor returned no URL (unknown).","anyOf":[{"type":"boolean"},{"type":"null"}]},"failureReason":{"anyOf":[{"type":"string"},{"type":"null"}]},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"readyAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"createdByUserId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]}},"required":["reportId","slug","companyUrl","status","disposition","dispositionReason","canonicalName","firmographics","buyingCommittee","q1RowCount","q2RowCount","q3RowCount","ghostFilterDropped","aiPostFilterDropped","dedupDropped","failureReason","createdAt","readyAt","createdByUserId"],"additionalProperties":false},"AccountDisposition":{"type":"string","enum":["pass","investigate","fail","insufficient_data"]},"PostPersonIntelligenceResponse":{"type":"object","properties":{"snapshotId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"slug":{"type":"string"},"status":{"$ref":"#/components/schemas/ToolStatus"},"cached":{"type":"boolean"}},"required":["snapshotId","slug","status","cached"],"additionalProperties":false},"PersonIntelligenceRow":{"type":"object","properties":{"snapshotId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"slug":{"type":"string"},"personUrl":{"type":"string"},"status":{"$ref":"#/components/schemas/ToolStatus"},"profile":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"aiRead":{"$ref":"#/components/schemas/AiRead"},"evaluatedSignals":{"type":"array","items":{"$ref":"#/components/schemas/EvaluatedSignal"}},"scoredSignals":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"object","properties":{"strength":{"type":"number","minimum":1,"maximum":10},"signalContext":{"type":"string"},"relevanceReasoning":{"type":"string"},"topicTags":{"type":"array","items":{"type":"string"}},"scoredAt":{"type":"string"}},"required":["strength","signalContext","relevanceReasoning","topicTags","scoredAt"],"additionalProperties":false}},"activitySummary":{"anyOf":[{"$ref":"#/components/schemas/ActivitySummary"},{"type":"null"}]},"rawActivityCount":{"type":"integer","minimum":0,"maximum":9007199254740991},"signalsCount":{"type":"integer","minimum":0,"maximum":9007199254740991},"hiring":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"openToWork":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"recentJobChange":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"savedSignalEventIds":{"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"sourceCompanyReportId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"failureReason":{"anyOf":[{"type":"string"},{"type":"null"}]},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"readyAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"createdByUserId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]}},"required":["snapshotId","slug","personUrl","status","profile","aiRead","evaluatedSignals","scoredSignals","rawActivityCount","signalsCount","hiring","openToWork","recentJobChange","savedSignalEventIds","sourceCompanyReportId","failureReason","createdAt","readyAt","createdByUserId"],"additionalProperties":false},"AiRead":{"anyOf":[{"type":"object","properties":{"buyerClassification":{"type":"string","enum":["buyer","seller","influencer"]},"employerBusinessModel":{"type":"string"},"classificationReason":{"type":"string"},"confidence":{"type":"number","minimum":0,"maximum":1}},"required":["buyerClassification","employerBusinessModel","classificationReason","confidence"],"additionalProperties":false},{"type":"null"}]},"EvaluatedSignal":{"type":"object","properties":{"signalId":{"type":"string"},"activityType":{"type":"string","enum":["post","repost","comment","reaction"]},"postText":{"anyOf":[{"type":"string"},{"type":"null"}]},"postUrl":{"anyOf":[{"type":"string"},{"type":"null"}]},"score":{"type":"integer","minimum":1,"maximum":5},"reason":{"type":"string"},"postedAt":{"description":"When the activity was posted on LinkedIn (ISO string). Captured from actor result but may be missing when the actor did not surface a timestamp — nullable/optional so the Portal degrades gracefully.","anyOf":[{"type":"string"},{"type":"null"}]},"itemId":{"description":"Raw activity item id — the activity-chart highlight join (intelligence depth). Absent on pre-release rows.","type":"string"},"pipeline":{"description":"Which fetch pipeline produced the underlying item: A = engagement, B-1 = authored posts, B-2 = reposts. Absent on pre-release rows.","type":"string","enum":["A","B-1","B-2"]}},"required":["signalId","activityType","postText","postUrl","score","reason"],"additionalProperties":false},"ActivitySummary":{"type":"object","properties":{"digest":{"anyOf":[{"type":"object","properties":{"summary":{"type":"string"},"bullets":{"type":"array","items":{"type":"string"}},"outreachAngle":{"type":"string"},"angleRefs":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string"},"type":{"type":"string"}},"required":["url","type"],"additionalProperties":false}},"topicRollups":{"type":"array","items":{"type":"object","properties":{"topic":{"type":"string"},"itemCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"note":{"type":"string"}},"required":["topic","itemCount","note"],"additionalProperties":false}},"generatedAt":{"type":"string"}},"required":["topicRollups","generatedAt"],"additionalProperties":false},{"type":"null"}]},"buckets":{"type":"array","items":{"type":"object","properties":{"weekStart":{"type":"string"},"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"signals":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["weekStart","total","signals"],"additionalProperties":false}},"undatedCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"outOfWindowCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"score":{"type":"object","properties":{"value":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"label":{"type":"string","enum":["Quiet","Occasional","Active","Highly active"]},"components":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"number"}}},"required":["value","label","components"],"additionalProperties":false},"windowStart":{"anyOf":[{"type":"string"},{"type":"null"}]},"windowEnd":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["digest","buckets","undatedCount","score","windowStart","windowEnd"],"additionalProperties":false,"description":"Digest + weekly activity buckets + deterministic score, computed during the run. Null on snapshots predating the intelligence-depth release."},"IntelligenceHistoryResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/IntelligenceHistoryEntry"}},"total":{"type":"integer","minimum":0,"maximum":9007199254740991},"offset":{"type":"integer","minimum":0,"maximum":9007199254740991},"limit":{"type":"integer","minimum":1,"maximum":9007199254740991}},"required":["items","total","offset","limit"],"additionalProperties":false},"IntelligenceHistoryEntry":{"oneOf":[{"$ref":"#/components/schemas/IntelligenceHistoryAccountEntry"},{"$ref":"#/components/schemas/IntelligenceHistoryPersonEntry"}],"type":"object","discriminator":{"propertyName":"type","mapping":{"account":"#/components/schemas/IntelligenceHistoryAccountEntry","person":"#/components/schemas/IntelligenceHistoryPersonEntry"}}},"IntelligenceHistoryAccountEntry":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"slug":{"type":"string"},"canonicalName":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"$ref":"#/components/schemas/ToolStatus"},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"createdByUserId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"createdByUserEmail":{"anyOf":[{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},{"type":"null"}]},"type":{"type":"string","const":"account"},"disposition":{"anyOf":[{"$ref":"#/components/schemas/AccountDisposition"},{"type":"null"}]},"industry":{"anyOf":[{"type":"string"},{"type":"null"}]},"committeeSize":{"type":"integer","minimum":0,"maximum":9007199254740991},"employeeCount":{"anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]}},"required":["id","slug","canonicalName","status","createdAt","createdByUserId","createdByUserEmail","type"],"additionalProperties":false},"IntelligenceHistoryPersonEntry":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"slug":{"type":"string"},"canonicalName":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"$ref":"#/components/schemas/ToolStatus"},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"createdByUserId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"createdByUserEmail":{"anyOf":[{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},{"type":"null"}]},"type":{"type":"string","const":"person"},"fullName":{"anyOf":[{"type":"string"},{"type":"null"}]},"currentTitle":{"anyOf":[{"type":"string"},{"type":"null"}]},"currentCompany":{"anyOf":[{"type":"string"},{"type":"null"}]},"rawActivityCount":{"type":"integer","minimum":0,"maximum":9007199254740991},"signalsCount":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["id","slug","canonicalName","status","createdAt","createdByUserId","createdByUserEmail","type"],"additionalProperties":false},"MemberContextResponse":{"type":"object","properties":{"context":{"type":"object","properties":{"roleRationale":{"type":"string"},"opener":{"type":"string"},"confidence":{"type":"number"},"generatedAt":{"type":"string"}},"required":["roleRationale","opener","confidence","generatedAt"],"additionalProperties":false},"fromCache":{"type":"boolean"}},"required":["context","fromCache"],"additionalProperties":false},"PushToInboxResponse":{"type":"object","properties":{"signalEventId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"deduped":{"type":"boolean","description":"true when this signal was already pushed to inbox (ON CONFLICT DO NOTHING branch — returns the existing signal_events.id)."}},"required":["signalEventId","deduped"],"additionalProperties":false},"PublicSignupResponse":{"type":"object","properties":{"sent":{"type":"boolean","const":true}},"required":["sent"],"additionalProperties":false},"MeSignupResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"status":{"type":"string"}},"required":["id","status"],"additionalProperties":false},"MagicLinkResponse":{"type":"object","properties":{"sent":{"type":"boolean"}},"required":["sent"],"additionalProperties":false},"LogoutResponse":{"type":"object","properties":{"ok":{"type":"boolean"}},"required":["ok"],"additionalProperties":false},"Error":{"type":"object","properties":{"error":{"type":"string","example":"NotFound"},"message":{"example":"Resource not found","type":"string"}},"required":["error"],"additionalProperties":false,"description":"Standard error envelope"},"MeResponse":{"type":"object","properties":{"user":{"$ref":"#/components/schemas/User"},"customer":{"anyOf":[{"$ref":"#/components/schemas/MeCustomer"},{"type":"null"}]},"signupRequest":{"$ref":"#/components/schemas/SignupRequest"}},"required":["user","customer"],"additionalProperties":false},"ProvisioningStatus":{"type":"object","properties":{"lifecyclePhase":{"type":"string","enum":["pending_review","prospect","onboarding_running","awaiting_admin_icp_review","awaiting_customer_setup","active","paused","suspended","deactivated"],"description":"Current customer lifecycle phase (or pending_review pre-customer)"},"currentStep":{"anyOf":[{"type":"number","const":1},{"type":"number","const":2},{"type":"number","const":3},{"type":"number","const":4},{"type":"number","const":5}],"description":"Highest step the customer should currently watch (1-5)","example":3},"steps":{"minItems":5,"maxItems":5,"type":"array","items":{"$ref":"#/components/schemas/ProvisioningStep"}},"estimatedSecondsRemaining":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"Heuristic estimate based on historical step durations; null if unknown"}},"required":["lifecyclePhase","currentStep","steps","estimatedSecondsRemaining"],"additionalProperties":false},"MeSourceListResponse":{"type":"object","properties":{"sources":{"type":"array","items":{"$ref":"#/components/schemas/SourceWithStats"}},"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["sources","total"],"additionalProperties":false},"MeDestinationListResponse":{"type":"object","properties":{"destinations":{"type":"array","items":{"$ref":"#/components/schemas/DestinationWithStats"}}},"required":["destinations"],"additionalProperties":false},"TestDestinationResponse":{"type":"object","properties":{"success":{"type":"boolean"},"error":{"type":"string"},"responseData":{}},"required":["success"],"additionalProperties":false},"MeIcpResponse":{"type":"object","properties":{"icp":{"$ref":"#/components/schemas/IcpProfile"},"classificationExamples":{"anyOf":[{"type":"string"},{"type":"null"}]},"resettable":{"type":"boolean"},"effectiveThresholds":{"type":"object","properties":{"title":{"type":"number"},"marketAffinity":{"type":"number"},"industry":{"type":"number"},"companySize":{"type":"number"},"location":{"type":"number"}},"required":["title","marketAffinity","industry","companySize","location"],"additionalProperties":false},"effectiveTargetLocations":{"type":"array","items":{"type":"string"}}},"required":["icp","classificationExamples","resettable","effectiveThresholds","effectiveTargetLocations"],"additionalProperties":false},"ActivateResponse":{"type":"object","properties":{"ok":{"type":"boolean","const":true},"lifecyclePhase":{"type":"string","const":"active"},"discoveryKickedFor":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Number of sources for which an immediate discovery job was enqueued"}},"required":["ok","lifecyclePhase","discoveryKickedFor"],"additionalProperties":false},"DashboardOverview":{"type":"object","properties":{"range":{"type":"object","properties":{"from":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"to":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"days":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["from","to","days"],"additionalProperties":false},"signals":{"type":"object","properties":{"deliveredCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Distinct signals with at least one delivered activation in range"},"totalCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Total signals in range (delivered or not)"},"avgScore":{"type":"number","description":"Average signal strength (1-10) in range"},"avgIcpPct":{"type":"number","description":"Average composite ICP percentage (0-100) across signals with a composite in range. Signals without composite are excluded from the mean rather than counted as 0."},"trendVsPriorPercent":{"type":"number","description":"% change in totalCount vs prior equivalent window; 0 when prior was 0"}},"required":["deliveredCount","totalCount","avgScore","avgIcpPct","trendVsPriorPercent"],"additionalProperties":false},"sources":{"type":"object","properties":{"activeCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"totalCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"All sources for the customer (active + paused)."},"topSourceByYield":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"displayName":{"anyOf":[{"type":"string"},{"type":"null"}]},"signalCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","displayName","signalCount"],"additionalProperties":false},{"type":"null"}]}},"required":["activeCount","totalCount","topSourceByYield"],"additionalProperties":false},"funnel":{"type":"object","properties":{"postsDiscovered":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"postsQualified":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"postsWatching":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Currently is_active=true with lifecycle in (qualified, harvesting)"},"engagementCollected":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Comment + reaction events captured in range"},"signalsDelivered":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["postsDiscovered","postsQualified","postsWatching","engagementCollected","signalsDelivered"],"additionalProperties":false},"systemStatus":{"type":"object","properties":{"lifecyclePhase":{"type":"string"},"pausedReason":{"anyOf":[{"type":"string"},{"type":"null"}]},"pausedUntil":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]}},"required":["lifecyclePhase","pausedReason","pausedUntil"],"additionalProperties":false},"signalStrengthDistribution":{"type":"array","items":{"type":"object","properties":{"strength":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["strength","count"],"additionalProperties":false},"description":"Signals grouped by strength (1-10) in range"},"topSignalPersonas":{"type":"array","items":{"type":"object","properties":{"persona":{"type":"string"},"count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"avgStrength":{"type":"number"}},"required":["persona","count","avgStrength"],"additionalProperties":false},"description":"Top 10 personas by signal count, with average strength"},"postRelevanceDistribution":{"type":"array","items":{"type":"object","properties":{"relevanceScore":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["relevanceScore","count"],"additionalProperties":false},"description":"Watched posts grouped by relevance_score (1-5) in range"}},"required":["range","signals","sources","funnel","systemStatus","signalStrengthDistribution","topSignalPersonas","postRelevanceDistribution"],"additionalProperties":false},"MeSignalListResponse":{"type":"object","properties":{"signals":{"type":"array","items":{"$ref":"#/components/schemas/Signal"}},"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"limit":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"offset":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["signals","total","limit","offset"],"additionalProperties":false},"MeSignalDetail":{"type":"object","properties":{"signal":{"$ref":"#/components/schemas/Signal"},"pipelineResult":{"type":"object","properties":{"deterministicSellerCheck":{"anyOf":[{"type":"object","properties":{"passed":{"type":"boolean"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["passed","reason"],"additionalProperties":false},{"type":"null"}],"description":"Layer 1 of buyer/seller pipeline. NULL until backfill ships (backlog)."},"aiIdentityReview":{"anyOf":[{"type":"object","properties":{"skipped":{"type":"boolean"},"passed":{"type":"boolean"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["skipped","passed","reason"],"additionalProperties":false},{"type":"null"}],"description":"Layer 2 of buyer/seller pipeline. NULL until backfill ships (backlog)."},"classification":{"type":"string","enum":["buyer","influencer","unknown"],"description":"Derived from icp_analysis.persona field today; \"unknown\" when not present"},"icpScoring":{"type":"object","properties":{"composite":{"anyOf":[{"type":"number"},{"type":"null"}]},"dimensions":{"anyOf":[{"type":"object","properties":{"title":{"type":"number"},"marketAffinity":{"type":"number"},"industry":{"type":"number"},"companySize":{"type":"number"},"location":{"type":"number"}},"required":["title","marketAffinity","industry","companySize","location"],"additionalProperties":false},{"type":"null"}]},"thresholds":{"anyOf":[{"type":"object","properties":{"title":{"type":"number"},"marketAffinity":{"type":"number"},"industry":{"type":"number"},"companySize":{"type":"number"},"location":{"type":"number"}},"required":["title","marketAffinity","industry","companySize","location"],"additionalProperties":false},{"type":"null"}]}},"required":["composite","dimensions","thresholds"],"additionalProperties":false}},"required":["deterministicSellerCheck","aiIdentityReview","classification","icpScoring"],"additionalProperties":false},"sourcePost":{"anyOf":[{"type":"object","properties":{"url":{"anyOf":[{"type":"string"},{"type":"null"}]},"text":{"anyOf":[{"type":"string"},{"type":"null"}]},"postedBy":{"anyOf":[{"type":"string"},{"type":"null"}]},"postedAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"totalEngagement":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]}},"required":["url","text","postedBy","postedAt","totalEngagement"],"additionalProperties":false},{"type":"null"}]},"delivery":{"anyOf":[{"type":"object","properties":{"destinationId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"destinationName":{"anyOf":[{"type":"string"},{"type":"null"}]},"deliveredAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"status":{"type":"string","description":"One of 'pending' | 'delivered' | 'failed'. UI uses this to render the three states distinctly; 'pending' shows as 'Sending…' (warning tone) while the worker hasn't yet processed the activation. The codegen target lacks a literal-union helper so this is typed as `string` here; consumers narrow against the three known values.","example":"delivered"},"success":{"type":"boolean"},"error":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["destinationId","destinationName","deliveredAt","status","success","error"],"additionalProperties":false},{"type":"null"}]}},"required":["signal","pipelineResult","sourcePost","delivery"],"additionalProperties":false},"MeCompaniesListResponse":{"type":"object","properties":{"companies":{"type":"array","items":{"type":"object","properties":{"companyKey":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Canonical company key — LinkedIn company URL when enrichment is available, lowercased company name as fallback."},"companyName":{"anyOf":[{"type":"string"},{"type":"null"}]},"companyIndustry":{"anyOf":[{"type":"string"},{"type":"null"}]},"employeeCount":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"companyHeadquarters":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Flattened HQ location string, e.g. \"San Francisco, CA, US\"."},"companyLinkedinUrl":{"anyOf":[{"type":"string"},{"type":"null"}]},"companyWebsiteUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Company website URL from LinkedIn enrichment."},"companyTagline":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Company tagline from LinkedIn enrichment."},"companyFoundedYear":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"Year the company was founded."},"companySpecialities":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Company specialities/focus areas from LinkedIn enrichment."},"companyDescription":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Company description from LinkedIn enrichment or signal data."},"signalCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"personCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Distinct people detected at this company."},"latestSignalAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"avgIcpScore":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Average composite ICP score (0-1 scale) across signals at this company."},"topPersona":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Most common persona among signals at this company."}},"required":["companyKey","companyName","companyIndustry","employeeCount","companyHeadquarters","companyLinkedinUrl","companyWebsiteUrl","companyTagline","companyFoundedYear","companySpecialities","companyDescription","signalCount","personCount","latestSignalAt","avgIcpScore","topPersona"],"additionalProperties":false}},"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"limit":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"offset":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["companies","total","limit","offset"],"additionalProperties":false},"RelatedSignalsResponse":{"type":"object","properties":{"related":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"Signal event ID"},"customerId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"signalType":{"type":"string","enum":["COMPETITOR_POST_COMMENT","COMPETITOR_POST_REACTION","CUSTOMER_POST_COMMENT","CUSTOMER_POST_REACTION","COMPETITOR_EMPLOYEE_POST_COMMENT","COMPETITOR_EMPLOYEE_POST_REACTION","KEYWORD_SEARCH_COMMENT","KEYWORD_SEARCH_REACTION","INDUSTRY_SEARCH_COMMENT","INDUSTRY_SEARCH_REACTION","MENTION_TRACKING_COMMENT","MENTION_TRACKING_REACTION","HASHTAG_SEARCH_COMMENT","HASHTAG_SEARCH_REACTION","EVENT_SEARCH_COMMENT","EVENT_SEARCH_REACTION","EVENT_SEARCH_POST","TARGET_PERSON_POST","TARGET_PERSON_REPOST","TARGET_PERSON_COMMENT","TARGET_PERSON_REACTION","INTELLIGENCE_PUSH_ACTIVITY"],"description":"Signal classification"},"strength":{"type":"integer","minimum":1,"maximum":10,"example":7},"personName":{"type":"string","example":"Jane Doe"},"personTitle":{"anyOf":[{"type":"string"},{"type":"null"}],"example":"VP Marketing"},"personCompany":{"anyOf":[{"type":"string"},{"type":"null"}],"example":"Acme Corp"},"personLinkedinUrl":{"anyOf":[{"type":"string"},{"type":"null"}]},"companyEmployeeCount":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"companyIndustry":{"anyOf":[{"type":"string"},{"type":"null"}]},"companyDescription":{"anyOf":[{"type":"string"},{"type":"null"}]},"personLocation":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Person's LinkedIn-displayed location (e.g. 'Belfast Metropolitan Area'). Joined from person_profile_cache."},"personHeadline":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Person's LinkedIn headline (e.g. 'VP Marketing | Sales engagement evangelist'). Joined from person_profile_cache."},"personAbout":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Person's LinkedIn About text (long-form bio). Joined from person_profile_cache."},"personExperience":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"title":{"anyOf":[{"type":"string"},{"type":"null"}]},"company":{"anyOf":[{"type":"string"},{"type":"null"}]},"companyUrl":{"anyOf":[{"type":"string"},{"type":"null"}]},"startDate":{"anyOf":[{"type":"string"},{"type":"null"}]},"endDate":{"anyOf":[{"type":"string"},{"type":"null"}]},"description":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["title","company","companyUrl","startDate","endDate","description"],"additionalProperties":false}},{"type":"null"}],"description":"Person's LinkedIn work history (most-recent first). Joined from person_profile_cache.experience. Each entry has title, company, companyUrl, startDate, endDate, description — endDate is null/empty when the role is current. Portal uses this to render concurrent + past roles at the current company on the signal detail page."},"companyHeadquarters":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Company HQ location (e.g. 'San Francisco, CA, US'). Flattened from person_profile_cache.companyHeadquarters → company_profile_cache.headquarters."},"stackCount":{"description":"Count of other signals from the same person OR same company within the last 90 days. Mirrors the Signal Stack panel on the detail page (person match via person_profile_cache.linkedin_urn, company match via case-insensitive personCompany). Used to render the Signal Stack indicator on /signals. 0 when no siblings.","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"icpAnalysis":{"anyOf":[{"$ref":"#/components/schemas/IcpAnalysis"},{"type":"null"}]},"buyerClassification":{"description":"Normalized buyer/seller/influencer classification: COALESCE(metadata, icp_analysis)->>'buyerClassification'. Coverage is mixed by era (backfill wrote metadata only; older reaction rows wrote icp_analysis only; current rows write both) — this field is the single normalized read. null = pre-classification row (treat as buyer). Drives the Influencer chip + classification filter (plan 2026-08-28).","anyOf":[{"type":"string"},{"type":"null"}]},"signalContext":{"anyOf":[{"type":"string"},{"type":"null"}]},"event":{"anyOf":[{"type":"object","properties":{"name":{"type":"string"},"startDate":{"type":"string"},"endDate":{"type":"string"},"role":{"type":"string","enum":["author","engager"]},"evidence":{"type":"string","enum":["author_attendance","author_recap","engager_comment","engager_reaction"]},"phaseAtCapture":{"anyOf":[{"type":"string","enum":["pre","live","wrap"]},{"type":"null"}]}},"required":["name","startDate","endDate","role","evidence"],"additionalProperties":false},{"type":"null"}]},"talkingPoints":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"postTextPreview":{"anyOf":[{"type":"string"},{"type":"null"}]},"aiPostSummary":{"anyOf":[{"type":"string"},{"type":"null"}]},"whyItMatters":{"anyOf":[{"type":"string"},{"type":"null"}]},"engagementDetail":{"anyOf":[{"type":"string"},{"type":"null"}]},"sourceEventType":{"anyOf":[{"type":"string"},{"type":"null"}]},"sourcePostUrl":{"anyOf":[{"type":"string"},{"type":"null"}]},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"archivedAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"tags":{"description":"Workspace tag values applied to this signal. Present on /me list + detail responses; ordered by category then value name.","type":"array","items":{"$ref":"#/components/schemas/SignalTag"}},"relation":{"type":"string","enum":["person","company"],"description":"How the related signal matched: same person or same company."}},"required":["id","customerId","signalType","strength","personName","personTitle","personCompany","personLinkedinUrl","companyEmployeeCount","companyIndustry","companyDescription","personLocation","personHeadline","personAbout","personExperience","companyHeadquarters","icpAnalysis","signalContext","talkingPoints","postTextPreview","aiPostSummary","whyItMatters","engagementDetail","sourceEventType","sourcePostUrl","createdAt","relation"],"additionalProperties":false}},"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["related","total"],"additionalProperties":false},"MeWatchedPostListResponse":{"type":"object","properties":{"posts":{"type":"array","items":{"$ref":"#/components/schemas/WatchedPost"}},"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"limit":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"offset":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["posts","total","limit","offset"],"additionalProperties":false},"MeSourceSignalsResponse":{"type":"object","properties":{"signals":{"type":"array","items":{"$ref":"#/components/schemas/Signal"}},"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"limit":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"offset":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["signals","total","limit","offset"],"additionalProperties":false},"MeDeliveryListResponse":{"type":"object","properties":{"deliveries":{"type":"array","items":{"$ref":"#/components/schemas/DeliveryRecord"}},"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"limit":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"offset":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["deliveries","total","limit","offset"],"additionalProperties":false},"MeActivityResponse":{"type":"object","properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/ActivityEvent"}},"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Customer-facing event count after filtering (NOT raw pipeline_logs count)"}},"required":["events","total"],"additionalProperties":false},"Usage":{"type":"object","properties":{"banner":{"type":"string","const":"beta","description":"Tells the portal to show the placeholder banner"},"activity":{"type":"object","properties":{"signalsThisMonth":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"signalsLastMonth":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"sourcesActive":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"postsMonitored":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Cumulative count of all watched_posts ever for this customer"},"postsThisMonth":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"discoveryRunsToDate":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Count of \"Discovery completed\" pipeline_logs all-time"}},"required":["signalsThisMonth","signalsLastMonth","sourcesActive","postsMonitored","postsThisMonth","discoveryRunsToDate"],"additionalProperties":false},"systemStatus":{"type":"object","properties":{"lastActivityAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}],"description":"Most recent signal createdAt; null if no activity yet"},"operational":{"type":"boolean","description":"true unless lifecyclePhase is suspended/deactivated"}},"required":["lastActivityAt","operational"],"additionalProperties":false}},"required":["banner","activity","systemStatus"],"additionalProperties":false},"SessionListResponse":{"type":"object","properties":{"sessions":{"type":"array","items":{"$ref":"#/components/schemas/SessionRecord"}}},"required":["sessions"],"additionalProperties":false},"RevokeAllResponse":{"type":"object","properties":{"ok":{"type":"boolean","const":true},"revokedCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Number of sessions just revoked (includes the calling session — next request will fail auth)"}},"required":["ok","revokedCount"],"additionalProperties":false},"CreditSummary":{"type":"object","properties":{"credits":{"type":"object","properties":{"allotted":{"type":"integer","minimum":0,"maximum":9007199254740991,"description":"Monthly bucket size per plan (whole-number grant)"},"remaining":{"type":"number","description":"Monthly bucket balance (numeric to scale 4; can go negative under enforcement-OFF soft mode)"},"used":{"type":"number","minimum":0,"description":"allotted - remaining, clamped at 0 (numeric to scale 4)"},"periodStart":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"periodEnd":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}],"description":"When monthly bucket resets. NULL for Trial customers per design §4.4a"}},"required":["allotted","remaining","used","periodStart","periodEnd"],"additionalProperties":false},"bundleBreakdown":{"type":"object","properties":{"post_intake":{"type":"number","minimum":0},"engagement_capture":{"type":"number","minimum":0},"engager_evaluation":{"type":"number","minimum":0},"signal_delivery":{"type":"number","minimum":0},"account_intelligence":{"type":"number","minimum":0},"person_evaluation":{"type":"number","minimum":0}},"required":["post_intake","engagement_capture","engager_evaluation","signal_delivery","account_intelligence","person_evaluation"],"additionalProperties":false,"description":"Credits burned per Bundle for the current period (numeric to scale 4; sums to monthly+pack consumption)"},"bundleWeights":{"type":"object","properties":{"post_intake":{"type":"number","minimum":0},"engagement_capture":{"type":"number","minimum":0},"engager_evaluation":{"type":"number","minimum":0},"signal_delivery":{"type":"number","minimum":0},"account_intelligence":{"type":"number","minimum":0},"person_evaluation":{"type":"number","minimum":0}},"required":["post_intake","engagement_capture","engager_evaluation","signal_delivery","account_intelligence","person_evaluation"],"additionalProperties":false,"description":"Live per-bundle credit weights from system_settings.credit.bundleWeights. The portal uses these to render accurate \"Each X = N credits\" labels instead of stale hardcoded values."},"addOnPacks":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"credits":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991,"description":"Credits granted at purchase (whole number — packs are bought as whole units)"},"creditsRemaining":{"type":"number","minimum":0,"description":"Credits still available from this pack (numeric to scale 4 since migration 0038)"},"purchasedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"expiresAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$","description":"12 months after purchase for PAYG packs"},"source":{"type":"string","enum":["purchased","granted"],"description":"How this pack came into being. `purchased` = customer paid via Stripe PAYG Checkout (stripe_payment_intent_id is set). `granted` = SignalRaven admin granted as a bonus / make-good / trial extension via the admin SPA (stripe_payment_intent_id is null). Drives portal labeling so customers can distinguish receipts they owe from gifts."},"planSlugAtPurchase":{"type":"string","description":"Plan slug at purchase time — determines the $/credit rate that was charged"}},"required":["id","credits","creditsRemaining","purchasedAt","expiresAt","source","planSlugAtPurchase"],"additionalProperties":false},"description":"Active (non-empty, not expired) PAYG packs ordered FIFO by expiresAt ASC"},"totalBalance":{"type":"number","description":"monthly remaining + sum(active pack credits remaining) — numeric to scale 4 since migration 0038"},"paygBalance":{"type":"number","minimum":0,"description":"Sum of active pack credits remaining — numeric to scale 4 since migration 0038"},"projectedExhaustion":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}],"description":"When monthly bucket is forecast to hit zero at current burn rate; null when no burn yet OR projected past period_end"},"cached":{"type":"boolean","description":"true = served from 5-min Redis cache; false = fresh compute"}},"required":["credits","bundleBreakdown","bundleWeights","addOnPacks","totalBalance","paygBalance","projectedExhaustion","cached"],"additionalProperties":false},"MePlan":{"type":"object","properties":{"slug":{"type":"string","enum":["trial","trial_standard","solo","pro","scale","internal"],"description":"Plan slug"},"name":{"type":"string","example":"Zygnal Pro"},"monthlyPriceCents":{"type":"integer","minimum":0,"maximum":9007199254740991,"description":"0 for Trial + Internal"},"creditAllotment":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991,"description":"Monthly bucket size in credits"},"maxSources":{"anyOf":[{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},{"type":"null"}],"description":"null = unlimited (Scale + Internal)"},"maxDestinations":{"anyOf":[{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},{"type":"null"}],"description":"null = unlimited"},"maxUsers":{"anyOf":[{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},{"type":"null"}],"description":"Seat cap. null = unlimited (Scale + Internal). Read by getSeatCap() — null coerces to Infinity portal-side"},"signalStacking":{"type":"boolean","description":"Enables Pro+ signal-stacking feature (urgency bumps from history)"},"icpEditing":{"type":"string","enum":["basic","advanced"],"description":"Basic = simple ICP form. Advanced (Scale + Internal) = full dimension editing"},"paygEnabled":{"type":"boolean","description":"Whether the customer can buy add-on credit packs"},"addOnRatePerCredit":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"$/credit for PAYG purchases. NULL when paygEnabled=false","example":0.05},"isInternal":{"type":"boolean","description":"Derived as slug === \"internal\"; portal hides Stripe-only UX when true"},"stripeCustomerId":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"null until first paid upgrade. Manage-subscription button only shown when set"},"scheduledDowngrade":{"anyOf":[{"type":"object","properties":{"effectiveAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$","description":"ISO timestamp when the downgrade takes effect (= subscription current_period_end)"},"previousPlanSlug":{"type":"string"},"previousPlanName":{"type":"string"},"newPlanSlug":{"type":"string"},"newPlanName":{"type":"string"},"newMaxSources":{"anyOf":[{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},{"type":"null"}]},"newMaxDestinations":{"anyOf":[{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},{"type":"null"}]},"newMaxUsers":{"anyOf":[{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},{"type":"null"}]},"capChangesPreview":{"type":"string","description":"Plain-English summary of what will exceed the new plan caps at effectiveAt (e.g. \"10 sources and 1 destination will exceed your new plan's caps. Existing items keep running, but you won't be able to add new ones until you're under the limit.\"). Per design §3.4 soft enforcement: no auto-deactivation occurs. Returns \"You are already within the new plan caps.\" when nothing exceeds."},"notifiedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$","description":"ISO timestamp when the email + bell-icon notification fired. Banner survives a refresh; the email/bell fire once."},"targetType":{"description":"\"trial\" = cancel-to-trial flow (subscription terminates and customer returns to Trial). \"paid\" = paid-to-paid downgrade (subscription continues at the new lower price). Portal renders different banner copy for each variant.","type":"string","enum":["trial","paid"]},"targetPriceId":{"description":"Future Stripe Price ID the subscription will move to at effectiveAt. Null for cancel-to-trial (Trial has no Stripe Price). Webhook un-cancel branch compares this to the current price to distinguish \"downgrade completed\" from \"scheduled change cleared without reaching new price\".","anyOf":[{"type":"string"},{"type":"null"}]},"scheduleId":{"description":"Stripe Subscription Schedule ID when the change was scheduled via the SubscriptionSchedules API (paid-to-paid downgrades). Null for cancel_at_period_end-based changes (cancel-to-trial). Used by the undo endpoint to release the schedule cleanly.","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["effectiveAt","previousPlanSlug","previousPlanName","newPlanSlug","newPlanName","newMaxSources","newMaxDestinations","newMaxUsers","capChangesPreview","notifiedAt"],"additionalProperties":false},{"type":"null"}],"description":"Non-null while a downgrade is scheduled for next renewal. Read from customer.metadata.scheduledDowngrade — populated by the subscription.updated webhook handler."}},"required":["slug","name","monthlyPriceCents","creditAllotment","maxSources","maxDestinations","maxUsers","signalStacking","icpEditing","paygEnabled","addOnRatePerCredit","isInternal","stripeCustomerId","scheduledDowngrade"],"additionalProperties":false},"PublicPlansResponse":{"type":"object","properties":{"plans":{"type":"array","items":{"type":"object","properties":{"slug":{"type":"string","enum":["solo","pro","scale"],"description":"Customer-selectable plans only (excludes trial + internal)"},"name":{"type":"string"},"monthlyPriceCents":{"type":"integer","minimum":0,"maximum":9007199254740991},"creditAllotment":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"maxSources":{"anyOf":[{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},{"type":"null"}]},"maxDestinations":{"anyOf":[{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},{"type":"null"}]},"maxUsers":{"anyOf":[{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},{"type":"null"}]},"signalStacking":{"type":"boolean"},"icpEditing":{"type":"string","enum":["basic","advanced"]},"paygEnabled":{"type":"boolean"},"addOnRatePerCredit":{"anyOf":[{"type":"number"},{"type":"null"}]}},"required":["slug","name","monthlyPriceCents","creditAllotment","maxSources","maxDestinations","maxUsers","signalStacking","icpEditing","paygEnabled","addOnRatePerCredit"],"additionalProperties":false}}},"required":["plans"],"additionalProperties":false},"PaygPurchasesResponse":{"type":"object","properties":{"purchases":{"type":"array","items":{"$ref":"#/components/schemas/PaygPurchase"}},"hasMore":{"type":"boolean","description":"true when more rows exist past `limit`. Portal renders a hint pointing to Stripe Customer Portal for full history."}},"required":["purchases","hasMore"],"additionalProperties":false},"BillingInvoicesResponse":{"type":"object","properties":{"invoices":{"type":"array","items":{"$ref":"#/components/schemas/BillingInvoice"}},"hasMore":{"type":"boolean"}},"required":["invoices","hasMore"],"additionalProperties":false},"Source":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"Source ID"},"customerId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"sourceType":{"type":"string","enum":["own_company","competitor_company","competitor_company_broad","competitor_employee","keyword_search","industry_search","mention_tracking","hashtag_search","target_person","event_search"],"description":"Source type classification"},"linkedinUrl":{"type":"string","example":"https://www.linkedin.com/company/acme/"},"displayName":{"anyOf":[{"type":"string"},{"type":"null"}],"example":"Acme Corp"},"priority":{"type":"integer","minimum":1,"maximum":5,"example":3},"isActive":{"type":"boolean"},"metadata":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]},"topicFilter":{"anyOf":[{"type":"string"},{"type":"null"}]},"searchQuery":{"anyOf":[{"type":"string"},{"type":"null"}]},"industryCodes":{"anyOf":[{"type":"string"},{"type":"null"}]},"lastSeenPostId":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Most recent post ID seen during discovery"},"lastDiscoveryAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","customerId","sourceType","linkedinUrl","displayName","priority","isActive","metadata","topicFilter","searchQuery","industryCodes","lastSeenPostId","lastDiscoveryAt","createdAt"],"additionalProperties":false},"Destination":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"Destination ID"},"customerId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"destinationType":{"type":"string","enum":["google_sheet","clay_webhook","slack","webhook","n8n","notion"],"description":"Delivery channel type"},"name":{"type":"string","example":"Sales Team Slack"},"config":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{},"description":"Destination-specific configuration"},"routing":{"oneOf":[{"type":"object","properties":{"mode":{"type":"string","const":"all"}},"required":["mode"],"additionalProperties":false},{"type":"object","properties":{"mode":{"type":"string","const":"manual"}},"required":["mode"],"additionalProperties":false},{"type":"object","properties":{"mode":{"type":"string","const":"min_strength"},"minStrength":{"type":"integer","minimum":1,"maximum":10}},"required":["mode","minStrength"],"additionalProperties":false}],"description":"When to auto-route signals to this destination. Defaults to {mode:\"all\"}.","type":"object"},"isActive":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"signatureSecret":{"description":"HMAC secret used to sign outbound webhook deliveries (X-SignalRaven-Signature). Revealed once on create; rotate via POST :id/rotate-secret.","type":"string"}},"required":["id","customerId","destinationType","name","config","routing","isActive","createdAt"],"additionalProperties":false},"TeamListResponse":{"type":"object","properties":{"members":{"type":"array","items":{"type":"object","properties":{"userId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"email":{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"role":{"type":"string","enum":["admin","manager","prospector","user"]},"joinedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"lastLoginAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"isSelf":{"type":"boolean","description":"true if this row is the calling user"},"isPaused":{"type":"boolean","description":"True when the membership is paused (over-cap after a plan change). Paused members do not consume the seat cap and cannot sign in until reactivated. (Trial-to-Solo-seat-pause migration 0049)"},"pausedAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}],"description":"Timestamp when the membership was paused; null when isPaused=false."}},"required":["userId","email","role","joinedAt","lastLoginAt","isSelf","isPaused","pausedAt"],"additionalProperties":false}},"pendingInvites":{"type":"array","items":{"type":"object","properties":{"inviteId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"email":{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"role":{"type":"string","enum":["user","manager","prospector"]},"invitedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"expiresAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"inviterUserId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["inviteId","email","role","invitedAt","expiresAt","inviterUserId"],"additionalProperties":false}},"seatUsage":{"type":"object","properties":{"members":{"type":"integer","minimum":0,"maximum":9007199254740991,"description":"Active members (rows in customer_users)."},"pendingInvites":{"type":"integer","minimum":0,"maximum":9007199254740991,"description":"Non-accepted, non-expired invites — each counts against the cap."},"used":{"type":"integer","minimum":0,"maximum":9007199254740991,"description":"members + pendingInvites"},"cap":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Hard cap for this customer. null = unlimited (Scale + Internal plans; serialized from in-memory Infinity per #50 Day 3)."},"remaining":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"max(0, cap - used). null when cap is null (unlimited plan)."},"capReached":{"type":"boolean","description":"True when used >= cap — invites refused with 402 SeatCapReached. Always false for unlimited plans."}},"required":["members","pendingInvites","used","cap","remaining","capReached"],"additionalProperties":false}},"required":["members","pendingInvites","seatUsage"],"additionalProperties":false},"InviteResponse":{"type":"object","properties":{"inviteId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"email":{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"role":{"type":"string","enum":["user","manager","prospector"]},"expiresAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["inviteId","email","role","expiresAt"],"additionalProperties":false},"ChangeRoleResponse":{"type":"object","properties":{"userId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"fromRole":{"type":"string","enum":["admin","manager","prospector","user"]},"role":{"type":"string","enum":["admin","manager","prospector","user"]},"changed":{"type":"boolean"}},"required":["userId","role","changed"],"additionalProperties":false},"InviteStatus":{"oneOf":[{"type":"object","properties":{"status":{"type":"string","const":"valid"},"invitedEmail":{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"role":{"type":"string","enum":["user","manager","prospector"]},"customerName":{"type":"string"},"inviterName":{"type":"string"}},"required":["status","invitedEmail","role","customerName","inviterName"],"additionalProperties":false},{"type":"object","properties":{"status":{"type":"string","const":"expired"}},"required":["status"],"additionalProperties":false},{"type":"object","properties":{"status":{"type":"string","const":"already_accepted"}},"required":["status"],"additionalProperties":false},{"type":"object","properties":{"status":{"type":"string","const":"not_found"}},"required":["status"],"additionalProperties":false},{"type":"object","properties":{"status":{"type":"string","const":"email_already_user"}},"required":["status"],"additionalProperties":false},{"type":"object","properties":{"status":{"type":"string","const":"already_member"},"customerName":{"type":"string"}},"required":["status","customerName"],"additionalProperties":false}],"type":"object"},"ShareSignalResponse":{"type":"object","properties":{"shares":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"signalId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"toUserId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"message":{"anyOf":[{"type":"string"},{"type":"null"}]},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","signalId","toUserId","message","createdAt"],"additionalProperties":false}}},"required":["shares"],"additionalProperties":false},"CommentListResponse":{"type":"object","properties":{"comments":{"type":"array","items":{"$ref":"#/components/schemas/CreateCommentResponse"}}},"required":["comments"],"additionalProperties":false},"NotificationListResponse":{"type":"object","properties":{"unreadCount":{"type":"integer","minimum":0,"maximum":9007199254740991,"description":"Total unread for the current (user, customer). Drives the bell-icon badge."},"items":{"type":"array","items":{"$ref":"#/components/schemas/NotificationItem"}}},"required":["unreadCount","items"],"additionalProperties":false},"MarkReadResponse":{"type":"object","properties":{"updated":{"type":"integer","minimum":0,"maximum":9007199254740991,"description":"Count of rows whose read_at was set."},"unreadCount":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["updated","unreadCount"],"additionalProperties":false},"NotificationPrefs":{"type":"object","properties":{"emailSharedWithMe":{"type":"boolean","description":"Email when a teammate shares a signal with you. Default: true."},"emailMentioned":{"type":"boolean","description":"Email when a teammate @-mentions you. Default: true."},"emailCommentedOnMyShare":{"type":"boolean","description":"Email when a teammate comments on a signal you shared (and you are not the commenter). Default: false."},"emailRoleChanged":{"type":"boolean","description":"Email when an admin changes your role. Default: true."},"updatedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["emailSharedWithMe","emailMentioned","emailCommentedOnMyShare","emailRoleChanged","updatedAt"],"additionalProperties":false},"SignalActivityResponse":{"type":"object","properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/SignalActivityEvent"},"description":"Chronological events for the signal, newest-first. Today: shares + comments. Future: ratings + delivery events as #51 ships."}},"required":["events"],"additionalProperties":false},"MeTagCategoryListResponse":{"type":"object","properties":{"categories":{"type":"array","items":{"$ref":"#/components/schemas/TagCategory"}}},"required":["categories"],"additionalProperties":false},"TagCategoryCore":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"selectionMode":{"$ref":"#/components/schemas/TagSelectionMode"},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","name","selectionMode","createdAt"],"additionalProperties":false},"TagValueCore":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"SignalTagsResponse":{"type":"object","properties":{"tags":{"type":"array","items":{"$ref":"#/components/schemas/SignalTag"},"description":"Full post-mutation tag list for the signal, ordered by category then value name."}},"required":["tags"],"additionalProperties":false},"TagFacetsResponse":{"type":"object","properties":{"facets":{"type":"array","items":{"type":"object","properties":{"categoryId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"values":{"type":"array","items":{"type":"object","properties":{"valueId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["valueId","count"],"additionalProperties":false}},"noneCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Signals in the current filtered set with no value from this category."}},"required":["categoryId","values","noneCount"],"additionalProperties":false}}},"required":["facets"],"additionalProperties":false},"AuditEventListResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/AuditEvent"}},"nextCursor":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Opaque pagination cursor. Pass back via ?cursor= to get the next (older) page. Null when there are no more rows. Page size is fixed via the ?limit query param (default 50, max 100)."}},"required":["items","nextCursor"],"additionalProperties":false},"CancelToTrialResponse":{"type":"object","properties":{"ok":{"type":"boolean","const":true},"effectiveAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$","description":"ISO timestamp of when the downgrade takes effect (= current period_end). After this date, the customer is on the Trial plan with no auto-allotment; existing credits expire via the local-expiry cron."},"subscriptionId":{"type":"string","description":"Stripe subscription id that was scheduled for cancellation."},"previousPlanSlug":{"type":"string","description":"Plan slug the customer is downgrading FROM (e.g. \"pro\"). Used by the portal to render the confirmation."},"creditsRemaining":{"type":"integer","minimum":0,"maximum":9007199254740991,"description":"Credit balance at the time the downgrade was scheduled. Carries through until effectiveAt."}},"required":["ok","effectiveAt","subscriptionId","previousPlanSlug","creditsRemaining"],"additionalProperties":false},"Customer":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"Customer ID"},"name":{"type":"string","example":"Acme Corp"},"slug":{"type":"string","example":"acme-corp"},"settings":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}],"description":"Customer settings bag"},"productDescription":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Product/service description"},"lifecyclePhase":{"type":"string","description":"Customer lifecycle phase","example":"active"},"isActive":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"updatedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","name","slug","settings","productDescription","lifecyclePhase","isActive","createdAt","updatedAt"],"additionalProperties":false},"SignalSubscription":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"customerId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"signalType":{"type":"string"},"isEnabled":{"type":"boolean"},"minStrength":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","customerId","signalType","isEnabled","minStrength","createdAt"],"additionalProperties":false},"SignalListResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Signal"}},"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Total matching items"},"limit":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"offset":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["items","total","limit","offset"],"additionalProperties":false},"CreateIcpBody":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"minEmployees":{"type":"integer","minimum":1,"maximum":9007199254740991},"maxEmployees":{"type":"integer","minimum":1,"maximum":9007199254740991},"targetIndustries":{"type":"array","items":{"type":"string"}},"targetTitles":{"type":"array","items":{"type":"string"}},"excludeTitles":{"type":"array","items":{"type":"string"}},"targetPersonas":{"type":"array","items":{"type":"string"}},"additionalContext":{"type":"string"},"targetLocations":{"type":"array","items":{"type":"string"}},"targetBuyerIndustries":{"type":"array","items":{"type":"string"}},"buyerContext":{"type":"string"},"targetSeniority":{"type":"array","items":{"type":"string"}},"productCategory":{"type":"string"},"classificationExamples":{"type":"string"},"excludeInfluencers":{"type":"boolean"},"matchWeights":{"type":"object","properties":{"title":{"type":"number","minimum":0,"maximum":100},"marketAffinity":{"type":"number","minimum":0,"maximum":100},"industry":{"type":"number","minimum":0,"maximum":100},"companySize":{"type":"number","minimum":0,"maximum":100},"location":{"type":"number","minimum":0,"maximum":100}},"required":["title","marketAffinity","industry","companySize","location"],"additionalProperties":false},"minCompositeScore":{"type":"integer","minimum":0,"maximum":100},"isDefault":{"type":"boolean"}},"required":["name"],"additionalProperties":false},"UpdateIcpBody":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"minEmployees":{"type":"integer","minimum":1,"maximum":9007199254740991},"maxEmployees":{"type":"integer","minimum":1,"maximum":9007199254740991},"targetIndustries":{"type":"array","items":{"type":"string"}},"targetTitles":{"type":"array","items":{"type":"string"}},"excludeTitles":{"type":"array","items":{"type":"string"}},"targetPersonas":{"type":"array","items":{"type":"string"}},"additionalContext":{"type":"string"},"targetLocations":{"type":"array","items":{"type":"string"}},"targetBuyerIndustries":{"type":"array","items":{"type":"string"}},"buyerContext":{"type":"string"},"targetSeniority":{"type":"array","items":{"type":"string"}},"productCategory":{"type":"string"},"classificationExamples":{"type":"string"},"excludeInfluencers":{"type":"boolean"},"matchWeights":{"type":"object","properties":{"title":{"type":"number","minimum":0,"maximum":100},"marketAffinity":{"type":"number","minimum":0,"maximum":100},"industry":{"type":"number","minimum":0,"maximum":100},"companySize":{"type":"number","minimum":0,"maximum":100},"location":{"type":"number","minimum":0,"maximum":100}},"required":["title","marketAffinity","industry","companySize","location"],"additionalProperties":false},"minCompositeScore":{"type":"integer","minimum":0,"maximum":100},"isDefault":{"type":"boolean"}},"additionalProperties":false},"UpsertSubscriptionsBody":{"type":"array","items":{"type":"object","properties":{"signalType":{"type":"string","enum":["COMPETITOR_POST_COMMENT","COMPETITOR_POST_REACTION","CUSTOMER_POST_COMMENT","CUSTOMER_POST_REACTION","COMPETITOR_EMPLOYEE_POST_COMMENT","COMPETITOR_EMPLOYEE_POST_REACTION","KEYWORD_SEARCH_COMMENT","KEYWORD_SEARCH_REACTION","INDUSTRY_SEARCH_COMMENT","INDUSTRY_SEARCH_REACTION","MENTION_TRACKING_COMMENT","MENTION_TRACKING_REACTION","HASHTAG_SEARCH_COMMENT","HASHTAG_SEARCH_REACTION","EVENT_SEARCH_COMMENT","EVENT_SEARCH_REACTION","EVENT_SEARCH_POST","TARGET_PERSON_POST","TARGET_PERSON_REPOST","TARGET_PERSON_COMMENT","TARGET_PERSON_REACTION","JOB_CHANGE","PROMOTION_SCOPE_EXPANSION","COMPANY_HEADCOUNT_TREND","INTELLIGENCE_PUSH_ACTIVITY"]},"isEnabled":{"type":"boolean"},"minStrength":{"type":"integer","minimum":1,"maximum":10}},"required":["signalType","isEnabled"],"additionalProperties":false}},"CreateDestinationBody":{"type":"object","properties":{"destinationType":{"type":"string","enum":["google_sheet","clay_webhook","slack","webhook","n8n","notion"]},"name":{"type":"string","minLength":1,"maxLength":255},"config":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"routing":{"oneOf":[{"type":"object","properties":{"mode":{"type":"string","const":"all"}},"required":["mode"],"additionalProperties":false},{"type":"object","properties":{"mode":{"type":"string","const":"manual"}},"required":["mode"],"additionalProperties":false},{"type":"object","properties":{"mode":{"type":"string","const":"min_strength"},"minStrength":{"type":"integer","minimum":1,"maximum":10}},"required":["mode","minStrength"],"additionalProperties":false}],"type":"object"}},"required":["destinationType","name","config"],"additionalProperties":false},"CreateCustomerBody":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"slug":{"type":"string","minLength":1,"maxLength":100},"settings":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["name"],"additionalProperties":false},"UpdateCustomerBody":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"settings":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"isActive":{"type":"boolean"},"productDescription":{"type":"string"}},"additionalProperties":false},"Comment":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"authorUserId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"authorEmail":{"anyOf":[{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},{"type":"null"}]},"authorRemoved":{"type":"boolean","description":"True when the author is no longer a member of this customer (their customer_users link was deleted). The FE renders \"(removed)\" alongside the email."},"body":{"type":"string","description":"Empty string when deleted is true (the original text is redacted server-side to preserve privacy)."},"mentionedUserIds":{"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"mentionedEmails":{"type":"array","items":{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"}},"deleted":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","authorUserId","authorEmail","authorRemoved","body","mentionedUserIds","deleted","createdAt"],"additionalProperties":false}},"securitySchemes":{"cookieAuth":{"type":"apiKey","in":"cookie","name":"session"},"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"OAuth 2.1 bearer token from auth.signalraven.ai (see /developers)."}}}}