openapi: 3.0.3 info: title: traxy Customer API and MCP V1 version: 1.0.0 description: | Public customer-facing read API, Ordinal Audience Analytics endpoints, and remote MCP Streamable HTTP endpoint. Customer REST and Ordinal requests use bearer API keys. MCP uses OAuth access tokens issued for the traxy MCP resource; API keys are never accepted by MCP. Public REST clients must not send organizationId. Default API keys cover the general read API. Ordinal Audience Analytics is self-serve for paid workspaces and requires explicitly selected audience_analytics scopes on the key. The current MCP surface exposes 48 scope-gated tools through tools/list, including multi-workspace selection, confirmed lead, ICP, Signal Brief, Agent, Watchlist, post, Meetings, and delivery actions. MCP protocol versions 2025-11-25 (current) and 2025-06-18 are supported. servers: - url: https://api.traxy.ai/api/v1 description: Production security: - CustomerApiKey: [] tags: - name: Customer REST - name: Ordinal Audience Analytics - name: MCP OAuth - name: MCP paths: /customer/analytics/meetings: get: tags: - Customer REST summary: Get Meetings booked attribution counts. description: Uses the credential workspace and verifies its creator still has workspace read access. The feed omits meetingWith unless leads:contact_read is granted; source calendars and provider payloads are never returned. security: - CustomerApiKey: - analytics:read parameters: - &a1 in: query name: range schema: type: string enum: - 7d - 30d - 90d - all default: 30d responses: "200": description: Meetings read result content: application/json: schema: $ref: "#/components/schemas/CustomerMeetingsSummary" "400": $ref: "#/components/responses/ValidationFailed" "401": $ref: "#/components/responses/Unauthorized" "403": description: Read capability or active workspace membership required. "503": description: Meetings temporarily unavailable; retry after the Retry-After header. headers: Retry-After: schema: type: integer example: 1 /customer/meetings: get: tags: - Customer REST summary: List attributed Meetings with snapshot cursor pagination. description: Uses the credential workspace and verifies its creator still has workspace read access. The feed omits meetingWith unless leads:contact_read is granted; source calendars and provider payloads are never returned. security: - CustomerApiKey: - leads:read parameters: - *a1 - in: query name: limit schema: type: integer minimum: 1 maximum: 100 default: 50 - in: query name: cursor schema: type: string maxLength: 512 - in: query name: leadId schema: type: string format: uuid - in: query name: targetType schema: type: string enum: - PERSON - COMPANY responses: "200": description: Meetings read result content: application/json: schema: $ref: "#/components/schemas/CustomerMeetingsFeed" "400": $ref: "#/components/responses/ValidationFailed" "401": $ref: "#/components/responses/Unauthorized" "403": description: Read capability or active workspace membership required. "503": description: Meetings temporarily unavailable; retry after the Retry-After header. headers: Retry-After: schema: type: integer example: 1 /customer/workspace-access: get: tags: [Customer REST] summary: Get business-facing workspace data access. security: - CustomerApiKey: [workspace:read] responses: '200': description: API-visible workspace capabilities and usage. content: application/json: schema: $ref: '#/components/schemas/WorkspaceAccess' '401': $ref: '#/components/responses/Unauthorized' '402': $ref: '#/components/responses/InsufficientCapability' '429': $ref: '#/components/responses/RateLimited' /customer/leads: get: tags: [Customer REST] summary: List API-visible leads. security: - CustomerApiKey: [leads:read] parameters: - $ref: '#/components/parameters/Limit' - $ref: '#/components/parameters/Cursor' - $ref: '#/components/parameters/LeadTierFilter' - $ref: '#/components/parameters/LeadTiersFilter' - $ref: '#/components/parameters/LeadDispositionFilter' - $ref: '#/components/parameters/LeadDispositionsFilter' - $ref: '#/components/parameters/MinIcpMatchPercentFilter' - $ref: '#/components/parameters/MaxIcpMatchPercentFilter' - $ref: '#/components/parameters/MonitoredProfileIdFilter' - $ref: '#/components/parameters/MonitoredProfileIdsFilter' - $ref: '#/components/parameters/PostIdFilter' - $ref: '#/components/parameters/EngagementTypeFilter' - $ref: '#/components/parameters/EngagementTypesFilter' - $ref: '#/components/parameters/OwnerIdFilter' - $ref: '#/components/parameters/OwnerIdsFilter' - $ref: '#/components/parameters/DateFromFilter' - $ref: '#/components/parameters/DateToFilter' - $ref: '#/components/parameters/SearchQueryFilter' - $ref: '#/components/parameters/CompanyNamesFilter' - $ref: '#/components/parameters/LeadOriginFilter' responses: '200': description: Lead page. Contact fields are null unless the credential has leads:contact_read. content: application/json: schema: $ref: '#/components/schemas/LeadPage' '400': $ref: '#/components/responses/ValidationFailed' '401': $ref: '#/components/responses/Unauthorized' '402': $ref: '#/components/responses/InsufficientCapability' '429': $ref: '#/components/responses/RateLimited' /customer/leads/signals: get: tags: [Customer REST] summary: List visible lead signals with safe lead, post, and watched-profile context. security: - CustomerApiKey: [leads:read] parameters: - $ref: '#/components/parameters/Limit' - $ref: '#/components/parameters/Cursor' - $ref: '#/components/parameters/LeadIdFilter' - $ref: '#/components/parameters/MonitoredProfileIdFilter' - $ref: '#/components/parameters/MonitoredProfileIdsFilter' - $ref: '#/components/parameters/PostIdFilter' - $ref: '#/components/parameters/EngagementTypeFilter' - $ref: '#/components/parameters/EngagementTypesFilter' - $ref: '#/components/parameters/DateFromFilter' - $ref: '#/components/parameters/DateToFilter' - $ref: '#/components/parameters/MinIcpMatchPercentFilter' - $ref: '#/components/parameters/MaxIcpMatchPercentFilter' - $ref: '#/components/parameters/LeadDispositionFilter' - $ref: '#/components/parameters/SearchQueryFilter' - $ref: '#/components/parameters/CompanyNamesFilter' - $ref: '#/components/parameters/ProfileTypeFilter' - $ref: '#/components/parameters/RelationshipLabelFilter' - $ref: '#/components/parameters/LeadOriginFilter' responses: '200': description: Lead engagement page with a nullable canonical signal on each record and lead. content: application/json: schema: $ref: '#/components/schemas/LeadSignalPage' '400': $ref: '#/components/responses/ValidationFailed' '401': $ref: '#/components/responses/Unauthorized' '402': $ref: '#/components/responses/InsufficientCapability' '429': $ref: '#/components/responses/RateLimited' /customer/leads/counts: get: tags: [Customer REST] summary: Get API-visible lead counts. security: - CustomerApiKey: [leads:read] responses: '200': description: Lead counts grouped by tier/status. content: application/json: schema: type: object additionalProperties: true '401': $ref: '#/components/responses/Unauthorized' '402': $ref: '#/components/responses/InsufficientCapability' /customer/leads/stats: get: tags: [Customer REST] summary: Get aggregate lead stats. security: - CustomerApiKey: [leads:read] responses: '200': description: Aggregate lead stats. content: application/json: schema: type: object additionalProperties: true '401': $ref: '#/components/responses/Unauthorized' '402': $ref: '#/components/responses/InsufficientCapability' /customer/leads/{leadId}: get: tags: [Customer REST] summary: Get one API-visible lead. security: - CustomerApiKey: [leads:read] parameters: - $ref: '#/components/parameters/LeadId' responses: '200': description: Lead detail. content: application/json: schema: type: object required: [data] properties: data: $ref: '#/components/schemas/Lead' '400': $ref: '#/components/responses/ValidationFailed' '401': $ref: '#/components/responses/Unauthorized' '402': $ref: '#/components/responses/InsufficientCapability' '404': $ref: '#/components/responses/NotFound' /customer/leads/{leadId}/engagements: get: tags: [Customer REST] summary: List safe engagement summaries for one lead. security: - CustomerApiKey: [leads:read] parameters: - $ref: '#/components/parameters/LeadId' - $ref: '#/components/parameters/Limit' - $ref: '#/components/parameters/Cursor' - $ref: '#/components/parameters/EngagementTypeFilter' - $ref: '#/components/parameters/MonitoredProfileIdFilter' - $ref: '#/components/parameters/PostIdFilter' - $ref: '#/components/parameters/DateFromFilter' - $ref: '#/components/parameters/DateToFilter' responses: '200': description: Engagement page. content: application/json: schema: $ref: '#/components/schemas/PageEnvelope' '400': $ref: '#/components/responses/ValidationFailed' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' /customer/icp: get: tags: [Customer REST] summary: Get active ICP configuration. security: - CustomerApiKey: [icp:read] responses: '200': $ref: '#/components/responses/DataObject' '401': $ref: '#/components/responses/Unauthorized' '402': $ref: '#/components/responses/InsufficientCapability' /customer/icp/active: get: tags: [Customer REST] summary: Get active ICP configuration. security: - CustomerApiKey: [icp:read] responses: '200': $ref: '#/components/responses/DataObject' '401': $ref: '#/components/responses/Unauthorized' '402': $ref: '#/components/responses/InsufficientCapability' /customer/watchlist/profiles: get: tags: [Customer REST] summary: List watchlist profiles. security: - CustomerApiKey: [watchlist:read] parameters: - $ref: '#/components/parameters/Limit' - $ref: '#/components/parameters/Cursor' - $ref: '#/components/parameters/ProfileTypeFilter' - $ref: '#/components/parameters/ProfileTypesFilter' - $ref: '#/components/parameters/MonitoredProfileSourceFilter' - $ref: '#/components/parameters/SlotKindFilter' - $ref: '#/components/parameters/RelationshipLabelFilter' - $ref: '#/components/parameters/WatchlistStateFilter' - $ref: '#/components/parameters/SearchQueryFilter' - $ref: '#/components/parameters/WatchlistSortFilter' - $ref: '#/components/parameters/SortDirectionFilter' responses: '200': $ref: '#/components/responses/PageObject' '400': $ref: '#/components/responses/ValidationFailed' '401': $ref: '#/components/responses/Unauthorized' '402': $ref: '#/components/responses/InsufficientCapability' /customer/watchlist/profiles/{monitoredProfileId}: get: tags: [Customer REST] summary: Get one monitored profile with safe relationship and follower metadata. security: - CustomerApiKey: [watchlist:read] parameters: - $ref: '#/components/parameters/MonitoredProfileIdPath' responses: '200': $ref: '#/components/responses/DataObject' '400': $ref: '#/components/responses/ValidationFailed' '401': $ref: '#/components/responses/Unauthorized' '402': $ref: '#/components/responses/InsufficientCapability' '404': $ref: '#/components/responses/NotFound' /customer/watchlist/summary: get: tags: [Customer REST] summary: Get watchlist summary. security: - CustomerApiKey: [watchlist:read] responses: '200': $ref: '#/components/responses/DataObject' '401': $ref: '#/components/responses/Unauthorized' /customer/watchlist/recommendations: get: tags: [Customer REST] summary: List watchlist recommendations. security: - CustomerApiKey: [watchlist:read] responses: '200': $ref: '#/components/responses/DataObject' '401': $ref: '#/components/responses/Unauthorized' /customer/analytics/dashboard: get: tags: [Customer REST] summary: Get aggregate analytics dashboard. security: - CustomerApiKey: [analytics:read] parameters: - $ref: '#/components/parameters/Range' responses: '200': $ref: '#/components/responses/DataObject' '400': $ref: '#/components/responses/ValidationFailed' '401': $ref: '#/components/responses/Unauthorized' /customer/analytics/posts: get: tags: [Customer REST] summary: List post analytics, including safe postUrl and contentText. security: - CustomerApiKey: [analytics:read] parameters: - $ref: '#/components/parameters/Limit' - $ref: '#/components/parameters/Cursor' - $ref: '#/components/parameters/MonitoredProfileIdFilter' - $ref: '#/components/parameters/MonitoredProfileIdsFilter' - $ref: '#/components/parameters/ProfileTypeFilter' - $ref: '#/components/parameters/RelationshipLabelFilter' - $ref: '#/components/parameters/MonitoredProfileSourceFilter' - $ref: '#/components/parameters/DateFromFilter' - $ref: '#/components/parameters/DateToFilter' - $ref: '#/components/parameters/MinIcpMatchPercentFilter' - $ref: '#/components/parameters/ContentStatusFilter' - $ref: '#/components/parameters/SearchQueryFilter' - $ref: '#/components/parameters/ContentSortFilter' - $ref: '#/components/parameters/SortDirectionFilter' responses: '200': $ref: '#/components/responses/PageObject' '400': $ref: '#/components/responses/ValidationFailed' '401': $ref: '#/components/responses/Unauthorized' /customer/analytics/posts/{postId}/summary: get: tags: [Customer REST] summary: Get one post summary, including safe postUrl and contentText. security: - CustomerApiKey: [analytics:read] parameters: - $ref: '#/components/parameters/PostId' responses: '200': $ref: '#/components/responses/DataObject' '400': $ref: '#/components/responses/ValidationFailed' '404': $ref: '#/components/responses/NotFound' /customer/analytics/posts/{postId}/qualified-leads: get: tags: [Customer REST] summary: List qualified leads for one post. security: - CustomerApiKey: [analytics:read] parameters: - $ref: '#/components/parameters/PostId' - $ref: '#/components/parameters/Limit' - $ref: '#/components/parameters/Cursor' responses: '200': $ref: '#/components/responses/PageObject' '400': $ref: '#/components/responses/ValidationFailed' '404': $ref: '#/components/responses/NotFound' /customer/content-feed: get: tags: [Customer REST] summary: List content feed posts, including safe postUrl and contentText. security: - CustomerApiKey: [content:read] parameters: - $ref: '#/components/parameters/Limit' - $ref: '#/components/parameters/Cursor' - $ref: '#/components/parameters/MonitoredProfileIdFilter' - $ref: '#/components/parameters/MonitoredProfileIdsFilter' - $ref: '#/components/parameters/ProfileTypeFilter' - $ref: '#/components/parameters/RelationshipLabelFilter' - $ref: '#/components/parameters/MonitoredProfileSourceFilter' - $ref: '#/components/parameters/DateFromFilter' - $ref: '#/components/parameters/DateToFilter' - $ref: '#/components/parameters/MinIcpMatchPercentFilter' - $ref: '#/components/parameters/ContentStatusFilter' - $ref: '#/components/parameters/SearchQueryFilter' - $ref: '#/components/parameters/ContentSortFilter' - $ref: '#/components/parameters/SortDirectionFilter' responses: '200': $ref: '#/components/responses/PageObject' '400': $ref: '#/components/responses/ValidationFailed' '401': $ref: '#/components/responses/Unauthorized' /customer/content/feed: get: tags: [Customer REST] summary: List content feed posts, including safe postUrl and contentText. security: - CustomerApiKey: [content:read] parameters: - $ref: '#/components/parameters/Limit' - $ref: '#/components/parameters/Cursor' - $ref: '#/components/parameters/MonitoredProfileIdFilter' - $ref: '#/components/parameters/MonitoredProfileIdsFilter' - $ref: '#/components/parameters/ProfileTypeFilter' - $ref: '#/components/parameters/RelationshipLabelFilter' - $ref: '#/components/parameters/MonitoredProfileSourceFilter' - $ref: '#/components/parameters/DateFromFilter' - $ref: '#/components/parameters/DateToFilter' - $ref: '#/components/parameters/MinIcpMatchPercentFilter' - $ref: '#/components/parameters/ContentStatusFilter' - $ref: '#/components/parameters/SearchQueryFilter' - $ref: '#/components/parameters/ContentSortFilter' - $ref: '#/components/parameters/SortDirectionFilter' responses: '200': $ref: '#/components/responses/PageObject' '400': $ref: '#/components/responses/ValidationFailed' '401': $ref: '#/components/responses/Unauthorized' /customer/account-reports: get: tags: [Customer REST] summary: List account-level summaries derived from visible active leads. security: - CustomerApiKey: [leads:read] parameters: - $ref: '#/components/parameters/Limit' - $ref: '#/components/parameters/Cursor' - $ref: '#/components/parameters/CompanyNameFilter' - $ref: '#/components/parameters/MinIcpMatchPercentFilter' - $ref: '#/components/parameters/MaxIcpMatchPercentFilter' - $ref: '#/components/parameters/DateFromFilter' - $ref: '#/components/parameters/DateToFilter' - $ref: '#/components/parameters/SearchQueryFilter' - $ref: '#/components/parameters/AccountSortFilter' - $ref: '#/components/parameters/SortDirectionFilter' responses: '200': $ref: '#/components/responses/PageObject' '400': $ref: '#/components/responses/ValidationFailed' '401': $ref: '#/components/responses/Unauthorized' '402': $ref: '#/components/responses/InsufficientCapability' /customer/account-reports/{accountId}: get: tags: [Customer REST] summary: Get one account summary with top visible leads. security: - CustomerApiKey: [leads:read] parameters: - $ref: '#/components/parameters/AccountIdPath' - $ref: '#/components/parameters/MinIcpMatchPercentFilter' - $ref: '#/components/parameters/MaxIcpMatchPercentFilter' - $ref: '#/components/parameters/DateFromFilter' - $ref: '#/components/parameters/DateToFilter' responses: '200': $ref: '#/components/responses/DataObject' '400': $ref: '#/components/responses/ValidationFailed' '401': $ref: '#/components/responses/Unauthorized' '402': $ref: '#/components/responses/InsufficientCapability' '404': $ref: '#/components/responses/NotFound' /customer/integrations: get: tags: [Customer REST] summary: Get safe integration status. security: - CustomerApiKey: [integrations:read] responses: '200': $ref: '#/components/responses/DataObject' '401': $ref: '#/components/responses/Unauthorized' /customer/integrations/status: get: tags: [Customer REST] summary: Get safe integration status. security: - CustomerApiKey: [integrations:read] responses: '200': $ref: '#/components/responses/DataObject' '401': $ref: '#/components/responses/Unauthorized' /customer/integrations/leads/{leadId}/delivery: get: tags: [Customer REST] summary: Get lead delivery state. security: - CustomerApiKey: [integrations:read] parameters: - $ref: '#/components/parameters/LeadId' responses: '200': $ref: '#/components/responses/DataObject' '400': $ref: '#/components/responses/ValidationFailed' /customer/integrations/lead-delivery-state: get: tags: [Customer REST] summary: Get lead delivery state. security: - CustomerApiKey: [integrations:read] parameters: - name: leadId in: query required: true schema: type: string format: uuid responses: '200': $ref: '#/components/responses/DataObject' '400': $ref: '#/components/responses/ValidationFailed' /customer/sync/status: get: tags: [Customer REST] summary: Get sync status. security: - CustomerApiKey: [sync:read] responses: '200': $ref: '#/components/responses/DataObject' '401': $ref: '#/components/responses/Unauthorized' /customer/qualification/runs/latest: get: tags: [Customer REST] summary: Get latest qualification run. security: - CustomerApiKey: [sync:read] responses: '200': $ref: '#/components/responses/DataObject' '401': $ref: '#/components/responses/Unauthorized' /audience-analytics/health: get: tags: [Ordinal Audience Analytics] summary: Check Audience Analytics readiness for the key workspace. security: - CustomerApiKey: [audience_analytics:read] responses: '200': $ref: '#/components/responses/AudienceObject' '401': $ref: '#/components/responses/Unauthorized' '402': $ref: '#/components/responses/InsufficientCapability' /audience-analytics/linkedin-posts: get: tags: [Ordinal Audience Analytics] summary: Get aggregate-only audience analytics for a LinkedIn post. security: - CustomerApiKey: [audience_analytics:read] parameters: - name: postUrn in: query required: true description: LinkedIn post URN (`urn:li:activity:...`, `urn:li:share:...`, `urn:li:ugcPost:...`) or a LinkedIn `feed/update` URL containing one of those URNs. schema: type: string maxLength: 1024 examples: activityUrn: value: urn:li:activity:123456789 feedUpdateUrl: value: https://www.linkedin.com/feed/update/urn:li:share:123456789/ responses: '200': $ref: '#/components/responses/AudienceObject' '400': $ref: '#/components/responses/ValidationFailed' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/UnresolvedUrn' /audience-analytics/linkedin-posts/find-audience: post: tags: [Ordinal Audience Analytics] summary: Request on-demand audience discovery for one exact LinkedIn post. description: Resolves the supplied LinkedIn reference to one immutable post, prepares an exact qualification quote, and accepts the request only after its complete credit reservation succeeds. Replays with the same idempotency key and payload reuse the durable request. An incompatible replay returns 409. security: - CustomerApiKey: [audience_analytics:request] requestBody: required: true content: application/json: schema: type: object required: [postUrn] additionalProperties: false properties: postUrn: type: string maxLength: 1024 description: LinkedIn post URN or `feed/update` URL containing a LinkedIn post URN. idempotencyKey: type: string maxLength: 120 responses: '202': description: Discovery is already available, waiting for quote preparation, or represented by a durable qualification request. content: application/json: schema: $ref: '#/components/schemas/AudienceDiscoveryResponse' '400': $ref: '#/components/responses/ValidationFailed' '401': $ref: '#/components/responses/Unauthorized' '402': description: The full exact quote could not be reserved. No qualification request was created. content: application/json: schema: $ref: '#/components/schemas/ErrorEnvelope' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/UnresolvedUrn' '429': $ref: '#/components/responses/RateLimited' /audience-analytics/organization: get: tags: [Ordinal Audience Analytics] summary: Get aggregate audience breakdown for the key workspace. security: - CustomerApiKey: [audience_analytics:read] parameters: - $ref: '#/components/parameters/Range' - name: dimension in: query schema: type: string enum: [title, companySize, location, industry] default: industry responses: '200': $ref: '#/components/responses/AudienceObject' '400': $ref: '#/components/responses/ValidationFailed' '401': $ref: '#/components/responses/Unauthorized' '402': $ref: '#/components/responses/InsufficientCapability' /mcp/oauth/register: post: tags: [MCP OAuth] summary: Register a public MCP OAuth client. description: Dynamic Client Registration for public clients. Redirect URIs must be safe loopback URIs or explicitly allowlisted HTTPS origins. security: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/McpOAuthClientRegistrationRequest' responses: '201': description: Registered public client metadata. content: application/json: schema: $ref: '#/components/schemas/McpOAuthClientRegistrationResponse' '400': $ref: '#/components/responses/ValidationFailed' /mcp/oauth/authorize: get: tags: [MCP OAuth] summary: Start MCP OAuth authorization. description: Validates client, redirect URI, resource, scopes, and PKCE challenge, then redirects to the traxy consent screen. security: [] parameters: - name: response_type in: query required: true schema: type: string enum: [code] - name: client_id in: query required: true schema: type: string - name: redirect_uri in: query required: true schema: type: string format: uri - name: code_challenge in: query required: true schema: type: string - name: code_challenge_method in: query required: true schema: type: string enum: [S256] - name: scope in: query schema: type: string - name: resource in: query schema: type: string format: uri - name: state in: query schema: type: string responses: '302': description: Redirect to traxy consent screen. '400': $ref: '#/components/responses/ValidationFailed' /mcp/oauth/authorize/request: get: tags: [MCP OAuth] summary: Preview a pending MCP OAuth authorization request. security: - SupabaseUserJwt: [] parameters: - name: request in: query required: true schema: type: string responses: '200': description: Safe consent-screen metadata. content: application/json: schema: $ref: '#/components/schemas/McpOAuthAuthorizationPreview' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' /mcp/oauth/authorize/permissions: post: tags: [MCP OAuth] summary: Preview current account permissions in selected workspaces. description: Read-only authenticated preview. The request token stays in the body. Each workspace must pass current membership and MCP availability checks. security: - SupabaseUserJwt: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/McpOAuthAuthorizationPermissionsRequest' responses: '200': description: Available scope ceiling and per-workspace scopes. Response is not cacheable. content: application/json: schema: $ref: '#/components/schemas/McpOAuthAuthorizationPermissions' '400': $ref: '#/components/responses/ValidationFailed' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/InsufficientCapability' /mcp/oauth/authorize/complete: post: tags: [MCP OAuth] summary: Approve or cancel MCP OAuth authorization from traxy. description: Every active member may approve the requested actions permitted by their current role and MCP entitlement in the selected workspaces. Submitted scopes cap consent; each tool call also enforces the current role. Cancellation returns an access_denied callback. security: - SupabaseUserJwt: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/McpOAuthAuthorizeCompleteRequest' responses: '200': description: Redirect URL for the MCP client callback. content: application/json: schema: $ref: '#/components/schemas/McpOAuthAuthorizeCompleteResponse' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/InsufficientCapability' /mcp/oauth/token: post: tags: [MCP OAuth] summary: Exchange an authorization code or refresh token. description: Supports authorization_code with PKCE S256 and refresh_token with rotation. security: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/McpOAuthTokenRequest' responses: '200': description: MCP OAuth token response. content: application/json: schema: $ref: '#/components/schemas/McpOAuthTokenResponse' '400': $ref: '#/components/responses/ValidationFailed' '401': $ref: '#/components/responses/McpUnauthorized' /mcp/oauth/revoke: post: tags: [MCP OAuth] summary: Revoke an MCP OAuth token. security: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/McpOAuthRevokeRequest' responses: '200': description: Token revoke accepted. content: application/json: schema: type: object additionalProperties: false /mcp: get: tags: [MCP] summary: MCP GET sessions are not enabled in V1. security: - McpOAuth: [] responses: '405': $ref: '#/components/responses/MethodNotAllowed' post: tags: [MCP] summary: Streamable HTTP JSON-RPC endpoint for remote MCP clients. security: - McpOAuth: [] parameters: - name: Accept in: header required: true schema: type: string example: 'application/json, text/event-stream' - name: MCP-Protocol-Version in: header required: false schema: type: string example: '2025-11-25' description: Use the version negotiated during initialize, either 2025-11-25 (current) or 2025-06-18. The header may be omitted until negotiation completes. - name: Origin in: header schema: type: string description: Requests from a browser origin must come from an origin allowed by traxy. Non-browser clients can omit this header. requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/McpJsonRpcRequest' responses: '200': description: JSON-RPC response. content: application/json: schema: $ref: '#/components/schemas/McpJsonRpcResponse' examples: toolsListRepresentative: summary: Representative tools/list response with current MCP annotations. value: jsonrpc: '2.0' id: 2 result: tools: - name: traxy_get_workspace_access title: Get workspace access description: Return visible workspace access, usage, and capabilities. inputSchema: type: object properties: {} additionalProperties: false annotations: readOnlyHint: true outputSchema: type: object additionalProperties: true - name: traxy_get_mcp_connection_status title: Get MCP connection status description: Return safe diagnostics for the authenticated MCP connection. inputSchema: type: object properties: {} additionalProperties: false annotations: readOnlyHint: true outputSchema: type: object additionalProperties: true - name: traxy_get_agent_status title: Get agent status description: Return safe read-only status for the automated lead-finding agent. inputSchema: type: object properties: {} additionalProperties: false annotations: readOnlyHint: true outputSchema: type: object additionalProperties: true - name: traxy_list_agent_candidates title: List agent candidates description: List safe visible candidates for one agent run, the latest agent run, or the latest preview with locked-count availability. inputSchema: type: object properties: runId: type: string format: uuid source: type: string enum: [latest_agent_run, latest_onboarding_preview] limit: type: number minimum: 1 maximum: 100 offset: type: number minimum: 0 maximum: 10000 additionalProperties: false annotations: readOnlyHint: true outputSchema: type: object additionalProperties: true toolArgumentValidationError: summary: Known, authorized tool with model-correctable invalid arguments. value: jsonrpc: '2.0' id: call-1 result: content: - type: text text: '{"error":{"code":"validation_failed","message":"Tool traxy_get_lead failed input validation. Fix the arguments and retry.","issues":[{"path":"arguments.leadId","code":"invalid_string","message":"Invalid uuid"}]}}' structuredContent: error: code: validation_failed message: Tool traxy_get_lead failed input validation. Fix the arguments and retry. issues: - path: arguments.leadId code: invalid_string message: Invalid uuid isError: true '202': description: Notification accepted. The response has no body. '400': $ref: '#/components/responses/McpBadRequest' '401': $ref: '#/components/responses/McpUnauthorized' '403': $ref: '#/components/responses/McpOriginNotAllowed' '429': $ref: '#/components/responses/RateLimited' components: securitySchemes: CustomerApiKey: type: http scheme: bearer bearerFormat: trxy_live__ description: API key created from Integrations > API & MCP > API keys. Used for Customer REST and Ordinal Audience Analytics, not MCP OAuth. McpOAuth: type: http scheme: bearer bearerFormat: JWT description: Short-lived OAuth access token issued by traxy for the MCP resource. SupabaseUserJwt: type: http scheme: bearer bearerFormat: Supabase JWT description: Authenticated traxy app session token used by the consent screen. parameters: Limit: name: limit in: query description: Number of items to return. The default is 50 and the maximum is 100. schema: type: integer minimum: 1 maximum: 100 default: 50 Cursor: name: cursor in: query description: Opaque cursor returned in `page.nextCursor`. Pass it unchanged with the same filters and sort. Incompatible cursors return `validation_failed`. schema: type: string maxLength: 256 LeadIdFilter: name: leadId in: query schema: type: string format: uuid LeadTierFilter: name: tier in: query schema: type: string enum: [UNQUALIFIED, NURTURE, QUALIFIED, PRIORITY] LeadTiersFilter: name: leadTiers in: query description: Comma-separated lead tiers. Accepts up to four values. schema: type: string LeadDispositionFilter: name: disposition in: query schema: type: string enum: [ACTIVE, CLIENT, BAD_LEAD] LeadDispositionsFilter: name: dispositions in: query description: Comma-separated dispositions. Accepts up to three values. Omitted dispositions default to ACTIVE. schema: type: string MinIcpMatchPercentFilter: name: minIcpMatchPercent in: query description: Minimum ICP match percentage, from 0 to 100. Lead, lead signal, and account report endpoints default to 50 when omitted. Pass a lower value, such as 0, to include lower-scoring qualified engagers. schema: type: integer minimum: 0 maximum: 100 MaxIcpMatchPercentFilter: name: maxIcpMatchPercent in: query description: Maximum ICP match percentage, from 0 to 100. schema: type: integer minimum: 0 maximum: 100 MonitoredProfileIdFilter: name: monitoredProfileId in: query schema: type: string format: uuid MonitoredProfileIdsFilter: name: monitoredProfileIds in: query description: Comma-separated monitored profile IDs. Accepts up to 50 IDs. schema: type: string PostIdFilter: name: postId in: query schema: type: string format: uuid EngagementTypeFilter: name: engagementType in: query schema: type: string enum: [LIKE, COMMENT, REPOST, POST_AUTHOR] EngagementTypesFilter: name: engagementTypes in: query description: Comma-separated engagement types. Accepts up to four values. schema: type: string OwnerIdFilter: name: ownerId in: query schema: type: string format: uuid OwnerIdsFilter: name: ownerIds in: query description: Comma-separated owner IDs. Accepts up to 50 IDs. schema: type: string DateFromFilter: name: dateFrom in: query description: Inclusive start of the date range. schema: type: string format: date-time DateToFilter: name: dateTo in: query description: Inclusive end of the date range. schema: type: string format: date-time SearchQueryFilter: name: query in: query schema: type: string minLength: 1 maxLength: 160 CompanyNameFilter: name: companyName in: query schema: type: string minLength: 1 maxLength: 160 CompanyNamesFilter: name: companyNames in: query description: Comma-separated company names. Accepts up to 25 values. schema: type: string LeadOriginFilter: name: origin in: query description: Safe lead origin. `agent` includes automated Agent and preview discovery; `watchlist` includes watched-profile and manual workflows. schema: type: string enum: [agent, watchlist, all] default: all ProfileTypeFilter: name: profileType in: query schema: type: string enum: [TEAMMATE, COMPETITOR, INFLUENCER, INVESTOR, CUSTOM] ProfileTypesFilter: name: profileTypes in: query description: Comma-separated profile types. Accepts up to five values. schema: type: string MonitoredProfileSourceFilter: name: source in: query schema: type: string enum: [MEMBER_ONBOARDING, MANUAL_WATCHLIST] SlotKindFilter: name: slotKind in: query schema: type: string enum: [SELF, STANDARD, COMPETITOR] RelationshipLabelFilter: name: relationshipLabel in: query schema: type: string minLength: 1 maxLength: 80 WatchlistStateFilter: name: state in: query schema: type: string enum: [ACTIVE, PAUSED] WatchlistSortFilter: name: sort in: query schema: type: string enum: [createdAt, followers, lastEngagementSyncAt, displayName] default: createdAt ContentStatusFilter: name: status in: query schema: type: string enum: [any, qualified, unqualified] default: any ContentSortFilter: name: sort in: query schema: type: string enum: [date, engagement, reactions, comments, reposts] default: date AccountSortFilter: name: sort in: query schema: type: string enum: [latestSignalAt, leadCount, averageIcpMatchPercent, accountName] default: latestSignalAt SortDirectionFilter: name: sortDirection in: query schema: type: string enum: [asc, desc] default: desc Range: name: range in: query schema: type: string enum: [7d, 30d, 90d] default: 30d LeadId: name: leadId in: path required: true schema: type: string format: uuid PostId: name: postId in: path required: true schema: type: string format: uuid MonitoredProfileIdPath: name: monitoredProfileId in: path required: true schema: type: string format: uuid AccountIdPath: name: accountId in: path required: true schema: type: string minLength: 1 maxLength: 256 responses: DataObject: description: Data envelope. content: application/json: schema: type: object additionalProperties: true PageObject: description: Paginated data envelope. content: application/json: schema: $ref: '#/components/schemas/PageEnvelope' AudienceObject: description: Aggregate-only audience response. content: application/json: schema: type: object additionalProperties: true Unauthorized: description: Invalid, expired, or revoked API key. content: application/json: schema: $ref: '#/components/schemas/ErrorEnvelope' McpUnauthorized: description: Invalid, expired, revoked, or wrong-audience MCP OAuth token. Response includes a WWW-Authenticate challenge with resource metadata. headers: WWW-Authenticate: schema: type: string example: Bearer resource_metadata="https://api.traxy.ai/.well-known/oauth-protected-resource/api/v1/mcp" scope="workspace:read leads:read leads:contact_read agent:read" content: application/json: schema: $ref: '#/components/schemas/ErrorEnvelope' InsufficientCapability: description: Key or OAuth grant lacks the required scope. content: application/json: schema: $ref: '#/components/schemas/ErrorEnvelope' ValidationFailed: description: Request failed boundary validation. content: application/json: schema: $ref: '#/components/schemas/ErrorEnvelope' McpBadRequest: description: MCP transport/header failure or top-level request validation failure. content: application/json: schema: oneOf: - $ref: '#/components/schemas/McpJsonRpcResponse' - $ref: '#/components/schemas/ErrorEnvelope' NotFound: description: Resource not found for the key workspace. content: application/json: schema: $ref: '#/components/schemas/ErrorEnvelope' UnresolvedUrn: description: Malformed or unsupported LinkedIn URN. Valid absent and cross-workspace post URNs use NotFound. content: application/json: schema: $ref: '#/components/schemas/ErrorEnvelope' McpOriginNotAllowed: description: Browser Origin is not allowed for MCP. content: application/json: schema: $ref: '#/components/schemas/ErrorEnvelope' MethodNotAllowed: description: HTTP method not supported for this endpoint. content: application/json: schema: $ref: '#/components/schemas/ErrorEnvelope' RateLimited: description: Customer API rate limit exceeded. Production-like runtimes fail closed with this response if the distributed limiter is unavailable. content: application/json: schema: $ref: '#/components/schemas/ErrorEnvelope' schemas: CustomerMeetingsSummary: type: object properties: qualifiedCompanies: type: integer minimum: 0 maximum: 9007199254740991 attributedMeetings: type: integer minimum: 0 maximum: 9007199254740991 unmatchedBookings: type: integer minimum: 0 maximum: 9007199254740991 range: default: 30d type: string enum: - 7d - 30d - 90d - all lastAttributedAt: 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|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$ nullable: true windows: type: object properties: 7d: type: object properties: qualifiedCompanies: type: integer minimum: 0 maximum: 9007199254740991 attributedMeetings: type: integer minimum: 0 maximum: 9007199254740991 unmatchedBookings: type: integer minimum: 0 maximum: 9007199254740991 required: - qualifiedCompanies - attributedMeetings - unmatchedBookings additionalProperties: false 30d: type: object properties: qualifiedCompanies: type: integer minimum: 0 maximum: 9007199254740991 attributedMeetings: type: integer minimum: 0 maximum: 9007199254740991 unmatchedBookings: type: integer minimum: 0 maximum: 9007199254740991 required: - qualifiedCompanies - attributedMeetings - unmatchedBookings additionalProperties: false required: - 7d - 30d additionalProperties: false required: - qualifiedCompanies - attributedMeetings - unmatchedBookings - range - lastAttributedAt additionalProperties: false CustomerMeetingsFeed: type: object properties: data: 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)$ meetingCount: type: integer minimum: 0 maximum: 9007199254740991 targetType: type: string enum: - PERSON - COMPANY lifecycleStatus: type: string enum: - PENDING - TENTATIVE - ACCEPTED - DECLINED - OCCURRED - CANCELLED direction: type: string enum: - INBOUND - OUTBOUND - UNKNOWN meetingStartAt: 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|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$ bookedAt: 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|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$ attributedAt: 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|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$ company: type: object properties: name: type: string nullable: true domain: type: string nullable: true required: - name - domain additionalProperties: false leadRelationship: type: string enum: - DIRECT - COMPANY nullable: true meetingOutcome: type: string enum: - already_client - closed_won nullable: true lead: 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 headline: type: string nullable: true title: type: string nullable: true icpMatchPercent: type: number foundAt: type: string nullable: true required: - id - name - headline - title - icpMatchPercent - foundAt additionalProperties: false nullable: true meetingWith: type: object properties: name: type: string nullable: true email: type: string nullable: true required: - name - email additionalProperties: false nullable: true required: - id - meetingCount - targetType - lifecycleStatus - direction - meetingStartAt - bookedAt - attributedAt - company - leadRelationship - meetingOutcome - lead additionalProperties: false page: type: object properties: limit: type: integer minimum: 1 maximum: 100 cursor: type: string nullable: true nextCursor: type: string nullable: true required: - limit - cursor - nextCursor additionalProperties: false required: - data - page additionalProperties: false McpOAuthClientRegistrationRequest: type: object additionalProperties: false required: [redirect_uris] properties: client_name: type: string example: Codex redirect_uris: type: array minItems: 1 items: type: string format: uri example: ['http://localhost:1455/callback'] grant_types: type: array items: type: string enum: [authorization_code, refresh_token] response_types: type: array items: type: string enum: [code] scope: type: string description: Space-separated OAuth scopes. example: 'workspace:read leads:read leads:contact_read agent:read' token_endpoint_auth_method: type: string enum: [none] default: none McpOAuthClientRegistrationResponse: type: object required: - client_id - client_name - redirect_uris - grant_types - response_types - token_endpoint_auth_method - scope properties: client_id: type: string example: mcp_abc123 client_name: type: string example: Codex redirect_uris: type: array items: type: string format: uri grant_types: type: array items: type: string response_types: type: array items: type: string token_endpoint_auth_method: type: string enum: [none] scope: type: string example: 'workspace:read leads:read leads:contact_read analytics:read agent:read' McpOAuthAuthorizationPreview: type: object required: [clientName, requestedScopes, expiresAt, resource] properties: clientName: type: string example: Codex requestedScopes: $ref: '#/components/schemas/McpConsentScopes' expiresAt: type: string format: date-time resource: type: string format: uri example: https://api.traxy.ai/api/v1/mcp McpConsentScopes: type: array maxItems: 20 items: type: string enum: - leads:read - leads:contact_read - leads:contact_enrich - leads:manage - analytics:read - icp:read - icp:manage - watchlist:read - watchlist:manage - content:read - integrations:read - integrations:manage - integrations:deliver - sync:read - agent:read - agent:run - workspace:read - audience_analytics:read - audience_analytics:request - post_qualification:manage McpOAuthAuthorizationPermissionsRequest: type: object additionalProperties: false required: [requestToken, organizationIds] properties: requestToken: type: string minLength: 32 maxLength: 256 organizationIds: type: array minItems: 1 maxItems: 50 items: type: string format: uuid McpOAuthAuthorizationPermissions: type: object required: [scopes, workspaces] properties: scopes: $ref: '#/components/schemas/McpConsentScopes' workspaces: type: array minItems: 1 maxItems: 50 items: type: object required: [organizationId, scopes] properties: organizationId: type: string format: uuid scopes: $ref: '#/components/schemas/McpConsentScopes' McpOAuthAuthorizeCompleteRequest: oneOf: - type: object additionalProperties: false required: [requestToken, organizationId, approved] properties: requestToken: type: string minLength: 32 maxLength: 256 organizationId: type: string format: uuid organizationIds: type: array minItems: 1 maxItems: 50 items: type: string format: uuid scopes: allOf: - $ref: '#/components/schemas/McpConsentScopes' - minItems: 1 approved: type: boolean enum: [true] - type: object additionalProperties: false required: [requestToken, approved] properties: requestToken: type: string minLength: 32 maxLength: 256 organizationId: type: string format: uuid approved: type: boolean enum: [false] McpOAuthAuthorizeCompleteResponse: type: object required: [redirectUrl] properties: redirectUrl: type: string format: uri description: Client callback URL. Do not log or send to analytics because it may contain an authorization code. McpOAuthTokenRequest: oneOf: - type: object additionalProperties: false required: - grant_type - code - redirect_uri - client_id - code_verifier properties: grant_type: type: string enum: [authorization_code] code: type: string redirect_uri: type: string format: uri client_id: type: string code_verifier: type: string minLength: 43 maxLength: 128 resource: type: string format: uri - type: object additionalProperties: false required: [grant_type, refresh_token, client_id] properties: grant_type: type: string enum: [refresh_token] refresh_token: type: string client_id: type: string scope: type: string resource: type: string format: uri McpOAuthTokenResponse: type: object required: [access_token, token_type, expires_in, refresh_token, scope] properties: access_token: type: string description: Short-lived JWT for `/api/v1/mcp`. token_type: type: string enum: [Bearer] expires_in: type: integer example: 900 refresh_token: type: string description: Opaque refresh token. Store securely; traxy stores only a hash. scope: type: string example: 'workspace:read leads:read leads:contact_read analytics:read agent:read' McpOAuthRevokeRequest: type: object additionalProperties: false required: [token] properties: token: type: string token_type_hint: type: string enum: [access_token, refresh_token] ErrorEnvelope: type: object required: [error] properties: error: type: object required: [code, message, status, request_id] properties: code: type: string example: invalid_api_key message: type: string example: Invalid API key. status: type: integer example: 401 request_id: type: string WorkspaceAccess: type: object required: - organizationId - dataAccess - usage properties: organizationId: type: string format: uuid dataAccess: type: object additionalProperties: false required: - workspace - leads - leadContactData - leadContactEnrichment - analytics - icp - watchlist - content - integrations - sync - agent - audienceAnalytics - audienceDiscovery properties: workspace: type: boolean leads: type: boolean leadContactData: type: boolean leadContactEnrichment: type: boolean description: Whether the credential can request credit-consuming contact enrichment. analytics: type: boolean icp: type: boolean watchlist: type: boolean content: type: boolean integrations: type: boolean sync: type: boolean agent: type: boolean audienceAnalytics: type: boolean audienceDiscovery: type: boolean usage: type: object additionalProperties: false required: - apiVisibleLeadCount - monitoredProfileCount properties: apiVisibleLeadCount: type: integer monitoredProfileCount: type: integer AudienceDiscoveryResponse: type: object additionalProperties: false required: - status - postId properties: status: type: string enum: - queued - pending - already_available postId: type: string format: uuid quoteId: type: string format: uuid nullable: true description: Exact quote used for the request, or the quote still being prepared. requestId: type: string format: uuid nullable: true description: Durable qualification request. Null only while its quote is still preparing. audience: type: object additionalProperties: true description: Aggregate-only audience data, present when analytics are already available. LeadPage: allOf: - $ref: '#/components/schemas/PageEnvelope' - type: object properties: data: type: array items: $ref: '#/components/schemas/Lead' LeadSignalPage: allOf: - $ref: '#/components/schemas/PageEnvelope' - type: object properties: data: type: array items: $ref: '#/components/schemas/LeadSignalRecord' LeadSignalRecord: type: object required: - id - engagementType - reactionType - engagedAt - capturedAt - signal - lead - primarySignal - engagedWith - post properties: id: type: string format: uuid engagementType: type: string enum: [LIKE, COMMENT, REPOST, POST_AUTHOR] reactionType: type: string nullable: true engagedAt: type: string format: date-time capturedAt: type: string format: date-time signal: type: object nullable: true allOf: - $ref: '#/components/schemas/LeadSignal' lead: $ref: '#/components/schemas/Lead' primarySignal: type: object additionalProperties: true description: Backward-compatible LinkedIn engagement context. engagedWith: type: object additionalProperties: true post: type: object additionalProperties: true LeadSignal: type: object additionalProperties: false required: - summary - whyRelevant - topic - type - strength - sentiment - occurredAt - source properties: summary: type: string maxLength: 300 whyRelevant: type: string maxLength: 500 topic: type: string nullable: true maxLength: 160 type: type: string enum: [ COMPETITOR, PAIN, TRIGGER, TOPIC, CATEGORY_INTEREST, CUSTOM, GENERAL_ENGAGEMENT, ] strength: type: string enum: [DIRECT, CONTEXTUAL, ACTIVITY] sentiment: type: string enum: [NEGATIVE, POSITIVE, MIXED, NEUTRAL, UNKNOWN] occurredAt: type: string format: date-time source: type: object additionalProperties: false required: [name, title, url] properties: name: type: string nullable: true title: type: string nullable: true url: type: string nullable: true Lead: type: object required: - id - profile - contact - signal properties: id: type: string format: uuid icpMatchPercent: type: integer nullable: true intentScore: type: number leadTier: type: string nullable: true profile: type: object additionalProperties: false required: - displayName - headline - location - currentCompany - profileUrl properties: displayName: type: string nullable: true headline: type: string nullable: true location: type: string nullable: true currentCompany: type: string nullable: true profileUrl: type: string format: uri nullable: true description: Canonical LinkedIn profile URL; null without leads:contact_read. contact: nullable: true description: Null unless the credential has leads:contact_read. type: object additionalProperties: false required: - workEmail - workEmailStatus - personalEmail - personalEmailStatus - contactPhone - contactPhoneStatus properties: workEmail: type: string format: email nullable: true workEmailStatus: type: string nullable: true personalEmail: type: string format: email nullable: true personalEmailStatus: type: string nullable: true contactPhone: type: string nullable: true contactPhoneStatus: type: string nullable: true signal: type: object nullable: true description: The lead's strongest current canonical signal, or null when unavailable. allOf: - $ref: '#/components/schemas/LeadSignal' PageEnvelope: type: object required: [data, page] properties: data: type: array items: type: object additionalProperties: true page: type: object required: [limit, nextCursor] properties: limit: type: integer cursor: type: string nullable: true nextCursor: type: string nullable: true McpJsonRpcRequest: type: object required: [jsonrpc, method] additionalProperties: false properties: jsonrpc: type: string enum: ['2.0'] id: oneOf: - type: string nullable: true - type: number method: type: string description: MCP request or notification method, including initialize, tools/list, tools/call, and notifications/initialized. params: type: object additionalProperties: true McpJsonRpcResponse: type: object required: [jsonrpc] properties: jsonrpc: type: string enum: ['2.0'] id: oneOf: - type: string nullable: true - type: number result: type: object additionalProperties: true error: type: object additionalProperties: true