This article serves as a comprehensive guide to the GraphQL API provided by the Rewriter app. This API allows managing internal URLs and URL redirects.
Routes stored in the Rewriter commonly have complex paths, since they communicate with other systems and databases. To improve client-side usage and SEO rankings, the Rewriter app has, in the definition of the routes, the standard paths along with canonical (shorter) paths. For instance, the standard path to a product is /_v/segment/routing/vtex.store@2.x/product/:id/:slug/p, while the canonical path to a product is /:slug/p.
The Rewriter app is responsible for three main types of routes: product, search, and navigation routes.
The first two are first-class entities in Rewriter, meaning Rewriter identifies these routes and directly forwards them to the rendering pipeline.
Navigation routes, in turn, are client-side defined routes related to custom paths and VTEX IO pre-defined templates, such as department, brand, and category routes. These routes can have a canonical path and a search query string.
In Rewriter, navigation routes are identified by the internal type, and routes used to redirect a route from one path to another are identified by the redirect type.
The table below summarizes the classification of routes used in the API.
| Type of route | Description |
|---|---|
| Internal | Identifies navigation routes. Its standard path can have segments specifying the communication with other systems such as databases or apps, possibly making them long. It can be associated with a canonical path, omitting some segments, for improved client-side usage and SEO ranking. |
| Redirect | Navigation route that redirects one path to another. There are various reasons to use a redirect including URL changes, content removal, SEO and navigation improvements, and others. |
Rewriter includes functionalities to:
- Create an internal route.
- Create a canonical path related to an internal route.
- Create a redirect route.
- Delete an internal route.
- Delete a canonical path related to an internal route.
- Delete a redirect route.
- Create translated URLs for cross-border stores.
In the following sections are the definitions of endpoints and parameter descriptions of the Rewriter GraphQL API.
Schema overview
Query
[block:html] { "html": "<svg xmlns="http://www.w3.org/2000/svg\" viewBox="0 0 1083 572">\n \n <g id="graph1" class="graph" transform="translate(4 567)">\n \n \n @import url("https://fonts.googleapis.com/css?family=Lato|Open+Sans|Oswald|Raleway|Roboto|Indie+Flower|Gamja+Flower");\n \n \n #graph1 text{fill:#4c555a;font-family:Roboto;font-size:13px;text-anchor:middle; alignment-baseline:middle}\n \n \n #graph1 text.texttitle{font-weight:700;}\n \n \n #graph1 a{fill:#f71963}\n \n \n #graph1 rect{fill:#fff;stroke:#dfe2e5}\n \n \n #graph1 rect.title{fill:#f6f8fa}\n \n \n #graph1 polygon{stroke-width:4;fill:#eee;stroke:#dfe2e5}\n \n \n #graph1 path{stroke-width:4;fill:none;stroke:#dfe2e5}\n \n \n #graph1 path.zoom{stroke-width:1;fill:none;stroke:#000}\n \n \n #graph1 g.edge:hover text{display:block;fill:#f71963}\n \n \n #graph1 g.edge:hover path{stroke:#ADB0B3}\n \n \n #graph1 g.edge:hover polygon{fill:#ADB0B3;stroke:#ADB0B3}\n \n \n #graph1 text.arrow{display:none}\n \n \n\n <g id="node1" transform="translate(8,-407)" class="node">\n <rect width="163" height="26" class="title"/>\n <text x="81.5" y="13" class="texttitle">\n Query\n \n <rect y="26" width="163" height="26"/> \n <text x="81.5" y="39">\n version: String\n \n <rect y="52" width="163" height="26"/> \n <text x="81.5" y="65">\n <a text-anchor="middle" alignment-baseline="middle" href="#redirect">\n redirect: \n <a text-anchor="middle" alignment-baseline="middle" href="#queryredirect">\n QueryRedirect!\n \n <rect y="78" width="163" height="26"/> \n <text x="81.5" y="91">\n <a text-anchor="middle" alignment-baseline="middle" href="#internal">internal:\n <a text-anchor="middle" alignment-baseline="middle" href="#queryinternal">QueryInternal!\n \n \n\n\n <g id="node2" transform="translate(222,-463)" class="node">\n <rect width="389" height="26" class="title"/> \n <text x="194.5" y="13" class="texttitle">\n QueryRedirect\n \n <rect y="26" width="389" height="26"/> \n <text x="194.5" y="39"> \n get(path:String!, locator:<a text-anchor="middle" alignment-baseline="middle"\n href="#routelocator">RouteLocator): \n <a text-anchor="middle" alignment-baseline="middle" href="#redirect">Redirect\n \n <rect y="52" width="389" height="26"/> \n <text x="194.5" y="65"> \n listRedirects(limit:Int, next:String): \n <a text-anchor="middle" alignment-baseline="middle" href="#listredirectsresponse">ListRedirectsResponse!\n \n \n\n\n <g id="edge1" class="edge">\n <path d="M171 -340c52.4 0 108.055 -17.035 152.958 -35.48"/>\n <polygon points="322.797,-378.789 333.372,-379.432 325.506,-372.334 322.797,-378.789"/>\n <text x="285" y="-335" class="arrow">\n Query: redirect\n \n \n\n\n <g id="node3" transform="translate(133,-260)" class="node">\n <rect width="380" height="26" class="title"/> \n <text x="190" y="13" class="texttitle">\n QueryInternal\n \n <rect y="26" width="380" height="26"/> \n <text x="190" y="39">\n get(path:String!, locator:<a text-anchor="middle" alignment-baseline="middle"\n href="#routelocator">RouteLocator): <a text-anchor="middle" alignment-baseline="middle" href="#internal">Internal\n \n <rect y="52" width="380" height="26"/>\n <text x="190" y="65">\n listInternals(limit:Int, next:String): <a text-anchor="middle" alignment-baseline="middle" href="#listinternalsresponse">ListInternalsResponse!\n \n <rect y="78" width="380" height="26"/> \n <text x="190" y="91">\n routes(locator:<a text-anchor="middle" alignment-baseline="middle"\n href="#entitylocator">EntityLocator): \n <a text-anchor="middle" alignment-baseline="middle" href="#routesbybinding">[RoutesByBinding!]\n \n \n\n\n <g id="edge2" class="edge">\n <path d="M171-318c53.234 0 108.222 21.066 152.49 44.144"/>\n <polygon points="325.304 -276.856 332.483 -269.064 322.012 -270.678 325.304 -276.856"/>\n <text x="285" y="-320" class="arrow">\n Query: internal\n \n \n\n\n <g id="node4" transform="translate(901,-564)" class="node">\n <rect width="141" height="26" class="title"/> \n <text x="70.5" y="13" class="texttitle">\n Redirect\n \n <rect y="26" width="141" height="26"/> \n <text x="70.5" y="39">\n from: String!\n \n <rect y="52" width="141" height="26"/> \n <text x="70.5" y="65">\n to: String!\n \n <rect y="78" width="141" height="26"/> \n <text x="70.5" y="91">\n endDate: String\n \n <rect y="104" width="141" height="26"/> \n <text x="70.5" y="117">\n type: <a text-anchor="middle" alignment-baseline="middle" href="#redirecttypes">RedirectTypes!\n \n <rect y="130" width="141" height="26"/> \n <text x="70.5" y="143">\n binding: String!\n \n <rect y="156" width="141" height="26"/> \n <text x="70.5" y="169"> \n origin: String\n \n \n\n <g id="edge3" class="edge">\n <path d="M611-423c72.714-50.71 177.892-52.13 267.452-50.693"/>\n <polygon points="878.553 -477.192 888.448 -473.406 878.351 -470.195 878.553 -477.192"/>\n <text x="810" y="-490" class="arrow">\n QueryRedirect: get\n \n \n \n\n <g id="node5" transform="translate(662,-438)" class="node">\n <rect x="0" y="0" width="152" height="26" class="title"/>\n <text x="76" y="13" class="texttitle">\n ListRedirectsResponse\n \n <rect x="0" y="26" width="152" height="26"/>\n <text x="76" y="39">\n routes: <a text-anchor="middle" alignment-baseline="middle" href="#redirect">[Redirect!]\n \n <rect x="0" y="52" width="152" height="26"/> \n <text x="76" y="65">\n next: String\n \n \n\n\n <g id="edge4" class="edge">\n <path d="M611-398h32.844"/>\n <polygon points="643.974 -401.5 653.974 -398 643.974 -394.5 643.974 -401.5"/>\n <text x="600" y="-375" class="arrow">\n QueryRedirect: listRedirects\n \n \n\n <g id="node6" transform="translate(871,-361)" class="node">\n <rect width="202" height="26" class="title"/> \n <text x="101" y="13" class="texttitle">\n Internal\n \n <rect y="26" width="202" height="26"/> \n <text x="101" y="39">\n from: String!\n \n <rect y="52" width="202" height="26"/> \n <text x="101" y="65">\n declarer: String!\n \n <rect y="78" width="202" height="26"/> \n <text x="101" y="91">\n type: String!\n \n <rect y="104" width="202" height="26"/> \n <text x="101" y="117">\n id: String!\n \n <rect y="130" width="202" height="26"/> \n <text x="101" y="143">\n query: JSON\n \n <rect y="156" width="202" height="26"/> \n <text x="101" y="169">\n binding: String!\n \n <rect y="182" width="202" height="26"/> \n <text x="101" y="195">\n endDate: String\n \n <rect y="208" width="202" height="26"/> \n <text x="101" y="221">\n imagePath: String\n \n <rect y="234" width="202" height="26"/> \n <text x="101" y="247">\n imageTitle: String\n \n <rect y="260" width="202" height="26"/> \n <text x="101" y="273">\n routesVersion: Float\n \n <rect y="286" width="202" height="26"/> \n <text x="101" y="299">\n resolveAs: String\n \n <rect y="312" width="202" height="26"/> \n <text x="101" y="325">\n origin: String\n \n <rect y="338" width="202" height="26"/> \n <text x="101" y="351">\n disableSitemapEntry: Boolean\n \n \n\n\n <g id="edge5" class="edge">\n <path d="M512.49-230h334.915"/>\n <polygon points="857.611 -230 847.611 -226.5 847.611 -233.5"/>\n <text x="670" y="-245" class="arrow">\n QueryInternal: get\n \n \n\n\n <g id="node7" transform="translate(600,-221)" class="node">\n <rect width="150" height="26" class="title"/> \n <text x="75" y="13" class="texttitle">\n ListInternalsResponse\n \n <rect y="26" width="150" height="26"/> \n <text x="75" y="39">\n routes: <a text-anchor="middle" alignment-baseline="middle" href="#internal">[Internal!]\n \n <rect y="52" width="150" height="26"/> \n <text x="75" y="65">\n next: String\n \n \n\n\n <g id="edge6" class="edge">\n <path d="M511.87 -196c23.329 0 47.75 1.01 71.724 2.596"/>\n <polygon points="593.872,-192.016 583.494,-189.886 584.43,-196.823"/>\n <text x="540" y="-220" class="arrow">\n QueryInternal: listInternals\n \n \n\n\n <g id="node8" transform="translate(617,-125)" class="node">\n <rect width="122" height="26" class="title"/> \n <text x="61" y="13" class="texttitle">\n RoutesByBinding\n \n <rect y="26" width="122" height="26"/> \n <text x="61" y="39">\n binding: String!\n \n <rect y="52" width="122" height="26" /> \n <text x="61" y="65">\n route: String!\n \n \n\n\n <g id="edge7" class="edge">\n <path d="M512.34-171.493c25.857 0 55.24 25.974 86.66 48.493a251.463 251.463 0 007.254 5.519"/>\n <polygon points="607.852 -117.396 597.667 -120.316 601.711 -126.03"/>\n <text x="510" y="-130" class="arrow">\n QueryInternal: routes\n \n \n\n\n <g id="edge8" class="edge">\n <path d="M814-397h64.723"/>\n <polygon points="878.859 -401.5 888.859 -397.5 878.859 -394"/>\n <text x="880" y="-370" class="arrow">\n ListRedirectsResponse: routes\n \n \n\n <g id="edge9" class="edge">\n <path d="M750.392 -182h97.013"/>\n <polygon points="847.611,-185.5 857.611,-182 847.611,-178.5 847.611,-185.5"/>\n <text x="800" y="-155" class="arrow">\n ListInternalsResponse: routes\n \n \n \n" } [/block]
Mutation
[block:html] { "html": "<svg xmlns="http://www.w3.org/2000/svg\" viewBox="0 0 1083 572">\n \n <g id="graph0" class="graph" transform="translate(4 567)">\n \n \n @import url("https://fonts.googleapis.com/css?family=Lato|Open+Sans|Oswald|Raleway|Roboto|Indie+Flower|Gamja+Flower");\n \n \n #graph0 text{fill:#4c555a;font-family:Roboto;font-size:13px;text-anchor:middle; alignment-baseline:middle}\n \n \n #graph0 text.texttitle{font-weight:700;}\n \n \n #graph0 a{fill:#f71963}\n \n \n #graph0 rect{fill:#fff;stroke:#dfe2e5}\n \n \n #graph0 rect.title{fill:#f6f8fa}\n \n \n #graph0 polygon{stroke-width:4;fill:#dfe2e5;stroke:#dfe2e5}\n \n \n #graph0 path{stroke-width:4;fill:none;stroke:#dfe2e5}\n \n \n #graph0 path.zoom{stroke-width:1;fill:none;stroke:#000}\n \n \n #graph0 g.edge:hover text{display:block;fill:#f71963}\n \n \n g.edge:hover path{stroke:#ADB0B3}\n \n \n #graph0 g.edge:hover polygon{fill:#ADB0B3;stroke:#ADB0B3}\n \n \n #graph0 text.arrow{display:none}\n \n \n \n <g transform="translate(8,-382)" class="node"\n id="node1">\n <title id="mutation">Mutation <rect width="163" height="26" class="title"/>\n <text x="81.5" y="13" class="texttitle">\n Mutation\n <rect y="26" width="163" height="26"/> \n <text x="81.5" y="39">\n <a text-anchor="middle" alignment-baseline="middle"\n href="#redirect">redirect\n <a text-anchor="middle" alignment-baseline="middle"\n href="#mutateredirect">\n MutateRedirect!\n <rect y="52" width="163" height="26"/> \n <text x="81.5" y="65">\n <a text-anchor="middle" alignment-baseline="middle"\n href="#internal">internal:\n <a text-anchor="middle" alignment-baseline="middle" href="#mutateinternal">\n MutateInternal!\n \n \n <g transform="translate(250,-516)"\n class="node"\n id="node2"\n >\n <title\n id="title41">MutateRedirect<rect width="389" height="26" class="title"/>\n <text x="194.5" y="13" class="texttitle">\n MutateRedirect\n <rect y="26" width="389" height="26"/> \n <text x="194.5" y="39"> save(route: <a text-anchor="middle" alignment-baseline="middle"\n href="#redirectinput">RedirectInput!):\n <a text-anchor="middle" alignment-baseline="middle" href="#redirect">Redirect\n <rect y="52" width="389" height="26"/> \n <text x="194.5" y="65"> saveMany(routes: [<a text-anchor="middle" alignment-baseline="middle"\n href="#redirectinput">RedirectInput!]!): Boolean!\n <rect y="78" width="389" height="26"/> \n <text x="194.5" y="91"> delete(path: String! locator: <a text-anchor="middle" alignment-baseline="middle"\n href="#routelocator">RouteLocator): \n <a text-anchor="middle" alignment-baseline="middle" href="#redirect">Redirect\n <rect y="104" width="389" height="26"/> \n <text x="194.5" y="117">deleteMany(paths: [String!]! locators: [<a text-anchor="middle" alignment-baseline="middle"\n href="#routelocator">RouteLocator!]): Boolean!\n \n \n <g\n class="edge"\n id="edge1">\n <title\n id="title56">Mutation:redirectport->MutateRedirect\n <path\n id="path58"\n d="M171,-343C223.4,-343 279.055,-360.035 323.958,-378.48"/>\n <polygon\n id="polygon60"\n points="322.797,-381.789 333.372,-382.432 325.506,-375.334 322.797,-381.789"/>\n <text\n class="arrow"\n y="-330"\n x="270"\n id="text1040">Mutation: redirect\n \n \n <g\n class="node"\n transform="translate(260,-265)"\n id="node3">\n <title\n id="title63">MutateInternal\n <rect width="380" height="26" class="title"/> \n <text x="190" y="13" class="texttitle">\n MutateInternal\n <rect y="26" width="380" height="26"/> \n <text x="190" y="39">save(route: <a text-anchor="middle" alignment-baseline="middle"\n href="#internalinput">InternalInput!): \n <a text-anchor="middle" alignment-baseline="middle" href="#internal">Internal\n <rect y="52" width="380" height="26"/>\n <text x="190" y="65">saveMany(routes: [<a text-anchor="middle" alignment-baseline="middle"\n href="#internalinput">InternalInput!]!): Boolean!\n <rect y="78" width="380" height="26"/> \n <text x="190" y="91">delete(path: String! locator: <a text-anchor="middle" alignment-baseline="middle"\n href="#routelocator">RouteLocator): \n <a text-anchor="middle" alignment-baseline="middle" href="#internal">Internal\n <rect y="104" width="380" height="26"/> \n <text x="190" y="117">deleteMany(paths: [String!]! locators: [<a text-anchor="middle" alignment-baseline="middle"\n href="#routelocator">RouteLocator!]): Boolean!\n \n \n <g\n class="edge"\n id="edge2"\n <title\n id="title82">Mutation:internalport->MutateInternal\n <path\n id="path84"\n d="M171,-318C224.234,-318 279.222,-296.934 323.49,-273.856" />\n <polygon\n id="polygon86"\n points="325.304,-276.856 332.483,-269.064 322.012,-270.678 325.304,-276.856" />\n <text\n class="arrow"\n y="-325"\n x="270"\n id="text1057">Mutation: internal\n \n \n <g id="node4" transform="translate(895,-564)" class="node">\n <rect width="141" height="26" class="title"/> \n <text x="70.5" y="13" class="texttitle">\n Redirect\n \n <rect y="26" width="141" height="26"/> \n <text x="70.5" y="39">\n from: String!\n \n <rect y="52" width="141" height="26"/> \n <text x="70.5" y="65">\n to: String!\n \n <rect y="78" width="141" height="26"/> \n <text x="70.5" y="91">\n endDate: String\n \n <rect y="104" width="141" height="26"/> \n <text x="70.5" y="117">\n type: <a text-anchor="middle" alignment-baseline="middle" href="#redirecttypes">RedirectTypes!\n \n <rect y="130" width="141" height="26"/> \n <text x="70.5" y="143">\n binding: String!\n \n <rect y="156" width="141" height="26"/> \n <text x="70.5" y="169"> \n origin: String\n \n \n \n <g\n class="edge"\n id="edge3">\n <title id="title120">MutateRedirect:deleteport-Redirect\n <path id="path122" d="M638.408988 -423.268995H883.9345079999999"/>\n <polygon id="polygon124" points="874.039508,-426.724425 883.9345079999999,-422.938425 873.837508,-419.727425 NaN,NaN"/>\n <text\n class="arrow"\n y="-400"\n x="760"\n id="text1079">MutateRedirect: delete\n \n \n <g id="node6" transform="translate(871,-361)" class="node">\n <rect width="202" height="26" class="title"/> \n <text x="101" y="13" class="texttitle">\n Internal\n \n <rect y="26" width="202" height="26"/> \n <text x="101" y="39">\n from: String!\n \n <rect y="52" width="202" height="26"/> \n <text x="101" y="65">\n declarer: String!\n \n <rect y="78" width="202" height="26"/> \n <text x="101" y="91">\n type: String!\n \n <rect y="104" width="202" height="26"/> \n <text x="101" y="117">\n id: String!\n \n <rect y="130" width="202" height="26"/> \n <text x="101" y="143">\n query: JSON\n \n <rect y="156" width="202" height="26"/> \n <text x="101" y="169">\n binding: String!\n \n <rect y="182" width="202" height="26"/> \n <text x="101" y="195">\n endDate: String\n \n <rect y="208" width="202" height="26"/> \n <text x="101" y="221">\n imagePath: String\n \n <rect y="234" width="202" height="26"/> \n <text x="101" y="247">\n imageTitle: String\n \n <rect y="260" width="202" height="26"/> \n <text x="101" y="273">\n routesVersion: Float\n \n <rect y="286" width="202" height="26"/> \n <text x="101" y="299">\n resolveAs: String\n \n <rect y="312" width="202" height="26"/> \n <text x="101" y="325">\n origin: String\n \n <rect y="338" width="202" height="26"/> \n <text x="101" y="351">\n disableSitemapEntry: Boolean\n \n \n\n \n <g\n class="edge"\n id="edge5">\n <title\n id="title208">MutateInternal:saveport-Internal\n <path\n id="path210"\n d="m 640.17993,-230 c 67.21793,0 137.20647,0 207.22513,0" />\n <polygon\n id="polygon212"\n points="847.611,-226.5 847.611,-233.5 857.611,-230"/>\n <text\n class="arrow"\n y="-245"\n x="750"\n id="text1115">MutateInternal: save\n \n \n <g\n class="edge"\n id="edge7">\n <title id="title252">MutateInternal:deleteport-Internal\n <path id="path254" d="M639.58 -177.5H846.81"/>\n <polygon id="polygon256" points="847.01342131345,-181.00056601197 857.0133800773599,-177.50595082727997 847.01689767831,-174.00100372963 NaN,NaN"/>\n <text\n class="arrow"\n y="-155"\n x="750">MutateInternal: delete\n \n <g\n id="edg4"\n class="edge">\n <title\n id="title120-2">MutateRedirect:saveport-Redirect\n <path d="M638.409 -473.268995H883.935" id="path122-4"/>\n <polygon points="873.837,-469.727425 874.039,-476.724425 883.935,-472.938425 NaN,NaN" id="polygon124-8"/>\n <text\n x="760"\n y="-490"\n class="arrow">MutateRedirect: save\n \n \n" } [/block]
Schema description
[block:callout]
{
"type": "warning",
"body": "Arguments must be provided by the user. The exclamation mark ! indicates that a type cannot be nullable."
}
[/block]