Sales tools
Sales covers the pipeline: opportunities, their deliverables and tasks, converting a won opportunity to a project, and the budgets of live proposals.
The toolset also has:
search_recordsdelete_recordwith the opportunity row and budget row kinds- The three report tools,
get_overview_report,get_revenue_reportandget_receivables_report
To write or send the proposal document itself, add the Proposals toolset.
Tools
Each tool below shows what the server sends: its description (written for the AI), its kind, the permissions it needs, the fields it returns, and its inputs. An input in a.b or a[].b form is a field inside an object or a list. For the shared rules on results, pages, money and errors, see Results, errors and limits.
list_opportunities
List the opportunities (the sales pipeline) that the user can see, newest first. To find one opportunity by name or number, use search_records. Filter with project_status_ids, lead_score_ids, assigned_to_ids, team_ids or no_team, opportunity_tags, an estimated start date range, a due date range and project_number. Send response_format detailed for the description, dates, tags, currency and referrer. projects lists the delivery projects made from the opportunity.
| Title | List opportunities |
| Toolsets | Sales |
| Kind | Read only, Idempotent |
| Needs | api_read, and an opportunity read permission (all, team or assigned). A project read permission is not enough |
| Returns | opportunities, count, limit, offset, has_more |
| Input | Type | Required | Description |
|---|---|---|---|
project_status_ids |
array of integers | Only opportunities with one of these status ids. From search_records with kinds project_status and status opportunity. | |
lead_score_ids |
array of integers | Only opportunities with one of these lead score ids. From search_records with kinds lead_score. | |
assigned_to_ids |
array of integers | Only opportunities assigned to one of these members. From search_records with kinds member. | |
opportunity_tags |
array of strings | Only opportunities with all of these tags. | |
team_ids |
array of integers | Only opportunities of one of these teams. From search_records with kinds team. | |
no_team |
boolean | true for only the opportunities with no team. Do not send with team_ids. | |
estimated_start_date |
string | Only opportunities with an estimated start on or after this date, yyyy-mm-dd. | |
estimated_end_date |
string | Only opportunities with an estimated start on or before this date, yyyy-mm-dd. | |
due_date_from |
string | Only opportunities due on or after this date, yyyy-mm-dd. | |
due_date_to |
string | Only opportunities due on or before this date, yyyy-mm-dd. | |
project_number |
string | Only the opportunity with this exact number. | |
response_format |
string | concise (default) or detailed. One of concise, detailed. |
|
limit |
integer | Maximum rows to return. Default 25, maximum 100 (25 for detailed). | |
offset |
integer | Number of rows to skip. Default 0. |
get_opportunity
Read one opportunity by id, with its deliverables and tasks, custom fields, lead score and its members with their project roles (members). Read it before update_opportunity or convert_opportunity, and send its project_status id as expected_project_status_id in those calls. projects lists the delivery projects made from the opportunity (an empty list means that it is not converted), and variation is not null for a variation opportunity and shows what convert_opportunity would do. Deliverables come in pages, so if deliverables_page.has_more is true, call again with deliverable_offset set to offset plus count. Rows are concise. Send response_format detailed for their money, dates, notes and the budget lines of each task.
| Title | Get opportunity |
| Toolsets | Sales |
| Kind | Read only, Idempotent |
| Needs | api_read, and read access to the opportunity |
| Returns | id, name, project_number, estimated_start_date, project_status, client, team, lead_score, projects, description, currency, estimated_end_date, enquiry_date, target_date, due_date, deal_won_at, deal_lost_at, opportunity_tags, variation_opportunity, variation, referrer_company, referrer_contact, amount, due_at, colour, default_rate_card, project_templates, invoicing_structure, estimated_deposit, project_tags, members, counts, deliverables, deliverables_page, contacts, custom_fields, recent_notes, notes_count, total_budget, financial_summary |
| Input | Type | Required | Description |
|---|---|---|---|
opportunity_id |
integer | Yes | From search_records or list_opportunities. |
include |
array of strings | Sections to return. Default all but contacts. tasks also returns deliverables. financials returns total_budget and financial_summary. One of financials, deliverables, tasks, contacts, custom_fields, notes. |
|
deliverable_ids |
array of integers | Only these deliverables and their tasks. Ids from an earlier get_opportunity. Default all. | |
deliverable_offset |
integer | Number of deliverables to skip. Default 0. | |
response_format |
string | concise (default) or detailed. detailed adds the money, dates, notes and task budget lines. One of concise, detailed. |
create_opportunity
Create an opportunity (a deal in the sales pipeline) for a client company. Search for the opportunity with search_records first, and use update_opportunity when it exists. A field that is not sent takes the default of the Drum form: the default status and lead score, today as the enquiry date, the default templates, and the user as the member when the account has no opportunity roles. The templates add their deliverables. The money fields and the lead score need the permission to see opportunity money. It sends the webhooks of the account and can start its automations.
| Title | Create opportunity |
| Toolsets | Sales |
| Kind | Writes data |
| Needs | api_create, create_opportunities and read_companies. Money fields and lead_score_id also need view_opportunity_financial_values |
| Returns | opportunity, replayed |
| Input | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | 255 characters or fewer. |
client_company_id |
integer | Yes | From search_records with kinds company. |
project_status_id |
integer | From search_records with kinds project_status and status opportunity. | |
description |
string | ||
lead_score_id |
integer | From search_records with kinds lead_score. | |
team_id |
integer | From search_records with kinds team. | |
amount_cents |
integer | Deal value in cents. | |
invoicing_structure |
string | How the deal will be invoiced. One of payment_on_delivery, monthly. |
|
estimated_deposit_cents |
integer | Expected deposit in cents. | |
enquiry_date |
string | Date of the enquiry. | |
target_date |
string | Next action date. | |
due_at |
string | Due time, ISO 8601. | |
estimated_start_date |
string | Expected start of the work. | |
estimated_end_date |
string | Expected end of the work. | |
default_rate_card_id |
integer | From search_records with kinds rate_card. | |
project_template_ids |
array of integers | From search_records with kinds project_template. Replaces the templates. | |
referrer_company_id |
integer | From search_records with kinds company. | |
referrer_contact_id |
integer | From search_records with kinds contact. | |
colour |
string | One of red, orange, amber, yellow, lime, green, emerald, teal, cyan, sky, blue, indigo, violet, purple, fuchsia, pink, rose. |
|
role_members |
array of objects | The members of each role. | |
role_members[].project_role_id |
integer or null | Yes | From search_records with kinds project_role. null: the members with no role. |
role_members[].member_ids |
array of integers | Yes | From search_records with kinds member. |
opportunity_tags |
array of strings | Tags of the opportunity. | |
location_id |
integer | From search_records with kinds location. Needed when the number uses the location. | |
idempotency_key |
string | 255 characters or fewer. |
update_opportunity
Change the fields of one opportunity. Omit a field to keep it, and send null to clear an optional field. A status of a lost type sets the lost date, and on a variation opportunity it also declines the proposal and rejects the variation, but a won status does not convert the opportunity, and a variation opportunity refuses it: use convert_opportunity. Send expected_project_status_id from get_opportunity, and the call answers conflict (stale_state) if the status changed. The money fields and the lead score need the permission to see opportunity money. A change sends the webhooks of the account, and a status change can start its automations.
| Title | Update opportunity |
| Toolsets | Sales |
| Kind | Writes data, Idempotent |
| Needs | api_update, and read and update access to the opportunity. Money fields and lead_score_id also need view_opportunity_financial_values |
| Returns | opportunity |
| Input | Type | Required | Description |
|---|---|---|---|
opportunity_id |
integer | Yes | From search_records or list_opportunities. |
name |
string | ||
client_company_id |
integer | From search_records with kinds company. | |
project_status_id |
integer | From search_records with kinds project_status and status opportunity. | |
description |
string or null | null clears it. | |
lead_score_id |
integer or null | From search_records with kinds lead_score. null clears it. | |
team_id |
integer or null | From search_records with kinds team. null clears it. | |
amount_cents |
integer | Deal value in cents. | |
invoicing_structure |
string or null | How the deal will be invoiced. null clears it. | |
estimated_deposit_cents |
integer | Expected deposit in cents. | |
enquiry_date |
string or null | Date of the enquiry. null clears it. | |
target_date |
string or null | Next action date. null clears it. | |
due_at |
string or null | Due time, ISO 8601. null clears it. | |
estimated_start_date |
string or null | Expected start of the work. null clears it. | |
estimated_end_date |
string or null | Expected end of the work. null clears it. | |
default_rate_card_id |
integer | From search_records with kinds rate_card. | |
project_template_ids |
array of integers | From search_records with kinds project_template. Replaces the templates. | |
referrer_company_id |
integer or null | From search_records with kinds company. null clears it. | |
referrer_contact_id |
integer or null | From search_records with kinds contact. null clears it. | |
colour |
string or null | null clears it. | |
project_role_id |
integer or null | The role whose members member_ids replaces, from search_records with kinds project_role. null: the members with no role. | |
member_ids |
array of integers | From search_records with kinds member. Replaces the members of project_role_id. Other roles are kept. | |
add_opportunity_tags |
array of strings | Other tags are kept. | |
remove_opportunity_tags |
array of strings | Other tags are kept. | |
expected_project_status_id |
integer | The current status id, from get_opportunity. |
add_opportunity_row
Add a deliverable or task to an opportunity. A task needs deliverable_id, from get_opportunity. Price an opportunity in its proposal budget (add_proposal_row), not on its tasks. The result has the new rows. After a timeout, read the opportunity with get_opportunity before you try again.
| Title | Add opportunity row |
| Toolsets | Sales |
| Kind | Writes data |
| Needs | api_create, and the web permissions for the row: opportunity update access or update_budgets for a deliverable or task, and update_budgets for budget fields and expense lines |
| Returns | rows |
| Input | Type | Required | Description |
|---|---|---|---|
opportunity_id |
integer | Yes | From search_records or list_opportunities. |
row_type |
string | Yes | One of deliverable, task. |
deliverable_id |
integer | row_type task, from get_opportunity. | |
position |
integer | 1-based place among its siblings. Default last. | |
row |
object | The fields of the new row. | |
row.name |
string | ||
row.description |
string | deliverable. | |
row.start_date |
string | yyyy-mm-dd. | |
row.end_date |
string | deliverable. | |
row.due_date |
string | task. | |
row.project_phase_id |
integer | deliverable. | |
row.rate_card_id |
integer | deliverable, kinds rate_card. | |
row.from_project_template_deliverable_ids |
array of integers | deliverable: copies these template deliverables with their tasks. | |
row.item_type |
string | One of task, heading, event, process_only. |
|
row.note |
string | task. |
update_opportunity_row
Change a deliverable or task of an opportunity, by row_type and id from get_opportunity. Omit a field to keep it, and send null to clear it. Price an opportunity in its proposal budget (add_proposal_row), not on its tasks. The result has the changed row. Delete rows with delete_record, row_type as kind.
| Title | Update opportunity row |
| Toolsets | Sales |
| Kind | Writes data, Idempotent |
| Needs | api_update, and the same permissions as add_opportunity_row |
| Returns | rows |
| Input | Type | Required | Description |
|---|---|---|---|
opportunity_id |
integer | Yes | From search_records or list_opportunities. |
row_type |
string | Yes | One of deliverable, task. |
id |
integer | Yes | From get_opportunity. |
position |
integer | 1-based place among its siblings. | |
row |
object | The fields to change. | |
row.name |
string | ||
row.description |
string or null | deliverable. null clears it. | |
row.status |
string | deliverable or task. One of not_started, in_progress, completed, not_applicable, blocked. |
|
row.start_date |
string or null | yyyy-mm-dd. null clears it. | |
row.end_date |
string or null | deliverable. null clears it. | |
row.due_date |
string or null | task. null clears it. | |
row.project_phase_id |
integer or null | deliverable. null clears it. | |
row.rate_card_id |
integer or null | deliverable, kinds rate_card. null clears it. | |
row.deliverable_id |
integer | task: moves it there, from get_opportunity. | |
row.item_type |
string | One of task, heading, event, process_only. |
|
row.member_ids |
array of integers | task: replaces its members. | |
row.note |
string or null | task. null clears it. |
convert_opportunity
Convert an opportunity and mark it won, which cannot be reversed. A usual opportunity becomes a new delivery project: the call makes a project number, marks the client company as a client, and moves the email threads of the opportunity to the project. A variation opportunity (variation is not null in get_opportunity) makes no project: the call accepts the proposal of the variation and adds the variation to the budget and contract value of its project, so send variation.total as expected_total_cents and no project inputs. It sends the webhooks of the account and can start its automations. Send expected_project_status_id from get_opportunity, and the call answers conflict (stale_state) if the status or the total changed. If the conversion is done already, the result has created false and the existing project, and nothing changes.
| Title | Convert opportunity |
| Toolsets | Sales |
| Kind | Writes data, Destructive |
| Needs | api_create, opportunity read and update access and create_projects, or read_quotes and accept_quotes for the accepted proposal. budget_cents also needs view_opportunity_financial_values |
| Returns | created, project, opportunity |
| Input | Type | Required | Description |
|---|---|---|---|
opportunity_id |
integer | Yes | From search_records or list_opportunities. |
expected_project_status_id |
integer | Yes | The current status id of the opportunity, from get_opportunity. |
project_status_id |
integer | Status of the project. From search_records with kinds project_status and status project. Default: the default status of the template. | |
name |
string | Project name. Default: the opportunity name. | |
description |
string | Project description. Default: the opportunity description. | |
team_id |
integer | Team of the project. From search_records with kinds team. Default: the opportunity team. | |
start_date |
string | Project start, yyyy-mm-dd. | |
end_date |
string | Project end, yyyy-mm-dd. | |
location_id |
integer | Location of the project. From search_records with kinds location. | |
budget_cents |
integer | Budget and final deal value in cents, tax exclusive, in the default currency of the account. Needs the permission to see opportunity money. | |
proposal_id |
integer | Accepted proposal to build the project from. From search_records with kinds proposal. Default: the last accepted proposal. | |
structure_type |
string | budget (default): deliverables from the proposal budget. proposal: from the quote sections. One of budget, proposal. |
|
allow_additional_project |
boolean | Make one more project when a project already exists. Default false. | |
expected_total_cents |
integer | Variation opportunity only, and required there when you can see opportunity money: the cents of variation.total from get_opportunity, tax exclusive. It is the value that the user confirms. | |
won_status_id |
integer | Variation opportunity only. The won status of the opportunity. From search_records with kinds project_status and status opportunity. Default: the default won status. |
get_proposal
Read one live proposal (a quote on an opportunity) with its budget and the ids of all budget rows. Each row shows the keys that add_proposal_row and update_proposal_row take for its row type, and its record_kind for delete_record. The quote sections and fee lines are not in the result. Budget deliverables come in pages, so if budget.deliverables_page.has_more is true, call again with budget_deliverable_offset set to offset plus count. Budget items are concise, and response_format detailed adds their values, other fields and lines.
| Title | Get proposal |
| Toolsets | Sales |
| Kind | Read only, Idempotent |
| Needs | api_read, read_quotes, read_budgets, and read access to the proposal’s opportunity or project |
| Returns | id, name, description, status, project, project_template, currency, total_excluding_tax, deleted, budget, warnings |
| Input | Type | Required | Description |
|---|---|---|---|
proposal_id |
integer | Yes | From search_records with kinds proposal. |
budget_deliverable_ids |
array of integers | Only these budget deliverables. Ids from get_proposal. Default all. | |
budget_deliverable_offset |
integer | Number of budget deliverables to skip. Default 0. | |
response_format |
string | concise (default): id, record_kind, kind, name, item_type and position of each budget item. detailed adds the values, the other fields and the lines. One of concise, detailed. |
add_proposal_row
Add one row to the budget of a live proposal. A new budget_deliverable or budget_item can include its new children, and a new budget_deliverable can copy one of the same budget (copy_from_id). delete_record takes the row_type as the kind of the new row. The proposal’s fees do not change, and a finalised budget refuses the row. After a timeout, read the proposal with get_proposal before you try again.
| Title | Add proposal row |
| Toolsets | Sales |
| Kind | Writes data |
| Needs | api_create, the get_proposal permissions, and update_budgets |
| Returns | proposal_id, row_type, record_kind, row, rows, warnings |
| Input | Type | Required | Description |
|---|---|---|---|
proposal_id |
integer | Yes | From search_records with kinds proposal. |
row_type |
string | Yes | One of budget_phase, budget_deliverable, budget_item, budget_item_resource, budget_item_cost. |
budget_deliverable_id |
integer | row_type budget_item: its budget deliverable, from get_proposal. | |
budget_item_id |
integer | row_type budget_item_resource or budget_item_cost: its budget item, from get_proposal. | |
position |
integer | 1-based place in the row’s list. | |
row |
object | Yes | The keys of row_type, as get_proposal shows that row. |
row.name |
string | ||
row.description |
string | ||
row.colour |
string | A phase takes gray, red, orange, yellow, blue, green or indigo. One of red, orange, amber, yellow, lime, green, emerald, teal, cyan, sky, blue, indigo, violet, purple, fuchsia, pink, rose, gray. |
|
row.budget_type |
string | One of fixed_price, time_and_materials. |
|
row.budget_phase_id |
integer | A budget phase, from get_proposal. | |
row.budget_phase_name |
string | Or a budget phase name. | |
row.kind |
string | fixed: quantity x rate. dynamic: sum of lines. One of fixed, dynamic, non_financial. |
|
row.item_type |
string | One of task, event, process_only. |
|
row.delivery_task_name |
string | Its task name on a project. | |
row.quantity |
number | ||
row.quantity_unit |
string | One of hour, day, per_item. |
|
row.billable_rate_cents |
integer | Tax exclusive. | |
row.resource_type_id |
integer | From search_records with kinds resource_type. | |
row.preferred_member_id |
integer | From search_records with kinds member. | |
row.rate_cents |
integer | Tax exclusive. Omit to use the rate cards. | |
row.notes |
string | ||
row.cost_type_id |
integer | From search_records with kinds cost_type. | |
row.items |
array of objects | ||
row.items[].kind |
string | fixed: quantity x rate. dynamic: sum of lines. One of fixed, dynamic, non_financial. |
|
row.items[].name |
string | Yes | |
row.items[].item_type |
string | One of task, event, process_only. |
|
row.items[].description |
string | ||
row.items[].delivery_task_name |
string | Its task name on a project. | |
row.items[].quantity |
number | ||
row.items[].quantity_unit |
string | One of hour, day, per_item. |
|
row.items[].billable_rate_cents |
integer | Tax exclusive. | |
row.items[].resources |
array of objects | ||
row.items[].resources[].resource_type_id |
integer | From search_records with kinds resource_type. | |
row.items[].resources[].preferred_member_id |
integer | From search_records with kinds member. | |
row.items[].resources[].quantity |
number | ||
row.items[].resources[].quantity_unit |
string | One of hour, day, per_item. |
|
row.items[].resources[].rate_cents |
integer | Tax exclusive. Omit to use the rate cards. | |
row.items[].resources[].notes |
string | ||
row.items[].costs |
array of objects | ||
row.items[].costs[].cost_type_id |
integer | Yes | From search_records with kinds cost_type. |
row.items[].costs[].name |
string | Yes | |
row.items[].costs[].description |
string | ||
row.items[].costs[].quantity |
number | ||
row.items[].costs[].quantity_unit |
string | One of hour, day, per_item. |
|
row.items[].costs[].billable_rate_cents |
integer | Tax exclusive. | |
row.resources |
array of objects | ||
row.resources[].resource_type_id |
integer | From search_records with kinds resource_type. | |
row.resources[].preferred_member_id |
integer | From search_records with kinds member. | |
row.resources[].quantity |
number | ||
row.resources[].quantity_unit |
string | One of hour, day, per_item. |
|
row.resources[].rate_cents |
integer | Tax exclusive. Omit to use the rate cards. | |
row.resources[].notes |
string | ||
row.costs |
array of objects | ||
row.costs[].cost_type_id |
integer | Yes | From search_records with kinds cost_type. |
row.costs[].name |
string | Yes | |
row.costs[].description |
string | ||
row.costs[].quantity |
number | ||
row.costs[].quantity_unit |
string | One of hour, day, per_item. |
|
row.costs[].billable_rate_cents |
integer | Tax exclusive. | |
row.copy_from_id |
integer | A deliverable of the same budget to copy, from get_proposal. |
update_proposal_row
Change one budget row of a live proposal by row_type and id (from get_proposal). Only the keys sent change, and null clears a field. Add a child row with add_proposal_row, not here. budget_deliverable_id moves a budget_item to another budget deliverable, and position (1 is first) moves the row in its list. A finalised budget refuses the change, and delete_record deletes a row with its row_type as kind.
| Title | Update proposal row |
| Toolsets | Sales |
| Kind | Writes data, Idempotent |
| Needs | api_update, the get_proposal permissions, and update_budgets |
| Returns | proposal_id, row_type, record_kind, row, rows, warnings |
| Input | Type | Required | Description |
|---|---|---|---|
proposal_id |
integer | Yes | From search_records with kinds proposal. |
row_type |
string | Yes | One of budget_phase, budget_deliverable, budget_item, budget_item_resource, budget_item_cost. |
id |
integer | Yes | Row id, from get_proposal. |
budget_deliverable_id |
integer | row_type budget_item: move it to this budget deliverable, from get_proposal. | |
position |
integer | 1-based place in the row’s list. | |
row |
object | The keys to change, as get_proposal shows that row. | |
row.name |
string | ||
row.description |
string or null | null clears it. | |
row.colour |
string or null | A phase takes gray, red, orange, yellow, blue, green or indigo. null clears it. | |
row.budget_type |
string | One of fixed_price, time_and_materials. |
|
row.budget_phase_id |
integer or null | A budget phase, from get_proposal. null clears it. | |
row.budget_phase_name |
string | Or a budget phase name. | |
row.kind |
string | fixed: quantity x rate. dynamic: sum of lines. One of fixed, dynamic, non_financial. |
|
row.item_type |
string | One of task, event, process_only. |
|
row.delivery_task_name |
string or null | Its task name on a project. null clears it. | |
row.quantity |
number | ||
row.quantity_unit |
string | One of hour, day, per_item. |
|
row.billable_rate_cents |
integer | Tax exclusive. | |
row.resource_type_id |
integer | From search_records with kinds resource_type. | |
row.preferred_member_id |
integer or null | From search_records with kinds member. null clears it. | |
row.rate_cents |
integer | Tax exclusive. Omit to use the rate cards. | |
row.notes |
string or null | null clears it. | |
row.cost_type_id |
integer | From search_records with kinds cost_type. |