{"openapi":"3.0.0","paths":{"/v1/health":{"get":{"operationId":"HealthController_check","parameters":[],"responses":{"200":{"description":"The API is healthy","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthCheckResponse"}}}}},"summary":"Get API health status","tags":["health"]}},"/v1/users":{"get":{"description":"List the users in your team.","operationId":"UsersController_findAll","parameters":[{"name":"limit","required":false,"in":"query","description":"Limit the number of results","schema":{"type":"number"}}],"responses":{"200":{"description":"List of users","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/UserDto"}}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"List users","tags":["users"]}},"/v1/users/{id}":{"get":{"description":"Fetch a single team user by ID.","operationId":"UsersController_findOne","parameters":[{"name":"id","required":true,"in":"path","description":"User ID","schema":{"type":"string"}}],"responses":{"200":{"description":"The user","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"404":{"description":"User not found"},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"Get user","tags":["users"]}},"/v1/leads":{"get":{"description":"List leads for the team, with optional filters. Pass `linkedinUrl` to find the lead IDs for one LinkedIn profile — the usual first step before `DELETE /v1/leads/{id}` when a prospect has replied somewhere else.","operationId":"LeadsController_findMany","parameters":[{"name":"campaignId","required":false,"in":"query","description":"Filter by campaign ID","schema":{"type":"string"}},{"name":"linkedinUrl","required":false,"in":"query","description":"Find the leads for one LinkedIn profile. The URL is normalized before matching, so any spelling works — `http`/`https`, with or without `www.`, a trailing slash, or tracking parameters. Sales Navigator and private (39-character) profile URLs are matched too.\n\nThe same person can hold one lead per campaign and one per list, so this can return several leads — combine it with `campaignId` to narrow to the sequence you mean. Returns 400 if the value is not a LinkedIn profile URL.","schema":{"example":"https://www.linkedin.com/in/jane-doe","type":"string"}},{"name":"listId","required":false,"in":"query","description":"Filter by list ID","schema":{"type":"string"}},{"name":"campaignStatus","required":false,"in":"query","description":"Filter by `campaignStatus`: the campaign's status when the lead was added. It does not reflect where the lead is in its sequence.","schema":{"type":"string","enum":["CREATED","ACTIVE","PAUSED","ERROR","ARCHIVED","COMPLETED"]}},{"name":"replied","required":false,"in":"query","description":"Filter to leads that have / have not replied","schema":{"type":"boolean"}},{"name":"unread","required":false,"in":"query","description":"Filter to leads with / without an unread reply","schema":{"type":"boolean"}},{"name":"skipped","required":false,"in":"query","description":"Filter to leads that were / were not skipped","schema":{"type":"boolean"}},{"name":"skippedReason","required":false,"in":"query","description":"Filter by skip reason","schema":{"type":"string","enum":["DUPLICATE_IN_ANOTHER_CAMPAIGN_AT_IMPORT","DUPLICATE_IN_ANOTHER_TEAM_CAMPAIGN_AT_IMPORT"]}},{"name":"limit","required":false,"in":"query","description":"Maximum number of leads to return (1-100)","schema":{"minimum":1,"maximum":100,"default":25,"type":"number"}},{"name":"cursor","required":false,"in":"query","description":"Cursor from a previous response, to fetch the next page","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedLeadsDto"}}}},"400":{"description":"`linkedinUrl` is not a LinkedIn profile URL"},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"List leads","tags":["leads"]}},"/v1/leads/{id}":{"get":{"description":"Get a single lead by ID, including its full event history.","operationId":"LeadsController_findOne","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeadDetailDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"404":{"description":"Lead not found"},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"Get lead","tags":["leads"]},"patch":{"description":"Update a lead’s editable metadata (notes, custom fields, name, company). Does not change campaign or workflow status.","operationId":"LeadsController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateLeadDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeadDetailDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"404":{"description":"Lead not found"},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"Update lead","tags":["leads"]},"delete":{"description":"Stop a lead’s campaign sequence. Cancels every remaining step, including a message already waiting out a delay, at any point in the sequence. The lead record is retained; confirm with `stoppedAt` on GET /v1/leads/{id}.","operationId":"LeadsController_stop","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StopLeadResponseDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"404":{"description":"Lead not found"},"429":{"description":"Rate limit exceeded. Retry after cooldown."},"503":{"description":"The sequence could not be stopped and is still running. Nothing was changed — retry."}},"security":[{"api-key":[]}],"summary":"Stop lead","tags":["leads"]}},"/v1/leads/add_to_campaign":{"post":{"description":"Add leads to an existing campaign. Batch operation — up to 100 leads at a time.","operationId":"LeadsController_createBatch","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateLeadsBatchDto"}}}},"responses":{"201":{"description":"The leads have been successfully added to the campaign","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateLeadsBatchResponseDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"Add leads to a campaign","tags":["leads"]}},"/v1/campaigns":{"post":{"description":"Create a campaign (name + optional dates). The message sequence is built, and the campaign launched, in the app — neither is settable via the API.","operationId":"CampaignsController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCampaignDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"Create campaign","tags":["campaigns"]},"get":{"description":"Get all campaigns for the authenticated team, with optional status and owner filters.","operationId":"CampaignsController_findAll","parameters":[{"name":"status","required":false,"in":"query","description":"Filter by campaign status","schema":{"enum":["ACTIVE","PAUSED","ARCHIVED","COMPLETED","CREATED"],"type":"string"}},{"name":"userIds","required":false,"in":"query","description":"Filter by owner user IDs","schema":{"example":["123e4567-e89b-12d3-a456-426614174001","123e4567-e89b-12d3-a456-426614174002"],"type":"array","items":{"type":"string"}}}],"responses":{"200":{"description":"Return campaigns matching the criteria","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CampaignDto"}}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"List campaigns","tags":["campaigns"]}},"/v1/campaigns/{id}":{"patch":{"description":"Update a campaign’s name and/or start/end dates. Does not change the message sequence or status.","operationId":"CampaignsController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCampaignDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"404":{"description":"Campaign not found"},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"Update campaign","tags":["campaigns"]},"get":{"description":"Fetch a single campaign by ID.","operationId":"CampaignsController_findOne","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Return the campaign if found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"404":{"description":"Campaign not found"},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"Get campaign","tags":["campaigns"]},"delete":{"description":"Delete a campaign. The campaign is hidden immediately; its leads and running activity are cancelled and removed in the background (async — returns 202).","operationId":"CampaignsController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"202":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignAsyncOpResponseDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"404":{"description":"Campaign not found"},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"Delete campaign","tags":["campaigns"]}},"/v1/campaigns/{id}/sequence":{"get":{"description":"The campaign sequence (steps and branches) as configured in the editor. Branching steps expose their conditions — e.g. connected vs. not connected, invitation accepted vs. expired, replied vs. not replied. Use the `format` query parameter to choose the representation.","operationId":"CampaignsController_getSequence","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"format","required":false,"in":"query","description":"Response shape: `graph` (default, faithful/lossless), `tree` (nested branches), `readable` (human outline), or `all`.","schema":{"enum":["graph","tree","readable","all"],"type":"string"}}],"responses":{"200":{"description":"The campaign sequence in the requested format","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignSequenceResponseDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"404":{"description":"Campaign not found"},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"Get campaign sequence","tags":["campaigns"]}},"/v1/campaigns/{id}/statistics":{"get":{"description":"Detailed campaign performance: invitations/messages sent and accepted/replied, profile visits, and rates.","operationId":"CampaignsController_getStatistics","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Campaign statistics with rates","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignStatisticsResponseDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"404":{"description":"Campaign not found"},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"Campaign statistics","tags":["campaigns"]}},"/v1/campaigns/{id}/leads":{"get":{"description":"List the leads in a campaign, with optional filters.","operationId":"CampaignsController_getLeads","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"campaignStatus","required":false,"in":"query","description":"Filter by `campaignStatus`: the campaign's status when the lead was added. It does not reflect where the lead is in its sequence.","schema":{"type":"string","enum":["CREATED","ACTIVE","PAUSED","ERROR","ARCHIVED","COMPLETED"]}},{"name":"hasReplied","required":false,"in":"query","description":"Filter to leads that have / have not replied","schema":{"type":"boolean"}},{"name":"limit","required":false,"in":"query","description":"Maximum number of leads to return (1-100)","schema":{"minimum":1,"maximum":100,"default":25,"type":"number"}},{"name":"cursor","required":false,"in":"query","description":"Cursor from a previous response, to fetch the next page","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedCampaignLeadsDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"404":{"description":"Campaign not found"},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"List campaign leads","tags":["campaigns"]}},"/v1/campaigns/{id}/pause":{"post":{"description":"Pause a running campaign.","operationId":"CampaignsController_pause","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignStatusResponseDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"404":{"description":"Campaign not found"},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"Pause campaign","tags":["campaigns"]}},"/v1/campaigns/{id}/resume":{"post":{"description":"Resume a paused campaign.","operationId":"CampaignsController_resume","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignStatusResponseDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"404":{"description":"Campaign not found"},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"Resume campaign","tags":["campaigns"]}},"/v1/campaigns/{id}/paused-activities":{"get":{"description":"List the activity types currently paused for a campaign.","operationId":"CampaignsController_getPausedActivities","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PausedActivitiesResponseDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"404":{"description":"Campaign not found"},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"List paused activities","tags":["campaigns"]}},"/v1/campaigns/{id}/pause-activities":{"post":{"description":"Pause specific activity types for a campaign without pausing the whole campaign.","operationId":"CampaignsController_pauseActivities","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityTypesBodyDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PausedActivitiesResponseDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"404":{"description":"Campaign not found"},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"Pause campaign activities","tags":["campaigns"]}},"/v1/campaigns/{id}/resume-activities":{"post":{"description":"Resume previously paused activity types for a campaign.","operationId":"CampaignsController_resumeActivities","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityTypesBodyDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PausedActivitiesResponseDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"404":{"description":"Campaign not found"},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"Resume campaign activities","tags":["campaigns"]}},"/v1/campaigns/{id}/archive":{"post":{"description":"Archive a campaign. The campaign is hidden immediately and moved to ARCHIVED in the background (async — returns 202).","operationId":"CampaignsController_archive","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"202":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignAsyncOpResponseDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"404":{"description":"Campaign not found"},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"Archive campaign","tags":["campaigns"]}},"/v1/analytics":{"get":{"description":"Account-level analytics across all campaigns for a period.","operationId":"AnalyticsController_getAccountAnalytics","parameters":[{"name":"period","required":false,"in":"query","description":"Time period for analytics","schema":{"default":"last-7-days","type":"string","enum":["last-7-days","last-30-days","last-90-days"]}},{"name":"userId","required":false,"in":"query","description":"Filter to a specific user","schema":{"example":"user_abc123","type":"string"}}],"responses":{"200":{"description":"Aggregated outreach metrics for the account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalyticsResponseDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"Account analytics","tags":["analytics"]}},"/v1/analytics/daily":{"get":{"description":"Day-by-day activity breakdown for a date range.","operationId":"AnalyticsController_getDailyAnalytics","parameters":[{"name":"startDate","required":true,"in":"query","description":"Start of the date range (YYYY-MM-DD)","schema":{"format":"date","example":"2026-03-16","type":"string"}},{"name":"endDate","required":true,"in":"query","description":"End of the date range (YYYY-MM-DD)","schema":{"format":"date","example":"2026-03-22","type":"string"}},{"name":"userId","required":false,"in":"query","description":"Filter to a specific user","schema":{"type":"string"}},{"name":"campaignId","required":false,"in":"query","description":"Filter to a specific campaign","schema":{"type":"string"}}],"responses":{"200":{"description":"Daily activity data with totals","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DailyAnalyticsResponseDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"Daily analytics","tags":["analytics"]}},"/v1/analytics/by-user":{"get":{"description":"Metrics broken down by each team member for a period.","operationId":"AnalyticsController_getByUserAnalytics","parameters":[{"name":"period","required":false,"in":"query","description":"Time period for analytics","schema":{"default":"last-7-days","type":"string","enum":["last-7-days","last-30-days","last-90-days"]}}],"responses":{"200":{"description":"Per-user outreach metrics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ByUserAnalyticsResponseDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"Analytics by user","tags":["analytics"]}},"/v1/teams/me":{"get":{"description":"Get the current team's name and user count.","operationId":"TeamsController_getMyTeamInfo","parameters":[],"responses":{"200":{"description":"Team information retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeResponseDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"Current team","tags":["teams"]}},"/.well-known/oauth-authorization-server":{"get":{"operationId":"OAuthController_authServerMetadata","parameters":[],"responses":{"200":{"description":""}},"tags":["oauth"]}},"/.well-known/oauth-protected-resource":{"get":{"operationId":"OAuthController_protectedResourceMetadata","parameters":[],"responses":{"200":{"description":""}},"tags":["oauth"]}},"/.well-known/oauth-protected-resource/mcp":{"get":{"operationId":"OAuthController_protectedResourceMetadataForMcp","parameters":[],"responses":{"200":{"description":""}},"tags":["oauth"]}},"/.well-known/oauth-protected-resource/identity":{"get":{"operationId":"OAuthController_protectedResourceMetadataForIdentity","parameters":[],"responses":{"200":{"description":""}},"tags":["oauth"]}},"/.well-known/oauth-scopes":{"get":{"operationId":"OAuthController_scopes","parameters":[],"responses":{"200":{"description":""}},"tags":["oauth"]}},"/oauth/register":{"post":{"operationId":"OAuthController_register","parameters":[],"responses":{"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"tags":["oauth"]}},"/oauth/authorize":{"post":{"operationId":"OAuthController_authorize","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthorizeQueryDto"}}}},"responses":{"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"tags":["oauth"]},"get":{"operationId":"OAuthController_authorizeRedirect","parameters":[],"responses":{"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"tags":["oauth"]}},"/oauth/authorize/finalize":{"post":{"operationId":"OAuthController_finalize","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinalizeRequestDto"}}}},"responses":{"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"tags":["oauth"]}},"/oauth/signup/finalize":{"post":{"operationId":"OAuthController_signupFinalize","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignupFinalizeRequestDto"}}}},"responses":{"200":{"description":""}},"tags":["oauth"]}},"/oauth/token":{"post":{"operationId":"OAuthController_token","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenRequestDto"}}}},"responses":{"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"tags":["oauth"]}},"/oauth/revoke":{"post":{"operationId":"OAuthController_revoke","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevokeRequestDto"}}}},"responses":{"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"tags":["oauth"]}},"/v1/lists":{"post":{"description":"Create a new lead/audience list.","operationId":"ListsController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateListDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedListDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"Create list","tags":["lists"]},"get":{"description":"List the lead/audience lists for the team.","operationId":"ListsController_findAll","parameters":[{"name":"limit","required":false,"in":"query","description":"Maximum number of lists to return (1-100)","schema":{"minimum":1,"maximum":100,"default":25,"type":"number"}},{"name":"cursor","required":false,"in":"query","description":"Cursor from a previous response, to fetch the next page","schema":{"type":"string"}},{"name":"includeBlacklist","required":false,"in":"query","description":"Include blacklist (suppression) lists in the results","schema":{"default":false,"type":"boolean"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedListsDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"List lists","tags":["lists"]}},"/v1/lists/{id}/leads":{"post":{"description":"Add leads to a list. Batch — up to 100 at a time.","operationId":"ListsController_addLeads","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddLeadsToListDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddLeadsToListResponseDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"404":{"description":"List not found"},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"Add leads to a list","tags":["lists"]},"delete":{"description":"Remove leads from a list by lead ID and/or LinkedIn URL.","operationId":"ListsController_removeLeads","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveLeadsFromListDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveLeadsResponseDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"404":{"description":"List not found"},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"Remove leads from a list","tags":["lists"]},"get":{"description":"List the leads in a list.","operationId":"ListsController_findLeads","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","description":"Maximum number of leads to return (1-100)","schema":{"minimum":1,"maximum":100,"default":25,"type":"number"}},{"name":"cursor","required":false,"in":"query","description":"Cursor from a previous response, to fetch the next page","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedListLeadsDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"404":{"description":"List not found"},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"List list leads","tags":["lists"]}},"/v1/lists/{id}":{"get":{"description":"Fetch a single list by ID.","operationId":"ListsController_findOne","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"404":{"description":"List not found"},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"Get list","tags":["lists"]}},"/v1/blacklist":{"post":{"description":"Create a new blacklist (suppression list).","operationId":"BlacklistController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBlacklistDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedListDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"Create blacklist","tags":["blacklist"]},"get":{"description":"List the blacklist (suppression) lists for the team.","operationId":"BlacklistController_findAll","parameters":[{"name":"limit","required":false,"in":"query","description":"Maximum number of blacklists to return (1-100)","schema":{"minimum":1,"maximum":100,"default":25,"type":"number"}},{"name":"cursor","required":false,"in":"query","description":"Cursor from a previous response, to fetch the next page","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedListsDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"List blacklists","tags":["blacklist"]}},"/v1/blacklist/{id}/leads":{"post":{"description":"Add profiles to a blacklist. Batch — up to 100 at a time.","operationId":"BlacklistController_addLeads","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddLeadsToListDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddLeadsToListResponseDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"404":{"description":"Blacklist not found"},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"Add to blacklist","tags":["blacklist"]},"delete":{"description":"Remove profiles from a blacklist by lead ID and/or LinkedIn URL.","operationId":"BlacklistController_removeLeads","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveLeadsFromListDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveLeadsResponseDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"404":{"description":"Blacklist not found"},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"Remove from blacklist","tags":["blacklist"]},"get":{"description":"List the excluded profiles in a blacklist.","operationId":"BlacklistController_findLeads","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","description":"Maximum number of leads to return (1-100)","schema":{"minimum":1,"maximum":100,"default":25,"type":"number"}},{"name":"cursor","required":false,"in":"query","description":"Cursor from a previous response, to fetch the next page","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedListLeadsDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"404":{"description":"Blacklist not found"},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"List blacklist entries","tags":["blacklist"]}},"/v1/blacklist/{id}":{"get":{"description":"Fetch a single blacklist by ID.","operationId":"BlacklistController_findOne","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"404":{"description":"Blacklist not found"},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"Get blacklist","tags":["blacklist"]}},"/v1/accounts":{"get":{"description":"List the connected LinkedIn accounts (seats) for the team, with connection health.","operationId":"LinkedinAccountsController_findAll","parameters":[{"name":"limit","required":false,"in":"query","description":"Maximum number of accounts to return (1-200)","schema":{"minimum":1,"maximum":200,"default":50,"type":"number"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AccountDto"}}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"List accounts","tags":["accounts"]}},"/v1/accounts/{id}/limits":{"get":{"description":"Get an account's daily sending caps and remaining quota for today.","operationId":"LinkedinAccountsController_getLimits","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"number"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountLimitsDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"404":{"description":"Account not found"},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"Get account limits","tags":["accounts"]},"patch":{"description":"Update an account's daily caps, sending days, timezone, and auto-withdraw settings. Caps are clamped to safe maximums.","operationId":"LinkedinAccountsController_updateLimits","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"number"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAccountLimitsDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountLimitsDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"404":{"description":"Account not found"},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"Update account limits","tags":["accounts"]}},"/v1/webhooks":{"post":{"description":"Create a webhook subscription. The signing secret is never returned.","operationId":"WebhooksController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebhookDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"Create webhook","tags":["webhooks"]},"get":{"description":"List the webhook subscriptions for the team.","operationId":"WebhooksController_findAll","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/WebhookDto"}}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"List webhooks","tags":["webhooks"]}},"/v1/webhooks/{id}":{"patch":{"description":"Update a webhook subscription (name, endpoint, and/or event types).","operationId":"WebhooksController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWebhookDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"404":{"description":"Webhook not found"},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"Update webhook","tags":["webhooks"]},"get":{"description":"Fetch a single webhook subscription by ID.","operationId":"WebhooksController_findOne","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"404":{"description":"Webhook not found"},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"Get webhook","tags":["webhooks"]}},"/v1/snippets":{"get":{"description":"List message snippets/templates visible to the caller (personal + team-shared).","operationId":"SnippetsController_findAll","parameters":[{"name":"status","required":false,"in":"query","description":"Filter by snippet status","schema":{"type":"string","enum":["ACTIVE","ARCHIVED"]}},{"name":"limit","required":false,"in":"query","description":"Maximum number of snippets to return (1-100)","schema":{"minimum":1,"maximum":100,"default":25,"type":"number"}},{"name":"cursor","required":false,"in":"query","description":"Cursor from a previous response, to fetch the next page","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedSnippetsDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"List snippets","tags":["snippets"]},"post":{"description":"Create a personal (or team-shared) snippet/template.","operationId":"SnippetsController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSnippetDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SnippetDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"409":{"description":"Shortcut already in use"},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"Create snippet","tags":["snippets"]}},"/v1/snippets/{id}":{"patch":{"description":"Update one of your own snippets.","operationId":"SnippetsController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSnippetDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SnippetDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"404":{"description":"Snippet not found"},"409":{"description":"Shortcut already in use"},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"Update snippet","tags":["snippets"]},"delete":{"description":"Delete one of your own snippets.","operationId":"SnippetsController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":"Snippet deleted"},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"404":{"description":"Snippet not found"},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"Delete snippet","tags":["snippets"]}},"/oauth/userinfo":{"get":{"operationId":"IdentityController_userinfo","parameters":[],"responses":{"200":{"description":""}},"tags":["identity"]}},"/v1/messages":{"post":{"description":"Send a message into a lead’s existing LinkedIn conversation. If Botdog has not recorded the conversation yet (for example the lead connected and wrote first), it is found on LinkedIn and recorded, and its id is returned as `chatId`. Never starts a new conversation. Rate-limited per sending account.","operationId":"MessagingController_sendMessage","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendMessageDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendMessageResponseDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"404":{"description":"Lead not found"},"422":{"description":"No conversation exists with this lead yet"},"429":{"description":"Per-account send limit reached"}},"security":[{"api-key":[]}],"summary":"Send a message","tags":["messaging"]}},"/v1/conversations/{id}/reply":{"post":{"description":"Reply to a conversation by its id: the `chatId` returned by POST /v1/messages, GET /v1/leads/{id} or the LEAD_MESSAGE_REPLIED webhook, or the conversation id in the Botdog inbox URL. The conversation must be with one of your team’s leads. Rate-limited per sending account.","operationId":"MessagingController_reply","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReplyDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendMessageResponseDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"404":{"description":"Conversation not found, or not with one of your team’s leads"},"429":{"description":"Per-account send limit reached"}},"security":[{"api-key":[]}],"summary":"Reply to a conversation","tags":["messaging"]}},"/v1/messages/schedule":{"post":{"description":"Schedule a message to a lead’s conversation for a future time (60s–90 days). Counts against the daily per-account budget.","operationId":"MessagingController_schedule","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleMessageDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduledMessageResponseDto"}}}},"400":{"description":"fireAt out of range"},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"404":{"description":"Lead not found"},"422":{"description":"No conversation exists yet"},"429":{"description":"Per-account daily limit reached"}},"security":[{"api-key":[]}],"summary":"Schedule a message","tags":["messaging"]}},"/v1/conversations/{id}/read":{"post":{"operationId":"MessagingController_setReadStatus","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReadStatusDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReadStatusResponseDto"}}}},"401":{"description":"Unauthorized. API key is missing or invalid."},"403":{"description":"The key owner has no seat assigned (write endpoints only), the team is on Botdog Managed and so may only read (write endpoints only), or the subscription/plan does not permit this."},"404":{"description":"Conversation not found"},"429":{"description":"Rate limit exceeded. Retry after cooldown."}},"security":[{"api-key":[]}],"summary":"Mark a conversation read or unread","tags":["messaging"]}}},"info":{"title":"Botdog API","description":"API documentation for Botdog.\n\n**Authentication**: Pass your API key as the `x-api-key` header.\nKeys are 32-character hexadecimal strings with no prefix.\nExample: `x-api-key: 0123456789abcdef0123456789abcdef`\n\nDo NOT use the `Authorization` header.","version":"1.0","contact":{}},"tags":[{"name":"campaigns","description":"Manage campaigns for a user"},{"name":"leads","description":"Manage leads for a campaign"},{"name":"users","description":"Manage your organization users"},{"name":"analytics","description":"Account-level analytics and daily breakdowns"}],"servers":[{"url":"https://api.botdog.co","description":"API server"}],"components":{"securitySchemes":{"api-key":{"type":"apiKey","in":"header","name":"x-api-key"}},"schemas":{"MemoryUsage":{"type":"object","properties":{"rss":{"type":"number","description":"Resident Set Size - total memory allocated for the process execution","example":47378432},"heapTotal":{"type":"number","description":"Total size of the allocated heap","example":23068672},"heapUsed":{"type":"number","description":"Actual memory used by the heap","example":11601456},"external":{"type":"number","description":"Memory used by C++ objects bound to JavaScript objects","example":1789775},"arrayBuffers":{"type":"number","description":"Memory allocated for ArrayBuffers and SharedArrayBuffers","example":1064517}},"required":["rss","heapTotal","heapUsed","external"]},"HealthCheckResponse":{"type":"object","properties":{"status":{"type":"string","description":"Current status of the API","example":"ok"},"timestamp":{"type":"string","description":"Current server timestamp","example":"2023-04-02T12:00:00.000Z"},"uptime":{"type":"number","description":"Server uptime in seconds","example":3600},"memoryUsage":{"description":"Memory usage statistics","allOf":[{"$ref":"#/components/schemas/MemoryUsage"}]}},"required":["status","timestamp","uptime","memoryUsage"]},"UserDto":{"type":"object","properties":{"id":{"type":"string","description":"The unique identifier for the user","example":"550e8400-e29b-41d4-a716-446655440000"},"email":{"type":"string","description":"The user's email address","example":"user@example.com"},"name":{"type":"string","description":"The user's name","example":"John Doe"},"createdAt":{"format":"date-time","type":"string","description":"When the user was created","example":"2023-04-02T12:00:00.000Z"}},"required":["id","email","name","createdAt"]},"LeadSummaryDto":{"type":"object","properties":{"id":{"type":"string","description":"The unique identifier of the lead"},"name":{"type":"string","description":"The name of the lead","example":"Jane Doe"},"linkedinProfile":{"type":"string","description":"The LinkedIn profile URL of the lead","example":"https://www.linkedin.com/in/jane-doe"},"company":{"type":"string","description":"The lead's company","nullable":true},"job":{"type":"string","description":"The lead's job title","nullable":true},"campaignId":{"type":"string","description":"The campaign this lead belongs to, if any","nullable":true},"listId":{"type":"string","description":"The list this lead belongs to, if any","nullable":true},"campaignStatus":{"type":"string","description":"The campaign's status when this lead was added to it. It is not updated as the lead moves through its sequence, so it does not show whether the lead's sequence is still running, has finished, failed or was stopped. For that, read the lead's `events` on GET /v1/leads/{id}: `WORKFLOW_CLEANUP` means the sequence finished, `WORKFLOW_FAILED` means it failed, and `stoppedAt` is set when it was stopped through the API.","nullable":true},"hasReplied":{"type":"boolean","description":"Whether the lead has replied"},"hasUnreadReply":{"type":"boolean","description":"Whether the lead has an unread reply"},"isSkipped":{"type":"boolean","description":"Whether the lead was skipped"},"skippedReason":{"type":"string","description":"Why the lead was skipped, if applicable","nullable":true},"createdAt":{"format":"date-time","type":"string","description":"When the lead was created"},"invitedAt":{"format":"date-time","type":"string","description":"When the invite was sent","nullable":true},"connectedAt":{"format":"date-time","type":"string","description":"When the lead connected","nullable":true},"repliedAt":{"format":"date-time","type":"string","description":"When the lead replied","nullable":true},"withdrawnAt":{"format":"date-time","type":"string","description":"When the invitation was withdrawn","nullable":true},"stoppedAt":{"format":"date-time","type":"string","description":"When the lead was stopped, if it was. This is the authoritative confirmation that a stop took effect: it is written only after the lead’s sequence has been torn down, so a non-null value means no further steps — including any message already waiting on a delay — can run. Poll this after DELETE /v1/leads/{id} rather than the `stopped` flag on the stop response.","nullable":true}},"required":["id","name","linkedinProfile","hasReplied","hasUnreadReply","isSkipped","createdAt"]},"PaginatedLeadsDto":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/LeadSummaryDto"}},"nextCursor":{"type":"string","description":"Opaque cursor for the next page; null when there are no more results. Pass it back as the `cursor` query parameter.","nullable":true}},"required":["data","nextCursor"]},"LeadEventDto":{"type":"object","properties":{"id":{"type":"string","description":"The unique identifier of the event"},"type":{"type":"string","description":"The event type","example":"INVITE_SENT"},"createdAt":{"format":"date-time","type":"string","description":"When the event occurred"},"scheduledAt":{"format":"date-time","type":"string","description":"When the underlying action was scheduled, if applicable","nullable":true},"details":{"type":"string","description":"Human-readable details about the event","nullable":true},"cancellationReason":{"type":"string","description":"Reason an action was cancelled, if applicable","nullable":true}},"required":["id","type","createdAt"]},"LeadDetailDto":{"type":"object","properties":{"id":{"type":"string","description":"The unique identifier of the lead"},"name":{"type":"string","description":"The name of the lead","example":"Jane Doe"},"linkedinProfile":{"type":"string","description":"The LinkedIn profile URL of the lead","example":"https://www.linkedin.com/in/jane-doe"},"company":{"type":"string","description":"The lead's company","nullable":true},"job":{"type":"string","description":"The lead's job title","nullable":true},"campaignId":{"type":"string","description":"The campaign this lead belongs to, if any","nullable":true},"listId":{"type":"string","description":"The list this lead belongs to, if any","nullable":true},"campaignStatus":{"type":"string","description":"The campaign's status when this lead was added to it. It is not updated as the lead moves through its sequence, so it does not show whether the lead's sequence is still running, has finished, failed or was stopped. For that, read the lead's `events` on GET /v1/leads/{id}: `WORKFLOW_CLEANUP` means the sequence finished, `WORKFLOW_FAILED` means it failed, and `stoppedAt` is set when it was stopped through the API.","nullable":true},"hasReplied":{"type":"boolean","description":"Whether the lead has replied"},"hasUnreadReply":{"type":"boolean","description":"Whether the lead has an unread reply"},"isSkipped":{"type":"boolean","description":"Whether the lead was skipped"},"skippedReason":{"type":"string","description":"Why the lead was skipped, if applicable","nullable":true},"createdAt":{"format":"date-time","type":"string","description":"When the lead was created"},"invitedAt":{"format":"date-time","type":"string","description":"When the invite was sent","nullable":true},"connectedAt":{"format":"date-time","type":"string","description":"When the lead connected","nullable":true},"repliedAt":{"format":"date-time","type":"string","description":"When the lead replied","nullable":true},"withdrawnAt":{"format":"date-time","type":"string","description":"When the invitation was withdrawn","nullable":true},"stoppedAt":{"format":"date-time","type":"string","description":"When the lead was stopped, if it was. This is the authoritative confirmation that a stop took effect: it is written only after the lead’s sequence has been torn down, so a non-null value means no further steps — including any message already waiting on a delay — can run. Poll this after DELETE /v1/leads/{id} rather than the `stopped` flag on the stop response.","nullable":true},"location":{"type":"string","description":"The lead's location","nullable":true},"lastMessage":{"type":"string","description":"The most recent message in the conversation","nullable":true},"chatId":{"type":"string","description":"Id of the lead’s standard LinkedIn conversation — the `id` that POST /v1/conversations/{id}/reply expects. Null until Botdog has linked one; POST /v1/messages does not need it, and records it on first use.","nullable":true},"statusNote":{"type":"string","description":"A free-text status note","nullable":true},"customField1":{"type":"string","nullable":true},"customField2":{"type":"string","nullable":true},"customField3":{"type":"string","nullable":true},"customAttributes":{"type":"object","description":"Custom key-value attributes supplied when the lead was added","nullable":true},"updatedAt":{"format":"date-time","type":"string","description":"When the lead was last updated"},"events":{"description":"Chronological event history for the lead","type":"array","items":{"$ref":"#/components/schemas/LeadEventDto"}}},"required":["id","name","linkedinProfile","hasReplied","hasUnreadReply","isSkipped","createdAt","updatedAt","events"]},"UpdateLeadDto":{"type":"object","properties":{"name":{"type":"string","description":"The lead's name"},"company":{"type":"string","description":"The lead's company"},"statusNote":{"type":"string","description":"A free-text status note"},"customField1":{"type":"string","description":"Custom field 1"},"customField2":{"type":"string","description":"Custom field 2"},"customField3":{"type":"string","description":"Custom field 3"},"customAttributes":{"type":"object","description":"Custom key-value attributes (replaces the existing object)","additionalProperties":true}}},"StopLeadResponseDto":{"type":"object","properties":{"leadId":{"type":"string","description":"The lead that was stopped"},"stopped":{"type":"boolean","description":"True when the sequence was torn down and the stop recorded. The request fails with 503 instead of returning false if the sequence could not be stopped, so a 2xx response always means the lead is stopped.","example":true}},"required":["leadId","stopped"]},"LeadCreateDto":{"type":"object","properties":{"name":{"type":"string","description":"The name of the lead","example":"John Doe"},"linkedinUrl":{"type":"string","description":"LinkedIn profile URL of the lead (https:// will be added automatically if missing)","example":"https://www.linkedin.com/in/johndoe"},"title":{"type":"string","description":"Job title of the lead","example":"Software Engineer"},"company":{"type":"string","description":"Company of the lead","example":"Acme Inc."},"location":{"type":"string","description":"Location of the lead","example":"San Francisco, CA"},"customAttributes":{"type":"object","description":"Any additional attributes for the lead that can be used in workflow messages","example":{"customKey1":"customValue1","customKey2":"customValue2"}}},"required":["linkedinUrl"]},"CreateLeadsBatchDto":{"type":"object","properties":{"campaignId":{"type":"string","description":"The campaign ID to add these leads to","example":"123e4567-e89b-12d3-a456-426614174000"},"leads":{"description":"Array of leads to create (maximum 100)","type":"array","items":{"$ref":"#/components/schemas/LeadCreateDto"}}},"required":["campaignId","leads"]},"CreateLeadsBatchResponseDto":{"type":"object","properties":{"count":{"type":"number","description":"The number of leads successfully created","example":50},"campaignId":{"type":"string","description":"The campaign ID the leads were added to","example":"123e4567-e89b-12d3-a456-426614174000"}},"required":["count","campaignId"]},"CreateCampaignDto":{"type":"object","properties":{"name":{"type":"string","description":"The campaign name","example":"Q4 Outreach"},"startDate":{"type":"string","description":"When the campaign should start (ISO 8601)","example":"2026-07-01T09:00:00Z"},"endDate":{"type":"string","description":"When the campaign should end (ISO 8601)","example":"2026-08-01T09:00:00Z"}},"required":["name"]},"CampaignDto":{"type":"object","properties":{"id":{"type":"string","description":"The unique identifier of the campaign","example":"123e4567-e89b-12d3-a456-426614174000"},"name":{"type":"string","description":"The name of the campaign","example":"Q4 Sales Outreach"},"status":{"type":"string","description":"The current status of the campaign","example":"ACTIVE","enum":["ACTIVE","PAUSED","ARCHIVED","COMPLETED","CREATED"]},"ownerId":{"type":"string","description":"The ID of the user who owns this campaign","example":"123e4567-e89b-12d3-a456-426614174000"},"ownerEmail":{"type":"string","description":"The email of the user who owns this campaign","example":"john.doe@example.com"},"createdAt":{"format":"date-time","type":"string","description":"The date the campaign was created","example":"2023-09-15T12:00:00Z"},"updatedAt":{"format":"date-time","type":"string","description":"The date the campaign was last updated","example":"2023-09-16T14:30:00Z"},"startDate":{"format":"date-time","type":"string","description":"The date the campaign will start","example":"2023-09-15T12:00:00Z"},"endDate":{"format":"date-time","type":"string","description":"The date the campaign will end","example":"2023-09-15T12:00:00Z"}},"required":["id","name","status","ownerId","ownerEmail","createdAt","updatedAt","startDate","endDate"]},"UpdateCampaignDto":{"type":"object","properties":{"name":{"type":"string","description":"The campaign name"},"startDate":{"type":"string","description":"When the campaign should start (ISO 8601)"},"endDate":{"type":"string","description":"When the campaign should end (ISO 8601)"}}},"SequenceGraphNodeDto":{"type":"object","properties":{"id":{"type":"number","description":"Stable numeric id of the step","example":2},"stepType":{"type":"string","description":"Step type","example":"WAIT_FOR_INVITATION_RESPONSE"},"label":{"type":"string","description":"Human-readable label for the step type","example":"Wait for invitation response"},"metadata":{"type":"object","description":"Step configuration (message text, wait duration, etc.)","additionalProperties":true},"next":{"type":"number","description":"Next step id for a linear step, or null to end this branch. Present only on non-branching steps.","example":3,"nullable":true},"choice":{"type":"object","description":"Branch map for a conditional step: outcome -> next step id (null ends the branch). Present only on branching steps.","additionalProperties":{"type":"number","nullable":true},"example":{"invitation_accepted":3,"expired":null}}},"required":["id","stepType","label"]},"CampaignSequenceResponseDto":{"type":"object","properties":{"campaignId":{"type":"string","description":"The id of the campaign this sequence belongs to","example":"123e4567-e89b-12d3-a456-426614174000"},"editorViewType":{"type":"string","description":"Which editor produced the campaign","example":"ADVANCED","enum":["SIMPLE","ADVANCED"]},"source":{"type":"string","description":"Where the sequence was read from: `workflow` (modern), `legacy` (old linear sequences), or `empty` (no sequence yet).","example":"workflow","enum":["workflow","legacy","empty"]},"firstStep":{"type":"number","description":"Id of the first step to run, or null when there is no sequence","example":1,"nullable":true},"steps":{"description":"Present when format is `graph` or `all`","type":"array","items":{"$ref":"#/components/schemas/SequenceGraphNodeDto"}},"tree":{"type":"object","description":"Present when format is `tree` or `all`. Nested step tree rooted at the first step; null for an empty sequence.","additionalProperties":true,"nullable":true},"readable":{"description":"Present when format is `readable` or `all`. One line per step/branch.","example":["Step 1 · Send invitation (start)","    → then step 2 (Wait for invitation response)"],"type":"array","items":{"type":"string"}}},"required":["campaignId","editorViewType","source"]},"CampaignStatisticsDto":{"type":"object","properties":{"progress":{"type":"number","description":"Campaign completion percentage","example":45.2,"nullable":true},"totalLeadCount":{"type":"number","example":500},"totalLeadsInProgress":{"type":"number","example":224},"totalLeadsSkipped":{"type":"number","example":12},"invitationsSent":{"type":"number","example":264},"invitationsAccepted":{"type":"number","example":37},"invitationsSkipped":{"type":"number","example":5},"messagesSent":{"type":"number","example":37},"inmailsSent":{"type":"number","example":0},"messagesReplied":{"type":"number","example":3},"profileVisits":{"type":"number","example":264},"companyInvitationsSent":{"type":"number","example":0},"postsReactions":{"type":"number","example":0},"aiAccepted":{"type":"number","example":480},"aiRejected":{"type":"number","example":8}},"required":["progress","totalLeadCount","totalLeadsInProgress","totalLeadsSkipped","invitationsSent","invitationsAccepted","invitationsSkipped","messagesSent","inmailsSent","messagesReplied","profileVisits","companyInvitationsSent","postsReactions","aiAccepted","aiRejected"]},"CampaignRatesDto":{"type":"object","properties":{"invitationAcceptanceRate":{"type":"number","description":"Invitation acceptance rate percentage","example":14},"messageReplyRate":{"type":"number","description":"Message reply rate percentage","example":6}},"required":["invitationAcceptanceRate","messageReplyRate"]},"CampaignStatisticsResponseDto":{"type":"object","properties":{"campaignId":{"type":"string","example":"cm1abc123def456"},"campaignName":{"type":"string","example":"Cold Outreach - ML Engineers"},"status":{"type":"string","example":"ACTIVE"},"owner":{"type":"string","example":"sid@pavoai.com"},"statistics":{"$ref":"#/components/schemas/CampaignStatisticsDto"},"rates":{"$ref":"#/components/schemas/CampaignRatesDto"}},"required":["campaignId","campaignName","status","owner","statistics","rates"]},"CampaignLeadDto":{"type":"object","properties":{"id":{"type":"string","description":"The unique identifier of the lead"},"name":{"type":"string","description":"The name of the lead","example":"Jane Doe"},"linkedinProfile":{"type":"string","description":"The LinkedIn profile URL of the lead","example":"https://www.linkedin.com/in/jane-doe"},"company":{"type":"string","description":"The lead's company","nullable":true},"job":{"type":"string","description":"The lead's job title","nullable":true},"campaignStatus":{"type":"string","description":"The campaign's status when this lead was added to it. It is not updated as the lead moves through its sequence, so it does not show whether the lead's sequence is still running, has finished, failed or was stopped. For that, read the lead's `events` on GET /v1/leads/{id}: `WORKFLOW_CLEANUP` means the sequence finished, `WORKFLOW_FAILED` means it failed, and `stoppedAt` is set when it was stopped through the API.","enum":["CREATED","ACTIVE","PAUSED","ERROR","ARCHIVED","COMPLETED"]},"hasReplied":{"type":"boolean","description":"Whether the lead has replied","example":false},"createdAt":{"format":"date-time","type":"string","description":"When the lead was added to the campaign"}},"required":["id","name","linkedinProfile","campaignStatus","hasReplied","createdAt"]},"PaginatedCampaignLeadsDto":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CampaignLeadDto"}},"nextCursor":{"type":"string","description":"Opaque cursor for the next page; null when there are no more results. Pass it back as the `cursor` query parameter.","nullable":true}},"required":["data","nextCursor"]},"CampaignStatusResponseDto":{"type":"object","properties":{"campaignId":{"type":"string","description":"The campaign identifier"},"status":{"type":"string","description":"The resulting campaign status","example":"PAUSED"}},"required":["campaignId","status"]},"PausedActivityDto":{"type":"object","properties":{"activityType":{"type":"string","enum":["PROFILE_VISIT","SEND_INVITATION","SEND_MESSAGE","SEND_INMAIL","SEND_COMPANY_PAGE_INVITATION","REACT_TO_POSTS"]},"pausedAt":{"format":"date-time","type":"string","description":"When the activity type was paused"}},"required":["activityType","pausedAt"]},"PausedActivitiesResponseDto":{"type":"object","properties":{"pausedActivities":{"type":"array","items":{"$ref":"#/components/schemas/PausedActivityDto"}}},"required":["pausedActivities"]},"ActivityTypesBodyDto":{"type":"object","properties":{"activityTypes":{"type":"array","description":"The activity types to pause/resume","example":["SEND_INVITATION"],"items":{"type":"string","enum":["PROFILE_VISIT","SEND_INVITATION","SEND_MESSAGE","SEND_INMAIL","SEND_COMPANY_PAGE_INVITATION","REACT_TO_POSTS"]}}},"required":["activityTypes"]},"CampaignAsyncOpResponseDto":{"type":"object","properties":{"campaignId":{"type":"string","description":"The campaign identifier"},"status":{"type":"string","description":"The accepted async operation. The campaign is hidden immediately and removed/archived in the background.","example":"deletion_requested","enum":["deletion_requested","archival_requested"]}},"required":["campaignId","status"]},"InvitationsDto":{"type":"object","properties":{"sent":{"type":"number","example":677},"accepted":{"type":"number","example":92},"rate":{"type":"number","description":"Acceptance rate as percentage","example":13.6}},"required":["sent","accepted","rate"]},"MessagesDto":{"type":"object","properties":{"sent":{"type":"number","example":92},"replied":{"type":"number","example":4},"rate":{"type":"number","description":"Reply rate as percentage","example":4.3}},"required":["sent","replied","rate"]},"CampaignsSummaryDto":{"type":"object","properties":{"active":{"type":"number","example":6},"totalLeadsInProgress":{"type":"number","example":1420}},"required":["active","totalLeadsInProgress"]},"AnalyticsResponseDto":{"type":"object","properties":{"period":{"type":"string","example":"last-7-days"},"invitations":{"$ref":"#/components/schemas/InvitationsDto"},"messages":{"$ref":"#/components/schemas/MessagesDto"},"campaigns":{"$ref":"#/components/schemas/CampaignsSummaryDto"}},"required":["period","invitations","messages","campaigns"]},"DailyDataPointDto":{"type":"object","properties":{"date":{"type":"string","example":"2026-03-19"},"invitationsSent":{"type":"number","example":142},"invitationsAccepted":{"type":"number","example":16},"messagesSent":{"type":"number","example":16},"messagesReplied":{"type":"number","example":1}},"required":["date","invitationsSent","invitationsAccepted","messagesSent","messagesReplied"]},"DailyTotalsDto":{"type":"object","properties":{"invitationsSent":{"type":"number","example":677},"invitationsAccepted":{"type":"number","example":92},"messagesSent":{"type":"number","example":92},"messagesReplied":{"type":"number","example":4},"invitationAcceptanceRate":{"type":"number","example":13.6},"messageReplyRate":{"type":"number","example":4.3}},"required":["invitationsSent","invitationsAccepted","messagesSent","messagesReplied","invitationAcceptanceRate","messageReplyRate"]},"DailyAnalyticsResponseDto":{"type":"object","properties":{"startDate":{"type":"string","example":"2026-03-16"},"endDate":{"type":"string","example":"2026-03-22"},"data":{"type":"array","items":{"$ref":"#/components/schemas/DailyDataPointDto"}},"totals":{"$ref":"#/components/schemas/DailyTotalsDto"}},"required":["startDate","endDate","data","totals"]},"UserAnalyticsDto":{"type":"object","properties":{"userId":{"type":"string","example":"user_abc123"},"email":{"type":"string","example":"anannya@pavoai.com"},"name":{"type":"string","example":"Anannya Mishra"},"invitations":{"$ref":"#/components/schemas/InvitationsDto"},"messages":{"$ref":"#/components/schemas/MessagesDto"}},"required":["userId","email","name","invitations","messages"]},"ByUserAnalyticsResponseDto":{"type":"object","properties":{"period":{"type":"string","example":"last-7-days"},"users":{"type":"array","items":{"$ref":"#/components/schemas/UserAnalyticsDto"}}},"required":["period","users"]},"MeResponseDto":{"type":"object","properties":{"teamName":{"type":"string","example":"Acme Corp","description":"Name of your organization"},"userCount":{"type":"number","example":5,"description":"Count of users in your organization"}},"required":["teamName","userCount"]},"AuthorizeQueryDto":{"type":"object","properties":{}},"FinalizeRequestDto":{"type":"object","properties":{}},"SignupFinalizeRequestDto":{"type":"object","properties":{}},"TokenRequestDto":{"type":"object","properties":{}},"RevokeRequestDto":{"type":"object","properties":{}},"CreateListDto":{"type":"object","properties":{"name":{"type":"string","description":"The name of the list","example":"Q4 prospects"},"isBlacklist":{"type":"boolean","description":"Whether this list is a blacklist (suppression list)","default":false}},"required":["name"]},"CreatedListDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"isBlacklist":{"type":"boolean"}},"required":["id","name","isBlacklist"]},"ListLeadInputDto":{"type":"object","properties":{"linkedinUrl":{"type":"string","description":"LinkedIn profile URL (https:// is added automatically if missing)","example":"https://www.linkedin.com/in/johndoe"},"name":{"type":"string","description":"The name of the lead"},"company":{"type":"string","description":"Company of the lead"},"location":{"type":"string","description":"Location of the lead"},"title":{"type":"string","description":"Job title of the lead"}},"required":["linkedinUrl"]},"AddLeadsToListDto":{"type":"object","properties":{"leads":{"description":"Profiles to add (maximum 100). Duplicates are skipped.","type":"array","items":{"$ref":"#/components/schemas/ListLeadInputDto"}}},"required":["leads"]},"AddLeadsToListResponseDto":{"type":"object","properties":{"listId":{"type":"string","description":"The list the leads were added to"},"count":{"type":"number","description":"Number of leads created (duplicates skipped)"}},"required":["listId","count"]},"RemoveLeadsFromListDto":{"type":"object","properties":{"leadIds":{"description":"Lead IDs to remove","type":"array","items":{"type":"string"}},"linkedinUrls":{"description":"LinkedIn profile URLs to remove","type":"array","items":{"type":"string"}}}},"RemoveLeadsResponseDto":{"type":"object","properties":{"listId":{"type":"string","description":"The list the leads were removed from"},"deletedCount":{"type":"number","description":"Number of leads removed"}},"required":["listId","deletedCount"]},"ListDto":{"type":"object","properties":{"id":{"type":"string","description":"The unique identifier of the list"},"name":{"type":"string","description":"The name of the list","example":"Q4 prospects"},"type":{"type":"string","description":"How the list was created","example":"API_IMPORT"},"isBlacklist":{"type":"boolean","description":"Whether this list is a blacklist (suppression list)","example":false},"leadCount":{"type":"number","description":"Number of leads in the list","example":42},"createdAt":{"format":"date-time","type":"string","description":"When the list was created"}},"required":["id","name","type","isBlacklist","leadCount","createdAt"]},"PaginatedListsDto":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ListDto"}},"nextCursor":{"type":"string","description":"Opaque cursor for the next page; null when there are no more results. Pass it back as the `cursor` query parameter.","nullable":true}},"required":["data","nextCursor"]},"ListLeadDto":{"type":"object","properties":{"id":{"type":"string","description":"The unique identifier of the lead"},"name":{"type":"string","description":"The name of the lead","example":"Jane Doe"},"linkedinProfile":{"type":"string","description":"The LinkedIn profile URL of the lead","example":"https://www.linkedin.com/in/jane-doe"},"company":{"type":"string","description":"The lead's company","nullable":true},"createdAt":{"format":"date-time","type":"string","description":"When the lead was added"}},"required":["id","name","linkedinProfile","createdAt"]},"PaginatedListLeadsDto":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ListLeadDto"}},"nextCursor":{"type":"string","description":"Opaque cursor for the next page; null when there are no more results. Pass it back as the `cursor` query parameter.","nullable":true}},"required":["data","nextCursor"]},"CreateBlacklistDto":{"type":"object","properties":{"name":{"type":"string","description":"The name of the blacklist","example":"Do not contact"}},"required":["name"]},"AccountDto":{"type":"object","properties":{"id":{"type":"number","description":"The internal identifier of the connected account"},"unipileId":{"type":"string","description":"The provider (Unipile) account identifier"},"status":{"type":"string","description":"The account status","example":"UNIPILE_OK"},"unipileStatus":{"type":"string","description":"Detailed provider connection status / health","nullable":true},"lastUnipileStatusUpdate":{"format":"date-time","type":"string","description":"When the connection status was last updated","nullable":true},"ownerId":{"type":"string","description":"The ID of the user who owns this account"},"ownerEmail":{"type":"string","description":"The email of the user who owns this account"}},"required":["id","unipileId","status","ownerId","ownerEmail"]},"LimitBucketDto":{"type":"object","properties":{"limit":{"type":"number","description":"The configured daily cap","example":15},"usedToday":{"type":"number","description":"How many have been used so far today","example":4},"remaining":{"type":"number","description":"Remaining quota for today (never negative)","example":11}},"required":["limit","usedToday","remaining"]},"AccountLimitsBreakdownDto":{"type":"object","properties":{"invitations":{"$ref":"#/components/schemas/LimitBucketDto"},"messages":{"$ref":"#/components/schemas/LimitBucketDto"},"profileVisits":{"$ref":"#/components/schemas/LimitBucketDto"},"inmails":{"$ref":"#/components/schemas/LimitBucketDto"},"companyPageInvitations":{"$ref":"#/components/schemas/LimitBucketDto"},"reactToPosts":{"$ref":"#/components/schemas/LimitBucketDto"}},"required":["invitations","messages","profileVisits","inmails","companyPageInvitations","reactToPosts"]},"AccountLimitsDto":{"type":"object","properties":{"accountId":{"type":"number","description":"The account (seat) identifier"},"ownerId":{"type":"string","description":"The ID of the user who owns this account"},"timezone":{"type":"string","description":"The timezone used to determine the daily reset boundary","example":"America/New_York"},"date":{"type":"string","description":"The date (in the account timezone) the usage counts apply to","example":"2026-06-18"},"isCurrentlyThrottled":{"type":"boolean","description":"Whether the account is currently throttled by LinkedIn","example":false},"activeDaysOfWeek":{"description":"Days of the week on which sending is active","example":["MONDAY","TUESDAY","WEDNESDAY","THURSDAY","FRIDAY"],"type":"array","items":{"type":"string"}},"inMailCredit":{"type":"number","description":"Remaining InMail credits","example":0},"searchesPerDay":{"type":"number","description":"Daily search cap (no per-day usage counter is tracked)","example":80},"limits":{"$ref":"#/components/schemas/AccountLimitsBreakdownDto"}},"required":["accountId","ownerId","timezone","date","isCurrentlyThrottled","activeDaysOfWeek","inMailCredit","searchesPerDay","limits"]},"UpdateAccountLimitsDto":{"type":"object","properties":{"maxDailyInvites":{"type":"number","description":"Daily connection-invite cap","minimum":0},"maxDailyMessages":{"type":"number","description":"Daily message cap","minimum":0},"maxDailyInmails":{"type":"number","description":"Daily InMail cap","minimum":0},"maxDailyProfileVisits":{"type":"number","description":"Daily profile-visit cap","minimum":0},"maxDailyCompanyPageInvitations":{"type":"number","description":"Daily company-page-invitation cap","minimum":0},"maxDailyReactToPosts":{"type":"number","description":"Daily post-reaction cap","minimum":0},"enableAutoWithdrawal":{"type":"boolean","description":"Whether to auto-withdraw pending invites"},"inviteWithdrawalDuration":{"type":"number","description":"Days after which a pending invite is auto-withdrawn (1-91)","minimum":1,"maximum":91},"activeDaysOfWeek":{"type":"array","description":"Days of the week on which sending is active","items":{"type":"string","enum":["MONDAY","TUESDAY","WEDNESDAY","THURSDAY","FRIDAY","SATURDAY","SUNDAY"]}},"timezone":{"type":"string","description":"IANA timezone used for the daily reset and sending window","example":"America/New_York"}}},"CreateWebhookDto":{"type":"object","properties":{"name":{"type":"string","description":"A human-readable name for the webhook"},"endpoint":{"type":"string","description":"The URL that will receive event notifications (POST)","example":"https://example.com/hooks/botdog"},"eventTypes":{"type":"array","description":"The event types to subscribe to","items":{"type":"string","enum":["CAMPAIGN_STARTED","CAMPAIGN_COMPLETED","LEAD_PROFILE_VISITED","LEAD_INVITATION_SENT","LEAD_INVITATION_ACCEPTED","LEAD_MESSAGE_SENT","LEAD_MESSAGE_REPLIED","LEAD_INVITATION_WITHDRAWN","LEAD_SKIPPED","NON_CAMPAIGN_LEAD_INBOX_MESSAGE_RECEIVED","INBOX_MESSAGE_SENT","ACCOUNT_DISCONNECTED","DAILY_LIMIT_REACHED"]}},"campaignIds":{"description":"Restrict delivery to specific campaign IDs (default: all)","type":"array","items":{"type":"string"}}},"required":["name","endpoint","eventTypes"]},"WebhookDto":{"type":"object","properties":{"id":{"type":"string","description":"The unique identifier of the webhook"},"name":{"type":"string","description":"A human-readable name for the webhook"},"endpoint":{"type":"string","description":"The URL that receives event notifications","example":"https://example.com/hooks/botdog"},"status":{"type":"string","description":"The webhook status","example":"ACTIVE"},"scope":{"type":"string","description":"Delivery scope. ALL and SPECIFIC_CAMPAIGNS carry campaign events; CONNECTED_ACCOUNT carries events that belong to no campaign, such as inbox messages from outside your campaigns.","example":"ALL"},"type":{"type":"string","description":"The webhook type","example":"GENERIC"},"isTeamWebhook":{"type":"boolean","description":"Whether the webhook is shared across the team","example":false},"eventTypes":{"description":"Event types this webhook is subscribed to","example":["LEAD_INVITATION_ACCEPTED","LEAD_MESSAGE_REPLIED"],"type":"array","items":{"type":"string"}},"campaignIds":{"description":"Campaign IDs this webhook is scoped to (empty when scope is ALL)","type":"array","items":{"type":"string"}},"createdAt":{"format":"date-time","type":"string","description":"When the webhook was created"},"updatedAt":{"format":"date-time","type":"string","description":"When the webhook was last updated"}},"required":["id","name","endpoint","status","scope","type","isTeamWebhook","eventTypes","campaignIds","createdAt","updatedAt"]},"UpdateWebhookDto":{"type":"object","properties":{"name":{"type":"string","description":"A human-readable name for the webhook"},"endpoint":{"type":"string","description":"The URL that receives notifications"},"eventTypes":{"type":"array","description":"Replace the subscribed event types","items":{"type":"string","enum":["CAMPAIGN_STARTED","CAMPAIGN_COMPLETED","LEAD_PROFILE_VISITED","LEAD_INVITATION_SENT","LEAD_INVITATION_ACCEPTED","LEAD_MESSAGE_SENT","LEAD_MESSAGE_REPLIED","LEAD_INVITATION_WITHDRAWN","LEAD_SKIPPED","NON_CAMPAIGN_LEAD_INBOX_MESSAGE_RECEIVED","INBOX_MESSAGE_SENT","ACCOUNT_DISCONNECTED","DAILY_LIMIT_REACHED"]}}}},"SnippetDto":{"type":"object","properties":{"id":{"type":"string","description":"The unique identifier of the snippet"},"name":{"type":"string","description":"The name of the snippet"},"shortcut":{"type":"string","description":"The keyboard shortcut for the snippet, if any","nullable":true},"type":{"type":"string","description":"The snippet type: a static TEXT template or an LLM prompt","example":"TEXT"},"status":{"type":"string","description":"The snippet status","example":"ACTIVE"},"content":{"type":"string","description":"The template body (for TEXT snippets)","nullable":true},"prompt":{"type":"string","description":"The generation prompt (for LLM snippets)","nullable":true},"isShared":{"type":"boolean","description":"Whether the snippet is shared with the team","example":false},"createdAt":{"format":"date-time","type":"string","description":"When the snippet was created"},"updatedAt":{"format":"date-time","type":"string","description":"When the snippet was last updated"}},"required":["id","name","type","status","isShared","createdAt","updatedAt"]},"PaginatedSnippetsDto":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SnippetDto"}},"nextCursor":{"type":"string","description":"Opaque cursor for the next page; null when there are no more results. Pass it back as the `cursor` query parameter.","nullable":true}},"required":["data","nextCursor"]},"CreateSnippetDto":{"type":"object","properties":{"name":{"type":"string","description":"The snippet name"},"type":{"type":"string","description":"A static TEXT template or an LLM prompt","enum":["TEXT","LLM"],"default":"TEXT"},"content":{"type":"string","description":"Template body (required for TEXT)"},"prompt":{"type":"string","description":"Generation prompt (required for LLM)"},"shortcut":{"type":"string","description":"A quick-access shortcut (must be unique)"}},"required":["name"]},"UpdateSnippetDto":{"type":"object","properties":{"name":{"type":"string","description":"The snippet name"},"content":{"type":"string","description":"Template body (for TEXT snippets)"},"prompt":{"type":"string","description":"Generation prompt (for LLM snippets)"},"shortcut":{"type":"string","description":"A quick-access shortcut (must be unique)"},"status":{"type":"string","description":"Set ACTIVE or ARCHIVED","enum":["ACTIVE","ARCHIVED"]}}},"SendMessageDto":{"type":"object","properties":{"leadId":{"type":"string","description":"The lead to message (must already have a conversation)"},"text":{"type":"string","description":"The message text","maxLength":8000}},"required":["leadId","text"]},"SendMessageResponseDto":{"type":"object","properties":{"leadId":{"type":"string","description":"The lead that was messaged"},"chatId":{"type":"string","description":"The conversation the message was sent to. Use it with POST /v1/conversations/{id}/reply."},"messageId":{"type":"string","description":"The provider message id, if returned","nullable":true}},"required":["chatId","messageId"]},"ReplyDto":{"type":"object","properties":{"text":{"type":"string","description":"The reply text","maxLength":8000}},"required":["text"]},"ScheduleMessageDto":{"type":"object","properties":{"leadId":{"type":"string","description":"The lead to message (must already have a conversation)"},"text":{"type":"string","description":"The message text","maxLength":8000},"fireAt":{"type":"string","description":"When to send (ISO 8601). Must be 60s–90 days in the future. Counts against the daily per-account send budget.","example":"2026-06-19T09:00:00Z"}},"required":["leadId","text","fireAt"]},"ScheduledMessageResponseDto":{"type":"object","properties":{"scheduledMessageId":{"type":"string","description":"The scheduled message id"},"chatId":{"type":"string","description":"The conversation it will be sent to"},"fireAt":{"format":"date-time","type":"string","description":"When it will fire"},"status":{"type":"string","description":"The status","example":"PENDING"}},"required":["scheduledMessageId","chatId","fireAt","status"]},"ReadStatusDto":{"type":"object","properties":{"read":{"type":"boolean","description":"true to mark read, false to mark unread","default":true}},"required":["read"]},"ReadStatusResponseDto":{"type":"object","properties":{"chatId":{"type":"string","description":"The conversation"},"read":{"type":"boolean","description":"The resulting read state"}},"required":["chatId","read"]}}}}