API reference
Everything in the dashboard is available through the REST API. Create an API key under Workspace → Settings → API keys and send it as a Bearer token.
Authentication
curl https://adssakti.store/api/links \ -H "Authorization: Bearer sl_xxxxxxxxxxxxxxxx"
API keys are scoped to a workspace, so no workspaceId is needed. When calling the API from the browser with your session cookie, pass ?workspaceId=<id or slug>.
Create a link
curl -X POST https://adssakti.store/api/links \
-H "Authorization: Bearer sl_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/launch",
"key": "launch",
"tagNames": ["marketing"],
"expiresAt": "2027-01-01T00:00:00Z",
"geo": { "DE": "https://example.de/launch" },
"utm_source": "newsletter"
}'Errors
Errors use a consistent envelope and standard status codes (400, 401, 403, 404, 409, 422, 429, 500):
{ "error": { "code": "conflict", "message": "Key \"launch\" already exists on adssakti.store." } }Webhooks
Payload: { id, event, createdAt, data }. Verify the X-Webhook-Signature header: HMAC-SHA256 of the raw body using your endpoint secret, hex encoded.
Endpoints
/api/linkslinks.readList links. Query: search, domain, tagIds, folderId, showArchived, sortBy, page, pageSize. Total in X-Total-Count header.
/api/linkslinks.writeCreate a link. Body: url (required), domain, key, prefix, tagIds/tagNames, folderId, comments, expiresAt, expiredUrl, password, proxy+title/description/image, rewrite, doIndex, publicStats, ios, android, geo, utm_*, testVariants, externalId.
/api/links/{linkId}links.readRetrieve a link by id (or ext_<externalId>).
/api/links/{linkId}links.writeUpdate a link (same fields as create).
/api/links/{linkId}links.writeDelete a link.
/api/links/bulklinks.writeCreate up to 100 links. Body: array of link objects.
/api/links/bulklinks.writeUpdate many links. Body: { linkIds, data }.
/api/links/bulklinks.writeDelete many links. Query: linkIds=a,b,c
/api/links/countlinks.readCount links; optional groupBy=domain|tagId|userId|folderId.
/api/links/existslinks.readCheck key availability. Query: domain, key.
/api/links/infolinks.readRetrieve by domain+key, linkId or externalId.
/api/links/randomlinks.readGenerate an unused random key.
/api/links/exportlinks.readCSV export of links.
/api/analyticsanalytics.readAnalytics. Query: groupBy=count|timeseries|countries|cities|regions|continents|devices|browsers|os|triggers|referers|referer_urls|top_links|top_urls|utm_*; interval=24h|7d|30d|90d|1y|ytd|all or start/end; filters: linkId, externalId, domain, tagId, folderId, country, city, device, browser, os, referer, url, utm_*.
/api/domainsdomains.readList custom domains (includes DNS verification records).
/api/domainsdomains.writeAdd a domain. Body: slug, placeholder, expiredUrl, notFoundUrl.
/api/domains/{slug}domains.writeUpdate domain settings / archive / set primary.
/api/domains/{slug}domains.writeRemove a domain and its links.
/api/domains/{slug}/verifydomains.writeCheck the DNS TXT record and mark the domain verified.
/api/tagstags.*List / create tags. Body: name, color.
/api/tags/{id}tags.writeUpdate / delete a tag.
/api/folderslinks.*List folders you can read (includeRestricted=true lists all) / create one (you become its owner). Body: name, description, accessLevel (read|write|null).
/api/folders/{id}links.*Detail with members / update name, description, accessLevel / delete (folder owner or workspace owner).
/api/folders/{id}/userslinks.*Folder members: list / upsert { userId, role: owner|editor|viewer } / remove (query userId).
/api/folders/{id}/access-requestslinks.*Request access for yourself / list pending requests / approve or deny { userId, approve, role? }.
/api/utmList / create UTM templates.
/api/workspacesList your workspaces / create one. Body: name, slug.
/api/workspaces/{idOrSlug}Retrieve / update / delete a workspace.
/api/workspaces/{idOrSlug}/usersMembers: list, change role, remove (query userId).
/api/workspaces/{idOrSlug}/invitesEmail invites and the shareable invite link (PUT regenerates).
/api/tokensList / create API keys (key returned once).
/api/webhooksList / create webhooks. Body: name, url, triggers[].
/api/qrQR code image. Query: url, size, fgColor, bgColor, level, format=png|svg. Public.
/api/metatagsOG title/description/image for a URL. Public.
/api/abuseSubmit an abuse report. Body: name, email, url, category, reason. Public, rate limited.
Redirect behaviour
- Keys are case-insensitive by default; `/key+` opens a preview page instead of redirecting.
- Query parameters on the short link are forwarded to the destination; `?qr=1` marks a QR scan.
- Order of checks: password → banned → disabled → expired → bot/preview → cloaking → iOS → Android → geo → default.
- Clicks from known bots are not counted. One click per visitor per link per hour is recorded.
Shortlink API v1