{"openapi":"3.1.0","info":{"version":"0.1.0","title":"ZUTMCheck Attribution Handoff Verifier API","description":"Automated regression verification API for Google Ads GCLID and UTM parameters passing across CMP consent banners to lead capture boundaries (HubSpot forms, Calendly embeds, cross-domain linkers)."},"components":{"schemas":{"AuditReport":{"type":"object","properties":{"id":{"type":"string","example":"aud_12345678"},"created_at":{"type":"string","example":"2026-11-11T12:00:00.000Z"},"mode":{"type":"string","enum":["quick","quick_scan","contract"],"description":"Mode of audit: quick single URL scan or explicit contract regression test","example":"quick_scan"},"entry_url":{"type":"string"},"target_type":{"type":"string","enum":["auto","hubspot_form","calendly_embed","cross_domain_url"],"description":"Expected lead capture or handoff component type","example":"auto"},"comparison_scope":{"type":"string"},"required_params":{"type":"array","items":{"type":"string","enum":["gclid","utm_source","utm_medium","utm_campaign","utm_term","utm_content"]}},"share_token":{"type":"string"},"synthetic_params":{"type":"object","additionalProperties":{"type":"string"}},"overall_status":{"type":"string","enum":["VERIFIED","BROKEN","INDETERMINATE","NOT_APPLICABLE"],"description":"Four-state verification outcome (strictly avoiding false positives)","example":"VERIFIED"},"summary":{"type":"string"},"states":{"type":"object","properties":{"no_action":{"type":"object","properties":{"state":{"type":"string","enum":["no_action","reject","accept"]},"status":{"type":"string","enum":["VERIFIED","BROKEN","INDETERMINATE","NOT_APPLICABLE"],"description":"Four-state verification outcome (strictly avoiding false positives)","example":"VERIFIED"},"indeterminate_reason":{"type":"string"},"hop_1_redirect":{"type":"object","properties":{"status":{"type":"string","enum":["VERIFIED","BROKEN","INDETERMINATE","NOT_APPLICABLE"],"description":"Four-state verification outcome (strictly avoiding false positives)","example":"VERIFIED"},"final_url":{"type":"string"},"redirect_chain":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string"},"status":{"type":"number"}},"required":["url","status"]}},"params_lost":{"type":"array","items":{"type":"string"}},"evidence":{"type":"string"}},"required":["status","final_url","redirect_chain","params_lost","evidence"]},"hop_2_consent":{"type":"object","properties":{"status":{"type":"string","enum":["VERIFIED","BROKEN","INDETERMINATE","NOT_APPLICABLE"],"description":"Four-state verification outcome (strictly avoiding false positives)","example":"VERIFIED"},"cmp_detected":{"type":"string","nullable":true},"gcs_observed":{"type":"string","nullable":true},"gcd_observed":{"type":"string","nullable":true},"gcl_aw_cookie_written":{"type":"boolean"},"storage_granted":{"type":"boolean"},"evidence":{"type":"string"}},"required":["status","cmp_detected","gcs_observed","gcd_observed","gcl_aw_cookie_written","storage_granted","evidence"]},"hop_3_handoff":{"type":"object","properties":{"status":{"type":"string","enum":["VERIFIED","BROKEN","INDETERMINATE","NOT_APPLICABLE"],"description":"Four-state verification outcome (strictly avoiding false positives)","example":"VERIFIED"},"target_detected":{"type":"string","nullable":true},"matched_params":{"type":"object","additionalProperties":{"type":"string"}},"missing_params":{"type":"array","items":{"type":"string"}},"evidence":{"type":"string"}},"required":["status","target_detected","matched_params","missing_params","evidence"]},"evidence_summary":{"type":"string"}},"required":["state","status","hop_1_redirect","hop_2_consent","hop_3_handoff","evidence_summary"]},"reject":{"type":"object","properties":{"state":{"type":"string","enum":["no_action","reject","accept"]},"status":{"type":"string","enum":["VERIFIED","BROKEN","INDETERMINATE","NOT_APPLICABLE"],"description":"Four-state verification outcome (strictly avoiding false positives)","example":"VERIFIED"},"indeterminate_reason":{"type":"string"},"hop_1_redirect":{"type":"object","properties":{"status":{"type":"string","enum":["VERIFIED","BROKEN","INDETERMINATE","NOT_APPLICABLE"],"description":"Four-state verification outcome (strictly avoiding false positives)","example":"VERIFIED"},"final_url":{"type":"string"},"redirect_chain":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string"},"status":{"type":"number"}},"required":["url","status"]}},"params_lost":{"type":"array","items":{"type":"string"}},"evidence":{"type":"string"}},"required":["status","final_url","redirect_chain","params_lost","evidence"]},"hop_2_consent":{"type":"object","properties":{"status":{"type":"string","enum":["VERIFIED","BROKEN","INDETERMINATE","NOT_APPLICABLE"],"description":"Four-state verification outcome (strictly avoiding false positives)","example":"VERIFIED"},"cmp_detected":{"type":"string","nullable":true},"gcs_observed":{"type":"string","nullable":true},"gcd_observed":{"type":"string","nullable":true},"gcl_aw_cookie_written":{"type":"boolean"},"storage_granted":{"type":"boolean"},"evidence":{"type":"string"}},"required":["status","cmp_detected","gcs_observed","gcd_observed","gcl_aw_cookie_written","storage_granted","evidence"]},"hop_3_handoff":{"type":"object","properties":{"status":{"type":"string","enum":["VERIFIED","BROKEN","INDETERMINATE","NOT_APPLICABLE"],"description":"Four-state verification outcome (strictly avoiding false positives)","example":"VERIFIED"},"target_detected":{"type":"string","nullable":true},"matched_params":{"type":"object","additionalProperties":{"type":"string"}},"missing_params":{"type":"array","items":{"type":"string"}},"evidence":{"type":"string"}},"required":["status","target_detected","matched_params","missing_params","evidence"]},"evidence_summary":{"type":"string"}},"required":["state","status","hop_1_redirect","hop_2_consent","hop_3_handoff","evidence_summary"]},"accept":{"type":"object","properties":{"state":{"type":"string","enum":["no_action","reject","accept"]},"status":{"type":"string","enum":["VERIFIED","BROKEN","INDETERMINATE","NOT_APPLICABLE"],"description":"Four-state verification outcome (strictly avoiding false positives)","example":"VERIFIED"},"indeterminate_reason":{"type":"string"},"hop_1_redirect":{"type":"object","properties":{"status":{"type":"string","enum":["VERIFIED","BROKEN","INDETERMINATE","NOT_APPLICABLE"],"description":"Four-state verification outcome (strictly avoiding false positives)","example":"VERIFIED"},"final_url":{"type":"string"},"redirect_chain":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string"},"status":{"type":"number"}},"required":["url","status"]}},"params_lost":{"type":"array","items":{"type":"string"}},"evidence":{"type":"string"}},"required":["status","final_url","redirect_chain","params_lost","evidence"]},"hop_2_consent":{"type":"object","properties":{"status":{"type":"string","enum":["VERIFIED","BROKEN","INDETERMINATE","NOT_APPLICABLE"],"description":"Four-state verification outcome (strictly avoiding false positives)","example":"VERIFIED"},"cmp_detected":{"type":"string","nullable":true},"gcs_observed":{"type":"string","nullable":true},"gcd_observed":{"type":"string","nullable":true},"gcl_aw_cookie_written":{"type":"boolean"},"storage_granted":{"type":"boolean"},"evidence":{"type":"string"}},"required":["status","cmp_detected","gcs_observed","gcd_observed","gcl_aw_cookie_written","storage_granted","evidence"]},"hop_3_handoff":{"type":"object","properties":{"status":{"type":"string","enum":["VERIFIED","BROKEN","INDETERMINATE","NOT_APPLICABLE"],"description":"Four-state verification outcome (strictly avoiding false positives)","example":"VERIFIED"},"target_detected":{"type":"string","nullable":true},"matched_params":{"type":"object","additionalProperties":{"type":"string"}},"missing_params":{"type":"array","items":{"type":"string"}},"evidence":{"type":"string"}},"required":["status","target_detected","matched_params","missing_params","evidence"]},"evidence_summary":{"type":"string"}},"required":["state","status","hop_1_redirect","hop_2_consent","hop_3_handoff","evidence_summary"]}},"required":["no_action","reject","accept"]},"remediation":{"type":"object","nullable":true,"properties":{"title":{"type":"string"},"issue_summary":{"type":"string"},"root_cause_hop":{"type":"string","enum":["hop_1_redirect","hop_2_consent","hop_3_handoff","none"]},"steps":{"type":"array","items":{"type":"string"}},"documentation_links":{"type":"array","items":{"type":"string"}}},"required":["title","issue_summary","root_cause_hop","steps","documentation_links"]},"sanitized_headers":{"type":"array","items":{"type":"string"}}},"required":["id","created_at","mode","entry_url","synthetic_params","overall_status","summary","states","remediation","sanitized_headers"]},"AuditRequest":{"type":"object","properties":{"mode":{"type":"string","enum":["quick","quick_scan","contract"],"default":"quick_scan","description":"Mode of audit: quick single URL scan or explicit contract regression test","example":"quick_scan"},"entry_url":{"type":"string","maxLength":4096,"format":"uri","description":"Landing page URL to audit (will be dynamically appended with synthetic parameters)","example":"https://example.com/landing?product=demo"},"cmp_expectation":{"type":"string","enum":["auto","cookiebot","onetrust","none","custom"],"default":"auto","description":"Expected Consent Management Platform adapter","example":"auto"},"custom_cmp_selectors":{"type":"object","properties":{"accept_selector":{"type":"string","maxLength":512,"example":"#accept-cookies-btn"},"reject_selector":{"type":"string","maxLength":512,"example":"#reject-cookies-btn"}},"description":"Custom selectors for unsupported or bespoke CMP banners"},"cta_selector":{"type":"string","maxLength":512,"description":"Optional non-submit CTA selector (e.g. link/button to book a demo or open popup)","example":"a.book-demo-btn"},"handoff_expectation":{"type":"object","properties":{"target_type":{"type":"string","enum":["auto","hubspot_form","calendly_embed","cross_domain_url"],"default":"auto","description":"Expected lead capture or handoff component type","example":"auto"},"target_selector":{"type":"string","maxLength":512},"required_params":{"type":"array","items":{"type":"string","enum":["gclid","utm_source","utm_medium","utm_campaign","utm_term","utm_content"]},"minItems":1,"maxItems":6,"default":["gclid","utm_source","utm_medium","utm_campaign","utm_term","utm_content"]},"shared_cookie_ok":{"type":"boolean","default":true,"description":"Deprecated compatibility field; cookies never replace exact target-component parameter evidence","example":true}},"default":{"target_type":"auto","required_params":["gclid","utm_source","utm_medium","utm_campaign","utm_term","utm_content"],"shared_cookie_ok":true},"description":"Expectation for the final handoff component"},"staging_bypass_headers":{"type":"object","additionalProperties":{"type":"string","maxLength":2048}},"request_headers":{"type":"object","additionalProperties":{"type":"string","maxLength":2048},"description":"Optional custom headers for automation or preview environments (e.g. x-vercel-protection-bypass). Values will NOT be stored in plaintext."}},"required":["entry_url"]},"RegressionComparisonReport":{"type":"object","properties":{"before_report_id":{"type":"string"},"after_report_id":{"type":"string"},"created_at":{"type":"string"},"overall_transition":{"type":"string","enum":["FIXED","IMPROVED","REGRESSED","UNCHANGED","NEUTRAL"]},"items":{"type":"array","items":{"type":"object","properties":{"checkpoint":{"type":"string"},"before_status":{"type":"string","enum":["VERIFIED","BROKEN","INDETERMINATE","NOT_APPLICABLE"],"description":"Four-state verification outcome (strictly avoiding false positives)","example":"VERIFIED"},"after_status":{"type":"string","enum":["VERIFIED","BROKEN","INDETERMINATE","NOT_APPLICABLE"],"description":"Four-state verification outcome (strictly avoiding false positives)","example":"VERIFIED"},"transition":{"type":"string","enum":["FIXED","REGRESSED","UNCHANGED","CHANGED"]},"notes":{"type":"string"}},"required":["checkpoint","before_status","after_status","transition","notes"]}},"summary":{"type":"string"}},"required":["before_report_id","after_report_id","created_at","overall_transition","items","summary"]},"CompareRequest":{"type":"object","properties":{"before_report_id":{"type":"string","maxLength":100,"example":"aud_before123"},"after_report_id":{"type":"string","maxLength":100,"example":"aud_after456"}},"required":["before_report_id","after_report_id"]}},"parameters":{}},"paths":{"/api/v1/audits":{"post":{"summary":"Execute an attribution handoff audit","description":"Runs browser verification across CMP states (no_action, reject, accept) to the handoff boundary.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuditRequest"}}}},"responses":{"200":{"description":"Audit execution report","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuditReport"}}}},"400":{"description":"Bad request"}}}},"/api/v1/audits/{id}":{"get":{"summary":"Retrieve an audit report by ID","parameters":[{"schema":{"type":"string","maxLength":100,"example":"aud_12345678"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Audit report details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuditReport"}}}},"404":{"description":"Audit report not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/api/v1/regressions/compare":{"post":{"summary":"Compare pre-fix vs post-fix audit reports","description":"Evaluates each checkpoint for FIXED, REGRESSED, or UNCHANGED transitions.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompareRequest"}}}},"responses":{"200":{"description":"Regression comparison report","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegressionComparisonReport"}}}},"404":{"description":"One or both reports not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/api/v1/health":{"get":{"summary":"Health check","responses":{"200":{"description":"Service is healthy","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"timestamp":{"type":"string"}},"required":["status","timestamp"]}}}}}}}}}