Certificate of analysis vs specification: pass, fail or indeterminate per clause

$0.005 USDC per call · Business, finance and compliance · POST /api/v1/coa-gate · Id coa-gate

Checks the values on a certificate of analysis or test report against specification limits clause by clause (up to 200 clauses), for an agent accepting a lot or a supplier's material. Each clause has a parameter, an optional min and max and a unit; each result has a value, an optional reported uncertainty and an optional less-than or greater-than qualifier ("<0.01"). rule simple (default): the reported value is compared with the limits and uncertainty is ignored. rule guard-banded: a clause passes only if value +/- uncertainty lies inside the limits, fails only if it lies wholly outside, and is indeterminate when the interval straddles a limit. A missing result, a unit with no supplied conversion, a guard-banded result with no reported uncertainty (state "0" for an exact value), or a censored value that cannot be placed against a limit is indeterminate, never pass. Overall: fail if any clause fails, unknown if any is indeterminate, else pass. Does not validate the laboratory, the method or the certificate's authenticity.

What you get

A 'meets specification' stamp is not a check. Every clause recomputed from the numbers, with uncertainty and censored values handled explicitly.

Call it

Send the JSON body below to https://agents.writerslogic.com/api/v1/coa-gate. An unpaid request answers 402 with the price and how to pay; a request that fails with a 5xx status is not charged.

curl -i -X POST https://agents.writerslogic.com/api/v1/coa-gate \
  -H 'content-type: application/json' \
  -d '{"rule":"guard-banded","clauses":[{"id":"assay","parameter":"Assay","min":"99.0","unit":"%"},{"id":"pb","parameter":"Lead","max":"0.5","unit":"ppm"},{"id":"water","parameter":"Water","max":"0.2","unit":"%"}],"results":[{"parameter":"Assay","value":"99.4","uncertainty":"0.3","unit":"%"},{"parameter":"Lead","value":"0.1","qualifier":"<","unit":"ppm"}]}'

Input

FieldTypeRequiredDescription
clausesarray<object>; max 200 itemsyes
resultsarray<object>; max 400 itemsyes
rulestring; one of "simple", "guard-banded"no
conversionsarray<object>; max 50 itemsnoCaller-supplied unit conversions; none are built in.

Example request body

{
  "rule": "guard-banded",
  "clauses": [
    {
      "id": "assay",
      "parameter": "Assay",
      "min": "99.0",
      "unit": "%"
    },
    {
      "id": "pb",
      "parameter": "Lead",
      "max": "0.5",
      "unit": "ppm"
    },
    {
      "id": "water",
      "parameter": "Water",
      "max": "0.2",
      "unit": "%"
    }
  ],
  "results": [
    {
      "parameter": "Assay",
      "value": "99.4",
      "uncertainty": "0.3",
      "unit": "%"
    },
    {
      "parameter": "Lead",
      "value": "0.1",
      "qualifier": "<",
      "unit": "ppm"
    }
  ]
}

Result

The response is { "data": ..., "_provenance": ... }. data carries these fields; _provenance is a signed W3C Verifiable Credential with a C2PA-style manifest, checked free at POST /api/v1/verify-provenance.

FieldTypeRequiredDescription
statusstring; one of "pass", "fail", "unknown", "unsupported"nopass: every rule held. fail: a rule was violated (see witnesses). unknown: the input lacks the evidence to decide. unsupported: outside what this engine covers. Missing evidence is never a pass.
clausesarray<object>no
countsobjectno
unusedResultsarray<string>noParameters on the certificate that no clause refers to.
rulestringno
witnessesarray<object>no
versionsobjectnoEvery semantic dependency of this answer (engine, tables and their as-of dates, tokenizer, calendar, rounding profile).
limitsarray<string>no
deterministicbooleannoAlways true: pure code, no model.

Pay and connect

Available through: x402 (USDC on Base), MCP. MCP clients reach it through the money-math-kit package.

Machine-readable