Create and Manage Opportunities
This tutorial demonstrates how to create and manage opportunities and opportunity groups within Bid Board Pro. The steps include creating an opportunity, updating the opportunity, creating an opportunity group, and creating a new child opportunity.
If you aren’t already familiar with the BuildingConnected data model, see the BuildingConnected API Field Guide.
Opportunity Types
BuildingConnected has two types of opportunities: domestic and foreign. Domestic opportunities are created from invites published by BuildingConnected. Foreign opportunities aren’t linked to an invite and have been created manually using email ingestion, manual entry, API, etc.
The opportunities endpoint lists both domestic and foreign opportunities. The source
field indicates whether an opportunity is domestic or foreign. Domestic opportunities have a source
value of BUILDINGCONNECTED
and foreign opportunities have any other source
value. For example, an opportunity created using the BuildingConnected API has a source
value of API
; it’s a foreign opportunity.
Before You Begin
- Verify that you have a BuildingConnected account.
- Verify that you have an appropriate subscription for the BuildingConnected API group you want to use:
- Users, Certification, Offices (GET endpoints) — no subscription required
- Opportunities — Bid Board Pro
- Opportunity Project Pairs — both Bid Board Pro and BuildingConnected Pro
- All others — BuildingConnected Pro
- Ensure that your BuildingConnected user is linked with an Autodesk ID. See How to connect your Autodesk ID to BuildingConnected.
- Register an app, and select the BuildingConnected API. For more information, see the Create an App tutorial.
- Acquire a 3-legged OAuth token with
data:read
anddata:write
scopes.
Step 1: Create an opportunity
To create a foreign opportunity, call POST opportunities. The only required field for foreign opportunities is name.
Request
curl -X POST -v 'https://developer.api.autodesk.com/construction/buildingconnected/v2/opportunities' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer nFRJxzCD8OOUr7hzBwbr06D76zAT' \
--data-raw '{
"name": "My Opportunity",
"number": "OPP-1234",
"client": {
"lead": {
"email": "lead@company.com"
}
}
}'
Response
{
"id": "64bff0c62e67d083fd9f8c3c",
"name": "My Opportunity",
"number": "OPP-1234",
"client": {
"company": {
"id": "64c00cb72e67d083fd9f8c3d",
"name": "Client Company"
},
"lead": {
"id": "64c00ccc2e67d083fd9f8c3e",
"email": "lead@company.com",
"firstName": "Lead",
"lastName": "Person",
"phoneNumber": "555-555-5555"
},
"office": {
"id": "64c00d282e67d083fd9f8c40",
"name": "San Francisco",
"location": {
"country": "US",
"state": "CA",
"streetName": "Market St",
"streetNumber": "1",
"suite": null,
"city": "San Francisco",
"zip": "94105",
"complete": "1 Market St, San Francisco, CA 94105, United States of America",
"coords": {
"lat": 37.7939943,
"lng": -122.3977218
},
"precisionLevel": null
}
}
},
"competitors": [],
"customTags": [],
"createdAt": "2023-06-13T20:03:08.807Z",
"updatedAt": "2023-06-13T20:03:08.807Z",
"defaultCurrency": "USD",
"source": "BUILDINGCONNECTED",
"isNdaRequired": false,
"isPublic": false,
"outcome": {
"state": "UNKNOWN",
"otherReason": null,
"updatedAt": null,
"updatedBy": "64c00e0e2e67d083fd9f8c41"
},
"requestType": "PROPOSAL",
"submissionState": "UNDECIDED",
"workflowBucket": "UNDECIDED_ACTIVE_ORPHAN",
"isParent": false,
"parentId": null,
"groupChildren": null,
"bid": null,
"members": [
{
"viewedAt": "2023-07-25T17:51:13.172Z",
"userId": "64c00e342e67d083fd9f8c42",
"type": "ASSIGNEE"
},
{
"viewedAt": null,
"userId": "64c00e3d2e67d083fd9f8c43",
"type": "FOLLOWER"
}
],
"dueAt": "2023-08-10T19:00:00.000Z",
"jobWalkAt": null,
"rfisDueAt": null,
"expectedStartAt": null,
"expectedFinishAt": null,
"invitedAt": "2023-06-13T20:08:26.912Z",
"tradeName": "Concrete",
"projectSize": null,
"projectInformation": null,
"location": {
"country": "US",
"state": "CA",
"streetName": "Market St",
"streetNumber": "1",
"suite": null,
"city": "San Francisco",
"zip": "94105",
"complete": "1 Market St, San Francisco, CA 94105, United States of America",
"coords": {
"lat": 37.7939943,
"lng": -122.3977218
},
"precisionLevel": null
},
"tradeSpecificInstructions": null,
"architect": null,
"engineer": null,
"propertyOwner": null,
"propertyTenant": null,
"declineReasons": [],
"additionalInfo": null,
"priority": "UNKNOWN",
"marketSector": "NONE",
"rom": null,
"winProbability": null,
"followUpAt": null,
"contractStartAt": null,
"contractDuration": null,
"averageCrewSize": null,
"estimatingHours": null,
"feePercentage": null,
"profitMargin": null,
"finalValue": null,
"isArchived": false,
"owningOfficeId": "64c00e7d2e67d083fd9f8c44",
"isSealedBidding": false,
"clientValues": {
"name": "Large Recreation Area",
"dueAt": "2023-07-28T19:00:00.000Z",
"jobWalkAt": null,
"rfisDueAt": null,
"expectedStartAt": null,
"expectedFinishAt": null,
"tradeName": "Concrete",
"projectSize": null,
"projectInformation": null,
"location": {
"country": "US",
"state": "CA",
"streetName": "Market St",
"streetNumber": "1",
"suite": null,
"city": "San Francisco",
"zip": "94105",
"complete": "1 Market St, San Francisco, CA 94105, United States of America",
"coords": {
"lat": 37.7939943,
"lng": -122.3977218
},
"precisionLevel": null
},
"tradeSpecificInstructions": null,
"architect": null
}
}
Step 2: Update the opportunity
Both domestic and foreign opportunities can be updated by calling PATCH opportunities/{opportunityId}.
Note that domestic opportunities (for which the value of source
is BUILDINGCONNECTED
) cannot have their clientValues
object modified, because it contains values from its original invite. The following example updates a domestic opportunity.
Request
curl -X PATCH -v 'https://developer.api.autodesk.com/construction/buildingconnected/v2/opportunities/6488cb7ca1695b330397e3ee' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer nFRJxzCD8OOUr7hzBwbr06D76zAT' \
-d '{
"name": "Large Recreation",
"number": "OPP-9999",
"dueAt": "2023-08-10T19:00:00.000Z"
}'
Response
{
"id": "64bff0c62e67d083fd9f8c3c",
"name": "Large Recreation",
"number": "OPP-9999",
"client": {
"company": {
"id": "64c00cb72e67d083fd9f8c3d",
"name": "Client Company"
},
"lead": {
"id": "64c00ccc2e67d083fd9f8c3e",
"email": "lead@company.com",
"firstName": "Lead",
"lastName": "Person",
"phoneNumber": "555-555-5555"
},
"office": {
"id": "64c00d282e67d083fd9f8c40",
"name": "San Francisco",
"location": {
"country": "US",
"state": "CA",
"streetName": "Market St",
"streetNumber": "1",
"suite": null,
"city": "San Francisco",
"zip": "94105",
"complete": "1 Market St, San Francisco, CA 94105, United States of America",
"coords": {
"lat": 37.7939943,
"lng": -122.3977218
},
"precisionLevel": null
}
}
},
"competitors": [],
"customTags": [],
"createdAt": "2023-06-13T20:03:08.807Z",
"updatedAt": "2023-07-25T17:51:13.210Z",
"defaultCurrency": "USD",
"source": "BUILDINGCONNECTED",
"isNdaRequired": false,
"isPublic": false,
"outcome": {
"state": "UNKNOWN",
"otherReason": null,
"updatedAt": null,
"updatedBy": "64c00e0e2e67d083fd9f8c41"
},
"requestType": "PROPOSAL",
"submissionState": "UNDECIDED",
"workflowBucket": "UNDECIDED_ACTIVE_ORPHAN",
"isParent": false,
"parentId": null,
"groupChildren": null,
"bid": null,
"members": [
{
"viewedAt": "2023-07-25T17:51:13.172Z",
"userId": "64c00e342e67d083fd9f8c42",
"type": "ASSIGNEE"
},
{
"viewedAt": null,
"userId": "64c00e3d2e67d083fd9f8c43",
"type": "FOLLOWER"
}
],
"dueAt": "2023-08-10T19:00:00.000Z",
"jobWalkAt": null,
"rfisDueAt": null,
"expectedStartAt": null,
"expectedFinishAt": null,
"invitedAt": "2023-06-13T20:08:26.912Z",
"tradeName": "Concrete",
"projectSize": null,
"projectInformation": null,
"location": {
"country": "US",
"state": "CA",
"streetName": "Market St",
"streetNumber": "1",
"suite": null,
"city": "San Francisco",
"zip": "94105",
"complete": "1 Market St, San Francisco, CA 94105, United States of America",
"coords": {
"lat": 37.7939943,
"lng": -122.3977218
},
"precisionLevel": null
},
"tradeSpecificInstructions": null,
"architect": null,
"engineer": null,
"propertyOwner": null,
"propertyTenant": null,
"declineReasons": [],
"additionalInfo": null,
"priority": "UNKNOWN",
"marketSector": "NONE",
"rom": null,
"winProbability": null,
"followUpAt": null,
"contractStartAt": null,
"contractDuration": null,
"averageCrewSize": null,
"estimatingHours": null,
"feePercentage": null,
"profitMargin": null,
"finalValue": null,
"isArchived": false,
"owningOfficeId": "64c00e7d2e67d083fd9f8c44",
"isSealedBidding": false,
"clientValues": {
"name": "Large Recreation Area",
"dueAt": "2023-07-28T19:00:00.000Z",
"jobWalkAt": null,
"rfisDueAt": null,
"expectedStartAt": null,
"expectedFinishAt": null,
"tradeName": "Concrete",
"projectSize": null,
"projectInformation": null,
"location": {
"country": "US",
"state": "CA",
"streetName": "Market St",
"streetNumber": "1",
"suite": null,
"city": "San Francisco",
"zip": "94105",
"complete": "1 Market St, San Francisco, CA 94105, United States of America",
"coords": {
"lat": 37.7939943,
"lng": -122.3977218
},
"precisionLevel": null
},
"tradeSpecificInstructions": null,
"architect": null
}
}
Step 3: (Optional) Create an Opportunity Group
Multiple domestic and foreign opportunities can be grouped together for easy tracking. A group is a cluster of opportunities that are the children of a single parent opportunity.
A group parent opportunity is a foreign opportunity that acts as a container for its children and for general project information. A group parent has the following characteristics:
- Its
isParent
field is set totrue
. - It does not have a
clientValues
object. - It does not have bids.
- It does not have its own client files.
Note that group parent opportunities must be created directly (they are foreign), and cannot be converted to or from any other type of opportunity. An opportunity cannot be both a parent and a child.
A group’s child opportunities are identified by the presence of the parentId
field, which corresponds to the id
field of the group parent.
There are two options for creating a new group:
- Option A: Create the group parent without any children, and add them later.
- Option B: Add existing opportunities as children when creating the group.
Note that you can always create new child opportunities for the group as shown in Step 4. You can also add or remove existing opportunities to the group by calling PATCH opportunities/{opportunityId} to modify the group later.
Option 3A: Create the Group Parent with no Children
Request
curl -X POST -v 'https://developer.api.autodesk.com/construction/buildingconnected/v2/opportunities' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer nFRJxzCD8OOUr7hzBwbr06D76zAT' \
-d '{
"name": "Opportunity Group A",
"isParent": true
}'
Response
{
"id": "65cbc7a93fb9dd001db0f1cc",
"name": "Opportunity Group A",
"number": null,
"client": null,
"competitors": [],
"customTags": [],
"createdAt": "2024-02-13T19:48:57.247Z",
"updatedAt": "2024-02-13T19:48:57.367Z",
"defaultCurrency": null,
"source": "API",
"isNdaRequired": false,
"projectIsPublic": false,
"outcome": {
"state": "UNKNOWN",
"otherReason": null,
"updatedAt": null,
"updatedBy": null
},
"requestType": "PROPOSAL",
"submissionState": "UNDECIDED",
"workflowBucket": "UNDECIDED_ACTIVE_PARENT",
"isParent": true,
"parentId": null,
"groupChildren": [],
"bid": null,
"members": [
{
"viewedAt": null,
"userId": "62e2d09e5f849100753fb397",
"type": "FOLLOWER"
}
],
"dueAt": null,
"jobWalkAt": null,
"rfisDueAt": null,
"expectedStartAt": null,
"expectedFinishAt": null,
"invitedAt": null,
"tradeName": null,
"projectSize": null,
"projectInformation": null,
"location": {
"country": "CA",
"state": null,
"streetName": null,
"streetNumber": null,
"suite": null,
"city": null,
"zip": null,
"complete": "Canada",
"coords": {
"lat": 56.130366,
"lng": -106.346771
},
"precisionLevel": 0
},
"tradeSpecificInstructions": null,
"architect": null,
"engineer": null,
"propertyOwner": null,
"propertyTenant": null,
"declineReasons": [],
"additionalInfo": null,
"priority": "UNKNOWN",
"marketSector": "NONE",
"rom": null,
"winProbability": null,
"followUpAt": null,
"contractStartAt": null,
"contractDuration": null,
"averageCrewSize": null,
"estimatingHours": null,
"feePercentage": null,
"profitMargin": null,
"finalValue": null,
"isArchived": false,
"owningOfficeId": "62e2d137c2f0a30059ea7821",
"isSealedBidding": false,
"clientValues": null
}
Option 3B: Add Existing Opportunities to the New Group
When creating the new group parent opportunity, identify the existing opportunities to include in the group by providing their IDs with a groupChildren
list.
Request
curl -X POST -v 'https://developer.api.autodesk.com/construction/buildingconnected/v2/opportunities' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer nFRJxzCD8OOUr7hzBwbr06D76zAT' \
-d '{
"name": "Opportunity Group B",
"isParent": true,
"groupChildren": [ "65cbc84509ebe3001da80315", "65cbc85bb0f9a3002fbbe0ce", "65cbc87ad989f800266430a8" ]
}'
Response
{
"id": "65cbc8bf3fb9dd001db0f1d2",
"name": "Opportunity Group B",
"number": null,
"client": null,
"competitors": [],
"customTags": [],
"createdAt": "2024-02-13T19:53:35.217Z",
"updatedAt": "2024-02-13T19:53:35.569Z",
"defaultCurrency": null,
"source": "API",
"isNdaRequired": false,
"projectIsPublic": false,
"outcome": {
"state": "UNKNOWN",
"otherReason": null,
"updatedAt": null,
"updatedBy": null
},
"requestType": "PROPOSAL",
"submissionState": "UNDECIDED",
"workflowBucket": "UNDECIDED_ACTIVE_PARENT",
"isParent": true,
"parentId": null,
"groupChildren": [
"65cbc84509ebe3001da80315",
"65cbc85bb0f9a3002fbbe0ce",
"65cbc87ad989f800266430a8"
],
"bid": null,
"members": [
{
"viewedAt": null,
"userId": "62e2d09e5f849100753fb397",
"type": "FOLLOWER"
}
],
"dueAt": null,
"jobWalkAt": null,
"rfisDueAt": null,
"expectedStartAt": null,
"expectedFinishAt": null,
"invitedAt": null,
"tradeName": null,
"projectSize": null,
"projectInformation": null,
"location": {
"country": "CA",
"state": null,
"streetName": null,
"streetNumber": null,
"suite": null,
"city": null,
"zip": null,
"complete": "Canada",
"coords": {
"lat": 56.130366,
"lng": -106.346771
},
"precisionLevel": 0
},
"tradeSpecificInstructions": null,
"architect": null,
"engineer": null,
"propertyOwner": null,
"propertyTenant": null,
"declineReasons": [],
"additionalInfo": null,
"priority": "UNKNOWN",
"marketSector": "OTHER",
"rom": null,
"winProbability": null,
"followUpAt": null,
"contractStartAt": null,
"contractDuration": null,
"averageCrewSize": null,
"estimatingHours": null,
"feePercentage": null,
"profitMargin": null,
"finalValue": null,
"isArchived": false,
"owningOfficeId": "62e2d137c2f0a30059ea7821",
"isSealedBidding": false,
"clientValues": null
}
Step 4: (Optional) Create a New Child Opportunity in the Group
Create a new opportunity and include the parentId
field to make it a child of the specified group.
curl -X POST -v 'https://developer.api.autodesk.com/construction/buildingconnected/v2/opportunities' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer nFRJxzCD8OOUr7hzBwbr06D76zAT' \
-d '{
"name": "Child 1",
"parentId": "65cbc7a93fb9dd001db0f1cc"
}'
Response
{
"id": "65cbc7ec3fb9dd001db0f1ce",
"name": "Child 1",
"number": null,
"client": null,
"competitors": [],
"customTags": [],
"createdAt": "2024-02-13T19:50:04.174Z",
"updatedAt": "2024-02-13T19:50:04.228Z",
"defaultCurrency": null,
"source": "API",
"isNdaRequired": false,
"projectIsPublic": false,
"outcome": {
"state": "UNKNOWN",
"otherReason": null,
"updatedAt": null,
"updatedBy": null
},
"requestType": "PROPOSAL",
"submissionState": "UNDECIDED",
"workflowBucket": "UNDECIDED_ACTIVE_CHILD",
"isParent": false,
"parentId": "65cbc7a93fb9dd001db0f1cc",
"groupChildren": null,
"bid": null,
"members": [
{
"viewedAt": null,
"userId": "62e2d09e5f849100753fb397",
"type": "FOLLOWER"
}
],
"dueAt": null,
"jobWalkAt": null,
"rfisDueAt": null,
"expectedStartAt": null,
"expectedFinishAt": null,
"invitedAt": null,
"tradeName": null,
"projectSize": null,
"projectInformation": null,
"location": {
"country": "CA",
"state": null,
"streetName": null,
"streetNumber": null,
"suite": null,
"city": null,
"zip": null,
"complete": "Canada",
"coords": {
"lat": 56.130366,
"lng": -106.346771
},
"precisionLevel": 0
},
"tradeSpecificInstructions": null,
"architect": null,
"engineer": null,
"propertyOwner": null,
"propertyTenant": null,
"declineReasons": [],
"additionalInfo": null,
"priority": "UNKNOWN",
"marketSector": "NONE",
"rom": null,
"winProbability": null,
"followUpAt": null,
"contractStartAt": null,
"contractDuration": null,
"averageCrewSize": null,
"estimatingHours": null,
"feePercentage": null,
"profitMargin": null,
"finalValue": null,
"isArchived": false,
"owningOfficeId": "62e2d137c2f0a30059ea7821",
"isSealedBidding": false,
"clientValues": null
}