Authentication
All API requests require authentication using a Bearer token. Include your API token in the Authorization header of each request:
Authorization: Bearer YOUR_API_TOKEN
For detailed information about authentication, token generation, and permissions, see the API Authentication documentation.
All endpoints are scoped to a specific account. Only opportunities belonging to the authenticated user's account will be accessible.
The Opportunity Object
An opportunity object represents a potential client engagement or sales opportunity within Drum. To access won or active projects, you'll need to use the Projects API instead.
Core Attributes
Attribute | Type | Description |
id | integer | Unique identifier for the opportunity. |
name | string | The opportunity name. |
description | string | null | Optional detailed description of the opportunity. |
project_number | string | Unique opportunity number/code. |
currency | string | Three-letter ISO currency code (e.g., "AUD", "USD", "GBP"). |
Classification
Attribute | Type | Description |
project_type | string | Always "opportunity" for this endpoint. |
Sales-Specific Dates
Attribute | Type | Description |
enquiry_date | string | null | Date the opportunity enquiry was received (YYYY-MM-DD). |
target_date | string | null | Target close date (configurable name via account settings). |
due_date | string | null | Due date for proposal/response (if enabled, YYYY-MM-DDTHH:MM:SSZ). |
deal_won_date | string | null | Date the opportunity was won (auto-set when status changes). |
deal_lost_date | string | null | Date the opportunity was lost (auto-set when status changes). |
estimated_start_date | string | null | Estimated project start date if won (YYYY-MM-DD). |
estimated_end_date | string | null | Estimated project end date if won (YYYY-MM-DD). |
Sales Information
Attribute | Type | Description |
amount | decimal | Deal value/opportunity amount in currency units. |
invoicing_structure | string | null | Either "payment_on_delivery" or "monthly". |
estimated_deposit | decimal | Estimated deposit amount (requires |
lead_score | object | null | Lead score details including |
Associations
Attribute | Type | Description |
project_status | object | null | Sales status details including |
client | object | null | Client information with |
team | object | null | Team assignment with |
assigned_users | array | Array of assigned users with |
Financial Metrics
Note: Financial data requires the view_project_metrics permission. Without this permission, these fields will not be included in the response.
Attribute | Type | Description |
total_budget | decimal | Total opportunity budget in currency units. |
total_invoiced | decimal | Total amount invoiced (typically 0 for opportunities). |
costs_to_date | decimal | Actual costs incurred on the opportunity. |
unbilled_costs | decimal | Costs not yet invoiced. |
estimated_deposit | decimal | Estimated deposit amount. |
Profitability Metrics
Note: These fields require the view_gross_profit permission in addition to view_project_metrics. Without this permission, these fields will not be included in the response.
Attribute | Type | Description |
work_in_progress | decimal | WIP calculation (invoiced - earned revenue). |
remaining_cost_to_complete | decimal | Estimated costs remaining. |
Counters
Attribute | Type | Description |
quotes_count | integer | Number of quotes associated with opportunity. |
invoices_count | integer | Number of invoices (typically 0). |
progress_claims_count | integer | Number of progress claims (typically 0). |
costs_count | integer | Number of cost entries. |
Metadata
Attribute | Type | Description |
opportunity_tags | array of strings | Tags applied to the opportunity. |
planned | boolean | Whether opportunity is in planning state. |
Nested Data (Show Endpoint Only)
Attribute | Type | Description |
deliverables | array | Array of deliverable objects (only in GET /opportunities/:id endpoint). See Deliverables below. |
Example Object (Index)
The index endpoint returns a lightweight representation:
{
"id": 101,
"name": "Enterprise CRM Implementation",
"project_number": "OPP-042",
"description": "Implementation of Salesforce CRM for enterprise client",
"currency": "AUD",
"project_type": "opportunity",
"enquiry_date": "2025-10-01",
"target_date": "2025-12-15",
"estimated_start_date": "2026-01-15",
"estimated_end_date": "2026-06-30",
"project_status": {
"id": 2,
"name": "Proposal Submitted",
"complete_status": false
},
"client": {
"id": 456,
"name": "Enterprise Solutions Ltd",
"type": "Company"
},
"team": {
"id": 3,
"name": "Sales Team"
},
"amount": 250000.00,
"lead_score": {
"id": 4,
"name": "Hot Lead"
},
"total_budget": 250000.00,
"planned": false
}Example Object (Show)
The show endpoint includes comprehensive details and nested data:
{
"id": 101,
"name": "Enterprise CRM Implementation",
"project_number": "OPP-042",
"description": "Implementation of Salesforce CRM for enterprise client with full data migration and training",
"currency": "AUD",
"project_type": "opportunity",
"enquiry_date": "2025-10-01",
"target_date": "2025-12-15",
"due_date": "2025-11-30T17:00:00Z",
"deal_won_date": null,
"deal_lost_date": null,
"estimated_start_date": "2026-01-15",
"estimated_end_date": "2026-06-30",
"project_status": {
"id": 2,
"name": "Proposal Submitted",
"complete_status": false
},
"client": {
"id": 456,
"name": "Enterprise Solutions Ltd",
"type": "Company"
},
"team": {
"id": 3,
"name": "Sales Team"
},
"amount": 250000.00,
"invoicing_structure": "payment_on_delivery",
"lead_score": {
"id": 4,
"name": "Hot Lead"
},
"assigned_users": [
{
"id": 12,
"name": "Sarah Johnson"
},
{
"id": 18,
"name": "Michael Chen"
}
],
"total_budget": 250000.00,
"total_invoiced": 0.00,
"costs_to_date": 5000.00,
"unbilled_costs": 5000.00,
"estimated_deposit": 50000.00,
"work_in_progress": -5000.00,
"remaining_cost_to_complete": 195000.00,
"quotes_count": 2,
"invoices_count": 0,
"progress_claims_count": 0,
"costs_count": 12,
"opportunity_tags": ["enterprise", "crm", "high-priority"],
"planned": false,
"deliverables": [
{
"id": 50,
"name": "Discovery & Requirements",
"description": "Initial discovery phase with stakeholder workshops",
"position": 1,
"status": "completed",
"billing_type": "fixed_fee",
"allow_time_tracking": "allowed",
"percentage_complete": 100,
"currency": "AUD",
"start_date": null,
"end_date": null,
"duration": 40.0,
"budget": 15000.00,
"invoiced_amount": 0.00,
"total_cost": 5000.00,
"budget_invoiced_percent": 0.0,
"plan_only": false,
"purchase_number": null,
"claim_items_count": 0,
"tasks": [
{
"id": 501,
"name": "Stakeholder Workshops",
"note": "Conduct requirements gathering workshops",
"position": 1,
"item_type": "task",
"status": "completed",
"allow_time_tracking": "allowed",
"active": true,
"visible": true,
"currency": "AUD",
"due_date": null,
"start_date": null,
"estimated_start_date": null,
"completed_date": "2025-10-15T14:30:00Z",
"budget_type": "hourly",
"original_quantity_unit": "hour",
"original_rate": 150.00,
"original_duration": 20.0,
"original_total": 3000.00,
"variation_duration": 0.0,
"variation_total": 0.0,
"actual_duration": 18.0,
"actual_total": 2700.00,
"budget": 3000.00,
"total": 3000.00,
"remaining": 300.00,
"budget_used_percentage": 90.0,
"tracked_times_count": 4,
"costs_count": 0,
"booked_bookings_count": 0,
"resource_type": {
"id": 8,
"name": "Senior Consultant"
}
}
]
}
]
}Deliverable Object
Deliverables in opportunities represent proposed work packages or phases. The structure is identical to project deliverables. See the Projects API documentation for complete field descriptions.
Task Object
Tasks in opportunities represent proposed work items. The structure is identical to project tasks. See the Projects API documentation for complete field descriptions.
List all opportunities
Returns a paginated list of opportunities for the authenticated account. Results can be filtered using query parameters.
Endpoint
GET /api/v1/opportunities
Path Parameters
Parameter | Type | Description |
account_id | integer | The ID of the account to retrieve opportunities from. Must be an account the authenticated user has access to. |
Query Parameters
Parameter | Type | Description |
status | integer | Filter by opportunity status ID. Only opportunities with this |
project_status | integer | Alternative filter by status ID (same as |
assigned_to | integer | Filter by assigned user. Provide an |
opportunity_tag_list | array of strings | Filter by opportunity tags. Provide one or more tag names to return opportunities with any of those tags. Example: |
lead_score | integer | Filter by lead score ID. Only opportunities with this |
team | integer | Filter by team ID. Provide a |
estimated_start_date | string | Filter by estimated start date (from). Returns opportunities with |
estimated_end_date | string | Filter by estimated end date (to). Returns opportunities with |
page | integer | Page number for pagination. Defaults to 1. |
items | integer | Number of items per page. Defaults to 20. |
Example Request
curl https://app.getdrum.com/api/v1/opportunities \
-H "Authorization: Bearer YOUR_API_TOKEN"
Example Request with Filters
curl "https://app.getdrum.com/api/v1/opportunities?status=2&lead_score=4&team=3&page=1&items=50" \
-H "Authorization: Bearer YOUR_API_TOKEN"
Example Request with Tags and Date Range
curl "https://app.getdrum.com/api/v1/opportunities?opportunity_tag_list[]=enterprise&estimated_start_date=2026-01-01&estimated_end_date=2026-12-31" \
-H "Authorization: Bearer YOUR_API_TOKEN"
Response
Returns an array of opportunity objects. The index endpoint returns a lightweight representation without nested deliverables/tasks.
Note: Financial fields (total_budget, estimated_deposit) are only included if the user has the view_project_metrics permission.
[
{
"id": 101,
"name": "Enterprise CRM Implementation",
"project_number": "OPP-042",
"description": "Implementation of Salesforce CRM for enterprise client",
"currency": "AUD",
"project_type": "opportunity",
"enquiry_date": "2025-10-01",
"target_date": "2025-12-15",
"estimated_start_date": "2026-01-15",
"estimated_end_date": "2026-06-30",
"project_status": {
"id": 2,
"name": "Proposal Submitted",
"complete_status": false
},
"client": {
"id": 456,
"name": "Enterprise Solutions Ltd",
"type": "Company"
},
"team": {
"id": 3,
"name": "Sales Team"
},
"amount": 250000.00,
"lead_score": {
"id": 4,
"name": "Hot Lead"
},
"total_budget": 250000.00,
"planned": false
},
{
"id": 102,
"name": "Website Redesign - Tech Startup",
"project_number": "OPP-043",
"description": "Complete website redesign and rebrand",
"currency": "AUD",
"project_type": "opportunity",
"enquiry_date": "2025-10-15",
"target_date": "2026-01-31",
"estimated_start_date": "2026-02-01",
"estimated_end_date": "2026-04-30",
"project_status": {
"id": 1,
"name": "Proposal In Progress",
"complete_status": false
},
"client": {
"id": 457,
"name": "Tech Startup Co",
"type": "Company"
},
"team": {
"id": 2,
"name": "Design Team"
},
"amount": 75000.00,
"lead_score": {
"id": 3,
"name": "Warm Lead"
},
"total_budget": 75000.00,
"planned": false
}
]
Note: The API uses pagination via the page and items query parameters. Use pagination metadata from response headers if available, or implement client-side pagination based on the number of results returned.
Retrieve an opportunity
Retrieves the details of a specific opportunity by ID.
Endpoint
GET /api/v1/opportunities/:id
Path Parameters
Parameter | Type | Description |
account_id | integer | The ID of the account the opportunity belongs to. |
id | integer | The ID of the opportunity to retrieve. |
Example Request
curl https://app.getdrum.com/api/v1/opportunities/101 \
-H "Authorization: Bearer YOUR_API_TOKEN"
Response
Returns a comprehensive opportunity object with nested deliverables and tasks.
Note: Financial fields require appropriate permissions:
Basic financial data (
total_budget,total_invoiced, etc.) requiresview_project_metricspermissionProfitability metrics (
work_in_progress,remaining_cost_to_complete) require bothview_project_metricsANDview_gross_profitpermissions
Note: If the requested project ID exists but is a won project (not an opportunity), the endpoint will return a 404 Not Found error. Use the Projects API to access won projects.
{
"id": 101,
"name": "Enterprise CRM Implementation",
"project_number": "OPP-042",
"description": "Implementation of Salesforce CRM for enterprise client with full data migration and training",
"currency": "AUD",
"project_type": "opportunity",
"enquiry_date": "2025-10-01",
"target_date": "2025-12-15",
"due_date": "2025-11-30T17:00:00Z",
"deal_won_date": null,
"deal_lost_date": null,
"estimated_start_date": "2026-01-15",
"estimated_end_date": "2026-06-30",
"project_status": {
"id": 2,
"name": "Proposal Submitted",
"complete_status": false
},
"client": {
"id": 456,
"name": "Enterprise Solutions Ltd",
"type": "Company"
},
"team": {
"id": 3,
"name": "Sales Team"
},
"amount": 250000.00,
"invoicing_structure": "payment_on_delivery",
"lead_score": {
"id": 4,
"name": "Hot Lead"
},
"assigned_users": [
{
"id": 12,
"name": "Sarah Johnson"
},
{
"id": 18,
"name": "Michael Chen"
}
],
"total_budget": 250000.00,
"total_invoiced": 0.00,
"costs_to_date": 5000.00,
"unbilled_costs": 5000.00,
"estimated_deposit": 50000.00,
"work_in_progress": -5000.00,
"remaining_cost_to_complete": 195000.00,
"quotes_count": 2,
"invoices_count": 0,
"progress_claims_count": 0,
"costs_count": 12,
"opportunity_tags": ["enterprise", "crm", "high-priority"],
"planned": false,
"deliverables": [
{
"id": 50,
"name": "Discovery & Requirements",
"description": "Initial discovery phase with stakeholder workshops",
"position": 1,
"status": "completed",
"billing_type": "fixed_fee",
"allow_time_tracking": "allowed",
"percentage_complete": 100,
"currency": "AUD",
"start_date": null,
"end_date": null,
"duration": 40.0,
"budget": 15000.00,
"invoiced_amount": 0.00,
"total_cost": 5000.00,
"budget_invoiced_percent": 0.0,
"plan_only": false,
"purchase_number": null,
"claim_items_count": 0,
"tasks": [
{
"id": 501,
"name": "Stakeholder Workshops",
"note": "Conduct requirements gathering workshops",
"position": 1,
"item_type": "task",
"status": "completed",
"allow_time_tracking": "allowed",
"active": true,
"visible": true,
"currency": "AUD",
"due_date": null,
"start_date": null,
"estimated_start_date": null,
"completed_date": "2025-10-15T14:30:00Z",
"budget_type": "hourly",
"original_quantity_unit": "hour",
"original_rate": 150.00,
"original_duration": 20.0,
"original_total": 3000.00,
"variation_duration": 0.0,
"variation_total": 0.0,
"actual_duration": 18.0,
"actual_total": 2700.00,
"budget": 3000.00,
"total": 3000.00,
"remaining": 300.00,
"budget_used_percentage": 90.0,
"tracked_times_count": 4,
"costs_count": 0,
"booked_bookings_count": 0,
"resource_type": {
"id": 8,
"name": "Senior Consultant"
}
},
{
"id": 502,
"name": "Requirements Documentation",
"note": null,
"position": 2,
"item_type": "task",
"status": "completed",
"allow_time_tracking": "allowed",
"active": true,
"visible": true,
"currency": "AUD",
"due_date": null,
"start_date": null,
"estimated_start_date": null,
"completed_date": "2025-10-20T16:00:00Z",
"budget_type": "hourly",
"original_quantity_unit": "hour",
"original_rate": 125.00,
"original_duration": 20.0,
"original_total": 2500.00,
"variation_duration": 0.0,
"variation_total": 0.0,
"actual_duration": 18.0,
"actual_total": 2250.00,
"budget": 2500.00,
"total": 2500.00,
"remaining": 250.00,
"budget_used_percentage": 90.0,
"tracked_times_count": 3,
"costs_count": 0,
"booked_bookings_count": 0,
"resource_type": {
"id": 9,
"name": "Business Analyst"
}
}
]
},
{
"id": 51,
"name": "Implementation Phase",
"description": "CRM configuration and data migration",
"position": 2,
"status": "not_started",
"billing_type": "fixed_fee",
"allow_time_tracking": "allowed",
"percentage_complete": 0,
"currency": "AUD",
"start_date": null,
"end_date": null,
"duration": 200.0,
"budget": 180000.00,
"invoiced_amount": 0.00,
"total_cost": 0.00,
"budget_invoiced_percent": 0.0,
"plan_only": false,
"purchase_number": null,
"claim_items_count": 0,
"tasks": [
{
"id": 503,
"name": "System Configuration",
"note": "Configure Salesforce to requirements",
"position": 1,
"item_type": "task",
"status": "not_started",
"allow_time_tracking": "allowed",
"active": true,
"visible": true,
"currency": "AUD",
"due_date": null,
"start_date": null,
"estimated_start_date": null,
"completed_date": null,
"budget_type": "hourly",
"original_quantity_unit": "hour",
"original_rate": 150.00,
"original_duration": 80.0,
"original_total": 12000.00,
"variation_duration": 0.0,
"variation_total": 0.0,
"actual_duration": 0.0,
"actual_total": 0.0,
"budget": 12000.00,
"total": 12000.00,
"remaining": 12000.00,
"budget_used_percentage": 0.0,
"tracked_times_count": 0,
"costs_count": 0,
"booked_bookings_count": 0,
"resource_type": {
"id": 10,
"name": "Salesforce Developer"
}
}
]
}
]
}Error Responses
The Opportunities API uses standard HTTP response codes to indicate success or failure.
HTTP Status Codes
Status Code | Description |
200 | Success - The request was successful. |
401 | Unauthorised - Missing, invalid, or expired API token. |
403 | Forbidden - The authenticated user lacks the required API permissions (api_read, api_create, api_update, or api_delete). |
404 | Not Found - The requested account or opportunity does not exist, the authenticated user does not have access, or the ID refers to a won project (not an opportunity). |
Error Response Format
Error responses include a standard structure with details about what went wrong:
{
"error": "Forbidden"
}Common Error Scenarios
401 Unauthorised
Occurs when:
No
Authorisationheader is providedThe API token is invalid or malformed
The API token has expired
Solution: Verify your API token is valid and properly included in the Authorisation header.
403 Forbidden
Occurs when:
The authenticated user's role lacks the required API permissions
The account user has been archived or deactivated
Solution: Contact your account administrator to verify your API permissions. Admin users automatically have all API permissions.
404 Not Found
Occurs when:
The specified account ID doesn't exist or you don't have access
The specified opportunity ID doesn't exist within the account
The ID refers to a won project (use the Projects API instead)
The opportunity exists but belongs to a different account
Solution: Verify the account_id and opportunity id are correct and that you have access to the account. If you receive a 404 when you know the ID exists, check if it's a won project (project_type: "project") rather than an opportunity.
Rate Limiting
Currently, rate limiting is not enforced on API requests. However, infrastructure is in place for future rate limiting:
General API: 300 requests per 5 minutes per IP address
Per endpoint throttling may be introduced as needed
We recommend implementing exponential backoff in your API client to handle potential future rate limits gracefully.
API Permissions
The Opportunities API requires multiple levels of permissions:
Base API Permissions
Required based on HTTP method:
Method | Required Permission |
GET |
|
POST |
|
PUT/PATCH |
|
DELETE |
|
Opportunity Visibility Permissions
In addition to api_read, users need one of the following permissions to view opportunities:
Permission | Description |
| Access all opportunities in the account |
| Access opportunities assigned to team members |
| Access only opportunities where user is directly assigned |
Note: Opportunities use the OpportunityPolicy which is separate from the ProjectPolicy. The permission names may vary slightly between projects and opportunities based on your account's configuration.
Financial Data Permissions
Financial data visibility is controlled by additional permissions:
Permission | Data Included |
| Basic financial data: |
| Profitability metrics: |
Note: Without these permissions, financial fields will be completely excluded from API responses. This ensures sensitive financial data is only visible to authorised users.
Permission Hierarchy
Account administrators automatically have all API permissions
Other users must be granted permissions through their account role configuration
Financial permissions are additive:
view_gross_profitrequiresview_project_metricsto be useful
Notes
Opportunities vs Projects: This endpoint returns only opportunities (sales pipeline, project_type: "opportunity"). Won projects (project_type: "project") are accessed through the Projects API.
Client Restrictions: Opportunities can only be associated with Company clients, not BusinessOverhead. This is enforced at the model level.
Sales Statuses: Opportunities use sales-specific project statuses (won, lost, proposal in progress, etc.) which are separate from project statuses.
Auto-Dated Fields:
deal_won_dateanddeal_lost_dateare automatically set when the opportunity status changes to a "won" or "lost" status type.Multitenancy: All opportunities are scoped to accounts. Users can only access opportunities from accounts they belong to.
Authorization: The API enforces permission-based access using
OpportunityPolicy. Users are restricted to opportunities they have permission to view based on their role configuration.Soft Deletes: Deleted opportunities are soft-deleted (archived) rather than permanently removed. Archived opportunities are not returned by the API.
Money Format: All monetary amounts are returned in decimal format (e.g., 250000.00 for $250,000). The
currencyfield indicates the currency code.Date Format: Dates are returned in ISO 8601 format (YYYY-MM-DD). Datetimes include time zone information (YYYY-MM-DDTHH:MM:SSZ).
Nested Data: The show endpoint includes nested
deliverablesandtasksarrays, ordered bypositionfield. The index endpoint excludes this nested data for performance.Permission-Gated Fields: Financial and profitability data are conditionally included based on user permissions. API clients should handle missing fields gracefully.
Eager Loading: The API uses efficient eager loading to minimize database queries. Large opportunities with many deliverables/tasks may still result in substantial response payloads.
Lead Scoring: The
lead_scoreassociation helps prioritize opportunities. Lead scores are configured per account and can be customized.Assigned Users: Unlike projects which use role-based assignments, opportunities use a simpler assignment model where users are directly assigned to opportunities without specific roles.
