Skip to content

Create a short link on the domain

POST
/api/v1/domains/{domain_id}/short_links
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.

domain_id
required
string format: uuid
Media typeapplication/json
object
slug

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.

string
<= 200 characters
destination_url
required

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://.”

string format: uri
status_code

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.

integer
default: 302
Allowed values: 301 302 307 308
preserve_query

Defaults to true. An explicit null means “not supplied” and yields that default.

boolean
default: true
expires_at

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.”

string | null format: date-time
Example
{
"slug": "docs",
"destination_url": "https://docs.example.com",
"status_code": 302,
"preserve_query": true
}

Created — published to the edge by a background job

Media typeapplication/json
object
short_link
required

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
id
required
string format: uuid
domain_id
required
string format: uuid
path
required

Canonical stored form, always with a leading slash. Matched exactly and case-sensitively at the edge.

string
url
required

Https:// + the domain’s hostname + path.

string format: uri
destination_url
required
string format: uri
status_code
required
integer
Allowed values: 301 302 307 308
preserve_query
required
boolean
enabled
required
boolean
expires_at
required
string | null format: date-time
created_at
required
string format: date-time
Example
{
"short_link": {
"path": "/docs",
"url": "https://go.example.com/docs",
"status_code": 301
}
}

Missing or invalid API key

Media typeapplication/json

The ONLY error envelope — produced by Api::V1::BaseController#render_error_response

object
error
required
string
errors
Array<string>
validation_errors
object
key
additional properties
Array<string>
Example
{
"error": "Invalid API key",
"errors": [],
"validation_errors": {}
}

API access has not been enabled; org suspended; or owner email unverified

Media typeapplication/json

The ONLY error envelope — produced by Api::V1::BaseController#render_error_response

object
error
required
string
errors
Array<string>
validation_errors
object
key
additional properties
Array<string>
Examplegenerated
{
"error": "example",
"errors": [
"example"
],
"validation_errors": {
"additionalProperty": [
"example"
]
}
}

Not found (cross-tenant ids are indistinguishable from missing ones)

Media typeapplication/json

The ONLY error envelope — produced by Api::V1::BaseController#render_error_response

object
error
required
string
errors
Array<string>
validation_errors
object
key
additional properties
Array<string>
Example
{
"error": "Not found",
"errors": [],
"validation_errors": {}
}

Validation failed (validation_errors keyed by attribute)

Media typeapplication/json

The ONLY error envelope — produced by Api::V1::BaseController#render_error_response

object
error
required
string
errors
Array<string>
validation_errors
object
key
additional properties
Array<string>
Examplegenerated
{
"error": "example",
"errors": [
"example"
],
"validation_errors": {
"additionalProperty": [
"example"
]
}
}

Over 300 requests/minute for this key

Media typeapplication/json

The ONLY error envelope — produced by Api::V1::BaseController#render_error_response

object
error
required
string
errors
Array<string>
validation_errors
object
key
additional properties
Array<string>
Example
{
"error": "Rate limit exceeded",
"errors": [],
"validation_errors": {}
}