Opportunities
Create, maintain, close, and review customer- and supplier-side opportunities from the workflows where selling work happens.
Endpoints
| Endpoint | Use it for |
|---|---|
GET /opportunities | Find visible opportunities by text, status, relationship, owner, product, or created date. |
POST /opportunities | Create an opportunity for one existing customer or supplier. |
GET /opportunities/{id} | Read exact opportunity details, structured metadata, products, and recent activity. |
PATCH /opportunities/{id} | Update an open opportunity and move it between lead and in-progress stages. |
POST /opportunities/{id}/close | Close an in-progress opportunity as won or lost. |
PUT /opportunities/{id}/meta | Create or replace one structured detail by key. |
Reads require opportunities:read. Writes require opportunities:write. GET /me reports effectiveCapabilities.opportunities for view, create, update, close, and metadata access, plus the matching writeReadiness.opportunities checks.
Opportunity access follows the acting user's current customer, supplier, and product visibility. This keeps pipeline work aligned with the relationships each person can already use in ShelfCycle.
Find opportunities
Use GET /opportunities for focused pipeline review or to select an exact opportunity before reading or updating it.
curl "$SHELFCYCLE_API_BASE_URL/opportunities?status=LEAD,IN_PROGRESS&assignedToId=user-id&sortDirection=desc&limit=50" \
-H "Authorization: Bearer $SHELFCYCLE_API_KEY" \
-H "X-ShelfCycle-Client: Opportunity follow-up"
Supported filters include:
queryfor matching text;statusfor one or more ofLEAD,IN_PROGRESS, orCLOSED;- exact
customerId,supplierId, orproductId; assignedToIdfor one or more owners;createdFromandcreatedToISO timestamps; andsortDirectionasascordescforupdatedAtordering.
Responses include the complete visible meta.total, the page meta.limit, and a signed meta.nextCursor when more results are available. Continue with the cursor by itself so the original filters and ordering stay together.
Read exact context
After selecting an opportunity, fetch its exact detail before deciding on an update.
curl "$SHELFCYCLE_API_BASE_URL/opportunities/opportunity-id" \
-H "Authorization: Bearer $SHELFCYCLE_API_KEY"
Selected fields from one response:
{
"data": {
"type": "opportunity",
"id": "opportunity-id",
"title": "Northstar solvent program",
"description": "Qualify annual demand and delivery requirements.",
"status": "IN_PROGRESS",
"successStatus": null,
"estimatedValue": {
"value": "125000.00",
"kind": "estimate",
"currencyCode": "USD"
},
"assignedTo": { "id": "user-id", "name": "Jordan Buyer" },
"relationships": [
{
"customer": {
"id": "customer-id",
"name": "Northstar Chemical",
"pipelineStatus": "PROSPECT"
}
}
],
"products": [{ "id": "product-id", "code": "ACETONE-PAIL" }],
"meta": [
{
"key": "next_step",
"value": "Confirm annual volume",
"updatedAt": "2026-08-08T14:00:00.000Z"
}
],
"timeline": [
{ "eventType": "STATUS_CHANGED", "createdAt": "2026-08-08T13:30:00.000Z" }
],
"timelineCoverage": { "status": "complete", "limit": 100 },
"createdAt": "2026-08-08T13:00:00.000Z",
"updatedAt": "2026-08-08T14:00:00.000Z"
}
}
Estimated values are exact decimal strings with an explicit three-letter currency. An opportunity without an entered estimate returns estimatedValue: null.
Create an opportunity
Choose exactly one existing customer or supplier. Add an owner, products, description, and estimated value when they are known.
Call the same route with dryRun=true first when your workflow wants a readiness check:
curl "$SHELFCYCLE_API_BASE_URL/opportunities?dryRun=true" \
-X POST \
-H "Authorization: Bearer $SHELFCYCLE_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: crm-intake-4182:create-opportunity" \
-d '{
"title": "Northstar solvent program",
"description": "Qualify annual demand and delivery requirements.",
"customerId": "customer-id",
"estimatedValue": 125000,
"assignedToId": "user-id",
"productIds": ["product-id"]
}'
Review data.status, checks, and verification. When the response is ready, remove dryRun=true and execute with the same request body and stable Idempotency-Key.
The saved response includes the complete opportunity detail and idempotencyStatus. Reusing the same key with the same body returns the original opportunity; reusing it for a different body returns 409 idempotency_key_reused.
Update an open opportunity
Fetch the latest detail and send its updatedAt value in If-Match. PATCH accepts title, description, estimated value, owner, and a status of LEAD or IN_PROGRESS.
curl "$SHELFCYCLE_API_BASE_URL/opportunities/opportunity-id?dryRun=true" \
-X PATCH \
-H "Authorization: Bearer $SHELFCYCLE_API_KEY" \
-H "Content-Type: application/json" \
-H "If-Match: 2026-08-08T14:00:00.000Z" \
-d '{
"status": "IN_PROGRESS",
"estimatedValue": 140000,
"assignedToId": "user-id"
}'
After a ready response, execute the same request without dryRun=true. If another update landed first, 409 stale_record means fetch the detail again, rebuild from the latest values, and retry once with the new updatedAt.
Close as won or lost
Move an opportunity to IN_PROGRESS before closing it. Then record the outcome and optional closing notes.
curl "$SHELFCYCLE_API_BASE_URL/opportunities/opportunity-id/close?dryRun=true" \
-X POST \
-H "Authorization: Bearer $SHELFCYCLE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"successStatus": "WON",
"closingNotes": "Approved for the initial annual program."
}'
Execute without dryRun=true after the readiness response is ready. The returned opportunity has status: "CLOSED", successStatus: "WON" or "LOST", and a populated closedAt.
Maintain structured details
Use the metadata route to create or replace one organization-defined opportunity detail. The same key updates in place.
curl "$SHELFCYCLE_API_BASE_URL/opportunities/opportunity-id/meta" \
-X PUT \
-H "Authorization: Bearer $SHELFCYCLE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"key": "next_step",
"value": "Confirm annual volume"
}'
Add dryRun=true when the workflow wants to confirm target visibility and write readiness before saving.
Review the pipeline
Use GET /reports/pipeline-summary for complete visible counts and entered estimate totals grouped by status, owner, or customer and supplier activity.
curl "$SHELFCYCLE_API_BASE_URL/reports/pipeline-summary?groupBy=status&status=LEAD,IN_PROGRESS" \
-H "Authorization: Bearer $SHELFCYCLE_API_KEY"
The report includes opportunity counts, estimate totals and currency, missing-value counts, won and lost counts, oldest open dates, and filtered-population totals. See the Reports guide for grouping and filter details.
Create against one selected customer or supplier, fetch the latest detail before changes, and use the dedicated close route to record won or lost outcomes.