{"id":"url-canonicalize","title":"URL canonicalizer and lookalike-host check","description":"Canonicalizes up to 50 absolute http(s) URLs for an agent about to fetch, dedupe or click them: WHATWG-parsed lowercase host, default port and fragment and userinfo removed, dot segments and unreserved percent-escapes normalized, tracking parameters (utm_*, gclid, fbclid and the Mozilla strip list plus yours) removed, and flags userinfo@host tricks, backslash and multiple-@ authorities, obfuscated IPv4 hosts, xn-- labels (decoded to Unicode, invalid or ASCII-only punycode, mixed-script hosts via the Unicode safety rules) and open-redirect-shaped parameters (next=, redirect=, url= pointing off-site or at //host or javascript:). Does NOT resolve DNS, fetch anything, follow redirects, or decide that a site is safe; registrable domains use a public-suffix SUBSET plus any suffixes you supply.","roi":"Catches the URL that reads as one site and loads another, and gives stable keys for dedupe, 50 URLs per $0.005 call.","audience":"developer","package":"infra-preflight-kit","channels":["x402","mcp"],"endpoint":{"method":"POST","url":"https://agents.writerslogic.com/api/v1/url-canonicalize","path":"/api/v1/url-canonicalize","contentType":"application/json"},"price":{"amount":"0.005","currency":"USDC","network":"base","perCall":true,"failedCallsCharged":false},"inputSchema":{"type":"object","additionalProperties":false,"required":["urls"],"properties":{"urls":{"type":"array","minItems":1,"maxItems":50,"items":{"type":"string","maxLength":2048},"description":"Absolute URLs including the scheme."},"extraTrackingParams":{"type":"array","maxItems":50,"items":{"type":"string","maxLength":64},"description":"Extra query parameter names to strip (case-insensitive)."},"sortQuery":{"type":"boolean","description":"Sort remaining query segments for a dedupe key. Off by default: order can matter to servers."},"publicSuffixes":{"type":"array","maxItems":200,"items":{"type":"string","maxLength":100},"description":"Extra public suffixes (e.g. \"co.xx\") used for registrable-domain decisions."}}},"resultSchema":{"type":"object","properties":{"status":{"type":"string","enum":["pass","fail","unknown","unsupported"],"description":"pass: 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."},"items":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer"},"valid":{"type":"boolean"},"canonical":{"description":"Canonical URL, or null when the input does not parse."},"host":{"description":"ASCII (punycode) host with non-default port."},"hostUnicode":{"description":"Host with xn-- labels decoded."},"registrableDomain":{"description":"eTLD+1 from the public-suffix subset plus caller suffixes."},"removedParams":{"type":"array","items":{"type":"string"}},"findings":{"type":"array","items":{"type":"object","properties":{"ruleId":{"type":"string"},"severity":{"type":"string","enum":["info","warn","risk"]},"detail":{"type":"string"}}}}}}},"riskCount":{"type":"integer","description":"Number of items with at least one risk finding."},"witnesses":{"type":"array","items":{"type":"object","properties":{"ruleId":{"type":"string"},"detail":{"type":"string"},"path":{"type":"string","description":"JSON pointer or dotted path into the input."},"offset":{"type":"integer"},"index":{"type":"integer"},"expected":{"description":"What the rule required."},"actual":{"description":"What the input had."}}}},"versions":{"type":"object","description":"Every semantic dependency of this answer (engine, tables and their as-of dates, tokenizer, calendar, rounding profile)."},"limits":{"type":"array","items":{"type":"string"}},"deterministic":{"type":"boolean","description":"Always true: pure code, no model."}}},"outputSchema":{"type":"object","properties":{"data":{"type":"object","properties":{"status":{"type":"string","enum":["pass","fail","unknown","unsupported"],"description":"pass: 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."},"items":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer"},"valid":{"type":"boolean"},"canonical":{"description":"Canonical URL, or null when the input does not parse."},"host":{"description":"ASCII (punycode) host with non-default port."},"hostUnicode":{"description":"Host with xn-- labels decoded."},"registrableDomain":{"description":"eTLD+1 from the public-suffix subset plus caller suffixes."},"removedParams":{"type":"array","items":{"type":"string"}},"findings":{"type":"array","items":{"type":"object","properties":{"ruleId":{"type":"string"},"severity":{"type":"string","enum":["info","warn","risk"]},"detail":{"type":"string"}}}}}}},"riskCount":{"type":"integer","description":"Number of items with at least one risk finding."},"witnesses":{"type":"array","items":{"type":"object","properties":{"ruleId":{"type":"string"},"detail":{"type":"string"},"path":{"type":"string","description":"JSON pointer or dotted path into the input."},"offset":{"type":"integer"},"index":{"type":"integer"},"expected":{"description":"What the rule required."},"actual":{"description":"What the input had."}}}},"versions":{"type":"object","description":"Every semantic dependency of this answer (engine, tables and their as-of dates, tokenizer, calendar, rounding profile)."},"limits":{"type":"array","items":{"type":"string"}},"deterministic":{"type":"boolean","description":"Always true: pure code, no model."}}},"_provenance":{"type":"object","description":"C2PA-aligned manifest and W3C VC 2.0 (eddsa-jcs-2022) issued by the hub DID; verify at POST /api/v1/verify-provenance"}},"required":["data","_provenance"]},"example":{"urls":["HTTPS://Example.COM:443/a/./b/%7Efoo?utm_source=x&id=7&gclid=abc#top","https://paypal.com@evil.example/login","https://xn--pple-43d.com/","https://shop.example/login?next=https://evil.example/steal"]},"openapiOperation":{"operationId":"url_canonicalize","summary":"URL canonicalizer and lookalike-host check","description":"Canonicalizes up to 50 absolute http(s) URLs for an agent about to fetch, dedupe or click them: WHATWG-parsed lowercase host, default port and fragment and userinfo removed, dot segments and unreserved percent-escapes normalized, tracking parameters (utm_*, gclid, fbclid and the Mozilla strip list plus yours) removed, and flags userinfo@host tricks, backslash and multiple-@ authorities, obfuscated IPv4 hosts, xn-- labels (decoded to Unicode, invalid or ASCII-only punycode, mixed-script hosts via the Unicode safety rules) and open-redirect-shaped parameters (next=, redirect=, url= pointing off-site or at //host or javascript:). Does NOT resolve DNS, fetch anything, follow redirects, or decide that a site is safe; registrable domains use a public-suffix SUBSET plus any suffixes you supply.\n\nPrice: 0.005 USDC on Base (x402).","x-x402-price-usdc":"0.005","x-x402-amount":"5000","x-payment-info":{"protocols":["x402"],"price":{"mode":"fixed","currency":"USD","amount":"0.005"}},"x-audience":"developer","x-sample-url":"https://agents.writerslogic.com/api/v1/samples/url-canonicalize","security":[{"x402":[]},{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["urls"],"properties":{"urls":{"type":"array","minItems":1,"maxItems":50,"items":{"type":"string","maxLength":2048},"description":"Absolute URLs including the scheme."},"extraTrackingParams":{"type":"array","maxItems":50,"items":{"type":"string","maxLength":64},"description":"Extra query parameter names to strip (case-insensitive)."},"sortQuery":{"type":"boolean","description":"Sort remaining query segments for a dedupe key. Off by default: order can matter to servers."},"publicSuffixes":{"type":"array","maxItems":200,"items":{"type":"string","maxLength":100},"description":"Extra public suffixes (e.g. \"co.xx\") used for registrable-domain decisions."}}},"example":{"urls":["HTTPS://Example.COM:443/a/./b/%7Efoo?utm_source=x&id=7&gclid=abc#top","https://paypal.com@evil.example/login","https://xn--pple-43d.com/","https://shop.example/login?next=https://evil.example/steal"]}}}},"responses":{"200":{"description":"Paid result with provenance","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"status":{"type":"string","enum":["pass","fail","unknown","unsupported"],"description":"pass: 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."},"items":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer"},"valid":{"type":"boolean"},"canonical":{"description":"Canonical URL, or null when the input does not parse."},"host":{"description":"ASCII (punycode) host with non-default port."},"hostUnicode":{"description":"Host with xn-- labels decoded."},"registrableDomain":{"description":"eTLD+1 from the public-suffix subset plus caller suffixes."},"removedParams":{"type":"array","items":{"type":"string"}},"findings":{"type":"array","items":{"type":"object","properties":{"ruleId":{"type":"string"},"severity":{"type":"string","enum":["info","warn","risk"]},"detail":{"type":"string"}}}}}}},"riskCount":{"type":"integer","description":"Number of items with at least one risk finding."},"witnesses":{"type":"array","items":{"type":"object","properties":{"ruleId":{"type":"string"},"detail":{"type":"string"},"path":{"type":"string","description":"JSON pointer or dotted path into the input."},"offset":{"type":"integer"},"index":{"type":"integer"},"expected":{"description":"What the rule required."},"actual":{"description":"What the input had."}}}},"versions":{"type":"object","description":"Every semantic dependency of this answer (engine, tables and their as-of dates, tokenizer, calendar, rounding profile)."},"limits":{"type":"array","items":{"type":"string"}},"deterministic":{"type":"boolean","description":"Always true: pure code, no model."}}},"_provenance":{"type":"object","description":"C2PA-aligned manifest and W3C VC 2.0 (eddsa-jcs-2022) issued by the hub DID; verify at POST /api/v1/verify-provenance"}},"required":["data","_provenance"]}}}},"400":{"description":"Invalid request (no payment consumed)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"}}}}}},"401":{"description":"Invalid X-API-KEY","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"}}}}}},"402":{"description":"Payment required or invalid","content":{"application/json":{"schema":{"type":"object","description":"x402 v2 PaymentRequired (also base64 in the PAYMENT-REQUIRED header)","properties":{"x402Version":{"type":"integer"},"error":{"type":"string"},"code":{"type":"string"},"resource":{"type":"object"},"accepts":{"type":"array","items":{"type":"object"}},"extensions":{"type":"object"}}}}}},"502":{"description":"Upstream failure; the payment is released or not settled","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"}}}}}}}},"links":{"docs":"https://agents.writerslogic.com/docs/url-canonicalize/","docsJson":"https://agents.writerslogic.com/docs/url-canonicalize.json","sample":"https://agents.writerslogic.com/api/v1/samples/url-canonicalize","openapi":"https://agents.writerslogic.com/openapi.json","catalog":"https://agents.writerslogic.com/api/v1/catalog","verifyProvenance":"https://agents.writerslogic.com/api/v1/verify-provenance","index":"https://agents.writerslogic.com/docs/index.json"}}