API reference
The HTTP API uses Laravel Sanctum. Authenticate with a Bearer token. Workspace routes require membership and scoped token abilities for read and write operations.
Authentication model
- Session cookies apply to browser use; programmatic access uses personal access tokens.
- Tokens are created per user and carry one or more abilities, e.g.
workspace:acme-corp:readandworkspace:acme-corp:write. - Read routes require a matching
:read(or:write). Mutating routes require:write.
Base URL
All paths below are relative to your deployment origin. Versioned endpoints are available under /api/v1 and should be preferred for new integrations. Legacy unversioned endpoints remain for backward compatibility during migration.
Rate limiting
Workspace API routes are throttled per authenticated user and workspace (see API_WORKSPACE_REQUESTS_PER_MINUTE in environment configuration, default 120 per rolling minute). Expect HTTP 429 when exceeded.
Endpoints
| Method | Path | Middleware | Description |
|---|---|---|---|
GET |
/api/user |
auth:sanctum |
Returns the authenticated user for the given Bearer token or session. |
GET |
/api/workspaces/{workspace}/tokens |
auth:sanctum, workspace.member, workspace.sanctum:read, workspace.api |
Lists workspace-scoped API tokens for workspace members (metadata only, no plaintext tokens). |
POST |
/api/workspaces/{workspace}/tokens |
auth:sanctum, workspace.member, workspace.sanctum:write, workspace.api |
Creates a named personal access token scoped to the workspace. Supports scope=read_only or scope=read_write (default). Plaintext token returned once. |
DELETE |
/api/workspaces/{workspace}/tokens/{tokenId} |
auth:sanctum, workspace.member, workspace.sanctum:write, workspace.api |
Revokes a workspace token immediately. |
GET |
/api/workspaces/{workspace}/links |
auth:sanctum, workspace.member, workspace.sanctum:read, workspace.api |
Paginated list of links. Optional query: status=active|archived, per_page=1–100. |
POST |
/api/workspaces/{workspace}/links |
auth:sanctum, workspace.member, workspace.sanctum:write, workspace.api |
Creates a link. Requires a role that can manage link content. Returns 422 when the active-link quota is exceeded. |
GET |
/api/workspaces/{workspace}/links/{id} |
auth:sanctum, workspace.member, workspace.sanctum:read, workspace.api |
Returns one link scoped to the workspace (implicit binding). |
PATCH |
/api/workspaces/{workspace}/links/{id} |
auth:sanctum, workspace.member, workspace.sanctum:write, workspace.api |
Updates title, destination URL, campaign tag, UTM defaults, or status. Reactivating from archived counts toward the active-link quota. |
DELETE |
/api/workspaces/{workspace}/links/{id} |
auth:sanctum, workspace.member, workspace.sanctum:write, workspace.api |
Deletes the link (owner role required, same as the web app). |
POST |
/api/workspaces/{workspace}/links/import |
auth:sanctum, workspace.member, workspace.sanctum:write, workspace.api |
Queues a bulk link import; poll progress at GET /links/imports/{id}. |
POST |
/api/workspaces/{workspace}/conversions |
auth:sanctum, workspace.member, workspace.sanctum:write, workspace.api |
Records a server-side conversion against a link by short_code or id and fans out conversion.recorded webhooks. |
GET/POST/PATCH/DELETE |
/api/workspaces/{workspace}/folders |
auth:sanctum, workspace.member, workspace.sanctum, workspace.api |
Manage folders for organizing links (reads need :read ability, writes need :write). |
GET/POST/PATCH/DELETE |
/api/workspaces/{workspace}/tags |
auth:sanctum, workspace.member, workspace.sanctum, workspace.api |
Manage tags for cross-cutting link organization. |
GET/POST/PATCH/DELETE |
/api/workspaces/{workspace}/utm-templates |
auth:sanctum, workspace.member, workspace.sanctum, workspace.api |
Manage reusable UTM templates applied when creating or editing links. |
GET |
/api/workspaces/{workspace}/analytics/summary |
auth:sanctum, workspace.member, workspace.sanctum:read, workspace.api |
Read-only analytics summary (KPIs, trend, device breakdown). Requires Owner, Admin, or Analyst (same as CSV export). Query params: start_date, end_date, link_id, device, campaign, trigger=all|link|qr (use all or omit to disable a filter). |
GET |
/api/workspaces/{workspace}/analytics/scans |
auth:sanctum, workspace.member, workspace.sanctum:read, workspace.api |
Paginated scan rows with the same filters as summary/export. Optional: page, per_page (1–100). |
GET |
/api/workspaces/{workspace}/analytics/filters |
auth:sanctum, workspace.member, workspace.sanctum:read, workspace.api |
Link list and distinct campaign values for building filter UIs (export role required). |
GET |
/api/v1/workspaces/{workspace}/audit-logs |
auth:sanctum, workspace.member, workspace.sanctum:read, workspace.api |
List audit log events with optional filters: action, actor, from, to. |
GET |
/api/v1/workspaces/{workspace}/audit-logs/export |
auth:sanctum, workspace.member, workspace.sanctum:read, workspace.api |
Export filtered audit log CSV (Enterprise entitlement required). |
GET |
/api/workspaces/{workspace}/webhooks |
auth:sanctum, workspace.member, workspace.sanctum:read, workspace.api |
List outbound webhook endpoints for the workspace. Requires a role that can manage content (Owner/Admin). |
POST |
/api/workspaces/{workspace}/webhooks |
auth:sanctum, workspace.member, workspace.sanctum:write, workspace.api |
Create endpoint URL + event list and receive a signing secret once in meta.signing_secret. |
PATCH |
/api/workspaces/{workspace}/webhooks/{id} |
auth:sanctum, workspace.member, workspace.sanctum:write, workspace.api |
Update endpoint URL/description/events/enabled and optionally rotate signing secret with rotate_secret=true. |
DELETE |
/api/workspaces/{workspace}/webhooks/{id} |
auth:sanctum, workspace.member, workspace.sanctum:read, workspace.api |
Delete endpoint and delivery logs. |
GET |
/api/workspaces/{workspace}/webhooks/{id}/deliveries |
auth:sanctum, workspace.member, workspace.sanctum, workspace.api |
Paginated delivery attempts including status code, attempt number, and error details. |
GET |
/api/workspaces/{workspace}/domains |
auth:sanctum, workspace.member, workspace.sanctum:read, workspace.api |
List custom domains with status, DNS instructions (TXT name/value, CNAME target), and not-found fallback. |
POST |
/api/workspaces/{workspace}/domains |
auth:sanctum, workspace.member, workspace.sanctum:write, workspace.api |
Register a hostname (plan-limited) and queue the first DNS TXT verification check. |
PATCH |
/api/workspaces/{workspace}/domains/{id} |
auth:sanctum, workspace.member, workspace.sanctum:write, workspace.api |
Update the domain not_found_url fallback for unknown short codes. |
DELETE |
/api/workspaces/{workspace}/domains/{id} |
auth:sanctum, workspace.member, workspace.sanctum:write, workspace.api |
Remove a domain; assigned links fall back to the default short link host. |
POST |
/api/workspaces/{workspace}/domains/{id}/verify |
auth:sanctum, workspace.member, workspace.sanctum:write, workspace.api |
Queue a DNS ownership re-check; responds 202 Accepted. |
Create a token (example)
While signed in, POST JSON with a display name. The response includes the plaintext token—store it securely.
curl -X POST "https://link.iutils.net/api/workspaces/{workspace}/tokens" \
-H "Authorization: Bearer {existing_token_or_session_not_used_here}" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"name":"CI export bot","scope":"read_only"}'
In practice, token creation is typically performed from the browser while authenticated; use the same route with your session or an existing token that already has workspace access.
List tokens (example)
curl -X GET "https://link.iutils.net/api/workspaces/{workspace}/tokens" \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"
Revoke token (example)
curl -X DELETE "https://link.iutils.net/api/workspaces/{workspace}/tokens/{tokenId}" \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"
List links (example)
curl -X GET "https://link.iutils.net/api/workspaces/{workspace}/links" \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"
Analytics summary (example)
Members without analytics export permission (see Team & roles) receive HTTP 403 on analytics routes.
curl -X GET "https://link.iutils.net/api/workspaces/{workspace}/analytics/summary?start_date=2026-01-01&end_date=2026-01-31" \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"
Analytics scans (example)
curl -X GET "https://link.iutils.net/api/workspaces/{workspace}/analytics/scans?per_page=50&page=1" \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"
Create webhook endpoint (example)
curl -X POST "https://link.iutils.net/api/workspaces/{workspace}/webhooks" \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"url":"https://hooks.example.com/scan","event_types":["scan.logged","conversion.recorded"],"enabled":true}'
Record a conversion (example)
Report server-side conversions against a link by short code or id. Each conversion also fans out to webhook endpoints subscribed to conversion.recorded.
curl -X POST "https://link.iutils.net/api/workspaces/{workspace}/conversions" \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"short_code":"spring24","source":"api","meta":{"order_id":"A-1001"}}'
Analytics breakdown (example)
Ranked rows per dimension: country, city, region, device, browser, os, or referrer. Accepts the same filters as other analytics endpoints plus trigger=link|qr.
curl -X GET "https://link.iutils.net/api/workspaces/{workspace}/analytics/breakdown?dimension=country&trigger=qr" \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"
List webhook deliveries (example)
curl -X GET "https://link.iutils.net/api/workspaces/{workspace}/webhooks/{id}/deliveries?page=1" \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"
Errors
Versioned routes return a standard error envelope: { error: { code, message, details? } }. Common codes include unauthenticated (401), forbidden (403), not_found (404), validation_failed (422), and rate-limit responses (429).
Idempotency and side effects
GET requests are read-only. POST to create a token is not idempotent—each call mints a new token. Revoke tokens via the DELETE endpoint or the workspace token settings screen.
Audit trail
Creating API tokens may be recorded in the audit log when enabled, including token name and workspace context.
Related guides
Team & roles · Security & privacy · Trust center · Troubleshooting