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
| Level | Who decides when to retry | Pending behavior | Retry |
|---|---|---|---|
SDK (/v1/evaluate) | Your application | The SDK may wait a bounded time, or return a pending approval for polling or webhooks | Explicit 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 request | Never waits. The request is blocked immediately with a challenge | Same 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 state | Result | Decision record | Billing |
|---|---|---|---|
| Unknown asset | allow with reason asset_not_registered | No | 0 units |
| Registered asset with no policies | allow with reason no_policies_assigned | Yes | 0 units |
| Registered asset with one or more policies | allow, deny, or approval_required | Yes | 1 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
- Your application calls
/v1/evaluatewith a stableoperation_id. - 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"
}
- Either the SDK waits a short, bounded time for a decision (interactive UX), or your application stores the pending approval and continues later.
- Once the approval is
approved, retry/v1/evaluatewith the sameoperation_id,asset,transport, andmetadata, plus the originalapproval_idandpayload_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
- Register a webhook endpoint for the approval events you need (see Approvals & Webhooks).
- When the approval is resolved, OpenProdkt sends a signed event with a stable event ID.
- Your receiver verifies the signature and timestamp, deduplicates on the event ID, and then
resumes the operation by retrying
/v1/evaluatewith the stored tuple. Delivery can repeat, so the handler must be idempotent. approval.rejected,approval.expired, andapproval.revokedend the operation without execution.
Flow 4: Transparent proxy approval
- The proxy receives a request for a registered asset whose policy requires approval.
- 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.
- The CX or orchestrator tracks the approval through polling or the approval webhook. The protected application does not need the approval ID.
- After approval, the application resends the unchanged request through the proxy with the same
operation_idand authorization context. Noapproval_idorpayload_hashis required. - 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_idas the idempotency key in your upstream calls, and reconcile ambiguous outcomes in your application.
Endpoint reference
| Endpoint | Purpose | Used by | Example result |
|---|---|---|---|
POST /v1/evaluate | Application authorization. operation_id is required on every call. An optional approval_id and payload_hash form the explicit retry tuple. | SDKs and framework adapters | 200 allow, 202 pending, 403 deny |
POST /v1/proxy/evaluate | The same contract for the transparent proxy adapter only. Requires the proxy.enabled entitlement. Never returns 202. | Proxy adapter | 200 allow, 403 approval_required or deny |
POST /v1/asset-discoveries | Inventory 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 imports | Observation accepted for administrator review |
POST /v1/playground/decision | Console 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 playground | 200 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
- Approvals & Webhooks for the approval lifecycle and webhook verification
- SDK Manual for language-specific helpers
- Transparent Proxy for proxy setup
- Developer Guide for status codes and quota responses