openapi: 3.0.0
info:
  version: 1.0.0
  title: State API
  description: State API for managing short links and analytics
servers:
  - url: /api
security:
  - ApiKeyAuth: []
components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
  schemas:
    VersionResponse:
      type: object
      properties:
        version:
          type: string
          example: 1.0.0
        build_id:
          type: string
          example: build-123
        build_time:
          type: string
          format: date-time
          example: 2024-01-01T00:00:00Z
      required:
        - version
        - build_id
        - build_time
    Folder:
      type: object
      properties:
        id:
          type: number
          example: 1
        name:
          type: string
          example: My Folder
        color:
          type: string
          example: "#FF0000"
        created_at:
          type: string
          format: date-time
          example: 2024-01-01T00:00:00Z
        updated_at:
          type: string
          format: date-time
          example: 2024-01-01T00:00:00Z
      required:
        - id
        - name
        - created_at
        - updated_at
    FoldersResponse:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/Folder"
        total:
          type: number
          example: 100
        offset:
          type: number
          example: 0
        limit:
          type: number
          example: 25
      required:
        - items
        - total
        - offset
        - limit
    CreateFolder:
      type: object
      properties:
        name:
          type: string
          example: My Folder
        color:
          type: string
          example: "#FF0000"
      required:
        - name
    CreateFolderRequest:
      type: object
      properties:
        name:
          type: string
          example: My Folder
        color:
          type: string
          example: "#FF0000"
      required:
        - name
    Tag:
      type: object
      properties:
        id:
          type: number
          example: 1
        name:
          type: string
          example: important
        color:
          type: string
          example: "#00FF00"
        created_at:
          type: string
          format: date-time
          example: 2024-01-01T00:00:00Z
        updated_at:
          type: string
          format: date-time
          example: 2024-01-01T00:00:00Z
      required:
        - id
        - name
        - created_at
        - updated_at
    TagsResponse:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/Tag"
        total:
          type: number
          example: 50
        offset:
          type: number
          example: 0
        limit:
          type: number
          example: 25
      required:
        - items
        - total
        - offset
        - limit
    CreateTag:
      type: object
      properties:
        name:
          type: string
          example: My tag
        color:
          type: string
          example: "#FF0000"
      required:
        - name
    CreateTagRequest:
      type: object
      properties:
        name:
          type: string
          example: My tag
        color:
          type: string
          example: "#FF0000"
      required:
        - name
    Domain:
      type: object
      properties:
        id:
          type: number
          example: 1
        org_id:
          type: string
          example: org-123
        name:
          type: string
          example: My Domain
        slug_length:
          type: number
          example: 6
        allow_preview:
          type: boolean
          example: false
        verified:
          type: boolean
          example: true
        owner:
          type: string
          example: state
      required:
        - id
        - org_id
        - name
        - slug_length
        - allow_preview
        - verified
    DomainsResponse:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/Domain"
        total:
          type: number
          example: 10
        offset:
          type: number
          example: 0
        limit:
          type: number
          example: 25
      required:
        - items
        - total
        - offset
        - limit
    Organization:
      type: object
      properties:
        id:
          type: string
          example: org-123
        name:
          type: string
          example: My Organization
        slug:
          type: string
          example: my-org
        logo:
          type: string
          nullable: true
          example: https://example.com/logo.png
      required:
        - id
        - name
        - slug
    Bio:
      type: object
      nullable: true
      properties:
        title:
          type: string
          nullable: true
          example: My Bio
        subtitle:
          type: string
          nullable: true
          example: Software Developer
        email:
          type: string
          nullable: true
          example: john@example.com
        image:
          type: string
          nullable: true
          example: https://example.com/photo.jpg
    BioLink:
      type: object
      properties:
        id:
          type: number
          example: 1
        type:
          type: string
          example: website
        url:
          type: string
          example: https://example.com
        title:
          type: string
          nullable: true
          example: My Website
        username:
          type: string
          nullable: true
          example: johndoe
      required:
        - id
        - type
        - url
    BioLinkCreate:
      type: object
      properties:
        type:
          type: string
          enum:
            - behance
            - bluesky
            - discord
            - dribbble
            - facebook
            - flickr
            - github
            - instagram
            - linkedin
            - mastodon
            - medium
            - pinterest
            - railway
            - reddit
            - snapchat
            - telegram
            - tiktok
            - tumblr
            - twitter
            - threads
            - vimeo
            - whatsapp
            - youtube
            - zoom
          example: "@reddit"
        url:
          anyOf:
            - type: string
              format: uri
              example: https://example.com
            - type: string
              example: username
        title:
          type: string
          nullable: true
          example: My Website
      required:
        - url
    BioLinkEditable:
      type: object
      properties:
        id:
          type: number
          example: 1
        type:
          type: string
          example: website
        url:
          type: string
          example: https://example.com
        title:
          type: string
          nullable: true
          example: My Website
        order:
          type: number
          example: 1
        enabled:
          type: boolean
          example: true
        created_at:
          type: string
          format: date-time
          example: 2024-01-01T00:00:00Z
        updated_at:
          type: string
          format: date-time
          example: 2024-01-01T00:00:00Z
      required:
        - id
        - type
        - url
        - order
        - enabled
        - created_at
        - updated_at
    BioLinkOrder:
      type: array
      items:
        type: object
        properties:
          id:
            type: number
          index:
            type: number
        required:
          - id
          - index
    BioResponse:
      type: object
      properties:
        id:
          type: number
          example: 1
        organization:
          $ref: "#/components/schemas/Organization"
        bio:
          $ref: "#/components/schemas/Bio"
        links:
          type: array
          items:
            $ref: "#/components/schemas/BioLink"
      required:
        - id
        - organization
        - bio
        - links
    LinkFolder:
      type: object
      properties:
        id:
          type: number
          example: 1
        name:
          type: string
          example: Marketing
        color:
          type: string
          nullable: true
          example: "#FF0000"
      required:
        - id
        - name
    LinkTag:
      type: object
      properties:
        id:
          type: number
          example: 1
        name:
          type: string
          example: social
        color:
          type: string
          nullable: true
          example: "#00FF00"
      required:
        - id
        - name
    ABLink:
      type: object
      properties:
        id:
          type: number
          example: 1
        url:
          type: string
          example: https://example.com/variant-a
        percent:
          type: number
          example: 50
      required:
        - id
        - url
        - percent
    ABLinkRequest:
      type: object
      properties:
        id:
          type: number
          example: null
        url:
          type: string
          example: https://example.com/variant-a
        percent:
          type: number
          example: 50
      required:
        - url
        - percent
    GeoLink:
      type: object
      properties:
        id:
          type: number
          example: 1
        url:
          type: string
          example: https://example.com/us
        country:
          type: string
          example: US
      required:
        - id
        - url
        - country
    GeoLinkRequest:
      type: object
      properties:
        id:
          type: number
          example: null
        url:
          type: string
          example: https://example.com/us
        country:
          type: string
          example: US
      required:
        - url
        - country
    ShortLink:
      type: object
      properties:
        id:
          type: string
          example: link-123
        organization_id:
          type: string
          example: org-123
        user_id:
          type: string
          example: user-123
        url:
          type: string
          example: https://example.com
        domain_id:
          type: number
          example: 1
        domain:
          type: string
          example: state.sk
        slug:
          type: string
          example: my-link
        short_url:
          type: string
          example: https://example.com/my-link
        title:
          type: string
          example: My Link
        utm_source:
          type: string
          nullable: true
          example: google
        utm_medium:
          type: string
          nullable: true
          example: cpc
        utm_campaign:
          type: string
          nullable: true
          example: spring_sale
        utm_term:
          type: string
          nullable: true
          example: running+shoes
        utm_content:
          type: string
          nullable: true
          example: logo
        utm_reference:
          type: string
          nullable: true
          example: ref123
        redirect_code:
          anyOf:
            - type: number
              enum:
                - 301
            - type: number
              enum:
                - 302
            - nullable: true
          example: 302
        folder_id:
          type: number
          nullable: true
          example: 1
        folder:
          allOf:
            - $ref: "#/components/schemas/LinkFolder"
            - nullable: true
        tags:
          type: array
          nullable: true
          items:
            $ref: "#/components/schemas/LinkTag"
        expires_at:
          type: string
          nullable: true
          format: date-time
          example: 2024-12-31T23:59:59Z
        expires_after:
          type: number
          nullable: true
          example: 30
        expire_url:
          type: string
          nullable: true
          example: https://example.com/expired
        ios:
          type: string
          nullable: true
          example: https://apps.apple.com/app/id123
        android:
          type: string
          nullable: true
          format: uri
          example: https://play.google.com/store/apps/details?id=com.example
        created_at:
          type: string
          format: date-time
          example: 2024-01-01T00:00:00Z
        updated_at:
          type: string
          format: date-time
          example: 2024-01-01T00:00:00Z
        ab:
          type: array
          items:
            $ref: "#/components/schemas/ABLink"
        geo:
          type: array
          items:
            $ref: "#/components/schemas/GeoLink"
        has_password:
          type: boolean
          example: false
        clicks:
          type: number
          example: 150
        geo_url:
          type: string
          nullable: true
          example: https://example.com/geo
      required:
        - id
        - organization_id
        - user_id
        - url
        - domain_id
        - domain
        - slug
        - short_url
        - created_at
        - updated_at
        - ab
        - geo
        - has_password
        - clicks
    LinksResponse:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/ShortLink"
        total:
          type: number
          example: 100
        offset:
          type: number
          example: 0
        limit:
          type: number
          example: 25
      required:
        - items
        - total
        - offset
        - limit
    ImportLinksRequest:
      type: object
      properties:
        domain_id:
          type: number
          example: 1
        folder_id:
          type: number
          example: null
        tags:
          type: array
          items:
            type: number
          example: []
        csv:
          type: array
          items:
            type: object
            properties:
              url:
                type: string
                example: https://whitetown.com/products
              domain_id:
                type: string
                example: 1
              slug:
                type: string
                example: null
            required:
              - url
          example:
            - url: https://whitetown.com/products
      required:
        - domain_id
        - csv
    MoveFolderLinksRequest:
      type: object
      properties:
        folder_id:
          type: number
          example: 42
        ids:
          type: array
          items:
            type: number
          example:
            - 1
            - 2
            - 3
      required:
        - ids
    AssignTagsLinksReques:
      type: object
      properties:
        tags:
          type: array
          items:
            type: number
          example:
            - 42
            - 69
        ids:
          type: array
          items:
            type: number
          example:
            - 1
            - 2
            - 3
      required:
        - tags
        - ids
    CreateLinkRequest:
      type: object
      properties:
        url:
          type: string
          example: https://whitetown.com/products
        domain_id:
          type: number
          example: 1
        slug:
          type: string
          example: null
        slug_length:
          type: number
          example: null
        title:
          type: string
          example: null
        folder_id:
          type: number
          example: null
        tags:
          type: array
          items:
            type: number
          example: []
        utm_source:
          type: string
          example: state
        utm_medium:
          type: string
          example: cpc
        utm_campaign:
          type: string
          example: spring_sale
        utm_term:
          type: string
          example: dbf+tools
        utm_content:
          type: string
          example: logo
        utm_reference:
          type: string
          example: state
        redirect_code:
          anyOf:
            - type: number
              enum:
                - 301
            - type: number
              enum:
                - 302
            - nullable: true
          example: 302
        password:
          type: string
          example: null
        remove_password:
          type: boolean
          example: false
        expires_at:
          type: string
          format: date-time
          example: null
        expires_after:
          type: number
          example: 0
        expire_url:
          type: string
          example: null
      required:
        - url
        - domain_id
    Click:
      type: object
      properties:
        id:
          type: string
          example: click-123
        link_id:
          type: string
          example: link-123
        domain_id:
          type: number
          example: 1
        domain:
          type: string
          example: state.sk
        slug:
          type: string
          example: my-link
        url:
          type: string
          example: https://example.com
        title:
          type: string
          example: My Link
        ip:
          type: string
          example: 192.168.1.1
        browser:
          type: string
          example: Chrome
        os:
          type: string
          example: Windows
        device:
          type: string
          example: Desktop
        language:
          type: string
          example: en-US
        platform:
          type: string
          example: Win32
        brand:
          type: string
          example: Google
        is_mobile:
          type: boolean
          example: false
        color_scheme:
          type: string
          example: light
        referer:
          type: string
          example: https://google.com
        continent:
          type: string
          example: North America
        country:
          type: string
          example: United States
        region:
          type: string
          example: California
        city:
          type: string
          example: San Francisco
        is_eu:
          type: boolean
          example: false
        geo:
          type: object
          properties: {}
        query:
          type: object
          properties: {}
        created_at:
          type: string
          example: 2024-01-01T00:00:00Z
        updated_at:
          type: string
          example: 2024-01-01T00:00:00Z
        utm_campaign:
          type: string
          example: spring_sale
        utm_source:
          type: string
          example: google
        utm_medium:
          type: string
          example: cpc
        utm_term:
          type: string
          example: running+shoes
        utm_content:
          type: string
          example: logo
        utm_reference:
          type: string
          example: ref123
      required:
        - id
        - link_id
        - domain_id
        - domain
        - slug
        - url
        - created_at
        - updated_at
    ClicksStreamResponse:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/Click"
        total:
          type: number
          example: 1000
        offset:
          type: number
          example: 0
        limit:
          type: number
          example: 25
      required:
        - items
        - total
        - offset
        - limit
    AnalyticsSummaryObject:
      type: object
      properties:
        total:
          type: number
          example: 150
        month:
          type: number
          example: 25
      required:
        - total
        - month
    AnalyticsSummary:
      type: object
      properties:
        links:
          $ref: "#/components/schemas/AnalyticsSummaryObject"
        clicks:
          $ref: "#/components/schemas/AnalyticsSummaryObject"
      required:
        - links
        - clicks
    TitleValue:
      type: object
      properties:
        title:
          type: string
          example: United States
        value:
          type: string
          example: US
      required:
        - title
        - value
    AnalyticsValuesResponse:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/TitleValue"
        total:
          type: number
          example: 50
        offset:
          type: number
          example: 0
        limit:
          type: number
          example: 25
      required:
        - items
        - total
        - offset
        - limit
    TimeCount:
      type: object
      properties:
        time:
          type: string
          example: 2024-01-01
        clicks:
          type: number
          example: 150
      required:
        - time
        - clicks
    TitleClicks:
      type: object
      properties:
        title:
          type: string
          example: US
        clicks:
          type: number
          example: 150
      required:
        - title
        - clicks
    GroupedField:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/TitleClicks"
        total:
          type: number
          example: 50
        offset:
          type: number
          example: 0
        limit:
          type: number
          example: 25
      required:
        - items
        - total
        - offset
        - limit
    AnalyticsGroupsResponse:
      type: object
      properties:
        field1:
          $ref: "#/components/schemas/GroupedField"
        field2:
          $ref: "#/components/schemas/GroupedField"
    GeoContinent:
      type: object
      properties:
        code:
          type: string
          example: NA
        geonameId:
          type: number
          example: 6255149
        names:
          type: object
          properties:
            de:
              type: string
              example: Nordamerika
            en:
              type: string
              example: North America
            es:
              type: string
              example: Norteamérica
            fr:
              type: string
              example: Amérique du Nord
            ja:
              type: string
              example: 北アメリカ
            pt-BR:
              type: string
              example: América do Norte
            ru:
              type: string
              example: Северная Америка
            zh-CN:
              type: string
              example: 北美洲
      required:
        - code
        - geonameId
        - names
    GeoCountry:
      type: object
      properties:
        geonameId:
          type: number
          example: 6252001
        isoCode:
          type: string
          example: US
        names:
          type: object
          properties:
            de:
              type: string
              example: USA
            en:
              type: string
              example: United States
            es:
              type: string
              example: Estados Unidos
            fr:
              type: string
              example: États Unis
            ja:
              type: string
              example: アメリカ
            pt-BR:
              type: string
              example: EUA
            ru:
              type: string
              example: США
            zh-CN:
              type: string
              example: 美国
      required:
        - geonameId
        - isoCode
        - names
    GeoRegisteredCountry:
      allOf:
        - $ref: "#/components/schemas/GeoCountry"
        - type: object
          properties:
            isInEuropeanUnion:
              type: boolean
              example: false
          required:
            - isInEuropeanUnion
    GeoTraits:
      type: object
      properties:
        isAnonymous:
          type: boolean
          example: false
        isAnonymousProxy:
          type: boolean
          example: false
        isAnonymousVpn:
          type: boolean
          example: false
        isAnycast:
          type: boolean
          example: false
        isHostingProvider:
          type: boolean
          example: false
        isLegitimateProxy:
          type: boolean
          example: false
        isPublicProxy:
          type: boolean
          example: false
        isResidentialProxy:
          type: boolean
          example: false
        isSatelliteProvider:
          type: boolean
          example: false
        isTorExitNode:
          type: boolean
          example: false
        ipAddress:
          type: string
          example: 172.100.25.142
        network:
          type: string
          example: 172.100.0.0/19
      required:
        - isAnonymous
        - isAnonymousProxy
        - isAnonymousVpn
        - isAnycast
        - isHostingProvider
        - isLegitimateProxy
        - isPublicProxy
        - isResidentialProxy
        - isSatelliteProvider
        - isTorExitNode
        - ipAddress
        - network
    GeoCity:
      type: object
      properties:
        geonameId:
          type: number
          example: 5110629
        names:
          type: object
          properties:
            de:
              type: string
              example: Buffalo
            en:
              type: string
              example: Buffalo
            es:
              type: string
              example: Búfalo
            fr:
              type: string
              example: Buffalo
            ja:
              type: string
              example: バッファロー
            pt-BR:
              type: string
              example: Buffalo
            ru:
              type: string
              example: Буффало
            zh-CN:
              type: string
              example: 水牛城
      required:
        - geonameId
        - names
    GeoLocation:
      type: object
      properties:
        accuracyRadius:
          type: number
          example: 5
        latitude:
          type: number
          example: 42.9135
        longitude:
          type: number
          example: -78.889
        metroCode:
          type: number
          example: 514
        timeZone:
          type: string
          example: America/New_York
      required:
        - accuracyRadius
        - latitude
        - longitude
        - metroCode
        - timeZone
    GeoPostal:
      type: object
      properties:
        code:
          type: string
          example: "14213"
      required:
        - code
    GeoSubdivision:
      type: object
      properties:
        geonameId:
          type: number
          example: 5128638
        isoCode:
          type: string
          example: NY
        names:
          type: object
          properties:
            de:
              type: string
              example: New York
            en:
              type: string
              example: New York
            es:
              type: string
              example: Nueva York
            fr:
              type: string
              example: New York
            ja:
              type: string
              example: ニューヨーク州
            pt-BR:
              type: string
              example: Nova Iorque
            ru:
              type: string
              example: Нью-Йорк
            zh-CN:
              type: string
              example: 纽约州
      required:
        - geonameId
        - isoCode
        - names
    GeoResponse:
      type: object
      properties:
        continent:
          $ref: "#/components/schemas/GeoContinent"
        country:
          $ref: "#/components/schemas/GeoCountry"
        registeredCountry:
          $ref: "#/components/schemas/GeoRegisteredCountry"
        traits:
          $ref: "#/components/schemas/GeoTraits"
        city:
          $ref: "#/components/schemas/GeoCity"
        location:
          $ref: "#/components/schemas/GeoLocation"
        postal:
          $ref: "#/components/schemas/GeoPostal"
        subdivisions:
          type: array
          items:
            $ref: "#/components/schemas/GeoSubdivision"
      required:
        - continent
        - country
        - registeredCountry
        - traits
        - location
    Country:
      type: object
      properties:
        clicks:
          type: number
          example: 1500
        title:
          type: string
          example: United States
        value:
          type: string
          example: US
        iso2:
          type: string
          example: US
        iso3:
          type: string
          example: USA
      required:
        - clicks
        - title
        - value
        - iso2
        - iso3
    CountriesResponse:
      type: object
      properties:
        items:
          type: array
          items:
            type: array
            items:
              $ref: "#/components/schemas/Country"
        total:
          type: number
          example: 50
        offset:
          type: number
          example: 0
        limit:
          type: number
          example: 25
      required:
        - items
        - total
        - offset
        - limit
    City:
      type: object
      properties:
        clicks:
          type: number
          example: 250
        title:
          type: string
          example: San Francisco
        country:
          type: string
          example: United States
        region:
          type: string
          example: California
      required:
        - clicks
        - title
        - country
        - region
    CitiesResponse:
      type: object
      properties:
        items:
          type: array
          items:
            type: array
            items:
              $ref: "#/components/schemas/City"
        total:
          type: number
          example: 100
        offset:
          type: number
          example: 0
        limit:
          type: number
          example: 25
      required:
        - items
        - total
        - offset
        - limit
    Region:
      type: object
      properties:
        clicks:
          type: number
          example: 500
        title:
          type: string
          example: California
        country:
          type: string
          example: United States
      required:
        - clicks
        - title
        - country
    RegionsResponse:
      type: object
      properties:
        items:
          type: array
          items:
            type: array
            items:
              $ref: "#/components/schemas/Region"
        total:
          type: number
          example: 25
        offset:
          type: number
          example: 0
        limit:
          type: number
          example: 25
      required:
        - items
        - total
        - offset
        - limit
    LimitParam:
      type: string
      enum:
        - "10"
        - "25"
        - "50"
        - "75"
        - "100"
    DomainParam:
      type: string
      example: state.sk
    LinkIdParam:
      type: string
    SlugParam:
      type: string
    PeriodParam:
      type: string
      enum:
        - today
        - yesterday
        - week
        - lastweek
        - month
        - lastmonth
        - year
        - all
      description: You can also provide a custom range, period=YYYY-MM-DD,YYYY-MM-DD,
        i.e. period=2025-10-01,2025-10-13
    FieldParam:
      type: string
      enum:
        - country
        - city
        - region
        - continent
        - browser
        - os
        - device
      example: country
    IpParam:
      type: string
    FolderIdParam:
      type: string
    TagIdParam:
      type: string
    UpdateMobileLinksRequest:
      type: object
      properties:
        ios:
          type: string
          example: https://apps.apple.com/app/id123
        android:
          type: string
          example: https://play.google.com/store/apps/details?id=com.example
    UpdateABLinksRequest:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/ABLinkRequest"
      required:
        - items
    UpdateGeoLinksRequest:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/GeoLinkRequest"
      required:
        - items
  parameters:
    LimitParam:
      schema:
        $ref: "#/components/schemas/LimitParam"
      required: false
      name: limit
      in: query
    DomainParam:
      schema:
        $ref: "#/components/schemas/DomainParam"
      required: true
      name: domain
      in: query
    LinkIdParam:
      schema:
        $ref: "#/components/schemas/LinkIdParam"
      required: true
      name: link_id
      in: path
    SlugParam:
      schema:
        $ref: "#/components/schemas/SlugParam"
      required: true
      name: slug
      in: query
    PeriodParam:
      schema:
        $ref: "#/components/schemas/PeriodParam"
      required: false
      description: You can also provide a custom range, period=YYYY-MM-DD,YYYY-MM-DD,
        i.e. period=2025-10-01,2025-10-13
      name: period
      in: query
    FieldParam:
      schema:
        $ref: "#/components/schemas/FieldParam"
      required: true
      name: field
      in: query
    IpParam:
      schema:
        $ref: "#/components/schemas/IpParam"
      required: false
      name: ip
      in: query
    FolderIdParam:
      schema:
        $ref: "#/components/schemas/FolderIdParam"
      required: true
      name: folder_id
      in: path
    TagIdParam:
      schema:
        $ref: "#/components/schemas/TagIdParam"
      required: true
      name: tag_id
      in: path
paths:
  /links:
    get:
      tags:
        - Short links
      summary: Get short links
      parameters:
        - schema:
            type: number
          required: false
          name: domain_id
          in: query
        - schema:
            type: string
          required: false
          name: search
          in: query
        - schema:
            type: string
          required: false
          name: order
          in: query
        - schema:
            type: number
          required: false
          name: folder_id
          in: query
        - schema:
            type: number
          required: false
          name: tag_id
          in: query
        - schema:
            type: boolean
          required: false
          name: all
          in: query
        - schema:
            type: number
          required: false
          name: page
          in: query
        - schema:
            type: number
          required: false
          name: limit
          in: query
      responses:
        "200":
          description: Links response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/LinksResponse"
        "403":
          description: Access denied
        "404":
          description: Link not found
  /links/import:
    post:
      tags:
        - Short links
      summary: Import links
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ImportLinksRequest"
      responses:
        "200":
          description: Links response
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/ShortLink"
        "400":
          description: Failed to import links
  /links/folder:
    post:
      tags:
        - Short links
      summary: Move links to a folder
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/MoveFolderLinksRequest"
      responses:
        "200":
          description: Links response
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    enum:
                      - OK
                required:
                  - message
        "400":
          description: Failed to move links
  /links/tags:
    post:
      tags:
        - Short links
      summary: Assign tags to links
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/AssignTagsLinksReques"
      responses:
        "200":
          description: Links response
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    enum:
                      - OK
                required:
                  - message
        "400":
          description: Failed to assign tags to links
  /link:
    post:
      tags:
        - Short link
      summary: Create short link
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateLinkRequest"
      responses:
        "200":
          description: Link response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ShortLink"
        "400":
          description: Cannot create a link
        "403":
          description: Access denied
        "412":
          description: Validation failed
        "417":
          description: Wrong URL or domain
    get:
      tags:
        - Short link
      summary: Get short link by domain and slug
      parameters:
        - $ref: "#/components/parameters/DomainParam"
        - $ref: "#/components/parameters/SlugParam"
        - $ref: "#/components/parameters/IpParam"
      responses:
        "200":
          description: Link response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ShortLink"
        "403":
          description: Access denied
        "404":
          description: Link not found
  /link/{link_id}:
    get:
      tags:
        - Short link
      summary: Get short link by ID
      parameters:
        - $ref: "#/components/parameters/LinkIdParam"
        - $ref: "#/components/parameters/IpParam"
      responses:
        "200":
          description: Link response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ShortLink"
        "403":
          description: Access denied
        "404":
          description: Link not found
    put:
      tags:
        - Short link
      summary: Update short link
      parameters:
        - $ref: "#/components/parameters/LinkIdParam"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateLinkRequest"
      responses:
        "200":
          description: Link response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ShortLink"
        "400":
          description: Cannot create a link
        "403":
          description: Access denied
        "404":
          description: Link not found
        "412":
          description: Validation failed
        "417":
          description: Wrong URL or domain
    delete:
      tags:
        - Short link
      summary: Delete short link
      parameters:
        - $ref: "#/components/parameters/LinkIdParam"
      responses:
        "201":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    enum:
                      - OK
                required:
                  - message
        "403":
          description: Access denied
        "404":
          description: Link not found
  /link/{link_id}/mobile:
    put:
      tags:
        - Short link
      summary: Update mobile links (iOS, Android)
      parameters:
        - $ref: "#/components/parameters/LinkIdParam"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpdateMobileLinksRequest"
      responses:
        "200":
          description: Link response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ShortLink"
        "403":
          description: Access denied
        "404":
          description: Link not found
  /link/{link_id}/ab:
    put:
      tags:
        - Short link
      summary: Update A/B links
      parameters:
        - $ref: "#/components/parameters/LinkIdParam"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpdateABLinksRequest"
      responses:
        "200":
          description: Link response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ShortLink"
        "403":
          description: Access denied
        "404":
          description: Link not found
  /link/{link_id}/geo:
    put:
      tags:
        - Short link
      summary: Update geo links
      parameters:
        - $ref: "#/components/parameters/LinkIdParam"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpdateGeoLinksRequest"
      responses:
        "200":
          description: Link response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ShortLink"
        "403":
          description: Access denied
        "404":
          description: Link not found
  /folders:
    get:
      tags:
        - Folders
      summary: Get folders
      parameters:
        - schema:
            type: string
          required: false
          name: search
          in: query
        - schema:
            type: number
          required: false
          name: page
          in: query
        - schema:
            type: number
          required: false
          name: limit
          in: query
      responses:
        "200":
          description: Folders list
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/FoldersResponse"
        "403":
          description: Access denied
        "404":
          description: Folders not found
    post:
      tags:
        - Folders
      summary: Add folder
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateFolderRequest"
      responses:
        "200":
          description: Folder
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Folder"
        "403":
          description: Access denied
  /folders/{folder_id}:
    put:
      tags:
        - Folders
      summary: Save folder
      parameters:
        - $ref: "#/components/parameters/FolderIdParam"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateFolderRequest"
      responses:
        "200":
          description: Folder
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Folder"
        "403":
          description: Access denied
        "404":
          description: Folder not found
    delete:
      tags:
        - Folders
      summary: Delete folder
      parameters:
        - $ref: "#/components/parameters/FolderIdParam"
      responses:
        "201":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    enum:
                      - OK
                required:
                  - message
        "403":
          description: Access denied
        "404":
          description: Folder not found
  /tags:
    get:
      tags:
        - Tags
      summary: Get tags
      parameters:
        - schema:
            type: string
          required: false
          name: search
          in: query
        - schema:
            type: number
          required: false
          name: page
          in: query
        - schema:
            type: number
          required: false
          name: limit
          in: query
      responses:
        "200":
          description: Tags list
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TagsResponse"
        "403":
          description: Access denied
        "404":
          description: Tags not found
    post:
      tags:
        - Tags
      summary: Add tag
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateTagRequest"
      responses:
        "200":
          description: Tag
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Tag"
        "403":
          description: Access denied
  /tags/{tag_id}:
    put:
      tags:
        - Tags
      summary: Save tag
      parameters:
        - $ref: "#/components/parameters/TagIdParam"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateTagRequest"
      responses:
        "200":
          description: Tag
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Tag"
        "403":
          description: Access denied
        "404":
          description: Tag not found
    delete:
      tags:
        - Tags
      summary: Delete tag
      parameters:
        - $ref: "#/components/parameters/TagIdParam"
      responses:
        "201":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    enum:
                      - OK
                required:
                  - message
        "403":
          description: Access denied
        "404":
          description: Tag not found
  /domains/available:
    get:
      tags:
        - Domains
      summary: Get available domains
      parameters:
        - schema:
            type: string
          required: false
          name: search
          in: query
      responses:
        "200":
          description: Domains list
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DomainsResponse"
        "403":
          description: Access denied
        "404":
          description: Domains not found
  /team/bio:
    get:
      tags:
        - Bio
      summary: Get bio
      security:
        - ApiKeyAuth: []
      responses:
        "200":
          description: Bio summary
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BioResponse"
  /team/bio/info:
    get:
      tags:
        - Bio
      summary: Get bio info
      security:
        - ApiKeyAuth: []
      responses:
        "200":
          description: Bio info
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Bio"
    post:
      tags:
        - Bio
      summary: Update bio info
      security:
        - ApiKeyAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/Bio"
      responses:
        "200":
          description: Bio info
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Bio"
  /team/bio/links:
    get:
      tags:
        - Bio
      summary: Get bio links
      security:
        - ApiKeyAuth: []
      responses:
        "200":
          description: Bio links
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/BioLinkEditable"
    post:
      tags:
        - Bio
      summary: Add bio link
      security:
        - ApiKeyAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/BioLinkCreate"
      responses:
        "200":
          description: Bio link
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BioLink"
    patch:
      tags:
        - Bio
      summary: Change bio links order
      security:
        - ApiKeyAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/BioLinkOrder"
      responses:
        "200":
          description: Bio link
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    enum:
                      - OK
                required:
                  - message
  /team/bio/links/{link_id}:
    put:
      tags:
        - Bio
      summary: Update bio link
      security:
        - ApiKeyAuth: []
      parameters:
        - $ref: "#/components/parameters/LinkIdParam"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/BioLinkCreate"
      responses:
        "200":
          description: Bio link
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BioLink"
    delete:
      tags:
        - Bio
      summary: Delete bio link
      security:
        - ApiKeyAuth: []
      parameters:
        - $ref: "#/components/parameters/LinkIdParam"
      responses:
        "201":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    enum:
                      - OK
                required:
                  - message
  /analytics/summary:
    get:
      tags:
        - Analytics
      summary: Get analytics summary
      security:
        - ApiKeyAuth: []
      responses:
        "200":
          description: Summary
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AnalyticsSummary"
  /analytics/stream:
    get:
      tags:
        - Analytics
      summary: Get clicks raw values
      security:
        - ApiKeyAuth: []
      parameters:
        - schema:
            type: string
          required: false
          name: link_id
          in: query
        - schema:
            type: number
          required: false
          name: domain_id
          in: query
        - schema:
            type: string
          required: false
          name: search
          in: query
        - $ref: "#/components/parameters/PeriodParam"
        - schema:
            type: string
          required: false
          name: country
          in: query
        - schema:
            type: string
          required: false
          name: city
          in: query
        - schema:
            type: string
          required: false
          name: region
          in: query
        - schema:
            type: string
          required: false
          name: continent
          in: query
        - schema:
            type: string
          required: false
          name: browser
          in: query
        - schema:
            type: string
          required: false
          name: os
          in: query
        - schema:
            type: string
          required: false
          name: device
          in: query
        - schema:
            type: number
          required: false
          name: folder_id
          in: query
        - schema:
            type: number
          required: false
          name: tag_id
          in: query
        - schema:
            type: number
          required: false
          name: page
          in: query
        - $ref: "#/components/parameters/LimitParam"
      responses:
        "200":
          description: Clicks details
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ClicksStreamResponse"
  /analytics/values:
    get:
      tags:
        - Analytics
      summary: Get analytics values for a field
      security:
        - ApiKeyAuth: []
      parameters:
        - $ref: "#/components/parameters/FieldParam"
        - schema:
            type: string
          required: false
          name: link_id
          in: query
        - schema:
            type: string
          required: false
          name: search
          in: query
        - $ref: "#/components/parameters/PeriodParam"
        - schema:
            type: number
          required: false
          name: page
          in: query
        - $ref: "#/components/parameters/LimitParam"
      responses:
        "200":
          description: Requested values
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AnalyticsValuesResponse"
  /analytics/clicks:
    get:
      tags:
        - Analytics
      summary: Get clicks by periods
      security:
        - ApiKeyAuth: []
      parameters:
        - schema:
            type: string
          required: false
          name: link_id
          in: query
        - schema:
            type: number
          required: false
          name: domain_id
          in: query
        - schema:
            type: string
          required: false
          name: search
          in: query
        - $ref: "#/components/parameters/PeriodParam"
        - schema:
            type: string
          required: false
          name: country
          in: query
        - schema:
            type: string
          required: false
          name: city
          in: query
        - schema:
            type: string
          required: false
          name: region
          in: query
        - schema:
            type: string
          required: false
          name: continent
          in: query
        - schema:
            type: string
          required: false
          name: browser
          in: query
        - schema:
            type: string
          required: false
          name: os
          in: query
        - schema:
            type: string
          required: false
          name: device
          in: query
        - schema:
            type: number
          required: false
          name: folder_id
          in: query
        - schema:
            type: number
          required: false
          name: tag_id
          in: query
        - schema:
            type: number
          required: false
          name: page
          in: query
        - $ref: "#/components/parameters/LimitParam"
      responses:
        "200":
          description: Clicks by period
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/TimeCount"
  /analytics/links:
    get:
      tags:
        - Analytics
      summary: Get top short links
      security:
        - ApiKeyAuth: []
      parameters:
        - schema:
            type: string
          required: false
          name: link_id
          in: query
        - schema:
            type: number
          required: false
          name: domain_id
          in: query
        - schema:
            type: string
          required: false
          name: search
          in: query
        - $ref: "#/components/parameters/PeriodParam"
        - schema:
            type: string
          required: false
          name: country
          in: query
        - schema:
            type: string
          required: false
          name: city
          in: query
        - schema:
            type: string
          required: false
          name: region
          in: query
        - schema:
            type: string
          required: false
          name: continent
          in: query
        - schema:
            type: string
          required: false
          name: browser
          in: query
        - schema:
            type: string
          required: false
          name: os
          in: query
        - schema:
            type: string
          required: false
          name: device
          in: query
        - schema:
            type: number
          required: false
          name: folder_id
          in: query
        - schema:
            type: number
          required: false
          name: tag_id
          in: query
        - schema:
            type: number
          required: false
          name: page
          in: query
        - $ref: "#/components/parameters/LimitParam"
      responses:
        "200":
          description: Top short links
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/TimeCount"
  /analytics/geo:
    get:
      tags:
        - Analytics
      summary: Get geo information by ip
      security:
        - ApiKeyAuth: []
      parameters:
        - schema:
            type: string
            example: 8.8.8.8
          required: true
          name: ip
          in: query
      responses:
        "200":
          description: Geo info
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GeoResponse"
  /analytics/geo/countries:
    get:
      tags:
        - Analytics
      summary: Get top countries
      security:
        - ApiKeyAuth: []
      parameters:
        - schema:
            type: string
          required: false
          name: link_id
          in: query
        - schema:
            type: number
          required: false
          name: domain_id
          in: query
        - schema:
            type: string
          required: false
          name: search
          in: query
        - $ref: "#/components/parameters/PeriodParam"
        - schema:
            type: string
          required: false
          name: country
          in: query
        - schema:
            type: string
          required: false
          name: city
          in: query
        - schema:
            type: string
          required: false
          name: region
          in: query
        - schema:
            type: string
          required: false
          name: continent
          in: query
        - schema:
            type: string
          required: false
          name: browser
          in: query
        - schema:
            type: string
          required: false
          name: os
          in: query
        - schema:
            type: string
          required: false
          name: device
          in: query
        - schema:
            type: number
          required: false
          name: folder_id
          in: query
        - schema:
            type: number
          required: false
          name: tag_id
          in: query
        - schema:
            type: number
          required: false
          name: page
          in: query
        - $ref: "#/components/parameters/LimitParam"
      responses:
        "200":
          description: Top countries
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CountriesResponse"
  /analytics/geo/regions:
    get:
      tags:
        - Analytics
      summary: Get top regions
      security:
        - ApiKeyAuth: []
      parameters:
        - schema:
            type: string
          required: false
          name: link_id
          in: query
        - schema:
            type: number
          required: false
          name: domain_id
          in: query
        - schema:
            type: string
          required: false
          name: search
          in: query
        - $ref: "#/components/parameters/PeriodParam"
        - schema:
            type: string
          required: false
          name: country
          in: query
        - schema:
            type: string
          required: false
          name: city
          in: query
        - schema:
            type: string
          required: false
          name: region
          in: query
        - schema:
            type: string
          required: false
          name: continent
          in: query
        - schema:
            type: string
          required: false
          name: browser
          in: query
        - schema:
            type: string
          required: false
          name: os
          in: query
        - schema:
            type: string
          required: false
          name: device
          in: query
        - schema:
            type: number
          required: false
          name: folder_id
          in: query
        - schema:
            type: number
          required: false
          name: tag_id
          in: query
        - schema:
            type: number
          required: false
          name: page
          in: query
        - $ref: "#/components/parameters/LimitParam"
      responses:
        "200":
          description: Top regions
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RegionsResponse"
  /analytics/geo/cities:
    get:
      tags:
        - Analytics
      summary: Get top cities
      security:
        - ApiKeyAuth: []
      parameters:
        - schema:
            type: string
          required: false
          name: link_id
          in: query
        - schema:
            type: number
          required: false
          name: domain_id
          in: query
        - schema:
            type: string
          required: false
          name: search
          in: query
        - $ref: "#/components/parameters/PeriodParam"
        - schema:
            type: string
          required: false
          name: country
          in: query
        - schema:
            type: string
          required: false
          name: city
          in: query
        - schema:
            type: string
          required: false
          name: region
          in: query
        - schema:
            type: string
          required: false
          name: continent
          in: query
        - schema:
            type: string
          required: false
          name: browser
          in: query
        - schema:
            type: string
          required: false
          name: os
          in: query
        - schema:
            type: string
          required: false
          name: device
          in: query
        - schema:
            type: number
          required: false
          name: folder_id
          in: query
        - schema:
            type: number
          required: false
          name: tag_id
          in: query
        - schema:
            type: number
          required: false
          name: page
          in: query
        - $ref: "#/components/parameters/LimitParam"
      responses:
        "200":
          description: Top cities
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CitiesResponse"
  /analytics/groups:
    get:
      tags:
        - Analytics
      summary: Get data grouped by field(s)
      security:
        - ApiKeyAuth: []
      parameters:
        - schema:
            type: string
          required: false
          name: link_id
          in: query
        - schema:
            type: number
          required: false
          name: domain_id
          in: query
        - schema:
            type: string
          required: false
          name: search
          in: query
        - $ref: "#/components/parameters/PeriodParam"
        - schema:
            type: string
          required: false
          name: country
          in: query
        - schema:
            type: string
          required: false
          name: city
          in: query
        - schema:
            type: string
          required: false
          name: region
          in: query
        - schema:
            type: string
          required: false
          name: continent
          in: query
        - schema:
            type: string
          required: false
          name: browser
          in: query
        - schema:
            type: string
          required: false
          name: os
          in: query
        - schema:
            type: string
          required: false
          name: device
          in: query
        - schema:
            type: number
          required: false
          name: folder_id
          in: query
        - schema:
            type: number
          required: false
          name: tag_id
          in: query
        - schema:
            type: number
          required: false
          name: page
          in: query
        - $ref: "#/components/parameters/LimitParam"
        - schema:
            type: string
            example: country,browser
          required: true
          name: groups
          in: query
      responses:
        "200":
          description: Data grouped by field(s)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AnalyticsGroupsResponse"
  /version:
    get:
      tags:
        - General
      summary: Get version
      responses:
        "200":
          description: Version info
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/VersionResponse"
