{"openapi":"3.0.3","info":{"title":"Mekler: CSV Validator","version":"1.0.3","description":"Mekler checks CSV files against a fixed JSON column specification before import or handoff. It detects missing fields, duplicate values, invalid types/dates, disallowed values and numeric/row-count violations, returning row/column error codes. A separate endpoint checks the specification itself. No custom formulas, cross-column logic, factual verification or data repair. 0.05 native USDC per accepted request via x402 on Solana; no input retention."},"paths":{"/v1/accept/csv":{"post":{"summary":"Validate CSV","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["csv","spec"],"properties":{"csv":{"type":"string","description":"UTF-8 comma-delimited CSV with header. No trimming. Data record numbers start at 1; quoted newlines are one record."},"spec":{"type":"object","additionalProperties":false,"required":["columns"],"properties":{"columns":{"type":"array","minItems":1,"maxItems":50,"items":{"type":"object","additionalProperties":false,"required":["name","type"],"properties":{"name":{"type":"string","minLength":1,"maxLength":100},"type":{"type":"string","enum":["string","integer","decimal","boolean","date"],"description":"string: literal text; integer: base-10, no plus sign or leading zeros; decimal: plain decimal, no exponent; boolean: lowercase true/false; date: valid YYYY-MM-DD."},"required":{"type":"boolean","default":false,"description":"Reject empty cells. Whitespace is not trimmed."},"unique":{"type":"boolean","default":false,"description":"Reject repeated nonempty values within this column; numeric values compare numerically."},"min":{"oneOf":[{"type":"number"},{"type":"string"}],"description":"Inclusive numeric bound; allowed only for integer or decimal columns."},"max":{"oneOf":[{"type":"number"},{"type":"string"}],"description":"Inclusive numeric bound; allowed only for integer or decimal columns."},"enum":{"type":"array","minItems":1,"maxItems":100,"items":{"type":"string","maxLength":1000},"description":"Exact allowed cell strings, compared without trimming or normalization."}}},"description":"Fixed built-in checks. Every named column must exist, even when required is false."},"min_rows":{"type":"integer","minimum":0,"maximum":2000,"default":0},"max_rows":{"type":"integer","minimum":0,"maximum":2000,"default":2000},"allow_extra_columns":{"type":"boolean","default":false,"description":"If false, reject CSV headers not named in columns."}}}}},"example":{"csv":"id,amount\na,12.50\na,-2.00\n","spec":{"columns":[{"name":"id","type":"string","required":true,"unique":true},{"name":"amount","type":"decimal","required":true,"min":"0","max":"100"}],"min_rows":1}}}}},"responses":{"200":{"description":"Service result. Inspect X-Mekler-Payment-State: finalized includes PAYMENT-RESPONSE; provisional includes a purchase ID without a settlement receipt.","content":{"application/json":{"schema":{"type":"object","properties":{"schema_version":{"type":"integer","enum":[1]},"verdict":{"type":"string","enum":["pass","fail"]},"rows_checked":{"type":"integer","minimum":0},"failure_count":{"type":"integer","minimum":0},"failures":{"type":"array","maxItems":50,"items":{"type":"object","properties":{"code":{"type":"string","enum":["missing_column","extra_columns","row_width","required","type","min","max","enum","unique","min_rows","max_rows"]},"row":{"type":"integer","nullable":true,"description":"One-based data record, excluding header; null for file/header errors."},"column":{"type":"string","nullable":true,"description":"Column name, or null when the error applies to the row or file."}},"required":["code","row","column"]}},"failures_truncated":{"type":"boolean"},"receipt_sha256":{"type":"string","pattern":"^[0-9a-f]{64}$"},"boundary":{"type":"string"}},"required":["schema_version","verdict","rows_checked","failure_count","failures","failures_truncated","receipt_sha256","boundary"]},"example":{"schema_version":1,"verdict":"fail","rows_checked":2,"failure_count":2,"failures":[{"code":"unique","row":2,"column":"id"},{"code":"min","row":2,"column":"amount"}],"failures_truncated":false,"receipt_sha256":"32265ae46050fa0067b9adb0df085a5cf3d9fa3d47d91e9ea2f61135a382d8ac","boundary":"Only supplied explicit criteria checked; no certification of truth or subjective quality."}}},"headers":{"PAYMENT-RESPONSE":{"description":"Base64 JSON settlement receipt: success, transaction, network, payer. Present only after finality.","schema":{"type":"string"}},"X-Mekler-Payment-State":{"description":"finalized or provisional","schema":{"type":"string"}},"X-Mekler-Purchase-Id":{"description":"Purchase ID on provisional results.","schema":{"type":"string"}}}},"400":{"description":"Malformed input or unsupported criterion; no acceptance verdict","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"detail":{"type":"string"},"retry":{"type":"string"},"purchase_id":{"type":"string"},"price_usdc":{"type":"string"}},"required":["error"]},"example":{"error":"invalid_request"}}}},"413":{"description":"Request exceeds 256 KiB","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"detail":{"type":"string"},"retry":{"type":"string"},"purchase_id":{"type":"string"},"price_usdc":{"type":"string"}},"required":["error"]},"example":{"error":"body_too_large"}}}},"415":{"description":"Requires application/json","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"detail":{"type":"string"},"retry":{"type":"string"},"purchase_id":{"type":"string"},"price_usdc":{"type":"string"}},"required":["error"]},"example":{"error":"application/json required"}}}},"429":{"description":"API gateway throttling. Respect Retry-After when supplied; otherwise back off. Preserve any existing payment proof.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]},"example":{"message":"Too Many Requests"}}}},"402":{"description":"Payment required; PAYMENT-REQUIRED header contains the server-authored USDC quote.","headers":{"PAYMENT-REQUIRED":{"description":"Base64 JSON x402 v2 quote for valid unsigned input. Expired/invalid-proof errors may omit this header.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"detail":{"type":"string"},"retry":{"type":"string"},"purchase_id":{"type":"string"},"price_usdc":{"type":"string"}},"required":["error"]},"example":{"error":"payment_required","price_usdc":"0.050000"}}}},"202":{"description":"Settlement outcome pending; retry identical request and signed proof, never create a second payment.","headers":{"Retry-After":{"description":"Seconds before retrying identical body and proof.","schema":{"type":"string","enum":["5"]}}},"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["payment_pending"]},"purchase_id":{"type":"string"},"retry":{"type":"string"}},"required":["status","purchase_id","retry"]},"example":{"status":"payment_pending","purchase_id":"example-purchase-id","retry":"Resend the identical request and PAYMENT-SIGNATURE. Do not pay again."}}}},"409":{"description":"The proof is already bound to another request, or its transaction failed. Inspect error and purchase_id; do not automatically create another payment.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"detail":{"type":"string"},"retry":{"type":"string"},"purchase_id":{"type":"string"},"price_usdc":{"type":"string"}},"required":["error"]},"example":{"error":"payment_already_bound"}}}},"503":{"description":"Payment service temporarily unavailable; do not create a second payment after an ambiguous response.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"detail":{"type":"string"},"retry":{"type":"string"},"purchase_id":{"type":"string"},"price_usdc":{"type":"string"}},"required":["error"]},"example":{"error":"payment_temporarily_unavailable"}}}}},"parameters":[{"name":"PAYMENT-SIGNATURE","in":"header","required":false,"description":"Buyer-signed x402 v2 exact payment proof matching the server quote. Omit to obtain a 402 quote; send the identical proof on retry.","schema":{"type":"string"}}],"x-payment-info":{"protocols":[{"x402":{}}],"price":{"mode":"fixed","currency":"USD","amount":"0.05"}},"description":"Validate CSV before import using a fixed JSON column specification. Checks missing/extra columns, required cells, string/integer/decimal/boolean/date types, uniqueness, allowed values and numeric/row-count bounds. Returns pass/fail with row/column error codes. POST JSON with csv and spec.columns; schemas/examples attached. Full contract: /openapi.json. Max 2,000 rows, 50 columns, 256 KiB; first 50 failures. No formulas, cross-column rules, fact checking or data repair.","tags":["csv","data-validation","data-quality"],"operationId":"validateCsvDelivery","security":[{"x402":[]}]}},"/v1/accept/compile":{"post":{"summary":"Check CSV Validation Rules","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["requirements"],"properties":{"requirements":{"type":"object","additionalProperties":false,"required":["columns"],"properties":{"columns":{"type":"array","minItems":1,"maxItems":50,"items":{"type":"object","additionalProperties":false,"required":["name","type"],"properties":{"name":{"type":"string","minLength":1,"maxLength":100},"type":{"type":"string","enum":["string","integer","decimal","boolean","date"],"description":"string: literal text; integer: base-10, no plus sign or leading zeros; decimal: plain decimal, no exponent; boolean: lowercase true/false; date: valid YYYY-MM-DD."},"required":{"type":"boolean","default":false,"description":"Reject empty cells. Whitespace is not trimmed."},"unique":{"type":"boolean","default":false,"description":"Reject repeated nonempty values within this column; numeric values compare numerically."},"min":{"oneOf":[{"type":"number"},{"type":"string"}],"description":"Inclusive numeric bound; allowed only for integer or decimal columns."},"max":{"oneOf":[{"type":"number"},{"type":"string"}],"description":"Inclusive numeric bound; allowed only for integer or decimal columns."},"enum":{"type":"array","minItems":1,"maxItems":100,"items":{"type":"string","maxLength":1000},"description":"Exact allowed cell strings, compared without trimming or normalization."}}},"description":"Fixed built-in checks. Every named column must exist, even when required is false."},"min_rows":{"type":"integer","minimum":0,"maximum":2000,"default":0},"max_rows":{"type":"integer","minimum":0,"maximum":2000,"default":2000},"allow_extra_columns":{"type":"boolean","default":false,"description":"If false, reject CSV headers not named in columns."}}}}},"example":{"requirements":{"columns":[{"name":"id","type":"string","required":true,"unique":true},{"name":"amount","type":"decimal","required":true,"min":"0","max":"100"}],"min_rows":1}}}}},"responses":{"200":{"description":"Service result. Inspect X-Mekler-Payment-State: finalized includes PAYMENT-RESPONSE; provisional includes a purchase ID without a settlement receipt.","content":{"application/json":{"schema":{"type":"object","properties":{"schema_version":{"type":"integer","enum":[1]},"spec":{"type":"object","additionalProperties":false,"required":["columns"],"properties":{"columns":{"type":"array","minItems":1,"maxItems":50,"items":{"type":"object","additionalProperties":false,"required":["name","type"],"properties":{"name":{"type":"string","minLength":1,"maxLength":100},"type":{"type":"string","enum":["string","integer","decimal","boolean","date"]},"required":{"type":"boolean","default":false},"unique":{"type":"boolean","default":false},"min":{"oneOf":[{"type":"number"},{"type":"string"}]},"max":{"oneOf":[{"type":"number"},{"type":"string"}]},"enum":{"type":"array","minItems":1,"maxItems":100,"items":{"type":"string","maxLength":1000}}}}},"min_rows":{"type":"integer","minimum":0,"maximum":2000,"default":0},"max_rows":{"type":"integer","minimum":0,"maximum":2000,"default":2000},"allow_extra_columns":{"type":"boolean","default":false}}},"unsupported":{"type":"array","maxItems":0,"items":{"type":"string"}},"boundary":{"type":"string"}},"required":["schema_version","spec","unsupported","boundary"]},"example":{"schema_version":1,"spec":{"columns":[{"name":"id","type":"string","required":true,"unique":true},{"name":"amount","type":"decimal","required":true,"min":"0","max":"100"}],"min_rows":1},"unsupported":[],"boundary":"Typed requirements only; no natural-language interpretation."}}},"headers":{"PAYMENT-RESPONSE":{"description":"Base64 JSON settlement receipt: success, transaction, network, payer. Present only after finality.","schema":{"type":"string"}},"X-Mekler-Payment-State":{"description":"finalized or provisional","schema":{"type":"string"}},"X-Mekler-Purchase-Id":{"description":"Purchase ID on provisional results.","schema":{"type":"string"}}}},"400":{"description":"Malformed input or unsupported criterion; no acceptance verdict","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"detail":{"type":"string"},"retry":{"type":"string"},"purchase_id":{"type":"string"},"price_usdc":{"type":"string"}},"required":["error"]},"example":{"error":"invalid_request"}}}},"413":{"description":"Request exceeds 256 KiB","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"detail":{"type":"string"},"retry":{"type":"string"},"purchase_id":{"type":"string"},"price_usdc":{"type":"string"}},"required":["error"]},"example":{"error":"body_too_large"}}}},"415":{"description":"Requires application/json","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"detail":{"type":"string"},"retry":{"type":"string"},"purchase_id":{"type":"string"},"price_usdc":{"type":"string"}},"required":["error"]},"example":{"error":"application/json required"}}}},"429":{"description":"API gateway throttling. Respect Retry-After when supplied; otherwise back off. Preserve any existing payment proof.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]},"example":{"message":"Too Many Requests"}}}},"402":{"description":"Payment required; PAYMENT-REQUIRED header contains the server-authored USDC quote.","headers":{"PAYMENT-REQUIRED":{"description":"Base64 JSON x402 v2 quote for valid unsigned input. Expired/invalid-proof errors may omit this header.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"detail":{"type":"string"},"retry":{"type":"string"},"purchase_id":{"type":"string"},"price_usdc":{"type":"string"}},"required":["error"]},"example":{"error":"payment_required","price_usdc":"0.050000"}}}},"202":{"description":"Settlement outcome pending; retry identical request and signed proof, never create a second payment.","headers":{"Retry-After":{"description":"Seconds before retrying identical body and proof.","schema":{"type":"string","enum":["5"]}}},"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["payment_pending"]},"purchase_id":{"type":"string"},"retry":{"type":"string"}},"required":["status","purchase_id","retry"]},"example":{"status":"payment_pending","purchase_id":"example-purchase-id","retry":"Resend the identical request and PAYMENT-SIGNATURE. Do not pay again."}}}},"409":{"description":"The proof is already bound to another request, or its transaction failed. Inspect error and purchase_id; do not automatically create another payment.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"detail":{"type":"string"},"retry":{"type":"string"},"purchase_id":{"type":"string"},"price_usdc":{"type":"string"}},"required":["error"]},"example":{"error":"payment_already_bound"}}}},"503":{"description":"Payment service temporarily unavailable; do not create a second payment after an ambiguous response.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"detail":{"type":"string"},"retry":{"type":"string"},"purchase_id":{"type":"string"},"price_usdc":{"type":"string"}},"required":["error"]},"example":{"error":"payment_temporarily_unavailable"}}}}},"parameters":[{"name":"PAYMENT-SIGNATURE","in":"header","required":false,"description":"Buyer-signed x402 v2 exact payment proof matching the server quote. Omit to obtain a 402 quote; send the identical proof on retry.","schema":{"type":"string"}}],"x-payment-info":{"protocols":[{"x402":{}}],"price":{"mode":"fixed","currency":"USD","amount":"0.05"}},"description":"Validate a fixed JSON CSV column specification before assigning extraction or checking deliveries. Send typed column settings in requirements; returns the validated spec for /v1/accept/csv. Rejects unknown fields and unsupported settings. This checks the specification itself, not CSV data. No custom expressions, cross-column rules or prose-to-rule conversion. Schemas/examples attached; full contract: /openapi.json.","tags":["csv","schema-validation","data-contracts"],"operationId":"validateAcceptanceSpec","security":[{"x402":[]}]}}},"servers":[{"url":"https://csv-validator.mekler.ai"}],"x-agent-guide":{"purpose":"Check CSV schema and column constraints before import or delivery acceptance.","choose_when":["You already have CSV text and can express your requirements using the fixed column specification.","You need deterministic row/column failures to request corrections or reject a delivery."],"capabilities":["Every specified column must exist. Extra columns are rejected unless allow_extra_columns is true.","Per-column checks: type, required nonempty cells, uniqueness, exact allowed strings (enum), inclusive numeric min/max.","Types: string, integer, decimal, boolean, date. No whitespace trimming. Empty optional cells skip other checks.","Per-file checks: min_rows and max_rows; each data record must have the same field count as the header.","The compile endpoint validates the same fixed JSON specification; it returns that spec unchanged. It does not generate rules."],"not_supported":["Custom expressions or executable predicates","Cross-column arithmetic or conditional rules","Cross-file joins or referential integrity","Natural-language requirements","Truth verification, data repair or URL retrieval"],"calling":{"content_type":"application/json","csv":"POST /v1/accept/csv with {csv: string, spec: object}.","compile":"POST /v1/accept/compile with {requirements: object}, using the identical column-spec grammar.","spec":"columns is required; each entry requires name and type. Other supported fields are required, unique, enum, min, max. File options are min_rows, max_rows, allow_extra_columns. Unknown properties are rejected."},"constraints":{"request_bytes":262144,"data_records":2000,"columns":50,"reported_failures":50,"result_bytes":16384,"semantics":["Numeric uniqueness compares values numerically. Other uniqueness uses literal strings. Empty optional cells are skipped.","enum compares the original nonempty cell string, even for numeric columns.","Row numbers are one-based data records excluding the header. Quoted newlines remain part of one record.","Malformed CSV, invalid/duplicate headers or unsupported specs return 400, not a fail verdict."]},"result_interpretation":{"verdict":"pass means all evaluated built-in constraints passed; fail means at least one violation. Neither establishes factual accuracy.","failures":"First 50 violations as code, row and column. Null locations denote a file/header-level issue. Cell values are not returned.","failure_count":"Total counted violations, which can exceed failures length. Check failures_truncated.","receipt_sha256":"Hash of the canonical request, not a signature or proof of truth. Payment receipt is a separate header.","compiler":"schema_version, validated spec, unsupported=[], boundary. Unsupported settings instead return HTTP 400."},"selection_examples":[{"task":"Reject duplicate IDs and negative prices in extracted CSV.","endpoint":"/v1/accept/csv","fit":true},{"task":"Check the JSON spec before assigning extraction.","endpoint":"/v1/accept/compile","fit":true},{"task":"Verify invoice total equals quantity times unit price.","fit":false,"reason":"Cross-column expressions are unsupported."}],"payment":{"price":"0.05 native USDC per accepted request","network":"Solana mainnet","protocol":"x402 v2 exact","quote":"Send the valid intended JSON body without PAYMENT-SIGNATURE. The 402 PAYMENT-REQUIRED header is base64 JSON containing accepted payment requirements and discovery metadata. It is not a service result. A bodyless or empty-object unsigned POST returns a nonpayable preflight 402 for discovery; submit the intended valid JSON to obtain a payable quote. Never sign the preflight offer.","authorization":"Use an authorized buyer wallet and check network, asset, recipient and amount before signing. Send PAYMENT-SIGNATURE with identical JSON input. No API key or subscription is required.","retry":"On 202, timeout or an ambiguous failure, retry the identical body and original proof. Do not sign or pay again. Retry-After is 5 seconds for 202.","finality":"200 with X-Mekler-Payment-State=finalized includes a base64 JSON PAYMENT-RESPONSE receipt. After 15 minutes of uncertainty, a provisional 200 may have X-Mekler-Purchase-Id but no payment receipt. Provisional does not establish settlement.","expiry":"2026-10-27T14:19:19Z unless separately renewed; expired allowance or exhausted 1000-purchase shared pilot cap returns 503."},"privacy":"Inputs/results are processed in memory and not retained or logged. Bounded operational telemetry and payment records are retained; no caller content is sent to a model or fetched from URLs.","documentation":{"openapi":"/openapi.json","manifest":"/service.json","examples":"Each operation includes executable request and 200-response examples."}},"components":{"securitySchemes":{"x402":{"type":"apiKey","in":"header","name":"PAYMENT-SIGNATURE","description":"x402 v2 signed payment proof. Obtain requirements with a valid unsigned request (402), then retry identical input with the proof. No API key registration."}}}}