{"openapi":"3.1.0","info":{"title":"URL Canonicalize API","version":"1.0.0","description":"Normalize URLs to a canonical form so you can deduplicate, compare and clean them. The canonicalize endpoint lower-cases the scheme and host, drops the default port (80 for http, 443 for https), resolves ./ and ../ path segments and fixes percent-encoding using the standard WHATWG URL parser, then applies the cleanups you choose: strip marketing and analytics tracking parameters (all utm_* plus gclid, fbclid, msclkid, yclid, mc_eid and many more), sort the remaining query parameters into a stable order, optionally drop the #fragment, and add or remove the trailing slash. It returns the canonical URL, the fully parsed components and the exact list of changes it made. The compare endpoint canonicalizes two URLs and tells you whether they point to the same resource — perfect for catching duplicate links that differ only by tracking codes, casing, port or parameter order. Everything is computed locally with no network calls, so it is instant, private and safe. Ideal for crawlers and SEO tooling, link deduplication and analytics, cache keys, bookmarking and content pipelines. Pure local computation — no key, no third-party service, instant. Live, nothing stored. 3 endpoints. This canonicalizes the URL string; it does not fetch it or follow redirects — for link previews and unshortening use a URL-unfurl API.","contact":{"name":"PremiumApi","url":"https://www.oanor.com/by/premiumapi"}},"servers":[{"url":"https://api.oanor.com/urlcanon-api","description":"oanor gateway"}],"tags":[{"name":"URL"},{"name":"Meta"}],"components":{"securitySchemes":{"oanorKey":{"type":"apiKey","in":"header","name":"x-oanor-key","description":"Get your key at https://www.oanor.com/developer/keys"}}},"security":[{"oanorKey":[]}],"paths":{"/v1/canonicalize":{"get":{"operationId":"get_v1_canonicalize","tags":["URL"],"summary":"Canonicalize a URL","description":"","parameters":[{"name":"url","in":"query","required":true,"description":"The URL (with scheme)","schema":{"type":"string"},"example":"HTTPS://Example.COM:443/a/./b/../c?utm_source=x&b=2&a=1"},{"name":"remove_tracking","in":"query","required":false,"description":"Strip utm_*/gclid/fbclid… (default true)","schema":{"type":"string"}},{"name":"sort_query","in":"query","required":false,"description":"Sort query parameters (default true)","schema":{"type":"string"}},{"name":"remove_fragment","in":"query","required":false,"description":"Drop the #fragment (default false)","schema":{"type":"string"}},{"name":"trailing_slash","in":"query","required":false,"description":"keep (default), add or remove","schema":{"type":"string"}},{"name":"lowercase_path","in":"query","required":false,"description":"Lower-case the path (default false)","schema":{"type":"string"}}],"security":[{"oanorKey":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"data":{"input":"HTTPS://Example.COM:443/a/./b/../c?utm_source=x&b=2&a=1","changed":true,"changes":["normalized scheme/host/port/path encoding","removed tracking parameters","sorted query parameters"],"canonical":"https://example.com/a/c?a=1&b=2","components":{"host":"example.com","path":"/a/c","query":{"a":"1","b":"2"},"scheme":"https"}},"meta":{"timestamp":"2026-06-03T09:24:58.352Z","request_id":"a9b44bee-b3c4-40fc-a762-abe2e7b6abdd"},"status":"ok","message":"Canonicalize a URL","success":true}}}},"401":{"description":"Missing or invalid x-oanor-key header"},"402":{"description":"Active subscription required"},"429":{"description":"Rate-limit or monthly quota reached"},"502":{"description":"Upstream did not respond"}}}},"/v1/compare":{"get":{"operationId":"get_v1_compare","tags":["URL"],"summary":"Compare two URLs","description":"","parameters":[{"name":"a","in":"query","required":true,"description":"First URL","schema":{"type":"string"},"example":"https://X.com/p?utm_source=z&a=1"},{"name":"b","in":"query","required":true,"description":"Second URL","schema":{"type":"string"},"example":"https://x.com:443/p?a=1"}],"security":[{"oanorKey":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"data":{"a":{"input":"https://X.com/p?utm_source=z&a=1","canonical":"https://x.com/p?a=1"},"b":{"input":"https://x.com:443/p?a=1","canonical":"https://x.com/p?a=1"},"same":true},"meta":{"timestamp":"2026-06-03T09:24:58.453Z","request_id":"3c540c9b-600e-4986-ad0f-19bab0a2a9a1"},"status":"ok","message":"Compare two URLs","success":true}}}},"401":{"description":"Missing or invalid x-oanor-key header"},"402":{"description":"Active subscription required"},"429":{"description":"Rate-limit or monthly quota reached"},"502":{"description":"Upstream did not respond"}}}},"/v1/meta":{"get":{"operationId":"get_v1_meta","tags":["Meta"],"summary":"Spec","description":"","parameters":[],"security":[{"oanorKey":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":{"data":{"name":"URL Canonicalize API","notes":"Scheme and host are lower-cased and the default port dropped; the path is case-sensitive so it is left as-is unless lowercase_path is set. This canonicalizes the URL string locally — it does not fetch it or follow redirects (use a URL-unfurl/unshorten API for that). Nothing is stored.","version":"v1","endpoints":[{"path":"/v1/canonicalize","params":{"url":"the URL (required, with scheme)","sort_query":"sort query parameters (default true)","lowercase_path":"lower-case the path (default false)","trailing_slash":"keep (default), add or remove","remove_fragment":"drop the #fragment (default false)","remove_tracking":"strip utm_*/gclid/fbclid… (default true)"},"returns":"the canonical URL, its components and the changes made"},{"path":"/v1/compare","params":{"a":"first URL (required)","b":"second URL (required)","…options":"same options as canonicalize"},"returns":"whether a and b are the same URL, with both canonical forms"},{"path":"/v1/meta","params":[],"returns":"this document"}],"description":"Normalize URLs to a canonical form so you can deduplicate and compare them. The canonicalize endpoint lower-cases the scheme and host, removes the default port (80/443), resolves ./ and ../ path segments and fixes percent-encoding (all via the WHATWG URL parser), then applies the cleanups you want: strip marketing/analytics tracking parameters (utm_*, gclid, fbclid, msclkid and many more), sort the remaining query parameters, optionally drop the #fragment, and add or remove the trailing slash. It returns the canonical URL, the parsed components and exactly which changes were made. The compare endpoint canonicalizes two URLs and tells you whether they point to the same resource. Pure local, no network, no key."},"meta":{"timestamp":"2026-06-03T09:24:58.563Z","request_id":"b7990b1b-f008-4d32-abca-9d199697c8d1"},"status":"ok","message":"Meta","success":true}}}},"401":{"description":"Missing or invalid x-oanor-key header"},"402":{"description":"Active subscription required"},"429":{"description":"Rate-limit or monthly quota reached"},"502":{"description":"Upstream did not respond"}}}}},"x-oanor-pricing":[{"slug":"free","name":"Free","price_cents_month":0,"monthly_call_quota":4035,"rps_limit":2,"hard_limit":true},{"slug":"starter","name":"Starter","price_cents_month":555,"monthly_call_quota":13550,"rps_limit":8,"hard_limit":true},{"slug":"pro","name":"Pro","price_cents_month":2545,"monthly_call_quota":186500,"rps_limit":20,"hard_limit":true},{"slug":"mega","name":"Mega","price_cents_month":6345,"monthly_call_quota":975000,"rps_limit":50,"hard_limit":true}],"x-oanor-marketplace-url":"https://www.oanor.com/api/urlcanon-api"}