Recovery and Ownership Reconciliation

Reference nine operations for restricted diagnostics, retained delivery recovery, archive evidence, and native 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:

OperationRequired Capability
Read operations or validation diagnosticsRequire policy:audit
Retry publicationRequire policy:approve
Retry withdrawal or record archive evidenceRequire policy:archive
Inspect or decide ownership reconciliationRequire policy:system-configure
Select withdraw_policyRequire 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 ControlScope and Rule
Draft-ETagPin draft commands. Never substitute it for ownership evidence.
Policy ETagPin ordinary archive initiation. Do not use it for reconciliation.
Registry ETagPin reconciliation decisions and later binding-enumeration pages.
governedSetGenerationCopy this policy-set version from inspection. Policy rejects it if relevant approved policies change before the decision.
Idempotency-KeySupply 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:

ParameterTypeRequirement
policy_idPath stringIdentify 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 FieldTypeMeaning
deploymentId, generation, operationString, integer, stringIdentify the deployment generation and publication or withdrawal operation.
enforcementState, requestedAtString, timestampDescribe protection progress and request time.
retryable, attemptCountBoolean, integerIndicate advisory eligibility and latest event attempts.
lastErrorNullable stringDescribe retained failure text for unprocessed work.
issueCategory, severityNullable stringsClassify the projected issue. Severity uses warning or error.
requiresOperatorAction, detectedAtBoolean, nullable timestampIdentify operator intervention and issue detection.
replacedByGenerationNullable integerIdentify a successful successor when applicable.
diagnosticsArray of objectsRetain 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:

ParameterTypeRequirement
support_referencePath stringCopy 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:

ParameterTypeRequirement
policy_idPath stringIdentify the policy.
deployment_idPath stringSelect 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:

StatusMeaning
204Confirm the terminal-work reset. Return an empty body.
401, 403Reject missing identity or the operation-specific capability.
404Reject an unknown deployment or one belonging to another policy.
409Reject 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:

FieldTypeRequirement
deploymentIdStringIdentify the active withdrawal deployment for this policy.
ticketReferenceStringSupply 1–128 characters. Retain nonblank text after trimming.
descriptionStringSupply 1–512 characters. Retain nonblank text after trimming.
locationIdsArray of stringsSupply 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:

ParameterTypeRequirement
policy_idPath stringIdentify the affected policy.
refKeyOptional query stringSelect 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 FieldTypeRequirement
actionStringSelect an inspected allowed action below.
refKeyStringIdentify the nonblank inspected binding.
reasonStringSupply 1–512 characters with nonblank trimmed text.
governedSetGenerationIntegerSupply the inspected generation, at least one.

The following table lists each allowed decision and its additional required fields:

ActionAdditional Required FieldsMeaning
adopt_candidateSupply candidateUid, affectedPolicyIds, and affectedPolicyRevisions.Adopt the selected compatible native candidate.
authorize_replacementSupply impactAcknowledged, affectedPolicyIds, and affectedPolicyRevisions.Authorize replacement after accepting affected-policy impact.
withdraw_policySupply 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:

ParameterTypeRequirement
limitQuery integerSelect 1–100 bindings. Default to 100.
offsetQuery integerSelect a nonnegative offset. Default to zero.
If-MatchConditional headerSupply 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:

ParameterTypeRequirement
refKeyRepeated query stringSelect 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:

FieldTypeRequirement
actionStringSupply forget_stale_bindings.
targetStringMatch the inspected configured PIM target exactly.
bindingsObjectMap 1–100 selected nonblank reference keys to expected nonblank UID strings.
reasonStringSupply 1–512 characters with nonblank trimmed text.
governedSetGenerationIntegerMatch 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.

Last modified : November 03, 2026