{"openapi":"3.0.0","info":{"version":"1.0.0","title":"Zulk API","description":"Zu.lk is a powerful URL shortening platform that transforms long URLs into short, memorable links. Our platform offers advanced features including analytics, custom domains, password protection, and expiration dates. Visit our [homepage](https://zu.lk) to get started, explore the [API documentation](https://zu.lk/-/api) for integration details, or check out our [Model Context Protocol (MCP) server](https://zu.lk/-/mcp) for AI-powered integrations.","x-logo":{"url":"https://zu.lk/-/name-logo.svg","altText":"Zulk Logo","href":"https://zu.lk"}},"servers":[{"url":"https://api.zu.lk","description":"Production server"},{"url":"http://localhost:8787","description":"Development server"}],"tags":[{"name":"Authentication","description":"🔐 OAuth endpoints for web app authentication (no API key required)"},{"name":"API v1 - Users","description":"👥 User management endpoints (requires API key)"},{"name":"API v1 - Organizations","description":"🏢 Organization management endpoints (requires API key)"},{"name":"API v1 - Links","description":"🔗 URL shortening endpoints (requires API key)"},{"name":"API v1 - Analytics","description":"📊 Analytics and reporting endpoints (requires API key)"},{"name":"API v1 - Campaigns","description":"🎯 Campaign management endpoints for UTM tracking (requires API key)"}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-KEY","description":"API Key for authentication"},"ApiSecretAuth":{"type":"apiKey","in":"header","name":"X-API-Secret","description":"API Secret for authentication"}},"schemas":{"Link":{"type":"object","properties":{"id":{"type":"string","example":"1","description":"Link ID"},"key":{"type":"string","example":"abc123","description":"Short link key"},"url":{"type":"string","format":"uri","example":"https://example.com","description":"Original URL"},"created_at":{"type":"string","format":"date-time","example":"2025-01-01T00:00:00Z","description":"Creation timestamp"},"owner":{"type":"string","example":"org123","description":"Organization ID that owns this link"},"expires_at":{"type":"string","format":"date-time","example":"2025-08-31T15:59:00.000Z","description":"Link expiry date (ISO 8601 format)","nullable":true},"password":{"type":"string","example":"secure123","description":"Password protection for the link","nullable":true},"utm_params":{"type":"string","example":"{\"source\":\"google\",\"medium\":\"social\",\"campaign\":\"spring_sale\"}","description":"UTM parameters as JSON string","nullable":true}}},"CreateLink":{"type":"object","required":["url"],"properties":{"key":{"type":"string","example":"custom-key","description":"Custom short key (optional). Minimum length varies by plan: Base=7 chars, Pro=6 chars, Premium=5 chars. Shorter slugs are reserved for auction."},"url":{"type":"string","format":"uri","example":"https://example.com","description":"URL to shorten"},"length":{"type":"integer","minimum":5,"maximum":10,"example":7,"description":"Length of generated key (5-10). Minimum length varies by plan: Base=7, Pro=6, Premium=5. Shorter slugs are reserved for auction."},"expiresAt":{"type":"string","format":"date-time","example":"2025-08-31T15:59:00.000Z","description":"Link expiry date (ISO 8601 format) - Pro plans only"},"password":{"type":"string","example":"86fg97g97guigugu","description":"Password protection for the link - Pro plans only"},"utmParams":{"type":"object","description":"UTM parameters for tracking","properties":{"source":{"type":"string","example":"google","description":"UTM source parameter"},"medium":{"type":"string","example":"social","description":"UTM medium parameter"},"campaign":{"type":"string","example":"spring_sale","description":"UTM campaign parameter"},"term":{"type":"string","example":"running shorts","description":"UTM term parameter"},"content":{"type":"string","example":"textlink","description":"UTM content parameter"}}}}},"CreateLinkResponse":{"type":"object","properties":{"message":{"type":"string","example":"Record added successfully"},"created_at":{"type":"string","format":"date-time","example":"2025-01-01T00:00:00Z"},"shortLink":{"type":"string","example":"https://zu.lk/abc123"},"key":{"type":"string","example":"abc123"},"url":{"type":"string","format":"uri","example":"https://example.com"},"length":{"type":"integer","example":6},"expiresAt":{"type":"string","format":"date-time","example":"2025-08-31T15:59:00.000Z","nullable":true},"password":{"type":"string","example":"86fg97g97guigugu","nullable":true},"utmParams":{"type":"object","nullable":true,"example":{"source":"google","medium":"social","campaign":"spring_sale","term":"running shorts","content":"textlink"},"properties":{"source":{"type":"string"},"medium":{"type":"string"},"campaign":{"type":"string"},"term":{"type":"string"},"content":{"type":"string"}}},"plan":{"type":"string","example":"pro","description":"Organization plan (base, pro, premium)"}}},"Error":{"type":"object","properties":{"error":{"type":"string","example":"Error message","description":"Error message"}}},"User":{"type":"object","properties":{"id":{"type":"string","example":"123","description":"User ID"},"name":{"type":"string","example":"John Doe","description":"User name"},"age":{"type":"integer","example":42,"description":"User age"}}},"AuthUser":{"type":"object","properties":{"email":{"type":"string","format":"email","example":"user@example.com","description":"User email (lowercased)"},"user":{"type":"object","properties":{"id":{"type":"string","example":"123456789","description":"Google user ID"},"name":{"type":"string","example":"John Doe","description":"User display name"},"email":{"type":"string","format":"email","example":"user@example.com","description":"User email from Google"},"picture":{"type":"string","format":"uri","example":"https://lh3.googleusercontent.com/...","description":"User profile picture URL"}},"description":"Google OAuth user data"},"token":{"type":"string","example":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...","description":"JWT token"},"apiKey":{"type":"string","example":"ak_1234567890abcdef","description":"User API key"},"apiToken":{"type":"string","example":"at_1234567890abcdef","description":"User API token"}}},"Organization":{"type":"object","properties":{"id":{"type":"number","example":1,"description":"Organization ID"},"name":{"type":"string","example":"Acme Corp","description":"Organization name"},"plan":{"type":"string","example":"pro","description":"Organization plan (base, pro, premium)"},"role":{"type":"string","example":"OWNER","description":"User role in the organization"}}},"OrganizationMember":{"type":"object","properties":{"id":{"type":"number","example":123,"description":"User ID"},"name":{"type":"string","example":"John Doe","description":"User name"},"email":{"type":"string","format":"email","example":"john@example.com","description":"User email"},"role":{"type":"string","enum":["MANAGER","ADMIN","OWNER"],"example":"MANAGER","description":"User role in the organization"}}},"AddMemberRequest":{"type":"object","required":["email"],"properties":{"email":{"type":"string","format":"email","example":"newmember@example.com","description":"Email of the user to add"},"role":{"type":"string","enum":["MANAGER","ADMIN","OWNER"],"example":"MANAGER","default":"MANAGER","description":"Role to assign to the new member"}}},"UpdateRoleRequest":{"type":"object","required":["role"],"properties":{"role":{"type":"string","enum":["MANAGER","ADMIN","OWNER"],"example":"ADMIN","description":"New role for the member"}}},"AnalyticsResponse":{"type":"object","properties":{"orgId":{"type":"string","example":"1","description":"Organization ID"},"analytics":{"type":"object","properties":{"totalClicks":{"type":"number","example":1250,"description":"Total click count"},"dateRange":{"type":"object","properties":{"from":{"type":"string","example":"-7d","description":"Start date of the range"},"to":{"type":"string","example":"today","description":"End date of the range"}}},"interval":{"type":"string","example":"day","description":"Data interval"},"data":{"type":"array","items":{"type":"number"},"example":[120,150,89,200,180,145,220],"description":"Click data points"},"labels":{"type":"array","items":{"type":"string"},"example":["2025-08-09","2025-08-10","2025-08-11","2025-08-12","2025-08-13","2025-08-14","2025-08-15"],"description":"Date labels for data points"},"breakdown":{"type":"object","properties":{"byCountry":{"type":"object","additionalProperties":{"type":"number"},"example":{"US":450,"GB":320,"CA":180},"description":"Click breakdown by country"},"byBrowser":{"type":"object","additionalProperties":{"type":"number"},"example":{"Chrome":680,"Safari":320,"Firefox":250},"description":"Click breakdown by browser"},"byReferer":{"type":"object","additionalProperties":{"type":"number"},"example":{"direct":500,"facebook":350,"twitter":200,"google":200},"description":"Click breakdown by referer/platform"}}}}},"generatedAt":{"type":"string","format":"date-time","example":"2025-08-15T12:00:00Z","description":"Timestamp when analytics were generated"},"plan":{"type":"string","example":"base","description":"Organization plan affecting cache duration"},"cached":{"type":"boolean","example":false,"description":"Whether the data was served from cache"}}},"UpdateLinkRequest":{"type":"object","required":["url","key"],"properties":{"url":{"type":"string","format":"uri","example":"https://updated-example.com","description":"Updated URL"},"key":{"type":"string","example":"updated-key","description":"Updated short key"},"expiresAt":{"type":"string","format":"date-time","example":"2025-12-31T23:59:59.000Z","description":"Link expiry date (ISO 8601 format) - Pro plan feature","nullable":true},"password":{"type":"string","example":"secure123","description":"Password protection for the link - Pro plan feature","nullable":true}}},"CreateOrganization":{"type":"object","required":["name"],"properties":{"name":{"type":"string","example":"Acme Corp","description":"Organization name"}}},"QuotaInfo":{"type":"object","properties":{"used":{"type":"number","example":45,"description":"Number of resources used this month"},"limit":{"type":"number","example":100,"description":"Monthly limit for this resource type"},"remaining":{"type":"number","example":55,"description":"Remaining quota for this month"},"percentUsed":{"type":"number","example":45,"description":"Percentage of quota used"}}},"QuotaResponse":{"type":"object","properties":{"plan":{"type":"string","example":"base","description":"Organization plan","enum":["base","pro","premium"]},"quotas":{"type":"object","properties":{"links":{"$ref":"#/components/schemas/QuotaInfo"},"campaigns":{"$ref":"#/components/schemas/QuotaInfo"}}},"period":{"type":"object","properties":{"start":{"type":"string","format":"date-time","example":"2025-09-01T00:00:00.000Z","description":"Current billing period start"},"end":{"type":"string","format":"date-time","example":"2025-09-30T23:59:59.999Z","description":"Current billing period end"}}}}},"Campaign":{"type":"object","properties":{"id":{"type":"integer","example":123,"description":"Campaign ID"},"name":{"type":"string","example":"Summer 2025 Campaign","description":"Campaign name"},"base_url":{"type":"string","format":"uri","example":"https://example.com/landing","description":"Base URL for the campaign"},"utm_campaign":{"type":"string","example":"summer2025","description":"UTM campaign parameter"},"utm_source":{"type":"string","example":"social","description":"Default UTM source parameter","nullable":true},"utm_medium":{"type":"string","example":"organic","description":"Default UTM medium parameter","nullable":true},"utm_term":{"type":"string","example":"keywords","description":"Default UTM term parameter","nullable":true},"utm_content":{"type":"string","example":"header-banner","description":"Default UTM content parameter","nullable":true},"created_at":{"type":"string","format":"date-time","example":"2025-01-01T00:00:00Z","description":"Campaign creation timestamp"},"updated_at":{"type":"string","format":"date-time","example":"2025-01-01T00:00:00Z","description":"Campaign last update timestamp"},"org_id":{"type":"integer","example":1,"description":"Organization ID that owns this campaign"}}},"CampaignLink":{"type":"object","properties":{"id":{"type":"integer","example":456,"description":"Campaign link ID"},"campaign_id":{"type":"integer","example":123,"description":"Campaign ID this link belongs to"},"link_id":{"type":"integer","example":789,"description":"Reference to the main link record"},"platform":{"type":"string","example":"facebook","description":"Platform name for this link"},"utm_source":{"type":"string","example":"facebook","description":"UTM source parameter for this link","nullable":true},"utm_medium":{"type":"string","example":"social","description":"UTM medium parameter for this link","nullable":true},"utm_term":{"type":"string","example":"summer","description":"UTM term parameter for this link","nullable":true},"utm_content":{"type":"string","example":"post1","description":"UTM content parameter for this link","nullable":true},"key":{"type":"string","example":"summer-fb","description":"Short link key"},"url":{"type":"string","format":"uri","example":"https://example.com/landing?utm_source=facebook&utm_medium=social&utm_campaign=summer2025&utm_content=post1","description":"Full URL with UTM parameters"},"short_url":{"type":"string","format":"uri","example":"https://zu.lk/summer-fb","description":"Complete short URL"},"created_at":{"type":"string","format":"date-time","example":"2025-01-01T00:00:00Z","description":"Link creation timestamp"},"expires_at":{"type":"string","format":"date-time","example":"2025-08-31T15:59:00.000Z","description":"Link expiry date (ISO 8601 format)","nullable":true},"password":{"type":"string","example":"secure123","description":"Password protection for the link","nullable":true}}}}},"security":[{"ApiKeyAuth":[],"ApiSecretAuth":[]}],"paths":{"/v1/organizations":{"get":{"summary":"Get user organizations","description":"Retrieve organizations that the authenticated user has access to","tags":["API v1 - Organizations"],"security":[{"ApiKeyAuth":[],"ApiSecretAuth":[]}],"responses":{"200":{"description":"Successfully retrieved user organizations","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Organization"}}}}},"401":{"description":"Unauthorized - Invalid API credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"summary":"Create a new organization","description":"Create a new organization and assign the authenticated user as owner. Organizations always start with a base plan.","tags":["API v1 - Organizations"],"security":[{"ApiKeyAuth":[],"ApiSecretAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateOrganization"}}}},"responses":{"200":{"description":"Successfully created organization","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Organization created successfully"},"id":{"type":"number","example":1,"description":"Organization ID"},"name":{"type":"string","example":"Acme Corp","description":"Organization name"},"plan":{"type":"string","example":"base","description":"Organization plan (defaults to base)"},"role":{"type":"string","example":"OWNER","description":"User role in the organization"}}}}}},"400":{"description":"Bad request - Name is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized - Invalid API credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/organizations/{orgId}/members":{"get":{"summary":"Get organization members","description":"Retrieve all members of a specific organization","tags":["API v1 - Organizations"],"security":[{"ApiKeyAuth":[],"ApiSecretAuth":[]}],"parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"},"description":"Organization ID","example":"1"}],"responses":{"200":{"description":"Successfully retrieved organization members","content":{"application/json":{"schema":{"type":"object","properties":{"members":{"type":"array","items":{"$ref":"#/components/schemas/OrganizationMember"}},"total":{"type":"number","example":5,"description":"Total number of members"}}}}}},"401":{"description":"Unauthorized - Invalid API credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Access denied to this organization","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"summary":"Add member to organization","description":"Add a new member to an organization (requires ADMIN or OWNER role).","tags":["API v1 - Organizations"],"security":[{"ApiKeyAuth":[],"ApiSecretAuth":[]}],"parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"},"description":"Organization ID","example":"1"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddMemberRequest"}}}},"responses":{"200":{"description":"Successfully added member to organization","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Member added successfully"},"member":{"$ref":"#/components/schemas/OrganizationMember"}}}}}},"400":{"description":"Bad request - Email is required or invalid role","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized - Invalid API credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Access denied - Requires ADMIN or OWNER role","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"User not found - User must register first","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"User not found. User must register first."}}}},"409":{"description":"Conflict - User is already a member","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/organizations/{orgId}/members/{memberId}/role":{"patch":{"summary":"Update member role","description":"Update the role of a specific member in an organization (requires ADMIN or OWNER role)","tags":["API v1 - Organizations"],"security":[{"ApiKeyAuth":[],"ApiSecretAuth":[]}],"parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"},"description":"Organization ID","example":"1"},{"name":"memberId","in":"path","required":true,"schema":{"type":"string"},"description":"Member ID","example":"123"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateRoleRequest"}}}},"responses":{"200":{"description":"Successfully updated member role","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Member role updated successfully"},"member":{"type":"object","properties":{"id":{"type":"number","example":123},"name":{"type":"string","example":"John Doe"},"email":{"type":"string","example":"john@example.com"},"role":{"type":"string","example":"ADMIN"},"previousRole":{"type":"string","example":"MANAGER"}}}}}}}},"400":{"description":"Bad request - Role is required or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized - Invalid API credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Access denied - Requires ADMIN or OWNER role, or cannot change own role","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Member not found in this organization","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Member not found in this organization"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/organizations/{orgId}/members/{memberId}":{"delete":{"summary":"Remove member from organization","description":"Remove a member from an organization (requires ADMIN or OWNER role). Cannot remove yourself or the current OWNER.","tags":["API v1 - Organizations"],"security":[{"ApiKeyAuth":[],"ApiSecretAuth":[]}],"parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"},"description":"Organization ID","example":"1"},{"name":"memberId","in":"path","required":true,"schema":{"type":"string"},"description":"Member ID","example":"123"}],"responses":{"200":{"description":"Successfully removed member from organization","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Member removed successfully"},"removedMember":{"$ref":"#/components/schemas/OrganizationMember"}}}}}},"401":{"description":"Unauthorized - Invalid API credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Access denied - Requires ADMIN or OWNER role, cannot remove yourself, or cannot remove last OWNER","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Member not found in this organization","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Member not found in this organization"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/organizations/{orgId}/analytics/clicks":{"get":{"summary":"Get organization click analytics","description":"Retrieve click analytics data for an organization's links. Cached for 24h (base), 12h (pro), 6h (premium).","tags":["API v1 - Analytics"],"security":[{"ApiKeyAuth":[],"ApiSecretAuth":[]}],"parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"},"description":"Organization ID","example":"1"},{"name":"date_from","in":"query","required":false,"schema":{"type":"string"},"description":"Start date for analytics (default: -7d)","example":"-7d"},{"name":"date_to","in":"query","required":false,"schema":{"type":"string"},"description":"End date for analytics (default: today)","example":"today"},{"name":"interval","in":"query","required":false,"schema":{"type":"string"},"description":"Data interval (default: day)","example":"day"}],"responses":{"200":{"description":"Successfully retrieved analytics data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalyticsResponse"}}}},"401":{"description":"Unauthorized - Invalid API credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Access denied to this organization","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error - Failed to fetch analytics data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/organizations/{orgId}/quotas":{"get":{"summary":"Get organization quota usage","description":"Retrieve current quota usage information for an organization, including used, remaining, and limits for links and campaigns","tags":["API v1 - Organizations"],"security":[{"ApiKeyAuth":[],"ApiSecretAuth":[]}],"parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"},"description":"Organization ID","example":"1"}],"responses":{"200":{"description":"Successfully retrieved quota information","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuotaResponse"}}}},"401":{"description":"Unauthorized - Invalid API credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Access denied to this organization","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Organization not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Organization not found"}}}},"500":{"description":"Internal server error - Failed to fetch quota data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/organizations/{orgId}/usage":{"get":{"summary":"Get organization usage analytics","description":"Retrieve detailed usage analytics for an organization, including current month usage, limits, and historical breakdown data","tags":["API v1 - Organizations"],"security":[{"ApiKeyAuth":[],"ApiSecretAuth":[]}],"parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"},"description":"Organization ID","example":"1"},{"name":"startDate","in":"query","required":false,"schema":{"type":"string","format":"date-time"},"description":"Start date for historical usage data (ISO 8601 format)","example":"2025-09-01T00:00:00.000Z"},{"name":"endDate","in":"query","required":false,"schema":{"type":"string","format":"date-time"},"description":"End date for historical usage data (ISO 8601 format)","example":"2025-09-30T23:59:59.999Z"}],"responses":{"200":{"description":"Successfully retrieved usage analytics","content":{"application/json":{"schema":{"type":"object","properties":{"organization":{"type":"object","properties":{"id":{"type":"string","example":"1","description":"Organization ID"},"name":{"type":"string","example":"Acme Corp","description":"Organization name"},"plan":{"type":"string","example":"pro","description":"Organization plan","enum":["base","pro","premium"]}}},"currentMonth":{"type":"object","properties":{"usage":{"type":"object","properties":{"links":{"type":"number","example":450,"description":"Links used this month"},"campaigns":{"type":"number","example":12,"description":"Campaigns used this month"}}},"limits":{"type":"object","properties":{"monthlyLinks":{"type":"number","example":5000,"description":"Monthly link limit"},"monthlyCampaigns":{"type":"number","example":5000,"description":"Monthly campaign limit"}}},"percentUsed":{"type":"object","properties":{"links":{"type":"number","example":9,"description":"Percentage of link quota used"},"campaigns":{"type":"number","example":0,"description":"Percentage of campaign quota used"}}},"remaining":{"type":"object","properties":{"links":{"type":"number","example":4550,"description":"Remaining link quota"},"campaigns":{"type":"number","example":4988,"description":"Remaining campaign quota"}}}}},"breakdown":{"type":"object","properties":{"daily":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string","format":"date","example":"2025-09-01","description":"Date of usage"},"links":{"type":"number","example":15,"description":"Links created on this date"},"campaigns":{"type":"number","example":2,"description":"Campaigns created on this date"}}}},"total":{"type":"object","properties":{"links":{"type":"number","example":450,"description":"Total links in period"},"campaigns":{"type":"number","example":12,"description":"Total campaigns in period"}}}}}}}}}},"401":{"description":"Unauthorized - Invalid API credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Access denied to this organization","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Organization not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Organization not found"}}}},"500":{"description":"Internal server error - Failed to fetch usage data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/organizations/{orgId}/links":{"get":{"summary":"Get organization links","description":"Retrieve all links for a specific organization","tags":["API v1 - Links"],"security":[{"ApiKeyAuth":[],"ApiSecretAuth":[]}],"parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"},"description":"Organization ID","example":"1"}],"responses":{"200":{"description":"Successfully retrieved organization links","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Link"}}}}},"401":{"description":"Unauthorized - Invalid API credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Access denied to this organization","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"summary":"Create a new link in organization","description":"Create a new short link for the given URL in the specified organization","tags":["API v1 - Links"],"security":[{"ApiKeyAuth":[],"ApiSecretAuth":[]}],"parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"},"description":"Organization ID","example":"1"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateLink"}}}},"responses":{"200":{"description":"Successfully created short link","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateLinkResponse"}}}},"401":{"description":"Unauthorized - Invalid API credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Access denied to this organization, Pro plan required for premium features, or slug length restrictions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"organization-access":{"value":{"error":"Access denied to this organization"}},"expiry-plan-restriction":{"value":{"error":"Expiry date feature is only available for Pro plans. Please upgrade your organization."}},"password-plan-restriction":{"value":{"error":"Password protection feature is only available for Pro plans. Please upgrade your organization."}},"slug-length-restriction":{"value":{"error":"Custom slug must be 7 or more characters for base plan. Shorter slugs are reserved for auction."}}}}}},"429":{"description":"Quota exceeded - Monthly link or campaign limit reached","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Monthly link quota exceeded. You've used 100/100 links this month. Please upgrade your plan or wait until next month."},"currentUsage":{"type":"object","properties":{"links":{"type":"number","example":100},"campaigns":{"type":"number","example":45}}},"limits":{"type":"object","properties":{"monthlyLinks":{"type":"number","example":100},"monthlyCampaigns":{"type":"number","example":50}}}}}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/organizations/{orgId}/links/{id}":{"get":{"summary":"Get a specific link from organization","description":"Retrieve a specific link by ID from the specified organization","tags":["API v1 - Links"],"security":[{"ApiKeyAuth":[],"ApiSecretAuth":[]}],"parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"},"description":"Organization ID","example":"1"},{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Link ID","example":"1"}],"responses":{"200":{"description":"Successfully retrieved link","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Link"}}}},"401":{"description":"Unauthorized - Invalid API credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Access denied to this organization","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Link not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Link not found"}}}}}}},"/v1/organizations/{orgId}/links/{linkId}":{"put":{"summary":"Update a link in organization","description":"Update an existing short link for the specified organization. Premium features (expiry date, password) require Pro plan.","tags":["API v1 - Links"],"security":[{"ApiKeyAuth":[],"ApiSecretAuth":[]}],"parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"},"description":"Organization ID","example":"1"},{"name":"linkId","in":"path","required":true,"schema":{"type":"string"},"description":"Link ID","example":"1"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateLinkRequest"}}}},"responses":{"200":{"description":"Successfully updated link","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Link updated successfully"},"id":{"type":"string","example":"1","description":"Link ID"},"key":{"type":"string","example":"updated-key","description":"Updated short key"},"url":{"type":"string","format":"uri","example":"https://updated-example.com","description":"Updated URL"},"shortLink":{"type":"string","example":"https://zu.lk/updated-key","description":"Full short link URL"},"updated_at":{"type":"string","format":"date-time","example":"2025-08-15T12:00:00Z","description":"Update timestamp"},"previousKey":{"type":"string","example":"old-key","description":"Previous short key"},"expiresAt":{"type":"string","format":"date-time","example":"2025-12-31T23:59:59.000Z","description":"Link expiry date (null if removed)","nullable":true},"password":{"type":"string","example":"secure123","description":"Password protection (null if removed)","nullable":true},"plan":{"type":"string","example":"pro","description":"Organization plan"}}}}}},"400":{"description":"Bad request - URL and key are required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized - Invalid API credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Access denied to this organization, or Pro plan required for premium features","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Link not found in this organization","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Link not found in this organization"}}}},"409":{"description":"Conflict - Key is already taken","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/organizations/{orgId}/campaigns":{"get":{"summary":"Get campaigns","description":"Retrieve all campaigns for an organization with pagination","tags":["API v1 - Campaigns"],"security":[{"ApiKeyAuth":[],"ApiSecretAuth":[]}],"parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"},"description":"Organization ID","example":"1"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","default":1},"description":"Page number","example":1},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":10,"maximum":100},"description":"Number of campaigns per page (max 100)","example":10}],"responses":{"200":{"description":"Successfully retrieved campaigns","content":{"application/json":{"schema":{"type":"object","properties":{"campaigns":{"type":"array","items":{"$ref":"#/components/schemas/Campaign"}},"page":{"type":"integer","example":1},"limit":{"type":"integer","example":10},"total":{"type":"integer","example":25},"totalPages":{"type":"integer","example":3}}}}}},"401":{"description":"Unauthorized - Invalid API credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Access denied to this organization","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"summary":"Create campaign","description":"Create a new campaign with platform-specific links and UTM tracking","tags":["API v1 - Campaigns"],"security":[{"ApiKeyAuth":[],"ApiSecretAuth":[]}],"parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"},"description":"Organization ID","example":"1"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","base_url","utm_campaign"],"properties":{"name":{"type":"string","example":"Summer 2025 Campaign","description":"Campaign name"},"base_url":{"type":"string","format":"uri","example":"https://example.com/landing","description":"Base URL for the campaign"},"utm_campaign":{"type":"string","example":"summer2025","description":"UTM campaign parameter (must be unique per organization)"},"utm_source":{"type":"string","example":"social","description":"Default UTM source parameter"},"utm_medium":{"type":"string","example":"organic","description":"Default UTM medium parameter"},"utm_term":{"type":"string","example":"keywords","description":"Default UTM term parameter"},"utm_content":{"type":"string","example":"header-banner","description":"Default UTM content parameter"},"platforms":{"type":"array","items":{"type":"object","required":["platform"],"properties":{"platform":{"type":"string","example":"facebook","description":"Platform name (facebook, instagram, twitter, etc.)"},"utm_source":{"type":"string","example":"facebook","description":"Platform-specific UTM source (overrides campaign default)"},"utm_medium":{"type":"string","example":"social","description":"Platform-specific UTM medium (overrides campaign default)"},"utm_term":{"type":"string","example":"summer","description":"Platform-specific UTM term (overrides campaign default)"},"utm_content":{"type":"string","example":"post1","description":"Platform-specific UTM content (overrides campaign default)"},"custom_key":{"type":"string","example":"summer-fb","description":"Custom short key for this platform link"}}},"description":"Array of platform configurations","example":[{"platform":"facebook","utm_source":"facebook","utm_medium":"social","utm_content":"post1"},{"platform":"instagram","utm_source":"instagram","utm_medium":"story","custom_key":"summer-ig"}]},"reuseUTM":{"type":"boolean","default":false,"description":"Allow reusing existing UTM campaign names"}}}}}},"responses":{"200":{"description":"Campaign created successfully","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Campaign created successfully"},"campaign":{"$ref":"#/components/schemas/Campaign"},"links":{"type":"array","items":{"$ref":"#/components/schemas/CampaignLink"}}}}}}},"400":{"description":"Bad request - Missing required fields","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict - UTM campaign name already exists","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"UTM campaign name already exists"},"message":{"type":"string","example":"A campaign with UTM campaign \"summer2025\" already exists in this organization"},"existing_campaign":{"type":"object","properties":{"id":{"type":"integer","example":123},"name":{"type":"string","example":"Existing Campaign"},"utm_campaign":{"type":"string","example":"summer2025"}}}}}}}},"429":{"description":"Rate limit or quota exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Quota exceeded"},"currentUsage":{"type":"integer","example":5},"limits":{"type":"object","properties":{"campaigns":{"type":"integer","example":5}}}}}}}}}}},"/v1/organizations/{orgId}/campaigns/{campaignId}":{"get":{"summary":"Get campaign details","description":"Retrieve a specific campaign with all its links","tags":["API v1 - Campaigns"],"security":[{"ApiKeyAuth":[],"ApiSecretAuth":[]}],"parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"},"description":"Organization ID","example":"1"},{"name":"campaignId","in":"path","required":true,"schema":{"type":"string"},"description":"Campaign ID","example":"123"}],"responses":{"200":{"description":"Successfully retrieved campaign details","content":{"application/json":{"schema":{"type":"object","properties":{"campaign":{"$ref":"#/components/schemas/Campaign"},"links":{"type":"array","items":{"$ref":"#/components/schemas/CampaignLink"}}}}}}},"404":{"description":"Campaign not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"summary":"Update campaign","description":"Update campaign details including UTM parameters","tags":["API v1 - Campaigns"],"security":[{"ApiKeyAuth":[],"ApiSecretAuth":[]}],"parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"},"description":"Organization ID","example":"1"},{"name":"campaignId","in":"path","required":true,"schema":{"type":"string"},"description":"Campaign ID","example":"123"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","example":"Updated Campaign Name","description":"Updated campaign name"},"base_url":{"type":"string","format":"uri","example":"https://example.com/new-landing","description":"Updated base URL"},"utm_campaign":{"type":"string","example":"updated-campaign","description":"Updated UTM campaign parameter"},"utm_source":{"type":"string","example":"email","description":"Updated UTM source parameter"},"utm_medium":{"type":"string","example":"newsletter","description":"Updated UTM medium parameter"},"utm_term":{"type":"string","example":"updated-keywords","description":"Updated UTM term parameter"},"utm_content":{"type":"string","example":"updated-content","description":"Updated UTM content parameter"}}}}}},"responses":{"200":{"description":"Campaign updated successfully","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Campaign updated successfully"},"campaign":{"$ref":"#/components/schemas/Campaign"}}}}}},"400":{"description":"Bad request - No valid fields to update","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Campaign not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict - UTM campaign name already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"summary":"Delete campaign","description":"Delete a campaign and all its associated links","tags":["API v1 - Campaigns"],"security":[{"ApiKeyAuth":[],"ApiSecretAuth":[]}],"parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"},"description":"Organization ID","example":"1"},{"name":"campaignId","in":"path","required":true,"schema":{"type":"string"},"description":"Campaign ID","example":"123"}],"responses":{"200":{"description":"Campaign deleted successfully","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Campaign and all associated links deleted successfully"}}}}}},"404":{"description":"Campaign not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/organizations/{orgId}/campaigns/{campaignId}/analytics":{"get":{"summary":"Get campaign analytics","description":"Retrieve analytics data for a specific campaign","tags":["API v1 - Campaigns"],"security":[{"ApiKeyAuth":[],"ApiSecretAuth":[]}],"parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"},"description":"Organization ID","example":"1"},{"name":"campaignId","in":"path","required":true,"schema":{"type":"string"},"description":"Campaign ID","example":"123"}],"responses":{"200":{"description":"Successfully retrieved campaign analytics","content":{"application/json":{"schema":{"type":"object","properties":{"campaign":{"$ref":"#/components/schemas/Campaign"},"links":{"type":"array","items":{"allOf":[{"$ref":"#/components/schemas/CampaignLink"},{"type":"object","properties":{"clicks":{"type":"integer","example":245,"description":"Total clicks for this link"},"unique_clicks":{"type":"integer","example":198,"description":"Unique clicks for this link"},"conversion_rate":{"type":"string","example":"80.82","description":"Conversion rate percentage"}}}]}},"total_clicks":{"type":"integer","example":1247,"description":"Total clicks across all campaign links"},"total_unique_clicks":{"type":"integer","example":967,"description":"Total unique clicks across all campaign links"},"generatedAt":{"type":"string","format":"date-time","example":"2025-08-15T12:00:00Z","description":"Analytics generation timestamp"}}}}}},"404":{"description":"Campaign not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/organizations/{orgId}/campaigns/{campaignId}/links":{"post":{"summary":"Create campaign link","description":"Create a new link for an existing campaign","tags":["API v1 - Campaigns"],"security":[{"ApiKeyAuth":[],"ApiSecretAuth":[]}],"parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"},"description":"Organization ID","example":"1"},{"name":"campaignId","in":"path","required":true,"schema":{"type":"string"},"description":"Campaign ID","example":"123"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["platform"],"properties":{"platform":{"type":"string","example":"youtube","description":"Platform name for this link"},"utm_source":{"type":"string","example":"youtube","description":"Custom UTM source (overrides platform preset)"},"utm_medium":{"type":"string","example":"video","description":"Custom UTM medium (overrides platform preset)"},"utm_term":{"type":"string","example":"keyword","description":"Custom UTM term (overrides platform preset)"},"utm_content":{"type":"string","example":"banner","description":"Custom UTM content (overrides platform preset)"},"custom_key":{"type":"string","example":"my-youtube-link","description":"Custom short key for this link"}}}}}},"responses":{"200":{"description":"Campaign link created successfully","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Campaign link created successfully"},"link":{"$ref":"#/components/schemas/CampaignLink"}}}}}},"400":{"description":"Bad request - Platform is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Campaign not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict - Custom key is already taken","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/organizations/{orgId}/campaigns/{campaignId}/links/{linkId}":{"delete":{"summary":"Delete campaign link","description":"Delete a specific link from a campaign","tags":["API v1 - Campaigns"],"security":[{"ApiKeyAuth":[],"ApiSecretAuth":[]}],"parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"},"description":"Organization ID","example":"1"},{"name":"campaignId","in":"path","required":true,"schema":{"type":"string"},"description":"Campaign ID","example":"123"},{"name":"linkId","in":"path","required":true,"schema":{"type":"string"},"description":"Campaign Link ID","example":"456"}],"responses":{"200":{"description":"Campaign link deleted successfully","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Campaign link deleted successfully"}}}}}},"404":{"description":"Campaign or link not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}