Create a short link on the domain
const url = 'https://app.routeseam.com/api/v1/domains/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/short_links';const options = { method: 'POST', headers: {'X-Api-Key': '<X-Api-Key>', 'Content-Type': 'application/json'}, body: '{"slug":"docs","destination_url":"https://docs.example.com","status_code":302,"preserve_query":true}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://app.routeseam.com/api/v1/domains/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/short_links \ --header 'Content-Type: application/json' \ --header 'X-Api-Key: <X-Api-Key>' \ --data '{ "slug": "docs", "destination_url": "https://docs.example.com", "status_code": 302, "preserve_query": true }'A short link answers one exact path; at the edge an exact path match
beats the domain’s catch-all. Each link counts against the plan’s route
limit like any other route, so 403 also covers “route limit reached”.
A 422 carries the reason in error; validation_errors stays empty.
Every body field must be a single scalar — a list or an object in place
of one is a 422 naming the field.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”Request Bodyrequired
Section titled “Request Bodyrequired”object
Path after the hostname. Letters, numbers and - . _ ~ , starting with a letter or number, optionally nested with / (go/docs). A leading or trailing slash is stripped, so docs and /docs are the same slug. Case is preserved and matched exactly. Omit it (or send it blank) to have a random seven-character slug generated.
Destination URL; normalized server-side. Required — an absent key is forwarded as an empty string rather than reported as missing, so leaving it out answers 422 with “Destination must start with http:// or https://.”
Defaults to 302, not the 308 a domain catch-all defaults to. Omit the key to get that default: an explicit null is a 422 with “Choose one of 301, 302, 307 or 308.”, not a fallback.
Defaults to true. An explicit null means “not supplied” and yields that default.
Must be in the future. Omit it or send null for no expiry. A scalar that is not a date, such as true, answers 422 with “Set an expiry date in the future, or leave it empty.”
Example
{ "slug": "docs", "destination_url": "https://docs.example.com", "status_code": 302, "preserve_query": true}Responses
Section titled “Responses”Created — published to the edge by a background job
object
Exactly the keys Api::V1::ShortLinkSerializer emits. preserve_path and kind are deliberately absent: the edge ignores preserve_path for short links, and kind is an internal discriminator.
object
Canonical stored form, always with a leading slash. Matched exactly and case-sensitively at the edge.
Https:// + the domain’s hostname + path.
Example
{ "short_link": { "path": "/docs", "url": "https://go.example.com/docs", "status_code": 301 }}Missing or invalid API key
The ONLY error envelope — produced by Api::V1::BaseController#render_error_response
object
object
Example
{ "error": "Invalid API key", "errors": [], "validation_errors": {}}API access has not been enabled; org suspended; or owner email unverified
The ONLY error envelope — produced by Api::V1::BaseController#render_error_response
object
object
Examplegenerated
{ "error": "example", "errors": [ "example" ], "validation_errors": { "additionalProperty": [ "example" ] }}Not found (cross-tenant ids are indistinguishable from missing ones)
The ONLY error envelope — produced by Api::V1::BaseController#render_error_response
object
object
Example
{ "error": "Not found", "errors": [], "validation_errors": {}}Validation failed (validation_errors keyed by attribute)
The ONLY error envelope — produced by Api::V1::BaseController#render_error_response
object
object
Examplegenerated
{ "error": "example", "errors": [ "example" ], "validation_errors": { "additionalProperty": [ "example" ] }}Over 300 requests/minute for this key
The ONLY error envelope — produced by Api::V1::BaseController#render_error_response
object
object
Example
{ "error": "Rate limit exceeded", "errors": [], "validation_errors": {}}