Recovery and Ownership Reconciliation
These application programming interface (API) operations support authorized recovery. They do not replace authoring, review, or target-specific protection checks. Policy Integration Manager (PIM) ownership mappings connect reference keys to native unique identifiers (UIDs). A saved mapping does not prove that its native resource still exists.
Use the POLICY_API base and protected POLICY_AUTH_HEADER file from
authentication.
Every path below is relative to POLICY_API.
Set POLICY_ID to the affected policy identifier for policy-specific requests.
For retry, obtain DEPLOYMENT_ID from the operation-list response.
For reconciliation, copy identifiers and versions from the inspection response before constructing a decision body.
For symptom-based instructions, use the recovery playbooks. For changed compilation inputs, see automatic recompilation. Retained deployment retry does not request recompilation.
A deployment generation identifies a publication or removal request. That request can have several retry attempts. Retry sends the configuration already saved for that request. Reconciliation changes which PIM object Policy associates with a saved reference. Automatic recompilation instead generates updated configuration from already approved policy inputs.
Authority and Preconditions
The table maps each recovery operation to its required capability:
| Operation | Required Capability |
|---|---|
| Read operations or validation diagnostics | Require policy:audit |
| Retry publication | Require policy:approve |
| Retry withdrawal or record archive evidence | Require policy:archive |
| Inspect or decide ownership reconciliation | Require policy:system-configure |
Select withdraw_policy | Require both policy:system-configure and policy:archive |
These endpoints do not require an owner/editor grant. Such grants do not supply the command capabilities above. Policy derives decision actors from authenticated identity, not request-body fields. A support reference does not grant diagnostic access. Authors without these capabilities should retain safe evidence for authorized operators.
The following table summarizes the validator or control used for each recovery task:
| Token or Control | Scope and Rule |
|---|---|
Draft-ETag | Pin draft commands. Never substitute it for ownership evidence. |
Policy ETag | Pin ordinary archive initiation. Do not use it for reconciliation. |
Registry ETag | Pin reconciliation decisions and later binding-enumeration pages. |
governedSetGeneration | Copy this policy-set version from inspection. Policy rejects it if relevant approved policies change before the decision. |
Idempotency-Key | Supply 1–128 characters for either reconciliation decision endpoint. |
Reconciliation decisions require one strong registry token through If-Match.
An entity tag (ETag) validates inspected registry state. The governed-set generation tracks policy-set changes separately.
Preserve the exact quoted value returned by inspection.
Do not construct a token from ownershipVersion, or use a weak draft token.
Use a new decision key for changed evidence.
Reuse a key only with identical evidence and the same authenticated actor.
Retain the inspection response’s exact ETag as REGISTRY_ETAG.
Set DECISION_KEY to a new 1–128-character key for the specific inspected decision.
Missing registry preconditions return 428. Malformed tokens return 400.
Stale registry evidence returns 412.
Changed governed generations, illegal decisions, or changed decision-key content return 409.
Malformed decision bodies or missing/invalid decision keys return 422.
Repeat inspection after 409 or 412, compare the changed policies and mappings, then prepare a new decision if needed.
GET /policies/{policy_id}/operations
Read deployment generations and their retained publication or withdrawal work.
The request uses this path parameter:
| Parameter | Type | Requirement |
|---|---|---|
policy_id | Path string | Identify the policy whose operations you need. |
Require policy:audit. Accept no request body, query parameters, or conditional headers.
Return 200 with a top-level array, not an operations envelope.
Each entry includes:
| Response Field | Type | Meaning |
|---|---|---|
deploymentId, generation, operation | String, integer, string | Identify the deployment generation and publication or withdrawal operation. |
enforcementState, requestedAt | String, timestamp | Describe protection progress and request time. |
retryable, attemptCount | Boolean, integer | Indicate advisory eligibility and latest event attempts. |
lastError | Nullable string | Describe retained failure text for unprocessed work. |
issueCategory, severity | Nullable strings | Classify the projected issue. Severity uses warning or error. |
requiresOperatorAction, detectedAt | Boolean, nullable timestamp | Identify operator intervention and issue detection. |
replacedByGeneration | Nullable integer | Identify a successful successor when applicable. |
diagnostics | Array of objects | Retain sanitized publication diagnostics. |
Diagnostics contain supportReference, code, message, remediation, and
detectedAt, with retryable and requiresOperatorAction.
They can also include operationId, statusCode, resourceReference, and
details containing path, constraint, and message.
curl --fail-with-body \
-H "@${POLICY_AUTH_HEADER:?Complete authentication setup}" \
"${POLICY_API}/policies/${POLICY_ID}/operations"
Illustrative successful response:
[
{
"deploymentId": "deployment-7",
"generation": 7,
"operation": "publish",
"enforcementState": "publishing",
"requestedAt": "2026-10-29T12:00:00Z",
"retryable": true,
"attemptCount": 4,
"lastError": "Target temporarily unavailable",
"issueCategory": null,
"severity": null,
"requiresOperatorAction": false,
"detectedAt": null,
"replacedByGeneration": null,
"diagnostics": []
}
]
Return 401 without trusted identity, or 403 without audit capability.
Return 404 with no lifecycle operations for policy when no deployments exist.
That response does not establish whether the policy exists.
The retryable hint considers diagnostics and successor generations.
If diagnostics say retry cannot help, resolve the named problem before submitting the retry command.
Reading operations does not restart them.
Use the selected entry’s deploymentId in the retry path.
Do not substitute its integer generation, a policy revision, or a draft snapshot identifier.
GET /validation-diagnostics/{support_reference}
Retrieve restricted evidence from a compile, submit, or approval validation failure.
The request uses this path parameter to select the diagnostic evidence:
| Parameter | Type | Requirement |
|---|---|---|
support_reference | Path string | Copy the exact supportReference from the failure response. |
Require policy:audit. Accept no body, query parameters, or conditional headers.
Return 200 with the diagnostic object and Cache-Control: no-store.
curl --fail-with-body \
-H "@${POLICY_AUTH_HEADER:?Complete authentication setup}" \
"${POLICY_API}/validation-diagnostics/${SUPPORT_REFERENCE}"
{
"supportReference": "VAL-example",
"code": "approval_validation_failed",
"message": "Policy command validation failed.",
"remediation": "Review the indicated configuration constraints before retrying.",
"detectedAt": "2026-10-29T12:00:00Z",
"details": [
{
"path": "$.user_attribute",
"constraint": "required",
"message": "Set the identity source user attribute."
}
]
}
The shared diagnostic shape can also include nullable operationId,
statusCode, and resourceReference fields.
Return 401 without trusted identity, or 403 without audit capability.
Return 404 when evidence does not exist or its seven-day retention expires.
Preserve the original failure, timestamp, and reference before expiration.
Do not send credentials, raw identity attributes, or sensitive payloads during escalation.
Diagnostic retrieval does not repair the configuration or validate another draft head.
POST /policies/{policy_id}/deployments/{deployment_id}/retry
Reset eligible terminal work within an existing deployment generation. Policy reuses retained artifacts. It does not compile a corrected draft.
The retry request uses these path parameters:
| Parameter | Type | Requirement |
|---|---|---|
policy_id | Path string | Identify the policy. |
deployment_id | Path string | Select its retained generation from archive results or operation inspection. |
Require policy:approve for publication, or policy:archive for withdrawal.
Accept no body or query parameters.
This operation requires neither If-Match nor Idempotency-Key.
curl --fail-with-body -i -X POST \
-H "@${POLICY_AUTH_HEADER:?Complete authentication setup}" \
"${POLICY_API}/policies/${POLICY_ID}/deployments/${DEPLOYMENT_ID}/retry"
HTTP/1.1 204 No Content
The following table summarizes retry response status codes:
| Status | Meaning |
|---|---|
204 | Confirm the terminal-work reset. Return an empty body. |
401, 403 | Reject missing identity or the operation-specific capability. |
404 | Reject an unknown deployment or one belonging to another policy. |
409 | Reject replaced work, any newer generation, or work without a retryable terminal event. |
Correct the underlying condition before retrying.
A newer in-progress generation also prevents retrying its predecessor.
Repeated retry requests need not return 204. The first reset can remove terminal eligibility.
After a timeout, inspect operations before deciding whether another request makes sense.
A successful reset does not prove publication, withdrawal, or protection recovery.
An auditor must read subsequent operation progress. Verify target evidence separately.
If you can retry but lack policy:audit, arrange that progress check with an authorized auditor.
POST /policies/{policy_id}/archive-evidence
Record an immutable manual evidence event for an active withdrawal. This event does not replace observed deprotection.
Require policy:archive. Identify policy_id through the path.
Accept the following application/json body, with no extra fields.
This operation requires neither If-Match nor Idempotency-Key.
The request body accepts the following evidence fields:
| Field | Type | Requirement |
|---|---|---|
deploymentId | String | Identify the active withdrawal deployment for this policy. |
ticketReference | String | Supply 1–128 characters. Retain nonblank text after trimming. |
description | String | Supply 1–512 characters. Retain nonblank text after trimming. |
locationIds | Array of strings | Supply at least one distinct, nonblank expected location identifier. |
Prepare archive-evidence.json with the active deployment and verified expected locations:
{
"deploymentId": "withdrawal-8",
"ticketReference": "CHANGE-204",
"description": "Completed the approved manual withdrawal check for this location.",
"locationIds": ["location-17"]
}
Replace the illustrative identifiers with your verified values before submitting the file.
curl --fail-with-body -i -X POST \
-H "@${POLICY_AUTH_HEADER:?Complete authentication setup}" \
-H "Content-Type: application/json" \
--data-binary @archive-evidence.json \
"${POLICY_API}/policies/${POLICY_ID}/archive-evidence"
Return 201 with only the event identifier and recording timestamp:
{
"eventId": "event-38",
"recordedAt": "2026-10-29T12:30:00Z"
}
Return 401 or 403 for identity or capability failures.
Return 404 for an unknown policy draft identity or an unrelated/unknown deployment.
Return 409 for an inactive withdrawal.
Unexpected locations return 409 with detail.message and detail.unexpectedLocationIds.
Malformed or duplicate location identifiers return 422.
Capture the deployment from archive initiation or an authorized operations read.
Confirm expected locations with your authorized withdrawal operator before recording evidence.
This API does not expose a complete location-discovery operation.
Stop if you cannot establish that scope. Do not guess identifiers.
Repeated accepted submissions can record additional events rather than deduplicate automatically.
Check authorized history or audit export after an uncertain result.
A 201 records the claim, not completed withdrawal or removal of protection.
GET /policies/{policy_id}/pim-reconciliations
Inspect ownership evidence for a policy’s current governed publication.
Require policy:system-configure. Accept no body or conditional header.
The request uses this path parameter:
| Parameter | Type | Requirement |
|---|---|---|
policy_id | Path string | Identify the affected policy. |
refKey | Optional query string | Select one nonempty reference key used by its governed plan. |
Set REF_KEY to an exact reference key from the policy’s unresolved bindings.
If you do not have one, first call this route without the refKey query parameter to list those bindings.
curl --fail-with-body -i --get \
-H "@${POLICY_AUTH_HEADER:?Complete authentication setup}" \
--data-urlencode "refKey=${REF_KEY}" \
"${POLICY_API}/policies/${POLICY_ID}/pim-reconciliations"
Return 200 and a strong registry ETag.
Without refKey, return an incident envelope containing policyId,
ownershipVersion, governedSetGeneration, and bindings.
The array contains unresolved bindings, not every healthy mapping.
With refKey, return one binding directly:
{
"policyId": "policy-1",
"revisionId": 15,
"deploymentId": "deployment-7",
"generation": 7,
"refKey": "dataelement:customer__EMAIL",
"resourceKind": "data_element",
"persistedUid": "58",
"status": "missing",
"candidates": [],
"allowedActions": ["authorize_replacement", "withdraw_policy"],
"affectedPolicies": [
{
"policyId": "policy-1",
"revisionId": 15,
"revisionNumber": 3,
"deploymentId": "deployment-7",
"generation": 7,
"enforcementState": "publishing",
"affectedNativeRefs": ["dataelement:customer__EMAIL"],
"affectedNativeOperations": ["createDataElement"]
}
],
"ownershipVersion": 7,
"governedSetGeneration": 4
}
Each binding has resourceKind equal to data_element or source.
Its status uses healthy, missing, or replacement_authorized.
Each candidate includes uid, name, compatible, and a definition object.
Only allowedActions describes currently permissible decision choices.
The affectedPolicies array identifies shared impact and exact revision lineage.
Omit refKey to discover unresolved bindings before selecting one for detailed inspection.
A refKey names a symbolic ownership mapping. persistedUid identifies its native resource.
Do not substitute one for the other or derive them from display names.
Return 401 or 403 for identity or capability failures.
Return 404 for a missing binding, missing registry, or a reference outside the governed plan.
Return 409 without a current governed publication, or after a concurrent governed-set change.
Return 422 for malformed query values.
Return 503 when Policy cannot obtain complete native inventory.
An inventory failure never proves native absence.
Preserve the returned registry header and generation alongside reviewed candidate evidence.
POST /policies/{policy_id}/pim-reconciliations
Apply one inspected ownership decision.
Require policy:system-configure. Additionally require policy:archive for withdrawal.
Identify policy_id through the path. Accept no query parameters.
Require If-Match with the inspected registry token and an Idempotency-Key.
All body variants use application/json and reject extra fields.
The following table lists fields required by every reconciliation decision:
| Common Field | Type | Requirement |
|---|---|---|
action | String | Select an inspected allowed action below. |
refKey | String | Identify the nonblank inspected binding. |
reason | String | Supply 1–512 characters with nonblank trimmed text. |
governedSetGeneration | Integer | Supply the inspected generation, at least one. |
The following table lists each allowed decision and its additional required fields:
| Action | Additional Required Fields | Meaning |
|---|---|---|
adopt_candidate | Supply candidateUid, affectedPolicyIds, and affectedPolicyRevisions. | Adopt the selected compatible native candidate. |
authorize_replacement | Supply impactAcknowledged, affectedPolicyIds, and affectedPolicyRevisions. | Authorize replacement after accepting affected-policy impact. |
withdraw_policy | Supply integer policyVersion, at least one. | Start governed withdrawal using the current policy version. |
Supply a nonempty string for candidateUid.
Supply nonempty affected-policy arrays and revision maps for adoption or replacement.
Map policy identifiers to inspected revisionId values, not revisionNumber values.
Include the exact complete affected set.
Replacement requires impactAcknowledged: true. False does not authorize impact.
For withdrawal, obtain policyVersion from a current policy read.
Keep the registry token in If-Match. Do not replace it with the policy token.
Prepare reconciliation-decision.json with one complete decision variant.
Use the replacement, adoption, or withdrawal payload below only when current inspection permits that action.
curl --fail-with-body -i -X POST \
-H "@${POLICY_AUTH_HEADER:?Complete authentication setup}" \
-H "Content-Type: application/json" \
-H "If-Match: ${REGISTRY_ETAG}" \
-H "Idempotency-Key: ${DECISION_KEY}" \
--data-binary @reconciliation-decision.json \
"${POLICY_API}/policies/${POLICY_ID}/pim-reconciliations"
Replacement example reconciliation-decision.json:
{
"action": "authorize_replacement",
"refKey": "dataelement:customer__EMAIL",
"reason": "Reviewed shared impact after confirmed native deletion.",
"governedSetGeneration": 4,
"impactAcknowledged": true,
"affectedPolicyIds": ["policy-1"],
"affectedPolicyRevisions": {"policy-1": 15}
}
Adoption variant:
{
"action": "adopt_candidate",
"refKey": "dataelement:customer__EMAIL",
"reason": "Reviewed the compatible candidate and shared policy lineage.",
"governedSetGeneration": 4,
"candidateUid": "61",
"affectedPolicyIds": ["policy-1"],
"affectedPolicyRevisions": {"policy-1": 15}
}
Withdrawal variant:
{
"action": "withdraw_policy",
"refKey": "dataelement:customer__EMAIL",
"reason": "Approved withdrawal instead of replacing this binding.",
"governedSetGeneration": 4,
"policyVersion": 9
}
These variants illustrate alternative inspected situations. Do not submit adoption when inspection returns no compatible candidate.
Return 200 for adoption or replacement, with a registry ETag:
{
"action": "authorize_replacement",
"refKey": "dataelement:customer__EMAIL",
"affectedPolicyIds": ["policy-1"],
"affectedPolicyRevisions": {"policy-1": 15},
"governedSetGeneration": 4,
"ownershipVersion": 8,
"reconciliationId": "decision-204",
"status": "authorized"
}
Adoption returns the same shape with action: "adopt_candidate" and status: "completed".
Replacement authorization does not mean Policy already created a replacement resource.
Withdrawal returns 202 and a registry ETag:
{
"action": "withdraw_policy",
"refKey": "dataelement:customer__EMAIL",
"ownershipVersion": 7,
"status": "withdrawal_started",
"deploymentId": "withdrawal-8",
"generation": 8,
"remainingAffectedPolicyIds": []
}
Return 401 or 403 for identity or required capability failures.
Return 404 for missing or unrelated bindings.
Return 409 for incompatible candidates, changed affected lineage, invalid actions,
changed generations, or reused keys with different decision content.
Return 503 when complete inventory is unavailable.
The shared 400, 412, 422, and 428 precondition rules also apply.
An identical accepted decision can replay without another ownership transition.
Preserve its original evidence and key after an uncertain response.
Do not change its actor, reason, action, or affected set while reusing the key.
Reinspect the binding after success. Inspect operation progress after withdrawal acceptance.
Neither 200 nor 202 proves target publication or completed withdrawal.
GET /pim-reconciliations/bindings
Enumerate saved reference-to-UID mappings without querying native inventory.
Require policy:system-configure. Accept no body.
The request uses these pagination parameters:
| Parameter | Type | Requirement |
|---|---|---|
limit | Query integer | Select 1–100 bindings. Default to 100. |
offset | Query integer | Select a nonnegative offset. Default to zero. |
If-Match | Conditional header | Supply the first page’s registry token on every page after offset zero. |
curl --fail-with-body -i \
-H "@${POLICY_AUTH_HEADER:?Complete authentication setup}" \
"${POLICY_API}/pim-reconciliations/bindings?limit=1&offset=0"
Return 200, the registry ETag, and Cache-Control: no-store:
{
"target": "https://pim.example.test",
"ownershipVersion": 7,
"bindings": [{"refKey": "dataelement:customer__EMAIL", "persistedUid": "58"}],
"total": 2,
"limit": 1,
"offset": 0,
"nextOffset": 1
}
Bindings follow reference-key order.
The final page returns nextOffset: null.
Use each returned nextOffset for the next request while retaining the first page’s exact registry token.
Keep one registry version throughout enumeration:
curl --fail-with-body -i \
-H "@${POLICY_AUTH_HEADER:?Complete authentication setup}" \
-H "If-Match: ${REGISTRY_ETAG}" \
"${POLICY_API}/pim-reconciliations/bindings?limit=1&offset=1"
Return 401 or 403 for identity or capability failures.
Return 404 when the registry does not exist.
Return 400 for malformed tokens, 412 for a moved registry,
428 for missing later-page tokens, or 422 for invalid pagination.
On 412, restart from offset zero instead of continuing with a new token.
Enumeration establishes saved mappings only, not native absence or cleanup authority.
GET /pim-reconciliations
Inspect selected saved mappings against complete native inventory and current policy blockers.
Require policy:system-configure. Accept no body or conditional headers.
The request uses this repeated query parameter to select saved bindings:
| Parameter | Type | Requirement |
|---|---|---|
refKey | Repeated query string | Select 1–100 saved reference keys from enumeration. |
Policy deduplicates and sorts the selection.
Set REF_KEY to an exact saved reference key returned by binding enumeration.
curl --fail-with-body -i --get \
-H "@${POLICY_AUTH_HEADER:?Complete authentication setup}" \
--data-urlencode "refKey=${REF_KEY}" \
"${POLICY_API}/pim-reconciliations"
Return 200 and the registry ETag:
{
"target": "https://pim.example.test",
"ownershipVersion": 7,
"governedSetGeneration": 4,
"writerPending": false,
"bindings": [
{
"refKey": "dataelement:customer__EMAIL",
"persistedUid": "58",
"status": "missing",
"blockingPolicyIds": []
}
]
}
Each binding reports healthy or missing.
Retain the target, exact UID mappings, generation, and response header.
Stop cleanup when writerPending is true or any blocking policy remains.
Inspection does not reserve the registry. The decision rechecks these conditions.
Return 401 or 403 for identity or capability failures.
Return 404 for a missing registry or selected binding.
Return 409 for concurrent governed-set changes or reconciliation refusal.
Return 422 for invalid query selection.
Return 503 when complete native inventory is unavailable.
Restore that dependency before interpreting native presence.
POST /pim-reconciliations
Forget only selected, verified-stale saved mappings.
This command never deletes native resources.
Require policy:system-configure, registry If-Match, and Idempotency-Key.
Accept no query parameters.
The application/json body rejects extra fields:
| Field | Type | Requirement |
|---|---|---|
action | String | Supply forget_stale_bindings. |
target | String | Match the inspected configured PIM target exactly. |
bindings | Object | Map 1–100 selected nonblank reference keys to expected nonblank UID strings. |
reason | String | Supply 1–512 characters with nonblank trimmed text. |
governedSetGeneration | Integer | Match the inspected generation, at least one. |
Prepare forget-bindings.json with the inspected target, selected mappings, reason, and generation.
Use the example below only after verifying the same absence and blocker conditions.
curl --fail-with-body -i -X POST \
-H "@${POLICY_AUTH_HEADER:?Complete authentication setup}" \
-H "Content-Type: application/json" \
-H "If-Match: ${REGISTRY_ETAG}" \
-H "Idempotency-Key: ${DECISION_KEY}" \
--data-binary @forget-bindings.json \
"${POLICY_API}/pim-reconciliations"
Example forget-bindings.json, only after matching the preceding inspection:
{
"action": "forget_stale_bindings",
"target": "https://pim.example.test",
"bindings": {"dataelement:customer__EMAIL": "58"},
"reason": "Confirmed native absence and completed all contributing withdrawal work.",
"governedSetGeneration": 4
}
Return 200 and the resulting registry ETag:
{
"action": "forget_stale_bindings",
"status": "completed",
"reconciliationId": "forget-204",
"ownershipVersion": 8,
"forgottenBindings": {"dataelement:customer__EMAIL": "58"}
}
Return 401 or 403 for identity or capability failures.
Return 404 for a missing registry.
Return 409 for changed targets or generations, pending writers, live native resources,
changed mappings, active contributors, unfinished work, or conflicting decision-key reuse.
Return 503 when complete inventory is unavailable.
The shared 400, 412, 422, and 428 precondition rules also apply.
An identical accepted decision can replay without another registry transition. Policy checks the configured target before replay. Reenumerate after success and verify removal of exactly the selected mappings. Do not interpret removal as native resource deletion or permission to recreate an identity.
Evidence and Stop Boundaries
Preserve policy and deployment identifiers, generation, safe error details, and timestamps. For ownership decisions, also retain inspected mappings, target, registry header, governed generation, affected revision identifiers, decision key, and reason. Never include bearer tokens in this evidence.
Stop when inventory is incomplete, a candidate is incompatible, scope is unknown, or a successor generation owns the work. Send the response and identifiers to the Policy administrator. Ask the PIM administrator to investigate missing inventory or conflicting native objects. Do not repair these conditions through database edits or spoofed identity headers.
Feedback
Was this page helpful?