{"openapi":"3.1.0","info":{"title":"u4.nz API","version":"1.0.0","summary":"Create short links and read their click stats.","description":"Bearer token from your dashboard. Bodies can be JSON or form-encoded; responses are JSON. 600 requests a minute per account. Redirects themselves are not rate limited. Every API request is logged with the token, IP address and status; heavy or abusive keys can be revoked.","termsOfService":"https://u4.nz/terms","contact":{"url":"https://u4.nz"}},"servers":[{"url":"https://u4.nz"}],"security":[{"bearer":[]}],"tags":[{"name":"links","description":"Your short links"},{"name":"account"},{"name":"public","description":"No token needed"}],"paths":{"/api/me":{"get":{"tags":["account"],"summary":"Account and totals","operationId":"getMe","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Me"}}}},"401":{"description":"Bad or missing token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/links":{"get":{"tags":["links"],"summary":"List your links, newest first","operationId":"listLinks","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":1000,"default":100}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"links":{"type":"array","items":{"$ref":"#/components/schemas/Link"}}}}}}},"401":{"description":"Bad or missing token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["links"],"summary":"Create a link","operationId":"createLink","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri","description":"http(s) destination. Private hosts, raw IPs and u4.nz itself are refused."},"slug":{"type":"string","pattern":"^[A-Za-z0-9]([A-Za-z0-9_-]{0,62}[A-Za-z0-9])?$","description":"Custom slug, 4 or more characters. Omit for a random 6-character one. Shorter slugs are not available."},"expires":{"type":"integer","minimum":1,"maximum":3650,"description":"Days until the link stops resolving. Omit for never."}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri","description":"http(s) destination. Private hosts, raw IPs and u4.nz itself are refused."},"slug":{"type":"string","pattern":"^[A-Za-z0-9]([A-Za-z0-9_-]{0,62}[A-Za-z0-9])?$","description":"Custom slug, 4 or more characters. Omit for a random 6-character one. Shorter slugs are not available."},"expires":{"type":"integer","minimum":1,"maximum":3650,"description":"Days until the link stops resolving. Omit for never."}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Link"}}}},"400":{"description":"Bad URL, slug or expiry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Bad or missing token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Destination host is blocked, or slug is 3 characters or fewer","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Slug taken","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/links/bulk":{"post":{"tags":["links"],"summary":"Create up to 100 links","operationId":"createLinksBulk","description":"Each item succeeds or fails on its own.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["links"],"properties":{"links":{"type":"array","maxItems":100,"items":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri","description":"http(s) destination. Private hosts, raw IPs and u4.nz itself are refused."},"slug":{"type":"string","pattern":"^[A-Za-z0-9]([A-Za-z0-9_-]{0,62}[A-Za-z0-9])?$","description":"Custom slug, 4 or more characters. Omit for a random 6-character one. Shorter slugs are not available."},"expires":{"type":"integer","minimum":1,"maximum":3650,"description":"Days until the link stops resolving. Omit for never."}}}}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["links"],"properties":{"links":{"type":"array","maxItems":100,"items":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri","description":"http(s) destination. Private hosts, raw IPs and u4.nz itself are refused."},"slug":{"type":"string","pattern":"^[A-Za-z0-9]([A-Za-z0-9_-]{0,62}[A-Za-z0-9])?$","description":"Custom slug, 4 or more characters. Omit for a random 6-character one. Shorter slugs are not available."},"expires":{"type":"integer","minimum":1,"maximum":3650,"description":"Days until the link stops resolving. Omit for never."}}}}}}}}},"responses":{"207":{"description":"Per-item results","content":{"application/json":{"schema":{"type":"object","properties":{"created":{"type":"integer"},"results":{"type":"array","items":{"oneOf":[{"allOf":[{"type":"object","properties":{"ok":{"const":true}}},{"$ref":"#/components/schemas/Link"}]},{"type":"object","properties":{"ok":{"const":false},"url":{"type":"string"},"error":{"type":"string"}}}]}}}}}}},"400":{"description":"Body is not {\"links\":[…]} or has more than 100 items","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Bad or missing token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/links/{slug}":{"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"get":{"tags":["links"],"summary":"One link","operationId":"getLink","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Link"}}}},"404":{"description":"No such link, or not yours","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"tags":["links"],"summary":"Change destination or expiry","operationId":"updateLink","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri","description":"http(s) destination. Private hosts, raw IPs and u4.nz itself are refused."},"expires":{"oneOf":[{"type":"integer","minimum":1,"maximum":3650},{"type":"null"}],"description":"Days from now, or null for never."}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri","description":"http(s) destination. Private hosts, raw IPs and u4.nz itself are refused."},"expires":{"oneOf":[{"type":"integer","minimum":1,"maximum":3650},{"type":"null"}],"description":"Days from now, or null for never."}}}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Link"}}}},"400":{"description":"Bad URL or expiry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Destination host is blocked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such link","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["links"],"summary":"Delete a link and its click history","operationId":"deleteLink","responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"const":true}}}}}},"404":{"description":"No such link","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/links/{slug}/stats":{"get":{"tags":["links"],"summary":"Click stats","operationId":"getLinkStats","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}},{"name":"days","in":"query","schema":{"type":"integer","minimum":1,"maximum":365,"default":30}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Stats"}}}},"404":{"description":"No such link","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/links/{slug}/clicks.csv":{"get":{"tags":["links"],"summary":"Raw clicks as CSV (last 90 days, 50k rows max)","operationId":"getLinkClicksCsv","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"timestamp,country,referer,device","content":{"text/csv":{"schema":{"type":"string"}}}},"404":{"description":"No such link","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/{slug}":{"get":{"tags":["public"],"summary":"Follow a short link","operationId":"redirect","security":[],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"302":{"description":"Redirect to the destination","headers":{"Location":{"schema":{"type":"string","format":"uri"}}}},"404":{"description":"Unknown or expired"},"410":{"description":"Removed by an admin"}}}},"/{slug}+":{"get":{"tags":["public"],"summary":"Preview page: shows the destination instead of following it","operationId":"preview","security":[],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"HTML","content":{"text/html":{}}},"404":{"description":"Unknown or expired"}}}},"/{slug}.qr.svg":{"get":{"tags":["public"],"summary":"QR code for a short link","operationId":"qr","security":[],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"SVG","content":{"image/svg+xml":{}}},"404":{"description":"Unknown or expired"}}}}},"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"Token from the dashboard, prefixed u4_. Stored hashed; shown once."}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"string"}}},"Link":{"type":"object","properties":{"slug":{"type":"string"},"short":{"type":"string","format":"uri","example":"https://u4.nz/launch"},"qr":{"type":"string","format":"uri","example":"https://u4.nz/launch.qr.svg"},"url":{"type":"string","format":"uri"},"created_at":{"type":"integer","description":"Unix ms"},"expires_at":{"type":["integer","null"],"description":"Unix ms, or null for never"},"clicks":{"type":"integer"}}},"Stats":{"type":"object","properties":{"slug":{"type":"string"},"clicks":{"type":"integer","description":"All-time"},"window_days":{"type":"integer"},"window_clicks":{"type":"integer"},"by_day":{"type":"array","items":{"type":"object","properties":{"day":{"type":"string","format":"date"},"n":{"type":"integer"}}}},"by_country":{"type":"array","items":{"type":"object","properties":{"k":{"type":"string"},"n":{"type":"integer"}}}},"by_referer":{"type":"array","items":{"type":"object","properties":{"k":{"type":"string"},"n":{"type":"integer"}}}},"by_device":{"type":"array","items":{"type":"object","properties":{"k":{"type":"string"},"n":{"type":"integer"}}}}}},"Me":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"created_at":{"type":"integer"},"links":{"type":"integer"},"clicks":{"type":"integer"},"top":{"type":"array","items":{"type":"object","properties":{"k":{"type":"string"},"n":{"type":"integer"}}}}}}}}}