Slug rules
Slugs are the part of a share URL you choose — the q1-report in
https://anchorify.io/alice/q1-report. They are validated on every
publish.
The regex
^[a-z0-9](?:[a-z0-9-]{0,58}[a-z0-9])?$
In plain language:
- 1 to 60 characters total
- Lowercase letters (
a–z), digits (0–9), and hyphens (-) only - Cannot start or end with a hyphen
- Single-character slugs are allowed (e.g.
a,7) - No underscores, no uppercase, no dots, no slashes, no spaces, no punctuation, no unicode
Valid examples
q1-reportnotes-2026acardinal-heating-auditslug-with-many-hyphens-heregeology-week3
Invalid examples
| Slug | Why it fails |
|---|---|
Bad_Slug! |
uppercase + underscore + punctuation |
-leading |
starts with a hyphen |
trailing- |
ends with a hyphen |
UPPERCASE |
uppercase letters |
has space |
contains a space |
under_score |
contains an underscore |
dot.in.slug |
contains a dot |
slash/in/slug |
contains a slash |
| (empty string) | must be at least 1 character |
| 61+ chars | exceeds 60-char limit |
Random IDs are slugs too
When you publish without choosing a slug, the server assigns a random
8-character base36 id (e.g. k3p9x2af). Those random ids satisfy the
same regex, so the id column is polymorphic — every value, random or
chosen, is a valid slug.
Error response
A POST with an invalid slug returns:
{
"error": "invalid slug",
"reason": "must be lowercase alphanumeric + hyphens, 1-60 chars, no leading/trailing dash"
}
with HTTP status 400. If the slug is valid but already taken, the
status is 409 with {"error":"slug taken","slug":"<the-slug>"}
instead — pick a different one and retry.