# Salesmotion API > Compact API reference for AI agents. For the full OpenAPI spec with JSON schemas, see [openapi.json](openapi.json). Base URL: `https://api.salesmotion.io` Auth: `Authorization: Bearer ` Access tiers: - `Public API`: company resolution and company sub-resource reads shared by both full-workspace and public-api-only organizations. - `Full Access`: workspace-backed account, contact, signal, and account-insight reads. Public API-only organizations receive predictable empty-list or `404` behavior on these routes. - Separate account-insight connector spec: [openapi-v2-minimal.json](openapi-v2-minimal.json). ## Field Catalog ### Account fields id, organizationId, companyId, ownerId, createdAt, updatedAt, name, domain, logoUrl, featuredImageUrl, description, industry, headquartersLocation, numberOfEmployees, type, priority, mainScore, mainScoreComponents, summary, insights, swotAnalysis, threeWhys, valuePyramid, valueProposition, valueHypothesis (internal: highLevelMatch), pointOfView, linkedInUrl, crunchbaseUrl, zoomInfoUrl, salesforceUrl, salesNavigatorUrl, addedOn, lastRefreshAt, countryCode ### Contact fields id, organizationId, accountId, firstName, lastName, currentTitle, currentCompanyName, changeType, inCurrentRoleSince, lastChangeDetectedOn, mainScore, linkedInUrl, email, emailStatus, phone, location, previousTitle, previousCompanyName, profilePictureUrl, type, contactRole, personInsights, talkingPoints, positionWhenFormerUser, introPaths, matchingTargetKeywords, matchingTargetJobTitles, matchingTargetLocations, matchingTargetTechnologies ### Signal fields id, organizationId, accountId, type, subtype, headline, description, date, sources, matchingKeywords, relevance, fullContent, smartSummary, playUrls, slidesUrls, documentsUrls, clinicalTrialPrimaryCompletionDate, clinicalTrialStudyCompletionDate, clinicalTrialLastKnownStatus, clinicalTrialCollaborators, createdAt, updatedAt ### Company fields id, name, domain, websiteUrl, description, industry, headquartersLocation, numberOfEmployees, mainStockSymbol, crunchbaseUrl, linkedInUrl, fiscalYearInfo, insights (opt-in) ### News article fields id, companyId, headline, url, datePublished, description, excerpt, publisher, publisherUrl, featuredImageUrl, articleBody (opt-in) ### Job opening fields id, companyId, status, url, title, companyName, location, postedOn, applicants, seniorityLevel, employmentType, jobFunction, industries, jobDescription (opt-in) ### Earnings call fields id, companyId, stockSymbol, year, quarter, happenedAt, audioUrl, reportUrl, presentationUrl, fullTranscript (opt-in), generatedAnalysis (opt-in) ### Filing fields id, companyId, type, accessionNumber, url, filingDate, reportDate, fiscalYear, quarter, fullContent (opt-in) --- ## GET /v1/account-insights Full Access workspace read. Resolves an account by name, domain, or ID and returns the complete insight in a simplified, PDF-like structure. Designed for AI agents (e.g. Microsoft Copilot) that need the full account picture in a single call. Public API-only organizations always receive `status=not_found` on this route. At least one of query, domain, or accountId is required. **Resolution order**: accountId (direct lookup) → domain (exact match) → query (domain check, then text search). **Response `status` field**: - `found` — single account matched, `data` contains the full insight. - `multiple_matches` — text query matched several accounts. `candidates` lists them with `accountId`, `name`, and `domain`. `bestMatch` contains the highest-scored candidate. Re-call with `accountId` or `domain` to disambiguate. - `not_found` — no account matches the given criteria. All resolution outcomes return HTTP 200. Only `400` is returned for missing query parameters. | Param | Type | Required | Description | |-------|------|----------|-------------| | `signalsLimit` | number | no | Max signals when included (default 20, max 100) | | `contactsLimit` | number | no | Max contacts when included (default 10, max 100) | | `include` | string | no | Comma-separated opt-in for related resources: contacts, signals | | `sections` | string | no | Comma-separated list of insight sections to include in the response: profile, summary, research, swotAnalysis, value. When omitted, all sections are returned. The profile section is always included regardless of this parameter. | | `accountId` | number | no | Direct account ID lookup. Takes priority over domain and query if multiple params are provided. | | `domain` | string | no | Exact domain match. Automatically normalized: leading www/subdomains are stripped and the value is lowercased. Prefer this over query when you have a domain. | | `query` | string | no | Free-text company name search. Case-insensitive. If the value looks like a domain (e.g. contains a dot), it is first tried as an exact domain match before falling back to text search. | **200** Account insight response. Check the `status` field: found (data present), multiple_matches (candidates present), or not_found. ``` { status: string message?: string data?: { profile: { accountId, name?, domain?, logoUrl?, description?, headquartersLocation?, industry?, numberOfEmployees?, score?, type?, priority?, countryCode?, addedOn?, lastRefreshAt?, owner?, links? } summary?: { keyInsights?, opportunities?, challenges?, peopleUpdates?, topNews?, talkingPoints?, executivePerspective? } research?: { companyOverview?, keyPeopleChanges?, keyProjects?, aspirations?, businessGoals?, opportunities?, macroeconomicPerspective?, recentPressAnnouncements?, businessModel?, strategicInitiatives?, financials? } swotAnalysis?: { strengths?, weaknesses?, opportunities?, threats? } value?: { threeWhys?, valuePyramid?, valuePropositionIdeas?, valueHypothesis?, pointOfView? } } candidates?: [{ accountId: number name?: string domain?: string }] bestMatch?: { accountId: number name?: string domain?: string } included?: object meta: { requestId: string apiVersion: string timestamp: string } usage: { limit: number used: number remaining: number resetsAt: string } } ``` **400** No query parameters provided — at least one of query, domain, or accountId is required --- ## GET /v1/accounts/{accountId} Full Access workspace read. Returns one tracked Salesmotion account. Public API-only organizations always receive `404` on this route. | Param | Type | Required | Description | |-------|------|----------|-------------| | `accountId` | number | yes | | | `view` | `default`, `export` | no | | | `onlyWithFields` | string | no | Comma-separated account fields to select (e.g. id,name,domain) | | `signalsLimit` | number | no | | | `contactsLimit` | number | no | | | `include` | string | no | | **200** Account payload with optional included resources ``` { data: { id: number organizationId: string companyId?: string ownerId?: string createdAt: string updatedAt: string name?: string domain?: string logoUrl?: string featuredImageUrl?: string description?: string industry?: string headquartersLocation?: string numberOfEmployees?: number type: string priority?: number mainScore?: number mainScoreComponents?: object summary?: object insights?: object swotAnalysis?: object threeWhys?: object valuePyramid?: object valueProposition?: object valueHypothesis?: object pointOfView?: object linkedInUrl?: string crunchbaseUrl?: string zoomInfoUrl?: string salesforceUrl?: string salesNavigatorUrl?: string addedOn?: string lastRefreshAt?: string countryCode?: string } included?: object meta: { requestId: string apiVersion: string timestamp: string } usage: { limit: number used: number remaining: number resetsAt: string } } ``` **404** Account not found. Public API-only organizations always receive 404. --- ## GET /v1/accounts Full Access workspace read. Returns tracked Salesmotion accounts for the current organization. Public API-only organizations always receive an empty list on this route. | Param | Type | Required | Description | |-------|------|----------|-------------| | `view` | `default`, `export` | no | | | `perPage` | number | no | | | `page` | number | no | | | `sortOrder` | `asc`, `desc` | no | Sort direction (default: desc) | | `sortBy` | string | no | Account field to sort by (default: mainScore) | | `onlyWithFields` | string | no | Comma-separated account fields to select (e.g. id,name,domain) | | `include` | string | no | Supported: company,owner | | `hasSignalsOfType` | string | no | Combined with hasSignalsAfterDate — only count signals of this type (comma-separated, e.g. relevant-news,hiring-alert) | | `hasSignalsAfterDate` | string | no | ISO date — only accounts with at least one signal after this date | | `priority` | number | no | Filter by priority (1=high, 2=medium, 3=low) | | `type` | string | no | Filter by account type (e.g. prospect, customer, partner, churned, open-opportunity, competitor, other) | | `ownerId` | string | no | Filter by account owner user ID | | `companyId` | string | no | Filter by linked company ID | | `domain` | string | no | Exact domain match (e.g. acme.com) | | `textQuery` | string | no | Search accounts by name or domain | | `ids` | string | no | Comma-separated account ids | **200** Account list payload ``` { data: [{ id: number organizationId: string companyId?: string ownerId?: string createdAt: string updatedAt: string name?: string domain?: string logoUrl?: string featuredImageUrl?: string description?: string industry?: string headquartersLocation?: string numberOfEmployees?: number type: string priority?: number mainScore?: number mainScoreComponents?: object summary?: object insights?: object swotAnalysis?: object threeWhys?: object valuePyramid?: object valueProposition?: object valueHypothesis?: object pointOfView?: object linkedInUrl?: string crunchbaseUrl?: string zoomInfoUrl?: string salesforceUrl?: string salesNavigatorUrl?: string addedOn?: string lastRefreshAt?: string countryCode?: string }] included?: object meta: { requestId: string apiVersion: string timestamp: string page: number perPage: number totalCount: number totalPages: number } usage: { limit: number used: number remaining: number resetsAt: string } } ``` --- ## GET /v1/companies/{companyId} Public API company profile read. Resolve a company first with `/v1/companies/by-input/{companyInputId}`, then use the returned `data.id` here and on other company sub-resource endpoints. Default responses return the public company profile; generated fields such as `insights` are opt-in via `onlyWithFields`. | Param | Type | Required | Description | |-------|------|----------|-------------| | `companyId` | string | yes | | | `view` | `default`, `export` | no | | | `onlyWithFields` | string | no | Comma-separated company fields to select (e.g. id,name,domain,insights). Generated fields remain opt-in. | | `include` | string | no | Supported: latestEarningsCall,latestEarningsCallAnalysis | **200** Public company profile payload with optional included resources ``` { data: { id: string name?: string domain?: string websiteUrl?: string description?: string industry?: string headquartersLocation?: string numberOfEmployees?: number mainStockSymbol?: string crunchbaseUrl?: string linkedInUrl?: string fiscalYearInfo?: object insights?: object } included?: object meta: { requestId: string apiVersion: string timestamp: string } usage: { limit: number used: number remaining: number resetsAt: string } } ``` **404** Company not found --- ## GET /v1/companies/by-input/{companyInputId} Public API company resolution endpoint. Supports canonical company id, domain, website URL, stock symbol, LinkedIn URL, and Crunchbase URL. Use the returned `data.id` with `/v1/companies/{companyId}` and other company sub-resource endpoints to follow the resolve-first workflow. | Param | Type | Required | Description | |-------|------|----------|-------------| | `view` | `default`, `export` | no | | | `onlyWithFields` | string | no | Comma-separated company fields to select (e.g. id,name,domain,insights). Generated fields remain opt-in. | | `include` | string | no | Supported: latestEarningsCall,latestEarningsCallAnalysis | | `companyInputId` | string | yes | | **200** Resolved public company profile payload with optional included resources ``` { data: { id: string name?: string domain?: string websiteUrl?: string description?: string industry?: string headquartersLocation?: string numberOfEmployees?: number mainStockSymbol?: string crunchbaseUrl?: string linkedInUrl?: string fiscalYearInfo?: object insights?: object } included?: object meta: { requestId: string apiVersion: string timestamp: string } usage: { limit: number used: number remaining: number resetsAt: string } } ``` **404** Company not found for the provided input --- ## GET /v1/companies/{companyId}/news-articles Public API company news collection. Resolve a company first with `/v1/companies/by-input/{companyInputId}`, then request this company sub-resource. Default responses return article metadata only. Heavy raw text is returned only when explicitly requested with `onlyWithFields=articleBody`. | Param | Type | Required | Description | |-------|------|----------|-------------| | `companyId` | string | yes | | | `view` | `default`, `export` | no | | | `perPage` | number | no | | | `page` | number | no | | | `onlyWithFields` | string | no | Comma-separated news article fields to select (e.g. id,headline,url,datePublished,articleBody). Raw text is opt-in. | **200** Public company news article list payload ``` { data: [{ id: string companyId?: string headline?: string url: string datePublished: string description?: string excerpt?: string publisher?: string publisherUrl?: string featuredImageUrl?: string articleBody?: string }] meta: { requestId: string apiVersion: string timestamp: string page: number perPage: number totalCount: number totalPages: number } usage: { limit: number used: number remaining: number resetsAt: string } } ``` **404** Company not found --- ## GET /v1/companies/{companyId}/job-openings Public API company job openings collection. Resolve a company first with `/v1/companies/by-input/{companyInputId}`, then request this company sub-resource. Default responses return job-opening metadata and public URLs only. Full job description text is returned only when explicitly requested with `onlyWithFields=jobDescription`. | Param | Type | Required | Description | |-------|------|----------|-------------| | `companyId` | string | yes | | | `view` | `default`, `export` | no | | | `perPage` | number | no | | | `page` | number | no | | | `onlyWithFields` | string | no | Comma-separated job opening fields to select (e.g. id,title,url,postedOn,jobDescription). Full description text is opt-in. | **200** Public company job opening list payload ``` { data: [{ id: string companyId?: string status?: string url: string title?: string companyName?: string location?: string postedOn: string applicants?: string seniorityLevel?: string employmentType?: string jobFunction?: string industries?: string jobDescription?: string }] meta: { requestId: string apiVersion: string timestamp: string page: number perPage: number totalCount: number totalPages: number } usage: { limit: number used: number remaining: number resetsAt: string } } ``` **404** Company not found --- ## GET /v1/companies/{companyId}/earnings-calls Public API company earnings-calls collection. Resolve a company first with `/v1/companies/by-input/{companyInputId}`, then request this company sub-resource. Default responses return financial-event metadata and safe public URLs only. Heavy transcript text and AI-generated analysis are returned only when explicitly requested with `onlyWithFields`. | Param | Type | Required | Description | |-------|------|----------|-------------| | `companyId` | string | yes | | | `view` | `default`, `export` | no | | | `perPage` | number | no | | | `page` | number | no | | | `onlyWithFields` | string | no | Comma-separated earnings-call fields to select (e.g. id,year,audioUrl,fullTranscript,generatedAnalysis). Raw transcript text and generated analysis are opt-in. | **200** Public company earnings call list payload ``` { data: [{ id: number companyId?: string stockSymbol?: string year?: number quarter?: number happenedAt?: string audioUrl?: string reportUrl?: string presentationUrl?: string fullTranscript?: string generatedAnalysis?: object }] meta: { requestId: string apiVersion: string timestamp: string page: number perPage: number totalCount: number totalPages: number } usage: { limit: number used: number remaining: number resetsAt: string } } ``` **404** Company not found --- ## GET /v1/companies/{companyId}/filings Public API company filings collection. Resolve a company first with `/v1/companies/by-input/{companyInputId}`, then request this company sub-resource. Default responses return filing metadata and public SEC URLs only. Heavy filing text is returned only when explicitly requested with `onlyWithFields=fullContent`. | Param | Type | Required | Description | |-------|------|----------|-------------| | `companyId` | string | yes | | | `view` | `default`, `export` | no | | | `perPage` | number | no | | | `page` | number | no | | | `onlyWithFields` | string | no | Comma-separated filing fields to select (e.g. id,type,accessionNumber,url,filingDate,fullContent). Full filing text is opt-in. | **200** Public company filing list payload ``` { data: [{ id: number companyId?: string type?: string accessionNumber?: string url?: string filingDate?: string reportDate?: string fiscalYear?: number quarter?: number fullContent?: string }] meta: { requestId: string apiVersion: string timestamp: string page: number perPage: number totalCount: number totalPages: number } usage: { limit: number used: number remaining: number resetsAt: string } } ``` **404** Company not found --- ## GET /v1/contacts Full Access workspace read. Returns contacts linked to tracked accounts in the current organization. Public API-only organizations always receive an empty list on this route. | Param | Type | Required | Description | |-------|------|----------|-------------| | `perPage` | number | no | | | `page` | number | no | | | `sortOrder` | `asc`, `desc` | no | Sort direction (default: desc) | | `sortBy` | string | no | Contact field to sort by (default: inCurrentRoleSince) | | `onlyWithFields` | string | no | Comma-separated contact fields to select (e.g. id,firstName,lastName,currentTitle) | | `include` | string | no | Supported: account | | `isInCurrentRoleBeforeDate` | string | no | ISO date — contacts in current role before this date | | `isInCurrentRoleAfterDate` | string | no | ISO date — contacts in current role after this date | | `lastChangeDetectedBefore` | string | no | ISO date — only contacts with changes before this date | | `lastChangeDetectedAfter` | string | no | ISO date — only contacts with changes after this date | | `currentTitleTextQuery` | string | no | Title-specific search | | `textQuery` | string | no | Full-text search on name, title, company, location | | `type` | string | no | Filter by contact type (e.g. prospect, champion, contact) | | `changeType` | string | no | Filter by change type (e.g. promotion, newJoiner, departure, internalChange, newInRole) | | `accountId` | string | no | Filter by account ID (comma-separated for multiple) | **200** Contact list payload ``` { data: [{ id: string organizationId: string accountId?: number firstName?: string lastName?: string currentTitle?: string currentCompanyName?: string changeType?: string inCurrentRoleSince?: string lastChangeDetectedOn?: string mainScore?: number linkedInUrl?: string email?: string emailStatus?: string phone?: string location?: string previousTitle?: string previousCompanyName?: string profilePictureUrl?: string type?: string contactRole?: string personInsights?: object talkingPoints?: object positionWhenFormerUser?: object introPaths?: string[] matchingTargetKeywords?: string[] matchingTargetJobTitles?: string[] matchingTargetLocations?: string[] matchingTargetTechnologies?: string[] }] meta: { requestId: string apiVersion: string timestamp: string page: number perPage: number totalCount: number totalPages: number } usage: { limit: number used: number remaining: number resetsAt: string } } ``` --- ## GET /v1/contacts/{contactId} Full Access workspace read. Returns one tracked contact. Public API-only organizations always receive `404` on this route. | Param | Type | Required | Description | |-------|------|----------|-------------| | `contactId` | string | yes | | | `onlyWithFields` | string | no | Comma-separated contact fields to select | | `include` | string | no | Supported: account | **200** Contact payload ``` { data: { id: string organizationId: string accountId?: number firstName?: string lastName?: string currentTitle?: string currentCompanyName?: string changeType?: string inCurrentRoleSince?: string lastChangeDetectedOn?: string mainScore?: number linkedInUrl?: string email?: string emailStatus?: string phone?: string location?: string previousTitle?: string previousCompanyName?: string profilePictureUrl?: string type?: string contactRole?: string personInsights?: object talkingPoints?: object positionWhenFormerUser?: object introPaths?: string[] matchingTargetKeywords?: string[] matchingTargetJobTitles?: string[] matchingTargetLocations?: string[] matchingTargetTechnologies?: string[] } meta: { requestId: string apiVersion: string timestamp: string } usage: { limit: number used: number remaining: number resetsAt: string } } ``` **404** Contact not found. Public API-only organizations always receive 404. --- ## GET /v1/signals Full Access workspace read. Returns signals linked to tracked accounts in the current organization. Public API-only organizations always receive an empty list on this route. | Param | Type | Required | Description | |-------|------|----------|-------------| | `perPage` | number | no | | | `page` | number | no | | | `sortOrder` | `asc`, `desc` | no | Sort direction (default: desc) | | `sortBy` | string | no | Signal field to sort by (default: date) | | `onlyWithFields` | string | no | Comma-separated signal fields to select (e.g. id,type,headline,date) | | `textQuery` | string | no | Full-text search on signal content | | `beforeDate` | string | no | ISO date — only signals before this date | | `afterDate` | string | no | ISO date — only signals after this date | | `type` | string | no | Filter by signal type (comma-separated, e.g. relevant-news,hiring-alert,press-release,m-and-a-alert,funding-alert,earnings-call) | | `accountId` | string | no | Filter by account ID (comma-separated for multiple) | **200** Signal list payload ``` { data: [{ id: number organizationId: string accountId: number type: string subtype?: string headline: string description?: string date: string sources?: string[] matchingKeywords?: string[] relevance?: object fullContent?: string smartSummary?: object playUrls?: object slidesUrls?: string[] documentsUrls?: string[] clinicalTrialPrimaryCompletionDate?: string clinicalTrialStudyCompletionDate?: string clinicalTrialLastKnownStatus?: string clinicalTrialCollaborators?: string[] createdAt: string updatedAt: string }] meta: { requestId: string apiVersion: string timestamp: string page: number perPage: number totalCount: number totalPages: number } usage: { limit: number used: number remaining: number resetsAt: string } } ``` --- ## GET /v1/signals/counts Full Access workspace read. Returns signal aggregates for tracked accounts in the current organization. Public API-only organizations always receive an empty object on this route. | Param | Type | Required | Description | |-------|------|----------|-------------| | `textQuery` | string | no | Full-text search filter | | `beforeDate` | string | no | ISO date — only count signals before this date | | `afterDate` | string | no | ISO date — only count signals after this date | | `accountId` | string | no | Filter by account ID (comma-separated for multiple) | **200** Signal counts by type ``` { data: object meta: { requestId: string apiVersion: string timestamp: string } usage: { limit: number used: number remaining: number resetsAt: string } } ``` --- ## GET /v1/signals/{signalId} Full Access workspace read. Returns one tracked signal. Public API-only organizations always receive `404` on this route. | Param | Type | Required | Description | |-------|------|----------|-------------| | `signalId` | number | yes | | | `onlyWithFields` | string | no | Comma-separated signal fields to select | **200** Signal payload ``` { data: { id: number organizationId: string accountId: number type: string subtype?: string headline: string description?: string date: string sources?: string[] matchingKeywords?: string[] relevance?: object fullContent?: string smartSummary?: object playUrls?: object slidesUrls?: string[] documentsUrls?: string[] clinicalTrialPrimaryCompletionDate?: string clinicalTrialStudyCompletionDate?: string clinicalTrialLastKnownStatus?: string clinicalTrialCollaborators?: string[] createdAt: string updatedAt: string } meta: { requestId: string apiVersion: string timestamp: string } usage: { limit: number used: number remaining: number resetsAt: string } } ``` **404** Signal not found. Public API-only organizations always receive 404. --- ## POST /v1/feedback Submit feedback on API usage **Request body** ``` { rating?: number category?: string message: string context?: object } ``` **200** Feedback received ``` { data: object meta: { requestId: string apiVersion: string timestamp: string } } ``` --- ## GET /v1/usage Get customer-facing API usage and quota | Param | Type | Required | Description | |-------|------|----------|-------------| | `window` | `daily`, `monthly`, `custom` | no | | | `organizationId` | string | no | | | `groupBy` | `endpoint`, `apiKey`, `day` | no | | | `to` | string | no | | | `from` | string | no | | **200** Usage totals and quota ``` { data: { window: string from: string to: string quota: { limit, used, remaining, resetsAt } totals: object breakdown?: [{ key, requests, successful, failed }] } meta: { requestId: string apiVersion: string timestamp: string } } ``` --- ## GET /v1/usage/requests Get recent customer-facing API request history | Param | Type | Required | Description | |-------|------|----------|-------------| | `window` | `daily`, `monthly`, `custom` | no | | | `organizationId` | string | no | | | `perPage` | number | no | | | `page` | number | no | | | `to` | string | no | | | `from` | string | no | | **200** Paginated request history for the current organization ``` { data: [{ id: number occurredAt: string endpoint: string successful: boolean error?: string apiKeyId?: string input?: object }] meta: { requestId: string apiVersion: string timestamp: string page: number perPage: number totalCount: number totalPages: number } } ``` --- ## GET /v1/usage/limits Get usage limits configured for the current organization | Param | Type | Required | Description | |-------|------|----------|-------------| | `organizationId` | string | no | | **200** Contracted usage limits ``` { data: object meta: { requestId: string apiVersion: string timestamp: string } } ``` ---