{"openapi":"3.1.0","info":{"title":"CWR Check API","contact":{"name":"Kane Technology Group","url":"https://cwrcheck.com/","email":"alex@kanetechgroup.com"},"version":"1.0","description":"Validate CWR 2.1/2.2 files, lint JSON catalogs, and generate delivery-ready CWR. Free during the open beta — no authentication required.\n\n**Rate limits** (per client, per minute): lint 30, generate 30, validate 12, share 6. Exceeding one returns 429 with `Retry-After` and `X-RateLimit-*` headers.\n\nHuman-readable reference: https://cwrcheck.com/docs — catalog schema: https://cwrcheck.com/schema/catalog-v1.json"},"servers":[{"url":"https://cwrcheck.com"}],"paths":{"/api/validate":{"post":{"tags":["validation"],"summary":"Validate CWR files","description":"Validate up to 20 uploaded CWR files (10 MB each), statelessly. Returns per-file findings tied to line numbers, a work list, and a self-contained HTML report. Nothing is stored. Rate limit: 12/min.","operationId":"validate_files_api_validate_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_validate_files_api_validate_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Validate Files Api Validate Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/lint":{"post":{"tags":["generation"],"summary":"Check a JSON catalog (free dry run)","description":"Dry run of a JSON catalog: schema validation with JSON paths plus the generator's own checks. A clean lint guarantees /api/generate succeeds with the same input. Rate limit: 30/min.","operationId":"lint_catalog_api_lint_post","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Catalog"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Lint Catalog Api Lint Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/generate":{"post":{"tags":["generation"],"summary":"Generate a CWR file from a catalog","description":"Catalog in, fixed-width CWR file out, with a convention-conforming filename in Content-Disposition. A clean /api/lint on the same catalog guarantees this call succeeds, and the output passes /api/validate with zero errors. No API key is needed while billing is disabled (open beta); once enabled, pass X-API-Key. Rate limit: 30/min.","operationId":"generate_cwr_api_generate_post","parameters":[{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Catalog"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/usage":{"get":{"tags":["generation"],"summary":"Usage for your API key","description":"Current billing-period usage for the caller's API key.\n\nIncludes a per-client breakdown so administrators can re-bill\neach catalog's owner for exactly the works generated for them.","operationId":"usage_api_usage_get","parameters":[{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Usage Api Usage Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/billing/checkout":{"post":{"summary":"Billing Checkout","description":"Start a Stripe Checkout for an API key subscription.\n\nBody: ``{\"email\": \"...\"}``. Returns ``{\"url\": ...}`` to redirect\nthe buyer to Stripe. 503 until Stripe is configured via env.","operationId":"billing_checkout_api_billing_checkout_post","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Body"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Billing Checkout Api Billing Checkout Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/billing/claim":{"post":{"summary":"Billing Claim","description":"Exchange a paid checkout session id for the API key, once.","operationId":"billing_claim_api_billing_claim_post","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Body"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Billing Claim Api Billing Claim Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/healthz":{"get":{"summary":"Healthz","description":"Liveness probe for Render.","operationId":"healthz_healthz_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Healthz Healthz Get"}}}}}}},"/api/share":{"post":{"summary":"Share Report","description":"Create a shareable URL for one file's validation report.\n\nOpt-in persistence: the file is re-validated here and the\nserver-rendered report -- never client-supplied HTML -- is stored\nfor 30 days under an unguessable id. The uploaded file itself is\nstill discarded.","operationId":"share_report_api_share_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_share_report_api_share_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Share Report Api Share Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leads":{"post":{"summary":"Create Lead","description":"Managed-service inquiry or API key request from the site.\n\nThe \"website\" field is a honeypot: humans never see it, bots fill\nit. Honeypotted submissions are acknowledged but not stored. UTM\nattribution captured on the page is stored with the lead, and each\nlead is mirrored to Formspree for the email notification.","operationId":"create_lead_api_leads_post","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Body"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Create Lead Api Leads Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/leads":{"get":{"summary":"Admin Leads","description":"The inquiry list, gated by CWRCHECK_ADMIN_TOKEN (set on Render).","operationId":"admin_leads_api_admin_leads_get","parameters":[{"name":"x-admin-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Admin-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Leads Api Admin Leads Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/usage":{"get":{"summary":"Admin Usage","description":"Usage summary (counts and outcomes only), admin-token gated.","operationId":"admin_usage_api_admin_usage_get","parameters":[{"name":"x-admin-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Admin-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Usage Api Admin Usage Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"Body_share_report_api_share_post":{"properties":{"files":{"items":{"type":"string","contentMediaType":"application/octet-stream"},"type":"array","title":"Files"}},"type":"object","required":["files"],"title":"Body_share_report_api_share_post"},"Body_validate_files_api_validate_post":{"properties":{"files":{"items":{"type":"string","contentMediaType":"application/octet-stream"},"type":"array","title":"Files"}},"type":"object","required":["files"],"title":"Body_validate_files_api_validate_post"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}},"tags":[{"name":"validation","description":"Check existing CWR files. Free, nothing stored."},{"name":"generation","description":"Turn a JSON catalog into delivery-ready CWR. Free during the open beta; the X-API-Key header is reserved for when billing is enabled."}]}