bulk_create_accounts
ChatGPTdomain; existing accounts are returned with their accountId rather than duplicated. Use when the user pastes a list of companies, imports a CSV, or asks to bulk-add accounts. For a single account, prefer create_account.By Octolane
Revenue superintelligence built for modern sales and go-to-market teams. Connect Octolane to ChatGPT and Codex to read and manage your revenue workflow. Pipeline & deal management: Search deals, get full deal details, create new opportunities, move deals through pipeline stages, and get instant pipeline overviews with deal counts and total values. Create and customize sales pipelines, stages, and custom fields on the fly. Contacts & accounts: Search, create, update, and enrich contacts and companies by name, email, domain, industry, or job title. Bulk create up to 50 records or update up to 25 records in one request. Email & meetings: Search email threads with any contact or account, schedule emails for future delivery via your connected Gmail, and pull full meeting transcripts and attendee lists to prep for calls or write follow-ups. Tasks, notes & activities: Create tasks linked to deals, contacts, or accounts; log calls, meetings, and LinkedIn touches; and keep notes attached to the right records. Website visitor intelligence: Identify companies visiting your website with Octolane Signal and turn anonymous traffic into pipeline. AI memory: Octolane stores your ICP, sales process, pricing, and writing style as structured memory, so ChatGPT and Codex can use your team's context. Ask things like "which deals are stalled in negotiation," "prep me for my 2pm meeting," or "draft follow-ups for every demo this week." Connect an existing Octolane workspace to read, create, update, and delete CRM records and schedule emails, subject to workspace permissions and connected-service access.
domain; existing accounts are returned with their accountId rather than duplicated. Use when the user pastes a list of companies, imports a CSV, or asks to bulk-add accounts. For a single account, prefer create_account.email; existing contacts are returned with their contactId rather than duplicated. The backend auto-creates the associated account from each email domain. Use when the user pastes a list of people, imports a CSV, or asks to bulk-add contacts. For a single contact, prefer create_contact. Every email MUST be one you actually obtained from a real source (a prior tool/search result, an attachment, an email thread, or the user). NEVER guess or pattern-construct an address such as first.last@company.com - a guessed email pollutes the CRM and is rejected at send time (the recipient guard does not trust contacts this conversation created). If you have no real email for a person, omit them rather than inventing one.account, primary_contact, and additional_contacts - the backend auto-creates/upserts them by domain/email, so you do NOT need to call bulk_create_accounts or bulk_create_contacts first. Provide either pipeline_id or pipeline_name per item (defaults to the org's default pipeline if both omitted). Duplicate deal names within a pipeline are returned in skipped rather than failing the whole batch. Use when the user pastes a list of deals, imports a CSV, or asks to bulk-create deals. For a single deal, prefer create_deal.records is keyed by account/company UUID (company_id), where each value is a field patch keyed by property_name. Before calling, resolve account IDs with search_accounts and discover valid field property_names/types with get_account_fields. Do NOT guess custom attribute names. Values must match the attribute type: string for text/select/date strings, number for numeric fields, boolean for checkbox/radio, array for multi_select/team_members/date_range, and null to clear nullable fields. For more than 25 records, split the set into batches of at most 25 and call this tool once per batch - the MCP server has no async bulk-update job.records is keyed by contact/person UUID (people_id), where each value is a field patch keyed by property_name. Before calling, resolve contact IDs with search_contacts and discover valid field property_names/types with get_contact_fields. Do NOT guess custom attribute names. Be especially careful with email updates: use only confirmed CRM or user-provided email addresses. For more than 25 records, split the set into batches of at most 25 and call this tool once per batch - the MCP server has no async bulk-update job.records is keyed by opportunity UUID (opportunity_id), where each value is a field patch keyed by property_name. Before calling, resolve deal IDs with search_deals and discover valid fields with get_deal_fields for the relevant pipeline. Custom deal fields are pipeline-scoped; do NOT guess property names. Relationship fields take UUIDs: opportunity_account uses company_id, opportunity_contact uses people_id, and opportunity_other_stakeholders uses an array of people_id values. For more than 25 records, split the set into batches of at most 25 and call this tool once per batch - the MCP server has no async bulk-update job.updates is either a CREATE or an EDIT: (1) CREATE - omit stage_id and provide pipeline_id + label (color, probability, stage_type, is_default, description, stage_order are optional). (2) EDIT - provide stage_id and any of label, color, probability, stage_type, is_default, description. Use this tool whenever the user asks to add, create, rename, recolor, reorder, or reconfigure pipeline stages - there is no separate create_pipeline_stage tool. Pass description to set per-stage guidance / exit criteria (what a deal is doing in the stage and what's still pending to move it forward); it is surfaced back to the chat as context by list_pipeline_stages and get_pipeline_overview. Pass an empty string to clear it. Use list_pipeline_stages first to find stage IDs (for edits) or pipeline_id (for creates).name is ONLY the field label. It is a short noun phrase like "Commission" or "Renewal Date". It NEVER contains verbs ("add", "set"), quantities ("$50"), or the record you are targeting ("on Acme"). Extract the label alone from the user's request. Good: name: "Commission". Bad: name: "add Commission field and set 50 dollar on acme". Supported attribute_type values: string, number, checkbox, date, date_range, rating, timestamp, select, multi_select, currency, percentage, location, time, datetime, email, phone, website, url. For select / multi_select pass metadata.select_options as [{ value, label, color?, order }]. property_name is auto-generated from the name. SETTING A VALUE TOO: this tool only creates the field. When the user also wants a value set ("add Fund Size and set it to $2M on Acme"), call bulk_update_accounts next with the property_name this call returns.email MUST come from a real source (a tool/search result, attachment, email thread, or the user) - never guess or pattern-construct it (e.g. first.last@company.com). A guessed address is rejected at send time and pollutes the CRM; if you have no real email, do not invent one.name is ONLY the field label. It is a short noun phrase like "Commission" or "LinkedIn Verified". It NEVER contains verbs ("add", "set"), quantities ("$50"), or the record you are targeting ("on Fred"). Extract the label alone from the user's request. Good: name: "Commission". Bad: name: "add commission field and set 50 dollar on contact fred". Supported attribute_type values: string, number, checkbox, date, date_range, rating, timestamp, select, multi_select, currency, percentage, location, time, datetime, email, phone, website, url. For select / multi_select pass metadata.select_options as [{ value, label, color?, order }]. SETTING A VALUE TOO: this tool only creates the field. When the user also wants a value set ("add Commission and set 50 on Fred"), call bulk_update_contacts next with the property_name this call returns.entity_id + entity_type. Resolve the UUID first with search_deals / search_contacts / search_accounts; if the target contact or account doesn't exist, create it via create_contact or create_account before calling this tool. Use when asked to log a note, record a conversation summary, add context to a deal, or document an interaction. For many notes at once, call this tool once per note - the MCP server does not expose a bulk note tool.stages is provided, it REPLACES the template's default stages so the new pipeline starts with EXACTLY those stages in array order - prefer this on CRM migrations (Pipedrive, HubSpot, etc.) to avoid having to follow up with bulk_delete_stages + bulk_upsert_stages to clean up template defaults. Each stage may carry a description (what belongs in the stage, when to move a deal on), so set them here instead of a follow-up bulk_upsert_stages. When stages is omitted, the template's default stage set is used (prior behavior).name is ONLY the field label. It is a short noun phrase like "ARR" or "Renewal Date". It NEVER contains verbs ("add", "set"), quantities ("$100k"), or the record you are targeting ("on Stripe"). Extract the label alone from the user's request. Good: name: "ARR". Bad: name: "ARR and set the value $100k on Stripe". Use list_pipeline_stages or get_deal_fields to discover pipeline_id. Supported attribute_type values: string, number, checkbox, date, date_range, rating, timestamp, select, multi_select, currency, percentage, location, time, datetime, email, phone, website, url. For select / multi_select pass metadata.select_options as [{ value, label, color?, order }]. SETTING A VALUE TOO: this tool only creates the field. When the user also wants a value set ("set ARR to $100k on Stripe" and ARR does not exist yet), call bulk_update_deals next with the property_name this call returns.days days, oldest first. stale_by sets what moving means: activity (default) is the linked account's last email or meeting, not deal edits; stage is the deal's last stage change (renaming or reordering a stage also counts as one). A deal is never counted as staler than it is old: with no account activity, or no recorded stage change, since it was created, it counts from its creation date, so it is included once it is older than days. So an empty or short result does NOT mean the other deals had recent activity: a deal created within days is simply too new to count. Do not claim activity the result does not show. Won and lost deals are left out. Pass days as a plain integer (e.g. 14) - do NOT compute a cutoff date yourself, the tool does the date math. Use when asked for stale, dormant, neglected, stuck or forgotten deals ("no activity in 2 weeks", "stuck in a stage for a month", "what's gone quiet"). Omit pipeline_name to search every pipeline in the org; a pipeline with exactly that name wins over partial matches, and matched_pipelines lists the pipelines searched. Each deal carries days_stale and stale_since_source, which says what it was measured from. Returns a page of deals (limit sets its size) with total_count and total_amount over every match; pass offset to page through the rest.field_name; if the field label is custom/unknown, call get_deal_fields first to resolve it.pipeline_fields array, one entry per pipeline) - use this when the user asks for fields without naming a pipeline. Returns field names, types, and valid dropdown options. Each pipeline can have different custom fields. Use when asked "what fields can I set on a deal," before creating/updating deals, or when asked about deal properties or pipeline-specific custom fields.search_meetings identifies the meeting the user is asking about. Returns utterances, attendee details (name, email, status, organizer flag), summary, brief, calendar invite description, and recording metadata (video/thumbnail). Note: transcript may be null if the bot didn't join or the meeting hasn't ended. EXPENSIVE: full transcripts are large. Only call when the user asks about a specific meeting or a small set. For broad questions across many meetings (e.g. 'summarize my recent calls', 'patterns across customer meetings'), use search_meetings (which already returns title, summary, brief, and attendees) and reason from those summaries instead of pulling each transcript. PAGINATION: long transcripts are returned in chunks. The response includes transcriptPagination { totalUtterances, returnedUtterances, hasMore, nextOffset }. When hasMore is true and you need more of the transcript, call again with transcript_offset set to nextOffset to read the next chunk.limit up to 50 and increase offset by the number of notes returned until that total reaches total_count. Use when asked to find notes, show notes, pull up notes, or check what's been logged for any CRM record.description (free-text exit criteria / guidance on what a deal does in that stage and what's pending to advance it) - read it when reasoning about deals in a stage. avg_deal_size is the mean over the deals that HAVE an amount (deals_with_value), so it is not total_value / deal_count when some deals have no amount - quote deals_with_value alongside it. Use when asked about pipeline health, funnel status, deal distribution, stage breakdown, "how's my pipeline," "show me the funnel," or "what's in my pipeline."property_name, plus a readable property_label), the old and new values, the author, and the timestamp. For reference fields such as a deal stage or account, old_value_label/new_value_label resolve the stored id to its name. ONE FIELD: pass property_name to narrow to a single field's history; get the correct name from get_account_fields / get_contact_fields / get_deal_fields rather than guessing. PROVENANCE: read source, not user, to say who or what made a change. source is one of user_web, public_api, mcp, chat, workflow, enrichment, integration_sync, csv_import, system. For public_api, source_api_key_id names which of the workspace's API keys wrote, so several automations are separable. user is the person when one was involved, but it is NOT a provenance signal on its own: a public-API write resolves the author to the workspace owner, so a human there does not mean a human made the change. source is null on entries predating this field - say the origin is unknown, never 'unknown user' and never guess a person. For mcp, mcp_key_id names the agent connection and tool the tool it called. change_kind says what happened: created (a value the record was created with - defaulted: true when the system filled it in rather than anyone choosing it), updated, or for deal stakeholders linked / unlinked; null on older entries. PAGINATION: results are one page, not the complete history. Use limit up to 100 and start with offset: 0; while the number of entries read is less than total_count, call this tool again with offset increased by the number of entries returned. Ordering is stable across pages.description (free-text exit criteria / guidance on what a deal does in that stage and what's pending to advance it - read it when reasoning about where a deal stands or what's blocking it). Use when asked about pipeline stages, what stages exist, or stage configuration. Omit both parameters to list stages for all pipelines.pipeline_id, name and total_deals. Use it to get a pipeline id for another tool, or to answer what pipelines exist. total_deals counts every deal in the pipeline, won and lost included. It matches get_pipeline_overview's total except for a deal whose stage was deleted, which the per-stage overview has no row for. For a pipeline's stages use list_pipeline_stages; for stage-by-stage totals use get_pipeline_overview.object_type ('contact' or 'account') and object_id (UUID of the linked record) - call search_contacts or search_accounts first to resolve the ID. If the contact/account doesn't exist, create it first with create_contact or create_account. occurred_at may be a future, current, or past date.id to update). Use when the user explicitly asks to save context that should persist across AI turns - e.g. 'remember that our ICP is seed-stage SaaS', 'save this as my writing style', 'note that Acme evaluates quarterly'. Prefer org-scope for shared workspace context (ICP, pricing, process) and user-scope for personal context (writing style, signature). Org-scope writes require admin privileges. Never use this for transient chat notes - memory is for durable, curated context, not conversation facts. Passing id updates that exact block: its scope and category are fixed, so the ones you send are ignored and cannot convert a block or rename it. OUTCOME: check saved before telling the user it worked. A custom write can be matched to an existing block and kept unchanged, which returns saved: false with that block's id, title and content - report what is actually stored, not the wording you asked for, and pass the returned id back if you mean to overwrite it.scheduled_at must be ISO 8601 with timezone offset; interpret natural-language times like 'tomorrow 9am' against the user's timezone. Returns a per-draft results array so partial failures are visible (e.g. unconnected sender, past scheduled_at). Each draft fans out into one row per to recipient - capture the returned scheduled_mail_ids if the user may want to edit or cancel later.limit up to 50 and start with offset: 0; while the number of records read is less than total_count, call this tool again with offset increased by the number of results returned. Ordering is stable across pages. PARAMETER CHOICE: use the top-level semantic params (query, domain, industry) for common filters. Use additional_filters only for custom attributes, interaction dates, employee range, or anything beyond the semantic params. ADDITIONAL_FILTERS PREREQUISITE: for custom attributes, call get_account_fields first to get the correct property_name. Do NOT guess property names. MULTIPLE COMPANY NAMES IN ONE QUERY: use keywords, not query. See the keywords parameter docs for the batching rule. ZERO RESULTS RETRY: if the search returns total_count=0, retry ONCE with a different keyword before telling the user the company does not exist. Drop legal suffixes ("Acme Inc" → "Acme", "OpenAI LLC" → "OpenAI"), try the domain alone when known (works even if the display name differs), or the short / common name when the CSV imported a long-form legal name. Stop after one retry - do not loop.limit up to 50 and start with offset: 0; while the number of records read is less than total_count, call this tool again with offset increased by the number of results returned. Ordering is stable across pages. PARAMETER CHOICE: use the top-level semantic params (query, company_name, job_title) for common filters. Use additional_filters only for custom attributes, seniority, last interaction, or anything beyond the semantic params. ADDITIONAL_FILTERS PREREQUISITE: for custom attributes, call get_contact_fields first to get the correct property_name. Do NOT guess property names. MULTIPLE PEOPLE IN ONE QUERY: use keywords, not query. See the keywords parameter docs for the batching rule. ZERO RESULTS RETRY: if the search returns total_count=0, retry ONCE with a different keyword before telling the user the contact does not exist. Try the last name alone ("Gaby Jimenez" → "Jimenez" finds "Gabriela Jimenez" - nicknames don't fuzzy-match), the email if visible elsewhere in the chat (attachments, prior tool output, the user's message), or the full first name when you only used a nickname ("Mike" → "Michael"). Stop after one retry - do not loop.limit up to 50 and start with offset: 0; while the number of records read is less than total_count, call this tool again with offset increased by the number of results returned. Ordering is stable across pages. PARAMETER CHOICE: use the top-level semantic params (pipeline_name, stage_name, account_name, contact_name, min_amount, max_amount, close_date_from, close_date_to) for common filters. Use additional_filters only for custom attributes, owner, last activity, or anything beyond the semantic params. ADDITIONAL_FILTERS PREREQUISITES: (1) set pipeline_name or stage_name first to resolve a pipeline (additional_filters and sort_by both require this); (2) for custom attributes, call get_deal_fields first to get the correct property_name. Do NOT guess property names. MULTIPLE DEAL NAMES IN ONE QUERY: use keywords, not search_query. See the keywords parameter docs for the batching rule. ZERO RESULTS RETRY: if the search returns total_count=0, retry ONCE with a broader keyword before telling the user nothing was found. Drop trailing segments ("Acme Q4 Expansion Deal" → "Acme Q4 Expansion" → "Acme"), or swap to a different name field (account_name only or contact_name only). Stop after one retry - do not loop.keywords (up to 10) in a single call - do not loop with multiple search_emails calls. Searches across all mailboxes the user can access, including their own Gmail and any shared mailboxes delegated to them. Each result includes mailbox_email and is_shared so you can tell which inbox an email came from. Pass mailbox_id to restrict to a specific mailbox. A domain/email-only miss triggers a real-time Gmail sync. If only a different workspace member has a match, privacy-safe fallback fields expose activity or Gmail email subjects through workspace_email_subjects only; never claim access to the hidden message details or mailbox owner. Use when asked about email history, correspondence, what was emailed, communication with a lead or account, or "did I email them."activity_id from a prior activity search/timeline result.attendees is provided it REPLACES the entire list - any current attendee not included will be removed. Omit attendees to leave invitees untouched. For calendar_event_id, pass either the id field from a prior search_meetings result (an internal UUID) or the Google event ID of an existing event.cancel: true to unschedule. Otherwise pass any subset of editable fields (to, cc, bcc, subject, body, scheduled_at) to update them in place. Cancel is mutually exclusive with field edits. Each scheduled_mail_id maps to ONE recipient row - if the original draft was scheduled to multiple recipients, call this tool once per id. scheduled_at (when given) must be ISO 8601 with timezone offset, ≥30s in the future and ≤1 year out. Returns success:false (not an error) if the email has already sent, failed, cancelled, or is currently being processed.Click any prompt to copy it.