curl --request PATCH \
--url https://public-api.stora.co/2025-09/opportunities/{opportunity_id} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"site": {
"id": "site_14b419f1096013f1"
},
"line_items": [
{
"type": "unit_type",
"item": {
"id": "utype_f18fc91387cdf710"
}
},
{
"type": "protection",
"item": {
"id": "plvl_e8f3ad0a07e47566"
}
}
],
"metadata": {
"crm_id": "opportunity-123"
}
}
'import requests
url = "https://public-api.stora.co/2025-09/opportunities/{opportunity_id}"
payload = {
"site": { "id": "site_14b419f1096013f1" },
"line_items": [
{
"type": "unit_type",
"item": { "id": "utype_f18fc91387cdf710" }
},
{
"type": "protection",
"item": { "id": "plvl_e8f3ad0a07e47566" }
}
],
"metadata": { "crm_id": "opportunity-123" }
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
site: {id: 'site_14b419f1096013f1'},
line_items: [
{type: 'unit_type', item: {id: 'utype_f18fc91387cdf710'}},
{type: 'protection', item: {id: 'plvl_e8f3ad0a07e47566'}}
],
metadata: {crm_id: 'opportunity-123'}
})
};
fetch('https://public-api.stora.co/2025-09/opportunities/{opportunity_id}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://public-api.stora.co/2025-09/opportunities/{opportunity_id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'site' => [
'id' => 'site_14b419f1096013f1'
],
'line_items' => [
[
'type' => 'unit_type',
'item' => [
'id' => 'utype_f18fc91387cdf710'
]
],
[
'type' => 'protection',
'item' => [
'id' => 'plvl_e8f3ad0a07e47566'
]
]
],
'metadata' => [
'crm_id' => 'opportunity-123'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://public-api.stora.co/2025-09/opportunities/{opportunity_id}"
payload := strings.NewReader("{\n \"site\": {\n \"id\": \"site_14b419f1096013f1\"\n },\n \"line_items\": [\n {\n \"type\": \"unit_type\",\n \"item\": {\n \"id\": \"utype_f18fc91387cdf710\"\n }\n },\n {\n \"type\": \"protection\",\n \"item\": {\n \"id\": \"plvl_e8f3ad0a07e47566\"\n }\n }\n ],\n \"metadata\": {\n \"crm_id\": \"opportunity-123\"\n }\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.patch("https://public-api.stora.co/2025-09/opportunities/{opportunity_id}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"site\": {\n \"id\": \"site_14b419f1096013f1\"\n },\n \"line_items\": [\n {\n \"type\": \"unit_type\",\n \"item\": {\n \"id\": \"utype_f18fc91387cdf710\"\n }\n },\n {\n \"type\": \"protection\",\n \"item\": {\n \"id\": \"plvl_e8f3ad0a07e47566\"\n }\n }\n ],\n \"metadata\": {\n \"crm_id\": \"opportunity-123\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://public-api.stora.co/2025-09/opportunities/{opportunity_id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"site\": {\n \"id\": \"site_14b419f1096013f1\"\n },\n \"line_items\": [\n {\n \"type\": \"unit_type\",\n \"item\": {\n \"id\": \"utype_f18fc91387cdf710\"\n }\n },\n {\n \"type\": \"protection\",\n \"item\": {\n \"id\": \"plvl_e8f3ad0a07e47566\"\n }\n }\n ],\n \"metadata\": {\n \"crm_id\": \"opportunity-123\"\n }\n}"
response = http.request(request)
puts response.read_body{
"opportunity": {
"id": "opp_127b3057d5df338e",
"archived_at": null,
"associated_at": null,
"contact": {
"id": "con_1234567890abcdef"
},
"created_at": "2025-02-22T14:41:00Z",
"creator": {
"id": "con_1234567890abcdef"
},
"deal": null,
"line_items": [
{
"item": {
"id": "plvl_e8f3ad0a07e47566"
},
"quantity": 1,
"type": "protection"
},
{
"item": {
"id": "utype_f18fc91387cdf710"
},
"quantity": 1,
"type": "unit_type"
}
],
"metadata": {
"crm_id": "opportunity-123"
},
"site": {
"id": "site_14b419f1096013f1"
},
"source": "price_reveal",
"status": "open",
"updated_at": "2025-02-22T14:41:00Z"
},
"meta": {
"request_id": "01563646-58c1-4607-8fe0-cae3e92c4477",
"curies": [
{
"name": "bo",
"href": "https://app.stora.test{rel}",
"templated": true,
"title": "Backoffice"
},
{
"name": "sf",
"href": "https://acme.stora.test{rel}",
"templated": true,
"title": "Storefront"
}
]
}
}{
"error": {
"code": "resource_not_found",
"details": [],
"links": [
{
"kind": "open_api",
"name": "OpenAPI specification",
"url": "https://docs.stora.test/2025-09/openapi.json"
},
{
"kind": "documentation",
"name": "Errors",
"url": "https://docs.stora.test/2025-09/guides/errors"
}
],
"message": "The Opportunity was not found.",
"request_id": "01563646-58c1-4607-8fe0-cae3e92c4477",
"type": "invalid_request_error"
}
}{
"error": {
"code": "opportunity_associated",
"details": [],
"links": [
{
"kind": "open_api",
"name": "OpenAPI specification",
"url": "https://docs.stora.test/2025-09/openapi.json"
},
{
"kind": "documentation",
"name": "Errors",
"url": "https://docs.stora.test/2025-09/guides/errors"
}
],
"message": "The opportunity is associated with a deal. Only its metadata can be updated.",
"request_id": "01563646-58c1-4607-8fe0-cae3e92c4477",
"type": "invalid_request_error"
}
}{
"error": {
"code": "invalid_content",
"details": [
{
"message": "does not match the site of the existing line items",
"pointer": "/site/id"
}
],
"links": [
{
"kind": "open_api",
"name": "OpenAPI specification",
"url": "https://docs.stora.test/2025-09/openapi.json"
},
{
"kind": "documentation",
"name": "Errors",
"url": "https://docs.stora.test/2025-09/guides/errors"
}
],
"message": "The request body content is not valid.",
"request_id": "01563646-58c1-4607-8fe0-cae3e92c4477",
"type": "invalid_request_error"
}
}Update an Opportunity
Update an existing opportunity.
The contact cannot be changed. Once the opportunity is associated with a deal, only its metadata can be updated.
Omitting line_items leaves them unchanged, and an empty array removes them.
A unit type requires a site. Clearing or moving the site while keeping line items that belong to it is rejected.
Source, creator and lifecycle fields are read-only.
Required authorization scope: public.opportunity:write
curl --request PATCH \
--url https://public-api.stora.co/2025-09/opportunities/{opportunity_id} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"site": {
"id": "site_14b419f1096013f1"
},
"line_items": [
{
"type": "unit_type",
"item": {
"id": "utype_f18fc91387cdf710"
}
},
{
"type": "protection",
"item": {
"id": "plvl_e8f3ad0a07e47566"
}
}
],
"metadata": {
"crm_id": "opportunity-123"
}
}
'import requests
url = "https://public-api.stora.co/2025-09/opportunities/{opportunity_id}"
payload = {
"site": { "id": "site_14b419f1096013f1" },
"line_items": [
{
"type": "unit_type",
"item": { "id": "utype_f18fc91387cdf710" }
},
{
"type": "protection",
"item": { "id": "plvl_e8f3ad0a07e47566" }
}
],
"metadata": { "crm_id": "opportunity-123" }
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
site: {id: 'site_14b419f1096013f1'},
line_items: [
{type: 'unit_type', item: {id: 'utype_f18fc91387cdf710'}},
{type: 'protection', item: {id: 'plvl_e8f3ad0a07e47566'}}
],
metadata: {crm_id: 'opportunity-123'}
})
};
fetch('https://public-api.stora.co/2025-09/opportunities/{opportunity_id}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://public-api.stora.co/2025-09/opportunities/{opportunity_id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'site' => [
'id' => 'site_14b419f1096013f1'
],
'line_items' => [
[
'type' => 'unit_type',
'item' => [
'id' => 'utype_f18fc91387cdf710'
]
],
[
'type' => 'protection',
'item' => [
'id' => 'plvl_e8f3ad0a07e47566'
]
]
],
'metadata' => [
'crm_id' => 'opportunity-123'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://public-api.stora.co/2025-09/opportunities/{opportunity_id}"
payload := strings.NewReader("{\n \"site\": {\n \"id\": \"site_14b419f1096013f1\"\n },\n \"line_items\": [\n {\n \"type\": \"unit_type\",\n \"item\": {\n \"id\": \"utype_f18fc91387cdf710\"\n }\n },\n {\n \"type\": \"protection\",\n \"item\": {\n \"id\": \"plvl_e8f3ad0a07e47566\"\n }\n }\n ],\n \"metadata\": {\n \"crm_id\": \"opportunity-123\"\n }\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.patch("https://public-api.stora.co/2025-09/opportunities/{opportunity_id}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"site\": {\n \"id\": \"site_14b419f1096013f1\"\n },\n \"line_items\": [\n {\n \"type\": \"unit_type\",\n \"item\": {\n \"id\": \"utype_f18fc91387cdf710\"\n }\n },\n {\n \"type\": \"protection\",\n \"item\": {\n \"id\": \"plvl_e8f3ad0a07e47566\"\n }\n }\n ],\n \"metadata\": {\n \"crm_id\": \"opportunity-123\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://public-api.stora.co/2025-09/opportunities/{opportunity_id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"site\": {\n \"id\": \"site_14b419f1096013f1\"\n },\n \"line_items\": [\n {\n \"type\": \"unit_type\",\n \"item\": {\n \"id\": \"utype_f18fc91387cdf710\"\n }\n },\n {\n \"type\": \"protection\",\n \"item\": {\n \"id\": \"plvl_e8f3ad0a07e47566\"\n }\n }\n ],\n \"metadata\": {\n \"crm_id\": \"opportunity-123\"\n }\n}"
response = http.request(request)
puts response.read_body{
"opportunity": {
"id": "opp_127b3057d5df338e",
"archived_at": null,
"associated_at": null,
"contact": {
"id": "con_1234567890abcdef"
},
"created_at": "2025-02-22T14:41:00Z",
"creator": {
"id": "con_1234567890abcdef"
},
"deal": null,
"line_items": [
{
"item": {
"id": "plvl_e8f3ad0a07e47566"
},
"quantity": 1,
"type": "protection"
},
{
"item": {
"id": "utype_f18fc91387cdf710"
},
"quantity": 1,
"type": "unit_type"
}
],
"metadata": {
"crm_id": "opportunity-123"
},
"site": {
"id": "site_14b419f1096013f1"
},
"source": "price_reveal",
"status": "open",
"updated_at": "2025-02-22T14:41:00Z"
},
"meta": {
"request_id": "01563646-58c1-4607-8fe0-cae3e92c4477",
"curies": [
{
"name": "bo",
"href": "https://app.stora.test{rel}",
"templated": true,
"title": "Backoffice"
},
{
"name": "sf",
"href": "https://acme.stora.test{rel}",
"templated": true,
"title": "Storefront"
}
]
}
}{
"error": {
"code": "resource_not_found",
"details": [],
"links": [
{
"kind": "open_api",
"name": "OpenAPI specification",
"url": "https://docs.stora.test/2025-09/openapi.json"
},
{
"kind": "documentation",
"name": "Errors",
"url": "https://docs.stora.test/2025-09/guides/errors"
}
],
"message": "The Opportunity was not found.",
"request_id": "01563646-58c1-4607-8fe0-cae3e92c4477",
"type": "invalid_request_error"
}
}{
"error": {
"code": "opportunity_associated",
"details": [],
"links": [
{
"kind": "open_api",
"name": "OpenAPI specification",
"url": "https://docs.stora.test/2025-09/openapi.json"
},
{
"kind": "documentation",
"name": "Errors",
"url": "https://docs.stora.test/2025-09/guides/errors"
}
],
"message": "The opportunity is associated with a deal. Only its metadata can be updated.",
"request_id": "01563646-58c1-4607-8fe0-cae3e92c4477",
"type": "invalid_request_error"
}
}{
"error": {
"code": "invalid_content",
"details": [
{
"message": "does not match the site of the existing line items",
"pointer": "/site/id"
}
],
"links": [
{
"kind": "open_api",
"name": "OpenAPI specification",
"url": "https://docs.stora.test/2025-09/openapi.json"
},
{
"kind": "documentation",
"name": "Errors",
"url": "https://docs.stora.test/2025-09/guides/errors"
}
],
"message": "The request body content is not valid.",
"request_id": "01563646-58c1-4607-8fe0-cae3e92c4477",
"type": "invalid_request_error"
}
}Authorizations
Bearer Token necessary to use API
Path Parameters
The ID of the opportunity to retrieve
Query Parameters
This endpoint supports expandable responses. For more, see the documentation page.
Body
Update Opportunity Request
The site associated with the opportunity. To remove the association, set site to null.
Show child attributes
Show child attributes
Set of key-value pairs for storing additional information on the opportunity. Learn more about metadata.
Show child attributes
Show child attributes
Skip this property (do not include it inside the request) if you don't want to update the line items. Existing line items not included here in the update request will be removed. To remove all line items, provide an empty array. At most one item per type is allowed.
2Deal Unit Type Line Item
- Option 1
- Option 2
Show child attributes
Show child attributes
Was this page helpful?