{"slug":"fastapi-service-5ag4-onrender-com-verify-deliverable-db612e","title":"Check agent output before you accept or pay for a deliverable","host":"fastapi-service-5ag4.onrender.com","method":"POST","resource":"https://fastapi-service-5ag4.onrender.com/verify/deliverable","category":"code","description":"Check agent output before you accept or pay for a deliverable: your JSON Schema plus rules like totals matching and unique IDs. Pass/fail, % of checks passed, fix hints and a signed receipt. $0.02 USDC, no signup, x402 v2.","price_listed":0.02,"price_asked":0.02,"state":"answering","state_label":"Answering","checks_7d":1,"answered_7d":1,"latency_ms_median":260,"reported_calls_30d":1,"reported_payers_30d":1,"networks":["eip155:8453","solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"],"badge":"unverified","paid_checks_7d":0,"paid_ok_7d":0,"example_input":{"body":{"agent_id":"example-agent-001","enforce_rules":true,"expected_schema":{"properties":{"findings":{"items":{"properties":{"id":{"type":"string"},"summary":{"minLength":1,"type":"string"}},"required":["id","summary"],"type":"object"},"minItems":1,"type":"array"},"report_title":{"minLength":1,"type":"string"}},"required":["report_title","findings"],"type":"object"},"rules":[{"field":"findings[].id","type":"unique"}],"submitted_output":{"findings":[{"id":"F-1","summary":"Vendor A raised its entry plan by 10%."},{"id":"F-2","summary":"Vendor B added a free tier."}],"report_title":"Q3 competitor pricing scan"},"task_id":"example-task-002"},"bodyType":"json","method":"POST","type":"http"},"output_schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","properties":{"input":{"additionalProperties":false,"properties":{"body":{"properties":{"agent_id":{"anyOf":[{"maxLength":200,"minLength":1,"pattern":"^[^\\x00-\\x1f\\x7f]+$","type":"string"},{"type":"null"}],"default":null,"description":"Optional label identifying the agent that produced submitted_output (for example, the seller), used for /reputation and the trust score: records and scores belong to the producer, not to whoever calls this endpoint. It is an unauthenticated label. agent_ids starting with 'test-' are reserved for testing: the verification runs normally but is never recorded, so it cannot affect any reputation or trust score. 1-200 printable characters (same rule as GET /score/{agent_id}); a longer or malformed value is rejected (422), not truncated.","title":"Agent Id"},"bounds":{"anyOf":[{"additionalProperties":{"description":"Optional inclusive min/max for one field. Numbers, or ISO-8601 date /\ndatetime strings (compared as datetimes; naive values are treated as UTC).","properties":{"if_present":{"default":false,"description":"Optional. When true, the check is skipped where this field is absent (the whole path, or an element of an array it applies to) instead of being reported as unable to run: no flag, and enforce_rules does not fail on it. When false (default) an absent field is a flag, and a failure under enforce_rules.","title":"If Present","type":"boolean"},"max":{"anyOf":[{"type":"integer"},{"type":"number"},{"type":"string"},{"type":"null"}],"default":null,"title":"Max"},"min":{"anyOf":[{"type":"integer"},{"type":"number"},{"type":"string"},{"type":"null"}],"default":null,"title":"Min"}},"title":"Bound","type":"object"},"maxProperties":50,"type":"object"},{"type":"null"}],"default":null,"description":"Optional per-field min/max, keyed by dotted path with '[]' array wildcard (e.g. 'items[].price'). Numbers or ISO-8601 dates. Violations are reported as informational flags unless enforce_rules is true.","title":"Bounds"},"detail":{"default":"full","description":"'full' (default) returns everything; 'compact' returns only the summary, next actions, receipt and signature. Use compact inside verify-repair loops to save tokens. 'compact' fields: summary, next_actions, result, the receipt fields (verification_id, task_id, agent_id, output_hash, schema_hash, rules_hash, verified_at, verifier_version, enforce_rules, strict_content_check), verify and attestation - errors, errors_detail, flags, hints and the scores are left out entirely, not just emptied. Both shapes are fully signed.","enum":["full","compact"],"title":"Detail","type":"string"},"enforce_rules":{"default":false,"description":"Opt-in. When true, every configured bound and consistency rule must hold, or the result is 'fail' (like strict_content_check), with an 'enforce_rules: ...' entry in errors. That includes a rule or bound that cannot run (its path is missing, a value is not comparable, a value has nothing to be compared against): it fails rather than passing silently, so omitting a field, in the whole path or in any array element the rule applies to, cannot skip a binding rule. A rule or bound with if_present: true is skipped where its field is absent instead. When false (default) nothing changes: violations and unrunnable rules stay informational flags. Echoed back in the signed response.","title":"Enforce Rules","type":"boolean"},"expected_schema":{"additionalProperties":true,"title":"Expected Schema","type":"object"},"rules":{"anyOf":[{"items":{"description":"One caller-supplied cross-field rule. Paths use dotted keys with '[]'\nas an array wildcard, e.g. 'items[].price' or 'order.total'.\n\n  sum_equals: sum of `field` values == `equals_field` value (or `equals`)\n  gte / lte:  `field` >= / <= `other_field` value (or `value`)\n  exists_in:  every `field` value is among `in_field` values (or `values`)\n  unique:     no duplicates among `field` values; if `field` names an\n              array itself, no duplicate elements in it","properties":{"equals":{"anyOf":[{"type":"integer"},{"type":"number"},{"type":"null"}],"default":null,"title":"Equals"},"equals_field":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Equals Field"},"field":{"title":"Field","type":"string"},"if_present":{"default":false,"description":"Optional. When true, the check is skipped where this field is absent (the whole path, or an element of an array it applies to) instead of being reported as unable to run: no flag, and enforce_rules does not fail on it. When false (default) an absent field is a flag, and a failure under enforce_rules. Applies to this rule's own `field`; fields it refers to (equals_field, other_field, in_field) must still exist.","title":"If Present","type":"boolean"},"in_field":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"In Field"},"other_field":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Other Field"},"tolerance":{"default":1e-09,"description":"Absolute tolerance for sum_equals and the near-match check gte/lte use. The default (1e-9) suits exact arithmetic but is usually too tight for money that passed through any floating-point math (e.g. percentage discounts, tax, unit-price * quantity): 0.1 + 0.2 != 0.3 in IEEE-754 floats by about 5.5e-17, and real pricing data regularly carries larger rounding drift than that. For a field in major currency units (dollars, euros), 0.01 (one cent) is a reasonable tolerance; for minor units (cents) already stored as integers, the default is fine. Too loose a tolerance can mask a genuine mismatch, so prefer the smallest value that tolerates your data's own rounding, not a large one 'to be safe.'","minimum":0,"title":"Tolerance","type":"number"},"type":{"enum":["sum_equals","gte","lte","exists_in","unique"],"title":"Type","type":"string"},"value":{"anyOf":[{"type":"integer"},{"type":"number"},{"type":"string"},{"type":"null"}],"default":null,"title":"Value"},"values":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}],"default":null,"title":"Values"}},"required":["type","field"],"title":"ConsistencyRule","type":"object"},"maxItems":50,"type":"array"},{"type":"null"}],"default":null,"description":"Optional cross-field rules: sum_equals, gte, lte, exists_in, unique (duplicate detection). Violations are reported as informational flags unless enforce_rules is true.","title":"Rules"},"strict_content_check":{"default":false,"description":"Opt-in. When true, any string in submitted_output containing control characters (e.g. null bytes) or embedded HTML/script markup makes the result 'fail'. When false (default) this is not checked at all.","title":"Strict Content Check","type":"boolean"},"submitted_output":{"title":"Submitted Output"},"task_id":{"description":"Your own identifier for this verification. 1-200 printable characters, no control characters and no lone Unicode surrogate; a request outside that range is rejected (422), not truncated.","maxLength":200,"minLength":1,"pattern":"^[^\\x00-\\x1f\\x7f]+$","title":"Task Id","type":"string"}},"required":["task_id","expected_schema","submitted_output"],"title":"VerifySchemaRequest","type":"object"},"bodyType":{"enum":["json","form-data","text"],"type":"string"},"method":{"enum":["POST","PUT","PATCH"],"type":"string"},"type":{"const":"http","type":"string"}},"required":["type","method","bodyType","body"],"type":"object"},"output":{"properties":{"example":{"properties":{"agent_id":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Echo of the agent_id label supplied in the request; null if none. Identifies the agent that produced submitted_output (for example, the seller): this receipt, and any reputation or trust score it feeds, belongs to that producer. It is an unauthenticated label chosen by the caller, not a proven identity, and not the identity of whoever called this endpoint.","title":"Agent Id"},"attestation":{"description":"Ed25519 signature over this response (every field above, including the receipt fields) plus the timestamp and key_version. The timestamp is this service's own clock, not an externally verified one. Public key and verification steps: /.well-known/agent-card.json, capabilities.extensions (attestation entry).","properties":{"algorithm":{"const":"Ed25519","title":"Algorithm","type":"string"},"key_version":{"title":"Key Version","type":"string"},"signature":{"title":"Signature","type":"string"},"timestamp":{"title":"Timestamp","type":"string"}},"required":["algorithm","key_version","timestamp","signature"],"title":"Attestation","type":"object"},"enforce_rules":{"description":"Whether the request had enforce_rules on: true means every rule and bound had to hold (violations and unrunnable rules fail the result); false means they were only flags.","title":"Enforce Rules","type":"boolean"},"errors":{"description":"Every violation (schema, then strict-content, then enforce_rules), capped at the first 100 schema-validation errors; see errors_total / errors_omitted. Non-schema errors (strict-content, enforce_rules) are never capped. Not part of the 'compact' detail level.","items":{"type":"string"},"title":"Errors","type":"array"},"errors_detail":{"description":"The structured form of the leading entries in `errors`, same order, so a caller can act (check, path, expected, found) without parsing text; `errors` itself is unchanged, for compatibility. See errors_detail_total / errors_detail_omitted for how many entries in `errors` this covers.","items":{"description":"The structured form of one entry in `errors`, at the same index, so a caller can act\non a violation without parsing its text (verifier_version 0.4.0). Same shape as the\nmatching `Hint` (check, path, expected, found), plus the original text for compatibility.\nOnly the first errors_detail_total entries get one, same cap as hints (MAX_DETAILS /\nMAX_STRICT_ERRORS below) - a formatted string is far cheaper to keep than a structured\none; see errors_detail_total / errors_detail_omitted.","properties":{"check":{"description":"Same meaning as Hint.check.","title":"Check","type":"string"},"expected":{"description":"Same meaning as Hint.expected.","title":"Expected","type":"string"},"found":{"description":"Same meaning as Hint.found.","title":"Found","type":"string"},"message":{"description":"The matching entry in `errors`, verbatim.","title":"Message","type":"string"},"path":{"description":"Same meaning as Hint.path.","title":"Path","type":"string"}},"required":["check","path","expected","found","message"],"title":"ErrorDetail","type":"object"},"title":"Errors Detail","type":"array"},"errors_detail_omitted":{"description":"errors_total minus errors_detail_total; 0 when every error has a structured form.","title":"Errors Detail Omitted","type":"integer"},"errors_detail_total":{"description":"How many entries in `errors` have a structured form available. Same cap as `hints` (a structured form costs more to build than the text alone).","title":"Errors Detail Total","type":"integer"},"errors_omitted":{"description":"errors_total minus len(errors); 0 when nothing was cut off.","title":"Errors Omitted","type":"integer"},"errors_total":{"description":"How many errors exist in total. Equal to len(errors) unless the 100-error schema cap above was hit.","title":"Errors Total","type":"integer"},"flags":{"description":"Integrity findings (placeholder text, possible truncation, bounds and consistency-rule violations). severity is 'error' for a finding that enforce_rules made fail the result, 'info' otherwise; either way, a flag never itself changes 'result' - it is `errors` that does. Not part of the 'compact' detail level.","items":{"properties":{"check":{"title":"Check","type":"string"},"detail":{"title":"Detail","type":"string"},"field":{"title":"Field","type":"string"},"severity":{"default":"info","description":"'error' when enforce_rules made this specific bound/rule finding fail the result (see VerifySchemaRequest.enforce_rules); 'info' otherwise. Never affects `result` itself - `result` is decided by `errors`, of which this finding is then also a member.","enum":["info","error"],"title":"Severity","type":"string"}},"required":["check","field","detail"],"title":"Flag","type":"object"},"title":"Flags","type":"array"},"flags_omitted":{"description":"Integrity flags beyond the 100 returned; 0 when nothing was cut off.","title":"Flags Omitted","type":"integer"},"flags_total":{"description":"How many flags exist in total (flags holds at most the first 100, plus a flags_truncated marker when there are more), counting an unhashable_input flag if present.","title":"Flags Total","type":"integer"},"hints":{"description":"Machine-actionable, template-based fix hints: one per schema validation failure (first, in the same order as `errors`), then per strict-content failure and integrity flag. At most 20; see hints_total / hints_omitted. Where, what was expected, what was found. Never a guessed corrected value. Not part of the 'compact' detail level.","items":{"properties":{"check":{"description":"The JSON Schema keyword that failed (type, required, minimum, ...), or the integrity check (strict_content_check, placeholder_content, truncation, bounds, consistency:*, unhashable_input).","title":"Check","type":"string"},"expected":{"description":"What the check wanted at that path, from a fixed template (e.g. 'number').","title":"Expected","type":"string"},"found":{"description":"What was there instead, from a fixed template (e.g. 'string', 'missing', '-1'). Long values are shortened; whole values are never echoed.","title":"Found","type":"string"},"path":{"description":"Where, as a JSON path: '$.items[3].price'. For a missing required property, the path where it should be. Integrity hints use the flag's own field notation with a '$.' prefix.","title":"Path","type":"string"},"source":{"description":"'schema': a JSON Schema validation failure (one per entry in `errors`, same order). 'integrity': a strict-content failure or an informational flag.","enum":["schema","integrity"],"title":"Source","type":"string"}},"required":["source","check","path","expected","found"],"title":"Hint","type":"object"},"title":"Hints","type":"array"},"hints_omitted":{"description":"hints_total minus len(hints).","title":"Hints Omitted","type":"integer"},"hints_total":{"description":"How many hints exist in total (hints holds at most the first 20).","title":"Hints Total","type":"integer"},"integrity_checks":{"description":"Integrity checks that passed out of those evaluated (per string: placeholder and truncation, plus strict content when enabled; per schema-described object: completeness; per configured bound and consistency-rule comparison). Informational: only strict_content_check failures (and enforce_rules violations, if enabled) can change `result`. Not part of the 'compact' detail level.","properties":{"passed":{"title":"Passed","type":"integer"},"ratio":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"passed / total, a raw float in [0, 1]; null when total is 0 (nothing was checked). Informational only: never affects `result`.","title":"Ratio"},"total":{"title":"Total","type":"integer"}},"required":["ratio","passed","total"],"title":"SubScore","type":"object"},"next_actions":{"description":"What to do next, machine-readable. On 'fail': [{\"action\": \"repair_and_reverify\", \"using\": \"hints\"}]. On 'pass': [{\"action\": \"attach_receipt\", \"for\": \"seller\"}, {\"action\": \"proceed_to_payment\", \"for\": \"buyer\"}]. A plain list of string-keyed objects (not a stricter per-action model): the two shapes share only `action`, and a `for` field could not be a Python attribute name without an alias that REST and MCP risk serializing differently.","items":{"additionalProperties":{"type":"string"},"type":"object"},"title":"Next Actions","type":"array"},"output_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"SHA-256 (64 lowercase hex chars = 32 bytes; add 0x to use it as a bytes32) of the JCS canonical JSON of submitted_output, the data that was verified. Key order and whitespace in what you sent do not change it. null only if it has no JCS form (NaN/Infinity, a lone surrogate).","title":"Output Hash"},"overall":{"description":"A pooled count across both groups: (schema_compliance.passed + integrity_checks.passed) / (schema_compliance.total + integrity_checks.total), with those two sums as passed and total. It is NOT an average of the two ratios (the larger group weighs more), and it says nothing about whether the content is right. null ratio when the total is 0. Informational only: never changes `result`. Not part of the 'compact' detail level.","properties":{"passed":{"title":"Passed","type":"integer"},"ratio":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"passed / total, a raw float in [0, 1]; null when total is 0 (nothing was checked). Informational only: never affects `result`.","title":"Ratio"},"total":{"title":"Total","type":"integer"}},"required":["ratio","passed","total"],"title":"SubScore","type":"object"},"request_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"SHA-256 (64 lowercase hex chars, no 0x prefix) of the RFC 8785 (JCS) canonical JSON of the request as parsed: task_id, agent_id, expected_schema, submitted_output, strict_content_check, bounds, rules, enforce_rules, with defaults filled in (agent_id/bounds/rules null, strict_content_check and enforce_rules false). Inside bounds and rules, every PER-RULE field is also filled to its own default, not just the ones you supplied: an omitted consistency-rule field hashes as equals_field/equals/other_field/value/in_field/values: null, tolerance: 1e-9, if_present: false, and an omitted bound field hashes as if_present: false - so two requests whose rules/bounds differ only by which optional fields were typed out still hash identically here. This is the opposite convention from rules_hash (below), which hashes exactly and only the fields you supplied, with nothing defaulted in - hash your own rules JSON in rules_hash's documented shape if you need to confirm which rules were applied without re-deriving every default. null only if the request contains data with no JCS form (NaN/Infinity, a lone surrogate). Not part of the 'compact' detail level.","title":"Request Hash"},"result":{"enum":["pass","fail"],"title":"Result","type":"string"},"rules_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"SHA-256 (64 lowercase hex chars) of the RFC 8785 (JCS) canonical JSON of {\"bounds\": <the bounds you supplied or null>, \"rules\": <the rules you supplied or null>}, containing exactly the fields you supplied (fields left at their defaults are not included), so you can hash your own rules JSON in that shape and compare. It lets a buyer confirm which rules were applied. null when no bounds or rules were supplied (or they contain NaN/Infinity).","title":"Rules Hash"},"schema_compliance":{"description":"JSON Schema assertions that passed out of those evaluated (each keyword such as type/required/minimum, at each place it applies; anyOf/oneOf/not/if count once, applicators like properties and items are not counted themselves). A separate figure from integrity_checks: the two ratios are never averaged (see `overall` for the pooled count). Informational: `result` is decided by errors, not by this. Not part of the 'compact' detail level.","properties":{"passed":{"title":"Passed","type":"integer"},"ratio":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"passed / total, a raw float in [0, 1]; null when total is 0 (nothing was checked). Informational only: never affects `result`.","title":"Ratio"},"total":{"title":"Total","type":"integer"}},"required":["ratio","passed","total"],"title":"SubScore","type":"object"},"schema_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"SHA-256 (64 lowercase hex chars) of the JCS canonical JSON of expected_schema. null only if it has no JCS form.","title":"Schema Hash"},"strict_content_check":{"description":"Whether the request had strict_content_check on: true means control characters and embedded HTML/script markup in submitted_output failed the result; false means that check did not run.","title":"Strict Content Check","type":"boolean"},"summary":{"description":"Compact digest of the verdict: the same `result`, and `blocking_checks` (the distinct check codes that caused a 'fail', empty on 'pass') - for a caller that wants the headline without reading `errors`/`flags`.","properties":{"blocking_checks":{"description":"Distinct check codes that caused 'fail' (the same codes used in `errors_detail[].check`, `flags[].check` and `hints[].check`), in first-seen order; empty on 'pass'.","items":{"type":"string"},"title":"Blocking Checks","type":"array"},"result":{"description":"Same value as the top-level `result`.","enum":["pass","fail"],"title":"Result","type":"string"}},"required":["result","blocking_checks"],"title":"Summary","type":"object"},"task_id":{"title":"Task Id","type":"string"},"verification_id":{"description":"Unique UUID (v4) for this verification. Part of the signed receipt.","title":"Verification Id","type":"string"},"verified_at":{"description":"ISO-8601 UTC time this service ran the verification. Identical to attestation.timestamp (the same value, read once); this service's own clock, not an externally verified time.","title":"Verified At","type":"string"},"verifier_version":{"title":"Verifier Version","type":"string"},"verify":{"description":"How to verify this receipt without any other lookup than this response and public_key_url: canonicalization and hash algorithm behind every hash and the signature itself, this service's name, and its MCP endpoint.","properties":{"canonicalization":{"description":"How every hash below, and the signed bytes themselves, are computed.","title":"Canonicalization","type":"string"},"hash_algorithm":{"description":"Algorithm behind every *_hash field in this response.","title":"Hash Algorithm","type":"string"},"key_version":{"description":"Matches attestation.key_version.","title":"Key Version","type":"string"},"mcp":{"description":"This service's MCP (Model Context Protocol) endpoint.","title":"Mcp","type":"string"},"public_key_url":{"description":"Agent-card URL listing the public key for key_version below, and every key this service has ever signed with.","title":"Public Key Url","type":"string"},"service":{"description":"This service's name.","title":"Service","type":"string"}},"required":["public_key_url","key_version","canonicalization","hash_algorithm","service","mcp"],"title":"VerifySection","type":"object"}},"required":["summary","next_actions","result","verification_id","task_id","agent_id","output_hash","schema_hash","rules_hash","request_hash","verified_at","verifier_version","enforce_rules","strict_content_check","errors","errors_total","errors_omitted","errors_detail_total","errors_detail_omitted","flags_total","flags_omitted","hints","hints_total","hints_omitted","schema_compliance","integrity_checks","overall","verify","attestation"],"title":"VerifySchemaResponse","type":"object"},"type":{"type":"string"}},"required":["type"],"type":"object"}},"required":["input"],"type":"object"},"history":[{"day":"2026-10-03","reachable":true,"status":402,"valid_402":true,"asked_usdc":0.02,"price_match":true,"latency_ms":260,"error":null}],"description_full":"Check agent output before you accept or pay for a deliverable: your JSON Schema plus rules like totals matching and unique IDs. Pass/fail, % of checks passed, fix hints and a signed receipt. $0.02 USDC, no signup, x402 v2.","last_updated":"2026-10-03T00:50:08.886Z","schemes":["exact"]}