Run sample transfers through a draft or the enforced policy, read the per-rule trace, and keep a regression suite for every policy change.
Dry-run policy evaluation answers one question: what would the policy do with this request? It has no side effects. No transaction is created, no approval request is opened, and nothing is written to the audit log. You can call it as often as you like, against any policy, in any status.
With policy_id: that policy, whatever its status. Use this to test a draft before activation.
Without policy_id: the policy your organization currently enforces. Use this to check live behavior.
If you leave out policy_id and your organization has no enforced policy and no quorum, the result is "approved" with allowed: true and the reason “No active policy and no quorum”. That tells you nothing about your rules, so always pass policy_id when testing a draft.
Every field in the request is optional. A field you leave out counts as not applicable, so a condition on that field won’t match. Send the fields your rules depend on, with the values a real transfer would carry.
A rule on actor_type never matches when you leave actor_type out. If your rules treat API keys and dashboard users differently, send apikey or session in every test.
A readable explanation, useful in logs and test output.
trace shows the path. There is one entry per rule the engine reached, in order:
matched: false with reason and failed_condition tells you the first condition that stopped the rule, with the expected value and the actual value from your request. Later conditions in that rule were not checked.
terminal: true marks the rule that ended evaluation. Rules after it don’t appear.
When no rule matches, trace lists every rule with matched: false, and result is approved. trace is left out when your organization has nothing enforced and you don’t pass policy_id.
Policies change, and a rule order that was right last month can shadow a new rule. Keep a list of test cases next to your policy definition, and run all of them against every new draft before you activate it.
Run each case with the draft’s policy_id, and fail the check if any field in expect differs. Run it in CI when the policy definition lives in your repository, or by hand before you send a draft to quorum. Always include the boundary values of every threshold.
{"docsConfig":{"theme":"palm","$schema":"https://mintlify.com/docs.json","name":"Bitnob","description":"Bitnob is a financial infrastructure API for bitcoin, stablecoins, and local currency rails across Africa. Guides, API reference, and courses.","colors":{"primary":"#00A57F","light":"#00E4AF","dark":"#00795D"},"logo":{"light":"https://mintcdn.com/bitnob/1gUqO4UxgycXihsV/logo/light.svg?fit=max\u0026auto=format\u0026n=1gUqO4UxgycXihsV\u0026q=85\u0026s=d85bd0bfb85b47fa764bc1ff421b8ce8","dark":"https://mintcdn.com/bitnob/1gUqO4UxgycXihsV/logo/dark.svg?fit=max\u0026auto=format\u0026n=1gUqO4UxgycXihsV\u0026q=85\u0026s=e86a2938d369b4849b355e94a9aa39d4"},"favicon":"https://mintcdn.com/bitnob/_7Z9zBKHf2nvKkWh/favicon.svg?fit=max\u0026auto=format\u0026n=_7Z9zBKHf2nvKkWh\u0026q=85\u0026s=f807ad45c796566ee843893b0bc3345d","api":{"params":{"expanded":"closed"},"playground":{"display":"interactive"},"examples":{"languages":["curl","javascript","python","php","go","java"],"prefill":true}},"navbar":{"links":[{"href":"https://status.bitnob.com","label":"Status"},{"href":"https://app.bitnob.com","label":"Dashboard"}],"primary":{"type":"button","label":"Get Started","href":"https://bitnob.com"}},"footer":{"socials":{"x":"https://x.com/bitnob","github":"https://github.com/bitnob","website":"https://bitnob.com"}},"search":{"prompt":"Ask a question or search the Bitnob docs"},"seo":{"metatags":{"og:site_name":"Bitnob Docs","twitter:card":"summary_large_image","twitter:site":"@bitnob","twitter:creator":"@bitnob"},"organization":{"id":"https://bitnob.com/#organization","name":"Bitnob","url":"https://bitnob.com/","logo":"https://bitnob.com/bitnob-logo.png","sameAs":["https://x.com/bitnob","https://twitter.com/Bitnob_Official","https://linkedin.com/company/bitnob","https://github.com/bitnob","https://instagram.com/Bitnob","https://youtube.com/@bitnob","https://facebook.com/bitnob","https://tiktok.com/@bitnob"]},"indexing":"navigable"},"contextual":{"options":["copy","view","assistant","download-pdf","download-spec","chatgpt","claude","perplexity","grok","devin","windsurf","cursor","vscode","mcp","add-mcp","devin-mcp"],"display":"header"},"thumbnails":{"appearance":"dark","background":"https://mintcdn.com/bitnob/6uym4cOVBRGACTcE/images/og-background.png?fit=max\u0026auto=format\u0026n=6uym4cOVBRGACTcE\u0026q=85\u0026s=05d6033949a75937f6e325be7eb98d83"},"markdown":{"schema":true,"instructions":["Bitnob API requests authenticate with an `X-Auth-Client` API key header against https://api.bitnob.com.","Always use the sandbox environment for testing. Never put live API keys in sample code.","Money amounts are integers in the smallest unit of the currency (satoshis for BTC, cents for fiat). Never use floats.","Every state-changing request takes a client-supplied `reference` and must be treated as idempotent on retry.","Quotes expire. Re-quote rather than reusing a stale quote id."]},"styling":{"latex":false},"navigation":{"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"bitnob","hasAudioNarration":false,"actualSubdomain":"bitnob","customDomains":["www.bitnob.dev"],"gitSource":{"type":"github","owner":"bitnob","repo":"stealthdocs","deployBranch":"main","contentDirectory":"","isPrivate":true,"mountPath":"","label":""},"chroma":{"latestBuiltDeploymentHistoryId":"6aecadec07fe6b5b8129a2aa","collectionId":"a203871d-299d-4c5c-a71a-ab8b1036668b","liveDeploymentHistoryId":"6aecadec07fe6b5b8129a2aa","schemaVersion":"v3"},"feedback":{"thumbs":true,"agentFeedback":true},"entitlements":{"AI_CHAT":{"status":"DISABLED"}},"buildId":"6aeda9e8f8ed849a5c7d8668","clientVersion":"0.0.4074","searchFilterCounts":[{"language":"default","tag":"Docs","count":117},{"language":"default","tag":"Business API","count":110},{"language":"default","tag":"Learn","count":106},{"language":"default","tag":"Enterprise API","count":89},{"language":"default","tag":"Bitnob Business","count":82},{"language":"default","tag":"Courses","count":82},{"language":"default","tag":"Card issuing","count":44},{"language":"default","tag":"Guides","count":43},{"language":"default","tag":"Get started","count":35},{"language":"default","tag":"Bitnob Enterprise","count":35}]},"assistantConfig":{"enableAskAiButton":false,"enableStarterQuestions":false,"enableContextualStarterQuestions":false,"enableAskAiSearchBar":true},"basePath":"","hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"rbac-expansion","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"vite-origin","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-serve","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"live-agents","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"comment-mode","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"privacy":{"consentBanner":{"enabled":true}},"googleFontsInlined":false},"customCss":[{"filePath":"playground.css","content":".pg-shell{--pg-bg:rgb(var(--background-light));--pg-fg:rgb(var(--gray-900));--pg-muted:rgb(var(--gray-500));--pg-border:rgb(var(--gray-200));--pg-field-bg:rgb(var(--background-light));--pg-field-border:rgb(var(--gray-300));--pg-placeholder:rgb(var(--gray-400));--pg-hover:rgb(var(--gray-50));--pg-primary:rgb(var(--primary));color-scheme:light;margin:1.5rem 0;border:1px solid var(--pg-border);border-radius:0.875rem;background:var(--pg-bg);overflow:hidden}.dark .pg-shell{--pg-bg:rgb(var(--gray-900));--pg-fg:rgb(var(--gray-100));--pg-muted:rgb(var(--gray-400));--pg-border:rgb(var(--gray-800));--pg-field-bg:rgb(var(--background-dark));--pg-field-border:rgb(var(--gray-800));--pg-placeholder:rgb(var(--gray-500));--pg-hover:rgb(var(--gray-800));--pg-primary:rgb(var(--primary-light));color-scheme:dark}.pg-header{padding:1rem 1.25rem;border-bottom:1px solid var(--pg-border)}.pg-title{font-size:1rem;font-weight:600;color:var(--pg-fg)}.pg-subtitle{margin-top:0.125rem;font-size:0.875rem;color:var(--pg-muted)}.pg-body{padding:1.25rem;display:flex;flex-direction:column;gap:1rem}.pg-label{display:block;font-size:0.875rem;font-weight:500;color:var(--pg-fg);margin-bottom:0.375rem}.pg-input,.pg-select,.pg-textarea{width:100%;border-radius:0.5rem;border:1px solid var(--pg-field-border);background:var(--pg-field-bg);color:var(--pg-fg);padding:0.5rem 0.75rem;font-size:0.875rem;line-height:1.5}.pg-input,.pg-textarea{font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.pg-textarea{resize:vertical}.pg-input::placeholder,.pg-textarea::placeholder{color:var(--pg-placeholder)}.pg-input:focus,.pg-select:focus,.pg-textarea:focus{outline:none;border-color:var(--pg-primary);box-shadow:0 0 0 2px rgb(var(--primary)/0.35)}.pg-row{display:flex;flex-wrap:wrap;align-items:center;gap:0.5rem}.pg-grid{display:grid;grid-template-columns:1fr;gap:1rem}@media (min-width:640px){.pg-grid{grid-template-columns:2fr 1fr}}.pg-btn-primary,.pg-btn-secondary{display:inline-flex;align-items:center;justify-content:center;gap:0.375rem;height:2.25rem;border-radius:0.75rem;padding:0 0.75rem;font-size:0.875rem;font-weight:500;cursor:pointer;transition:opacity .15s,background-color .15s}.pg-btn-primary{background:rgb(var(--primary));color:#fff;border:1px solid transparent}.pg-btn-primary:hover{opacity:.8}.pg-btn-secondary{background:var(--pg-bg);color:var(--pg-fg);border:1px solid var(--pg-border)}.pg-btn-secondary:hover{background:var(--pg-hover)}.pg-btn-primary:disabled,.pg-btn-secondary:disabled{opacity:.5;cursor:not-allowed}.pg-meta{font-size:0.75rem;color:var(--pg-muted)}.pg-check{display:inline-flex;align-items:center;gap:0.5rem;font-size:0.875rem;color:var(--pg-fg)}.pg-note{border-radius:0.5rem;padding:0.5rem 0.75rem;font-size:0.875rem;border:1px solid}.pg-error{border-color:rgb(254 202 202);background:rgb(254 242 242);color:rgb(185 28 28)}.dark .pg-error{border-color:rgb(127 29 29);background:rgb(69 10 10);color:rgb(252 165 165)}.pg-ok{border-color:rgb(167 243 208);background:rgb(236 253 245);color:rgb(4 120 87)}.dark .pg-ok{border-color:rgb(6 78 59);background:rgb(2 44 34);color:rgb(110 231 183)}.pg-warn{border-color:rgb(253 230 138);background:rgb(255 251 235);color:rgb(180 83 9)}.dark .pg-warn{border-color:rgb(120 53 15);background:rgb(69 26 3);color:rgb(253 230 138)}.pg-grid2{display:grid;grid-template-columns:1fr;gap:1rem}@media (min-width:640px){.pg-grid2{grid-template-columns:1fr 1fr}}.pg-grid3{display:grid;grid-template-columns:1fr;gap:0.75rem}@media (min-width:640px){.pg-grid3{grid-template-columns:repeat(3,1fr)}}.pg-between{margin-top:0.5rem;display:flex;align-items:center;justify-content:space-between}.pg-end{margin-top:0.5rem;display:flex;align-items:center;justify-content:flex-end}.pg-wrap{display:flex;flex-wrap:wrap;gap:0.5rem 1rem;padding-top:0.375rem}.pg-strong{font-weight:500;margin-bottom:0.25rem}.pg-file{display:block;width:100%;font-size:0.875rem;color:var(--pg-fg)}.pg-file::file-selector-button{margin-right:0.75rem;height:2.25rem;border-radius:0.75rem;border:0;padding:0 0.75rem;font-size:0.875rem;font-weight:500;color:#fff;background:rgb(var(--primary));cursor:pointer}.pg-checklabel{display:flex;align-items:center;gap:0.5rem;font-size:0.875rem;color:var(--pg-fg);cursor:pointer}.pg-checklabel-tight{display:flex;align-items:center;gap:0.375rem;font-size:0.875rem;color:var(--pg-fg);cursor:pointer}.pg-inline-label{font-size:0.875rem;font-weight:500;color:var(--pg-fg)}.pg-endpad{display:flex;align-items:flex-end;padding-bottom:0.5rem}.pg-tablewrap{overflow-x:auto;border-radius:0.5rem;border:1px solid var(--pg-border)}.pg-table{width:100%;font-size:0.875rem;border-collapse:collapse}.pg-table th{border-bottom:1px solid var(--pg-border);text-align:left;color:var(--pg-muted);font-weight:500;padding:0.5rem 0.75rem}.pg-table td{padding:0.5rem 0.75rem;color:var(--pg-fg)}.pg-table tr+tr td{border-top:1px solid var(--pg-border)}.pg-result-row{display:flex;justify-content:space-between;gap:1rem;font-size:0.875rem;padding:0.25rem 0}.pg-result-key{color:var(--pg-muted)}.pg-result-val{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;color:var(--pg-fg);word-break:break-all}"}],"page":{"pagePath":"docs/platform/policies/test-rules-with-dry-run-evaluation","slug":"/docs/platform/policies/test-rules-with-dry-run-evaluation","pageMetadata":{"title":"Test policy rules with dry-run evaluation","sidebarTitle":"Test with dry runs","description":"Run sample transfers through a draft or the enforced policy, read the per-rule trace, and keep a regression suite for every policy change.","related":["/docs/platform/policies/how-policy-evaluation-works","/docs/platform/policies/change-an-enforced-policy","/docs/platform/policies/rule-reference"],"href":"/docs/platform/policies/test-rules-with-dry-run-evaluation"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"Run sample transfers through a draft or the enforced policy, read the per-rule trace, and keep a regression suite for every policy change.\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={a:`a`,code:`code`,li:`li`,p:`p`,pre:`pre`,span:`span`,strong:`strong`,tbody:`tbody`,td:`td`,th:`th`,thead:`thead`,tr:`tr`,ul:`ul`,..._provideComponents(),...props.components},{CodeBlock,Heading,Table,Warning}=_components;if(!CodeBlock)_missingMdxReference(`CodeBlock`,true);if(!Heading)_missingMdxReference(`Heading`,true);if(!Table)_missingMdxReference(`Table`,true);if(!Warning)_missingMdxReference(`Warning`,true);return _jsxs(_Fragment,{children:[_jsxs(_components.p,{children:[_jsx(_components.a,{href:`/api-reference/platform/policies/dry-run-policy-evaluation`,children:`Dry-run policy evaluation`}),` answers one question: what would the policy do with this request? It has no side effects. No transaction is created, no approval request is opened, and nothing is written to the audit log. You can call it as often as you like, against any policy, in any status.`]}),`\n`,_jsx(Heading,{level:`2`,id:`which-policy-is-evaluated`,children:`Which policy is evaluated`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsxs(_components.strong,{children:[`With `,_jsx(_components.code,{children:`policy_id`})]}),`: that policy, whatever its status. Use this to test a draft before activation.`]}),`\n`,_jsxs(_components.li,{children:[_jsxs(_components.strong,{children:[`Without `,_jsx(_components.code,{children:`policy_id`})]}),`: the policy your organization currently enforces. Use this to check live behavior.`]}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`If you leave out `,_jsx(_components.code,{children:`policy_id`}),` and your organization has no enforced policy and no quorum, the result is `,_jsx(_components.code,{children:`\"approved\"`}),` with `,_jsx(_components.code,{children:`allowed: true`}),` and the reason “No active policy and no quorum”. That tells you nothing about your rules, so always pass `,_jsx(_components.code,{children:`policy_id`}),` when testing a draft.`]}),`\n`,_jsx(Heading,{level:`2`,id:`build-the-request`,children:`Build the request`}),`\n`,_jsx(_components.p,{children:`Every field in the request is optional. A field you leave out counts as not applicable, so a condition on that field won’t match. Send the fields your rules depend on, with the values a real transfer would carry.`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`12`,language:`json`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`json`,children:_jsxs(_components.code,{language:`json`,numberOfLines:`12`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`{`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"policy_id\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"f47ac10b-58cc-4372-a567-0e02b2c3d479\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"wallet_id\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"chain\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"ethereum\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"network\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"sepolia\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"asset_symbol\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"USDC\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"amount\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"15000\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"amount_usd\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"15000\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"to_address\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"0x2222222222222222222222222222222222222222\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"actor_type\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"apikey\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"is_automated\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:`false`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`]})})}),`\n`,_jsx(Warning,{children:_jsxs(_components.p,{children:[`A rule on `,_jsx(_components.code,{children:`actor_type`}),` never matches when you leave `,_jsx(_components.code,{children:`actor_type`}),` out. If your rules treat API keys and dashboard users differently, send `,_jsx(_components.code,{children:`apikey`}),` or `,_jsx(_components.code,{children:`session`}),` in every test.`]})}),`\n`,_jsx(Heading,{level:`2`,id:`read-the-response`,children:`Read the response`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`31`,language:`json`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`json`,children:_jsxs(_components.code,{language:`json`,numberOfLines:`31`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`{`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"result\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"awaiting_approval\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"allowed\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:`false`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"policy_id\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"f47ac10b-58cc-4372-a567-0e02b2c3d479\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"rule_id\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"7c9e6679-7425-40de-944b-e07fc1f90ae7\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"reason\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"Approval required by policy Transfer limits / rule Approve over $10,000\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"requires_approval\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:`true`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"required_approvals\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`1`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"expiry_hours\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`24`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"trace\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: [`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"rule_index\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`0`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"rule_name\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"Block over $50,000\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"matched\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:`false`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"reason\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"amount_usd: 15000 not > 50000\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"failed_condition\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"field\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"amount_usd\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"operator\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"greater_than\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"expected\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"50000\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"actual\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"15000\"`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` },`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"rule_index\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`1`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"rule_name\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"Approve over $10,000\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"matched\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:`true`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"terminal\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:`true`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"action\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"require_approval\"`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` ]`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`]})})}),`\n`,_jsx(_components.p,{children:`The top-level fields are the decision:`}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Field`}),_jsx(_components.th,{children:`Meaning`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`allowed`})}),_jsx(_components.td,{children:`Whether the request would go ahead without being held or blocked.`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`result`})}),_jsxs(_components.td,{children:[`How the decision was reached. See `,_jsx(_components.a,{href:`/docs/platform/policies/rule-reference#evaluation-results`,children:`Evaluation results`}),`.`]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`rule_id`})}),_jsx(_components.td,{children:`The rule that decided it, if one matched.`})]}),_jsxs(_components.tr,{children:[_jsxs(_components.td,{children:[_jsx(_components.code,{children:`requires_approval`}),`, `,_jsx(_components.code,{children:`required_approvals`}),`, `,_jsx(_components.code,{children:`expiry_hours`})]}),_jsxs(_components.td,{children:[`Set when the deciding rule is `,_jsx(_components.code,{children:`require_approval`}),`.`]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`delay_minutes`})}),_jsxs(_components.td,{children:[`Set when the deciding rule is `,_jsx(_components.code,{children:`delay`}),`.`]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`reason`})}),_jsx(_components.td,{children:`A readable explanation, useful in logs and test output.`})]})]})]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.code,{children:`trace`}),` shows the path. There is one entry per rule the engine reached, in order:`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`matched: false`}),` with `,_jsx(_components.code,{children:`reason`}),` and `,_jsx(_components.code,{children:`failed_condition`}),` tells you the first condition that stopped the rule, with the `,_jsx(_components.code,{children:`expected`}),` value and the `,_jsx(_components.code,{children:`actual`}),` value from your request. Later conditions in that rule were not checked.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`terminal: true`}),` marks the rule that ended evaluation. Rules after it don’t appear.`]}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`When no rule matches, `,_jsx(_components.code,{children:`trace`}),` lists every rule with `,_jsx(_components.code,{children:`matched: false`}),`, and `,_jsx(_components.code,{children:`result`}),` is `,_jsx(_components.code,{children:`approved`}),`. `,_jsx(_components.code,{children:`trace`}),` is left out when your organization has nothing enforced and you don’t pass `,_jsx(_components.code,{children:`policy_id`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`debug-a-surprising-result`,children:`Debug a surprising result`}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Symptom`}),_jsx(_components.th,{children:`Likely cause`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsxs(_components.td,{children:[`A rule you expected never appears in `,_jsx(_components.code,{children:`trace`})]}),_jsx(_components.td,{children:`An earlier rule matched first. Move your rule up, or narrow the earlier one.`})]}),_jsxs(_components.tr,{children:[_jsxs(_components.td,{children:[_jsx(_components.code,{children:`failed_condition.actual`}),` is missing`]}),_jsxs(_components.td,{children:[`You didn’t send that field, or it couldn’t be resolved. For `,_jsx(_components.code,{children:`amount_usd`}),`, `,_jsx(_components.code,{children:`reason`}),` says “resolution error”. Send `,_jsx(_components.code,{children:`amount_usd`}),` explicitly in tests.`]})]}),_jsxs(_components.tr,{children:[_jsxs(_components.td,{children:[_jsx(_components.code,{children:`actual`}),` and `,_jsx(_components.code,{children:`expected`}),` look equal but the rule failed`]}),_jsxs(_components.td,{children:[`Check the operator. `,_jsx(_components.code,{children:`greater_than`}),` excludes the boundary, `,_jsx(_components.code,{children:`greater_than_or_equal`}),` includes it.`]})]}),_jsxs(_components.tr,{children:[_jsxs(_components.td,{children:[_jsx(_components.code,{children:`in`}),` against a list never matches`]}),_jsxs(_components.td,{children:[`Values are compared exactly. Check case and the identifier format, for example `,_jsx(_components.code,{children:`tron`}),` and not `,_jsx(_components.code,{children:`TRX`}),` for `,_jsx(_components.code,{children:`chain`}),`.`]})]}),_jsxs(_components.tr,{children:[_jsxs(_components.td,{children:[`Every request returns `,_jsx(_components.code,{children:`approved`}),` with “No active policy”`]}),_jsxs(_components.td,{children:[`You left out `,_jsx(_components.code,{children:`policy_id`}),` and nothing is enforced yet. Pass the draft’s `,_jsx(_components.code,{children:`policy_id`}),`.`]})]}),_jsxs(_components.tr,{children:[_jsxs(_components.td,{children:[`Every request returns `,_jsx(_components.code,{children:`approved`}),` with all rules unmatched`]}),_jsxs(_components.td,{children:[`Your conditions use fields you aren’t sending. Check `,_jsx(_components.code,{children:`failed_condition`}),` on each rule.`]})]})]})]}),`\n`,_jsx(Heading,{level:`2`,id:`keep-a-regression-suite`,children:`Keep a regression suite`}),`\n`,_jsx(_components.p,{children:`Policies change, and a rule order that was right last month can shadow a new rule. Keep a list of test cases next to your policy definition, and run all of them against every new draft before you activate it.`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`6`,language:`json`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`json`,children:_jsxs(_components.code,{language:`json`,numberOfLines:`6`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`[`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` { `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"name\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"small payout passes\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"request\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: { `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"amount_usd\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"500\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }, `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"expect\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: { `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"result\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"approved\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"allowed\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:`true`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` } },`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` { `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"name\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"mid payout held\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"request\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: { `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"amount_usd\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"15000\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }, `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"expect\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: { `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"result\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"awaiting_approval\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"required_approvals\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`1`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` } },`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` { `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"name\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"large payout blocked\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"request\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: { `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"amount_usd\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"60000\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }, `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"expect\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: { `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"result\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"rejected\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"allowed\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:`false`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` } },`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` { `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"name\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"boundary is not held\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"request\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: { `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"amount_usd\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"10000\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }, `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"expect\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: { `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"result\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"approved\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` } }`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`]`})}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[`Run each case with the draft’s `,_jsx(_components.code,{children:`policy_id`}),`, and fail the check if any field in `,_jsx(_components.code,{children:`expect`}),` differs. Run it in CI when the policy definition lives in your repository, or by hand before you send a draft to quorum. Always include the boundary values of every threshold.`]})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"Test policy rules with dry-run evaluation","sidebarTitle":"Test with dry runs","description":"Run sample transfers through a draft or the enforced policy, read the per-rule trace, and keep a regression suite for every policy change.","related":["/docs/platform/policies/how-policy-evaluation-works","/docs/platform/policies/change-an-enforced-policy","/docs/platform/policies/rule-reference"],"href":"/docs/platform/policies/test-rules-with-dry-run-evaluation"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"Which policy is evaluated","slug":"which-policy-is-evaluated","depth":2,"children":[]},{"title":"Build the request","slug":"build-the-request","depth":2,"children":[]},{"title":"Read the response","slug":"read-the-response","depth":2,"children":[]},{"title":"Debug a surprising result","slug":"debug-a-surprising-result","depth":2,"children":[]},{"title":"Keep a regression suite","slug":"keep-a-regression-suite","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":["/_mintlify/custom/bitnob/a5987023060b539e/test-playground.js"],"subdomain":"bitnob","siteName":"Bitnob","title":"Test policy rules with dry-run evaluation - Bitnob","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-11-06T02:20:04.902Z","originalFileLocation":"docs/platform/policies/test-rules-with-dry-run-evaluation.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Run sample transfers through a draft or the enforced policy, read the per-rule trace, and keep a regression suite for every policy change.\">\u003cmeta data-mint-head name=\"application-name\" content=\"Bitnob\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/bitnob/eBFTVQiF9mXbjiUl/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/bitnob/eBFTVQiF9mXbjiUl/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/bitnob/eBFTVQiF9mXbjiUl/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/bitnob/eBFTVQiF9mXbjiUl/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/bitnob/eBFTVQiF9mXbjiUl/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/bitnob/eBFTVQiF9mXbjiUl/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/bitnob/eBFTVQiF9mXbjiUl/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/bitnob/eBFTVQiF9mXbjiUl/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/bitnob/eBFTVQiF9mXbjiUl/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Test policy rules with dry-run evaluation - Bitnob\">\u003cmeta data-mint-head property=\"og:description\" content=\"Run sample transfers through a draft or the enforced policy, read the per-rule trace, and keep a regression suite for every policy change.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Bitnob Docs\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://www.bitnob.dev/docs/platform/policies/test-rules-with-dry-run-evaluation\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://bitnob.mintlify.site/_mintlify/api/og/v2?division=Guides\u0026amp;title=Test+policy+rules+with+dry-run+evaluation\u0026amp;description=Run+sample+transfers+through+a+draft+or+the+enforced+policy%2C+read+the+per-rule+trace%2C+and+keep+a+regression+suite+for+every+policy+change.\u0026amp;theme=1bbb91a73b5fc150fde1eea2\u0026amp;signature=a40d6d05bed7327bdbe30e7fc5a4fd06830cd7988f5f255dcce4e3fa9f4c7817\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Test policy rules with dry-run evaluation - Bitnob\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Run sample transfers through a draft or the enforced policy, read the per-rule trace, and keep a regression suite for every policy change.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://bitnob.mintlify.site/_mintlify/api/og/v2?division=Guides\u0026amp;title=Test+policy+rules+with+dry-run+evaluation\u0026amp;description=Run+sample+transfers+through+a+draft+or+the+enforced+policy%2C+read+the+per-rule+trace%2C+and+keep+a+regression+suite+for+every+policy+change.\u0026amp;theme=1bbb91a73b5fc150fde1eea2\u0026amp;signature=a40d6d05bed7327bdbe30e7fc5a4fd06830cd7988f5f255dcce4e3fa9f4c7817\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/bitnob/eBFTVQiF9mXbjiUl/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Bitnob\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#00A57F\">\u003cmeta data-mint-head name=\"twitter:creator\" content=\"@bitnob\">\u003clink data-mint-head rel=\"canonical\" href=\"https://www.bitnob.dev/docs/platform/policies/test-rules-with-dry-run-evaluation\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/docs/platform/policies/test-rules-with-dry-run-evaluation.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://bitnob.com/#organization\",\"name\":\"Bitnob\",\"url\":\"https://bitnob.com/\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://bitnob.com/bitnob-logo.png\"},\"sameAs\":[\"https://x.com/bitnob\",\"https://twitter.com/Bitnob_Official\",\"https://linkedin.com/company/bitnob\",\"https://github.com/bitnob\",\"https://instagram.com/Bitnob\",\"https://youtube.com/@bitnob\",\"https://facebook.com/bitnob\",\"https://tiktok.com/@bitnob\"]},{\"@type\":\"WebSite\",\"@id\":\"https://www.bitnob.dev#website\",\"name\":\"Bitnob\",\"url\":\"https://www.bitnob.dev\",\"publisher\":{\"@id\":\"https://bitnob.com/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://www.bitnob.dev/docs/platform/policies/test-rules-with-dry-run-evaluation#webpage\",\"url\":\"https://www.bitnob.dev/docs/platform/policies/test-rules-with-dry-run-evaluation\",\"name\":\"Test policy rules with dry-run evaluation\",\"description\":\"Run sample transfers through a draft or the enforced policy, read the per-rule trace, and keep a regression suite for every policy change.\",\"dateModified\":\"2026-11-06T02:20:04.902Z\",\"isPartOf\":{\"@id\":\"https://www.bitnob.dev#website\"},\"breadcrumb\":{\"@id\":\"https://www.bitnob.dev/docs/platform/policies/test-rules-with-dry-run-evaluation#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://www.bitnob.dev/docs/platform/policies/test-rules-with-dry-run-evaluation#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Policies\",\"item\":\"https://www.bitnob.dev/docs/platform/policies/overview\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Guides\",\"item\":\"https://www.bitnob.dev/docs/platform/policies/require-approval-for-high-value-transfers\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Test policy rules with dry-run evaluation\",\"item\":\"https://www.bitnob.dev/docs/platform/policies/test-rules-with-dry-run-evaluation\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://www.bitnob.dev/docs/platform/policies/test-rules-with-dry-run-evaluation#article\",\"headline\":\"Test policy rules with dry-run evaluation\",\"name\":\"Test policy rules with dry-run evaluation\",\"description\":\"Run sample transfers through a draft or the enforced policy, read the per-rule trace, and keep a regression suite for every policy change.\",\"url\":\"https://www.bitnob.dev/docs/platform/policies/test-rules-with-dry-run-evaluation\",\"mainEntityOfPage\":{\"@id\":\"https://www.bitnob.dev/docs/platform/policies/test-rules-with-dry-run-evaluation#webpage\"},\"dateModified\":\"2026-11-06T02:20:04.902Z\",\"publisher\":{\"@id\":\"https://bitnob.com/#organization\"},\"isPartOf\":{\"@id\":\"https://www.bitnob.dev#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"Bitnob\",\"creator\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","siteName":"Bitnob","nav":{"global":null,"tabs":[{"tab":"Home","icon":"house","pages":[{"title":"Home","href":""}]},{"tab":"Docs","icon":"book-open","dropdowns":[{"dropdown":"Bitnob Business","icon":"bolt","description":"Payouts, cards, trading, and virtual accounts.","groups":[{"group":"Get started","icon":"rocket","expanded":true,"pages":[{"title":"Introduction to the Bitnob APIs","sidebarTitle":"Introduction","href":"/docs/getting-started/overview"},{"title":"Set up your account","href":"/docs/getting-started/account-setup"},{"title":"Bitnob Business API quickstart","sidebarTitle":"Quickstart","href":"/docs/getting-started/quickstart"},{"group":"Concepts","pages":[{"title":"Core concepts and architecture","href":"/docs/getting-started/core-concepts-and-architecture"},{"title":"Currencies and amounts","href":"/docs/getting-started/core-concepts-and-architecture/currencies-and-amounts"},{"title":"Fees and limits by product","sidebarTitle":"Fees and limits","href":"/docs/getting-started/fees-and-limits"},{"title":"Which KYC endpoint to use","sidebarTitle":"Which KYC endpoint","href":"/docs/getting-started/which-kyc-endpoint"}]},{"group":"Build reliably","pages":[{"title":"API keys and credential security","href":"/docs/getting-started/api-best-practices/api-keys-and-credentials"},{"title":"Idempotency and references","href":"/docs/getting-started/api-best-practices/idempotency-and-reference-integrity"},{"title":"Webhooks and event handling","href":"/docs/getting-started/api-best-practices/webhook-best-practices"},{"title":"Errors and retries","href":"/docs/getting-started/api-best-practices/errors-and-retries"},{"title":"Quote lifecycle and expiry","href":"/docs/getting-started/api-best-practices/quote-expiry-and-transaction-windows"},{"title":"Test in sandbox","href":"/docs/getting-started/api-best-practices/simulating-flows-and-testing-in-sandbox"},{"title":"Observability, logging, and traceability","href":"/docs/getting-started/api-best-practices/observability-logging-and-traceability"}]}]},{"group":"Bitcoin","icon":"bitcoin","pages":[{"title":"Bitcoin and Lightning on Bitnob","sidebarTitle":"Overview","href":"/docs/bitcoin/overview"},{"group":"Concepts","pages":[{"title":"LNURL and Lightning addresses","href":"/docs/bitcoin/lnurl-and-lightning-addresses"}]},{"group":"Get started","pages":[{"title":"Send bitcoin on-chain or over Lightning","href":"/docs/bitcoin/send-bitcoin"}]},{"group":"Guides","pages":[{"title":"Issue addresses and Lightning invoices","href":"/docs/bitcoin/issuing-bitcoin-addresses-and-lightning-invoices"},{"title":"Test Lightning payments in sandbox","sidebarTitle":"Test Lightning in sandbox","href":"/docs/bitcoin/test-lightning-in-sandbox"}]},{"group":"Reference","pages":[{"title":"Confirmations and webhook events","href":"/docs/bitcoin/confirmations-and-webhook-events"}]}]},{"group":"Stablecoins","icon":"coins","pages":[{"title":"Stablecoins on Bitnob","sidebarTitle":"Overview","href":"/docs/stablecoins/overview"},{"group":"Concepts","pages":[{"title":"How stablecoins work on Bitnob","href":"/docs/stablecoins/key-concepts"},{"title":"Why multiple chains","href":"/docs/stablecoins/why-support-stablecoins-on-multiple-chains"}]},{"group":"Get started","pages":[{"title":"Accept USDT and settle in naira","href":"/docs/stablecoins/accept-usdt-and-settle-in-naira"}]},{"group":"Guides","pages":[{"title":"Set up for stablecoins","href":"/docs/stablecoins/getting-started-with-stablecoins"},{"title":"Issue deposit addresses","href":"/docs/stablecoins/issuing-stablecoin-addresses"},{"title":"Receive deposits","href":"/docs/stablecoins/receiving-stablecoin-deposits"},{"title":"Send stablecoins","href":"/docs/stablecoins/sending-stablecoins"},{"title":"Transfer between wallets","href":"/docs/stablecoins/internal-wallet-to-wallet-transfers"},{"title":"Receive stablecoin webhooks","href":"/docs/stablecoins/webhooks"},{"title":"Handle transfer failures","href":"/docs/stablecoins/error-handling-and-failure-scenarios"},{"title":"Reconcile balances","href":"/docs/stablecoins/stablecoin-reconciliation-and-ledger-integrity-guide"}]},{"group":"Reference","pages":[{"title":"Stablecoin address webhook events","sidebarTitle":"Address webhook events","href":"/docs/stablecoins/address-webhook-events"},{"title":"Withdrawal webhook events","sidebarTitle":"Withdrawal webhook events","href":"/docs/stablecoins/withdrawal-webhook-events"},{"title":"Supported stablecoin chains and tokens","sidebarTitle":"Supported chains","href":"/docs/stablecoins/supported-chains"}]}]},{"group":"Trading","icon":"arrow-right-arrow-left","pages":[{"title":"Trading and currency conversion","sidebarTitle":"Overview","href":"/docs/trading/overview"},{"group":"Concepts","pages":[{"title":"How trading works","href":"/docs/trading/how-trading-works"}]},{"group":"Get started","pages":[{"title":"Swap bitcoin to USDT","href":"/docs/trading/swap-bitcoin-to-usdt"}]},{"group":"Guides","pages":[{"title":"Create a quote","href":"/docs/trading/create-quote"},{"title":"Execute a trade","href":"/docs/trading/execute-trade"},{"title":"Track orders and history","href":"/docs/trading/trade-status-and-history"},{"title":"Receive trade webhooks","href":"/docs/trading/trade-webhooks"},{"title":"Handle trading failures","href":"/docs/trading/error-handling-patterns"}]},{"group":"Reference","pages":[{"title":"Trade statuses and webhook events","sidebarTitle":"Statuses and webhook events","href":"/docs/trading/statuses-and-webhook-events"}]}]},{"group":"Payouts","icon":"money-bill-transfer","pages":[{"title":"Payouts to bank accounts and mobile money","sidebarTitle":"Overview","href":"/docs/payouts/overview"},{"group":"Concepts","pages":[{"title":"How payouts settle","href":"/docs/payouts/settlement-models"},{"title":"The payout lifecycle","href":"/docs/payouts/payouts-lifecycle"}]},{"group":"Get started","pages":[{"title":"Send your first payout","href":"/docs/payouts/send-your-first-payout"}]},{"group":"Guides","pages":[{"title":"Validate a beneficiary","href":"/docs/payouts/validate-a-beneficiary"},{"title":"Send a SWIFT payout","href":"/docs/payouts/swift-payout"},{"title":"Receive payout webhooks","href":"/docs/payouts/webhook-payout"},{"title":"Handle payout failures","href":"/docs/payouts/error-handling"},{"title":"Payouts API integration guide","href":"/api-reference/payouts/usage-example"},{"title":"The Trip timeline","href":"/docs/payouts/understanding-trip-timeline"},{"title":"Payout incident postmortem template","href":"/docs/payouts/payout-incident-postmortem"},{"title":"Troubleshooting: payout stuck in pending","href":"/docs/payouts/troubleshoot-payout-stuck"},{"title":"Troubleshooting: webhooks not received","href":"/docs/payouts/troubleshoot-webhooks-not-received"}]},{"group":"Reference","pages":[{"title":"Payout statuses and webhook events","sidebarTitle":"Statuses and webhook events","href":"/docs/payouts/statuses-and-webhook-events"},{"title":"Payout webhook events","sidebarTitle":"Webhook events","href":"/docs/payouts/webhook-events"},{"title":"Supported currencies and rails","href":"/docs/payouts/supported-currencies"},{"group":"Corridors","pages":[{"title":"Corridor behavior","href":"/docs/payouts/corridor-specific-behavior"},{"title":"Nigeria","href":"/docs/payouts/corridor-specific-behavior/nigeria-payout"},{"title":"Ghana","href":"/docs/payouts/corridor-specific-behavior/ghana-payout"},{"title":"Kenya","href":"/docs/payouts/corridor-specific-behavior/kenya-payout"}]},{"title":"Payout glossary","sidebarTitle":"Glossary","href":"/docs/payouts/glossary-terms"}]}]},{"group":"Card issuing","icon":"credit-card","pages":[{"title":"Virtual card issuing on Bitnob","sidebarTitle":"Overview","href":"/docs/card-issuing/overview"},{"group":"Concepts","pages":[{"title":"How card issuance works","href":"/docs/card-issuing/card-issuance"}]},{"group":"Get started","pages":[{"title":"Issue your first card","href":"/docs/card-issuing/issue-your-first-card"}]},{"group":"Guides","pages":[{"title":"Verify cardholders with Card KYC","sidebarTitle":"Card KYC","href":"/docs/card-issuing/card-kyc"},{"title":"Fund a card","href":"/docs/card-issuing/card-funding"},{"title":"Freeze, unfreeze, or terminate a card","href":"/docs/card-issuing/card-status-management"},{"title":"Set card spending limits","sidebarTitle":"Set spending limits","href":"/docs/card-issuing/spending-limits"},{"title":"Monitor card transactions","href":"/docs/card-issuing/transaction-monitoring"},{"title":"Receive card webhooks","href":"/docs/card-issuing/receive-card-webhooks"},{"title":"Decrypt card secured details","sidebarTitle":"Decrypt card details","href":"/docs/card-issuing/decrypt-card-details"}]},{"group":"Reference","pages":[{"title":"Webhook events","href":"/docs/card-issuing/webhooks"},{"title":"Virtual card webhook events","sidebarTitle":"Webhook payloads","href":"/docs/card-issuing/webhook-payloads"},{"title":"Fees and decline rules","href":"/docs/card-issuing/card-fees"},{"title":"Virtual card glossary","sidebarTitle":"Glossary","href":"/docs/card-issuing/virtual-card-glossary"}]}]},{"group":"Virtual accounts","icon":"building-columns","pages":[{"title":"NGN virtual accounts on Bitnob","sidebarTitle":"Overview","href":"/docs/virtual-accounts/overview"},{"group":"Get started","pages":[{"title":"Set up NGN virtual accounts","sidebarTitle":"Set up virtual accounts","href":"/docs/virtual-accounts/set-up-virtual-accounts"},{"title":"Virtual account deposit webhook","sidebarTitle":"Deposit webhook","href":"/docs/virtual-accounts/deposit-webhook"}]}]}]},{"dropdown":"Bitnob Enterprise","icon":"wallet","description":"Policy-governed wallets.","groups":[{"group":"Get started","icon":"rocket","expanded":true,"pages":[{"title":"Bitnob Enterprise API overview","sidebarTitle":"Introduction","href":"/docs/platform/overview"},{"title":"Set up your Bitnob Enterprise account","sidebarTitle":"Set up your account","href":"/docs/platform/account-setup"},{"title":"Bitnob Enterprise API quickstart","sidebarTitle":"Quickstart","href":"/docs/platform/quickstart"},{"group":"Concepts","pages":[{"title":"Bitnob Enterprise core concepts","sidebarTitle":"Core concepts","href":"/docs/platform/core-concepts"}]},{"group":"Build reliably","pages":[{"title":"Bitnob Enterprise API best practices","sidebarTitle":"Best practices","href":"/docs/platform/best-practices"}]}]},{"group":"Policies","icon":"shield-check","pages":[{"title":"Transaction policies on Bitnob Enterprise","sidebarTitle":"Overview","href":"/docs/platform/policies/overview"},{"group":"Concepts","pages":[{"title":"How Bitnob Enterprise evaluates policy rules","sidebarTitle":"How evaluation works","href":"/docs/platform/policies/how-policy-evaluation-works"},{"title":"Policy lifecycle and quorum approval","sidebarTitle":"Lifecycle and quorum","href":"/docs/platform/policies/policy-lifecycle-and-quorum"}]},{"group":"Get started","pages":[{"title":"Write and activate your first Enterprise policy","sidebarTitle":"Write your first policy","href":"/docs/platform/policies/write-and-activate-your-first-policy"}]},{"group":"Guides","pages":[{"title":"Require approval for high-value transfers","sidebarTitle":"Require approval","href":"/docs/platform/policies/require-approval-for-high-value-transfers"},{"title":"Delay large transfers with a policy time lock","sidebarTitle":"Add a time lock","description":"Use a delay rule to hold large or unusual transfers for a fixed window before they execute, giving your team time to catch a bad one.","href":"/docs/platform/policies/delay-large-transfers-with-a-time-lock"},{"title":"Test policy rules with dry-run evaluation","sidebarTitle":"Test with dry runs","href":"/docs/platform/policies/test-rules-with-dry-run-evaluation"},{"title":"Change an enforced Bitnob Enterprise policy","sidebarTitle":"Change a live policy","description":"Enforced policies are immutable. Copy the live rules into a new draft, test the difference, and replace the policy through quorum.","href":"/docs/platform/policies/change-an-enforced-policy"},{"title":"Handle transactions held or rejected by policy","sidebarTitle":"Handle held transactions","href":"/docs/platform/policies/handle-held-and-rejected-transactions"}]},{"group":"Reference","pages":[{"title":"Bitnob Enterprise policy rule reference","sidebarTitle":"Rule reference","href":"/docs/platform/policies/rule-reference"},{"title":"Policy statuses, errors, and webhook events","sidebarTitle":"Statuses and events","href":"/docs/platform/policies/statuses-and-webhook-events"}]}]},{"group":"Gas sponsorship","icon":"gas-pump","pages":[{"title":"Gas sponsorship on Bitnob Enterprise","sidebarTitle":"Overview","href":"/docs/platform/gas-sponsorship/overview"},{"group":"Concepts","pages":[{"title":"How Bitnob Enterprise gas stations work","sidebarTitle":"How gas stations work","href":"/docs/platform/gas-sponsorship/how-gas-stations-work"},{"title":"How Bitnob sponsored transfers work","sidebarTitle":"How sponsored transfers work","href":"/docs/platform/gas-sponsorship/how-sponsored-transfers-work"},{"title":"What users sign for a sponsored transfer, by chain","sidebarTitle":"Signing by chain","href":"/docs/platform/gas-sponsorship/signing-by-chain"}]},{"group":"Get started","pages":[{"title":"Set up a gas station for your Enterprise wallets","sidebarTitle":"Set up a gas station","href":"/docs/platform/gas-sponsorship/set-up-a-gas-station"},{"title":"Send your first sponsored transfer on Solana","sidebarTitle":"Send your first transfer","href":"/docs/platform/gas-sponsorship/send-your-first-sponsored-transfer"}]},{"group":"Guides","pages":[{"title":"Sign sponsored transfers on EVM chains","sidebarTitle":"Sign on EVM chains","href":"/docs/platform/gas-sponsorship/sign-on-evm-chains"},{"title":"Sign sponsored USDT transfers on Tron","sidebarTitle":"Sign on Tron","href":"/docs/platform/gas-sponsorship/sign-on-tron"},{"title":"Charge your own fee on sponsored transfers","sidebarTitle":"Charge a partner fee","href":"/docs/platform/gas-sponsorship/charge-a-partner-fee"},{"title":"Sweep a full stablecoin balance with gross mode","sidebarTitle":"Sweep a full balance","href":"/docs/platform/gas-sponsorship/sweep-a-full-balance"},{"title":"Handle sponsored transfer failures and expiry","sidebarTitle":"Handle failures","href":"/docs/platform/gas-sponsorship/handle-failures-and-expiry"}]},{"group":"Reference","pages":[{"title":"Gas station fields, health, and webhook events","sidebarTitle":"Gas station reference","href":"/docs/platform/gas-sponsorship/gas-station-reference"},{"title":"Sponsored transfer statuses, errors, and tracking","sidebarTitle":"Sponsored transfer statuses","href":"/docs/platform/gas-sponsorship/statuses-errors-and-events"}]}]},{"group":"Bitcoin","icon":"bitcoin","pages":[{"group":"Concepts","pages":[{"title":"Custody models","href":"/docs/bitcoin/custody-models"},{"title":"UTXO management","href":"/docs/bitcoin/utxo-management-introduction"},{"title":"Fees and confirmation strategy","href":"/docs/bitcoin/fee-market-and-transaction-strategies"}]},{"group":"Guides","pages":[{"title":"Run business-managed custody","href":"/docs/bitcoin/business-managed-non-custodial-bitcoin-wallets"},{"title":"Build self-custodial wallets","href":"/docs/bitcoin/user-managed-self-custodial-wallets"}]}]},{"group":"Use cases","icon":"briefcase","pages":[{"title":"Exchange integration guide","href":"/docs/platform/exchange-integration-guide"}]}]}]},{"tab":"Business API","icon":"code","pages":[{"title":"Business API","href":"/api-reference/authentication/authentication"}]},{"tab":"Enterprise API","icon":"wallet","pages":[{"title":"Enterprise API","href":"/docs/platform/authentication"}]},{"tab":"Playground","icon":"flask","pages":[{"title":"Playground","href":"/docs/playground/overview"}]},{"tab":"Learn","icon":"graduation-cap","pages":[{"title":"Learn","href":"/learn/overview"}]},{"tab":"Changelog","icon":"clock-rotate-left","pages":[{"title":"Changelog","href":"/changelog"}]}]},"basePath":"","title":"Test policy rules with dry-run evaluation - Bitnob","buildId":"dpl_BLQvU86QFwq3AhPofSTw6q8dGWKm","deploymentId":"dpl_BLQvU86QFwq3AhPofSTw6q8dGWKm","dynamics":[],"chunks":[]}