Skip to main content

Integration Flows and Billing

This page describes the customer-facing flows for governed requests: allow and deny, approval with a bounded wait or explicit retry, webhook-driven resume, and transparent proxy approval. It also defines what is recorded and billed for each kind of asset. Field-level details are in the API Reference, and the approval lifecycle is described in Approvals & Webhooks.

Two integration levels​

LevelWho decides when to retryPending behaviorRetry
SDK (/v1/evaluate)Your applicationThe SDK may wait a bounded time, or return a pending approval for polling or webhooksExplicit retry with the same operation_id, approval_id, and payload_hash
Transparent proxy (/v1/proxy/evaluate)The CX or orchestrator observes approval, and your application retries the unchanged requestNever waits. The request is blocked immediately with a challengeSame operation_id and context. No approval_id needed

The protected application never sees a silent wait in proxy mode. A request that needs approval is rejected at once, and the retry is the caller's decision.

Decision and billing table​

Asset stateResultDecision recordBilling
Unknown assetallow with reason asset_not_registeredNo0 units
Registered asset with no policiesallow with reason no_policies_assignedYes0 units
Registered asset with one or more policiesallow, deny, or approval_requiredYes1 decision unit, even when no condition matches (no_matching_policy)
  • An unknown asset may still produce a discovery observation for administrator review. That observation is not a decision record and is not billed.
  • A registered asset with no policies is a pass-through. It is allowed without policy evaluation, is recorded in decision history, and is not billed.
  • A pending approval adds 1 approval unit on top of its decision unit. Duplicate requests for the same pending operation, approval polling, resolution, and approved retries are not billed again.
  • Notifications are metered separately from decisions and approvals.

Flow 1: SDK allow or deny​

Your code makes one authorization call. The SDK returns normally on allow and raises a typed denial on deny. There is no status mapping in your business handler.

{
"version": "v1",
"asset": { "id": "ast_e8f1a2c3" },
"operation_id": "refund-2026-002",
"transport": { "kind": "http", "http": { "method": "POST", "path": "/refunds" } },
"metadata": { "operation": "refund", "amount": 1200 }
}

Allow response (200):

{
"version": "v1",
"operation_id": "refund-2026-002",
"assetId": "ast_e8f1a2c3",
"decision": "allow",
"decisionId": "dec_1d2e3f40",
"reason": "no_matching_policy"
}

A deny is returned as 403 with decision: "deny" and the matching policy. The SDK raises a denial outcome; your application stops and reports the reason.

Flow 2: SDK approval with a bounded wait or explicit retry​

  1. Your application calls /v1/evaluate with a stable operation_id.
  2. The PDP records the decision and creates an approval. The response is 202:
{
"version": "v1",
"operation_id": "refund-2026-001",
"assetId": "ast_e8f1a2c3",
"decision": "approval_required",
"decisionId": "dec_9f2a1c4e",
"policyId": "pol_8a1b2c3d",
"approvalId": "apr_5c6d7e8f",
"approvalStatus": "pending",
"payload_hash": "sha256:9b1c...e4f0",
"approval_expires_at": "2026-09-13T11:15:00Z"
}
  1. Either the SDK waits a short, bounded time for a decision (interactive UX), or your application stores the pending approval and continues later.
  2. Once the approval is approved, retry /v1/evaluate with the same operation_id, asset, transport, and metadata, plus the original approval_id and payload_hash:
{
"version": "v1",
"asset": { "id": "ast_e8f1a2c3" },
"operation_id": "refund-2026-001",
"approval_id": "apr_5c6d7e8f",
"payload_hash": "sha256:9b1c...e4f0",
"transport": { "kind": "http" },
"metadata": { "operation": "refund", "amount": 9000 }
}

The first valid approved retry returns 200 with decision: "allow", and the approval moves to consumed. Run your business operation once for that allow. A later retry for the same approval is denied, so do not treat a retry as a new authorization.

A pending approval is not a failure. Rejected, expired, and revoked approvals do not authorize the operation.

Flow 3: Webhook-driven SDK resume​

  1. Register a webhook endpoint for the approval events you need (see Approvals & Webhooks).
  2. When the approval is resolved, OpenProdkt sends a signed event with a stable event ID.
  3. Your receiver verifies the signature and timestamp, deduplicates on the event ID, and then resumes the operation by retrying /v1/evaluate with the stored tuple. Delivery can repeat, so the handler must be idempotent.
  4. approval.rejected, approval.expired, and approval.revoked end the operation without execution.

Flow 4: Transparent proxy approval​

  1. The proxy receives a request for a registered asset whose policy requires approval.
  2. The request is blocked immediately. The upstream is not called, and the response is:
{
"code": "approval_required",
"retry_after_seconds": 30,
"operation_id": "refund-2026-001",
"approval_expires_at": "2026-09-13T11:15:00Z"
}

The response is HTTP 403 with Retry-After: 30 and Cache-Control: no-store. gRPC callers receive PERMISSION_DENIED. The proxy never returns 202 and never holds the request open.

  1. The CX or orchestrator tracks the approval through polling or the approval webhook. The protected application does not need the approval ID.
  2. After approval, the application resends the unchanged request through the proxy with the same operation_id and authorization context. No approval_id or payload_hash is required.
  3. The first redemption is allowed. Later attempts are denied because the approval is consumed.

A request without a stable operation_id cannot redeem an approval. Without a stable operation_id, a matching request fingerprint alone is not enough to redeem an approval.

What "single redemption" means​

  • Only the first successful redemption of an approved operation returns allow. Concurrent attempts result in one allow and the rest are denied.
  • This is a guarantee about the approval state only. It is not exactly-once execution in your upstream system.
  • If the allow response is lost after the approval is consumed, the approval is not redeemed again, and the upstream outcome may be unknown. Use the same operation_id as the idempotency key in your upstream calls, and reconcile ambiguous outcomes in your application.

Endpoint reference​

EndpointPurposeUsed byExample result
POST /v1/evaluateApplication authorization. operation_id is required on every call. An optional approval_id and payload_hash form the explicit retry tuple.SDKs and framework adapters200 allow, 202 pending, 403 deny
POST /v1/proxy/evaluateThe same contract for the transparent proxy adapter only. Requires the proxy.enabled entitlement. Never returns 202.Proxy adapter200 allow, 403 approval_required or deny
POST /v1/asset-discoveriesInventory and detection-point ingestion, independent of any authorization decision. Not required for normal application integration and never a substitute for /v1/evaluate.Detection points, CMDB and inventory importsObservation accepted for administrator review
POST /v1/playground/decisionConsole dry run with the same policy engine. A registered-asset run consumes one decision unit. It has no approval fields and never redeems an approval.Console and playground200 with the evaluated result

/v1/decision is no longer an application contract. Use /v1/evaluate for SDK traffic and /v1/proxy/evaluate for the proxy.

Architecture overview​

Application code calls the PEP. The PDP owns policy, approvals, and billing. MCP is a future protocol adapter with its own tool-call semantics. It is not a generic HTTP wrapper.

Next steps​