diff --git a/.generated-info b/.generated-info
index 9dd05ea93f..96df2ceea3 100644
--- a/.generated-info
+++ b/.generated-info
@@ -1,4 +1,4 @@
{
- "spec_repo_commit": "62a19e4",
- "generated": "2025-08-27 15:01:27.781"
+ "spec_repo_commit": "6d9663b",
+ "generated": "2025-08-27 16:38:12.845"
}
diff --git a/.generator/schemas/v2/openapi.yaml b/.generator/schemas/v2/openapi.yaml
index e09c948047..19e228a115 100644
--- a/.generator/schemas/v2/openapi.yaml
+++ b/.generator/schemas/v2/openapi.yaml
@@ -14485,6 +14485,10 @@ components:
description: Entity definition in raw JSON or YAML representation.
example: "apiVersion: v3\nkind: service\nmetadata:\n name: myservice\n"
type: string
+ EntityReference:
+ description: The unique reference for an IDP entity.
+ example: service:my-service
+ type: string
EntityRelationships:
description: Entity relationships.
properties:
@@ -34444,6 +34448,8 @@ components:
description: If enabled, the rule is calculated as part of the score.
example: true
type: boolean
+ level:
+ $ref: '#/components/schemas/RuleLevel'
modified_at:
description: Time of the last rule outcome modification.
format: date-time
@@ -34464,6 +34470,13 @@ components:
description: The unique ID for a scorecard rule.
example: q8MQxk8TCqrHnWkx
type: string
+ RuleLevel:
+ description: The maturity level of the rule (1, 2, or 3).
+ example: 2
+ format: int32
+ maximum: 3
+ minimum: 1
+ type: integer
RuleName:
description: Name of the notification rule.
example: Rule 1
@@ -43835,6 +43848,57 @@ components:
id:
$ref: '#/components/schemas/ApiID'
type: object
+ UpdateOutcomesAsyncAttributes:
+ description: The JSON:API attributes for a batched set of scorecard outcomes.
+ properties:
+ results:
+ description: Set of scorecard outcomes to update asynchronously.
+ items:
+ $ref: '#/components/schemas/UpdateOutcomesAsyncRequestItem'
+ type: array
+ type: object
+ UpdateOutcomesAsyncRequest:
+ description: Scorecard outcomes batch request.
+ properties:
+ data:
+ $ref: '#/components/schemas/UpdateOutcomesAsyncRequestData'
+ type: object
+ UpdateOutcomesAsyncRequestData:
+ description: Scorecard outcomes batch request data.
+ properties:
+ attributes:
+ $ref: '#/components/schemas/UpdateOutcomesAsyncAttributes'
+ type:
+ $ref: '#/components/schemas/UpdateOutcomesAsyncType'
+ type: object
+ UpdateOutcomesAsyncRequestItem:
+ description: Scorecard outcome for a single entity and rule.
+ properties:
+ entity_reference:
+ $ref: '#/components/schemas/EntityReference'
+ remarks:
+ description: Any remarks regarding the scorecard rule's evaluation. Supports
+ HTML hyperlinks.
+ example: 'See: Services'
+ type: string
+ rule_id:
+ $ref: '#/components/schemas/RuleId'
+ state:
+ $ref: '#/components/schemas/State'
+ required:
+ - rule_id
+ - entity_reference
+ - state
+ type: object
+ UpdateOutcomesAsyncType:
+ default: batched-outcome
+ description: The JSON:API type for scorecard outcomes.
+ enum:
+ - batched-outcome
+ example: batched-outcome
+ type: string
+ x-enum-varnames:
+ - BATCHED_OUTCOME
UpdateResourceEvaluationFiltersRequest:
description: Request object to update a resource filter.
properties:
@@ -61882,6 +61946,39 @@ paths:
resultsPath: data
x-unstable: '**Note**: This endpoint is in public beta.
+ If you have any feedback, contact [Datadog support](https://docs.datadoghq.com/help/).'
+ post:
+ description: Updates multiple scorecard rule outcomes in a single batched request.
+ operationId: UpdateScorecardOutcomesAsync
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/UpdateOutcomesAsyncRequest'
+ description: Set of scorecard outcomes.
+ required: true
+ responses:
+ '202':
+ description: Accepted
+ '400':
+ $ref: '#/components/responses/BadRequestResponse'
+ '403':
+ $ref: '#/components/responses/ForbiddenResponse'
+ '409':
+ $ref: '#/components/responses/ConflictResponse'
+ '429':
+ $ref: '#/components/responses/TooManyRequestsResponse'
+ security:
+ - apiKeyAuth: []
+ appKeyAuth: []
+ - AuthZ:
+ - apm_service_catalog_write
+ summary: Update Scorecard outcomes asynchronously
+ tags:
+ - Service Scorecards
+ x-codegen-request-body-name: body
+ x-unstable: '**Note**: This endpoint is in public beta.
+
If you have any feedback, contact [Datadog support](https://docs.datadoghq.com/help/).'
/api/v2/scorecard/outcomes/batch:
post:
diff --git a/docs/datadog_api_client.v2.model.rst b/docs/datadog_api_client.v2.model.rst
index 2f8c1b79c8..5d21e8bf53 100644
--- a/docs/datadog_api_client.v2.model.rst
+++ b/docs/datadog_api_client.v2.model.rst
@@ -19527,6 +19527,41 @@ datadog\_api\_client.v2.model.update\_open\_api\_response\_data module
:members:
:show-inheritance:
+datadog\_api\_client.v2.model.update\_outcomes\_async\_attributes module
+------------------------------------------------------------------------
+
+.. automodule:: datadog_api_client.v2.model.update_outcomes_async_attributes
+ :members:
+ :show-inheritance:
+
+datadog\_api\_client.v2.model.update\_outcomes\_async\_request module
+---------------------------------------------------------------------
+
+.. automodule:: datadog_api_client.v2.model.update_outcomes_async_request
+ :members:
+ :show-inheritance:
+
+datadog\_api\_client.v2.model.update\_outcomes\_async\_request\_data module
+---------------------------------------------------------------------------
+
+.. automodule:: datadog_api_client.v2.model.update_outcomes_async_request_data
+ :members:
+ :show-inheritance:
+
+datadog\_api\_client.v2.model.update\_outcomes\_async\_request\_item module
+---------------------------------------------------------------------------
+
+.. automodule:: datadog_api_client.v2.model.update_outcomes_async_request_item
+ :members:
+ :show-inheritance:
+
+datadog\_api\_client.v2.model.update\_outcomes\_async\_type module
+------------------------------------------------------------------
+
+.. automodule:: datadog_api_client.v2.model.update_outcomes_async_type
+ :members:
+ :show-inheritance:
+
datadog\_api\_client.v2.model.update\_resource\_evaluation\_filters\_request module
-----------------------------------------------------------------------------------
diff --git a/examples/v2/service-scorecards/UpdateScorecardOutcomesAsync.py b/examples/v2/service-scorecards/UpdateScorecardOutcomesAsync.py
new file mode 100644
index 0000000000..edee85101e
--- /dev/null
+++ b/examples/v2/service-scorecards/UpdateScorecardOutcomesAsync.py
@@ -0,0 +1,38 @@
+"""
+Update Scorecard outcomes asynchronously returns "Accepted" response
+"""
+
+from os import environ
+from datadog_api_client import ApiClient, Configuration
+from datadog_api_client.v2.api.service_scorecards_api import ServiceScorecardsApi
+from datadog_api_client.v2.model.state import State
+from datadog_api_client.v2.model.update_outcomes_async_attributes import UpdateOutcomesAsyncAttributes
+from datadog_api_client.v2.model.update_outcomes_async_request import UpdateOutcomesAsyncRequest
+from datadog_api_client.v2.model.update_outcomes_async_request_data import UpdateOutcomesAsyncRequestData
+from datadog_api_client.v2.model.update_outcomes_async_request_item import UpdateOutcomesAsyncRequestItem
+from datadog_api_client.v2.model.update_outcomes_async_type import UpdateOutcomesAsyncType
+
+# there is a valid "create_scorecard_rule" in the system
+CREATE_SCORECARD_RULE_DATA_ID = environ["CREATE_SCORECARD_RULE_DATA_ID"]
+
+body = UpdateOutcomesAsyncRequest(
+ data=UpdateOutcomesAsyncRequestData(
+ attributes=UpdateOutcomesAsyncAttributes(
+ results=[
+ UpdateOutcomesAsyncRequestItem(
+ rule_id=CREATE_SCORECARD_RULE_DATA_ID,
+ entity_reference="service:my-service",
+ remarks='See: Services',
+ state=State.PASS,
+ ),
+ ],
+ ),
+ type=UpdateOutcomesAsyncType.BATCHED_OUTCOME,
+ ),
+)
+
+configuration = Configuration()
+configuration.unstable_operations["update_scorecard_outcomes_async"] = True
+with ApiClient(configuration) as api_client:
+ api_instance = ServiceScorecardsApi(api_client)
+ api_instance.update_scorecard_outcomes_async(body=body)
diff --git a/src/datadog_api_client/configuration.py b/src/datadog_api_client/configuration.py
index db01c60e2b..06f44f0d23 100644
--- a/src/datadog_api_client/configuration.py
+++ b/src/datadog_api_client/configuration.py
@@ -312,6 +312,7 @@ def __init__(
"v2.delete_scorecard_rule": False,
"v2.list_scorecard_outcomes": False,
"v2.list_scorecard_rules": False,
+ "v2.update_scorecard_outcomes_async": False,
"v2.update_scorecard_rule": False,
"v2.create_incident_service": False,
"v2.delete_incident_service": False,
diff --git a/src/datadog_api_client/v2/api/service_scorecards_api.py b/src/datadog_api_client/v2/api/service_scorecards_api.py
index 63cd7157ec..17f1b0de83 100644
--- a/src/datadog_api_client/v2/api/service_scorecards_api.py
+++ b/src/datadog_api_client/v2/api/service_scorecards_api.py
@@ -16,6 +16,7 @@
)
from datadog_api_client.v2.model.outcomes_response import OutcomesResponse
from datadog_api_client.v2.model.outcomes_response_data_item import OutcomesResponseDataItem
+from datadog_api_client.v2.model.update_outcomes_async_request import UpdateOutcomesAsyncRequest
from datadog_api_client.v2.model.outcomes_batch_response import OutcomesBatchResponse
from datadog_api_client.v2.model.outcomes_batch_request import OutcomesBatchRequest
from datadog_api_client.v2.model.list_rules_response import ListRulesResponse
@@ -235,6 +236,26 @@ def __init__(self, api_client=None):
api_client=api_client,
)
+ self._update_scorecard_outcomes_async_endpoint = _Endpoint(
+ settings={
+ "response_type": None,
+ "auth": ["apiKeyAuth", "appKeyAuth", "AuthZ"],
+ "endpoint_path": "/api/v2/scorecard/outcomes",
+ "operation_id": "update_scorecard_outcomes_async",
+ "http_method": "POST",
+ "version": "v2",
+ },
+ params_map={
+ "body": {
+ "required": True,
+ "openapi_types": (UpdateOutcomesAsyncRequest,),
+ "location": "body",
+ },
+ },
+ headers_map={"accept": ["*/*"], "content_type": ["application/json"]},
+ api_client=api_client,
+ )
+
self._update_scorecard_rule_endpoint = _Endpoint(
settings={
"response_type": (UpdateRuleResponse,),
@@ -628,6 +649,23 @@ def list_scorecard_rules_with_pagination(
}
return endpoint.call_with_http_info_paginated(pagination)
+ def update_scorecard_outcomes_async(
+ self,
+ body: UpdateOutcomesAsyncRequest,
+ ) -> None:
+ """Update Scorecard outcomes asynchronously.
+
+ Updates multiple scorecard rule outcomes in a single batched request.
+
+ :param body: Set of scorecard outcomes.
+ :type body: UpdateOutcomesAsyncRequest
+ :rtype: None
+ """
+ kwargs: Dict[str, Any] = {}
+ kwargs["body"] = body
+
+ return self._update_scorecard_outcomes_async_endpoint.call_with_http_info(**kwargs)
+
def update_scorecard_rule(
self,
rule_id: str,
diff --git a/src/datadog_api_client/v2/model/rule_attributes.py b/src/datadog_api_client/v2/model/rule_attributes.py
index 3156d9a7bf..25ad024b5e 100644
--- a/src/datadog_api_client/v2/model/rule_attributes.py
+++ b/src/datadog_api_client/v2/model/rule_attributes.py
@@ -15,6 +15,13 @@
class RuleAttributes(ModelNormal):
+ validations = {
+ "level": {
+ "inclusive_maximum": 3,
+ "inclusive_minimum": 1,
+ },
+ }
+
@cached_property
def openapi_types(_):
return {
@@ -23,6 +30,7 @@ def openapi_types(_):
"custom": (bool,),
"description": (str,),
"enabled": (bool,),
+ "level": (int,),
"modified_at": (datetime,),
"name": (str,),
"owner": (str,),
@@ -35,6 +43,7 @@ def openapi_types(_):
"custom": "custom",
"description": "description",
"enabled": "enabled",
+ "level": "level",
"modified_at": "modified_at",
"name": "name",
"owner": "owner",
@@ -48,6 +57,7 @@ def __init__(
custom: Union[bool, UnsetType] = unset,
description: Union[str, UnsetType] = unset,
enabled: Union[bool, UnsetType] = unset,
+ level: Union[int, UnsetType] = unset,
modified_at: Union[datetime, UnsetType] = unset,
name: Union[str, UnsetType] = unset,
owner: Union[str, UnsetType] = unset,
@@ -72,6 +82,9 @@ def __init__(
:param enabled: If enabled, the rule is calculated as part of the score.
:type enabled: bool, optional
+ :param level: The maturity level of the rule (1, 2, or 3).
+ :type level: int, optional
+
:param modified_at: Time of the last rule outcome modification.
:type modified_at: datetime, optional
@@ -94,6 +107,8 @@ def __init__(
kwargs["description"] = description
if enabled is not unset:
kwargs["enabled"] = enabled
+ if level is not unset:
+ kwargs["level"] = level
if modified_at is not unset:
kwargs["modified_at"] = modified_at
if name is not unset:
diff --git a/src/datadog_api_client/v2/model/update_outcomes_async_attributes.py b/src/datadog_api_client/v2/model/update_outcomes_async_attributes.py
new file mode 100644
index 0000000000..32ccccee28
--- /dev/null
+++ b/src/datadog_api_client/v2/model/update_outcomes_async_attributes.py
@@ -0,0 +1,42 @@
+# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License.
+# This product includes software developed at Datadog (https://www.datadoghq.com/).
+# Copyright 2019-Present Datadog, Inc.
+from __future__ import annotations
+
+from typing import List, Union, TYPE_CHECKING
+
+from datadog_api_client.model_utils import (
+ ModelNormal,
+ cached_property,
+ unset,
+ UnsetType,
+)
+
+
+if TYPE_CHECKING:
+ from datadog_api_client.v2.model.update_outcomes_async_request_item import UpdateOutcomesAsyncRequestItem
+
+
+class UpdateOutcomesAsyncAttributes(ModelNormal):
+ @cached_property
+ def openapi_types(_):
+ from datadog_api_client.v2.model.update_outcomes_async_request_item import UpdateOutcomesAsyncRequestItem
+
+ return {
+ "results": ([UpdateOutcomesAsyncRequestItem],),
+ }
+
+ attribute_map = {
+ "results": "results",
+ }
+
+ def __init__(self_, results: Union[List[UpdateOutcomesAsyncRequestItem], UnsetType] = unset, **kwargs):
+ """
+ The JSON:API attributes for a batched set of scorecard outcomes.
+
+ :param results: Set of scorecard outcomes to update asynchronously.
+ :type results: [UpdateOutcomesAsyncRequestItem], optional
+ """
+ if results is not unset:
+ kwargs["results"] = results
+ super().__init__(kwargs)
diff --git a/src/datadog_api_client/v2/model/update_outcomes_async_request.py b/src/datadog_api_client/v2/model/update_outcomes_async_request.py
new file mode 100644
index 0000000000..72a6b65e27
--- /dev/null
+++ b/src/datadog_api_client/v2/model/update_outcomes_async_request.py
@@ -0,0 +1,42 @@
+# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License.
+# This product includes software developed at Datadog (https://www.datadoghq.com/).
+# Copyright 2019-Present Datadog, Inc.
+from __future__ import annotations
+
+from typing import Union, TYPE_CHECKING
+
+from datadog_api_client.model_utils import (
+ ModelNormal,
+ cached_property,
+ unset,
+ UnsetType,
+)
+
+
+if TYPE_CHECKING:
+ from datadog_api_client.v2.model.update_outcomes_async_request_data import UpdateOutcomesAsyncRequestData
+
+
+class UpdateOutcomesAsyncRequest(ModelNormal):
+ @cached_property
+ def openapi_types(_):
+ from datadog_api_client.v2.model.update_outcomes_async_request_data import UpdateOutcomesAsyncRequestData
+
+ return {
+ "data": (UpdateOutcomesAsyncRequestData,),
+ }
+
+ attribute_map = {
+ "data": "data",
+ }
+
+ def __init__(self_, data: Union[UpdateOutcomesAsyncRequestData, UnsetType] = unset, **kwargs):
+ """
+ Scorecard outcomes batch request.
+
+ :param data: Scorecard outcomes batch request data.
+ :type data: UpdateOutcomesAsyncRequestData, optional
+ """
+ if data is not unset:
+ kwargs["data"] = data
+ super().__init__(kwargs)
diff --git a/src/datadog_api_client/v2/model/update_outcomes_async_request_data.py b/src/datadog_api_client/v2/model/update_outcomes_async_request_data.py
new file mode 100644
index 0000000000..f1e183d42f
--- /dev/null
+++ b/src/datadog_api_client/v2/model/update_outcomes_async_request_data.py
@@ -0,0 +1,56 @@
+# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License.
+# This product includes software developed at Datadog (https://www.datadoghq.com/).
+# Copyright 2019-Present Datadog, Inc.
+from __future__ import annotations
+
+from typing import Union, TYPE_CHECKING
+
+from datadog_api_client.model_utils import (
+ ModelNormal,
+ cached_property,
+ unset,
+ UnsetType,
+)
+
+
+if TYPE_CHECKING:
+ from datadog_api_client.v2.model.update_outcomes_async_attributes import UpdateOutcomesAsyncAttributes
+ from datadog_api_client.v2.model.update_outcomes_async_type import UpdateOutcomesAsyncType
+
+
+class UpdateOutcomesAsyncRequestData(ModelNormal):
+ @cached_property
+ def openapi_types(_):
+ from datadog_api_client.v2.model.update_outcomes_async_attributes import UpdateOutcomesAsyncAttributes
+ from datadog_api_client.v2.model.update_outcomes_async_type import UpdateOutcomesAsyncType
+
+ return {
+ "attributes": (UpdateOutcomesAsyncAttributes,),
+ "type": (UpdateOutcomesAsyncType,),
+ }
+
+ attribute_map = {
+ "attributes": "attributes",
+ "type": "type",
+ }
+
+ def __init__(
+ self_,
+ attributes: Union[UpdateOutcomesAsyncAttributes, UnsetType] = unset,
+ type: Union[UpdateOutcomesAsyncType, UnsetType] = unset,
+ **kwargs,
+ ):
+ """
+ Scorecard outcomes batch request data.
+
+ :param attributes: The JSON:API attributes for a batched set of scorecard outcomes.
+ :type attributes: UpdateOutcomesAsyncAttributes, optional
+
+ :param type: The JSON:API type for scorecard outcomes.
+ :type type: UpdateOutcomesAsyncType, optional
+ """
+ if attributes is not unset:
+ kwargs["attributes"] = attributes
+ if type is not unset:
+ kwargs["type"] = type
+ super().__init__(kwargs)
diff --git a/src/datadog_api_client/v2/model/update_outcomes_async_request_item.py b/src/datadog_api_client/v2/model/update_outcomes_async_request_item.py
new file mode 100644
index 0000000000..f24511d62e
--- /dev/null
+++ b/src/datadog_api_client/v2/model/update_outcomes_async_request_item.py
@@ -0,0 +1,63 @@
+# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License.
+# This product includes software developed at Datadog (https://www.datadoghq.com/).
+# Copyright 2019-Present Datadog, Inc.
+from __future__ import annotations
+
+from typing import Union, TYPE_CHECKING
+
+from datadog_api_client.model_utils import (
+ ModelNormal,
+ cached_property,
+ unset,
+ UnsetType,
+)
+
+
+if TYPE_CHECKING:
+ from datadog_api_client.v2.model.state import State
+
+
+class UpdateOutcomesAsyncRequestItem(ModelNormal):
+ @cached_property
+ def openapi_types(_):
+ from datadog_api_client.v2.model.state import State
+
+ return {
+ "entity_reference": (str,),
+ "remarks": (str,),
+ "rule_id": (str,),
+ "state": (State,),
+ }
+
+ attribute_map = {
+ "entity_reference": "entity_reference",
+ "remarks": "remarks",
+ "rule_id": "rule_id",
+ "state": "state",
+ }
+
+ def __init__(
+ self_, entity_reference: str, rule_id: str, state: State, remarks: Union[str, UnsetType] = unset, **kwargs
+ ):
+ """
+ Scorecard outcome for a single entity and rule.
+
+ :param entity_reference: The unique reference for an IDP entity.
+ :type entity_reference: str
+
+ :param remarks: Any remarks regarding the scorecard rule's evaluation. Supports HTML hyperlinks.
+ :type remarks: str, optional
+
+ :param rule_id: The unique ID for a scorecard rule.
+ :type rule_id: str
+
+ :param state: The state of the rule evaluation.
+ :type state: State
+ """
+ if remarks is not unset:
+ kwargs["remarks"] = remarks
+ super().__init__(kwargs)
+
+ self_.entity_reference = entity_reference
+ self_.rule_id = rule_id
+ self_.state = state
diff --git a/src/datadog_api_client/v2/model/update_outcomes_async_type.py b/src/datadog_api_client/v2/model/update_outcomes_async_type.py
new file mode 100644
index 0000000000..ce7c4bf5cc
--- /dev/null
+++ b/src/datadog_api_client/v2/model/update_outcomes_async_type.py
@@ -0,0 +1,35 @@
+# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License.
+# This product includes software developed at Datadog (https://www.datadoghq.com/).
+# Copyright 2019-Present Datadog, Inc.
+from __future__ import annotations
+
+
+from datadog_api_client.model_utils import (
+ ModelSimple,
+ cached_property,
+)
+
+from typing import ClassVar
+
+
+class UpdateOutcomesAsyncType(ModelSimple):
+ """
+ The JSON:API type for scorecard outcomes.
+
+ :param value: If omitted defaults to "batched-outcome". Must be one of ["batched-outcome"].
+ :type value: str
+ """
+
+ allowed_values = {
+ "batched-outcome",
+ }
+ BATCHED_OUTCOME: ClassVar["UpdateOutcomesAsyncType"]
+
+ @cached_property
+ def openapi_types(_):
+ return {
+ "value": (str,),
+ }
+
+
+UpdateOutcomesAsyncType.BATCHED_OUTCOME = UpdateOutcomesAsyncType("batched-outcome")
diff --git a/src/datadog_api_client/v2/models/__init__.py b/src/datadog_api_client/v2/models/__init__.py
index a370727c3b..17bb49b9ef 100644
--- a/src/datadog_api_client/v2/models/__init__.py
+++ b/src/datadog_api_client/v2/models/__init__.py
@@ -3802,6 +3802,11 @@
from datadog_api_client.v2.model.update_open_api_response import UpdateOpenAPIResponse
from datadog_api_client.v2.model.update_open_api_response_attributes import UpdateOpenAPIResponseAttributes
from datadog_api_client.v2.model.update_open_api_response_data import UpdateOpenAPIResponseData
+from datadog_api_client.v2.model.update_outcomes_async_attributes import UpdateOutcomesAsyncAttributes
+from datadog_api_client.v2.model.update_outcomes_async_request import UpdateOutcomesAsyncRequest
+from datadog_api_client.v2.model.update_outcomes_async_request_data import UpdateOutcomesAsyncRequestData
+from datadog_api_client.v2.model.update_outcomes_async_request_item import UpdateOutcomesAsyncRequestItem
+from datadog_api_client.v2.model.update_outcomes_async_type import UpdateOutcomesAsyncType
from datadog_api_client.v2.model.update_resource_evaluation_filters_request import (
UpdateResourceEvaluationFiltersRequest,
)
@@ -6743,6 +6748,11 @@
"UpdateOpenAPIResponse",
"UpdateOpenAPIResponseAttributes",
"UpdateOpenAPIResponseData",
+ "UpdateOutcomesAsyncAttributes",
+ "UpdateOutcomesAsyncRequest",
+ "UpdateOutcomesAsyncRequestData",
+ "UpdateOutcomesAsyncRequestItem",
+ "UpdateOutcomesAsyncType",
"UpdateResourceEvaluationFiltersRequest",
"UpdateResourceEvaluationFiltersRequestData",
"UpdateResourceEvaluationFiltersResponse",
diff --git a/tests/v2/cassettes/test_scenarios/test_create_a_new_rule_returns_bad_request_response.frozen b/tests/v2/cassettes/test_scenarios/test_create_a_new_rule_returns_bad_request_response.frozen
new file mode 100644
index 0000000000..5d0a1ab654
--- /dev/null
+++ b/tests/v2/cassettes/test_scenarios/test_create_a_new_rule_returns_bad_request_response.frozen
@@ -0,0 +1 @@
+2025-08-26T15:48:59.496Z
\ No newline at end of file
diff --git a/tests/v2/cassettes/test_scenarios/test_create_a_new_rule_returns_bad_request_response.yaml b/tests/v2/cassettes/test_scenarios/test_create_a_new_rule_returns_bad_request_response.yaml
new file mode 100644
index 0000000000..52808d7836
--- /dev/null
+++ b/tests/v2/cassettes/test_scenarios/test_create_a_new_rule_returns_bad_request_response.yaml
@@ -0,0 +1,21 @@
+interactions:
+- request:
+ body: '{"data":{"attributes":{"enabled":true,"level":2,"name":"Team Defined","scorecard_id":"NOT.FOUND"},"type":"rule"}}'
+ headers:
+ accept:
+ - application/json
+ content-type:
+ - application/json
+ method: POST
+ uri: https://api.datadoghq.com/api/v2/scorecard/rules
+ response:
+ body:
+ string: '{"errors":[{"status":"400","title":"Bad Request","detail":"attribute
+ \"scorecard_id\" failed scorecard lookup"}]}'
+ headers:
+ content-type:
+ - application/vnd.api+json
+ status:
+ code: 400
+ message: Bad Request
+version: 1
diff --git a/tests/v2/cassettes/test_scenarios/test_update_an_existing_scorecard_rule_returns_bad_request_response.frozen b/tests/v2/cassettes/test_scenarios/test_update_an_existing_scorecard_rule_returns_bad_request_response.frozen
new file mode 100644
index 0000000000..5eaafa2c36
--- /dev/null
+++ b/tests/v2/cassettes/test_scenarios/test_update_an_existing_scorecard_rule_returns_bad_request_response.frozen
@@ -0,0 +1 @@
+2025-08-26T19:33:28.111Z
\ No newline at end of file
diff --git a/tests/v2/cassettes/test_scenarios/test_update_an_existing_scorecard_rule_returns_bad_request_response.yaml b/tests/v2/cassettes/test_scenarios/test_update_an_existing_scorecard_rule_returns_bad_request_response.yaml
new file mode 100644
index 0000000000..78bec0e741
--- /dev/null
+++ b/tests/v2/cassettes/test_scenarios/test_update_an_existing_scorecard_rule_returns_bad_request_response.yaml
@@ -0,0 +1,56 @@
+interactions:
+- request:
+ body: '{"data":{"attributes":{"enabled":true,"name":"Test-Update_an_existing_scorecard_rule_returns_Bad_Request_response-1756236808","owner":"Datadog","scorecard_name":"OpenAPI
+ Spec Test Best Practices"},"type":"rule"}}'
+ headers:
+ accept:
+ - application/json
+ content-type:
+ - application/json
+ method: POST
+ uri: https://api.datadoghq.com/api/v2/scorecard/rules
+ response:
+ body:
+ string: '{"data":{"id":"z661h8n2bpc5q0kx","type":"rule","attributes":{"category":"OpenAPI
+ Spec Test Best Practices","created_at":"2025-08-26T19:32:32.06573621Z","custom":true,"enabled":true,"level":3,"modified_at":"2025-08-26T19:32:32.06573621Z","name":"Test-Update_an_existing_scorecard_rule_returns_Bad_Request_response-1756236808","owner":"Datadog","scorecard_name":"OpenAPI
+ Spec Test Best Practices"},"relationships":{"scorecard":{"data":{"id":"qsxpoYRhU_yz","type":"scorecard"}}}}}'
+ headers:
+ content-type:
+ - application/vnd.api+json
+ status:
+ code: 201
+ message: Created
+- request:
+ body: '{"data":{"attributes":{"enabled":true,"level":2,"name":"Team Defined","scorecard_id":"NOT.FOUND"},"type":"rule"}}'
+ headers:
+ accept:
+ - application/json
+ content-type:
+ - application/json
+ method: PUT
+ uri: https://api.datadoghq.com/api/v2/scorecard/rules/z661h8n2bpc5q0kx
+ response:
+ body:
+ string: '{"errors":[{"status":"400","title":"Bad Request","detail":"attribute
+ \"scorecard_id\" failed scorecard lookup"}]}'
+ headers:
+ content-type:
+ - application/vnd.api+json
+ status:
+ code: 400
+ message: Bad Request
+- request:
+ body: null
+ headers:
+ accept:
+ - '*/*'
+ method: DELETE
+ uri: https://api.datadoghq.com/api/v2/scorecard/rules/z661h8n2bpc5q0kx
+ response:
+ body:
+ string: ''
+ headers: {}
+ status:
+ code: 204
+ message: No Content
+version: 1
diff --git a/tests/v2/cassettes/test_scenarios/test_update_an_existing_scorecard_rule_returns_not_found_response.frozen b/tests/v2/cassettes/test_scenarios/test_update_an_existing_scorecard_rule_returns_not_found_response.frozen
new file mode 100644
index 0000000000..865cee5ede
--- /dev/null
+++ b/tests/v2/cassettes/test_scenarios/test_update_an_existing_scorecard_rule_returns_not_found_response.frozen
@@ -0,0 +1 @@
+2025-08-26T19:33:28.966Z
\ No newline at end of file
diff --git a/tests/v2/cassettes/test_scenarios/test_update_an_existing_scorecard_rule_returns_not_found_response.yaml b/tests/v2/cassettes/test_scenarios/test_update_an_existing_scorecard_rule_returns_not_found_response.yaml
new file mode 100644
index 0000000000..8e1069df4d
--- /dev/null
+++ b/tests/v2/cassettes/test_scenarios/test_update_an_existing_scorecard_rule_returns_not_found_response.yaml
@@ -0,0 +1,22 @@
+interactions:
+- request:
+ body: '{"data":{"attributes":{"enabled":true,"level":2,"name":"Team Defined","scorecard_name":"Deployments
+ automated via Deployment Trains"},"type":"rule"}}'
+ headers:
+ accept:
+ - application/json
+ content-type:
+ - application/json
+ method: PUT
+ uri: https://api.datadoghq.com/api/v2/scorecard/rules/REPLACE.ME
+ response:
+ body:
+ string: '{"errors":[{"status":"404","title":"Not Found","detail":"rule not found:
+ REPLACE.ME"}]}'
+ headers:
+ content-type:
+ - application/vnd.api+json
+ status:
+ code: 404
+ message: Not Found
+version: 1
diff --git a/tests/v2/cassettes/test_scenarios/test_update_scorecard_outcomes_asynchronously_returns_accepted_response.frozen b/tests/v2/cassettes/test_scenarios/test_update_scorecard_outcomes_asynchronously_returns_accepted_response.frozen
new file mode 100644
index 0000000000..90ae34fee2
--- /dev/null
+++ b/tests/v2/cassettes/test_scenarios/test_update_scorecard_outcomes_asynchronously_returns_accepted_response.frozen
@@ -0,0 +1 @@
+2025-08-26T14:46:17.790Z
\ No newline at end of file
diff --git a/tests/v2/cassettes/test_scenarios/test_update_scorecard_outcomes_asynchronously_returns_accepted_response.yaml b/tests/v2/cassettes/test_scenarios/test_update_scorecard_outcomes_asynchronously_returns_accepted_response.yaml
new file mode 100644
index 0000000000..bbf24ff799
--- /dev/null
+++ b/tests/v2/cassettes/test_scenarios/test_update_scorecard_outcomes_asynchronously_returns_accepted_response.yaml
@@ -0,0 +1,56 @@
+interactions:
+- request:
+ body: '{"data":{"attributes":{"enabled":true,"name":"Test-Update_Scorecard_outcomes_asynchronously_returns_Accepted_response-1756219577","owner":"Datadog","scorecard_name":"OpenAPI
+ Spec Test Best Practices"},"type":"rule"}}'
+ headers:
+ accept:
+ - application/json
+ content-type:
+ - application/json
+ method: POST
+ uri: https://api.datadoghq.com/api/v2/scorecard/rules
+ response:
+ body:
+ string: '{"data":{"id":"5e3dexz6x_4f_4pa","type":"rule","attributes":{"category":"OpenAPI
+ Spec Test Best Practices","created_at":"2025-08-26T14:46:18.889883535Z","custom":true,"enabled":true,"level":3,"modified_at":"2025-08-26T14:46:18.889883535Z","name":"Test-Update_Scorecard_outcomes_asynchronously_returns_Accepted_response-1756219577","owner":"Datadog","scorecard_name":"OpenAPI
+ Spec Test Best Practices"},"relationships":{"scorecard":{"data":{"id":"qsxpoYRhU_yz","type":"scorecard"}}}}}'
+ headers:
+ content-type:
+ - application/vnd.api+json
+ status:
+ code: 201
+ message: Created
+- request:
+ body: '{"data":{"attributes":{"results":[{"entity_reference":"service:my-service","remarks":"See:
+ Services","rule_id":"5e3dexz6x_4f_4pa","state":"pass"}]},"type":"batched-outcome"}}'
+ headers:
+ accept:
+ - '*/*'
+ content-type:
+ - application/json
+ method: POST
+ uri: https://api.datadoghq.com/api/v2/scorecard/outcomes
+ response:
+ body:
+ string: '{"data":{"id":"4iexte5r8prsrlrtzzxpy","type":"async-request"},"meta":{"total_received":1}}'
+ headers:
+ content-type:
+ - application/vnd.api+json
+ status:
+ code: 202
+ message: Accepted
+- request:
+ body: null
+ headers:
+ accept:
+ - '*/*'
+ method: DELETE
+ uri: https://api.datadoghq.com/api/v2/scorecard/rules/5e3dexz6x_4f_4pa
+ response:
+ body:
+ string: ''
+ headers: {}
+ status:
+ code: 204
+ message: No Content
+version: 1
diff --git a/tests/v2/cassettes/test_scenarios/test_update_scorecard_outcomes_asynchronously_returns_bad_request_response.frozen b/tests/v2/cassettes/test_scenarios/test_update_scorecard_outcomes_asynchronously_returns_bad_request_response.frozen
new file mode 100644
index 0000000000..b743ee81bc
--- /dev/null
+++ b/tests/v2/cassettes/test_scenarios/test_update_scorecard_outcomes_asynchronously_returns_bad_request_response.frozen
@@ -0,0 +1 @@
+2025-08-26T14:46:19.541Z
\ No newline at end of file
diff --git a/tests/v2/cassettes/test_scenarios/test_update_scorecard_outcomes_asynchronously_returns_bad_request_response.yaml b/tests/v2/cassettes/test_scenarios/test_update_scorecard_outcomes_asynchronously_returns_bad_request_response.yaml
new file mode 100644
index 0000000000..5f5c1ee07e
--- /dev/null
+++ b/tests/v2/cassettes/test_scenarios/test_update_scorecard_outcomes_asynchronously_returns_bad_request_response.yaml
@@ -0,0 +1,56 @@
+interactions:
+- request:
+ body: '{"data":{"attributes":{"enabled":true,"name":"Test-Update_Scorecard_outcomes_asynchronously_returns_Bad_Request_response-1756219579","owner":"Datadog","scorecard_name":"OpenAPI
+ Spec Test Best Practices"},"type":"rule"}}'
+ headers:
+ accept:
+ - application/json
+ content-type:
+ - application/json
+ method: POST
+ uri: https://api.datadoghq.com/api/v2/scorecard/rules
+ response:
+ body:
+ string: '{"data":{"id":"cyysw9dtqcu8zemc","type":"rule","attributes":{"category":"OpenAPI
+ Spec Test Best Practices","created_at":"2025-08-26T14:46:19.594805953Z","custom":true,"enabled":true,"level":3,"modified_at":"2025-08-26T14:46:19.594805953Z","name":"Test-Update_Scorecard_outcomes_asynchronously_returns_Bad_Request_response-1756219579","owner":"Datadog","scorecard_name":"OpenAPI
+ Spec Test Best Practices"},"relationships":{"scorecard":{"data":{"id":"qsxpoYRhU_yz","type":"scorecard"}}}}}'
+ headers:
+ content-type:
+ - application/vnd.api+json
+ status:
+ code: 201
+ message: Created
+- request:
+ body: '{"data":{"attributes":{"results":[{"entity_reference":"service:my-service","rule_id":"cyysw9dtqcu8zemc","state":"INVALID"}]},"type":"batched-outcome"}}'
+ headers:
+ accept:
+ - '*/*'
+ content-type:
+ - application/json
+ method: POST
+ uri: https://api.datadoghq.com/api/v2/scorecard/outcomes
+ response:
+ body:
+ string: '{"errors":[{"status":"400","title":"Bad Request","detail":"attribute
+ \"state\" must be one of \"pass fail skip\""}]}'
+ headers:
+ content-type:
+ - application/vnd.api+json
+ status:
+ code: 400
+ message: Bad Request
+- request:
+ body: null
+ headers:
+ accept:
+ - '*/*'
+ method: DELETE
+ uri: https://api.datadoghq.com/api/v2/scorecard/rules/cyysw9dtqcu8zemc
+ response:
+ body:
+ string: ''
+ headers: {}
+ status:
+ code: 204
+ message: No Content
+version: 1
diff --git a/tests/v2/cassettes/test_scenarios/test_update_scorecard_outcomes_asynchronously_returns_conflict_response.frozen b/tests/v2/cassettes/test_scenarios/test_update_scorecard_outcomes_asynchronously_returns_conflict_response.frozen
new file mode 100644
index 0000000000..eb7d1dc0b1
--- /dev/null
+++ b/tests/v2/cassettes/test_scenarios/test_update_scorecard_outcomes_asynchronously_returns_conflict_response.frozen
@@ -0,0 +1 @@
+2025-08-26T14:46:20.159Z
\ No newline at end of file
diff --git a/tests/v2/cassettes/test_scenarios/test_update_scorecard_outcomes_asynchronously_returns_conflict_response.yaml b/tests/v2/cassettes/test_scenarios/test_update_scorecard_outcomes_asynchronously_returns_conflict_response.yaml
new file mode 100644
index 0000000000..12a265387d
--- /dev/null
+++ b/tests/v2/cassettes/test_scenarios/test_update_scorecard_outcomes_asynchronously_returns_conflict_response.yaml
@@ -0,0 +1,21 @@
+interactions:
+- request:
+ body: '{"data":{"attributes":{"results":[{"entity_reference":"service:my-service","remarks":"See:
+ Services","rule_id":"INVALID.RULE_ID","state":"pass"}]},"type":"batched-outcome"}}'
+ headers:
+ accept:
+ - '*/*'
+ content-type:
+ - application/json
+ method: POST
+ uri: https://api.datadoghq.com/api/v2/scorecard/outcomes
+ response:
+ body:
+ string: '{"errors":[{"status":"409","title":"Invalid rule_id"}]}'
+ headers:
+ content-type:
+ - application/vnd.api+json
+ status:
+ code: 409
+ message: Conflict
+version: 1
diff --git a/tests/v2/features/service_scorecards.feature b/tests/v2/features/service_scorecards.feature
index 11d2c7f432..387f04cf71 100644
--- a/tests/v2/features/service_scorecards.feature
+++ b/tests/v2/features/service_scorecards.feature
@@ -10,11 +10,11 @@ Feature: Service Scorecards
And a valid "appKeyAuth" key in the system
And an instance of "ServiceScorecards" API
- @generated @skip @team:DataDog/service-catalog
+ @team:DataDog/service-catalog
Scenario: Create a new rule returns "Bad Request" response
Given operation "CreateScorecardRule" enabled
And new "CreateScorecardRule" request
- And body with value {"data": {"attributes": {"enabled": true, "name": "Team Defined", "scorecard_name": "Deployments automated via Deployment Trains"}, "type": "rule"}}
+ And body with value {"data": {"attributes": {"enabled": true, "level": 2, "name": "Team Defined", "scorecard_id": "NOT.FOUND"}, "type": "rule"}}
When the request is sent
Then the response status is 400 Bad Request
@@ -121,12 +121,41 @@ Feature: Service Scorecards
Then the response status is 200 OK
And the response has 4 items
+ @team:DataDog/service-catalog
+ Scenario: Update Scorecard outcomes asynchronously returns "Accepted" response
+ Given operation "UpdateScorecardOutcomesAsync" enabled
+ And there is a valid "create_scorecard_rule" in the system
+ And new "UpdateScorecardOutcomesAsync" request
+ And body with value {"data": {"attributes": {"results": [{"rule_id": "{{create_scorecard_rule.data.id}}", "entity_reference": "service:my-service", "remarks": "See: Services", "state": "pass"}]}, "type": "batched-outcome"}}
+ When the request is sent
+ Then the response status is 202 Accepted
+
+ @team:DataDog/service-catalog
+ Scenario: Update Scorecard outcomes asynchronously returns "Bad Request" response
+ Given operation "UpdateScorecardOutcomesAsync" enabled
+ And there is a valid "create_scorecard_rule" in the system
+ And new "UpdateScorecardOutcomesAsync" request
+ And body with value {"data": {"attributes": {"results": [{"rule_id": "{{create_scorecard_rule.data.id}}", "entity_reference": "service:my-service", "state": "INVALID"}]}, "type": "batched-outcome"}}
+ When the request is sent
+ Then the response status is 400 Bad Request
+ And the response "errors" has length 1
+ And the response "errors[0]" has field "detail"
+
+ @team:DataDog/service-catalog
+ Scenario: Update Scorecard outcomes asynchronously returns "Conflict" response
+ Given operation "UpdateScorecardOutcomesAsync" enabled
+ And new "UpdateScorecardOutcomesAsync" request
+ And body with value {"data": {"attributes": {"results": [{"rule_id": "INVALID.RULE_ID", "entity_reference": "service:my-service", "remarks": "See: Services", "state": "pass"}]}, "type": "batched-outcome"}}
+ When the request is sent
+ Then the response status is 409 Conflict
+ And the response "errors" has length 1
+
@generated @skip @team:DataDog/service-catalog
Scenario: Update an existing rule returns "Bad Request" response
Given operation "UpdateScorecardRule" enabled
And new "UpdateScorecardRule" request
And request contains "rule_id" parameter from "REPLACE.ME"
- And body with value {"data": {"attributes": {"enabled": true, "name": "Team Defined", "scorecard_name": "Deployments automated via Deployment Trains"}, "type": "rule"}}
+ And body with value {"data": {"attributes": {"enabled": true, "level": 2, "name": "Team Defined", "scorecard_name": "Deployments automated via Deployment Trains"}, "type": "rule"}}
When the request is sent
Then the response status is 400 Bad Request
@@ -139,3 +168,22 @@ Feature: Service Scorecards
And body with value {"data": { "attributes" : {"enabled": true, "name": "{{create_scorecard_rule.data.attributes.name}}", "scorecard_name": "{{create_scorecard_rule.data.attributes.scorecard_name}}", "description": "Updated description via test"}}}
When the request is sent
Then the response status is 200 Rule updated successfully
+
+ @team:DataDog/service-catalog
+ Scenario: Update an existing scorecard rule returns "Bad Request" response
+ Given operation "UpdateScorecardRule" enabled
+ And there is a valid "create_scorecard_rule" in the system
+ And new "UpdateScorecardRule" request
+ And request contains "rule_id" parameter from "create_scorecard_rule.data.id"
+ And body with value {"data": {"attributes": {"enabled": true, "level": 2, "name": "Team Defined", "scorecard_id": "NOT.FOUND"}, "type": "rule"}}
+ When the request is sent
+ Then the response status is 400 Bad Request
+
+ @team:DataDog/service-catalog
+ Scenario: Update an existing scorecard rule returns "Not Found" response
+ Given operation "UpdateScorecardRule" enabled
+ And new "UpdateScorecardRule" request
+ And request contains "rule_id" parameter with value "REPLACE.ME"
+ And body with value {"data": {"attributes": {"enabled": true, "level": 2, "name": "Team Defined", "scorecard_name": "Deployments automated via Deployment Trains"}, "type": "rule"}}
+ When the request is sent
+ Then the response status is 404 Not Found
diff --git a/tests/v2/features/undo.json b/tests/v2/features/undo.json
index 9878d7a467..444ec9d07d 100644
--- a/tests/v2/features/undo.json
+++ b/tests/v2/features/undo.json
@@ -2742,6 +2742,12 @@
"type": "safe"
}
},
+ "UpdateScorecardOutcomesAsync": {
+ "tag": "Service Scorecards",
+ "undo": {
+ "type": "idempotent"
+ }
+ },
"CreateScorecardOutcomesBatch": {
"tag": "Service Scorecards",
"undo": {