deployments.upsert
Create a deployment or patch an existing API-created deployment using a stable reference_id.
Use this method for idempotent ingestion when the caller may not know whether DX already has the deployment. Use deployments.update when a missing deployment should be an error instead of creating a new record.
Facts
| Method | POST https://yourinstance.getdx.net/api/deployments.upsert |
Arguments
Required arguments
| Name | Type | Description |
|---|---|---|
token |
Token |
Auth token passed as an HTTP header. |
reference_id |
Text or Integer |
Stable unique identifier used to find the deployment. Example: release-v2.4.0 |
When reference_id does not already exist, service, deployed_at, and either a recognized repository or merge_commit_shas are also required. See deployments.create for attribution guidance.
Optional arguments
Omitted fields remain unchanged when patching an existing deployment.
| Name | Type | Description |
|---|---|---|
deployed_at |
Timestamp |
Deployment timestamp. DX accepts an ISO-8601 timestamp, Unix seconds, or Unix milliseconds. |
service |
Object or Text |
Service receiving the deployment. Send an object with identifier and optional name, or a string to use the same value for both fields. Providing this field replaces the deployment’s service association. |
repository |
Text |
Repository name, including the organization or source-specific project prefix. |
commit_sha |
Text |
Deployed commit SHA, between 7 and 40 characters. Providing this field clears stored merge_commit_shas. |
merge_commit_shas |
Array<Text> |
Merge commit SHAs included in the deployment. Providing a non-empty array clears the stored commit_sha. |
environment |
Text |
Deployment environment. Example: production |
source_url |
Text |
External URL with more information about the deployment. |
source_name |
Text |
Name of the deployment source. Example: Argo CD |
metadata |
JSON |
Additional data you define. See Metadata replacement. |
region |
Object or Text |
Region to add or replace, recorded at this request’s deployed_at, which is required when region is sent. Send an object with name and an optional success boolean (default true), or a string to use as the name. See Recording regional deployments. |
integration_branch |
Text |
Branch used to integrate changes before release. Example: develop |
success |
Boolean |
Whether the deployment succeeded. Send a JSON boolean, not a string. |
Patch behavior
- An unknown
reference_idcreates a deployment and returnsaction: "created". - An existing
reference_idpatches that deployment and returnsaction: "updated". - Fields omitted from an update request retain their existing values.
- Existing deployments created by a native connector or deployment inference rule cannot be changed through this endpoint.
- Changes to attribution fields, including the repository, SHA, service, environment, integration branch, or deployment time, cause DX to recalculate deployment attribution asynchronously.
Metadata replacement
The metadata key uses replacement semantics:
- Omit
metadatato leave existing metadata unchanged. - Send an object to replace all existing metadata.
- Send
{}ornullto remove all existing metadata.
Metadata is replaced as a complete value rather than merged recursively. Include every metadata field you want to retain in each request.
Recording regional deployments
Use region when a release reaches several production regions, or other rollout targets such as customer tiers, at different times. Each regional pipeline calls deployments.upsert with the same reference_id, its own deployed_at, and its own region. Pipelines don’t need to know about each other:
curl -X POST https://yourinstance.getdx.net/api/deployments.upsert \
-H "Content-Type: application/json" \
-H "Authorization: Bearer xxxx-xxxxxxxxx-xxxx" \
--data '{
"reference_id": "release-v2.4.0",
"service": "payments-service",
"repository": "my-org/payments",
"commit_sha": "d1a34f0",
"deployed_at": "2026-09-29T16:18:00Z",
"region": { "name": "eu-west-1" }
}'
- The first call creates the deployment and its region at the request’s
deployed_at, so it needs the fieldsdeployments.upsertrequires to create a deployment. - Later calls add their region at the request’s
deployed_atand don’t change the deployment’sdeployed_at, unless the region is earlier. An earlier region moves the deployment’sdeployed_atback to it, sodeployed_atstays the start of the rollout, and DX recalculates attribution. - Sending a region again replaces its
deployed_atandsuccess. Usedeployments.delete_regionto remove one. - Names are trimmed and lowercased and can use letters, numbers,
-,_,.,/and:, up to 100 characters. A deployment can have up to 50 regions. - To move the deployment’s own
deployed_at, senddeployed_atwithoutregion. It can’t be moved later than any of its regions. - Region
successonly describes that region. The deployment’ssuccessis what standard DORA reporting uses.
Example requests
Create when missing
curl -X POST https://yourinstance.getdx.net/api/deployments.upsert \
-H "Content-Type: application/json" \
-H "Authorization: Bearer xxxx-xxxxxxxxx-xxxx" \
--data '{
"reference_id": "release-v2.4.0",
"deployed_at": "2026-09-29T16:00:00Z",
"service": { "identifier": "payments-service", "name": "Payments" },
"repository": "my-org/payments",
"commit_sha": "d1a34f0"
}'
Patch when present
curl -X POST https://yourinstance.getdx.net/api/deployments.upsert \
-H "Content-Type: application/json" \
-H "Authorization: Bearer xxxx-xxxxxxxxx-xxxx" \
--data '{
"reference_id": "release-v2.4.0",
"source_url": "https://deployments.example.com/releases/release-v2.4.0",
"success": true
}'
Success response
{
"ok": true,
"action": "updated",
"reference_id": "release-v2.4.0"
}
action is created when the request creates the deployment and updated when it patches an existing deployment.
Errors
| Error | Description |
|---|---|
not_authed |
The request did not include a valid API key. |
required_params_missing |
reference_id is missing, a supplied required value is blank, create fields are missing, or region was sent without deployed_at. |
invalid_reference_id |
reference_id is not text or an integer. |
deployment_not_api_managed |
The existing deployment is managed by a connector or inference rule. |
invalid_service_param |
service is not a string or an object with an identifier. |
invalid_timestamp |
deployed_at is not a readable timestamp. |
commit_sha_invalid |
commit_sha is invalid. |
merge_commit_shas_invalid |
merge_commit_shas is not a valid array of SHA strings. |
ambiguous_commit_sha_arguments |
Both commit_sha and a non-empty merge_commit_shas value were supplied. |
repository_not_found |
The repository could not be found. |
integration_branch_not_valid |
The integration branch could not be validated for the repository. |
metadata_invalid |
Metadata could not be processed. |
region_invalid |
region is not a string or an object with a valid name and boolean success. |
region_limit_reached |
The deployment already has 50 regions. |
region_deployed_at_before_deployment |
The new deployed_at is later than one of the deployment’s regions. |