{"openapi":"3.1.0","info":{"title":"U2L API","version":"1.0.0","description":"The U2L public REST API. Create and manage short links and QR codes, organize them into folders, and read click analytics programmatically. All endpoints are authenticated with a Bearer API key (`u2l_live_...`) created in the U2L dashboard under Settings > API. API access is available on every plan; request rates and creation velocity are limited per plan.","contact":{"name":"U2L AI Support","email":"support@u2l.ai","url":"https://u2l.ai/contact"}},"servers":[{"url":"https://u2l.ai","description":"Production"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"Links","description":"Create, list, read, update, and delete short links and QR codes."},{"name":"Folders","description":"Organize links into folders."},{"name":"Analytics","description":"Click analytics for links and account-wide stats."},{"name":"Domains","description":"Domains available to your account for link creation."},{"name":"Account","description":"Account profile and usage."},{"name":"Webhooks","description":"Manage outgoing webhook endpoints. U2L POSTs link.created / link.updated / link.deleted events to your URL, signed with a per-endpoint secret. Pro plan and above."}],"paths":{"/api/v1/links":{"post":{"tags":["Links"],"summary":"Create a link","operationId":"createLink","description":"Creates a short link or QR code. By default the domain is chosen automatically: destinations recognized as trusted land on `u2l.ai`, everything else on `u.gy` - this never errors. Pass a specific `domain` to use one of your subdomains or verified custom domains instead.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateLinkRequest"},"example":{"url":"https://example.com/my-page","alias":"my-link","title":"My example link"}}}},"responses":{"201":{"description":"Link created.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateLinkResponse"}}}},"400":{"$ref":"#/components/responses/SafetyBlocked"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"description":"The requested alias is already taken or reserved.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"conflict","message":"Alias \"my-link\" is already taken on u.gy."}}}}},"422":{"$ref":"#/components/responses/ValidationError"},"429":{"$ref":"#/components/responses/RateLimited"}}},"get":{"tags":["Links"],"summary":"List links","operationId":"listLinks","description":"Returns your links, newest first by default, with pagination. Filter by type, domain, folder, tag, or free-text search across slug, destination, and title.","parameters":[{"name":"page","in":"query","description":"Page number (1-based).","schema":{"type":"integer","minimum":1,"default":1}},{"name":"limit","in":"query","description":"Results per page (max 100).","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"type","in":"query","description":"Filter by link type.","schema":{"type":"string","enum":["SL","QR"]}},{"name":"domain","in":"query","description":"Filter by domain.","schema":{"type":"string"}},{"name":"folderId","in":"query","description":"Filter by folder ID.","schema":{"type":"string"}},{"name":"tag","in":"query","description":"Filter by tag.","schema":{"type":"string"}},{"name":"search","in":"query","description":"Free-text search across slug, destination, and title.","schema":{"type":"string"}},{"name":"sort","in":"query","description":"Sort field.","schema":{"type":"string","enum":["createdAt","title","clicks"],"default":"createdAt"}},{"name":"order","in":"query","description":"Sort direction.","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}}],"responses":{"200":{"description":"A page of links.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"links":{"type":"array","items":{"$ref":"#/components/schemas/Link"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/links/{domain}/{slug}":{"get":{"tags":["Links"],"summary":"Get a link","operationId":"getLink","description":"Returns a single link, including its total click count.","parameters":[{"$ref":"#/components/parameters/LinkDomain"},{"$ref":"#/components/parameters/LinkSlug"}],"responses":{"200":{"description":"The link.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Link"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}},"patch":{"tags":["Links"],"summary":"Update a link","operationId":"updateLink","description":"Updates a link. Only the fields you send are changed. Send `password: null` to remove a password; send `expiresAt: null` to remove expiration. Destination changes on `u2l.ai` links re-run the trust check - untrusted destinations are rejected (move the link to another domain instead).","parameters":[{"$ref":"#/components/parameters/LinkDomain"},{"$ref":"#/components/parameters/LinkSlug"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateLinkRequest"},"example":{"destination":"https://example.com/new-page","title":"Updated title"}}}},"responses":{"200":{"description":"The updated link.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Link"}}}},"400":{"$ref":"#/components/responses/SafetyBlocked"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}},"delete":{"tags":["Links"],"summary":"Delete a link","operationId":"deleteLink","description":"Permanently deletes a link. The short URL stops resolving immediately. This cannot be undone.","parameters":[{"$ref":"#/components/parameters/LinkDomain"},{"$ref":"#/components/parameters/LinkSlug"}],"responses":{"200":{"description":"Link deleted.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"},"example":{"message":"Link deleted successfully"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/folders":{"get":{"tags":["Folders"],"summary":"List folders","operationId":"listFolders","description":"Returns all your folders with the number of links in each, newest first.","responses":{"200":{"description":"Your folders.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"folders":{"type":"array","items":{"$ref":"#/components/schemas/Folder"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"}}},"post":{"tags":["Folders"],"summary":"Create a folder","operationId":"createFolder","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","description":"Folder name.","example":"Marketing campaigns"}}}}}},"responses":{"201":{"description":"Folder created.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Folder"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"422":{"$ref":"#/components/responses/ValidationError"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/folders/{folderId}":{"patch":{"tags":["Folders"],"summary":"Rename a folder","operationId":"renameFolder","parameters":[{"$ref":"#/components/parameters/FolderId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","description":"New folder name.","example":"Q3 campaigns"}}}}}},"responses":{"200":{"description":"Folder renamed.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"message":{"type":"string"}}},"example":{"id":"9f0c2f9e-...","name":"Q3 campaigns","message":"Folder renamed successfully"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/ValidationError"},"429":{"$ref":"#/components/responses/RateLimited"}}},"delete":{"tags":["Folders"],"summary":"Delete a folder","operationId":"deleteFolder","description":"Deletes a folder. Links inside it are NOT deleted - they are moved out of the folder.","parameters":[{"$ref":"#/components/parameters/FolderId"}],"responses":{"200":{"description":"Folder deleted.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"},"example":{"message":"Folder deleted successfully"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/analytics/{domain}/{slug}":{"get":{"tags":["Analytics"],"summary":"Get link analytics","operationId":"getLinkAnalytics","description":"Click analytics for a single link: totals plus breakdowns by country, device, browser, referrer, and operating system. Requires a plan with Analytics API access (Advanced plan or above).","parameters":[{"$ref":"#/components/parameters/LinkDomain"},{"$ref":"#/components/parameters/LinkSlug"},{"name":"timeRange","in":"query","description":"Number of days to include in `clicksInRange` and the breakdowns. Use `0` for all time.","schema":{"type":"integer","default":30}}],"responses":{"200":{"description":"Analytics for the link.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkAnalytics"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/stats":{"get":{"tags":["Analytics"],"summary":"Get account stats","operationId":"getAccountStats","description":"Account-wide totals: links, QR codes, all-time clicks, this week's clicks, plus your plan limits.","responses":{"200":{"description":"Account stats.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountStats"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/domains":{"get":{"tags":["Domains"],"summary":"List domains","operationId":"listDomains","description":"All domains you can create links on: the automatic default, U2L's first-party short domains, your claimed subdomains, and your custom domains. Domains are added and verified in the dashboard, not via the API.","responses":{"200":{"description":"Available domains.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"domains":{"type":"array","items":{"$ref":"#/components/schemas/Domain"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/account":{"get":{"tags":["Account"],"summary":"Get account info","operationId":"getAccount","description":"Your account profile and current usage against plan limits.","responses":{"200":{"description":"Account info.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Account"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/webhooks":{"get":{"tags":["Webhooks"],"summary":"List webhooks","description":"List all webhook endpoints on your account. The signing secret is never returned after creation.","operationId":"listWebhooks","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"webhooks":{"type":"array","items":{"$ref":"#/components/schemas/Webhook"}}}},"example":{"webhooks":[{"id":"we_f9ae3c2a1ee24e1b9321e359c9830b96","url":"https://example.com/u2l-webhook","events":["link.created","link.updated","link.deleted"],"active":true,"failureCount":0,"lastDeliveryAt":"2026-07-25 09:12:44","createdAt":"2026-07-25 08:52:02"}]}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["Webhooks"],"summary":"Create a webhook","description":"Register an HTTPS endpoint to receive link events. Requires the Pro plan or above; each plan has a maximum number of endpoints (Pro 3, Growth 5, Advanced 10, Team 20, Enterprise 50). The response includes the signing secret exactly once.","operationId":"createWebhook","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebhookRequest"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebhookResponse"},"example":{"id":"we_f9ae3c2a1ee24e1b9321e359c9830b96","url":"https://example.com/u2l-webhook","events":["link.created","link.updated","link.deleted"],"active":true,"failureCount":0,"lastDeliveryAt":null,"createdAt":"2026-07-25 08:52:02","secret":"u2lwh_833a6fd24a7215aa68e2137925f2b6edf1c3e02700dfdcef"}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/webhooks/{id}":{"patch":{"tags":["Webhooks"],"summary":"Update a webhook","description":"Change the URL, subscribed events, or active state. Setting active to true on a disabled endpoint resets its failure count.","operationId":"updateWebhook","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWebhookRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Webhook"},"example":{"id":"we_f9ae3c2a1ee24e1b9321e359c9830b96","url":"https://example.com/u2l-webhook","events":["link.created"],"active":true,"failureCount":0,"lastDeliveryAt":"2026-07-25 09:12:44","createdAt":"2026-07-25 08:52:02"}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Webhooks"],"summary":"Delete a webhook","description":"Remove a webhook endpoint. Pending deliveries to it are dropped.","operationId":"deleteWebhook","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"},"example":{"message":"Webhook deleted successfully"}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"u2l_live_...","description":"API key from the U2L dashboard (Settings > API). Format: `u2l_live_` followed by 32 hex characters."}},"parameters":{"LinkDomain":{"name":"domain","in":"path","required":true,"description":"The link's domain (e.g. `u.gy` or `u2l.ai`).","schema":{"type":"string","example":"u.gy"}},"LinkSlug":{"name":"slug","in":"path","required":true,"description":"The link's slug (the part after the domain).","schema":{"type":"string","example":"my-link"}},"FolderId":{"name":"folderId","in":"path","required":true,"description":"The folder's ID.","schema":{"type":"string"}}},"headers":{"XRateLimitLimit":{"description":"Requests allowed in the current window.","schema":{"type":"integer"}},"XRateLimitRemaining":{"description":"Requests remaining in the current window.","schema":{"type":"integer"}},"XRateLimitReset":{"description":"Unix timestamp when the window resets.","schema":{"type":"integer"}}},"responses":{"Unauthorized":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"unauthorized","message":"Invalid API key."}}}}},"Forbidden":{"description":"Your plan does not include this feature, or a limit was reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"forbidden","message":"Link limit reached for your plan."}}}}},"NotFound":{"description":"The resource does not exist or is not yours.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"not_found","message":"Link not found."}}}}},"ValidationError":{"description":"The request body failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"validation_error","message":"url is required."}}}}},"SafetyBlocked":{"description":"The destination was rejected by safety or trust checks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"validation_error","message":"This link was flagged by our safety checks."}}}}},"RateLimited":{"description":"Rate limit exceeded. Check X-RateLimit-Reset for when the window resets.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"rate_limited","message":"Rate limit exceeded. Try again later."}}}}}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}}}}},"Message":{"type":"object","properties":{"message":{"type":"string"}}},"Link":{"type":"object","properties":{"id":{"type":"string","description":"Link ID (UUID)."},"slug":{"type":"string","description":"The part after the domain."},"domain":{"type":"string","description":"The link's domain."},"destination":{"type":"string","description":"Where the link redirects to."},"title":{"type":"string","description":"Optional title."},"tags":{"type":"array","items":{"type":"string"}},"hasPassword":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time","description":"Expiration time, if set."},"permanent":{"type":"boolean","description":"true = 301 redirect, false = 302."},"type":{"type":"string","enum":["SL","QR","PG"],"description":"SL = short link, QR = QR code, PG = link-in-bio page."},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"folderId":{"type":"string"},"clicks":{"type":"integer","description":"Total clicks."},"ogTitle":{"type":"string","description":"Custom social preview title."},"ogDescription":{"type":"string"},"ogImage":{"type":"string"},"abTestEnabled":{"type":"boolean"},"destinationB":{"type":"string","description":"A/B variant destination."},"splitPercentage":{"type":"integer","description":"Traffic percentage to destination A."},"qrStyle":{"type":"object","description":"QR styling options (QR links only)."},"externalBrowser":{"type":"boolean","description":"Open in the phone's default browser when tapped inside in-app browsers (Android)."}}},"Pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"},"hasMore":{"type":"boolean"}}},"CustomOg":{"type":"object","description":"Custom social preview (Advanced plan or above).","properties":{"title":{"type":"string"},"description":{"type":"string"},"image":{"type":"string","description":"Image URL."}}},"AbTest":{"type":"object","description":"A/B testing config (Advanced plan or above).","properties":{"enabled":{"type":"boolean"},"destinationB":{"type":"string","description":"Variant B destination URL."},"splitPercentage":{"type":"integer","default":50,"description":"Traffic percentage to destination A."}}},"QrStyle":{"type":"object","description":"QR styling (QR links only; pattern/logo customization requires Pro plan or above).","properties":{"dotsType":{"type":"string","default":"rounded"},"cornersSquareType":{"type":"string","default":"extra-rounded"},"cornersDotType":{"type":"string","default":"dot"},"logo":{"type":"string","description":"Logo image URL."}}},"CreateLinkRequest":{"type":"object","required":["url"],"properties":{"url":{"type":"string","description":"Destination URL. `https://` is assumed if no scheme is given.","example":"https://example.com/my-page"},"domain":{"type":"string","default":"auto","description":"`auto` (default) picks the best domain for the destination. Or pass one of your domains from List domains."},"alias":{"type":"string","description":"Custom slug (5-50 chars, letters/numbers/hyphens/underscores). Random when omitted.","example":"my-link"},"title":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"password":{"type":"string","description":"Password-protect the link (Advanced plan or above)."},"expiresAt":{"type":"string","format":"date-time","description":"Expiration time (Advanced plan or above)."},"permanent":{"type":"boolean","default":true,"description":"true = 301 redirect, false = 302."},"folderId":{"type":"string"},"type":{"type":"string","enum":["SL","QR"],"default":"SL"},"customOg":{"$ref":"#/components/schemas/CustomOg"},"abTest":{"$ref":"#/components/schemas/AbTest"},"qrStyle":{"$ref":"#/components/schemas/QrStyle"}}},"UpdateLinkRequest":{"type":"object","description":"All fields optional - only sent fields are changed.","properties":{"destination":{"type":"string","description":"New destination URL."},"title":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"password":{"type":"string","description":"New password; send null to remove (Advanced plan or above)."},"expiresAt":{"type":"string","format":"date-time","description":"New expiration; send null to remove."},"permanent":{"type":"boolean"},"customOg":{"$ref":"#/components/schemas/CustomOg"},"abTest":{"$ref":"#/components/schemas/AbTest"}}},"CreateLinkResponse":{"type":"object","properties":{"id":{"type":"string"},"shortLink":{"type":"string","description":"The full short URL.","example":"https://u.gy/my-link"},"domain":{"type":"string"},"slug":{"type":"string"},"destination":{"type":"string"},"title":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"hasPassword":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"permanent":{"type":"boolean"},"type":{"type":"string","enum":["SL","QR"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"folderId":{"type":"string"},"clicks":{"type":"integer"},"noticeCode":{"type":"string","description":"Present when the domain differs from the one requested (trust-based placement)."},"notice":{"type":"string","description":"Human-readable explanation of the domain choice."},"requestedDomain":{"type":"string"}}},"Folder":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"linksCount":{"type":"integer"},"createdAt":{"type":"string","format":"date-time"}}},"Domain":{"type":"object","properties":{"domain":{"type":"string","example":"u.gy"},"type":{"type":"string","enum":["default","trust-based","standard","subdomain","custom"],"description":"`default` is the automatic choice; `trust-based` (u2l.ai) accepts trusted destinations only."},"verified":{"type":"boolean"},"placement":{"type":"string","description":"Placement rule, when applicable (`automatic` or `trusted-only`)."}}},"LinkAnalytics":{"type":"object","properties":{"totalClicks":{"type":"integer","description":"All-time clicks."},"clicksInRange":{"type":"integer","description":"Clicks within timeRange."},"clicksToday":{"type":"integer"},"clicksThisWeek":{"type":"integer"},"timeRange":{"type":"integer","description":"The requested range in days (0 = all time)."},"countries":{"type":"array","items":{"type":"object","properties":{"country":{"type":"string"},"clicks":{"type":"integer"}}}},"devices":{"type":"object","description":"Clicks per device type (mobile / desktop / tablet).","additionalProperties":{"type":"integer"}},"browsers":{"type":"array","items":{"type":"object","properties":{"browser":{"type":"string"},"clicks":{"type":"integer"}}}},"referrers":{"type":"array","items":{"type":"object","properties":{"referrer":{"type":"string"},"clicks":{"type":"integer"}}}},"os":{"type":"array","items":{"type":"object","properties":{"os":{"type":"string"},"clicks":{"type":"integer"}}}}}},"AccountStats":{"type":"object","properties":{"totalLinks":{"type":"integer"},"totalClicks":{"type":"integer"},"totalQRCodes":{"type":"integer"},"thisWeekClicks":{"type":"integer"},"plan":{"type":"string"},"limits":{"type":"object","properties":{"maxLinks":{"description":"Number, or the string `unlimited`.","oneOf":[{"type":"integer"},{"type":"string"}]},"maxQRCodes":{"oneOf":[{"type":"integer"},{"type":"string"}]},"apiRequestsPerMinute":{"type":"integer"},"apiRequestsPerDay":{"type":"integer"}}}}},"Account":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"plan":{"type":"string"},"billingCycle":{"type":"string","description":"monthly, yearly, or lifetime. Null on free plans."},"createdAt":{"type":"string","format":"date-time"},"usage":{"type":"object","properties":{"links":{"type":"integer"},"qrCodes":{"type":"integer"},"customDomains":{"type":"integer"},"apiKeysUsed":{"type":"integer"},"apiKeysLimit":{"type":"integer"}}}}},"Webhook":{"type":"object","properties":{"id":{"type":"string","example":"we_f9ae3c2a1ee24e1b9321e359c9830b96"},"url":{"type":"string","example":"https://example.com/u2l-webhook"},"events":{"type":"array","items":{"type":"string","enum":["link.created","link.updated","link.deleted"]}},"active":{"type":"boolean"},"failureCount":{"type":"integer","description":"Consecutive failed deliveries. The endpoint is disabled automatically at 20. Resets to 0 on any successful delivery."},"lastDeliveryAt":{"type":"string","nullable":true},"createdAt":{"type":"string"}}},"CreateWebhookRequest":{"type":"object","required":["url"],"properties":{"url":{"type":"string","description":"HTTPS URL that receives event POSTs.","example":"https://example.com/u2l-webhook"},"events":{"type":"array","description":"Events to subscribe to. Defaults to all.","items":{"type":"string","enum":["link.created","link.updated","link.deleted"]}}}},"CreateWebhookResponse":{"allOf":[{"$ref":"#/components/schemas/Webhook"},{"type":"object","properties":{"secret":{"type":"string","description":"Signing secret (u2lwh_...). Shown only in this response - store it now. Used to verify the X-U2L-Signature header.","example":"u2lwh_833a6fd24a7215aa68e213..."}}}]},"UpdateWebhookRequest":{"type":"object","properties":{"url":{"type":"string"},"events":{"type":"array","items":{"type":"string","enum":["link.created","link.updated","link.deleted"]}},"active":{"type":"boolean","description":"Re-enabling a disabled endpoint resets its failure count."}}}}}}